Files
magpie/internal/settings
Comic Changandyetone 024f494bc4 Allow provider-specific upstream model names (#280)
A provider may serve a model under an id of its own: namespaced with a
prefix, dated, a `-latest` that is not what models.dev calls it, or simply
a different spelling. magpie sends the name it knows the model by, and the
provider answers that it has no such model.

  magpie model wire relay-b/model-2 vendor-c/model-2-preview
  magpie model wire 'relay-b/*' 'vendor-c/*'
  magpie model wire relay-b/model-2 --reset

A `*` in the **value** stands for the model, so `relay-b/*` set to
`vendor-c/*` sends `vendor-c/model-3` for model-3. A value with no `*` sends
every model of that provider under one name, which is the case where a relay
really does serve them alike. The CLI shows the pattern the way it was
given, with a concrete line for one of the models, so what is in force is
not something you have to imagine. An exact key wins over the provider's.

The canonical id stays canonical. `Entry.Model` is not rewritten: it is the
key automatic routing groups are built from, what `Resolve` returns as the
model's identity, what `GET /models` lists, what an agent asks for, and what
a call is recorded and priced as. The alias goes into the request's model
field and nowhere else — which is the part that was wrong at first.
Handing it to the serializer gave the provider's name to the code that
decides what a request should look like: `buildChat` checks the model for
Gemini compatibility, `buildAnthropic` matches it for adaptive-only and
effort handling, `buildCodeAssist` maps by model. A provider serving a
model under a namespaced id got a request shaped as if it were that other
model. So the request is shaped from the model magpie knows and the field is
rewritten once at the end, with `rewriteModel` — which already existed to
put one provider's own model name in a body and keeps every other byte as
it was.

It has to reach every path. A request the provider understands as it came
is relayed by `passthrough` without being rebuilt, and the Anthropic token
count is asked of the provider directly; both rewrite the field too, so on
a provider speaking the client's own protocol — the common case for a relay
fronting one vendor — the alias still applies.

"Swapped" compared the canonical id with what the vendor's reply named, so
an alias that is not a prefix or a dated variant marked every call swapped.
It compares the name that was actually sent, in the gateway and in the
ledger alike; the ledger reads the map once for the lot, since its rows are
what a reader sets beside a bill. The Codex backend path is left alone: it
sends magpie's own pick and never an alias.

`provider.Test` asked with the canonical id, so a provider that only accepts
the alias reported a failure while its real requests worked. It asks with
the alias now and still reports the canonical id, since that is the one the
user picked.

A blank name was a hole: the setter trimmed what it was given, so a value of
only whitespace was removed on the way in, while the read path would have
used it had anything else written it — a hand-edited file, or a build from
before the trim. Both ends treat a blank as no name now. The key is
checked where it is written rather than in Save, so one hand-edited entry
cannot block every save, and #288's walk moves it on a provider rename
without a line here.

Co-authored-by: yetone <yetoneful@gmail.com>
2026-10-01 13:03:57 +08:00
..
tray: the menu bar shows several subscriptions' usage side by side (KevinXC on Discord) — Settings → Usage in the menu bar picked one card; its menu now ticks any number (kept open while ticking, saved once when it closes, Off unticks all, a ticked card that has gone stays listed to untick) and the pill says "3 subscriptions". settings.TrayUsages keeps them in order; a file with only the older trayUsage shows that one, and trayUsage is still written as the first for an older magpie. On the Mac the bird and a cell per card are drawn as one image by AppKit on the status item's button: the card's logo (a black glyph tinted in the menu bar's text colour, a coloured one as it is, the name's letter in a ring when there is none) and its two windows stacked, "42%" over "18%", in the bar's colour light or dark and sharp at any scale; the bird's flap goes through it. Arc flags run into numbers (Codex's logo) are spaced out for AppKit's SVG reader. A row longer than 10 characters (a plan's balance read from its page) is cut with an ellipsis in the bar and whole in the tooltip. Windows and Linux show the cards as text, " | " between them. TestTrayUsageCells, TestSVGArcFlags, TestTrayImage (darwin, renders 0-3 cards light and dark at 2x), TestTrayUsagesMigrate and tray-usages.test.cjs (Chromium, WebKit, en/zh) are new. go vet, go build (darwin GUI), go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./..., go test ./internal/gui pass; tray-usages, settings-groups, panel-*, click-scroll, old-webkit pass. Not seen in a live menu bar.
2026-09-30 19:45:44 +08:00