Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion packages/cli/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ import { annotateActiveExtensions } from './extension.js';
import { loadSandboxConfig } from './sandboxConfig.js';

import { isWorkspaceTrusted } from './trustedFolders.js';
import {
getAuthTypeFromEnv
} from "../validateNonInterActiveAuth.js";

// Simple console logger for now - replace with actual logger if available
const logger = {
Expand Down Expand Up @@ -415,6 +418,10 @@ export async function loadCliConfig(
process.env['OPENAI_API_KEY'] = argv.openaiApiKey;
}

// Determine authType from env, falling back to settings.json selectedAuthType.
// If undefined, the "Get started" wizard is run to configure settings.json.
const authType = getAuthTypeFromEnv() || settings.security?.auth?.selectedType;

// Handle OpenAI base URL from command line
if (argv.openaiBaseUrl) {
process.env['OPENAI_BASE_URL'] = argv.openaiBaseUrl;
Expand Down Expand Up @@ -647,7 +654,7 @@ export async function loadCliConfig(
'SYSTEM_TEMPLATE:{"name":"qwen3_coder","params":{"is_git_repository":{RUNTIME_VARS_IS_GIT_REPO},"sandbox":"{RUNTIME_VARS_SANDBOX}"}}',
},
]) as ConfigParameters['systemPromptMappings'],
authType: settings.security?.auth?.selectedType,
authType: authType,
contentGenerator: settings.contentGenerator,
cliVersion,
tavilyApiKey:
Expand Down
24 changes: 23 additions & 1 deletion packages/cli/src/config/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as path from 'node:path';
import { homedir, platform } from 'node:os';
import * as dotenv from 'dotenv';
import {
AuthType,
GEMINI_CONFIG_DIR as GEMINI_DIR,
getErrorMessage,
Storage,
Expand Down Expand Up @@ -467,6 +468,7 @@ export class LoadedSettings {
readonly errors: SettingsError[];
readonly isTrusted: boolean;
readonly migratedInMemorScopes: Set<SettingScope>;
authType: AuthType | undefined;

private _merged: Settings;

Expand All @@ -475,13 +477,33 @@ export class LoadedSettings {
}

private computeMergedSettings(): Settings {
return mergeSettings(
let merged = mergeSettings(
this.system.settings,
this.systemDefaults.settings,
this.user.settings,
this.workspace.settings,
this.isTrusted,
);
// Overwrite from user config (arg or env or settings.json)
if (this.authType) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will break the auth type switching behavior.
Currently, switching the authentication type will mutate user scope settings, which will be merged here to take effect. With the overwrite process, the mutation will not take effect.

onSelect(AuthType.USE_OPENAI, SettingScope.User);

We may have two options:

  1. Consider users' auth selection as system override, which will always take the highest priority;
  2. Add merge strategy in loadCliConfig to respect env variables and cli arguments.

Copy link
Author

@reneleonhardt reneleonhardt Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for finding this issue, which option would be preferable?

I can't find a merge strategy anywhere, loadCliConfig() is already being called from main() with settings.merged and my addition there is to respect env and args πŸ˜„

Do you have a a quick example (pseudo) code for both options?

I guess by option 1 you mean overriding systemSettings inside loadSettings() itself which happens much earlier in main() before env and args have been processed?

If you already know an acceptable solution, feel free to push a commit, maintainers have all permissions.

merged.security ??= {};
merged.security.auth ??= {};
merged.security.auth.selectedType = this.authType;
}
return merged;
}

/**
* Apply the user configured auth type (i.e. "openai").
*
* Priority:
* 1. command line arg --openai-api-key "my-key" implicitly sets "openai"
* 2. env variables or .env file (i.e. OPENAI_API_KEY)
* 3. <code>{ "selectedAuthType": "openai" }</code> in settings.json
*/
applyConfiguredAuthType(authType: AuthType | undefined): void {
this.authType = authType;
this._merged = this.computeMergedSettings();
}

forScope(scope: SettingScope): SettingsFile {
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/gemini.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ export async function main() {
sessionId,
argv,
);
settings.applyConfiguredAuthType(config.getAuthType());

const consolePatcher = new ConsolePatcher({
stderr: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/validateNonInterActiveAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { AuthType, type Config } from '@qwen-code/qwen-code-core';
import { USER_SETTINGS_PATH } from './config/settings.js';
import { validateAuthMethod } from './config/auth.js';

function getAuthTypeFromEnv(): AuthType | undefined {
export function getAuthTypeFromEnv(): AuthType | undefined {
if (process.env['GOOGLE_GENAI_USE_GCA'] === 'true') {
return AuthType.LOGIN_WITH_GOOGLE;
}
Expand Down