mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-14 06:17:27 +00:00
feat(cliproxy): clarify codex effort mapping and preset UX
This commit is contained in:
1 parent
a0d7c14ea0
commit
945db1d690
13 files changed
+245
-73
No files matched your search
@@ -165,7 +165,7 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
|
||||
{
|
||||
id: 'gpt-5.3-codex',
|
||||
name: 'GPT-5.3 Codex',
|
||||
description: 'Full reasoning support (xhigh)',
|
||||
description: 'Supports up to xhigh effort',
|
||||
thinking: {
|
||||
type: 'levels',
|
||||
levels: ['medium', 'high', 'xhigh'],
|
||||
@@ -187,7 +187,7 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
|
||||
{
|
||||
id: 'gpt-5-mini',
|
||||
name: 'GPT-5 Mini',
|
||||
description: 'Capped at high reasoning (no xhigh)',
|
||||
description: 'Capped at high effort (no xhigh)',
|
||||
thinking: {
|
||||
type: 'levels',
|
||||
levels: ['medium', 'high'],
|
||||
|
||||
@@ -14,6 +14,22 @@ import { CLIProxyProvider } from './types';
|
||||
import { initUI, color, bold, dim, ok, info, header } from '../utils/ui';
|
||||
import { getCcsDir } from '../utils/config-manager';
|
||||
|
||||
const CODEX_EFFORT_SUFFIX_REGEX = /-(xhigh|high|medium)$/i;
|
||||
|
||||
function stripCodexEffortSuffix(model: string, provider: CLIProxyProvider): string {
|
||||
if (provider !== 'codex') return model;
|
||||
return model.replace(CODEX_EFFORT_SUFFIX_REGEX, '');
|
||||
}
|
||||
|
||||
function normalizeCodexTierModel(
|
||||
provider: CLIProxyProvider,
|
||||
model: string,
|
||||
fallbackEffort: 'medium' | 'high' | 'xhigh'
|
||||
): string {
|
||||
if (provider !== 'codex') return model;
|
||||
return CODEX_EFFORT_SUFFIX_REGEX.test(model) ? model : `${model}-${fallbackEffort}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if provider has user settings configured
|
||||
*/
|
||||
@@ -120,7 +136,9 @@ export async function configureProviderModel(
|
||||
|
||||
// Find default index - use current model if configured, otherwise catalog default
|
||||
const currentModel = getCurrentModel(provider, customSettingsPath);
|
||||
const targetModel = currentModel || catalog.defaultModel;
|
||||
const targetModel = currentModel
|
||||
? stripCodexEffortSuffix(currentModel, provider)
|
||||
: catalog.defaultModel;
|
||||
const defaultIdx = catalog.models.findIndex((m) => m.id === targetModel);
|
||||
const safeDefaultIdx = defaultIdx >= 0 ? defaultIdx : 0;
|
||||
|
||||
@@ -142,10 +160,14 @@ export async function configureProviderModel(
|
||||
|
||||
// Get base env vars for defaults
|
||||
const baseEnv = getClaudeEnvVars(provider);
|
||||
const codexSonnetModel =
|
||||
provider === 'codex' && !selectedModel.match(/-(xhigh|high|medium)$/)
|
||||
? `${selectedModel}-high`
|
||||
: selectedModel;
|
||||
const selectedDefaultModel = normalizeCodexTierModel(provider, selectedModel, 'xhigh');
|
||||
const selectedOpusModel = normalizeCodexTierModel(provider, selectedModel, 'xhigh');
|
||||
const selectedSonnetModel = normalizeCodexTierModel(provider, selectedModel, 'high');
|
||||
const selectedHaikuModel = normalizeCodexTierModel(
|
||||
provider,
|
||||
baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL || selectedModel,
|
||||
'medium'
|
||||
);
|
||||
|
||||
// Read existing settings to preserve user customizations
|
||||
let existingSettings: Record<string, unknown> = {};
|
||||
@@ -167,10 +189,10 @@ export async function configureProviderModel(
|
||||
const ccsControlledEnv: Record<string, string> = {
|
||||
ANTHROPIC_BASE_URL: baseEnv.ANTHROPIC_BASE_URL || '',
|
||||
ANTHROPIC_AUTH_TOKEN: baseEnv.ANTHROPIC_AUTH_TOKEN || '',
|
||||
ANTHROPIC_MODEL: selectedModel,
|
||||
ANTHROPIC_DEFAULT_OPUS_MODEL: selectedModel,
|
||||
ANTHROPIC_DEFAULT_SONNET_MODEL: codexSonnetModel,
|
||||
ANTHROPIC_DEFAULT_HAIKU_MODEL: baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL || '',
|
||||
ANTHROPIC_MODEL: selectedDefaultModel,
|
||||
ANTHROPIC_DEFAULT_OPUS_MODEL: selectedOpusModel,
|
||||
ANTHROPIC_DEFAULT_SONNET_MODEL: selectedSonnetModel,
|
||||
ANTHROPIC_DEFAULT_HAIKU_MODEL: selectedHaikuModel,
|
||||
};
|
||||
|
||||
// Merge: user env vars (preserved) + CCS controlled (override)
|
||||
@@ -232,13 +254,16 @@ export async function showCurrentConfig(provider: CLIProxyProvider): Promise<voi
|
||||
|
||||
const currentModel = getCurrentModel(provider);
|
||||
const settingsPath = getProviderSettingsPath(provider);
|
||||
const normalizedCurrentModel = currentModel
|
||||
? stripCodexEffortSuffix(currentModel, provider)
|
||||
: undefined;
|
||||
|
||||
console.error('');
|
||||
console.error(header(`${catalog.displayName} Model Configuration`));
|
||||
console.error('');
|
||||
|
||||
if (currentModel) {
|
||||
const entry = catalog.models.find((m) => m.id === currentModel);
|
||||
const entry = catalog.models.find((m) => m.id === normalizedCurrentModel);
|
||||
const displayName = entry?.name || 'Unknown';
|
||||
console.error(
|
||||
` ${bold('Current:')} ${color(displayName, 'success')} ${dim(`(${currentModel})`)}`
|
||||
@@ -255,7 +280,7 @@ export async function showCurrentConfig(provider: CLIProxyProvider): Promise<voi
|
||||
console.error(dim(' [DEPRECATED] = Not recommended for use'));
|
||||
console.error('');
|
||||
catalog.models.forEach((m) => {
|
||||
const isCurrent = m.id === currentModel;
|
||||
const isCurrent = m.id === normalizedCurrentModel;
|
||||
console.error(formatModelDetailed(m, isCurrent));
|
||||
});
|
||||
|
||||
|
||||
@@ -35,6 +35,21 @@ interface SettingsFile {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
const CODEX_EFFORT_SUFFIX_REGEX = /-(xhigh|high|medium)$/i;
|
||||
|
||||
function hasCodexEffortSuffix(model: string): boolean {
|
||||
return CODEX_EFFORT_SUFFIX_REGEX.test(model);
|
||||
}
|
||||
|
||||
function normalizeCodexTierModel(
|
||||
provider: CLIProxyProfileName | undefined,
|
||||
model: string,
|
||||
fallbackEffort: 'medium' | 'high' | 'xhigh'
|
||||
): string {
|
||||
if (provider !== 'codex') return model;
|
||||
return hasCodexEffortSuffix(model) ? model : `${model}-${fallbackEffort}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build settings env object for a variant
|
||||
*/
|
||||
@@ -44,26 +59,25 @@ function buildSettingsEnv(
|
||||
port: number = CLIPROXY_DEFAULT_PORT
|
||||
): SettingsEnv {
|
||||
const baseEnv = getClaudeEnvVars(provider as CLIProxyProvider, port);
|
||||
const codexSonnetModel = normalizeCodexSonnetModel(provider, model);
|
||||
const defaultModel = normalizeCodexTierModel(provider, model, 'xhigh');
|
||||
const opusModel = normalizeCodexTierModel(provider, model, 'xhigh');
|
||||
const sonnetModel = normalizeCodexTierModel(provider, model, 'high');
|
||||
const haikuModel = normalizeCodexTierModel(
|
||||
provider,
|
||||
baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL || model,
|
||||
'medium'
|
||||
);
|
||||
|
||||
return {
|
||||
ANTHROPIC_BASE_URL: baseEnv.ANTHROPIC_BASE_URL || '',
|
||||
ANTHROPIC_AUTH_TOKEN: baseEnv.ANTHROPIC_AUTH_TOKEN || '',
|
||||
ANTHROPIC_MODEL: model,
|
||||
ANTHROPIC_DEFAULT_OPUS_MODEL: model,
|
||||
ANTHROPIC_DEFAULT_SONNET_MODEL: codexSonnetModel,
|
||||
ANTHROPIC_DEFAULT_HAIKU_MODEL: baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL || model,
|
||||
ANTHROPIC_MODEL: defaultModel,
|
||||
ANTHROPIC_DEFAULT_OPUS_MODEL: opusModel,
|
||||
ANTHROPIC_DEFAULT_SONNET_MODEL: sonnetModel,
|
||||
ANTHROPIC_DEFAULT_HAIKU_MODEL: haikuModel,
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeCodexSonnetModel(
|
||||
provider: CLIProxyProfileName | undefined,
|
||||
model: string
|
||||
): string {
|
||||
if (provider !== 'codex') return model;
|
||||
return /-(xhigh|high|medium)$/.test(model) ? model : `${model}-high`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure directory exists
|
||||
*/
|
||||
@@ -299,10 +313,20 @@ export function updateSettingsModel(
|
||||
|
||||
if (model) {
|
||||
settings.env = settings.env || ({} as SettingsEnv);
|
||||
const codexSonnetModel = normalizeCodexSonnetModel(provider, model);
|
||||
settings.env.ANTHROPIC_MODEL = model;
|
||||
settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL = model;
|
||||
settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL = codexSonnetModel;
|
||||
settings.env.ANTHROPIC_MODEL = normalizeCodexTierModel(provider, model, 'xhigh');
|
||||
settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL = normalizeCodexTierModel(provider, model, 'xhigh');
|
||||
settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL = normalizeCodexTierModel(
|
||||
provider,
|
||||
model,
|
||||
'high'
|
||||
);
|
||||
if (provider === 'codex' && settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL) {
|
||||
settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL = normalizeCodexTierModel(
|
||||
provider,
|
||||
settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL,
|
||||
'medium'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Clear model settings to use defaults
|
||||
delete (settings.env as unknown as Record<string, string>).ANTHROPIC_MODEL;
|
||||
|
||||
@@ -168,7 +168,7 @@ Run ${color('ccs config', 'command')} for web dashboard`.trim();
|
||||
],
|
||||
[
|
||||
['ccs gemini', 'Google Gemini (gemini-2.5-pro or 3-pro)'],
|
||||
['ccs codex', 'OpenAI Codex (gpt-5.3-codex)'],
|
||||
['ccs codex', 'OpenAI Codex (supports -medium/-high/-xhigh model suffixes)'],
|
||||
['ccs agy', 'Antigravity (Claude/Gemini models)'],
|
||||
['ccs qwen', 'Qwen Code (qwen3-coder)'],
|
||||
['ccs kiro', 'Kiro (AWS CodeWhisperer Claude models)'],
|
||||
@@ -346,11 +346,12 @@ Run ${color('ccs config', 'command')} for web dashboard`.trim();
|
||||
['--thinking <number>', 'Custom token budget (512-100000)'],
|
||||
['', ''],
|
||||
['--effort <level>', 'Codex alias for reasoning effort (medium/high/xhigh)'],
|
||||
['--effort xhigh', 'Codex 5.3 full-depth reasoning'],
|
||||
['--effort xhigh', 'Pin Codex effort to xhigh for this run'],
|
||||
['', ''],
|
||||
['Note:', 'Extended thinking allocates compute for step-by-step reasoning'],
|
||||
['', 'before responding.'],
|
||||
['', 'Providers: agy/gemini use --thinking, codex uses --effort (or --thinking alias).'],
|
||||
['', 'Codex model suffixes also pin effort: -medium / -high / -xhigh.'],
|
||||
]);
|
||||
|
||||
// Extended Context (1M)
|
||||
|
||||
Reference in new issue
Block a user