Commit Graph
5 Commits
Author SHA1 Message Date
Comic Chang 49f40b463f Configure per-model context windows and output limits (#279)
A provider that serves a model the catalogue does not list, or lists at the
wrong size, has a window and a reply limit magpie cannot know: both fall
back to whatever the catalogue says about the model's maker, which for such
a provider is nothing at all.

  magpie model context relay-a/gpt-5.5 262144
  magpie model output  relay-a/gpt-5.5 131072
  magpie model context 'relay-a/*' 200000
  magpie model output  relay-a/gpt-5.5 --reset

Both are looked for in the same order as each other: this model, then
`<provider id>/*`, then the provider's own list, then the catalogue. A
model's own value wins over its provider's. The reply limit is new; the
window is not — `Provider.Contexts` has been there, with a `"*"` of its own,
settable through `magpie provider set <id> context.<model>=`, and this
reuses it rather than shadowing it.

That reuse is the point rather than a detail. A context is a routing input
and not only a number agents are shown: at 95% of a held member's window a
request moves to a member that takes more, so two sources of truth would
mean the gateway routing on one number while agents are told another.
`magpie model context` is a second way to set the same field, not a second
field.

Both reach the agents. Pi keeps a model's window and reply limit in its own
models.json, OpenCode keeps its limit, and Crush, Droid, Cline, Qoder and
Zcode keep their own; an agent reads those files when it starts, so a limit
set here that never reaches them is a limit that does not take effect.
`magpie provider set` has always told the agents, and this behaves the same
way rather than introducing a second, quieter path. The test asserts each
setter reaches them exactly once — the two paths differ (one saves the
provider file, the other settings and then says so) and that difference is
worth pinning. An end-to-end pass confirms it: with a Pi models.json in
place, `magpie model context relay-a/sol 999999` writes `contextWindow:
999999` into `providers.magpie.models`.

A `0` is refused rather than read as a reset, naming `--reset`; a mistyped
model id is refused the way `magpie model name` refuses the same id; a reset
says what is actually in force instead of claiming to be back to the
vendor's list while a provider-wide value still applies; and
`magpie model context <provider>/*` reports that value rather than saying
the provider serves no such model. Validation happens where the entry is
written, so one hand-edited bad key cannot stop a theme or a window size
from saving, and #288's walk moves these on a provider rename without a
line here.
2026-10-01 02:14:22 +08:00
yetone 2c432fe3fa routing, models: a rerouted request's tooltip names who answered it (#337), and model names can go without their provider (#335) — the Routing page's and the tray panel's rows named the member that answered a rerouted request, but their tooltip still said the path first resolved; it now says the provider · account · model that answered, and on a second line what it was rerouted from. A setting, Settings → Preferences "Provider in model names" or magpie model suffix off (on by default, as before), writes the models listed to Codex and the other agents (OpenCode, Pi, omp…) by their name alone, except two in an agent's list that would read the same, which keep theirs. routing-reroute-title.test.cjs and plain-names.test.cjs (Chromium, WebKit, en/zh), TestPlainNames, TestPlainNamesReachAgents and TestModelSuffixCmd fail without the change; click-scroll, old-webkit, currency, text-size, panel-routing, routing-served, routing-steady pass. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. 2026-09-30 23:09:04 +08:00
Comic Chang 901ee08280 Count usage at the configured provider/model price (#278)
Magpie reports models.dev's list price for every call. That is the right
number for a vendor's own key and the wrong one for a provider that
resells or exposes a model at a different tariff, and it leaves a model the
catalogue does not list with no cost at all — a provider's own /models
gives ids, not economics.

  magpie model price relay-a/gpt-5.5 0.12,1.20,0.01,0.15
  magpie model price relay-a/* 0.12,1.20,0.01,0.15
  magpie model price relay-a/gpt-5.5 --reset
  magpie model prices

Absolute USD per million tokens. All four parts are required: a price
missing one would understate the rest of every call, and a hand-edited file
that left a part out would bill it at zero, so each part is a pointer and
the setter refuses a price that is negative, NaN or infinite, naming the
part at fault. Zero stays distinct throughout — a model served at no cost
has a price, not the absence of one. A `<provider>/*` entry covers every
model of that provider and an exact entry wins over it; --reset removes
only the exact entry and says so when a provider-wide one is still in
force.

The order a price is looked for in is the price for this model, then
`<provider>/*`, then the provider's own catalogue, then models.dev for the
maker. A price is a provider's tariff, not the model's: the same model
through two providers has two prices, and each keeps its own. A provider is
resolved by its id, or by an id it was renamed from, and never by its
display name — Find answers those too, and a record naming one was counted
at another provider's price.

provider.EffectivePrice is the one lookup every cost caller shares, so the
usage ledger and a session's totals both go through it, and a session
naming a model bare is still priced at its maker's list price, which is a
different question from what one provider charges. catalog.PriceOf and
PricedBy keep returning the models.dev price for anything wanting an
unbiased number. The background-task pickers (draw, search, vision) still
rank by catalogue price: they choose which model answers, not what a call
is reported to cost.

Unlike every other per-model preference this does not call
catalog.Touched. What a call costs is not what an agent picks a model by,
and the model lists magpie keeps in the agents' own files are not its to
rewrite over a number in a cost report. A rename moves the prices with it
through the walk #288 adds, so nothing here has to say so, and an id
recorded before a rename still resolves.

Validation happens where the entry is written, not in Save: one hand-edited
bad price in the file must not make saving a theme or a window size fail. A
price for a model the provider does not serve is refused the way
`magpie model name` refuses the same id, since it is a price that never
applies and nothing reports it as dead; a removal is exempt, so an entry
left for a model that has since gone can still be taken away.
2026-09-30 20:31:11 +08:00
yetone c1d38cc50f effort: Claude Code can start at max — settings.json's effortLevel keeps up to xhigh (/effort max lasts a session), so magpie keeps max as CLAUDE_CODE_EFFORT_LEVEL in its env, which every session asks for (tested: Claude Code then sends output_config.effort max), and another level takes it away. A model whose reasoning levels aren't known (one models.dev doesn't list, a custom provider's) can be given some of none…max on the Providers page or with magpie model efforts, which the lists agents get and the gateway then take it to have: a request's effort is fitted to them, max sent as max 2026-09-27 11:05:47 +08:00
yetone 47e12df418 models: a provider's model can go by a name of the user's, and offer only some of its reasoning levels — Claude Opus 5.5 · Claude Code can be Opus 5.5, and a model with six levels can offer just low, medium and high. Both are kept in settings.json by provider/model (modelNames, modelEfforts), apart from the vendor's list, so a Refresh, a restart or an upgrade leaves them, and the same model from another provider keeps its own; a provider renamed takes them along. They are applied where the catalog is made, so the gateway's /v1/models, the lists magpie writes into the agents (Codex's model catalog, ZCode, Pi, OpenCode, OMP …) and magpie's own pages all show them, and a change rewrites the agents' lists as any other change of the catalog does. Only what is shown changes: the id, where requests go, and the levels the vendor is asked at stay as they were; a found routing group keeps the model's own name. The provider's editor has Names & levels under its models — a name typed in place, a tick per level, Restore default — and the terminal has magpie model name <provider/model> <name>|--reset and magpie model efforts <provider/model> low,medium,high|--reset. Issue #92 2026-09-26 23:23:45 +08:00