summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorN. Taylor Mullen <[email protected]>2025-07-12 20:43:35 -0700
committerGitHub <[email protected]>2025-07-13 03:43:35 +0000
commit26a79fec2509e40a9fa3e82428a3c7ed30dce4f5 (patch)
tree56e3c2228e3f54cba3b130b3ee9568e4e8a7cd36
parent4442e893c367a901a4c801816e0ade5b78c291c9 (diff)
feat: Add GEMINI_DEFAULT_AUTH_TYPE support (#4002)
-rw-r--r--packages/cli/src/ui/components/AuthDialog.test.tsx174
-rw-r--r--packages/cli/src/ui/components/AuthDialog.tsx50
2 files changed, 199 insertions, 25 deletions
diff --git a/packages/cli/src/ui/components/AuthDialog.test.tsx b/packages/cli/src/ui/components/AuthDialog.test.tsx
index d9f1bd2c..2850762f 100644
--- a/packages/cli/src/ui/components/AuthDialog.test.tsx
+++ b/packages/cli/src/ui/components/AuthDialog.test.tsx
@@ -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)',
+ );
+ });
+
+ 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"',
+ );
- expect(lastFrame()).toContain('Existing API key detected (GEMINI_API_KEY)');
+ // 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 () => {
diff --git a/packages/cli/src/ui/components/AuthDialog.tsx b/packages/cli/src/ui/components/AuthDialog.tsx
index d46feb0b..ae076ee7 100644
--- a/packages/cli/src/ui/components/AuthDialog.tsx
+++ b/packages/cli/src/ui/components/AuthDialog.tsx
@@ -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;
}