diff options
| author | matt korwel <[email protected]> | 2025-06-19 16:52:22 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-06-19 16:52:22 -0700 |
| commit | 04518b52c0ddcd5ae1192763c55e472add218b3c (patch) | |
| tree | 2587b0ccc5460e9e94eb8b715956cb713950f7c8 /packages/cli/src/ui/hooks | |
| parent | c48fcaa8c3fe8175718b1bbfc7770a958012173c (diff) | |
Auth First Run (#1207)
Co-authored-by: Tommaso Sciortino <[email protected]>
Co-authored-by: N. Taylor Mullen <[email protected]>
Diffstat (limited to 'packages/cli/src/ui/hooks')
5 files changed, 76 insertions, 1 deletions
diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts index 7c750af1..04931c7f 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts @@ -103,6 +103,7 @@ describe('useSlashCommandProcessor', () => { let mockSetShowHelp: ReturnType<typeof vi.fn>; let mockOnDebugMessage: ReturnType<typeof vi.fn>; let mockOpenThemeDialog: ReturnType<typeof vi.fn>; + let mockOpenAuthDialog: ReturnType<typeof vi.fn>; let mockOpenEditorDialog: ReturnType<typeof vi.fn>; let mockPerformMemoryRefresh: ReturnType<typeof vi.fn>; let mockSetQuittingMessages: ReturnType<typeof vi.fn>; @@ -120,6 +121,7 @@ describe('useSlashCommandProcessor', () => { mockSetShowHelp = vi.fn(); mockOnDebugMessage = vi.fn(); mockOpenThemeDialog = vi.fn(); + mockOpenAuthDialog = vi.fn(); mockOpenEditorDialog = vi.fn(); mockPerformMemoryRefresh = vi.fn().mockResolvedValue(undefined); mockSetQuittingMessages = vi.fn(); @@ -171,6 +173,7 @@ describe('useSlashCommandProcessor', () => { mockSetShowHelp, mockOnDebugMessage, mockOpenThemeDialog, + mockOpenAuthDialog, mockOpenEditorDialog, mockPerformMemoryRefresh, mockCorgiMode, diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.ts index 0e622f23..ee7b55cb 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.ts @@ -68,6 +68,7 @@ export const useSlashCommandProcessor = ( setShowHelp: React.Dispatch<React.SetStateAction<boolean>>, onDebugMessage: (message: string) => void, openThemeDialog: () => void, + openAuthDialog: () => void, openEditorDialog: () => void, performMemoryRefresh: () => Promise<void>, toggleCorgiMode: () => void, @@ -198,6 +199,13 @@ export const useSlashCommandProcessor = ( }, }, { + name: 'auth', + description: 'change the auth method', + action: (_mainCommand, _subCommand, _args) => { + openAuthDialog(); + }, + }, + { name: 'editor', description: 'set external editor preference', action: (_mainCommand, _subCommand, _args) => { @@ -907,6 +915,7 @@ Add any other context about the problem here. setShowHelp, refreshStatic, openThemeDialog, + openAuthDialog, openEditorDialog, clearItems, performMemoryRefresh, diff --git a/packages/cli/src/ui/hooks/useAuthCommand.ts b/packages/cli/src/ui/hooks/useAuthCommand.ts new file mode 100644 index 00000000..a9b1cb1e --- /dev/null +++ b/packages/cli/src/ui/hooks/useAuthCommand.ts @@ -0,0 +1,57 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { useState, useCallback, useEffect } from 'react'; +import { LoadedSettings, SettingScope } from '../../config/settings.js'; +import { AuthType, Config, clearCachedCredentialFile } from '@gemini-cli/core'; + +async function performAuthFlow(authMethod: AuthType, config: Config) { + await config.refreshAuth(authMethod); + console.log(`Authenticated via "${authMethod}".`); +} + +export const useAuthCommand = ( + settings: LoadedSettings, + setAuthError: (error: string | null) => void, + config: Config, +) => { + const [isAuthDialogOpen, setIsAuthDialogOpen] = useState( + settings.merged.selectedAuthType === undefined, + ); + + useEffect(() => { + if (!isAuthDialogOpen) { + performAuthFlow(settings.merged.selectedAuthType as AuthType, config); + } + }, [isAuthDialogOpen, settings, config]); + + const openAuthDialog = useCallback(() => { + setIsAuthDialogOpen(true); + }, []); + + const handleAuthSelect = useCallback( + async (authMethod: string | undefined, scope: SettingScope) => { + if (authMethod) { + await clearCachedCredentialFile(); + settings.setValue(scope, 'selectedAuthType', authMethod); + } + setIsAuthDialogOpen(false); + setAuthError(null); + }, + [settings, setAuthError], + ); + + const handleAuthHighlight = useCallback((_authMethod: string | undefined) => { + // For now, we don't do anything on highlight. + }, []); + + return { + isAuthDialogOpen, + openAuthDialog, + handleAuthSelect, + handleAuthHighlight, + }; +}; diff --git a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx index 96dd6aef..36f420e4 100644 --- a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx +++ b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx @@ -359,6 +359,7 @@ describe('useGeminiStream', () => { props.handleSlashCommand, props.shellModeActive, () => 'vscode' as EditorType, + () => {}, ), { initialProps: { diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts index 6d92af0d..4049c884 100644 --- a/packages/cli/src/ui/hooks/useGeminiStream.ts +++ b/packages/cli/src/ui/hooks/useGeminiStream.ts @@ -22,6 +22,7 @@ import { GitService, EditorType, ThoughtSummary, + isAuthError, } from '@gemini-cli/core'; import { type Part, type PartListUnion } from '@google/genai'; import { @@ -87,6 +88,7 @@ export const useGeminiStream = ( >, shellModeActive: boolean, getPreferredEditor: () => EditorType | undefined, + onAuthError: () => void, ) => { const [initError, setInitError] = useState<string | null>(null); const abortControllerRef = useRef<AbortController | null>(null); @@ -496,7 +498,9 @@ export const useGeminiStream = ( setPendingHistoryItem(null); } } catch (error: unknown) { - if (!isNodeError(error) || error.name !== 'AbortError') { + if (isAuthError(error)) { + onAuthError(); + } else if (!isNodeError(error) || error.name !== 'AbortError') { addItem( { type: MessageType.ERROR, @@ -522,6 +526,7 @@ export const useGeminiStream = ( setInitError, geminiClient, startNewTurn, + onAuthError, ], ); |
