diff --git a/src/services/api/providerConfig.ts b/src/services/api/providerConfig.ts index 0e5fe44d..24de14c3 100644 --- a/src/services/api/providerConfig.ts +++ b/src/services/api/providerConfig.ts @@ -201,7 +201,7 @@ function parseModelDescriptor(model: string): ModelDescriptor { } } -function isCodexAlias(model: string): boolean { +export function isCodexAlias(model: string): boolean { const normalized = model.trim().toLowerCase() const base = normalized.split('?', 1)[0] ?? normalized return base in CODEX_ALIAS_MODELS diff --git a/src/utils/model/model.ts b/src/utils/model/model.ts index 97a74d95..002490ee 100644 --- a/src/utils/model/model.ts +++ b/src/utils/model/model.ts @@ -75,7 +75,15 @@ export function getUserSpecifiedModelSetting(): ModelSetting | undefined { specifiedModel = modelOverride } else { const settings = getSettings_DEPRECATED() || {} - specifiedModel = process.env.ANTHROPIC_MODEL || process.env.GEMINI_MODEL || process.env.OPENAI_MODEL || settings.model || undefined + // Read the model env var that matches the active provider to prevent + // cross-provider leaks (e.g. ANTHROPIC_MODEL sent to the OpenAI API). + const provider = getAPIProvider() + specifiedModel = + (provider === 'gemini' ? process.env.GEMINI_MODEL : undefined) || + (provider === 'openai' || provider === 'gemini' ? process.env.OPENAI_MODEL : undefined) || + (provider === 'firstParty' ? process.env.ANTHROPIC_MODEL : undefined) || + settings.model || + undefined } // Ignore the user-specified model if it's not in the availableModels allowlist. diff --git a/src/utils/model/providers.ts b/src/utils/model/providers.ts index 6b6d627e..2c25163b 100644 --- a/src/utils/model/providers.ts +++ b/src/utils/model/providers.ts @@ -1,4 +1,5 @@ import type { AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS } from '../../services/analytics/index.js' +import { isCodexAlias } from '../../services/api/providerConfig.js' import { isEnvTruthy } from '../envUtils.js' export type APIProvider = @@ -33,17 +34,11 @@ export function usesAnthropicAccountFlow(): boolean { return getAPIProvider() === 'firstParty' } function isCodexModel(): boolean { - const model = (process.env.OPENAI_MODEL || '').toLowerCase() - return ( - model === 'codexplan' || - model === 'codexspark' || - model === 'gpt-5.4' || - model === 'gpt-5.3-codex' || - model === 'gpt-5.3-codex-spark' || - model === 'gpt-5.2-codex' || - model === 'gpt-5.1-codex-max' || - model === 'gpt-5.1-codex-mini' - ) + const model = (process.env.OPENAI_MODEL || '').trim() + if (!model) return false + // Delegate to the canonical alias table in providerConfig to keep + // the two Codex detection systems (provider type + transport) in sync. + return isCodexAlias(model) } export function getAPIProviderForStatsig(): AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS {