分离OpenAI和Anthropic模型的环境变量

This commit is contained in:
HitMargin
2026-04-05 03:31:06 +08:00
parent ec5dfed19e
commit eb6fbe518e
9 changed files with 689 additions and 666 deletions

View File

@@ -10,6 +10,10 @@
* @[MODEL LAUNCH]: New models usually don't need changes here —
* VERTEX_REGION_CLAUDE_* is prefix-matched. New providers or new routing
* config vars (endpoint, project, region, auth) do.
*
* Note: OpenAI provider uses OPENAI_* env vars (OPENAI_API_KEY, OPENAI_BASE_URL,
* OPENAI_MODEL, OPENAI_DEFAULT_*_MODEL, OPENAI_SMALL_FAST_MODEL) which are all
* provider-managed to keep routing config isolated from Anthropic settings.
*/
const PROVIDER_MANAGED_ENV_VARS = new Set([
// The flag itself — settings can't unset it once the host set it
@@ -50,6 +54,23 @@ const PROVIDER_MANAGED_ENV_VARS = new Set([
'ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION',
'ANTHROPIC_DEFAULT_SONNET_MODEL_NAME',
'ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES',
// OpenAI provider specific
'OPENAI_API_KEY',
'OPENAI_BASE_URL',
'OPENAI_MODEL',
'OPENAI_DEFAULT_HAIKU_MODEL',
'OPENAI_DEFAULT_HAIKU_MODEL_DESCRIPTION',
'OPENAI_DEFAULT_HAIKU_MODEL_NAME',
'OPENAI_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES',
'OPENAI_DEFAULT_OPUS_MODEL',
'OPENAI_DEFAULT_OPUS_MODEL_DESCRIPTION',
'OPENAI_DEFAULT_OPUS_MODEL_NAME',
'OPENAI_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES',
'OPENAI_DEFAULT_SONNET_MODEL',
'OPENAI_DEFAULT_SONNET_MODEL_DESCRIPTION',
'OPENAI_DEFAULT_SONNET_MODEL_NAME',
'OPENAI_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES',
'OPENAI_SMALL_FAST_MODEL',
'ANTHROPIC_SMALL_FAST_MODEL',
'ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION',
'CLAUDE_CODE_SUBAGENT_MODEL',
@@ -122,6 +143,19 @@ export const SAFE_ENV_VARS = new Set([
'ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION',
'ANTHROPIC_DEFAULT_SONNET_MODEL_NAME',
'ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES',
// OpenAI provider specific
'OPENAI_DEFAULT_HAIKU_MODEL',
'OPENAI_DEFAULT_HAIKU_MODEL_DESCRIPTION',
'OPENAI_DEFAULT_HAIKU_MODEL_NAME',
'OPENAI_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES',
'OPENAI_DEFAULT_OPUS_MODEL',
'OPENAI_DEFAULT_OPUS_MODEL_DESCRIPTION',
'OPENAI_DEFAULT_OPUS_MODEL_NAME',
'OPENAI_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES',
'OPENAI_DEFAULT_SONNET_MODEL',
'OPENAI_DEFAULT_SONNET_MODEL_DESCRIPTION',
'OPENAI_DEFAULT_SONNET_MODEL_NAME',
'OPENAI_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES',
'ANTHROPIC_FOUNDRY_API_KEY',
'ANTHROPIC_MODEL',
'ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION',

View File

@@ -104,6 +104,11 @@ export function getBestModel(): ModelName {
// @[MODEL LAUNCH]: Update the default Opus model (3P providers may lag so keep defaults unchanged).
export function getDefaultOpusModel(): ModelName {
// For OpenAI provider, check OPENAI_DEFAULT_OPUS_MODEL first
if (getAPIProvider() === 'openai' && process.env.OPENAI_DEFAULT_OPUS_MODEL) {
return process.env.OPENAI_DEFAULT_OPUS_MODEL
}
// Anthropic-specific override (for first-party and other 3P providers)
if (process.env.ANTHROPIC_DEFAULT_OPUS_MODEL) {
return process.env.ANTHROPIC_DEFAULT_OPUS_MODEL
}
@@ -118,6 +123,14 @@ export function getDefaultOpusModel(): ModelName {
// @[MODEL LAUNCH]: Update the default Sonnet model (3P providers may lag so keep defaults unchanged).
export function getDefaultSonnetModel(): ModelName {
// For OpenAI provider, check OPENAI_DEFAULT_SONNET_MODEL first
if (
getAPIProvider() === 'openai' &&
process.env.OPENAI_DEFAULT_SONNET_MODEL
) {
return process.env.OPENAI_DEFAULT_SONNET_MODEL
}
// Anthropic-specific override (for first-party and other 3P providers)
if (process.env.ANTHROPIC_DEFAULT_SONNET_MODEL) {
return process.env.ANTHROPIC_DEFAULT_SONNET_MODEL
}
@@ -130,6 +143,11 @@ export function getDefaultSonnetModel(): ModelName {
// @[MODEL LAUNCH]: Update the default Haiku model (3P providers may lag so keep defaults unchanged).
export function getDefaultHaikuModel(): ModelName {
// For OpenAI provider, check OPENAI_DEFAULT_HAIKU_MODEL first
if (getAPIProvider() === 'openai' && process.env.OPENAI_DEFAULT_HAIKU_MODEL) {
return process.env.OPENAI_DEFAULT_HAIKU_MODEL
}
// Anthropic-specific override (for first-party and other 3P providers)
if (process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL) {
return process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL
}

View File

@@ -76,18 +76,29 @@ export function getDefaultOptionForUser(fastMode = false): ModelOption {
function getCustomSonnetOption(): ModelOption | undefined {
const is3P = getAPIProvider() !== 'firstParty'
const customSonnetModel = process.env.ANTHROPIC_DEFAULT_SONNET_MODEL
// For OpenAI provider, use OPENAI_DEFAULT_SONNET_MODEL; for other 3P, use ANTHROPIC_DEFAULT_SONNET_MODEL
const customSonnetModel =
getAPIProvider() === 'openai'
? process.env.OPENAI_DEFAULT_SONNET_MODEL
: process.env.ANTHROPIC_DEFAULT_SONNET_MODEL
// When a 3P user has a custom sonnet model string, show it directly
if (is3P && customSonnetModel) {
const is1m = has1mContext(customSonnetModel)
// Use appropriate NAME/DESCRIPTION env vars based on provider
const nameEnv =
getAPIProvider() === 'openai'
? process.env.OPENAI_DEFAULT_SONNET_MODEL_NAME
: process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_NAME
const descEnv =
getAPIProvider() === 'openai'
? process.env.OPENAI_DEFAULT_SONNET_MODEL_DESCRIPTION
: process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION
return {
value: 'sonnet',
label:
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_NAME ?? customSonnetModel,
label: nameEnv ?? customSonnetModel,
description:
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION ??
`Custom Sonnet model${is1m ? ' (1M context)' : ''}`,
descriptionForModel: `${process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION ?? `Custom Sonnet model${is1m ? ' with 1M context' : ''}`} (${customSonnetModel})`,
descEnv ?? `Custom Sonnet model${is1m ? ' (1M context)' : ''}`,
descriptionForModel: `${descEnv ?? `Custom Sonnet model${is1m ? ' with 1M context' : ''}`} (${customSonnetModel})`,
}
}
}
@@ -107,17 +118,28 @@ function getSonnet46Option(): ModelOption {
function getCustomOpusOption(): ModelOption | undefined {
const is3P = getAPIProvider() !== 'firstParty'
const customOpusModel = process.env.ANTHROPIC_DEFAULT_OPUS_MODEL
// For OpenAI provider, use OPENAI_DEFAULT_OPUS_MODEL; for other 3P, use ANTHROPIC_DEFAULT_OPUS_MODEL
const customOpusModel =
getAPIProvider() === 'openai'
? process.env.OPENAI_DEFAULT_OPUS_MODEL
: process.env.ANTHROPIC_DEFAULT_OPUS_MODEL
// When a 3P user has a custom opus model string, show it directly
if (is3P && customOpusModel) {
const is1m = has1mContext(customOpusModel)
// Use appropriate NAME/DESCRIPTION env vars based on provider
const nameEnv =
getAPIProvider() === 'openai'
? process.env.OPENAI_DEFAULT_OPUS_MODEL_NAME
: process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_NAME
const descEnv =
getAPIProvider() === 'openai'
? process.env.OPENAI_DEFAULT_OPUS_MODEL_DESCRIPTION
: process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION
return {
value: 'opus',
label: process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_NAME ?? customOpusModel,
description:
process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION ??
`Custom Opus model${is1m ? ' (1M context)' : ''}`,
descriptionForModel: `${process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION ?? `Custom Opus model${is1m ? ' with 1M context' : ''}`} (${customOpusModel})`,
label: nameEnv ?? customOpusModel,
description: descEnv ?? `Custom Opus model${is1m ? ' (1M context)' : ''}`,
descriptionForModel: `${descEnv ?? `Custom Opus model${is1m ? ' with 1M context' : ''}`} (${customOpusModel})`,
}
}
}
@@ -165,16 +187,27 @@ export function getOpus46_1MOption(fastMode = false): ModelOption {
function getCustomHaikuOption(): ModelOption | undefined {
const is3P = getAPIProvider() !== 'firstParty'
const customHaikuModel = process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL
// For OpenAI provider, use OPENAI_DEFAULT_HAIKU_MODEL; for other 3P, use ANTHROPIC_DEFAULT_HAIKU_MODEL
const customHaikuModel =
getAPIProvider() === 'openai'
? process.env.OPENAI_DEFAULT_HAIKU_MODEL
: process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL
// When a 3P user has a custom haiku model string, show it directly
if (is3P && customHaikuModel) {
// Use appropriate NAME/DESCRIPTION env vars based on provider
const nameEnv =
getAPIProvider() === 'openai'
? process.env.OPENAI_DEFAULT_HAIKU_MODEL_NAME
: process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME
const descEnv =
getAPIProvider() === 'openai'
? process.env.OPENAI_DEFAULT_HAIKU_MODEL_DESCRIPTION
: process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION
return {
value: 'haiku',
label: process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME ?? customHaikuModel,
description:
process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION ??
'Custom Haiku model',
descriptionForModel: `${process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION ?? 'Custom Haiku model'} (${customHaikuModel})`,
label: nameEnv ?? customHaikuModel,
description: descEnv ?? 'Custom Haiku model',
descriptionForModel: `${descEnv ?? 'Custom Haiku model'} (${customHaikuModel})`,
}
}
}

View File

@@ -8,7 +8,7 @@ export type ModelCapabilityOverride =
| 'adaptive_thinking'
| 'interleaved_thinking'
const TIERS = [
const ANTHROPIC_TIERS = [
{
modelEnvVar: 'ANTHROPIC_DEFAULT_OPUS_MODEL',
capabilitiesEnvVar: 'ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES',
@@ -23,9 +23,24 @@ const TIERS = [
},
] as const
const OPENAI_TIERS = [
{
modelEnvVar: 'OPENAI_DEFAULT_OPUS_MODEL',
capabilitiesEnvVar: 'OPENAI_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES',
},
{
modelEnvVar: 'OPENAI_DEFAULT_SONNET_MODEL',
capabilitiesEnvVar: 'OPENAI_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES',
},
{
modelEnvVar: 'OPENAI_DEFAULT_HAIKU_MODEL',
capabilitiesEnvVar: 'OPENAI_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES',
},
] as const
/**
* Check whether a 3p model capability override is set for a model that matches one of
* the pinned ANTHROPIC_DEFAULT_*_MODEL env vars.
* the pinned ANTHROPIC_DEFAULT_*_MODEL or OPENAI_DEFAULT_*_MODEL env vars.
*/
export const get3PModelCapabilityOverride = memoize(
(model: string, capability: ModelCapabilityOverride): boolean | undefined => {
@@ -33,7 +48,9 @@ export const get3PModelCapabilityOverride = memoize(
return undefined
}
const m = model.toLowerCase()
for (const tier of TIERS) {
// Choose the appropriate tier list based on provider
const tiers = getAPIProvider() === 'openai' ? OPENAI_TIERS : ANTHROPIC_TIERS
for (const tier of tiers) {
const pinned = process.env[tier.modelEnvVar]
const capabilities = process.env[tier.capabilitiesEnvVar]
if (!pinned || capabilities === undefined) continue