Price duplicated model ids by owner, never by file order

Merged
WI
4d ago
+732-120

Pricing resolution

A model id that several models.dev providers list resolves to one tariff. A $0/$0 listing is a free tier or plan, not a token tariff, so it takes part only when every listing is free. Of the rest, the tariff is chosen in this order (resolve_tariff in crates/relayburn-sdk/src/analyze/pricing.rs):

  1. The owner's own listing. The owner is the lab named by the listings' canonical_model_id (moonshotai/kimi-k3 → moonshotai), most-named first, ties by name.
  2. A first-party vendor's listing, in fixed precedence anthropic, openai, google, google-vertex, xai — for older first-party ids that carry no canonical_model_id.
  3. Unpriced when the id is in primary-model-ids.json (a retired first-party model never inherits a reseller tariff).
  4. The tariff most listings agree on, ties going to the alphabetically first provider id.

Provider order in the file never matters; the snapshot now parses into HashMaps.

Billing provider

PricingTable also keeps GitHub Copilot's own paid listings. billing_provider(SourceKind::CopilotCli) is github-copilot, and lookup_model_rate(model, source, pricing) prefers that provider's listing at every lookup step, falling back to the resolved tariff. Every cost view passes the turn's source (cost_for_turn, hotspots, cache expiry, CLAUDE.md attribution, tool-call patterns, tool-output bloat, compaction, ghost surface); context-delta span trees carry no harness and cover only Claude/Codex, so they take the resolved tariff. Other harnesses can reach several providers under one model id, so they take the resolved tariff too. The ghost-surface representative rate counts turns per (model, billing provider), so the most-used pair sets a mixed slice's rate. A ledger-home models.dev.json override replaces both the resolved and the billing-provider tariff of every model it prices.

Impact

  • kimi-k3 resolves to Moonshot's tariff: cache reads $0.30/M, not the $3/M of the reseller listed after Moonshot.
  • 410 of 3,796 bundled model ids change resolved tariff; 5 change for Copilot CLI turns. Both lists are in the comments below.
  • cost_for_turn takes the SDK's own PricingTable type; PricingTable stays unexported, as before.

Tests

Synthetic models.dev fixtures with duplicate ids across providers, each asserted in both file orders: owner beats agreeing and outnumbering resellers, owner ranking and fallback, primary-vendor precedence, consensus, provider-id tie-break, free listings never outvoting a paid tariff, free owner, primary and Copilot listings never displacing a paid tariff, billing-provider lookup in every cost view, insert / override merge semantics. Real-snapshot regressions: kimi-k3 equals Moonshot's listing, its Copilot rate equals Copilot's listing, and a cache-read-heavy Copilot kimi-k3 turn costs its tokens at Copilot's tariff. All six new resolution tests fail on origin/main.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Agent Relay sessions

  • claude session 37c21d89 · opened via gh pr create · last active 2026-10-23