Skip to content

v0.20.0 — a models catalog that describes itself

Choose a tag to compare

@izzoa izzoa released this 21 Sep 21:57
· 50 commits to main since this release

Highlights

  • GET /v1/models now describes what it advertises. The listing returned ids and nothing else, so an agent could see that a model was routable but not its context window, its capabilities, or what it costs — figures the router already held and already showed the dashboard. Real model ids now carry context_window, supports_tools / supports_vision / supports_reasoning, and a pricing object in per-1M USD, resolved through the same shared resolver the dashboard and the cost path use and marked when the figure is an estimate. Unknown values are absent, never null.
  • auto and tier keys deliberately describe nothing. A virtual id names a set of models, so no single window or price is true of it: a minimum understates and makes clients over-truncate every request, a maximum overstates and fails upstream, and a representative member's value changes silently when a tier is reordered. An absent field lets a client apply its own default; a wrong one makes it size and cost requests against a figure that was never true.
  • The Anthropic SDK now gets the Anthropic shape. anthropic.models.list() hits the same GET /v1/models URL as the OpenAI SDK, so unlike every other /v1 route this one takes no protocol from its path. The envelope is chosen by the anthropic-version header — never by the credential header, since the agent-key guard deliberately accepts Authorization: Bearer or x-api-key for either SDK. A response is one envelope or the other, never a hybrid.
  • New GET /v1/models/{id}. Serves every id the listing advertises — provider-qualified ids, unambiguous bare ids, tier keys and auto — including ids containing : and / (<providerId>:openai/gpt-6-astra) in either literal or percent-encoded spelling. Anything the listing hides is a 404, in the caller's own error envelope.
  • Listing and retrieve report one catalog. Both are built from a single entry set, so the routable-variant exclusion and the bare-id ambiguity rule cannot drift between the two surfaces or the two envelopes.

Upgrade notes

  • Nothing to do. No migrations, no new environment variables, no changed defaults.
  • No breaking changes. Every added field is additive; a caller that sends no anthropic-version header receives the OpenAI shape byte-for-byte as before, with the same advertised ids and the same id strings.
  • created is a fixed value rather than a real timestamp — polyrouter does not track model creation dates, and the only per-model timestamp it holds is the provider-sync time, which is rewritten on every sync and would churn a cached or sorted catalog. Clients that render the field will show the Unix epoch.
  • Effective prices are now visible to any holder of an agent API key. In a self-hosted deployment that key is the operator's own.

Full package changelogs live in packages/*/CHANGELOG.md.