mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 14:15:56 +00:00
feat: support claude opus 5
This commit is contained in:
1 parent
2043c65de7
commit
ee90dd2640
5 files changed
+84
-1
No files matched your search
@@ -236,6 +236,22 @@ describe('Model Catalog', () => {
|
|||||||
assert.strictEqual(fable5.extendedContext, true);
|
assert.strictEqual(fable5.extendedContext, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('includes Claude Opus 5 with adaptive levels and extended context', () => {
|
||||||
|
const { MODEL_CATALOG } = modelCatalog;
|
||||||
|
const opus5 = MODEL_CATALOG.claude.models.find((m) => m.id === 'claude-opus-5');
|
||||||
|
assert(opus5, 'Should include Claude Opus 5');
|
||||||
|
assert.strictEqual(opus5.name, 'Claude Opus 5');
|
||||||
|
// Opus 5 requires adaptive thinking (type: 'levels') like Sonnet 5 and Opus 4.8;
|
||||||
|
// manual budget_tokens is rejected with 400. Proxy reports zero + dynamic allowed.
|
||||||
|
assert.strictEqual(opus5.thinking.type, 'levels');
|
||||||
|
assert.deepStrictEqual(opus5.thinking.levels, ['low', 'medium', 'high', 'xhigh', 'max']);
|
||||||
|
assert.strictEqual(opus5.thinking.maxLevel, 'max');
|
||||||
|
assert.strictEqual(opus5.thinking.zeroAllowed, true);
|
||||||
|
assert.strictEqual(opus5.thinking.dynamicAllowed, true);
|
||||||
|
assert.strictEqual(opus5.nativeImageInput, true);
|
||||||
|
assert.strictEqual(opus5.extendedContext, true);
|
||||||
|
});
|
||||||
|
|
||||||
it('retains previous 4.5 snapshot models for explicit selection', () => {
|
it('retains previous 4.5 snapshot models for explicit selection', () => {
|
||||||
const { MODEL_CATALOG } = modelCatalog;
|
const { MODEL_CATALOG } = modelCatalog;
|
||||||
const ids = MODEL_CATALOG.claude.models.map((m) => m.id);
|
const ids = MODEL_CATALOG.claude.models.map((m) => m.id);
|
||||||
|
|||||||
@@ -499,6 +499,23 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
|
|||||||
},
|
},
|
||||||
extendedContext: true,
|
extendedContext: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'claude-opus-5',
|
||||||
|
name: 'Claude Opus 5',
|
||||||
|
description: 'Latest premium model',
|
||||||
|
nativeImageInput: true,
|
||||||
|
// Opus 5 (released 2026-07-14) uses adaptive thinking, matching Sonnet 5
|
||||||
|
// and Opus 4.8: Anthropic accepts only effort levels; manual budget_tokens
|
||||||
|
// is rejected with 400. Proxy metadata reports zero + dynamic allowed.
|
||||||
|
thinking: {
|
||||||
|
type: 'levels',
|
||||||
|
levels: ['low', 'medium', 'high', 'xhigh', 'max'],
|
||||||
|
maxLevel: 'max',
|
||||||
|
zeroAllowed: true,
|
||||||
|
dynamicAllowed: true,
|
||||||
|
},
|
||||||
|
extendedContext: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'claude-opus-4-8',
|
id: 'claude-opus-4-8',
|
||||||
name: 'Claude Opus 4.8',
|
name: 'Claude Opus 4.8',
|
||||||
|
|||||||
@@ -331,6 +331,28 @@ const PRICING_REGISTRY: Record<string, ModelPricing> = {
|
|||||||
fast: OPUS_48_FAST_RATES,
|
fast: OPUS_48_FAST_RATES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// Claude Opus 5 ($5/$25) — Claude 5 generation Opus (released 2026-07-14).
|
||||||
|
// Rates mirror Opus 4.8 (same Opus tier); fast mode reuses the 2x premium
|
||||||
|
// pending official Opus 5 numbers. Registered explicitly so it resolves to
|
||||||
|
// Opus-tier pricing instead of the unknown-model fallback.
|
||||||
|
'claude-opus-5': {
|
||||||
|
inputPerMillion: 5.0,
|
||||||
|
outputPerMillion: 25.0,
|
||||||
|
cacheCreationPerMillion: 6.25,
|
||||||
|
cacheReadPerMillion: 0.5,
|
||||||
|
serviceTiers: {
|
||||||
|
fast: OPUS_48_FAST_RATES,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'claude-opus-5-thinking': {
|
||||||
|
inputPerMillion: 5.0,
|
||||||
|
outputPerMillion: 25.0,
|
||||||
|
cacheCreationPerMillion: 6.25,
|
||||||
|
cacheReadPerMillion: 0.5,
|
||||||
|
serviceTiers: {
|
||||||
|
fast: OPUS_48_FAST_RATES,
|
||||||
|
},
|
||||||
|
},
|
||||||
// Claude Fable 5 ($10/$50) — most powerful tier, above Opus
|
// Claude Fable 5 ($10/$50) — most powerful tier, above Opus
|
||||||
'claude-fable-5': {
|
'claude-fable-5': {
|
||||||
inputPerMillion: 10.0,
|
inputPerMillion: 10.0,
|
||||||
|
|||||||
@@ -285,10 +285,26 @@ describe('model-pricing', () => {
|
|||||||
expect(sonnet5.cacheReadPerMillion).toBe(0.3);
|
expect(sonnet5.cacheReadPerMillion).toBe(0.3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return Opus-tier pricing for Claude Opus 5', () => {
|
||||||
|
// Opus 5 mirrors Opus 4.8 rates; date-stamped ids resolve via stripDateSuffix.
|
||||||
|
const opus5 = getModelPricing('claude-opus-5');
|
||||||
|
expect(opus5.inputPerMillion).toBe(5.0);
|
||||||
|
expect(opus5.outputPerMillion).toBe(25.0);
|
||||||
|
expect(opus5.cacheCreationPerMillion).toBe(6.25);
|
||||||
|
expect(opus5.cacheReadPerMillion).toBe(0.5);
|
||||||
|
expect(getModelPricing('claude-opus-5-20270101').inputPerMillion).toBe(5.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should apply fast-tier pricing for Claude Opus 5', () => {
|
||||||
|
const opus5fast = getModelPricing('claude-opus-5', { serviceTier: 'fast' });
|
||||||
|
expect(opus5fast.inputPerMillion).toBe(10.0);
|
||||||
|
expect(opus5fast.outputPerMillion).toBe(50.0);
|
||||||
|
});
|
||||||
|
|
||||||
it('should not map unknown future model families onto known family pricing', () => {
|
it('should not map unknown future model families onto known family pricing', () => {
|
||||||
const fallback = getModelPricing('unknown-model-xyz');
|
const fallback = getModelPricing('unknown-model-xyz');
|
||||||
|
|
||||||
expect(getModelPricing('claude-opus-5-20270101')).toEqual(fallback);
|
expect(getModelPricing('claude-opus-6-20270101')).toEqual(fallback);
|
||||||
expect(getModelPricing('gemini-3.2-pro')).toEqual(fallback);
|
expect(getModelPricing('gemini-3.2-pro')).toEqual(fallback);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -982,6 +982,18 @@ export const MODEL_CATALOGS: Record<string, ProviderCatalog> = {
|
|||||||
haiku: 'claude-haiku-4-5-20251001',
|
haiku: 'claude-haiku-4-5-20251001',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'claude-opus-5',
|
||||||
|
name: 'Claude Opus 5',
|
||||||
|
description: 'Latest premium model',
|
||||||
|
extendedContext: true,
|
||||||
|
presetMapping: {
|
||||||
|
default: 'claude-opus-5',
|
||||||
|
opus: 'claude-opus-5',
|
||||||
|
sonnet: 'claude-sonnet-5',
|
||||||
|
haiku: 'claude-haiku-4-5-20251001',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'claude-opus-4-8',
|
id: 'claude-opus-4-8',
|
||||||
name: 'Claude Opus 4.8',
|
name: 'Claude Opus 4.8',
|
||||||
|
|||||||
Reference in new issue
Block a user