mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-05 10:13:12 +00:00
1 parent
da6c99e3df
commit
24eae8ae8f
8 files changed
+111
-4
No files matched your search
@@ -247,6 +247,9 @@ describe('Model Catalog', () => {
|
||||
const { MODEL_CATALOG } = modelCatalog;
|
||||
const ids = MODEL_CATALOG.codex.models.map((m) => m.id);
|
||||
assert.deepStrictEqual(ids, [
|
||||
'gpt-5.6-sol',
|
||||
'gpt-5.6-terra',
|
||||
'gpt-5.6-luna',
|
||||
'gpt-5.5',
|
||||
'gpt-5.4',
|
||||
'gpt-5.4-mini',
|
||||
|
||||
@@ -29,6 +29,9 @@ describe('codex plan compatibility', () => {
|
||||
});
|
||||
|
||||
it('does not rewrite cross-plan or already-safe Codex models', () => {
|
||||
expect(getFreePlanFallbackCodexModel('gpt-5.6-sol')).toBeNull();
|
||||
expect(getFreePlanFallbackCodexModel('gpt-5.6-terra-high')).toBeNull();
|
||||
expect(getFreePlanFallbackCodexModel('gpt-5.6-luna-fast')).toBeNull();
|
||||
expect(getFreePlanFallbackCodexModel('gpt-5.4')).toBeNull();
|
||||
expect(getFreePlanFallbackCodexModel('gpt-5.4-mini')).toBeNull();
|
||||
expect(getFreePlanFallbackCodexModel('gpt-5.2')).toBeNull();
|
||||
@@ -94,6 +97,9 @@ describe('codex plan compatibility', () => {
|
||||
});
|
||||
|
||||
it('tracks Codex thinking caps for current safe defaults, paid models, and legacy aliases', () => {
|
||||
expect(getModelMaxLevel('codex', 'gpt-5.6-sol')).toBe('xhigh');
|
||||
expect(getModelMaxLevel('codex', 'gpt-5.6-terra')).toBe('xhigh');
|
||||
expect(getModelMaxLevel('codex', 'gpt-5.6-luna')).toBe('xhigh');
|
||||
expect(getModelMaxLevel('codex', 'gpt-5.5')).toBe('xhigh');
|
||||
expect(getModelMaxLevel('codex', 'gpt-5.4')).toBe('xhigh');
|
||||
expect(getModelMaxLevel('codex', 'gpt-5.4-mini')).toBe('high');
|
||||
|
||||
@@ -190,6 +190,42 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
|
||||
displayName: 'Copilot Codex',
|
||||
defaultModel: 'gpt-5.4',
|
||||
models: [
|
||||
{
|
||||
id: 'gpt-5.6-sol',
|
||||
name: 'GPT-5.6 Sol',
|
||||
description: 'Latest frontier agentic coding model.',
|
||||
thinking: {
|
||||
type: 'levels',
|
||||
levels: ['low', 'medium', 'high', 'xhigh'],
|
||||
maxLevel: 'xhigh',
|
||||
dynamicAllowed: false,
|
||||
},
|
||||
codexServiceTiers: ['fast'],
|
||||
},
|
||||
{
|
||||
id: 'gpt-5.6-terra',
|
||||
name: 'GPT-5.6 Terra',
|
||||
description: 'Balanced agentic coding model for everyday work.',
|
||||
thinking: {
|
||||
type: 'levels',
|
||||
levels: ['low', 'medium', 'high', 'xhigh'],
|
||||
maxLevel: 'xhigh',
|
||||
dynamicAllowed: false,
|
||||
},
|
||||
codexServiceTiers: ['fast'],
|
||||
},
|
||||
{
|
||||
id: 'gpt-5.6-luna',
|
||||
name: 'GPT-5.6 Luna',
|
||||
description: 'Fast and affordable agentic coding model.',
|
||||
thinking: {
|
||||
type: 'levels',
|
||||
levels: ['low', 'medium', 'high', 'xhigh'],
|
||||
maxLevel: 'xhigh',
|
||||
dynamicAllowed: false,
|
||||
},
|
||||
codexServiceTiers: ['fast'],
|
||||
},
|
||||
{
|
||||
id: 'gpt-5.5',
|
||||
name: 'GPT-5.5',
|
||||
|
||||
@@ -43,6 +43,8 @@ export interface ModelEntry {
|
||||
};
|
||||
/** Highest codex reasoning-effort suffix this model supports in the dashboard UI. */
|
||||
codexMaxEffort?: CodexEffort;
|
||||
/** Exact Codex reasoning-effort suffixes supported by this model in the dashboard UI. */
|
||||
codexEfforts?: CodexEffort[];
|
||||
/** Additional Codex service-tier suffixes supported by this model in the dashboard UI. */
|
||||
codexServiceTiers?: CodexServiceTier[];
|
||||
}
|
||||
@@ -347,12 +349,13 @@ function getPreferredOptionValue(
|
||||
|
||||
function getModelOptionValues(
|
||||
codexMaxEffort: CodexEffort | undefined,
|
||||
codexEfforts: readonly CodexEffort[] | undefined,
|
||||
codexServiceTiers: readonly CodexServiceTier[] | undefined,
|
||||
optionValue: string,
|
||||
isCodexProvider: boolean
|
||||
): string[] {
|
||||
return isCodexProvider
|
||||
? getCodexEffortVariants(optionValue, codexMaxEffort, codexServiceTiers)
|
||||
? getCodexEffortVariants(optionValue, codexMaxEffort, codexServiceTiers, codexEfforts)
|
||||
: [optionValue];
|
||||
}
|
||||
|
||||
@@ -395,6 +398,7 @@ export function FlexibleModelSelector({
|
||||
resolvedCatalogModels.flatMap((model) =>
|
||||
getModelOptionValues(
|
||||
model.codexMaxEffort,
|
||||
model.codexEfforts,
|
||||
model.codexServiceTiers,
|
||||
getPreferredOptionValue(model.id, routingHints.get(model.id.toLowerCase())),
|
||||
isCodexProvider
|
||||
@@ -431,6 +435,7 @@ export function FlexibleModelSelector({
|
||||
const routingHint = routingHints.get(model.id.toLowerCase());
|
||||
const optionValues = getModelOptionValues(
|
||||
model.codexMaxEffort,
|
||||
model.codexEfforts,
|
||||
model.codexServiceTiers,
|
||||
getPreferredOptionValue(model.id, routingHint),
|
||||
isCodexProvider
|
||||
@@ -485,6 +490,7 @@ export function FlexibleModelSelector({
|
||||
.flatMap((model) => {
|
||||
const routingHint = routingHints.get(model.id.toLowerCase());
|
||||
const optionValues = getModelOptionValues(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
getPreferredOptionValue(model.id, routingHint),
|
||||
|
||||
@@ -69,7 +69,8 @@ export function applyCodexEffortSuffix(
|
||||
export function getCodexEffortVariants(
|
||||
modelId: string,
|
||||
maxEffort: CodexEffort | undefined,
|
||||
serviceTiers: readonly CodexServiceTier[] = []
|
||||
serviceTiers: readonly CodexServiceTier[] = [],
|
||||
efforts?: readonly CodexEffort[]
|
||||
): string[] {
|
||||
if (!maxEffort) {
|
||||
const explicitEffort = parseCodexEffort(modelId);
|
||||
@@ -91,9 +92,9 @@ export function getCodexEffortVariants(
|
||||
|
||||
appendVariantsForEffort(undefined);
|
||||
|
||||
for (const effort of CODEX_EFFORTS_IN_ORDER) {
|
||||
for (const effort of efforts ?? CODEX_EFFORTS_IN_ORDER) {
|
||||
appendVariantsForEffort(effort);
|
||||
if (effort === maxEffort) {
|
||||
if (!efforts && effort === maxEffort) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,6 +259,48 @@ export const MODEL_CATALOGS: Record<string, ProviderCatalog> = {
|
||||
displayName: 'Codex',
|
||||
defaultModel: 'gpt-5.4',
|
||||
models: [
|
||||
{
|
||||
id: 'gpt-5.6-sol',
|
||||
name: 'GPT-5.6 Sol',
|
||||
description: 'Latest frontier agentic coding model.',
|
||||
codexMaxEffort: 'xhigh',
|
||||
codexEfforts: ['low', 'medium', 'high', 'xhigh'],
|
||||
codexServiceTiers: ['fast'],
|
||||
presetMapping: {
|
||||
default: 'gpt-5.6-sol',
|
||||
opus: 'gpt-5.6-sol',
|
||||
sonnet: 'gpt-5.6-sol',
|
||||
haiku: 'gpt-5.4-mini',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'gpt-5.6-terra',
|
||||
name: 'GPT-5.6 Terra',
|
||||
description: 'Balanced agentic coding model for everyday work.',
|
||||
codexMaxEffort: 'xhigh',
|
||||
codexEfforts: ['low', 'medium', 'high', 'xhigh'],
|
||||
codexServiceTiers: ['fast'],
|
||||
presetMapping: {
|
||||
default: 'gpt-5.6-terra',
|
||||
opus: 'gpt-5.6-terra',
|
||||
sonnet: 'gpt-5.6-terra',
|
||||
haiku: 'gpt-5.4-mini',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'gpt-5.6-luna',
|
||||
name: 'GPT-5.6 Luna',
|
||||
description: 'Fast and affordable agentic coding model.',
|
||||
codexMaxEffort: 'xhigh',
|
||||
codexEfforts: ['low', 'medium', 'high', 'xhigh'],
|
||||
codexServiceTiers: ['fast'],
|
||||
presetMapping: {
|
||||
default: 'gpt-5.6-luna',
|
||||
opus: 'gpt-5.6-luna',
|
||||
sonnet: 'gpt-5.6-luna',
|
||||
haiku: 'gpt-5.4-mini',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'gpt-5.5',
|
||||
name: 'GPT-5.5',
|
||||
|
||||
@@ -191,6 +191,10 @@ describe('FlexibleModelSelector', () => {
|
||||
expect(screen.getByText('gpt-5.3-codex-high')).toBeInTheDocument();
|
||||
expect(screen.getByText('gpt-5.3-codex-xhigh')).toBeInTheDocument();
|
||||
expect(screen.getByText('gpt-5.4-high-fast')).toBeInTheDocument();
|
||||
expect(screen.getByText('gpt-5.6-sol-low')).toBeInTheDocument();
|
||||
expect(screen.getByText('gpt-5.6-terra-xhigh')).toBeInTheDocument();
|
||||
expect(screen.getByText('gpt-5.6-luna-fast')).toBeInTheDocument();
|
||||
expect(screen.queryByText('gpt-5.6-sol-minimal')).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.click(screen.getByText('gpt-5.3-codex-high'));
|
||||
expect(onChange).toHaveBeenCalledWith('gpt-5.3-codex-high');
|
||||
|
||||
@@ -4,6 +4,9 @@ import { MODEL_CATALOGS } from '@/lib/model-catalogs';
|
||||
describe('codex model catalog defaults', () => {
|
||||
it('mirrors the current Codex runtime catalog and free-safe defaults', () => {
|
||||
const codexCatalog = MODEL_CATALOGS.codex;
|
||||
const codex56Sol = codexCatalog.models.find((model) => model.id === 'gpt-5.6-sol');
|
||||
const codex56Terra = codexCatalog.models.find((model) => model.id === 'gpt-5.6-terra');
|
||||
const codex56Luna = codexCatalog.models.find((model) => model.id === 'gpt-5.6-luna');
|
||||
const codex55 = codexCatalog.models.find((model) => model.id === 'gpt-5.5');
|
||||
const codex53 = codexCatalog.models.find((model) => model.id === 'gpt-5.3-codex');
|
||||
const codex52 = codexCatalog.models.find((model) => model.id === 'gpt-5.2');
|
||||
@@ -11,6 +14,12 @@ describe('codex model catalog defaults', () => {
|
||||
const codexMini = codexCatalog.models.find((model) => model.id === 'gpt-5.4-mini');
|
||||
|
||||
expect(codexCatalog.defaultModel).toBe('gpt-5.4');
|
||||
for (const model of [codex56Sol, codex56Terra, codex56Luna]) {
|
||||
expect(model?.tier).toBeUndefined();
|
||||
expect(model?.codexEfforts).toEqual(['low', 'medium', 'high', 'xhigh']);
|
||||
expect(model?.codexServiceTiers).toEqual(['fast']);
|
||||
expect(model?.presetMapping?.haiku).toBe('gpt-5.4-mini');
|
||||
}
|
||||
expect(codex55?.tier).toBe('paid');
|
||||
expect(codex55?.presetMapping?.haiku).toBe('gpt-5.4-mini');
|
||||
expect(codex55?.codexMaxEffort).toBe('xhigh');
|
||||
|
||||
Reference in new issue
Block a user