mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-29 20:20:57 +00:00
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:
parent
aa9cdf2a3c
commit
db12796df5
53 changed files with 5183 additions and 942 deletions
112
packages/cli/src/utils/modelConfigUtils.ts
Normal file
112
packages/cli/src/utils/modelConfigUtils.ts
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {
|
||||
AuthType,
|
||||
type ContentGeneratorConfig,
|
||||
type ContentGeneratorConfigSources,
|
||||
resolveModelConfig,
|
||||
type ModelConfigSourcesInput,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import type { Settings } from '../config/settings.js';
|
||||
|
||||
export interface CliGenerationConfigInputs {
|
||||
argv: {
|
||||
model?: string | undefined;
|
||||
openaiApiKey?: string | undefined;
|
||||
openaiBaseUrl?: string | undefined;
|
||||
openaiLogging?: boolean | undefined;
|
||||
openaiLoggingDir?: string | undefined;
|
||||
};
|
||||
settings: Settings;
|
||||
selectedAuthType: AuthType | undefined;
|
||||
/**
|
||||
* Injectable env for testability. Defaults to process.env at callsites.
|
||||
*/
|
||||
env?: Record<string, string | undefined>;
|
||||
}
|
||||
|
||||
export interface ResolvedCliGenerationConfig {
|
||||
/** The resolved model id (may be empty string if not resolvable at CLI layer) */
|
||||
model: string;
|
||||
/** API key for OpenAI-compatible auth */
|
||||
apiKey: string;
|
||||
/** Base URL for OpenAI-compatible auth */
|
||||
baseUrl: string;
|
||||
/** The full generation config to pass to core Config */
|
||||
generationConfig: Partial<ContentGeneratorConfig>;
|
||||
/** Source attribution for each resolved field */
|
||||
sources: ContentGeneratorConfigSources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified resolver for CLI generation config.
|
||||
*
|
||||
* Precedence (for OpenAI auth):
|
||||
* - model: argv.model > OPENAI_MODEL > QWEN_MODEL > settings.model.name
|
||||
* - apiKey: argv.openaiApiKey > OPENAI_API_KEY > settings.security.auth.apiKey
|
||||
* - baseUrl: argv.openaiBaseUrl > OPENAI_BASE_URL > settings.security.auth.baseUrl
|
||||
*
|
||||
* For non-OpenAI auth, only argv.model override is respected at CLI layer.
|
||||
*/
|
||||
export function resolveCliGenerationConfig(
|
||||
inputs: CliGenerationConfigInputs,
|
||||
): ResolvedCliGenerationConfig {
|
||||
const { argv, settings, selectedAuthType } = inputs;
|
||||
const env = inputs.env ?? (process.env as Record<string, string | undefined>);
|
||||
|
||||
const authType = selectedAuthType ?? AuthType.QWEN_OAUTH;
|
||||
|
||||
const configSources: ModelConfigSourcesInput = {
|
||||
authType,
|
||||
cli: {
|
||||
model: argv.model,
|
||||
apiKey: argv.openaiApiKey,
|
||||
baseUrl: argv.openaiBaseUrl,
|
||||
},
|
||||
settings: {
|
||||
model: settings.model?.name,
|
||||
apiKey: settings.security?.auth?.apiKey,
|
||||
baseUrl: settings.security?.auth?.baseUrl,
|
||||
generationConfig: settings.model?.generationConfig as
|
||||
| Partial<ContentGeneratorConfig>
|
||||
| undefined,
|
||||
},
|
||||
env,
|
||||
};
|
||||
|
||||
const resolved = resolveModelConfig(configSources);
|
||||
|
||||
// Log warnings if any
|
||||
for (const warning of resolved.warnings) {
|
||||
console.warn(`[modelProviderUtils] ${warning}`);
|
||||
}
|
||||
|
||||
// Resolve OpenAI logging config (CLI-specific, not part of core resolver)
|
||||
const enableOpenAILogging =
|
||||
(typeof argv.openaiLogging === 'undefined'
|
||||
? settings.model?.enableOpenAILogging
|
||||
: argv.openaiLogging) ?? false;
|
||||
|
||||
const openAILoggingDir =
|
||||
argv.openaiLoggingDir || settings.model?.openAILoggingDir;
|
||||
|
||||
// Build the full generation config
|
||||
// Note: we merge the resolved config with logging settings
|
||||
const generationConfig: Partial<ContentGeneratorConfig> = {
|
||||
...resolved.config,
|
||||
enableOpenAILogging,
|
||||
openAILoggingDir,
|
||||
};
|
||||
|
||||
return {
|
||||
model: resolved.config.model || '',
|
||||
apiKey: resolved.config.apiKey || '',
|
||||
baseUrl: resolved.config.baseUrl || '',
|
||||
generationConfig,
|
||||
sources: resolved.sources,
|
||||
};
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {
|
||||
AuthType,
|
||||
type ContentGeneratorConfig,
|
||||
type ContentGeneratorConfigSource,
|
||||
type ContentGeneratorConfigSources,
|
||||
type ModelProvidersConfig,
|
||||
type ProviderModelConfig as ModelConfig,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import type { Settings } from '../config/settings.js';
|
||||
|
||||
export interface GenerationConfigSourceInputs {
|
||||
argv: {
|
||||
model?: string | undefined;
|
||||
openaiApiKey?: string | undefined;
|
||||
openaiBaseUrl?: string | undefined;
|
||||
};
|
||||
settings: Settings;
|
||||
selectedAuthType: AuthType | undefined;
|
||||
/**
|
||||
* Injectable env for testability. Defaults to process.env at callsites.
|
||||
*/
|
||||
env?: Record<string, string | undefined>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get models configuration from settings, grouped by authType.
|
||||
* Returns the models config from the merged settings without mutating files.
|
||||
*/
|
||||
export function getModelProvidersConfigFromSettings(
|
||||
settings: Settings,
|
||||
): ModelProvidersConfig {
|
||||
return (settings.modelProviders as ModelProvidersConfig) || {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get models for a specific authType from settings.
|
||||
*/
|
||||
export function getModelsForAuthType(
|
||||
settings: Settings,
|
||||
authType: AuthType,
|
||||
): ModelConfig[] {
|
||||
const modelProvidersConfig = getModelProvidersConfigFromSettings(settings);
|
||||
return modelProvidersConfig[authType] || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Best-effort attribution for the seed generationConfig fields.
|
||||
*
|
||||
* NOTE:
|
||||
* - This does not attempt to distinguish user vs workspace settings; it reflects merged settings.
|
||||
* - This should stay consistent with the actual precedence used to compute the corresponding values.
|
||||
*/
|
||||
export function buildGenerationConfigSources(
|
||||
inputs: GenerationConfigSourceInputs,
|
||||
): ContentGeneratorConfigSources {
|
||||
const { argv, settings, selectedAuthType } = inputs;
|
||||
const env = inputs.env ?? (process.env as Record<string, string | undefined>);
|
||||
|
||||
const sources: ContentGeneratorConfigSources = {};
|
||||
|
||||
const setSource = (path: string, source: ContentGeneratorConfigSource) => {
|
||||
sources[path] = source;
|
||||
};
|
||||
|
||||
// Model/apiKey/baseUrl attribution mirrors current CLI precedence:
|
||||
// - model: argv.model > (OPENAI_MODEL|QWEN_MODEL|settings.model.name) only for OpenAI auth
|
||||
// - apiKey/baseUrl: only meaningful for OpenAI auth in current CLI wiring
|
||||
if (selectedAuthType === AuthType.USE_OPENAI) {
|
||||
if (argv.model) {
|
||||
setSource('model', { kind: 'cli', detail: '--model' });
|
||||
} else if (env['OPENAI_MODEL']) {
|
||||
setSource('model', { kind: 'env', envKey: 'OPENAI_MODEL' });
|
||||
} else if (env['QWEN_MODEL']) {
|
||||
setSource('model', { kind: 'env', envKey: 'QWEN_MODEL' });
|
||||
} else if (settings.model?.name) {
|
||||
setSource('model', { kind: 'settings', settingsPath: 'model.name' });
|
||||
}
|
||||
|
||||
if (argv.openaiApiKey) {
|
||||
setSource('apiKey', { kind: 'cli', detail: '--openaiApiKey' });
|
||||
} else if (env['OPENAI_API_KEY']) {
|
||||
setSource('apiKey', { kind: 'env', envKey: 'OPENAI_API_KEY' });
|
||||
} else if (settings.security?.auth?.apiKey) {
|
||||
setSource('apiKey', {
|
||||
kind: 'settings',
|
||||
settingsPath: 'security.auth.apiKey',
|
||||
});
|
||||
}
|
||||
|
||||
if (argv.openaiBaseUrl) {
|
||||
setSource('baseUrl', { kind: 'cli', detail: '--openaiBaseUrl' });
|
||||
} else if (env['OPENAI_BASE_URL']) {
|
||||
setSource('baseUrl', { kind: 'env', envKey: 'OPENAI_BASE_URL' });
|
||||
} else if (settings.security?.auth?.baseUrl) {
|
||||
setSource('baseUrl', {
|
||||
kind: 'settings',
|
||||
settingsPath: 'security.auth.baseUrl',
|
||||
});
|
||||
}
|
||||
} else if (argv.model) {
|
||||
// For non-openai auth types, the CLI only wires through an explicit raw model override.
|
||||
setSource('model', { kind: 'cli', detail: '--model' });
|
||||
}
|
||||
|
||||
const mergedGenerationConfig = settings.model?.generationConfig as
|
||||
| Partial<ContentGeneratorConfig>
|
||||
| undefined;
|
||||
if (mergedGenerationConfig) {
|
||||
setSource('generationConfig', {
|
||||
kind: 'settings',
|
||||
settingsPath: 'model.generationConfig',
|
||||
});
|
||||
// We also map the known top-level fields used by core.
|
||||
if (mergedGenerationConfig.samplingParams) {
|
||||
setSource('samplingParams', {
|
||||
kind: 'settings',
|
||||
settingsPath: 'model.generationConfig.samplingParams',
|
||||
});
|
||||
}
|
||||
for (const k of [
|
||||
'timeout',
|
||||
'maxRetries',
|
||||
'disableCacheControl',
|
||||
'schemaCompliance',
|
||||
] as const) {
|
||||
if (mergedGenerationConfig[k] !== undefined) {
|
||||
setSource(k, {
|
||||
kind: 'settings',
|
||||
settingsPath: `model.generationConfig.${k}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sources;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue