fix(pricing): normalize Bedrock dot-form model names and add opus-4-7#17
Open
estelledc wants to merge 1 commit into
Open
fix(pricing): normalize Bedrock dot-form model names and add opus-4-7#17estelledc wants to merge 1 commit into
estelledc wants to merge 1 commit into
Conversation
Two bugs in model_pricing converged into massive cost under-counting for
Bedrock-proxy users:
1. PRICING_TABLE patterns are dash-form ("opus-4-6"), but Bedrock emits
dot-form model strings ("aws.claude-opus-4.7"). String contains never
matched, so every Bedrock call hit the FALLBACK.
2. PRICING_TABLE is missing an "opus-4-7" entry. Direct-API users on the
newest Opus also hit the FALLBACK.
The FALLBACK was Sonnet pricing ($3/$15) — so:
- aws.claude-opus-4.7 → billed as Sonnet (under by ~5/3)
- aws.claude-opus-4.6 → billed as Sonnet (under by ~5/3)
- aws.claude-haiku-4.5 → billed as Sonnet (over by 3×; smaller volume)
- claude-opus-4-7 → billed as Sonnet (under by ~5/3)
Fix:
- Normalize lower-case + dots-to-dashes before lookup, so a single
dash-form table covers both name styles.
- Add opus-4-7 entry alongside opus-4-6 / opus-4-5.
- Family fallback (opus/sonnet/haiku → latest known pricing for that
family) instead of defaulting every miss to Sonnet, so a future
unknown Opus release does not silently mis-bill at Sonnet rates.
Bumps cache schema to v3 — existing v2 caches froze the under-counted
cost in place; the existing "Cache rebuilt" banner handles the
one-time rebuild on first launch.
Tests: 12 new in src/data/models.rs covering direct-API dash form,
Bedrock dot form, family fallback, case-insensitive lookup, and the
truly-unknown-string default. All 64 prior tests still pass (the 2
pre-existing rate_limits failures on main are unrelated).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes ~56% cost under-counting on Bedrock-proxy users (and a smaller hit on direct-API Opus 4.7 users). Independent of #16 — that one fixes token counts, this one fixes the per-token rates.
Two bugs converging
PRICING_TABLEuses dash-form patterns (opus-4-6,haiku-4-5). Two cases never match anything in the table:aws.claude-opus-4.7does not containopus-4-6oropus-4-7(or anything else dash-separated in the table). Every Bedrock call falls to FALLBACK.opus-4-7is missing from the table. Even direct-API users on the newest Opus fall to FALLBACK.FALLBACK_PRICINGwas hard-coded Sonnet ($3/$15/$0.30). So:aws.claude-opus-4.7aws.claude-opus-4.6aws.claude-haiku-4.5aws.claude-sonnet-4.5claude-opus-4-7(direct API)Net on a real Bedrock-proxy archive (28k events, ~12.7k unique messages, 8 active days):
(Token totals are unaffected; this PR only changes per-token rates. PR #16 separately fixes token counts on the same proxy environment.)
Fix
model_pricingnow does a two-stage lookup:.with-— then substring-match againstPRICING_TABLE. A single dash-form table now covers both name styles.opus,haiku, orsonnet, use the latest known pricing for that family. Truly unknown strings still default to Sonnet, preserving prior behavior for non-family inputs.Adds
opus-4-7to the explicit table.The family-default change is the load-bearing piece: it means a future Opus release we don't yet know about silently bills at Opus rates instead of Sonnet rates. Under-billing Opus traffic was the larger risk; over-billing a hypothetical future Sonnet (which would still match
sonnetsubstring anyway) is not.Cache schema bump
Bumped
CURRENT_SCHEMA_VERSION2 → 3. Existing v2 caches on user disks were populated by the buggy pricing and would otherwise freeze the under-counted cost in place. The existing "Cache rebuilt" banner handles the one-time recompute UX with no manual intervention.Tests
12 new tests in
src/data/models.rs::testscovering:claude-opus-9-9→ Opus, not Sonnet)All 64 prior tests still pass. The 2 pre-existing
rate_limitsfailures onmainare unrelated to this change.Test plan
cargo test models::→ 15 pass (3 baseline + 12 new)cargo test→ 64 pass (same 2 pre-existing rate_limits failures as on main)prices_direct_sonnet_dashandprices_direct_haiku_4_5_dash)🤖 Generated with Claude Code