Skip to content

fix(cost): warn on unpriced models; add Claude Opus 4.7/4.8/5, Sonnet 5, Fable 5/5.1 pricing - #5804

Open
arthi-arumugam-git wants to merge 1 commit into
Helicone:mainfrom
arthi-arumugam-git:fix/unknown-model-cost-warning-and-claude-5-pricing
Open

fix(cost): warn on unpriced models; add Claude Opus 4.7/4.8/5, Sonnet 5, Fable 5/5.1 pricing#5804
arthi-arumugam-git wants to merge 1 commit into
Helicone:mainfrom
arthi-arumugam-git:fix/unknown-model-cost-warning-and-claude-5-pricing

Conversation

@arthi-arumugam-git

Copy link
Copy Markdown

Ticket

None.

Component/Service

What part of Helicone does this affect?

  • Web (Frontend)
  • Jawn (Backend)
  • Worker (Proxy)
  • Bifrost (Marketing)
  • AI Gateway
  • Packages
  • Infrastructure/Docker
  • Documentation

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Performance improvement
  • Refactoring

Deployment Notes

  • No special deployment steps required
  • Database migrations need to run
  • Environment variable changes required
  • Coordination with other teams needed

Screenshots / Demos

Before After
claude-opus-4-8, 50,000 input + 15,000 output tokens: cost recorded as $0.00, token counts correct, nothing logged Same request: $0.625 (50,000 × $5/M + 15,000 × $25/M)
Any model absent from both pricing tables: null / 0, silently Still null / 0, plus one console.warn naming the provider and model

Extra Notes

Part 1: make an unpriced model loud

  • packages/cost/models/calculate-cost.ts: on a registry miss, console.warn with the providerModelId and provider before returning null (the return type is unchanged).
  • packages/cost/costCalc.ts: modelCost still returns 0 when costOfPrompt returns null, but now warns first. The warning is suppressed when the model registry has an entry for the same model and provider: Jawn calls modelCost on every non-gateway request before the registry path, and LoggingHandler prefers the registry result, so a legacy miss on a registry-priced model (for example gpt-5.4, which has no legacy row) is expected and would otherwise warn on every request.
  • No persisted values, schemas, or return types change. console.warn matches the existing logging in this package (unified/providers.ts).
  • One line per miss, not deduplicated; the fix for a noisy log is to add the missing pricing. The Worker's own legacy fallback (ProxyForwarder.ts, costOfPrompt(...) ?? 0) is not touched; it already goes through the registry warning first.

Part 2: Claude models missing from the registry

Added packages/cost/models/authors/anthropic/{claude-4.7-opus,claude-4.8-opus,claude-5-opus,claude-5-sonnet,claude-5-fable,claude-5.1-fable} (each with model.ts and endpoints.ts, mirroring claude-4.6-sonnet), wired into authors/anthropic/index.ts, plus equals rows in the legacy table packages/cost/providers/anthropic/index.ts.

Model API id Input 5m write 1h write Cache read Output
Claude Opus 4.7 claude-opus-4-7 $5 $6.25 $10 $0.50 $25
Claude Opus 4.8 claude-opus-4-8 $5 $6.25 $10 $0.50 $25
Claude Opus 5 claude-opus-5 $5 $6.25 $10 $0.50 $25
Claude Sonnet 5 claude-sonnet-5 $2 $2.50 $4 $0.20 $10
Claude Fable 5 claude-fable-5 $10 $12.50 $20 $1 $50
Claude Fable 5.1 claude-fable-5-1 $10 $12.50 $20 $0.25 $50

All per MTok. Multipliers are the standard 1.25x / 2x / 0.1x, except the Fable 5.1 cache read, which is 0.025x and set explicitly because the engine has no default for it. Context 1M, max output 128K, created set to each model's release date, all from the model pages listed below.

Choices a reviewer may want to change:

  • Only :anthropic endpoints are added. Bedrock, Vertex and OpenRouter rates are on other pages that I did not verify, and no pa/ Helicone endpoint is assumed to exist.
  • ptbEnabled: true matches every other :anthropic entry. Flip to false if pass-through billing should not be offered for these models yet.
  • supportedParameters and supportedPlugins mirror the 4.6 entries. The Sonnet 5 model page notes that non-default temperature/top_p/top_k return a 400 on that model; I left the informational list unchanged rather than guess at gateway behaviour.
  • Legacy rows use equals so that claude-fable-5 cannot match claude-fable-5-1, which has a different cache read rate.

Deliberately left out:

  • gpt-5.5 and Gemini 3.5/3.6/3.7 Flash, which are also missing from the registry; this PR only adds models whose full rate row I verified on Anthropic's pricing page.
  • Claude Mythos 5 / 5.1 (limited availability).
  • modelDetails entries, unified/models.ts playground mappings and the Stripe meter list; none of them affect cost calculation.

