diff --git a/packages/cli/src/gemini.tsx b/packages/cli/src/gemini.tsx index 91425d8d..a2e14ab0 100644 --- a/packages/cli/src/gemini.tsx +++ b/packages/cli/src/gemini.tsx @@ -17,8 +17,8 @@ import { start_sandbox } from './utils/sandbox.js'; import { LoadedSettings, loadSettings, - SettingScope, USER_SETTINGS_PATH, + SettingScope, } from './config/settings.js'; import { themeManager } from './ui/themes/theme-manager.js'; import { getStartupWarnings } from './utils/startupWarnings.js'; @@ -111,15 +111,9 @@ export async function main() { process.exit(0); } - // Set a default auth type if one isn't set for a couple of known cases. + // Set a default auth type if one isn't set. if (!settings.merged.selectedAuthType) { - if (process.env.GEMINI_API_KEY) { - settings.setValue( - SettingScope.User, - 'selectedAuthType', - AuthType.USE_GEMINI, - ); - } else if (process.env.CLOUD_SHELL === 'true') { + if (process.env.CLOUD_SHELL === 'true') { settings.setValue( SettingScope.User, 'selectedAuthType', diff --git a/packages/cli/src/ui/components/AuthDialog.test.tsx b/packages/cli/src/ui/components/AuthDialog.test.tsx index 8f07e2a5..60a8a930 100644 --- a/packages/cli/src/ui/components/AuthDialog.test.tsx +++ b/packages/cli/src/ui/components/AuthDialog.test.tsx @@ -5,7 +5,7 @@ */ import { render } from 'ink-testing-library'; -import { describe, it, expect, vi } from 'vitest'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { AuthDialog } from './AuthDialog.js'; import { LoadedSettings, SettingScope } from '../../config/settings.js'; import { AuthType } from '@google/gemini-cli-core'; @@ -13,7 +13,21 @@ import { AuthType } from '@google/gemini-cli-core'; describe('AuthDialog', () => { const wait = (ms = 50) => new Promise((resolve) => setTimeout(resolve, ms)); + let originalEnv: NodeJS.ProcessEnv; + + beforeEach(() => { + originalEnv = { ...process.env }; + process.env.GEMINI_API_KEY = ''; + vi.clearAllMocks(); + }); + + afterEach(() => { + process.env = originalEnv; + }); + it('should show an error if the initial auth type is invalid', () => { + process.env.GEMINI_API_KEY = ''; + const settings: LoadedSettings = new LoadedSettings( { settings: { @@ -41,6 +55,30 @@ describe('AuthDialog', () => { ); }); + it('should detect GEMINI_API_KEY environment variable', () => { + process.env.GEMINI_API_KEY = 'foobar'; + + const settings: LoadedSettings = new LoadedSettings( + { + settings: { + selectedAuthType: undefined, + }, + path: '', + }, + { + settings: {}, + path: '', + }, + [], + ); + + const { lastFrame } = render( + {}} settings={settings} />, + ); + + expect(lastFrame()).toContain('Existing API key detected (GEMINI_API_KEY)'); + }); + it('should prevent exiting when no auth method is selected and show error message', async () => { const onSelect = vi.fn(); const settings: LoadedSettings = new LoadedSettings( diff --git a/packages/cli/src/ui/components/AuthDialog.tsx b/packages/cli/src/ui/components/AuthDialog.tsx index a33e284d..d46feb0b 100644 --- a/packages/cli/src/ui/components/AuthDialog.tsx +++ b/packages/cli/src/ui/components/AuthDialog.tsx @@ -24,7 +24,11 @@ export function AuthDialog({ initialErrorMessage, }: AuthDialogProps): React.JSX.Element { const [errorMessage, setErrorMessage] = useState( - initialErrorMessage || null, + initialErrorMessage + ? initialErrorMessage + : process.env.GEMINI_API_KEY + ? 'Existing API key detected (GEMINI_API_KEY). Select "Gemini API Key" option to use it.' + : null, ); const items = [ { @@ -46,13 +50,17 @@ export function AuthDialog({ { label: 'Vertex AI', value: AuthType.USE_VERTEX_AI }, ]; - let initialAuthIndex = items.findIndex( - (item) => item.value === settings.merged.selectedAuthType, - ); + const initialAuthIndex = items.findIndex((item) => { + if (settings.merged.selectedAuthType) { + return item.value === settings.merged.selectedAuthType; + } - if (initialAuthIndex === -1) { - initialAuthIndex = 0; - } + if (process.env.GEMINI_API_KEY) { + return item.value === AuthType.USE_GEMINI; + } + + return item.value === AuthType.LOGIN_WITH_GOOGLE; + }); const handleAuthSelect = (authMethod: AuthType) => { const error = validateAuthMethod(authMethod); @@ -90,13 +98,18 @@ export function AuthDialog({ padding={1} width="100%" > - Select Auth Method - + Get started + + How would you like to authenticate for this project? + + + + {errorMessage && ( {errorMessage}