refactor: update authentication handling and model configuration

- Enhanced authentication method validation in `auth.ts` and `auth.test.ts`.
- Introduced new model provider configuration logic
- Updated environment variable handling for various auth types.
- Removed deprecated utility functions and tests related to fallback mechanisms.
This commit is contained in:
mingholy.lmh 2026-01-06 15:36:44 +08:00
parent aa9cdf2a3c
commit db12796df5
53 changed files with 5183 additions and 942 deletions

View file

@ -1,24 +1,97 @@
/**
* @license
* Copyright 2025 Google LLC
* Copyright 2025 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*/
import { AuthType } from '@qwen-code/qwen-code-core';
import { loadEnvironment, loadSettings } from './settings.js';
import type {
ModelProvidersConfig,
ProviderModelConfig,
} from '@qwen-code/qwen-code-core';
import { loadEnvironment, loadSettings, type Settings } from './settings.js';
/**
* Default environment variable names for each auth type
*/
const DEFAULT_ENV_KEYS: Record<string, string> = {
[AuthType.USE_OPENAI]: 'OPENAI_API_KEY',
[AuthType.USE_ANTHROPIC]: 'ANTHROPIC_API_KEY',
[AuthType.USE_GEMINI]: 'GEMINI_API_KEY',
[AuthType.USE_VERTEX_AI]: 'GOOGLE_API_KEY',
};
/**
* Find model configuration from modelProviders by authType and modelId
*/
function findModelConfig(
modelProviders: ModelProvidersConfig | undefined,
authType: string,
modelId: string | undefined,
): ProviderModelConfig | undefined {
if (!modelProviders || !modelId) {
return undefined;
}
const models = modelProviders[authType];
if (!Array.isArray(models)) {
return undefined;
}
return models.find((m) => m.id === modelId);
}
/**
* Check if API key is available for the given auth type and model configuration.
* Prioritizes custom envKey from modelProviders over default environment variables.
*/
function hasApiKeyForAuth(
authType: string,
settings: Settings,
): { hasKey: boolean; checkedEnvKey: string | undefined } {
const modelProviders = settings.modelProviders as
| ModelProvidersConfig
| undefined;
const modelId = settings.model?.name;
// Try to find model-specific envKey from modelProviders
const modelConfig = findModelConfig(modelProviders, authType, modelId);
if (modelConfig?.envKey) {
const hasKey = !!process.env[modelConfig.envKey];
return { hasKey, checkedEnvKey: modelConfig.envKey };
}
// Fallback to default environment variable
const defaultEnvKey = DEFAULT_ENV_KEYS[authType];
if (defaultEnvKey) {
const hasKey = !!process.env[defaultEnvKey];
return { hasKey, checkedEnvKey: defaultEnvKey };
}
// Also check settings.security.auth.apiKey as fallback
if (settings.security?.auth?.apiKey) {
return { hasKey: true, checkedEnvKey: undefined };
}
return { hasKey: false, checkedEnvKey: undefined };
}
export function validateAuthMethod(authMethod: string): string | null {
const settings = loadSettings();
loadEnvironment(settings.merged);
if (authMethod === AuthType.USE_OPENAI) {
const hasApiKey =
process.env['OPENAI_API_KEY'] || settings.merged.security?.auth?.apiKey;
if (!hasApiKey) {
const { hasKey, checkedEnvKey } = hasApiKeyForAuth(
authMethod,
settings.merged,
);
if (!hasKey) {
const envKeyHint = checkedEnvKey
? `'${checkedEnvKey}'`
: "'OPENAI_API_KEY' (or configure modelProviders[].envKey)";
return (
'Missing API key for OpenAI-compatible auth. ' +
"Set settings.security.auth.apiKey, or set the 'OPENAI_API_KEY' environment variable. " +
'If you configured a model in settings.modelProviders with an envKey, set that env var as well.'
`Set settings.security.auth.apiKey, or set the ${envKeyHint} environment variable.`
);
}
return null;
@ -31,31 +104,50 @@ export function validateAuthMethod(authMethod: string): string | null {
}
if (authMethod === AuthType.USE_ANTHROPIC) {
const hasApiKey = process.env['ANTHROPIC_API_KEY'];
if (!hasApiKey) {
return 'ANTHROPIC_API_KEY environment variable not found.';
const { hasKey, checkedEnvKey } = hasApiKeyForAuth(
authMethod,
settings.merged,
);
if (!hasKey) {
const envKeyHint = checkedEnvKey || 'ANTHROPIC_API_KEY';
return `${envKeyHint} environment variable not found.`;
}
const hasBaseUrl = process.env['ANTHROPIC_BASE_URL'];
// Check baseUrl - can come from modelProviders or environment
const modelProviders = settings.merged.modelProviders as
| ModelProvidersConfig
| undefined;
const modelId = settings.merged.model?.name;
const modelConfig = findModelConfig(modelProviders, authMethod, modelId);
const hasBaseUrl =
modelConfig?.baseUrl || process.env['ANTHROPIC_BASE_URL'];
if (!hasBaseUrl) {
return 'ANTHROPIC_BASE_URL environment variable not found.';
return 'ANTHROPIC_BASE_URL environment variable not found (or configure modelProviders[].baseUrl).';
}
return null;
}
if (authMethod === AuthType.USE_GEMINI) {
const hasApiKey = process.env['GEMINI_API_KEY'];
if (!hasApiKey) {
return 'GEMINI_API_KEY environment variable not found. Please set it in your .env file or environment variables.';
const { hasKey, checkedEnvKey } = hasApiKeyForAuth(
authMethod,
settings.merged,
);
if (!hasKey) {
const envKeyHint = checkedEnvKey || 'GEMINI_API_KEY';
return `${envKeyHint} environment variable not found. Please set it in your .env file or environment variables.`;
}
return null;
}
if (authMethod === AuthType.USE_VERTEX_AI) {
const hasApiKey = process.env['GOOGLE_API_KEY'];
if (!hasApiKey) {
return 'GOOGLE_API_KEY environment variable not found. Please set it in your .env file or environment variables.';
const { hasKey, checkedEnvKey } = hasApiKeyForAuth(
authMethod,
settings.merged,
);
if (!hasKey) {
const envKeyHint = checkedEnvKey || 'GOOGLE_API_KEY';
return `${envKeyHint} environment variable not found. Please set it in your .env file or environment variables.`;
}
process.env['GOOGLE_GENAI_USE_VERTEXAI'] = 'true';