feat: support claude opus 5

This commit is contained in:
Kenneth Wong committed 2026-07-27 15:07:26 +08:00
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);
});
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', () => {
const { MODEL_CATALOG } = modelCatalog;
const ids = MODEL_CATALOG.claude.models.map((m) => m.id);
+17
View File
@@ -499,6 +499,23 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
},
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',
name: 'Claude Opus 4.8',
+22
View File
@@ -331,6 +331,28 @@ const PRICING_REGISTRY: Record<string, ModelPricing> = {
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': {
inputPerMillion: 10.0,
+17 -1
View File
@@ -285,10 +285,26 @@ describe('model-pricing', () => {
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', () => {
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);
});
});
+12
View File
@@ -982,6 +982,18 @@ export const MODEL_CATALOGS: Record<string, ProviderCatalog> = {
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',
name: 'Claude Opus 4.8',