feat: Add GEMINI_DEFAULT_AUTH_TYPE support (#4002)

This commit is contained in:
N. Taylor Mullen 2025-07-12 20:43:35 -07:00 committed by GitHub
parent 4442e893c3
commit 26a79fec25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 199 additions and 25 deletions

View File

@ -18,6 +18,7 @@ describe('AuthDialog', () => {
beforeEach(() => {
originalEnv = { ...process.env };
process.env.GEMINI_API_KEY = '';
process.env.GEMINI_DEFAULT_AUTH_TYPE = '';
vi.clearAllMocks();
});
@ -59,28 +60,165 @@ describe('AuthDialog', () => {
);
});
it('should detect GEMINI_API_KEY environment variable', () => {
process.env.GEMINI_API_KEY = 'foobar';
describe('GEMINI_API_KEY environment variable', () => {
it('should detect GEMINI_API_KEY environment variable', () => {
process.env.GEMINI_API_KEY = 'foobar';
const settings: LoadedSettings = new LoadedSettings(
{
settings: {
selectedAuthType: undefined,
const settings: LoadedSettings = new LoadedSettings(
{
settings: {
selectedAuthType: undefined,
},
path: '',
},
path: '',
},
{
settings: {},
path: '',
},
[],
);
{
settings: {},
path: '',
},
[],
);
const { lastFrame } = render(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
const { lastFrame } = render(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
expect(lastFrame()).toContain('Existing API key detected (GEMINI_API_KEY)');
expect(lastFrame()).toContain(
'Existing API key detected (GEMINI_API_KEY)',
);
});
it('should not show the GEMINI_API_KEY message if GEMINI_DEFAULT_AUTH_TYPE is set to something else', () => {
process.env.GEMINI_API_KEY = 'foobar';
process.env.GEMINI_DEFAULT_AUTH_TYPE = AuthType.LOGIN_WITH_GOOGLE;
const settings: LoadedSettings = new LoadedSettings(
{
settings: {
selectedAuthType: undefined,
},
path: '',
},
{
settings: {},
path: '',
},
[],
);
const { lastFrame } = render(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
expect(lastFrame()).not.toContain(
'Existing API key detected (GEMINI_API_KEY)',
);
});
it('should show the GEMINI_API_KEY message if GEMINI_DEFAULT_AUTH_TYPE is set to use api key', () => {
process.env.GEMINI_API_KEY = 'foobar';
process.env.GEMINI_DEFAULT_AUTH_TYPE = AuthType.USE_GEMINI;
const settings: LoadedSettings = new LoadedSettings(
{
settings: {
selectedAuthType: undefined,
},
path: '',
},
{
settings: {},
path: '',
},
[],
);
const { lastFrame } = render(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
expect(lastFrame()).toContain(
'Existing API key detected (GEMINI_API_KEY)',
);
});
});
describe('GEMINI_DEFAULT_AUTH_TYPE environment variable', () => {
it('should select the auth type specified by GEMINI_DEFAULT_AUTH_TYPE', () => {
process.env.GEMINI_DEFAULT_AUTH_TYPE = AuthType.LOGIN_WITH_GOOGLE;
const settings: LoadedSettings = new LoadedSettings(
{
settings: {
selectedAuthType: undefined,
},
path: '',
},
{
settings: {},
path: '',
},
[],
);
const { lastFrame } = render(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
// This is a bit brittle, but it's the best way to check which item is selected.
expect(lastFrame()).toContain('● Login with Google');
});
it('should fall back to default if GEMINI_DEFAULT_AUTH_TYPE is not set', () => {
const settings: LoadedSettings = new LoadedSettings(
{
settings: {
selectedAuthType: undefined,
},
path: '',
},
{
settings: {},
path: '',
},
[],
);
const { lastFrame } = render(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
// Default is LOGIN_WITH_GOOGLE
expect(lastFrame()).toContain('● Login with Google');
});
it('should show an error and fall back to default if GEMINI_DEFAULT_AUTH_TYPE is invalid', () => {
process.env.GEMINI_DEFAULT_AUTH_TYPE = 'invalid-auth-type';
const settings: LoadedSettings = new LoadedSettings(
{
settings: {
selectedAuthType: undefined,
},
path: '',
},
{
settings: {},
path: '',
},
[],
);
const { lastFrame } = render(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
expect(lastFrame()).toContain(
'Invalid value for GEMINI_DEFAULT_AUTH_TYPE: "invalid-auth-type"',
);
// Default is LOGIN_WITH_GOOGLE
expect(lastFrame()).toContain('● Login with Google');
});
});
it('should prevent exiting when no auth method is selected and show error message', async () => {

View File

@ -18,18 +18,47 @@ interface AuthDialogProps {
initialErrorMessage?: string | null;
}
function parseDefaultAuthType(
defaultAuthType: string | undefined,
): AuthType | null {
if (
defaultAuthType &&
Object.values(AuthType).includes(defaultAuthType as AuthType)
) {
return defaultAuthType as AuthType;
}
return null;
}
export function AuthDialog({
onSelect,
settings,
initialErrorMessage,
}: AuthDialogProps): React.JSX.Element {
const [errorMessage, setErrorMessage] = useState<string | 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 [errorMessage, setErrorMessage] = useState<string | null>(() => {
if (initialErrorMessage) {
return initialErrorMessage;
}
const defaultAuthType = parseDefaultAuthType(
process.env.GEMINI_DEFAULT_AUTH_TYPE,
);
if (process.env.GEMINI_DEFAULT_AUTH_TYPE && defaultAuthType === null) {
return (
`Invalid value for GEMINI_DEFAULT_AUTH_TYPE: "${process.env.GEMINI_DEFAULT_AUTH_TYPE}". ` +
`Valid values are: ${Object.values(AuthType).join(', ')}.`
);
}
if (
process.env.GEMINI_API_KEY &&
(!defaultAuthType || defaultAuthType === AuthType.USE_GEMINI)
) {
return 'Existing API key detected (GEMINI_API_KEY). Select "Gemini API Key" option to use it.';
}
return null;
});
const items = [
{
label: 'Login with Google',
@ -55,6 +84,13 @@ export function AuthDialog({
return item.value === settings.merged.selectedAuthType;
}
const defaultAuthType = parseDefaultAuthType(
process.env.GEMINI_DEFAULT_AUTH_TYPE,
);
if (defaultAuthType) {
return item.value === defaultAuthType;
}
if (process.env.GEMINI_API_KEY) {
return item.value === AuthType.USE_GEMINI;
}