mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-20 02:17:05 +00:00
Merge pull request #682 from 0xble/fix/claude-base-models
fix(config): update claude base models to latest
This commit is contained in:
9 files changed
+110
-14
No files matched your search
@@ -2,9 +2,9 @@
|
|||||||
"env": {
|
"env": {
|
||||||
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/claude",
|
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/claude",
|
||||||
"ANTHROPIC_AUTH_TOKEN": "ccs-internal-managed",
|
"ANTHROPIC_AUTH_TOKEN": "ccs-internal-managed",
|
||||||
"ANTHROPIC_MODEL": "claude-sonnet-4-5-20250929",
|
"ANTHROPIC_MODEL": "claude-sonnet-4-6",
|
||||||
"ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-5-20251101",
|
"ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-6",
|
||||||
"ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4-5-20250929",
|
"ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4-6",
|
||||||
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4-5-20251001"
|
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4-5-20251001"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +223,7 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
|
|||||||
claude: {
|
claude: {
|
||||||
provider: 'claude',
|
provider: 'claude',
|
||||||
displayName: 'Claude (Anthropic)',
|
displayName: 'Claude (Anthropic)',
|
||||||
defaultModel: 'claude-sonnet-4-5-20250929',
|
defaultModel: 'claude-sonnet-4-6',
|
||||||
models: [
|
models: [
|
||||||
{
|
{
|
||||||
id: 'claude-opus-4-6',
|
id: 'claude-opus-4-6',
|
||||||
@@ -238,6 +238,19 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
|
|||||||
},
|
},
|
||||||
extendedContext: true,
|
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',
|
id: 'claude-opus-4-5-20251101',
|
||||||
name: 'Claude Opus 4.5',
|
name: 'Claude Opus 4.5',
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ async function handleCreate(args: string[]): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Step 4: Model configuration (use preset default if available)
|
// 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;
|
let model = parsedArgs.model || openRouterModel || preset?.defaultModel;
|
||||||
if (!model && !parsedArgs.yes && !preset) {
|
if (!model && !parsedArgs.yes && !preset) {
|
||||||
model = await InteractivePrompt.input('Default model (ANTHROPIC_MODEL)', {
|
model = await InteractivePrompt.input('Default model (ANTHROPIC_MODEL)', {
|
||||||
|
|||||||
@@ -106,6 +106,33 @@ 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');
|
||||||
|
});
|
||||||
|
|
||||||
|
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', () => {
|
describe('Gemini models', () => {
|
||||||
it('has correct default model', () => {
|
it('has correct default model', () => {
|
||||||
const { MODEL_CATALOG } = modelCatalog;
|
const { MODEL_CATALOG } = modelCatalog;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export function useCopilotConfigForm() {
|
|||||||
const autoStart = localOverrides.autoStart ?? config?.auto_start ?? false;
|
const autoStart = localOverrides.autoStart ?? config?.auto_start ?? false;
|
||||||
const port = localOverrides.port ?? config?.port ?? 4141;
|
const port = localOverrides.port ?? config?.port ?? 4141;
|
||||||
const accountType = localOverrides.accountType ?? config?.account_type ?? 'individual';
|
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 rateLimit = localOverrides.rateLimit ?? config?.rate_limit?.toString() ?? '';
|
||||||
const waitOnLimit = localOverrides.waitOnLimit ?? config?.wait_on_limit ?? true;
|
const waitOnLimit = localOverrides.waitOnLimit ?? config?.wait_on_limit ?? true;
|
||||||
const opusModel = localOverrides.opusModel ?? config?.opus_model ?? '';
|
const opusModel = localOverrides.opusModel ?? config?.opus_model ?? '';
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import type { Profile } from '@/lib/api-client';
|
|||||||
import { ChevronDown, ChevronRight } from 'lucide-react';
|
import { ChevronDown, ChevronRight } from 'lucide-react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const DEFAULT_MODEL = 'claude-sonnet-4-5-20250929';
|
const DEFAULT_MODEL = 'claude-sonnet-4-6';
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
name: z
|
name: z
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ export const MODEL_CATALOGS: Record<string, ProviderCatalog> = {
|
|||||||
claude: {
|
claude: {
|
||||||
provider: 'claude',
|
provider: 'claude',
|
||||||
displayName: 'Claude (Anthropic)',
|
displayName: 'Claude (Anthropic)',
|
||||||
defaultModel: 'claude-sonnet-4-5-20250929',
|
defaultModel: 'claude-sonnet-4-6',
|
||||||
models: [
|
models: [
|
||||||
{
|
{
|
||||||
id: 'claude-opus-4-6',
|
id: 'claude-opus-4-6',
|
||||||
@@ -451,7 +451,19 @@ export const MODEL_CATALOGS: Record<string, ProviderCatalog> = {
|
|||||||
presetMapping: {
|
presetMapping: {
|
||||||
default: 'claude-opus-4-6',
|
default: 'claude-opus-4-6',
|
||||||
opus: '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',
|
haiku: 'claude-haiku-4-5-20251001',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ async function fetchEffectiveApiKey(): Promise<string> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply default preset for a provider to its settings
|
* 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 provider - The provider ID (e.g., 'gemini', 'codex', 'agy')
|
||||||
* @param port - Optional custom port (defaults to CLIPROXY_DEFAULT_PORT)
|
* @param port - Optional custom port (defaults to CLIPROXY_DEFAULT_PORT)
|
||||||
@@ -40,9 +40,9 @@ export async function applyDefaultPreset(
|
|||||||
const catalog = MODEL_CATALOGS[provider];
|
const catalog = MODEL_CATALOGS[provider];
|
||||||
if (!catalog) return { success: false };
|
if (!catalog) return { success: false };
|
||||||
|
|
||||||
// Get the first (recommended) model's preset mapping
|
const defaultModelEntry =
|
||||||
const firstModel = catalog.models[0];
|
catalog.models.find((model) => model.id === catalog.defaultModel) || catalog.models[0];
|
||||||
const mapping = firstModel?.presetMapping || {
|
const mapping = defaultModelEntry?.presetMapping || {
|
||||||
default: catalog.defaultModel,
|
default: catalog.defaultModel,
|
||||||
opus: catalog.defaultModel,
|
opus: catalog.defaultModel,
|
||||||
sonnet: catalog.defaultModel,
|
sonnet: catalog.defaultModel,
|
||||||
@@ -72,7 +72,7 @@ export async function applyDefaultPreset(
|
|||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
success: res.ok,
|
success: res.ok,
|
||||||
presetName: firstModel?.name || catalog.defaultModel,
|
presetName: defaultModelEntry?.name || catalog.defaultModel,
|
||||||
};
|
};
|
||||||
} catch {
|
} catch {
|
||||||
return { success: false };
|
return { success: false };
|
||||||
|
|||||||
@@ -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',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user