diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx index aff3fac3..c4f67294 100644 --- a/packages/cli/src/ui/App.tsx +++ b/packages/cli/src/ui/App.tsx @@ -939,8 +939,7 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => { {shouldShowIdePrompt ? ( ) : isFolderTrustDialogOpen ? ( diff --git a/packages/cli/src/ui/IdeIntegrationNudge.tsx b/packages/cli/src/ui/IdeIntegrationNudge.tsx index 72cd1756..f0c6172d 100644 --- a/packages/cli/src/ui/IdeIntegrationNudge.tsx +++ b/packages/cli/src/ui/IdeIntegrationNudge.tsx @@ -13,14 +13,12 @@ import { export type IdeIntegrationNudgeResult = 'yes' | 'no' | 'dismiss'; interface IdeIntegrationNudgeProps { - question: string; - description?: string; + ideName?: string; onComplete: (result: IdeIntegrationNudgeResult) => void; } export function IdeIntegrationNudge({ - question, - description, + ideName, onComplete, }: IdeIntegrationNudgeProps) { useInput((_input, key) => { @@ -56,9 +54,11 @@ export function IdeIntegrationNudge({ {'> '} - {question} + {`Do you want to connect your ${ideName ?? 'your'} editor to Gemini CLI?`} - {description && {description}} + {`If you select Yes, we'll install an extension that allows the CLI to access your open files and display diffs directly in ${ideName ?? 'your editor'}.`} { expect(installer).toBeInstanceOf(Object); }); - it('should return null for an unknown IDE', () => { + it('should return an OpenVSXInstaller for "vscodium"', () => { + const installer = getIdeInstaller(DetectedIde.VSCodium); + expect(installer).not.toBeNull(); + expect(installer).toBeInstanceOf(Object); + }); + + it('should return a DefaultIDEInstaller for an unknown IDE', () => { const installer = getIdeInstaller('unknown' as DetectedIde); - expect(installer).toBeNull(); + // Assuming DefaultIDEInstaller is the fallback + expect(installer).not.toBeNull(); + expect(installer).toBeInstanceOf(Object); }); }); @@ -59,4 +67,44 @@ describe('ide-installer', () => { }); }); }); + + describe('OpenVSXInstaller', () => { + let installer: IdeInstaller; + + beforeEach(() => { + installer = getIdeInstaller(DetectedIde.VSCodium)!; + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + describe('install', () => { + it('should call execSync with the correct command and return success', async () => { + const execSyncSpy = vi + .spyOn(child_process, 'execSync') + .mockImplementation(() => ''); + const result = await installer.install(); + expect(execSyncSpy).toHaveBeenCalledWith( + 'npx ovsx get google.gemini-cli-vscode-ide-companion', + { stdio: 'pipe' }, + ); + expect(result.success).toBe(true); + expect(result.message).toContain( + 'VS Code companion extension was installed successfully from OpenVSX', + ); + }); + + it('should return a failure message on failed installation', async () => { + vi.spyOn(child_process, 'execSync').mockImplementation(() => { + throw new Error('Command failed'); + }); + const result = await installer.install(); + expect(result.success).toBe(false); + expect(result.message).toContain( + 'Failed to install VS Code companion extension from OpenVSX', + ); + }); + }); + }); }); diff --git a/packages/core/src/ide/ide-installer.ts b/packages/core/src/ide/ide-installer.ts index 7db8e2d2..e6192bfa 100644 --- a/packages/core/src/ide/ide-installer.ts +++ b/packages/core/src/ide/ide-installer.ts @@ -147,11 +147,31 @@ class VsCodeInstaller implements IdeInstaller { } } +class OpenVSXInstaller implements IdeInstaller { + async install(): Promise { + // TODO: Use the correct extension path. + const command = `npx ovsx get google.gemini-cli-vscode-ide-companion`; + try { + child_process.execSync(command, { stdio: 'pipe' }); + return { + success: true, + message: + 'VS Code companion extension was installed successfully from OpenVSX. Please restart your terminal to complete the setup.', + }; + } catch (_error) { + return { + success: false, + message: `Failed to install VS Code companion extension from OpenVSX. Please try installing it manually.`, + }; + } + } +} + export function getIdeInstaller(ide: DetectedIde): IdeInstaller | null { switch (ide) { case DetectedIde.VSCode: return new VsCodeInstaller(); default: - return null; + return new OpenVSXInstaller(); } }