diff --git a/src/agents/model-id-normalization.ts b/src/agents/model-id-normalization.ts index 9b0b27a7f01..c0c694a0dfa 100644 --- a/src/agents/model-id-normalization.ts +++ b/src/agents/model-id-normalization.ts @@ -1,5 +1,5 @@ -// Keep model ID normalization dependency-free so config parsing and other -// startup-only paths do not pull in provider discovery or plugin loading. +// Keep these helpers dependency-free so config/model parsing can use them +// without pulling in provider discovery or auth-profile graphs. export function normalizeGoogleModelId(id: string): string { if (id === "gemini-3-pro") { return "gemini-3-pro-preview"; diff --git a/src/agents/model-selection.ts b/src/agents/model-selection.ts index acc29a32bf9..289d9d53290 100644 --- a/src/agents/model-selection.ts +++ b/src/agents/model-selection.ts @@ -16,12 +16,6 @@ import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "./defaults.js"; import type { ModelCatalogEntry } from "./model-catalog.js"; import { normalizeGoogleModelId } from "./model-id-normalization.js"; import { splitTrailingAuthProfile } from "./model-ref-profile.js"; -import { - findNormalizedProviderKey, - findNormalizedProviderValue, - normalizeProviderId, - normalizeProviderIdForAuth, -} from "./provider-id.js"; const log = createSubsystemLogger("model-selection"); @@ -41,6 +35,72 @@ function normalizeAliasKey(value: string): string { return value.trim().toLowerCase(); } +export function normalizeProviderId(provider: string): string { + const normalized = provider.trim().toLowerCase(); + if (normalized === "z.ai" || normalized === "z-ai") { + return "zai"; + } + if (normalized === "opencode-zen") { + return "opencode"; + } + if (normalized === "opencode-go-auth") { + return "opencode-go"; + } + if (normalized === "qwen") { + return "qwen-portal"; + } + if (normalized === "kimi" || normalized === "kimi-code" || normalized === "kimi-coding") { + return "kimi"; + } + if (normalized === "bedrock" || normalized === "aws-bedrock") { + return "amazon-bedrock"; + } + // Backward compatibility for older provider naming. + if (normalized === "bytedance" || normalized === "doubao") { + return "volcengine"; + } + return normalized; +} + +/** Normalize provider ID for auth lookup. Coding-plan variants share auth with base. */ +export function normalizeProviderIdForAuth(provider: string): string { + const normalized = normalizeProviderId(provider); + if (normalized === "volcengine-plan") { + return "volcengine"; + } + if (normalized === "byteplus-plan") { + return "byteplus"; + } + return normalized; +} + +export function findNormalizedProviderValue( + entries: Record | undefined, + provider: string, +): T | undefined { + if (!entries) { + return undefined; + } + const providerKey = normalizeProviderId(provider); + for (const [key, value] of Object.entries(entries)) { + if (normalizeProviderId(key) === providerKey) { + return value; + } + } + return undefined; +} + +export function findNormalizedProviderKey( + entries: Record | undefined, + provider: string, +): string | undefined { + if (!entries) { + return undefined; + } + const providerKey = normalizeProviderId(provider); + return Object.keys(entries).find((key) => normalizeProviderId(key) === providerKey); +} + export function modelKey(provider: string, model: string) { const providerId = provider.trim(); const modelId = model.trim(); diff --git a/src/agents/models-config.providers.ts b/src/agents/models-config.providers.ts index af9c3d6e34a..4281ad505cb 100644 --- a/src/agents/models-config.providers.ts +++ b/src/agents/models-config.providers.ts @@ -182,6 +182,8 @@ type ProfileApiKeyResolution = { discoveryApiKey?: string; }; +export { normalizeGoogleModelId }; + function toDiscoveryApiKey(value: string | undefined): string | undefined { const trimmed = value?.trim(); if (!trimmed || isNonSecretApiKeyMarker(trimmed)) {