The pi.dev harness could only be pointed at two hand-written qwen entries, and a
pi session was costed at one flat qwen rate whatever it actually ran on.
- `backend/openrouter.py` pulls APPE's published catalogue
(appe.dev.gabvdl.xyz/api/models/openrouter.json — a daily models.dev sync) and
serves it at `GET /api/models/openrouter`: ~340 models with $/Mtok in / out /
cache-read, context window, parameter size and capability tags. Cached 6h
in-process, with a `/data` disk copy so a restart with no network still lists
models, and warmed at startup so nothing waits on it.
- `conversations.rates_for()` prices a turn from that catalogue — per model,
cache-read included (OpenRouter's cache price is per-model policy, not
Anthropic's flat 10%). Unknown ids keep the old estimate; pi's own `costUSD`
still wins over any of it.
- The composer's model select gains `Browse OpenRouter…` on the pi harness: a
FuzzyList of the whole catalogue, each row stating the three rates that bill an
agent run plus size and context, with capability filters. Cheapest first.
- Any vendor-prefixed id now resolves to the pi harness frontend-side
(`isOpenRouterId`), so an arbitrary pick survives a resume.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>