From 062e77e55f05b821ff8c6c2b0380a57b5d8594f2 Mon Sep 17 00:00:00 2001 From: "Kai (Tam Nhu) Tran" <61256810+kaitranntt@users.noreply.github.com> Date: Sat, 30 May 2026 14:56:32 -0400 Subject: [PATCH] fix(analytics): price Claude Opus 4.7 thinking --- src/web-server/model-pricing.ts | 6 ++++++ tests/unit/model-pricing.test.ts | 22 ++++++++++------------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/web-server/model-pricing.ts b/src/web-server/model-pricing.ts index 6d7a8bfa..a8f42fe0 100644 --- a/src/web-server/model-pricing.ts +++ b/src/web-server/model-pricing.ts @@ -243,6 +243,12 @@ const PRICING_REGISTRY: Record = { cacheCreationPerMillion: 6.25, cacheReadPerMillion: 0.5, }, + 'claude-opus-4-7-thinking': { + inputPerMillion: 5.0, + outputPerMillion: 25.0, + cacheCreationPerMillion: 6.25, + cacheReadPerMillion: 0.5, + }, // --------------------------------------------------------------------------- // OpenAI Models - Source: better-ccusage diff --git a/tests/unit/model-pricing.test.ts b/tests/unit/model-pricing.test.ts index 9e6eca84..a6951211 100644 --- a/tests/unit/model-pricing.test.ts +++ b/tests/unit/model-pricing.test.ts @@ -256,14 +256,14 @@ describe('model-pricing', () => { expect(cost).toBe(36.75); // 5 + 25 + 6.25 + 0.5 }); - it('should calculate Claude Opus 4.7 cache cost consistently across repeat lookups', () => { + it('should calculate Claude Opus 4.7 thinking cost including cache token rates', () => { const usage: TokenUsage = { inputTokens: 1_000_000, outputTokens: 1_000_000, cacheCreationTokens: 1_000_000, cacheReadTokens: 1_000_000, }; - const cost = calculateCost(usage, 'claude-opus-4-7'); + const cost = calculateCost(usage, 'claude-opus-4-7-thinking'); expect(cost).toBe(36.75); // 5 + 25 + 6.25 + 0.5 }); }); @@ -469,17 +469,15 @@ describe('model-pricing', () => { }); it('gracefully ignores malformed cached model entries', () => { - setCachedModelsDevRegistry( - { - openai: { - id: 'openai', - models: { - 'null-entry': null, - 'gpt-5.5': { id: 'gpt-5.5', cost: { input: 5, output: 30 } }, - }, + setCachedModelsDevRegistry({ + openai: { + id: 'openai', + models: { + 'null-entry': null, + 'gpt-5.5': { id: 'gpt-5.5', cost: { input: 5, output: 30 } }, }, - } as unknown as Parameters[0] - ); + }, + } as unknown as Parameters[0]); expect(() => getModelPricing('openai/gpt-5.5')).not.toThrow(); expect(getModelPricing('openai/gpt-5.5').inputPerMillion).toBe(5);