fix(cliproxy): keep canonical codex model ids in settings

This commit is contained in:
Tam Nhu Tran
2026-02-22 23:40:45 +07:00
parent 5003ae55db
commit a81176da79
4 changed files with 37 additions and 51 deletions
+4 -4
View File
@@ -2,9 +2,9 @@
"env": { "env": {
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/codex", "ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/codex",
"ANTHROPIC_AUTH_TOKEN": "ccs-internal-managed", "ANTHROPIC_AUTH_TOKEN": "ccs-internal-managed",
"ANTHROPIC_MODEL": "gpt-5.3-codex-xhigh", "ANTHROPIC_MODEL": "gpt-5.3-codex",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "gpt-5.3-codex-xhigh", "ANTHROPIC_DEFAULT_OPUS_MODEL": "gpt-5.3-codex",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "gpt-5.3-codex-high", "ANTHROPIC_DEFAULT_SONNET_MODEL": "gpt-5.3-codex",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "gpt-5-mini-medium" "ANTHROPIC_DEFAULT_HAIKU_MODEL": "gpt-5-mini"
} }
} }
+6 -11
View File
@@ -21,13 +21,9 @@ function stripCodexEffortSuffix(model: string, provider: CLIProxyProvider): stri
return model.replace(CODEX_EFFORT_SUFFIX_REGEX, ''); return model.replace(CODEX_EFFORT_SUFFIX_REGEX, '');
} }
function normalizeCodexTierModel( function normalizeCodexTierModel(provider: CLIProxyProvider, model: string): string {
provider: CLIProxyProvider,
model: string,
fallbackEffort: 'medium' | 'high' | 'xhigh'
): string {
if (provider !== 'codex') return model; if (provider !== 'codex') return model;
return CODEX_EFFORT_SUFFIX_REGEX.test(model) ? model : `${model}-${fallbackEffort}`; return stripCodexEffortSuffix(model, provider);
} }
/** /**
@@ -160,13 +156,12 @@ export async function configureProviderModel(
// Get base env vars for defaults // Get base env vars for defaults
const baseEnv = getClaudeEnvVars(provider); const baseEnv = getClaudeEnvVars(provider);
const selectedDefaultModel = normalizeCodexTierModel(provider, selectedModel, 'xhigh'); const selectedDefaultModel = normalizeCodexTierModel(provider, selectedModel);
const selectedOpusModel = normalizeCodexTierModel(provider, selectedModel, 'xhigh'); const selectedOpusModel = normalizeCodexTierModel(provider, selectedModel);
const selectedSonnetModel = normalizeCodexTierModel(provider, selectedModel, 'high'); const selectedSonnetModel = normalizeCodexTierModel(provider, selectedModel);
const selectedHaikuModel = normalizeCodexTierModel( const selectedHaikuModel = normalizeCodexTierModel(
provider, provider,
baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL || selectedModel, baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL || selectedModel
'medium'
); );
// Read existing settings to preserve user customizations // Read existing settings to preserve user customizations
+15 -24
View File
@@ -37,17 +37,12 @@ interface SettingsFile {
const CODEX_EFFORT_SUFFIX_REGEX = /-(xhigh|high|medium)$/i; const CODEX_EFFORT_SUFFIX_REGEX = /-(xhigh|high|medium)$/i;
function hasCodexEffortSuffix(model: string): boolean { function canonicalizeModelForProvider(
return CODEX_EFFORT_SUFFIX_REGEX.test(model);
}
function normalizeCodexTierModel(
provider: CLIProxyProfileName | undefined, provider: CLIProxyProfileName | undefined,
model: string, model: string
fallbackEffort: 'medium' | 'high' | 'xhigh'
): string { ): string {
if (provider !== 'codex') return model; if (provider !== 'codex') return model;
return hasCodexEffortSuffix(model) ? model : `${model}-${fallbackEffort}`; return model.replace(CODEX_EFFORT_SUFFIX_REGEX, '');
} }
/** /**
@@ -59,13 +54,13 @@ function buildSettingsEnv(
port: number = CLIPROXY_DEFAULT_PORT port: number = CLIPROXY_DEFAULT_PORT
): SettingsEnv { ): SettingsEnv {
const baseEnv = getClaudeEnvVars(provider as CLIProxyProvider, port); const baseEnv = getClaudeEnvVars(provider as CLIProxyProvider, port);
const defaultModel = normalizeCodexTierModel(provider, model, 'xhigh'); const normalizedModel = canonicalizeModelForProvider(provider, model);
const opusModel = normalizeCodexTierModel(provider, model, 'xhigh'); const defaultModel = normalizedModel;
const sonnetModel = normalizeCodexTierModel(provider, model, 'high'); const opusModel = normalizedModel;
const haikuModel = normalizeCodexTierModel( const sonnetModel = normalizedModel;
const haikuModel = canonicalizeModelForProvider(
provider, provider,
baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL || model, baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL || model
'medium'
); );
return { return {
@@ -313,18 +308,14 @@ export function updateSettingsModel(
if (model) { if (model) {
settings.env = settings.env || ({} as SettingsEnv); settings.env = settings.env || ({} as SettingsEnv);
settings.env.ANTHROPIC_MODEL = normalizeCodexTierModel(provider, model, 'xhigh'); const normalizedModel = canonicalizeModelForProvider(provider, model);
settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL = normalizeCodexTierModel(provider, model, 'xhigh'); settings.env.ANTHROPIC_MODEL = normalizedModel;
settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL = normalizeCodexTierModel( settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL = normalizedModel;
provider, settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL = normalizedModel;
model,
'high'
);
if (provider === 'codex' && settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL) { if (provider === 'codex' && settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL) {
settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL = normalizeCodexTierModel( settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL = canonicalizeModelForProvider(
provider, provider,
settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL, settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL
'medium'
); );
} }
} else { } else {
@@ -100,10 +100,10 @@ cliproxy:
}; };
expect(settings.env.ANTHROPIC_BASE_URL).toContain('/api/provider/codex'); expect(settings.env.ANTHROPIC_BASE_URL).toContain('/api/provider/codex');
expect(settings.env.ANTHROPIC_MODEL).toBe('gpt-5.1-codex-mini-xhigh'); expect(settings.env.ANTHROPIC_MODEL).toBe('gpt-5.1-codex-mini');
expect(settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL).toBe('gpt-5.1-codex-mini-xhigh'); expect(settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL).toBe('gpt-5.1-codex-mini');
expect(settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL).toBe('gpt-5.1-codex-mini-high'); expect(settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL).toBe('gpt-5.1-codex-mini');
expect(settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL).toBe('gpt-5-mini-medium'); expect(settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL).toBe('gpt-5-mini');
expect(settings.env.CUSTOM_FLAG).toBe('keep-me'); expect(settings.env.CUSTOM_FLAG).toBe('keep-me');
expect(settings.hooks.PreToolUse.length).toBe(1); expect(settings.hooks.PreToolUse.length).toBe(1);
@@ -122,10 +122,10 @@ cliproxy:
let settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8')) as { let settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8')) as {
env: Record<string, string>; env: Record<string, string>;
}; };
expect(settings.env.ANTHROPIC_MODEL).toBe('gpt-5.3-codex-xhigh'); expect(settings.env.ANTHROPIC_MODEL).toBe('gpt-5.3-codex');
expect(settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL).toBe('gpt-5.3-codex-xhigh'); expect(settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL).toBe('gpt-5.3-codex');
expect(settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL).toBe('gpt-5.3-codex-high'); expect(settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL).toBe('gpt-5.3-codex');
expect(settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL).toBe('gpt-5-mini-medium'); expect(settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL).toBe('gpt-5-mini');
const modelOnly = updateVariant('demo', { model: 'gpt-5.3-codex' }); const modelOnly = updateVariant('demo', { model: 'gpt-5.3-codex' });
expect(modelOnly.success).toBe(true); expect(modelOnly.success).toBe(true);
@@ -133,9 +133,9 @@ cliproxy:
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8')) as { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8')) as {
env: Record<string, string>; env: Record<string, string>;
}; };
expect(settings.env.ANTHROPIC_MODEL).toBe('gpt-5.3-codex-xhigh'); expect(settings.env.ANTHROPIC_MODEL).toBe('gpt-5.3-codex');
expect(settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL).toBe('gpt-5.3-codex-xhigh'); expect(settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL).toBe('gpt-5.3-codex');
expect(settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL).toBe('gpt-5.3-codex-high'); expect(settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL).toBe('gpt-5.3-codex');
expect(settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL).toBe('gpt-5-mini-medium'); expect(settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL).toBe('gpt-5-mini');
}); });
}); });