chore(pricing): refresh the bundled snapshot; a refresh can no longer drop a model's pricing - #1483
Conversation
Regenerated from live LiteLLM/models.dev/OpenRouter: 5,938 primary entries (1,210 added, 11 removed, 298 repriced vs the 0.9.24 bundle) and 51 fallback entries; 394 primary entries carry a tier slot. The Grok Build family upstream is what makes grok-4.6-build priceable, shifting the Grok parser's authoritative-model pick to the real modelUsage id (pin updated with the reasoning in the test).
… drop a model's pricing Regenerated from live LiteLLM/models.dev/OpenRouter: 5,938 primary entries (1,210 added, 298 repriced vs the 0.9.24 bundle), fallback 51 from the gap-fill plus 9 carried forward. Upstream actually removed four entries (friendliai llama-3.1 bare and prefixed); seven more are excluded by the per-token-output filter, which is a rule change and is called out as one. Two bundler rules from review: - vendor-prefixed aliases no longer displace a richer entry for the same model: completeness (published cache slots) wins over first-write, so the new nebius/MiniMaxAI/MiniMax-M3 without cache-read rates cannot replace the publisher's entry that carries them; - previously-priced fallback entries carry forward when neither the new primary nor the gap-fill covers their key exactly or vendor-prefixed - the form the resolution pipeline queries. Nine models would otherwise have lost all pricing; a dated variant sharing the bare name does not count as coverage because it does not answer the undated query. The Grok Build family upstream makes grok-4.6-build priceable, so the Grok parser's authoritative-model pick prefers the real modelUsage id (pin updated with the reasoning in place).
iamtoruk
left a comment
There was a problem hiding this comment.
The snapshot regeneration itself is faithful. The top models by spend match upstream exactly, and no model in real use is dropped. The dollar impact on the maintainer's own data is negligible. But two things must change before this can land, because they cost other users money or hide a regression.
-
Guard 2 coverage is wrong and drops pricing for 96 models. The bundler's coverage check uses
Object.keys(snapshot).some(k => k.endsWith('/' + key)), which treats a bare id like grok-latest as covered by a vendor-prefixed key such as~x-ai/grok-latest. But the runtime resolver getModelCosts in src/models.ts never tries<vendor>/<id>for a bare id, so those fallback entries are dropped and the models return null (unpriced). This is not just grok-latest: 96 of the 145 removed fallback keys price on main and return null on this PR, including claude-opus-4.8, claude-fable-5.1, the claude/gpt/gemini/kimi "-latest" aliases, and the batch variants. Fix: drop theendsWith('/' + key)clause or check against what the runtime resolver actually reaches, then regenerate the fallback so those entries stay priced. -
The grok-parser-pipeline test edit masks a regression. That test now mocks grok-4.6-build to null, so the change it pins is grok-latest losing its price and falling back to grok-build rates, not "grok-4.6-build prices through the Grok Build family" as the new comment says. Revert that test edit. Once fix 1 is in, grok-latest keeps its own price and the test should not need changing.
-
The completeness-wins guard is not rate-neutral, so please either make it so or own the reprices. Beyond preventing a dropped price, it changes 43 input/output rates and 34 cache rates by itself, on the same upstream data, just by choosing a different row. Some of these are large, for example grok-3 from 3/15 to 1.25/2.5, grok-4 the same, mistral-large-latest from 8/24 to 0.5/1.5, deepseek-v3 from 1.14/4.56 to 0.27/1.1. These may well be the correct rows, but the PR presents the guards as hardening, not repricing. Either restrict the guard to replace only when input and output are identical (pure completeness), or keep the reprices and list them in the PR body and changelog so they are a deliberate, reviewed change.
One more thing: the finalized daily cache is not re-derived by a refresh, and there is no cache version bump here. So installed users only see any of this on days the cache is re-derived. Online, the live price feed wins anyway, so the bundle is only a gap-fill for offline or unpriced cases.
This is close, and the regeneration is good work. It just needs the coverage clause fixed, the test reverted, and the guard reprices owned or removed.
…uard, regenerated bundle (getagentseal#1483) - coveredByKey is exact-key only: the resolver never reaches vendor/<id> for a bare query, so the old endsWith clause dropped 96 priced fallback ids. - Pass 2 stripped writes are strictly slot-filling: a richer upstream row may only fill missing cache slots when input/output rates are identical, never re-price a filled slot (was re-pricing 43 input/output + 34 cache rates). - Carry now rescues dropped primary rows as well as fallback entries (twelve ids this cycle), so a refresh cannot leave a previously-priced model null. - Regenerated: 5,942 primary + 212 fallback; 159 carried; zero coverage regression and zero guard-caused rate changes vs upstream/main, verified by resolving every id from either bundle through the real getModelCosts.
…ntseal#1483) Upstream LiteLLM now publishes a distinct z-ai/glm-5.3 rate, so the prefixed spelling no longer equals the glm-5p2 sibling. Assert against the snapshot's own row (the gpt-5.6-codex pattern) so the test survives later upstream reprices and the z-ai/ -> zai/ namespace rename.
|
All three addressed on 1 — coverage is exact-key-only, and the loss it already caused is repaired. The 2 — test reverted byte-identical to main and passes 6/6 unmodified; 3 — the guard is now strictly slot-fill (your option A). Pass 2 replaces a stripped key only when input and output are identical and every slot the existing entry already carries keeps its value — it fills null slots, never re-prices a filled one. grok-3 and grok-4 are back at 3/15, mistral-large-latest back at 8/24. Rate-neutrality verified two ways: on today's identical fetched JSON, main's pass-2 vs this one — 0 input/output changes, 0 cache changes, 62 null-slot fills; and end-to-end, every remaining rate diff vs main is attributable to source data (181 same-key upstream reprices, 313 new upstream rows), none to the guard or the carry. Two things disclosed rather than smuggled:
On your cache note — agreed, and deliberate: this PR doesn't bump |
Split out of #1478 per review: the pure snapshot refresh lands on its own, because it moves money that has nothing to do with the tier mechanism and the mechanism is inert without fresh data anyway.
What's in the data
grok-build-latest,grok-build-0.1and routes) — which makesgrok-4.6-buildpriceable, so the Grok parser's authoritative-model rule now prefers the real modelUsage id (pin updated with the reasoning in place).Two bundler rules from the review, both fixing real damage this regen exposed
nebius/MiniMaxAI/MiniMax-M3with no cache-read rate, and pass 2 handed the stripped alias to it on first write — the publisher's entry carrying the published 6e-8 cache-read was silently replaced,buildCostsfell back toinput × 0.1(3e-8), and 1,574 calls repriced by −$2.99. Now a sparser alias cannot displace a richer entry for the same model.qwen/qwen3.5-plus-20260420shares the bare name but does not answer the undated query at runtime.Verification
npm run bundle-litellmtwice over (idempotent carry), MiniMax-M3 cache-read verified back at 6e-8, all nine carried keys present.tsc --noEmitclean; affected suites green (models, pricing-fallback-data, grok pipeline with the updated pin, codex, parser c4, budget).