From 09aeec57633828f9225591e090d8f442abc9d322 Mon Sep 17 00:00:00 2001 From: Brian Le Date: Wed, 4 Mar 2026 01:18:43 -0500 Subject: [PATCH 1/4] fix(config): update claude base models to latest - ANTHROPIC_MODEL: claude-sonnet-4-5-20250929 -> claude-sonnet-4-6 - ANTHROPIC_DEFAULT_SONNET_MODEL: claude-sonnet-4-5-20250929 -> claude-sonnet-4-6 - ANTHROPIC_DEFAULT_OPUS_MODEL: claude-opus-4-5-20251101 -> claude-opus-4-6 - ANTHROPIC_DEFAULT_HAIKU_MODEL: unchanged (claude-haiku-4-5-20251001, still latest) --- config/base-claude.settings.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/base-claude.settings.json b/config/base-claude.settings.json index ec3525f4..c8b703c9 100644 --- a/config/base-claude.settings.json +++ b/config/base-claude.settings.json @@ -2,9 +2,9 @@ "env": { "ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/claude", "ANTHROPIC_AUTH_TOKEN": "ccs-internal-managed", - "ANTHROPIC_MODEL": "claude-sonnet-4-5-20250929", - "ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-5-20251101", - "ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4-5-20250929", + "ANTHROPIC_MODEL": "claude-sonnet-4-6", + "ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-6", + "ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4-6", "ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4-5-20251001" } } From 3d183fe0e891886bbd51a3c5b30b301e966cce03 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Sat, 7 Mar 2026 15:35:12 +0700 Subject: [PATCH 2/4] fix(cliproxy): sync claude 4.6 selector defaults --- src/cliproxy/model-catalog.ts | 15 ++++++++++++++- tests/unit/cliproxy/model-catalog.test.js | 21 +++++++++++++++++++++ ui/src/lib/model-catalogs.ts | 16 ++++++++++++++-- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/cliproxy/model-catalog.ts b/src/cliproxy/model-catalog.ts index 5300ef8d..8194e640 100644 --- a/src/cliproxy/model-catalog.ts +++ b/src/cliproxy/model-catalog.ts @@ -223,7 +223,7 @@ export const MODEL_CATALOG: Partial> = claude: { provider: 'claude', displayName: 'Claude (Anthropic)', - defaultModel: 'claude-sonnet-4-5-20250929', + defaultModel: 'claude-sonnet-4-6', models: [ { id: 'claude-opus-4-6', @@ -238,6 +238,19 @@ export const MODEL_CATALOG: Partial> = }, extendedContext: true, }, + { + id: 'claude-sonnet-4-6', + name: 'Claude Sonnet 4.6', + description: 'Balanced performance and speed', + thinking: { + type: 'budget', + min: 1024, + max: 128000, + zeroAllowed: false, + dynamicAllowed: true, + }, + extendedContext: true, + }, { id: 'claude-opus-4-5-20251101', name: 'Claude Opus 4.5', diff --git a/tests/unit/cliproxy/model-catalog.test.js b/tests/unit/cliproxy/model-catalog.test.js index 87acb22a..ee9f5040 100644 --- a/tests/unit/cliproxy/model-catalog.test.js +++ b/tests/unit/cliproxy/model-catalog.test.js @@ -106,6 +106,27 @@ describe('Model Catalog', () => { }); }); + describe('Claude models', () => { + it('contains Claude provider catalog', () => { + const { MODEL_CATALOG } = modelCatalog; + assert(MODEL_CATALOG.claude, 'Should have Claude provider'); + assert.strictEqual(MODEL_CATALOG.claude.provider, 'claude'); + assert.strictEqual(MODEL_CATALOG.claude.displayName, 'Claude (Anthropic)'); + }); + + it('has correct default model', () => { + const { MODEL_CATALOG } = modelCatalog; + assert.strictEqual(MODEL_CATALOG.claude.defaultModel, 'claude-sonnet-4-6'); + }); + + it('includes Claude Sonnet 4.6', () => { + const { MODEL_CATALOG } = modelCatalog; + const sonnet = MODEL_CATALOG.claude.models.find((m) => m.id === 'claude-sonnet-4-6'); + assert(sonnet, 'Should include Claude Sonnet 4.6'); + assert.strictEqual(sonnet.name, 'Claude Sonnet 4.6'); + }); + }); + describe('Gemini models', () => { it('has correct default model', () => { const { MODEL_CATALOG } = modelCatalog; diff --git a/ui/src/lib/model-catalogs.ts b/ui/src/lib/model-catalogs.ts index 016d0564..0832c111 100644 --- a/ui/src/lib/model-catalogs.ts +++ b/ui/src/lib/model-catalogs.ts @@ -441,7 +441,7 @@ export const MODEL_CATALOGS: Record = { claude: { provider: 'claude', displayName: 'Claude (Anthropic)', - defaultModel: 'claude-sonnet-4-5-20250929', + defaultModel: 'claude-sonnet-4-6', models: [ { id: 'claude-opus-4-6', @@ -451,7 +451,19 @@ export const MODEL_CATALOGS: Record = { presetMapping: { default: 'claude-opus-4-6', opus: 'claude-opus-4-6', - sonnet: 'claude-sonnet-4-5-20250929', + sonnet: 'claude-sonnet-4-6', + haiku: 'claude-haiku-4-5-20251001', + }, + }, + { + id: 'claude-sonnet-4-6', + name: 'Claude Sonnet 4.6', + description: 'Balanced performance and speed', + extendedContext: true, + presetMapping: { + default: 'claude-sonnet-4-6', + opus: 'claude-opus-4-6', + sonnet: 'claude-sonnet-4-6', haiku: 'claude-haiku-4-5-20251001', }, }, From bea3084d5e4f7bc691503cffee8a235f94c3b87d Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Sat, 7 Mar 2026 15:40:29 +0700 Subject: [PATCH 3/4] fix(config): align claude defaults across catalogs --- src/commands/api-command.ts | 2 +- tests/unit/cliproxy/model-catalog.test.js | 8 +++- ui/src/components/profiles/profile-dialog.tsx | 2 +- ui/src/lib/preset-utils.ts | 10 ++--- ui/tests/unit/ui/lib/preset-utils.test.ts | 44 +++++++++++++++++++ 5 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 ui/tests/unit/ui/lib/preset-utils.test.ts diff --git a/src/commands/api-command.ts b/src/commands/api-command.ts index f44f6f49..4d1aae68 100644 --- a/src/commands/api-command.ts +++ b/src/commands/api-command.ts @@ -350,7 +350,7 @@ async function handleCreate(args: string[]): Promise { } // Step 4: Model configuration (use preset default if available) - const defaultModel = preset?.defaultModel || 'claude-sonnet-4-5-20250929'; + const defaultModel = preset?.defaultModel || 'claude-sonnet-4-6'; let model = parsedArgs.model || openRouterModel || preset?.defaultModel; if (!model && !parsedArgs.yes && !preset) { model = await InteractivePrompt.input('Default model (ANTHROPIC_MODEL)', { diff --git a/tests/unit/cliproxy/model-catalog.test.js b/tests/unit/cliproxy/model-catalog.test.js index ee9f5040..0b2b47f2 100644 --- a/tests/unit/cliproxy/model-catalog.test.js +++ b/tests/unit/cliproxy/model-catalog.test.js @@ -113,7 +113,6 @@ describe('Model Catalog', () => { assert.strictEqual(MODEL_CATALOG.claude.provider, 'claude'); assert.strictEqual(MODEL_CATALOG.claude.displayName, 'Claude (Anthropic)'); }); - it('has correct default model', () => { const { MODEL_CATALOG } = modelCatalog; assert.strictEqual(MODEL_CATALOG.claude.defaultModel, 'claude-sonnet-4-6'); @@ -125,6 +124,13 @@ describe('Model Catalog', () => { assert(sonnet, 'Should include Claude Sonnet 4.6'); assert.strictEqual(sonnet.name, 'Claude Sonnet 4.6'); }); + + it('retains previous 4.5 snapshot models for explicit selection', () => { + const { MODEL_CATALOG } = modelCatalog; + const ids = MODEL_CATALOG.claude.models.map((m) => m.id); + assert(ids.includes('claude-opus-4-5-20251101')); + assert(ids.includes('claude-sonnet-4-5-20250929')); + }); }); describe('Gemini models', () => { diff --git a/ui/src/components/profiles/profile-dialog.tsx b/ui/src/components/profiles/profile-dialog.tsx index b6873580..f880a6e4 100644 --- a/ui/src/components/profiles/profile-dialog.tsx +++ b/ui/src/components/profiles/profile-dialog.tsx @@ -18,7 +18,7 @@ import type { Profile } from '@/lib/api-client'; import { ChevronDown, ChevronRight } from 'lucide-react'; import { useTranslation } from 'react-i18next'; -const DEFAULT_MODEL = 'claude-sonnet-4-5-20250929'; +const DEFAULT_MODEL = 'claude-sonnet-4-6'; const schema = z.object({ name: z diff --git a/ui/src/lib/preset-utils.ts b/ui/src/lib/preset-utils.ts index 1121d5ab..dec9ba6a 100644 --- a/ui/src/lib/preset-utils.ts +++ b/ui/src/lib/preset-utils.ts @@ -27,7 +27,7 @@ async function fetchEffectiveApiKey(): Promise { /** * Apply default preset for a provider to its settings - * Uses the first model's presetMapping or falls back to using defaultModel for all tiers + * Uses the catalog default model's preset mapping or falls back to using defaultModel for all tiers * * @param provider - The provider ID (e.g., 'gemini', 'codex', 'agy') * @param port - Optional custom port (defaults to CLIPROXY_DEFAULT_PORT) @@ -40,9 +40,9 @@ export async function applyDefaultPreset( const catalog = MODEL_CATALOGS[provider]; if (!catalog) return { success: false }; - // Get the first (recommended) model's preset mapping - const firstModel = catalog.models[0]; - const mapping = firstModel?.presetMapping || { + const defaultModelEntry = + catalog.models.find((model) => model.id === catalog.defaultModel) || catalog.models[0]; + const mapping = defaultModelEntry?.presetMapping || { default: catalog.defaultModel, opus: catalog.defaultModel, sonnet: catalog.defaultModel, @@ -72,7 +72,7 @@ export async function applyDefaultPreset( }); return { success: res.ok, - presetName: firstModel?.name || catalog.defaultModel, + presetName: defaultModelEntry?.name || catalog.defaultModel, }; } catch { return { success: false }; diff --git a/ui/tests/unit/ui/lib/preset-utils.test.ts b/ui/tests/unit/ui/lib/preset-utils.test.ts new file mode 100644 index 00000000..460c1e1f --- /dev/null +++ b/ui/tests/unit/ui/lib/preset-utils.test.ts @@ -0,0 +1,44 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; + +import { MODEL_CATALOGS } from '@/lib/model-catalogs'; +import { applyDefaultPreset } from '@/lib/preset-utils'; + +describe('claude preset utils', () => { + afterEach(() => { + vi.unstubAllGlobals(); + vi.restoreAllMocks(); + }); + + it('keeps the claude catalog default on Sonnet 4.6', () => { + const claudeCatalog = MODEL_CATALOGS.claude; + + expect(claudeCatalog.defaultModel).toBe('claude-sonnet-4-6'); + expect(claudeCatalog.models.map((model) => model.id)).toContain('claude-sonnet-4-6'); + }); + + it('applies the default claude preset from the catalog default model mapping', async () => { + const fetchMock = vi + .fn() + .mockResolvedValueOnce({ + ok: true, + json: async () => ({ apiKey: { value: 'managed-key' } }), + }) + .mockResolvedValueOnce({ ok: true }); + + vi.stubGlobal('fetch', fetchMock); + + const result = await applyDefaultPreset('claude'); + + expect(result).toEqual({ success: true, presetName: 'Claude Sonnet 4.6' }); + + const [, requestInit] = fetchMock.mock.calls[1] ?? []; + const body = JSON.parse(String(requestInit?.body)); + + expect(body.settings.env).toMatchObject({ + ANTHROPIC_MODEL: 'claude-sonnet-4-6', + ANTHROPIC_DEFAULT_OPUS_MODEL: 'claude-opus-4-6', + ANTHROPIC_DEFAULT_SONNET_MODEL: 'claude-sonnet-4-6', + ANTHROPIC_DEFAULT_HAIKU_MODEL: 'claude-haiku-4-5-20251001', + }); + }); +}); From 4d0ded339f12abb4fec1c8596fac07c67581351f Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Sat, 7 Mar 2026 15:43:44 +0700 Subject: [PATCH 4/4] fix(ui): update copilot default claude model --- .../components/copilot/config-form/use-copilot-config-form.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/copilot/config-form/use-copilot-config-form.ts b/ui/src/components/copilot/config-form/use-copilot-config-form.ts index e507d8a4..461c5688 100644 --- a/ui/src/components/copilot/config-form/use-copilot-config-form.ts +++ b/ui/src/components/copilot/config-form/use-copilot-config-form.ts @@ -56,7 +56,7 @@ export function useCopilotConfigForm() { const autoStart = localOverrides.autoStart ?? config?.auto_start ?? false; const port = localOverrides.port ?? config?.port ?? 4141; const accountType = localOverrides.accountType ?? config?.account_type ?? 'individual'; - const currentModel = localOverrides.model ?? config?.model ?? 'claude-sonnet-4-5-20250929'; + const currentModel = localOverrides.model ?? config?.model ?? 'claude-sonnet-4-6'; const rateLimit = localOverrides.rateLimit ?? config?.rate_limit?.toString() ?? ''; const waitOnLimit = localOverrides.waitOnLimit ?? config?.wait_on_limit ?? true; const opusModel = localOverrides.opusModel ?? config?.opus_model ?? '';