Skip to content

Price openrouter/ models from OpenRouter's model list - #5

Merged
MattFisher merged 2 commits into
mainfrom
feat/openrouter-pricing
Oct 12, 2026
Merged

MattFisher merged 2 commits into
mainfrom
feat/openrouter-pricing

Conversation

@MattFisher

Copy link
Copy Markdown
Collaborator

Summary

openrouter/<provider>/<model> names stopped resolving because LiteLLM dropped all of its OpenRouter rows (BerriAI/litellm#45665, 2026-10-09). The live service returns zero openrouter rows, and /api/inspect-costs returns 400 for every OpenRouter model. That leaves OpenRouter runs unpriced by the Inspect Costs Plugin.

This PR makes refresh also fetch OpenRouter's public /api/v1/models and convert each priced model into a LiteLLM-shaped row keyed openrouter/<id>. Those rows are merged into the cached dataset. The Inspect resolver needs no change: it already scopes openrouter/... lookups to litellm_provider == "openrouter" and matches the full key.

  • Rates are OpenRouter's own. They can differ from the first-party provider's, and that is the right price for runs that go through OpenRouter. Its list also includes recent models LiteLLM lacks.
  • Router models are skipped. openrouter/auto-beta and its siblings are priced at -1. 451 of 458 models are kept.
  • One KV write. If either fetch fails, refresh throws and the previous cache stays in place. The trade-off: an OpenRouter outage also delays the LiteLLM refresh until the next six-hour run.
  • Tiered prices are ignored. For example, Gemini's >200K-token prices are not used, so the base rate applies. This matches how LiteLLM rows are already exported.
  • Capability flags (vision, tools, reasoning, prompt_caching) are derived from OpenRouter's fields, so the UI and API supports filters work on these rows.

Verification

  • Unit tests cover the converter and resolution of openrouter/... names, including dotted versions such as claude-opus-4-1 against claude-opus-4.1. Worker tests cover the merged refresh and the failure path (previous cache kept).
  • Against today's live LiteLLM and OpenRouter payloads, 13 OpenRouter judge models and 2 first-party controls all resolved to their own rows (for example, openrouter/openai/gpt-oss-20b: 0.018 input / 0.09 output per 1M tokens). First-party names still resolve to LiteLLM rows. The merged value is 2.2 MB, well under KV's limit.
  • wrangler dev --test-scheduled ran the real refresh in workerd: 4,492 models cached, and /api/inspect-costs served the OpenRouter prices.
  • npm test (31 passed), npm run typecheck, wrangler deploy --dry-run --env production, and pre-commit all pass.

Screenshots

Searching "openrouter" in the UI.

Before (production): 0 of 4041 models, and the footer credits only litellm.

After (local, refreshed): 451 OpenRouter rows with capability badges, and the footer credits both sources.

Not in scope

anthropic/claude-opus-4-1 (first-party) also fails to resolve. The cause is separate: LiteLLM's first-party anthropic rows now start at Claude 4.5, and 4.1 survives only as Bedrock and Databricks keys. openrouter/anthropic/claude-opus-4-1 resolves after this PR.

🤖 Generated with Claude Code

MattFisher and others added 2 commits October 12, 2026 20:28
LiteLLM dropped its openrouter rows, so every openrouter/<provider>/<model>
name was unresolvable. Refresh now also fetches OpenRouter's public
/api/v1/models, converts each priced model to a LiteLLM-shaped row keyed
openrouter/<id>, and merges it into the cached dataset. Router models
(priced at -1) are skipped. Both sources go into one KV write, so a failed
fetch from either keeps the previous cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README, llms.txt, the UI footer and the changelog now say that
openrouter/<provider>/<model> names are priced from OpenRouter's own model
list, at OpenRouter's rates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MattFisher
MattFisher merged commit a81e204 into main Oct 12, 2026
1 check passed
@MattFisher
MattFisher deleted the feat/openrouter-pricing branch October 12, 2026 09:42
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