Fix multiple bugs with auth flow including using the implemented but unused restart support. (#13565)

This commit is contained in:
Jacob Richman
2025-11-21 08:31:47 -08:00
committed by GitHub
parent b97661553f
commit 030a5ace97
13 changed files with 307 additions and 137 deletions

View File

@@ -25,6 +25,7 @@ import { validateAuthMethodWithSettings } from './useAuth.js';
import { runExitCleanup } from '../../utils/cleanup.js';
import { clearCachedCredentialFile } from '@google/gemini-cli-core';
import { Text } from 'ink';
import { RELAUNCH_EXIT_CODE } from '../../utils/processUtils.js';
// Mocks
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
@@ -229,6 +230,7 @@ describe('AuthDialog', () => {
});
it('exits process for Login with Google when browser is suppressed', async () => {
vi.useFakeTimers();
const exitSpy = vi
.spyOn(process, 'exit')
.mockImplementation(() => undefined as never);
@@ -241,14 +243,14 @@ describe('AuthDialog', () => {
mockedRadioButtonSelect.mock.calls[0][0];
await handleAuthSelect(AuthType.LOGIN_WITH_GOOGLE);
await vi.runAllTimersAsync();
expect(mockedRunExitCleanup).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith(
expect.stringContaining('Please restart Gemini CLI'),
);
expect(exitSpy).toHaveBeenCalledWith(0);
expect(exitSpy).toHaveBeenCalledWith(RELAUNCH_EXIT_CODE);
exitSpy.mockRestore();
logSpy.mockRestore();
vi.useRealTimers();
});
});

View File

@@ -5,7 +5,7 @@
*/
import type React from 'react';
import { useCallback } from 'react';
import { useCallback, useState } from 'react';
import { Box, Text } from 'ink';
import { theme } from '../semantic-colors.js';
import { RadioButtonSelect } from '../components/shared/RadioButtonSelect.js';
@@ -17,13 +17,13 @@ import { SettingScope } from '../../config/settings.js';
import {
AuthType,
clearCachedCredentialFile,
debugLogger,
type Config,
} from '@google/gemini-cli-core';
import { useKeypress } from '../hooks/useKeypress.js';
import { AuthState } from '../types.js';
import { runExitCleanup } from '../../utils/cleanup.js';
import { validateAuthMethodWithSettings } from './useAuth.js';
import { RELAUNCH_EXIT_CODE } from '../../utils/processUtils.js';
interface AuthDialogProps {
config: Config;
@@ -40,6 +40,7 @@ export function AuthDialog({
authError,
onAuthError,
}: AuthDialogProps): React.JSX.Element {
const [exiting, setExiting] = useState(false);
let items = [
{
label: 'Login with Google',
@@ -111,6 +112,9 @@ export function AuthDialog({
const onSelect = useCallback(
async (authType: AuthType | undefined, scope: LoadableSettingScope) => {
if (exiting) {
return;
}
if (authType) {
await clearCachedCredentialFile();
@@ -119,15 +123,12 @@ export function AuthDialog({
authType === AuthType.LOGIN_WITH_GOOGLE &&
config.isBrowserLaunchSuppressed()
) {
runExitCleanup();
debugLogger.log(
`
----------------------------------------------------------------
Logging in with Google... Please restart Gemini CLI to continue.
----------------------------------------------------------------
`,
);
process.exit(0);
setExiting(true);
setTimeout(async () => {
await runExitCleanup();
process.exit(RELAUNCH_EXIT_CODE);
}, 100);
return;
}
}
if (authType === AuthType.USE_GEMINI) {
@@ -136,7 +137,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
}
setAuthState(AuthState.Unauthenticated);
},
[settings, config, setAuthState],
[settings, config, setAuthState, exiting],
);
const handleAuthSelect = (authMethod: AuthType) => {
@@ -169,6 +170,23 @@ Logging in with Google... Please restart Gemini CLI to continue.
{ isActive: true },
);
if (exiting) {
return (
<Box
borderStyle="round"
borderColor={theme.border.focused}
flexDirection="row"
padding={1}
width="100%"
alignItems="flex-start"
>
<Text color={theme.text.primary}>
Logging in with Google... Restarting Gemini CLI to continue.
</Text>
</Box>
);
}
return (
<Box
borderStyle="round"