mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-14 16:17:02 +00:00
feat(pricing): support per-service-tier rates; wire Opus fast mode
Extend `ModelPricing` with an optional `serviceTiers` map keyed by
Anthropic's `service_tier` request parameter. `getModelPricing(model,
{ serviceTier })` returns the matching tier rates when present and
transparently falls through to base rates otherwise — existing call
sites keep current behavior.
Registry entries added (per Anthropic Fast mode pricing docs):
- claude-opus-4-8 fast: $10/$50 input/output (2x premium)
- claude-opus-4-7 fast: $30/$150 (6x premium)
- claude-opus-4-6 fast: $30/$150 (6x premium)
Cache rates derived from the documented Prompt caching multipliers
(1.25x for 5-min cache write, 0.1x for cache read).
Note: tier tracking through CliproxyRequestDetail is not wired yet —
that's a follow-up so usage transformers can pass `serviceTier` when
Anthropic returns it on the response. Schema is in place; integration
can land independently.
Also adds a defensive `claude-opus-4-8-20260530` pricing test to exercise
`stripDateSuffix` even though Anthropic no longer issues date-stamped IDs
for the 4.6+ generation (addresses presto-review suggestion #1).
Built [OnSteroids](https://onsteroids.ai)
This commit is contained in:
1 parent
357ce8b07a
commit
878775f5b6
2 files changed
+113
-5
No files matched your search
@@ -176,6 +176,46 @@ describe('model-pricing', () => {
|
||||
expect(opus48.cacheReadPerMillion).toBe(0.5);
|
||||
});
|
||||
|
||||
it('should match date-stamped Claude Opus 4.8 to correct pricing', () => {
|
||||
// Anthropic stopped issuing date-stamped Opus IDs starting with the 4.6
|
||||
// generation, so this is a defensive guard for stripDateSuffix in case
|
||||
// a third-party emits a synthesized dated alias.
|
||||
const opus48dated = getModelPricing('claude-opus-4-8-20260530');
|
||||
expect(opus48dated.inputPerMillion).toBe(5.0);
|
||||
expect(opus48dated.outputPerMillion).toBe(25.0);
|
||||
});
|
||||
|
||||
it('should return fast-tier pricing for Claude Opus 4.8 when serviceTier=fast', () => {
|
||||
// Anthropic's "fast mode" charges 2x for Opus 4.8 ($10/$50 vs $5/$25).
|
||||
// Cache rates scale by the same standard multipliers (1.25x write, 0.1x read).
|
||||
const opus48fast = getModelPricing('claude-opus-4-8', { serviceTier: 'fast' });
|
||||
expect(opus48fast.inputPerMillion).toBe(10.0);
|
||||
expect(opus48fast.outputPerMillion).toBe(50.0);
|
||||
expect(opus48fast.cacheCreationPerMillion).toBe(12.5);
|
||||
expect(opus48fast.cacheReadPerMillion).toBe(1.0);
|
||||
});
|
||||
|
||||
it('should return fast-tier pricing for Claude Opus 4.7 when serviceTier=fast', () => {
|
||||
// Fast mode on 4.7 carries a 6x premium ($30/$150 per Anthropic docs).
|
||||
const opus47fast = getModelPricing('claude-opus-4-7', { serviceTier: 'fast' });
|
||||
expect(opus47fast.inputPerMillion).toBe(30.0);
|
||||
expect(opus47fast.outputPerMillion).toBe(150.0);
|
||||
});
|
||||
|
||||
it('should fall back to standard rates when serviceTier is unknown', () => {
|
||||
// Unknown tier names must not throw; revert to base pricing transparently.
|
||||
const opus48 = getModelPricing('claude-opus-4-8', { serviceTier: 'enterprise-mythos' });
|
||||
expect(opus48.inputPerMillion).toBe(5.0);
|
||||
expect(opus48.outputPerMillion).toBe(25.0);
|
||||
});
|
||||
|
||||
it('should preserve standard rates for Opus 4.8 when serviceTier omitted', () => {
|
||||
// Regression guard: existing callers must keep current behavior.
|
||||
const opus48 = getModelPricing('claude-opus-4-8');
|
||||
expect(opus48.inputPerMillion).toBe(5.0);
|
||||
expect(opus48.outputPerMillion).toBe(25.0);
|
||||
});
|
||||
|
||||
it('should not map unknown future model families onto known family pricing', () => {
|
||||
const fallback = getModelPricing('unknown-model-xyz');
|
||||
|
||||
@@ -285,6 +325,17 @@ describe('model-pricing', () => {
|
||||
const cost = calculateCost(usage, 'claude-opus-4-8');
|
||||
expect(cost).toBe(36.75); // 5 + 25 + 6.25 + 0.5
|
||||
});
|
||||
|
||||
it('should calculate fast-tier Claude Opus 4.8 cost (2x premium)', () => {
|
||||
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-8', { serviceTier: 'fast' });
|
||||
expect(cost).toBe(73.5); // 10 + 50 + 12.5 + 1.0
|
||||
});
|
||||
});
|
||||
|
||||
describe('getKnownModels', () => {
|
||||
|
||||
Reference in new issue
Block a user