Merge pull request #1631 from sgaluza/sergey/add-claude-sonnet-5-pricing

feat(pricing): register Claude Sonnet 5 in the pricing registry
This commit is contained in:
Kai (Tam Nhu) Tran authored and GitHub committed 2026-07-08 10:18:03 -04:00
commit 5afd294c7e
2 files changed
+49

No files matched your search

+15
View File
@@ -216,6 +216,21 @@ const PRICING_REGISTRY: Record<string, ModelPricing> = {
cacheCreationPerMillion: 3.75,
cacheReadPerMillion: 0.3,
},
// Claude Sonnet 5 ($3/$15) — latest Sonnet; shares the standard Sonnet rates.
// Registered explicitly so it is a known model rather than relying on the
// unknown-model fallback that coincidentally matches these rates.
'claude-sonnet-5': {
inputPerMillion: 3.0,
outputPerMillion: 15.0,
cacheCreationPerMillion: 3.75,
cacheReadPerMillion: 0.3,
},
'claude-sonnet-5-thinking': {
inputPerMillion: 3.0,
outputPerMillion: 15.0,
cacheCreationPerMillion: 3.75,
cacheReadPerMillion: 0.3,
},
// Claude 4 Opus ($15/$75)
'claude-4-opus-20250514': {
inputPerMillion: 15.0,
+34
View File
@@ -277,6 +277,14 @@ describe('model-pricing', () => {
expect(fable5.cacheReadPerMillion).toBe(1.0);
});
it('should return correct pricing for Claude Sonnet 5', () => {
const sonnet5 = getModelPricing('claude-sonnet-5');
expect(sonnet5.inputPerMillion).toBe(3.0);
expect(sonnet5.outputPerMillion).toBe(15.0);
expect(sonnet5.cacheCreationPerMillion).toBe(3.75);
expect(sonnet5.cacheReadPerMillion).toBe(0.3);
});
it('should not map unknown future model families onto known family pricing', () => {
const fallback = getModelPricing('unknown-model-xyz');
@@ -398,6 +406,17 @@ describe('model-pricing', () => {
expect(cost).toBe(73.5); // 10 + 50 + 12.5 + 1.0
});
it('should calculate Claude Sonnet 5 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-sonnet-5');
expect(cost).toBe(22.05); // 3 + 15 + 3.75 + 0.3
});
it('should calculate fast-tier Claude Opus 4.8 cost (2x premium)', () => {
const usage: TokenUsage = {
inputTokens: 1_000_000,
@@ -426,6 +445,13 @@ describe('model-pricing', () => {
const models = getKnownModels();
expect(models.some((m) => m.startsWith('glm-'))).toBe(true);
});
it('should include Claude Sonnet 5 as an explicitly registered model', () => {
// Sonnet 5 must be a first-class known model rather than relying on the
// unknown-model fallback that happens to share Sonnet's $3/$15 rates.
const models = getKnownModels();
expect(models).toContain('claude-sonnet-5');
});
});
describe('hasCustomPricing', () => {
@@ -434,6 +460,14 @@ describe('model-pricing', () => {
expect(hasCustomPricing('glm-4.6')).toBe(true);
});
it('should treat Claude Sonnet 5 as a known model with explicit pricing', () => {
// Without an explicit registry entry Sonnet 5 falls through to
// UNKNOWN_MODEL_PRICING (which coincidentally matches Sonnet rates);
// register it so cost accounting is intentional, not accidental.
expect(hasCustomPricing('claude-sonnet-5')).toBe(true);
expect(hasCustomPricing('claude-sonnet-5-thinking')).toBe(true);
});
it('should return true for deterministic qwen3-coder alias', () => {
expect(hasCustomPricing('qwen3-coder')).toBe(true);
});