Tests

  • packages/__tests__/cost/modelCostFromRegistry.test.ts: 11 new tests. Five cover the warning (registry miss warns with provider and model; registry hit does not; legacy miss on a model unknown to both tables warns and returns 0; legacy miss on a registry-priced model does not warn; legacy hit does not warn). Six cover the new models, including the pricing page's worked example (50,000 in + 15,000 out at $5/$25 = $0.625) on Opus 4.7/4.8/5, the cache rates on Sonnet 5 and Fable 5, the 0.025x Fable 5.1 cache read, and the legacy rows for Opus 4.8 and Fable 5.1.
  • Before this change: 8 of the 11 new tests fail (the three "does not warn" cases pass trivially). After: all 11 pass.
  • packages/__tests__/cost: 13 suites, 201 tests, 8 snapshots pass (190 tests before this change). registrySnapshots.test.ts.snap was updated with -u; the diff adds the six new entries and bumps modelCount 15 → 21, totalEndpoints / totalModelProviderConfigs 329 → 335, totalModelsWithPtb 108 → 114, nothing else.

Sources (fetched 2026-09-02)

https://platform.claude.com/docs/en/about-claude/pricing, model pricing table rows as shown:

| Claude Fable 5.1 | $10 / MTok | $12.50 / MTok | $20 / MTok | $0.25 / MTok1 | $50 / MTok |
| Claude Fable 5   | $10 / MTok | $12.50 / MTok | $20 / MTok | $1 / MTok     | $50 / MTok |
| Claude Opus 5    | $5 / MTok  | $6.25 / MTok  | $10 / MTok | $0.50 / MTok  | $25 / MTok |
| Claude Opus 4.8  | $5 / MTok  | $6.25 / MTok  | $10 / MTok | $0.50 / MTok  | $25 / MTok |
| Claude Opus 4.7  | $5 / MTok  | $6.25 / MTok  | $10 / MTok | $0.50 / MTok  | $25 / MTok |
| Claude Sonnet 5  | $2 / MTok  | $2.50 / MTok  | $4 / MTok  | $0.20 / MTok  | $10 / MTok |

(columns: Base input tokens | 5m cache writes | 1h cache writes | Cache hits and refreshes | Output tokens)

1 Cache hits and refreshes on Claude Fable 5.1 and Claude Mythos 5.1 are priced at 0.025x the base input price. All other models use the standard 0.1x multiplier.

The $2/$10 per million input/output token pricing for Claude Sonnet 5, announced at launch as introductory pricing through August 31, 2026, is now the standard price.

Web search is available on the Claude API for $10 per 1,000 searches

Worked example on the same page (Claude Opus 5): "Input tokens | 50,000 × $5 / 1,000,000 | $0.25" and "Output tokens | 15,000 × $25 / 1,000,000 | $0.375".

Model ids, release dates, context window and max output: https://platform.claude.com/docs/en/models/overview and the per-model pages models/opus-4-7/overview, models/opus-4-8/overview, models/opus-5/overview, models/sonnet-5/overview, models/fable-5/overview, models/fable-5-1/overview (each states "Model ID", "Released", "Context window: 1M tokens", "Max output: 128K tokens"). The overview page notes: "Every Claude model ID is a pinned snapshot, including the dateless IDs used from the 4.6 generation on."

Context

Why are you making this change?

A registry lookup is an exact ${providerModelId}:${provider} match (registry.ts). When it misses, calculateModelCostBreakdown returns null (calculate-cost.ts), Jawn skips the breakdown (ResponseBodyHandler.ts), the legacy costOfPrompt also returns null, modelCost turns that into 0 (costCalc.ts), and LoggingHandler.ts stores atLeastZero(... ?? 0). Nothing on that path logs, so every request for a model that is not in the tables is recorded at $0.00 with correct token counts, and dashboard spend for a whole model family silently reads zero.

Today that covers every Anthropic model released after Claude 4.6. Anthropic's own worked example (50,000 input + 15,000 output tokens on Opus 5 at $5 / $25 per MTok) is billed at $0.625 and recorded by Helicone as $0.00; the same holds for claude-opus-4-8, which is priced identically. This PR makes the miss visible and adds the six Anthropic models whose full rate row is on the pricing page.

Screenshots / Demos

See the table above.

…5, Fable 5/5.1

A request for a model that is missing from the pricing tables was recorded
at $0.00 with correct token counts and no log line: calculateModelCostBreakdown
returned null on a registry miss and modelCost turned the legacy null into 0.

- Log a console.warn naming the provider and model on a registry miss
  (calculate-cost.ts) and on a legacy miss that the registry cannot price
  either (costCalc.ts). Return types and persisted values are unchanged.
- Add anthropic registry entries and legacy table rows for claude-opus-4-7,
  claude-opus-4-8, claude-opus-5, claude-sonnet-5, claude-fable-5 and
  claude-fable-5-1 at the rates on Anthropic's pricing page, including the
  0.025x cache read multiplier on Fable 5.1.
- Add tests for the warning and for each new model's rates; update the
  registry snapshot for the new entries.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@vercel

vercel Bot commented Sep 2, 2026

Copy link
Copy Markdown

@arthi-arumugam-git is attempting to deploy a commit to the Helicone Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant