diff options
| author | Shreya Keshive <[email protected]> | 2025-07-16 18:36:14 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-07-16 22:36:14 +0000 |
| commit | ab9eb9377fdfe7823be8ea0c7c394c5368b28951 (patch) | |
| tree | ad7f0ebf45902513d129d4eb09897a5345cad195 /packages/cli/src/ui/commands/ideCommand.ts | |
| parent | 69a8ae6a89918f4255304975f8653ff808264bc8 (diff) | |
Add /ide status & /ide install commands to manage IDE integration (#4265)
Diffstat (limited to 'packages/cli/src/ui/commands/ideCommand.ts')
| -rw-r--r-- | packages/cli/src/ui/commands/ideCommand.ts | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/packages/cli/src/ui/commands/ideCommand.ts b/packages/cli/src/ui/commands/ideCommand.ts new file mode 100644 index 00000000..0251e619 --- /dev/null +++ b/packages/cli/src/ui/commands/ideCommand.ts @@ -0,0 +1,165 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { fileURLToPath } from 'url'; +import { + Config, + getMCPDiscoveryState, + getMCPServerStatus, + IDE_SERVER_NAME, + MCPDiscoveryState, + MCPServerStatus, +} from '@google/gemini-cli-core'; +import { + CommandContext, + SlashCommand, + SlashCommandActionReturn, +} from './types.js'; +import * as child_process from 'child_process'; +import * as process from 'process'; +import { glob } from 'glob'; +import * as path from 'path'; + +const VSCODE_COMMAND = process.platform === 'win32' ? 'code.cmd' : 'code'; +const VSCODE_COMPANION_EXTENSION_FOLDER = 'vscode-ide-companion'; + +function isVSCodeInstalled(): boolean { + try { + child_process.execSync( + process.platform === 'win32' + ? `where.exe ${VSCODE_COMMAND}` + : `command -v ${VSCODE_COMMAND}`, + { stdio: 'ignore' }, + ); + return true; + } catch { + return false; + } +} + +export const ideCommand = (config: Config | null): SlashCommand | null => { + if (!config?.getIdeMode()) { + return null; + } + + return { + name: 'ide', + description: 'manage IDE integration', + subCommands: [ + { + name: 'status', + description: 'check status of IDE integration', + action: (_context: CommandContext): SlashCommandActionReturn => { + const status = getMCPServerStatus(IDE_SERVER_NAME); + const discoveryState = getMCPDiscoveryState(); + switch (status) { + case MCPServerStatus.CONNECTED: + return { + type: 'message', + messageType: 'info', + content: `🟢 Connected`, + }; + case MCPServerStatus.CONNECTING: + return { + type: 'message', + messageType: 'info', + content: `🔄 Initializing...`, + }; + case MCPServerStatus.DISCONNECTED: + default: + if (discoveryState === MCPDiscoveryState.IN_PROGRESS) { + return { + type: 'message', + messageType: 'info', + content: `🔄 Initializing...`, + }; + } else { + return { + type: 'message', + messageType: 'error', + content: `🔴 Disconnected`, + }; + } + } + }, + }, + { + name: 'install', + description: 'install required VS Code companion extension', + action: async (context) => { + if (!isVSCodeInstalled()) { + context.ui.addItem( + { + type: 'error', + text: `VS Code command-line tool "${VSCODE_COMMAND}" not found in your PATH.`, + }, + Date.now(), + ); + return; + } + + const bundleDir = path.dirname(fileURLToPath(import.meta.url)); + // The VSIX file is copied to the bundle directory as part of the build. + let vsixFiles = glob.sync(path.join(bundleDir, '*.vsix')); + if (vsixFiles.length === 0) { + // If the VSIX file is not in the bundle, it might be a dev + // environment running with `npm start`. Look for it in the original + // package location, relative to the bundle dir. + const devPath = path.join( + bundleDir, + '..', + '..', + '..', + '..', + '..', + VSCODE_COMPANION_EXTENSION_FOLDER, + '*.vsix', + ); + vsixFiles = glob.sync(devPath); + } + if (vsixFiles.length === 0) { + context.ui.addItem( + { + type: 'error', + text: 'Could not find the required VS Code companion extension. Please file a bug via /bug.', + }, + Date.now(), + ); + return; + } + + const vsixPath = vsixFiles[0]; + const command = `${VSCODE_COMMAND} --install-extension ${vsixPath} --force`; + context.ui.addItem( + { + type: 'info', + text: `Installing VS Code companion extension...`, + }, + Date.now(), + ); + try { + child_process.execSync(command, { stdio: 'pipe' }); + context.ui.addItem( + { + type: 'info', + text: 'VS Code companion extension installed successfully. Restart gemini-cli in a fresh terminal window.', + }, + Date.now(), + ); + } catch (_error) { + context.ui.addItem( + { + type: 'error', + text: `Failed to install VS Code companion extension.`, + }, + Date.now(), + ); + } + }, + }, + ], + }; +}; |
