mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 15:31:27 +00:00
Auth First Run (#1207)
Co-authored-by: Tommaso Sciortino <sciortino@gmail.com> Co-authored-by: N. Taylor Mullen <ntaylormullen@google.com>
This commit is contained in:
parent
c48fcaa8c3
commit
04518b52c0
37 changed files with 636 additions and 349 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -197,6 +198,13 @@ export const useSlashCommandProcessor = (
|
|||
openThemeDialog();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'auth',
|
||||
description: 'change the auth method',
|
||||
action: (_mainCommand, _subCommand, _args) => {
|
||||
openAuthDialog();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'editor',
|
||||
description: 'set external editor preference',
|
||||
|
|
@ -907,6 +915,7 @@ Add any other context about the problem here.
|
|||
setShowHelp,
|
||||
refreshStatic,
|
||||
openThemeDialog,
|
||||
openAuthDialog,
|
||||
openEditorDialog,
|
||||
clearItems,
|
||||
performMemoryRefresh,
|
||||
|
|
|
|||
57
packages/cli/src/ui/hooks/useAuthCommand.ts
Normal file
57
packages/cli/src/ui/hooks/useAuthCommand.ts
Normal file
|
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
|
@ -359,6 +359,7 @@ describe('useGeminiStream', () => {
|
|||
props.handleSlashCommand,
|
||||
props.shellModeActive,
|
||||
() => 'vscode' as EditorType,
|
||||
() => {},
|
||||
),
|
||||
{
|
||||
initialProps: {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
],
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue