Price duplicated model ids by owner, never by file order
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):
- 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. - A first-party vendor's listing, in fixed precedence
anthropic, openai, google, google-vertex, xai— for older first-party ids that carry nocanonical_model_id. - Unpriced when the id is in
primary-model-ids.json(a retired first-party model never inherits a reseller tariff). - 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-k3resolves 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_turntakes the SDK's ownPricingTabletype;PricingTablestays 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](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Agent Relay sessions
claudesession37c21d89· opened viagh pr create· last active 2026-10-23