* feat(gui): show and filter usage for each API key
* feat(gateway): issue per-user caller keys and attribute usage
* feat(gui): manage gateway users and filter caller-key usage
* test: verify caller-key failover and document user management
* refactor(gateway): use named caller keys without user accounts
* feat(gui): manage named caller keys with existing account styles
* fix: remove user breakdown from CLI and leftover gateway styling
* fix(usage): drop stale user field from request response
* feat(gateway): authenticate LAN calls with named caller keys
* fix(gateway): preserve LAN key rotation in the named caller store
* fix(gui): retain native LAN key copy and rotation controls
* fix(gui): inherit the global theme for API key inputs
* fix(usage): show client API keys using the existing terminology
* fix(gateway): rotate named keys without changing usage identity
* fix(gui): unify gateway keys and selectable connection examples
Keep sharing controls in Settings and manage credentials only in Gateway. Refresh the named-key list on navigation, ignore stale reads after key actions, and generate all API examples from the selected address and enabled key.
* fix(gui): keep caller key names literal in connection menus
* fix(access): use Magpie as default key and drop user migration
* refactor(gui): name caller key source and tests consistently
* refactor(usage): split provider-key accounting out of caller-key PR
* fix(gateway): preserve LAN compatibility and add headless key management
* fix(gui): clarify gateway keys and confirm destructive actions
* test(gateway): guard caller attribution under 120 concurrent requests
* fix(gateway): keep open access, tolerate migration errors and revoke legacy keys
* fix(backup): preserve named gateway keys and honor no-keys restores
* fix(gui): keep local API-key semantics and disambiguate shared credentials
* docs(gateway): keep review scope focused and append browser test documentation
* fix(backup): retain existing default keys when old backups lack their store
* fix(gateway): attribute video creation usage to the caller key
* fix(access): explain default key revocation blocked by read-only settings
* test(usage): preserve provider and caller identities after rebase
* test(gui): reconcile caller key fixtures with merged main
* docs(usage): clarify caller coverage and independent provider accounting
* fix(gui): initialize fast members for model-shortcut groups
Latest main introduced fast-member arrays but omitted the model shortcut's draft. The existing unlisted-models browser regression fails unchanged on main. Initialize fast to an empty list and assert a standard-speed group is saved, without relaxing existing assertions.
* fix(access): retain legacy LAN access when the key store cannot be created
Allow only the configured legacy credential before either migration marker exists. Refuse revoked mirrors, disabled matches and unreadable stores; keep the fallback's caller identity stable when migration later succeeds. Cover read-only configuration directories, remote credential transports and revocation.
* fix(backup): save settings before replacing gateway credentials
Leave the key store untouched when settings validation or writes fail. Restore the previous settings association when the key store refuses its write, and report a rollback failure separately. Cover invalid settings and read-only settings/store failures.
* fix(gui): reset missing caller filters and focus key controls without scrolling
* test(provider): synchronize Zhipu quota fixture observations
* feat(usage): attribute gateway usage to individual API keys
* refactor(usage): keep provider accounting focused on CLI and CSV
* fix(usage): attribute System One calls and name upstream key fields explicitly
* fix(usage): leave keyless System One requests unattributed
The rate is internal/fx: a free, no-key endpoint (open.er-api.com/v6/latest/USD), cached in memory and in a small file beside magpie's other caches (XDG_CACHE_HOME/magpie/fxrate.json) for 12h, refetched only once that's stale, and falling back to the last rate it ever had — or a fixed 7.2 — while offline; the currency row's tooltip names the rate and when it was learned. usage.FormatCost carries the $/¥ formatting (2 decimals above $1, 3 below, whole numbers above 100) that usage_cli.go and internal/tui/pages.go used to each have their own copy of; both now read Settings' currency once per command/redraw rather than per row. internal/gui/api.go exposes the rate on /api/settings always and on /api/state only when cny is actually chosen, so usd users' hot path never touches the network for a rate nothing shows with.
Tested with new internal/fx/fx_test.go (a fake server: fetches and caches, answers from memory then from the cache file with no further calls, refetches once stale, falls back to a stale cache or Fallback when offline, ignores a reply with no CNY rate), TestFXInState in internal/gui/fx_test.go, TestFmtCostShowsChosenCurrency in internal/tui/usage_test.go, and a new internal/gui/tests/currency.test.cjs in Chromium and WebKit, English and Chinese (the Usage page's $ by default and ¥12.34×7.2 once cny is picked, the currency row's labels/state/tooltip, a real wheel scroll deep into Settings left alone by picking a currency, the choice surviving a reload). go build -tags nogui, GOOS=linux and GOOS=windows builds, and go test -tags nogui -count=1 ./... all pass clean.
A fetch that failed is not tried again for 10 minutes (the stale or fixed rate shown at once meanwhile), so offline each state() does not wait up to 4s on the network: TestGetDoesNotRetryAFailedFetchAtOnce.
The product, module path (github.com/yetone/magpie), binaries, env vars
(MAGPIE_ADDR, MAGPIE_DEV_UI, MAGPIE_THEME, MAGPIE_DEBUG), config and cache
folders (~/.config/magpie, ~/.cache/magpie), bundle id (com.yetone.magpie),
gateway provider id and token, and every UI string now say magpie.
On first run magpie copies ~/.config/dial and ~/.cache/dial to the new
folders when they don't exist yet (copy, not move, so a still-running dial
keeps working; the old folders can be deleted by hand later).
The logo is a small round magpie in profile: one path for the header and
the tray, and the app tile adds the white belly and the blue-green tail.
The header mark is drawn in ink rather than the accent colour, which
fought the text in light mode.
The gateway now records every call's token counts (read from the provider's
own usage block, in both the translated and the pass-through paths) with the
calling agent taken from the client's User-Agent, into
~/.config/dial/usage.jsonl. A Usage tab sums them by period, agent and
model, with a per-hour/day/week timeline and cost at models.dev list
prices; dial usage does the same in the terminal.
Also nudges the window header 1pt up so the brand sits level with the
traffic lights, and lets ?view= open the window on a tab.