Commit Graph

  • 1fa21850a3 plugins: a plugin can say its sign-in renewed, and what a usage read means for it (要保证插件跟内置的所有逻辑都要一模一样) — a built-in whose sign-in renewed took the lapse mark off whatever the request then met, and a plugin could only clear it with a success: X-Magpie-Sign-In: renewed now clears it on any status. A usage read marked a plugin account whenever its error said to sign in again and cleared it on any clean read, where Qoder's, Kiro's and others' built-ins marked none from usage: auth.usage may now say signIn: expired, kept or renewed, taken as the header is; one that doesn't say keeps the old reading. TestPluginSaysSignIn and TestPluginUsageLapse fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./internal/gateway ./internal/provider ./internal/plugin pass. yetone 2026-10-01 04:46:24 +08:00
  • c9d2015e5d plugins: a plugin says apart what its answer means for the sign-in, so it can fail with its built-in's status (当然要做,要保证插件跟内置的所有逻辑都要一模一样) — magpie took a plugin account for lapsed on a 401 alone, so a plugin had to choose between the built-in's status and its lapse mark: Factory's and MiMo's refused renewals were 401s where the built-in answered 502 and marked the account, and Qoder's 403, Zed's retried 401, Kiro's unreachable refresh and Cursor's expired plan answered other than the built-in so as not to mark one it didn't. An answer's X-Magpie-Sign-In now says: expired marks the account lapsed whatever the status, kept leaves it be; without it a 401 marks it and a success clears it, as before. The agent never sees the header. TestPluginSaysSignIn fails without the change. yetone 2026-10-01 04:36:40 +08:00
  • 614d51799b routing: the Requests and Accounts columns read in order (the user: 这里排版是不是有问题啊?感觉好乱) — side by side, the accounts ran far on down the page beside an empty column under the requests; they now end where the requests do and scroll like them. An account's models were wrapped in among its numbers (tried, answered, last answered), a code chip mid-line; they now take a line of their own under them. A provider's own row said its model twice (heading and chip) and the provider's name twice (card and row); the row is now its model alone. The two-column rule had never matched at all: .rt-col is a container too, so an unnamed @container query was sized against the column (~446px), not the section; the section's container is now named. The requests list is sized in the frame after a resize, since the accounts beside it now follow its height (WebKit reported a ResizeObserver loop otherwise). routing-columns.test.cjs (Chromium, WebKit, en/zh: bottoms level, accounts scroll, models on their own line, a provider's row its model alone, one column below 860px) fails without the change. routing-steady, -busy, -compact, -shape, -flood, -effort-row, -kind, -served, panel-routing, click-scroll, old-webkit pass; go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./internal/gui pass. yetone 2026-10-01 04:35:59 +08:00
  • b2bcbdc91a plugins: a moved Cursor, Devin, Command Code, Kiro or Zed fails as its built-in did — their plugins' 0.1.4 answer each error with the built-in's status and words (Zed's and Kiro's failures before the answer as a 429/401/403/402/502 rather than a 200 stream, Command Code's and Cursor's bare errors in Go's status text, Devin's without a doubled prefix), so the gateway fails over, rests and marks lapsed as it did for the built-in. A move now needs 0.1.4 of them, and a magpie serving the gateway updates one moved before. Each version was installed from npm in a sandbox. yetone 2026-10-01 04:28:04 +08:00
  • b0a0165fc9 usage: a notification when a window is nearly used up or a balance runs low (#368) — Settings has Usage alert (off, or a share of 1–100%, 80 by default) and Low balance alert (off, or an amount, 5 by default), and magpie quota alert sets them from the command line. Each subscription or plan window, other than one set aside, is told once a run when it reaches the share, and a balance once until topped up past the amount again; what was said is kept, so a restart doesn't say it again, and a failed or stale reading neither alerts nor clears. The system's notifications are started only when first needed, so a Mac build that can't have them or a Linux desktop without a daemon still starts, and Settings says when they are refused or unavailable; a click opens the Usage page. TestDueAlerts and friends, TestAlertText and usage-alert.test.cjs fail without the change. yetone 2026-10-01 04:14:08 +08:00
  • 09e7a3f147 signin: a sign-in whose browser can't reach magpie finishes with the address pasted (Jorben on Discord: ChatGPT sign-in in Docker on a server never finished) — ChatGPT sends the browser back only to localhost:1455, which is the user's own computer, not the server, and magpie's paste field refused every built-in sign-in. Claude, Codex, Devin, Kiro (both steps of an AWS sign-in), Gemini, Antigravity and Zed now take the address the browser ended on, in the app and in magpie accounts add: only this sign-in's own port, path and state, traded through the same handler as the browser's, and once, whichever comes first. TestCodexSignInFromPastedAddress, TestPastedAddressAndCallbackFinishOnce, TestLoopbackSignInsTakePastedAddress and signin-paste-codex.test.cjs fail without the change. yetone 2026-10-01 04:09:16 +08:00
  • b3f0af602e gui: a moved built-in signs in from where it was, as it did (插件版…保持一模一样) — moved onto its plugin, a built-in left Subscriptions for "From plugins" and asked which of the plugin's ways to sign in where the built-in had one click; ZCode lost its site question (Z.ai or BigModel), Try again after a failed sign-in asked the way again, and Cursor, which kept one account built in, still read "keeps one account" though its plugin keeps more. It now stays under Subscriptions with its hint and site question, takes the plugin's way for the built-in's click (ZCode's for the site picked), tries the same way again, and keeps as many accounts as the plugin does. plugin-moved-signin.test.cjs (Chromium, WebKit, en/zh) fails without the change; plugin-signin, plugin-move, factory-sub, add-sheet, qoder-cn-tile, zed-sub, mimo-sub, commandcode-risk, old-webkit pass (zcode-site fails on the base too). yetone 2026-10-01 03:50:32 +08:00
  • 7d9f4458da plugins: a moved built-in's sign-in goes as the built-in's did (插件版…保持一模一样) — through its plugin, Devin, Grok and Cursor started with no CLI on the machine and failed ("install Grok Build first") where the built-in installed it; the code Factory's page asks to confirm was only in the instructions' text, not in the box to copy; and the sign-in never said the account was the one in use, so a first account read "added — switch to it any time". The CLI is now installed first as the built-in's was (Cancel stops the installer), the code in the instructions is given to copy, and the account in use says so. TestMovedSignInAsBuiltIn fails without the change. yetone 2026-10-01 03:50:31 +08:00
  • 04722aa9d5 gui: a moved built-in's editor shows no plugin:// endpoints (插件版…保持一模一样) — Zed moved onto its plugin listed plugin://zed/v1 under Endpoints with a Test button that could only fail; a plugin's provider is reached inside magpie, so neither shows. plugin-move.test.cjs (Chromium, WebKit, en/zh) fails without the change. yetone 2026-10-01 03:37:06 +08:00
  • 2ca1373db5 plugins: removing or switching off the plugin a built-in is moved onto moves the built-in back first (插件版…保持一模一样) — the provider went with the plugin, its accounts out of sight in plugin-auth.json; now its accounts go back to the built-in, then the plugin is removed or switched off, in the app and with magpie plugin rm|off. Installed marks such a plugin ("Serves Zed", a dot, no stripe) and asks in its row, not a dialog, naming what goes back; only a yes sends it. TestReleasePlugin and plugin-release.test.cjs (Chromium, WebKit, en/zh) fail without the change; plugin-market, click-scroll, old-webkit pass. yetone 2026-10-01 03:34:36 +08:00
  • f2de03a66b gui: moving a built-in onto its plugin, or back, runs to the end though the page goes (插件版…保持一模一样) — the move ran on the page's request, so closing or reloading the page stopped it halfway, the accounts in neither place until it was run again; it now runs on its own, for ten minutes at most. TestMoveOutlivesRequest fails without the change. yetone 2026-10-01 03:20:55 +08:00
  • 140b6161bc cli: magpie provider shows a moved built-in as the built-in read (插件版…保持一模一样) — Zed moved onto its plugin said its account came "from plugin's own sign-in" and listed plugin://zed endpoints no one can reach; it now says zed's own sign-in (another plugin's provider its name's sign-in) and leaves the plugin:// URLs out. TestShowMovedProvider fails without the change. yetone 2026-10-01 03:19:22 +08:00
  • 5346486d50 accounts: magpie accounts lists a moved built-in's accounts by its id, the one in use marked (插件版…保持一模一样) — with no agent named, they showed as plugin:zed rows as logins.json keeps them and none was marked in use; each plugin's provider now lists its accounts as its own page does, under its magpie id. TestAllLoginsMoved fails without the change. yetone 2026-10-01 03:16:20 +08:00
  • 0362a3f860 plugins: deleting a moved built-in hides it, as deleting the built-in did (插件版…保持一模一样) — a plugin's provider is signed out when deleted, and a built-in moved onto its plugin went the same way, every account signed out; it is now only hidden, its accounts and model picks kept, and Add brings it back. TestDeleteMovedHides fails without the change. yetone 2026-10-01 03:16:20 +08:00
  • 47786c456e plugins: a moved built-in's own account stays the agent's, and Qoder's first goes (插件版…保持一模一样) — the plugin's accounts were listed with no own one, so removing the agent CLI's own account (Devin, Grok, Command Code, Cursor, Kiro, ZCode, WorkBuddy) signed it out of the plugin and its name stayed as signed in at the move; it is now told by the mark each mover leaves on it, named as the CLI is signed in now, only hidden when removed (the CLI stays signed in) and shown again once the CLI or magpie signs in anew, as the built-in's was. Qoder's first account showed Remove and was refused; it now goes, the next put first, as the built-in let it. plugin.UseCached lets a test stand a plugin's provider up without Bun. TestMovedOwnAccount and TestMovedQoderFirstGoes fail without the change. yetone 2026-10-01 03:16:05 +08:00
  • a8f0baaaa0 gateway: a refusal after only thinking goes to the next account (#248, Koohoko: safeguards stopped the response above) — Opus 5.5 at xhigh thought 10–25s and then ended with stop_reason refusal, and magpie had counted the first thinking delta as the reply having started, so the stream was already Claude Code's and the refusal passed through instead of the next account being asked. Reasoning (Anthropic thinking, Responses reasoning and summaries, Chat reasoning_content, Gemini thought parts) is now held with the reply, up to 4 minutes, and let through with it as soon as text or a call comes. A ChatGPT bio_policy translated for Claude Code or a Chat agent kept only its message, read as any failure, and set the account aside; the refusal's code now survives translation. TestRefusalAfterThinkingFailsOver and TestThinkingHeldLonger fail without the change. yetone 2026-10-01 03:52:23 +08:00
  • 4e63e98359 gateway: a plugin's provider with several accounts fails over as a built-in's subscription does (别忘了同时添加多个账号、设置路由组、自动故障转移、额度不够时的转移、显示额度) — a test of it end to end, through the plugin host and a fake vendor: three accounts signed in in magpie, all on; one answering a quota 429, a quota error in the stream before any content, or a 401 hands the request to the next and rests, the 401 marking it lapsed; one whose five hours are used up for a model, as the plugin's usage says, is weighed last for that model even while in use, and first for a model its window doesn't count; a routing group of the plugin's model and another provider's answers from the other when every account of the plugin is out. It fails with the account's allowance asked of any agent but the plugin's provider's. yetone 2026-10-01 03:54:19 +08:00
  • 14e80e3155 gateway: the trace tells a moved provider's account as its provider's — a plugin's account went out with agent "plugin", so a moved Grok's plan read as "signed in" rather than as the built-in's. It now carries the provider's id. TestTraceNamesMovedAccount fails without the change. yetone 2026-10-01 03:36:46 +08:00
  • d4817bea56 plugin: a moved provider goes through its own proxy, and each account through its own (#237) — a plugin's fetches and usage went through magpie's global proxy whatever the provider or the account was set to. Go now hands the host the proxy ctx names, and host.js gives every fetch made for it Bun's proxy option; "direct" goes through none. Bun reads *_PROXY once and puts every fetch through them, so the host is started with them as MAGPIE_*_PROXY and applies magpie's itself to a fetch with no proxy of its own. A plugin sign-in's usage looks its proxy up under the provider's id, not "plugin:<id>". TestPluginProxy and TestMovedLoginProxy fail without the change. yetone 2026-10-01 03:35:33 +08:00
  • aed5e30d43 providers: a built-in moved onto its plugin keeps its place among the accounts — the plugins' accounts were listed after every built-in, so a moved one dropped to the end of the providers list, and of the order routing and the agents' model lists follow. One a built-in was moved onto now stands where the built-in stood; a plugin's own provider still goes last. TestMovedAccountKeepsItsPlace fails without the change. yetone 2026-10-01 03:28:59 +08:00
  • 8756ece70c plugins: a plugin's model is priced only when the plugin prices it, and says whether it takes images when the plugin says — OpenCode prices a model it has no price for at 0, as the plugins give their plans' models, and a 0 price made each plugin model the cheapest where magpie picks by price (a small model to search or describe images with, one to draw with) and showed it free. A price of 0 is none now. A model the plugin (or models.dev) says takes images, or doesn't, carries that answer (ImageInput), as a built-in's list did; one it said nothing of stays unknown. TestPluginCatalogPriceAndImages and TestFakePlugin fail without the change. yetone 2026-10-01 03:27:42 +08:00
  • db024bcd50 gateway: a Command Code Go conversation moved onto its plugin keeps its reasoning — the built-in replayed each assistant turn's reasoning to /alpha/generate, and the chat request built for the plugin carried reasoning_content only to DeepSeek, so the plugin, which reads it, had none to replay. Command Code's plugin gets it too. TestCommandCodePluginReasoning fails without the change. yetone 2026-10-01 03:23:20 +08:00
  • 4157b279f9 gateway: Cursor moved onto its plugin is told fast mode, as the built-in told Cursor — the chat request built for a plugin never carried service_tier, and Cursor's plugin reads fast mode there, so a fast request went at the normal tier. A fast chat request to Cursor's plugin says service_tier "priority"; no other chat upstream is told it. TestCursorPluginFast fails without the change. yetone 2026-10-01 03:22:49 +08:00
  • c1d86e2ed1 gateway: a moved provider counts a prompt's tokens by estimate, as its built-in did — count_tokens estimated for Cursor, Grok, Devin, Kiro, Qoder, Zed, Factory and a Command Code Go key by their agent, which a moved one's is "plugin", so the count went to the vendor through the plugin (Factory's to its API). A plugin's provider moved from one of them estimates; Command Code's whatever its plan, as only the plugin knows a Go key. The fake plugin takes $FAKE_ID to stand as a built-in's. TestMovedCountTokensEstimated fails without the change. yetone 2026-10-01 03:21:12 +08:00
  • cb9a6c0872 providers: a moved provider's models are the ones its plugin lists — Available read the list last fetched under the provider's id first, and a built-in moved onto its plugin left its own there, so the moved provider kept offering the built-in's last models whatever the plugin listed. A plugin's provider reads no fetched list; Fetched says none either. TestMovedProviderModelsArePlugins fails without the change. yetone 2026-10-01 03:18:52 +08:00
  • 696d844c88 gateway: Grok moved to its plugin searches the web by itself, as the built-in did — searchesItself knew Grok by its account's agent, which a moved Grok's is "plugin", so its Responses requests went to magpie's own searcher. It knows Grok by its id now. TestMovedGrokSearchesItself fails without the change. yetone 2026-10-01 03:16:17 +08:00
  • bd5ea31f7c gateway: a plugin account run out is asked its allowance again as the plugin's provider keeps it — a limited or full plugin account staled "plugin"/user, which no usage is kept under, so the router trusted the allowance it had and the account's rest was marked as "plugin"'s; both now go by UsageAgent ("plugin:grok"). A moved Grok's usage is kept as plugin:grok's, so the built-in's per-home branch needs nothing. TestPluginProvider fails without the change. yetone 2026-10-01 03:14:45 +08:00
  • d8f2e17dd7 plugins: a plugin's fetch gets its body as a string, as OpenCode hands it — the host passed a Buffer, and the plugins that reshape a request (Grok, WorkBuddy, MiMo) touch only a string body, so a moved provider's requests went out as the gateway built them. A UTF-8 body now goes as a string; one that isn't stays bytes. TestFakePlugin fails without the change. yetone 2026-10-01 02:53:12 +08:00
  • a170b909c9 plugins: a moved built-in's plugin comes up to date with magpie, as the built-in did — the fixes that bring each plugin in line with its built-in (plans, windows, lapsed sign-ins, refusals, bodies in bytes) are in @magpie-community's new releases, but a plugin was updated only by a click in Plugins, so an account moved before kept the old one. The magpie serving the gateway now updates, a little after it starts and every hour, the plugin of each built-in moved onto one to the version its move needs, and a move needs those versions: mimo 0.1.4, workbuddy 0.1.4, grok and qoder 0.1.2, the rest 0.1.3. One turned off, run from a folder or moved back is left alone. TestKeepMovedCurrent fails without the change. yetone 2026-10-01 03:34:22 +08:00
  • e332451169 plugins: the market lists magpie's community's plugins alone (来自 OpenCode 社区的插件可以删掉了,因为质量不行) — the section of the OpenCode community's plugins is gone, from the list built in, the community repo's registry and any copy fetched before; one is still a search away on npm, and one installed keeps its vendor's icon. TestBuiltinMarket, TestMarketSources, TestMarketIcon and plugin-market.test.cjs (Chromium, WebKit, en/zh) fail without the change. yetone 2026-10-01 03:26:51 +08:00
  • 566ae09db1 plugins: a moved provider's accounts keep what the built-in's had (你确保插件版的订阅 provider 和内置的一模一样了吗) — each account of a plugin provider has its own plan's models, not the first account's; a move carries each account's plan and a lapsed mark; a usage read that finds the sign-in gone marks the account and a clean one clears it, a network failure shows the last reading; a plugin that fails to load keeps its providers rather than taking them away; Kiro's API key is named and an OAuth account beside it stays off as in the built-in; Command Code Plan keeps its name. TestUnloadedPluginKeepsProviders, TestPluginUsageLapse, TestPluginAccountModels, TestMovedProviderName, TestKiroMover and the move test fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./internal/provider ./internal/plugin ./internal/gateway pass. yetone 2026-10-01 03:22:54 +08:00
  • 04805abf39 agent: MiniMax Code (#362) — MiniMax's mcode CLI (and its desktop app, same runtime) reads $MINIMAX_DATA_DIR/config.yaml, else ~/.minimax/config.yaml. Choosing a magpie model adds custom_provider.magpie there (the gateway, spoken to as Anthropic messages, with the catalog's models, efforts, limits and image support) and sets defaultModel to custom_provider:magpie/<model>; the user's own default and variant are kept and put back on reset, their comments, providers and keys on magpie's entry stay, and an emptied custom_provider goes. The Library installs skills into its skills folder; it reads no user-wide MCP file, so it gets no MCP target. Checked against @minimax-ai/code 0.5.10 in a sandbox HOME: mcode provider list shows magpie's entry and mcode exec reaches a fake upstream through it with magpie's key, model and effort; after a reset it loads the restored file. TestMiniMaxCode, TestMiniMaxCodeSync, TestMiniMaxCodeLeavesNoEmptyProviders, TestMiniMaxCodeDataDir and TestMiniMaxCodeSkills fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (TestUserPath and the Claude account tests pass alone). yetone 2026-10-01 03:24:29 +08:00
  • 71a4da187c library: while the Library loads, the page is drawn as it will be (资源库的加载动画有点草率) — it was one card of four blank bars, each shimmering on its own, with no tabs, and the page jumped when the library came. Now the real tabs are there at once (the last one open picked, and one can be picked while waiting, drawn in its own outline and kept), the Library folder waits, and the open tab's rows are in outline: an icon, a name and a path of varying lengths, a switch where the switches will be, the Instructions card and its Agents heading. The outline fades in only after 180ms, so a quick load goes straight to the page, and one sweep of light crosses every bar together; none with reduced motion. The tabs don't move when the library comes, only gain their counts. The header is one function for both. library-loading.test.cjs (Chromium, WebKit) fails without the change; library-all, library-items, library-toggle-status, import-all-skills, own-skill, market-have, old-webkit pass; click-scroll's WebKit Routing case fails now and then on main as well. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass. yetone 2026-10-01 03:20:32 +08:00
  • 6a6c5aa3e2 gui: omp-roles' and panel-effort's fake APIs answer /api/plugins as the other tests' do (#363) cyxer000 2026-10-01 03:21:03 +08:00
  • df019e18e7 zcode: an old plan with no monthly cap is no longer taken as used up (#366) — the quota reply's TIME_LIMIT is the month's MCP tool calls, which ZCode only shows and never stops the models on, but magpie read it as the account's monthly allowance, so an old plan reporting it at 100% had its ZCode models skipped with the 5 hours full. It is now shown as MCP · Month and set aside, as a pasted Zhipu key's already was, and a limit whose whole is 0 (no cap) counts as unused. TestZCodeNoMonthlyCap fails without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (the Claude account tests pass alone). yetone 2026-10-01 02:58:29 +08:00
  • 49f40b463f Configure per-model context windows and output limits (#279) Comic Chang 2026-10-01 02:14:22 +08:00
  • 94ba560257 plugins: a move installs the plugin as it now matches its built-in (插件版…保持一模一样) — each mover asks for the version published with the parity fixes (WorkBuddy 0.1.3; Command Code, Cursor, Devin, Factory, Kiro, MiMo, Zed, ZCode 0.1.2), updating an older one first, so a failed sign-in says why, a CLI's own account follows its key, refusals read as the built-in's. ZCode's own sign-in on its session alone (the Start Plan) no longer stops the move: zcode-auth 0.1.2 reads ZCode's credentials anew for each request, the session ZCode renews included, so the account goes marked as ZCode's and with no expiry of its own. TestCursorPluginContext and TestMoveDevin no longer lean on the machine: the first seeds its catalog (it failed wherever models.dev's cache wasn't there), the second waits for the fake CLI however loaded the machine. TestZCodeMover fails without the change. Each package installed from npm in an empty HOME comes at the version asked. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass but for TestUserPath and TestClaudeSignedOut, 5s timeouts under the whole run's load that pass alone. yetone 2026-10-01 02:12:42 +08:00
  • 44720c6190 gateway: Claude Code's WebSearch keeps its metadata through a relay that serves only Claude Code (#359) — a request carrying web_search_20250305 to an Anthropic endpoint other than api.anthropic.com is built again rather than relayed, and the rebuilt body dropped metadata (user_id); a relay limited to the official Claude Code client turned it away with 403. The client's metadata now goes on as sent when an Anthropic request is built for an Anthropic upstream (Bedrock still gets none, as on the relay path, #176). TestClaudeCodeWebSearchKeepsMetadata fails without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (Claude account tests and TestMoveDevin pass alone; TestCursorPluginContext fails on main since 1ce05f0). yetone 2026-10-01 02:12:35 +08:00
  • 1927f82c01 Fix model reasoning-level list jumping to top (#357) 2026-10-01 01:48:05 +08:00
  • 4f9acf72a4 subscriptions: Qoder CN, for accounts on qoder.cn (#349) — Qoder's China site (qoder.cn, Alibaba Cloud or phone sign-in) has its own accounts, sign-in page, account API (openapi.qoder.com.cn) and gateway (gateway.qoder.com.cn), so a qoder.cn account couldn't sign in through magpie's Qoder, which only knows qoder.com. A new Qoder CN subscription signs in there with the client id Qoder CN's own CLI sends, and everything after — polling, job token and refresh, user info, models, usage and chat — follows the site saved with the account; if qoder.cn refuses the job token, the account chats with its device token and renews it, as that CLI does. Qoder's tile is now Qoder (international), each tile saying which accounts it is for. Accounts saved before keep working on qoder.com unchanged. Not tried with a real qoder.cn account. TestSites, TestCNDeviceChatRefresh, TestQoderCNSignIn, TestQoderCNDeviceChat, TestQoderGlobalUnchanged and TestQoderCNGateway fail without the change; qoder-cn-tile.test.cjs (Chromium, WebKit, en/zh) added. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass but for TestCursorPluginContext, which fails on main (1ce05f0) as well; click-scroll, old-webkit pass. yetone 2026-10-01 01:36:13 +08:00
  • ba3c26dec4 providers: a Remote magpie provider uses another computer's shared magpie, each request translated at most once (Jorben on Discord: 远程 magpie / magpie 接力) — a custom provider pointed at another magpie has one API per address and couldn't know which API each model's own provider serves, so a request was translated on both computers (Chat → Messages here, then again there). magpie's /v1/models now tells each model's native_endpoints (the APIs its provider serves it on; none for a routing group) and its image input, and reads them, with max_output_tokens and supported_reasoning_levels, from a list; the new remote-magpie preset takes the other magpie's address however typed (host:port, /v1, /v1/messages) for all three APIs and lists all its models, its user's choice already. Add sheet tile with the address field and a hint to Settings → Share on local network; CLI: magpie provider add remote-magpie <key> url=http://<ip>:3425. Checked with two sandbox magpies over the LAN address with the key check on and a Messages-only fake upstream: Chat, Messages (streamed), count_tokens, Responses, a routing group and Gemini all reached it as /v1/messages, translated once. TestRemoteMagpieNativeAPI, TestFetchMagpieFields and TestRemoteMagpie fail without the change; remote-magpie.test.cjs (Chromium, WebKit, en/zh) added. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass but for TestCursorPluginContext, which fails on main (1ce05f0) as well; click-scroll, old-webkit pass. yetone 2026-10-01 01:26:45 +08:00
  • f1299714bf agents: Claude Code's effort reaches Opus 5.5 and Sonnet 5.5, follows each model's levels, and gets an ultracode switch (#351, #352, #353, #354) — Claude Code 2.1.251 on reads Opus 5.5's, Sonnet 5.5's and any newer Claude's effort only from modelSettings.<model>.effortLevel, so the top-level effortLevel magpie wrote left them at medium; it now writes modelSettings for the model (and the top key for the models that still read it), and a reset takes out only its own level. The levels offered follow what Claude Code 2.1.285 sends each model: Opus 4.5 low–high, Opus/Sonnet 4.6 without xhigh, Haiku 4.5, Sonnet 4.5 and older none; a level a model doesn't take is refused. A new ultracode square writes "ultracode": true, on models taking xhigh, and magpie claude ultra no longer writes "ultra" as the model. An open session keeps the effort it started with, so a change says to restart it while Claude Code runs. Checked against real Claude Code 2.1.285 in a sandbox HOME with a fake API recording the effort sent. TestClaudeEffortModelSettings, TestClaudeEffortPerModel, TestClaudeUltracode and TestClaudeEffortNotice fail without the change; claude-effort.test.cjs (Chromium, WebKit, en/zh) added. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; omp-roles, panel-effort, click-scroll, old-webkit pass. yetone 2026-10-01 01:16:04 +08:00
  • 1ce05f0270 plugins: a plugin's models show as the built-in's did (插件版…保持一模一样) — a model a plugin says its plan serves at no cost (WorkBuddy's x0.00 credits) is marked free, as the built-in marked it; Cursor's plugin models not named 1M hold what the catalog knows their base to (GPT-4o 128K, Kimi K2 131K), not Cursor's 200K, as the built-in's list; ZCode's own account moves marked as ZCode's, for the plugin (0.1.2) to read ZCode's own sign-in for each request and follow its switches, and comes back as ZCode's own with nothing saved. TestPluginUsage (free), TestCursorPluginContext and TestZCodeMover fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-10-01 01:18:01 +08:00
  • 1ec5495b26 agents: omp's roles pick their own models (subagents, smol, slow), keep their thinking level, and get back what they had before magpie (#325) cyxer000andyetone 2026-10-01 01:15:55 +08:00
  • 4ead7c84a3 gateway: Codex's Responses Lite tools reach SuperGrok and every other backend, and a group moves on when a member can't read a request (#350) — Codex sends a Lite model's tools as an additional_tools input item, its own functions in a "functions" namespace; magpie relayed the item to xAI, which 422s on it (unknown item type), and translated routes (Cursor, Anthropic, Chat…) dropped it, so the model had no tools. Outside OpenAI the item's tools now go in tools, the functions namespace opened into plain tools and earlier calls un-namespaced; OpenAI and the ChatGPT account still get Codex's own form. A 400/422 over the request's shape (failed to deserialize, unknown item type/parameter…) now moves to the group's next member, each asked once, the member not resting; the Routing page says so. TestAdditionalToolsRelayed, TestAdditionalToolsTranslated and TestGroupFailsOverARequestShape fail without the change; routing-shape.test.cjs (Chromium, WebKit, en/zh) added. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; click-scroll, old-webkit, routing-wb-refused pass. yetone 2026-10-01 01:05:22 +08:00
  • c47b22ee27 agents: "Hide all" in an agent's model list keeps its line, and an uninstalled Gemini CLI goes from the Agents page (#356, #230) — the line under an agent ("Showing 0 / N models") came only when a picker still listed one of magpie's models, so hiding them all took away the one way back; it now stays while any is hidden. Gemini CLI was taken as present from what it leaves in ~/.gemini (settings.json, .env, installation_id…), which stays after it is uninstalled, so its row stayed, offering to set up a CLI that can't run; it is now its gemini binary. TestAgentModelLineAllHidden and TestGeminiNotAntigravity fail without the change; agent-models-all-hidden.test.cjs (Chromium, WebKit, en/zh) added. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./internal/agent ./internal/gui ./internal/library ./internal/provider pass; agent-models, click-scroll, old-webkit pass. yetone 2026-10-01 00:56:00 +08:00
  • ee5b1b7d44 plugins: a plugin's account behaves as its built-in's (the user: 插件版的订阅 provider 和内置的…保持一模一样了吗) — a plugin's failed sign-in now says why ("the sign-in failed: the sign-in page expired") instead of a bare failure; a plugin account the provider refuses with 401 is marked lapsed, "<user>'s <provider> sign-in has expired — sign in again", beside the account and on its usage card as a built-in's is, and the mark goes when it answers again or is signed in anew; a Devin or Command Code account taken from the agent's CLI moves to the plugin marked as the CLI's and back as the agent's own, so the one it follows stays the one the CLI is signed in to. TestPluginProvider (lapsed), TestMoveSideState (cli) and TestPluginSignIn (reason) fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-10-01 01:00:04 +08:00
  • 424ff31a46 provider: the Providers and Gateway pages no longer wait on claude --version (deluxe on Discord: on Omarchy the two pages never loaded) — on Omarchy claude is a mise wrapper that installs or updates Claude Code before it answers, which on a slow network takes minutes or never ends; magpie asked it with no limit and with a lock held, so /api/providers (fetching the Claude account's models) and every Claude request waited with it. The CLI is now asked in the background, given a minute, and a caller waits at most 3s before the version it has stands in; a late answer is taken once it comes. Reproduced on an Omarchy VM (/api/providers unanswered after 100s on v0.1.516, 3.7s with the change). TestClaudeVersionDoesNotWaitForAStalledCLI and TestClaudeVersionTakenWhenItComes fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-10-01 00:46:46 +08:00
  • 4a0fbc332c plugins: a built-in moved onto its plugin looks and works as it did (你确保插件版的订阅 provider 和其对应的内置的…都保持一模一样了吗?) — moved onto its plugin, a built-in lost pieces: its tile's name, icon, plans and risk note went to the plugin's own, "Add account" still opened the built-in's sign-in (in the app, on the server and in magpie accounts add), an agent's own sign-in the built-in still found showed a second usage card of the same account, the account's plan badge went, WorkBuddy's daily check-in stopped, the provider's icon and site were the plugin's, WorkBuddy AI's card was named WorkBuddy, and Devin, which had no card of its own, lost the plugin's. Now a moved built-in keeps its tile and risk sheet and signs in through its plugin; its cards take the built-in's place and name, and it has none of its own; the plan the plugin tells stays with the account; WorkBuddy checks in through the plugin, which signs the call; a card is left out only where its built-in's slot showed it. TestMovedBuiltinQuiet, TestWorkBuddyCheckinThroughPlugin, TestMoveToPlugin (Devin-like card) and TestPluginUsage (plan kept) fail without the change. Command Code and Devin moved and back in a sandbox HOME: one card each, plan, name. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; plugin-move, plugin-signin, commandcode-risk, old-webkit pass; click-scroll's WebKit fails the same on origin/main under this load. yetone 2026-10-01 00:40:21 +08:00
  • 139cc6590a gateway: a Claude Code run whose subagent ended on StructuredOutput is let go, and runs left waiting on tool calls are bounded (#345) — a workflow's subagents end on StructuredOutput, which the client answers itself, so the bridge's claude -p waited 30 minutes for a result that never came, one process per subagent. Such a run now waits 30s (for a schema error the client sends at once) and ends; of other runs waiting 5 minutes or more on their caller's tools, 16 are kept, the longest waiting let go first (one that then gets its results starts anew with the whole conversation). TestClaudeRunEndsAfterStructuredOutput and TestClaudeParkedRunsAreBounded fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-10-01 00:40:01 +08:00
  • f3b45634a3 agents: Droid, Qoder, OpenHanako, WorkBuddy, OpenCode and ZCode no longer get an output limit above the model's context window (#347) cyxer000 2026-10-01 00:27:00 +08:00
  • abbffd73a4 agents: magpie omp auto sets omp's thinking to auto, and the panel's effort slider shows a level it doesn't list as it is (#339) cyxer000 2026-10-01 00:20:19 +08:00
  • 49f02c6f03 agents: omp's requests through magpie are known for omp's on omp 16 too (#343) cyxer000 2026-10-01 00:19:49 +08:00
  • 110567472d edit: a config that is a hard link stays one when magpie saves or clears it (#328) cyxer000 2026-09-30 23:36:01 +08:00
  • 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. yetone 2026-09-30 23:08:47 +08:00
  • adde88ef23 agents: Kimi Code offers a model's thinking levels, and the level picked reaches the model (#333) — the new Kimi Code (2.x) builds its thinking picker from a model's support_efforts and default_effort, which magpie never wrote, so it offered thinking only on or off. magpie now writes the model's levels (none left out: Kimi Code's Off is that) and default_effort high when the model has it, to ~/.kimi-code only; the old kimi-cli's schema has neither. Kimi Code sends the level inside thinking ({"type":"enabled","effort":…}), not as reasoning_effort, so the gateway moves it there on a Chat request that doesn't say reasoning_effort itself, and fits it like any other agent's. Checked with the real kimi CLI (2.1.1) in a sandbox HOME against a fake upstream: kimi doctor passes, /model shows Off Low Medium High Max, a pick reaches upstream as reasoning_effort; unknown values don't make it reject the file. TestKimiEfforts and TestKimiCodeEffortReachesChatVendor fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 22:58:50 +08:00
  • f5f10bda4d plugins: a plugin's accounts show their allowance as the built-ins' do (the user: 所有插件要完整支持显示额度!跟内置一模一样!) — a plugin's auth.usage now tells plan, user, until, renew, balance, resets (count, until, by window, five hours, weekly) and windows (used past 100 when overspent, resets at/in, display, span, the models a window counts or leaves out, aside), and magpie shows them on the usage page, in the menu bar, beside each account and to the gateway, which passes over an account used up for the model asked; a built-in moved onto its plugin keeps its card's name and icon. Also: Command Code's subscription endpoint answering 200 {"success":false} was read as "No plan" by the built-in (and the plugin), it is now unread; a moved Devin was listed twice, the built-in still finding the Devin CLI's own sign-in; and moving back left the plugin's rows in logins.json, listed as empty accounts. Checked in a sandbox HOME with real Command Code and Devin accounts moved onto the community plugins (0.1.1): GOAT, its period, 5 hours / Weekly / Credits for Command Code, Teams, balance and Daily/Weekly for Devin, the same on the built-in after moving back, no plugin rows left. TestPluginUsage, TestCommandCodeSubscriptionUnread and TestMove (the plugin's rows after moving back) fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (TestClaudeSignedOut and TestUserPath timed out once at load 22, pass alone). yetone 2026-09-30 22:53:46 +08:00
  • 6035cf99c8 agents: omp keeps magpie while a fallback chain or another role is on it, and a provider renamed takes those along (#340) cyxer000 2026-09-30 22:58:42 +08:00
  • b60cfa6787 agents: omp, Pi, Cline and dsh are no longer told a model writes more than its window holds (#338) cyxer000 2026-09-30 22:58:08 +08:00
  • a9ff84fd80 accounts: a Claude account's usage-limit resets show on its card, and can be used, by hand or by themselves (StringKe on Discord: claude-code usage 里有 reset) — magpie read Claude usage without the resets. It now asks as Claude Code does (/api/oauth/usage?cedar_ember=1&skip_spend=1) and shows ↺ N resets · until … on the card and panel. "Use a reset" spends the grant Anthropic names next through POST /api/organizations/{org}/reset_rate_limits, as Claude Code's /limit-reset does, the organization read from /api/oauth/profile; Auto-use (off by default, per account) spends one only when the account's whole week is used up, every other candidate is resting and the grant clears seven_day, at most one a week. The routing page labels an automatic one. Checked against fake servers with the user's JSON, never against Anthropic. TestClaudeGrants, TestClaudeResetsOnCard, TestUseClaudeReset, TestAutoUseClaudeReset, TestClaudeAutoReset and claude-resets.test.cjs (Chromium, WebKit, en/zh) fail without the change; codex-auto-reset, routing-auto-reset, click-scroll, old-webkit pass. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 22:53:34 +08:00
  • 69b366adec omp: each model is asked on its provider's own API (#329) — magpie wrote every model into omp's models.yml as openai-completions, so a Claude's thinking signatures had no place between tool turns. As for Pi, a Responses model now gets api: openai-responses and an Anthropic one api: anthropic-messages at the gateway's /v1/messages, thinking adaptively on Claude 4.6 and later, else on a budget (budget-effort would send output_config.effort, which Sonnet/Haiku 4.5 refuse); groups and the rest stay on Chat. A model offering max made omp 16.3.5 reject the whole file, so every magpie model vanished; max is now offered as xhigh, which the gateway fits to max. Checked with the real omp 16.3.5 in a sandbox HOME against a fake upstream: Claude → POST /v1/messages, deepseek → /v1/chat/completions. TestOmpModelsAskedOnTheirNativeAPI fails without the change; TestOmpMessagesRelayedAsSent guards the relay. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 22:27:09 +08:00
  • b03967bb79 library: agents in a running WSL distro take skills, MCP servers and instructions (#331) — the Library knew only this machine's agent ids, so codex@wsl:Ubuntu and the like were never offered, and the id's colon was refused as an agent's name and can't be in a Windows file name. Claude Code, Codex, Pi and OmO in a distro now get them at their default places under the distro's $HOME through \\wsl.localhost, only while it runs (opening a stopped one's files starts it; its state is kept and asking for it says to start it). Skills go in as copies, made beside and renamed into place and made again when the library's changes, since a Linux agent can't follow a link to a Windows folder (project skills share the same copy code); an MCP server that runs a Windows program (C:\…, *.exe/.cmd/.bat/.ps1) is refused for them with a message; Pi there gets no MCP servers, where its version decides the file. The id's colon is a dot in file and folder names, and setup export/import turns it back. TestWSLTargets, TestWSLSkillsCopied, TestWSLServers and TestWSLInstructions (a fake distro) fail without the change. go vet (and GOOS=windows for agent, library), go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. Not run against a real distro. yetone 2026-09-30 22:17:23 +08:00
  • 007a84964a agents: omp takes magpie's vision models for text-only (#327) cyxer000 2026-09-30 22:13:50 +08:00
  • ad90eced2b claude: every 1M model magpie writes for Claude Code is marked [1m] (StringKe on Discord: Autocompact is thrashing on Opus 5.5 with a Max subscription) — Claude Code 2.1.284 and before takes any Claude model not named with [1m] for 200K, CLAUDE_CODE_MAX_CONTEXT_TOKENS or not (it applies that only to models it doesn't know), and compacts at 160–190K over and over; magpie marked only its picker's options, and only when it knew the window, so a model typed, or picked while the window wasn't known, went into ANTHROPIC_MODEL, model, every tier and CLAUDE_CODE_SUBAGENT_MODEL bare. Each is now marked when magpie's list or models.dev gives a window of 1M or more. Checked with /context and full sessions of 2.1.280–2.1.285 in a sandbox HOME: unmarked compacted 3 times at 190K, marked 0. TestClaude1MMarked fails without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 22:11:08 +08:00
  • ed5b3da53a library: an All chip gives an MCP server or skill to every agent at once (StringKe on Discord: 一个个点太麻烦) — each row of the Library now leads its agent chips with All: one click turns the item on for every agent that can take it (those with no MCP file, or no SSE for an SSE server, are skipped; agents hidden on the Agents page keep what they have), and once all have it a click takes it off all. It is one call to the same servers/agents or skills/agents endpoint as a single chip, so the row isn't redrawn and nothing scrolls; a partial failure says on how many it took and names the first refusal, and the refused chip carries its dot. Shown only where two or more agents can take the item. library-all.test.cjs (Chromium, WebKit, en/zh) fails 14/14 without the change. library-all, library-toggle-status, library-items, shared-skills, old-webkit, click-scroll pass (70); go test ./internal/gui passes. yetone 2026-09-30 22:07:21 +08:00
  • d1491a43e8 gateway: X-Magpie-Account pins a request to one account of a subscription (gakki on Discord: 想单独测某个账号) — a subscription with several accounts took any of them in turn, so a probe of one account could be answered by another. The header (the account's email or login, or its id on the Routing page) narrows the request to that account alone: an unknown one is a 404 naming the accounts there are, one whose plan lacks the model a 400, one resting a 429 with until when, and nothing else is tried in its place (nor a Codex reset spent by itself). Pooled Codex accounts are pinned the same through /backend-api; the header is never sent on to the vendor, and the Routing page's trace records it. TestAccountPinned, TestAccountPinnedUnknown and TestAccountPinnedResting fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (TestClaudeAccountNamedAsItsLogin timed out once under load, passes alone). yetone 2026-09-30 22:02:09 +08:00
  • e92994b37a agents, library: Antigravity alone no longer shows Gemini CLI (#330), and turning an agent off on a skill or MCP server says it was removed (#332) — Gemini CLI was found from ~/.gemini existing, where Antigravity keeps its own folders (antigravity, antigravity-cli, config) and reads GEMINI.md; it now takes only what Gemini CLI writes there (settings.json, .env, google_accounts.json, installation_id, trustedFolders.json, mcp-oauth-tokens.json, an oauth_creds.json its own OAuth client minted, as #143) or a gemini on PATH. The Library's agent chips said 「已写入 X」 on the way off too; they now say 「已从 X 中移除」 (or N agents, or N updated for a mix). TestGeminiNotAntigravity and library-toggle-status.test.cjs (Chromium, WebKit, en/zh) fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; library-items, shared-skills, click-scroll, old-webkit pass. yetone 2026-09-30 21:57:06 +08:00
  • d1ec1cdf62 usage: a Codex account can spend one of its rate-limit resets by itself once its week is used up (StringKe on Discord: 账号里有 Bank Reset 的重置次数,可以自动使用 — 七天全部用完的时候重置) — off by default, turned on per account with Auto-use beside Use a reset (Usage page, panel) or magpie quota auto-reset <account> on. It fires only when every other account a request could go to is resting, fresh usage shows the weekly window used up (the 5 hours' being full never counts: a reset starts both, and five hours pass on their own), the account holds one, and none was spent by itself this week (kept in codex-autoreset.json across restarts); it spends the one expiring first, lifts the rest and asks once more, and on nothing_to_reset/no_credit/error ChatGPT's own 429 goes to the agent. Both the pooled accounts and Codex's own sign-in are covered; each use shows on the Routing page and in the request log. TestCodexAutoResetOneAccount, TestCodexAutoResetAfterEveryAccount, TestCodexAutoResetNot, TestWeekUsedUp, TestAutoResetKeptPastRestart, codex-auto-reset.test.cjs and routing-auto-reset.test.cjs are new; the gateway and GUI ones fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; click-scroll, old-webkit, tray-usages pass. yetone 2026-09-30 21:35:35 +08:00
  • 3bec6c0e40 providers: a built-in subscription moves onto its community plugin and back, its accounts with it (the user: 慢慢下掉内置的那些 Subscription Provider…不要让用户一升级完之后,突然发现他的所有服务都不可用了) — eleven built-ins (Zed, Qoder, Factory, MiMo, Devin, Grok, Command Code Plan, Cursor, Kiro, WorkBuddy, ZCode) each get a mover to their @magpie-community package. A move installs the plugin (updated when older than the mover needs), hands it every account in the plugin's shape, checks the plugin lists models for them, and only then lets the plugin serve the same provider id, so agents' model ids don't change; any failure rolls back and the built-in keeps serving. The built-in's accounts are kept as a backup, and "Run built-in again" (magpie plugin move-back <id>) takes the plugin's current sign-ins back, never copying a rotating token: they are taken out of the plugin in one step, and an account the built-in renewed meanwhile keeps its newer token. An account only the plugin can hold (Cursor's browser sign-in) stays with it. The provider editor shows "Runs on" with the button, a failed move's reason, and the CLI has magpie plugin move / move-back. Automatic moves (Retiring) are wired in but the list stays empty until the packages are on npm. Checked with real accounts in a sandbox HOME: Command Code Plan and Devin moved, answered a chat through the gateway on the plugin, moved back and answered again on the built-in. TestMove*, TestPutBackKeepsNewer, the movers' round-trip tests and plugin-move.test.cjs (Chromium, WebKit, en/zh) are new. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; click-scroll, old-webkit pass. yetone 2026-09-30 21:14:00 +08:00
  • d1b6c119c7 ci: the UI preview's planner uses deepseek-flash instead of deepseek-v4-pro (PLAN_MODEL still overrides) — asked for by the maintainer. Checked against DeepSeek's API: deepseek-flash answers the planner's JSON mode (response_format json_object) with a valid plan; it reasons first (~1k tokens on a small plan), well inside the planner's max_tokens 16000. yetone 2026-09-30 21:15:51 +08:00
  • eb3a0745e1 gateway: a rate limit that counts tokens reaches the agent as a rate limit, not as "prompt is too long" (StringKe on Discord: Autocompact is thrashing, /goal stops as context limit reached) — tooLongRe's "too many tokens" also matched Bedrock's 429 "Too many tokens, please wait before trying again." and Cerebras's per-minute limit, so magpie told Claude Code its conversation no longer fit; Claude Code compacted, hit the limit again a turn later and compacted again, three times, then gave up as thrashing. A 429, or an error in rate wording (rate limit, per minute/hour/day, TPM/TPD, please wait, try again later, throttled), is now passed on as the limit it is. TestRateLimitNotContextOverflow and TestRateLimitReachesClaudeCodeAsRateLimit fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 21:12:24 +08:00
  • 52c8e838d2 providers, sign-in, tray, plugins: four of StringKe's reports on Discord — (1) Removing a provider left its editor open and listed, and a second Remove said there was no such provider: the removal had been made, but moving the agents off its models failed on one agent whose config couldn't be written, and Reseat returned that as the change's error; now such an agent is a move with its error ("still on X, not moved: …", a warning in the panel, a line in the CLI and TUI), the others are moved, and the panel, told a delete failed, re-reads the list and closes the editor when the provider is gone. (2) The sign-in waiting sheet shows the sign-in link itself, selected whole on a click, with a copy button, for a browser other than the one that opens. (3) A subscription with several accounts offers "Account in use" among the menu bar's usages, following the account the gateway goes to first. (4) The Antigravity plugin's sign-in never started: magpie called every plugin's authorize with an inputs object, the way OpenCode's CLI does, and opencode-antigravity-auth then asked its Project ID on the terminal — magpie's stdin — until the minute ran out; inputs now go only to a method with prompts, as OpenCode's TUI passes them (checked against the real package under Bun in a sandbox: the Google sign-in URL comes back at once). TestReseatUnmovable, TestTrayInUse, TestInUseOf, TestAuthorizeNoPrompts, provider-remove.test.cjs, signin-link.test.cjs and tray-inuse.test.cjs fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; click-scroll, old-webkit, tray-usages, plugin-signin, signin-callback, factory-sub pass. yetone 2026-09-30 20:45:19 +08:00
  • 901ee08280 Count usage at the configured provider/model price (#278) Comic Chang 2026-09-30 20:31:11 +08:00
  • 8124d3f927 edit: a config kept as a symlink stays one when magpie saves or clears it (#323, jigaowan) — WriteAtomic wrote a temp file beside the path and renamed it over it, so a linked library.json, instructions.md, CLAUDE.md, settings.json or config.toml became a file of its own and the dotfiles target kept its old text; clearing instructions.md removed the link. Now a write goes to the file at the end of the links (the one it names when nothing is there yet, an error for a loop of links), keeping its mode, and clearing a linked file empties its target and keeps the link (Pi's migrated mcp.json stays as {}); a plain file is removed as before. Sign-ins and the Kiro/StepFun files magpie writes privately follow links the same way, and a failed edit rolled back deletes only what it made behind a link to nothing. TestWriteAtomicFollowsSymlink, TestRemoveKeepsSymlink, TestAtomicallyKeepsSymlink, TestLinkedFilesStayLinked and TestPrivateWritesKeepSymlink fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 20:21:24 +08:00
  • 1ba6939185 agents: OpenChamber gets its own row, its model and small model set to magpie's (#321) — OpenChamber keeps its own default model (preferences.json, a copy in settings.json, under $OPENCHAMBER_DATA_DIR or ~/.config/openchamber) and sends it with every session over OpenCode's, so setting OpenCode's model changed nothing it used. Its row writes defaultModel (a fresh updatedAt, defaultVariant cleared as its own settings do) and the small-model override, keeping every other key and refusing a preferences.json it can't read; magpie's provider goes into the OpenCode config it runs on, and stays there while either uses it. OpenCode's config now follows $OPENCODE_CONFIG_DIR: the OpenCode 2 OpenChamber bundles reads only that folder, so what magpie wrote to ~/.config/opencode was never read; OpenCode 1 reads it last, so it wins there too. A project with its own model in OpenChamber is named in the row. Checked against @openchamber/web 2.0.4 on OpenCode 2.0.18 in a sandbox HOME: its settings API returned magpie's model and OpenCode listed magpie's provider. TestOpenCodeConfigDir, TestOpenChamberModel and TestOpenChamberSettingsOnly fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; click-scroll, old-webkit pass. yetone 2026-09-30 20:12:05 +08:00
  • 953bce2cfb agents: Codex signed in with only an API key gets magpie as its provider, its picker listing magpie's models (#322, dakango: switching the Codex app to one of its own models went to OpenAI, 502) — magpie counted an API key in auth.json as a ChatGPT sign-in and only set openai_base_url, counting on Codex to ask the gateway for its models; but Codex asks for none with an API key (models-manager refresh_available_models returns early), so the picker showed Codex's built-in models and the one magpie model, and a built-in one went to OpenAI with the relay's key. Now only a ChatGPT sign-in takes that route; with an API key alone magpie is the model_provider with model_catalog_json listing every magpie model on for Codex, as when signed out, and a sync moves a setup an older magpie wrote; going back to Codex's own model restores the user's model_provider. A Codex model whose OpenAI can't be reached now fails naming the model and what to do instead of a bare 502. TestCodexAPIKeyUsesProvider, TestCodexAPIKeyBaseURLMoved and TestCodexOwnModelUnreached fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 20:05:34 +08:00
  • b63a0f1fd5 plugins: a plugin's provider takes more than one account, as a built-in subscription does (the user: 插件当然要支持多账号了) — a plugin kept one sign-in per provider, and signing in again replaced it. Now each sign-in goes beside the others: plugin-auth.json keeps the first under the provider's id, as OpenCode does (so what is signed in already stays the first account), the rest under id#slot; logins.json lists them as it lists the built-ins' accounts, so the editor shows them all, one first, the others ticked on behind it or off, any made first, any removed (which signs it out). The host runs every request in its account's scope, so a plugin's getAuth, client.auth.set (a refreshed token), loader and provider.models see that account alone; a sign-in to an account already there (the same id, else the same secret) replaces that one's rather than listing it twice. The gateway spreads and fails over across the accounts on, as for the built-ins. Accounts with no id are told apart by the end of their key ("API key …abcd"), else by their slot. Also on the Devin page: the header shows the plugin's icon, and Cognition's opencode-devin is off the market (its gateway answers 404 model_not_found for models and chat). TestPluginAccounts (plugin: per-account requests and refreshes, dedupe, sign-out; provider: first, on/off, switch, forget, labels), TestPluginProvider (gateway: a 429 on the first account goes on the second) and plugin-signin.test.cjs (add a second account in the editor, make it first; fails without the change) are new. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; plugin-signin, plugin-market, old-webkit, click-scroll pass. yetone 2026-09-30 19:58:20 +08:00
  • ef4edf8c58 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. yetone 2026-09-30 19:08:52 +08:00
  • 80737be8d7 gateway: a vendor's Responses API gets Codex's request as Codex sends it to a provider not OpenAI's (#292, @byhooi: Anyrouter's gpt-6-astra answered "invalid codex request" through magpie, and through CC Switch too with its remote compaction on) — Codex decides by its provider's name alone (is_openai: name == "OpenAI") whether to send what only OpenAI takes: each message's internal_chat_message_metadata_passthrough (content_item_kinds, turn_id), a call's encrypted_function_args, stream_options.reasoning_summary_delivery, configuration_update items. CC Switch's remote compaction switch is that name; signed in, Codex keeps its built-in provider, named OpenAI, and comes through openai_base_url, so every request magpie relayed carried them, and a relay that checks it is Codex's turned it away. A relayed Responses request to anyone but OpenAI's API and the ChatGPT backend now goes without them, as Codex itself leaves them out under another name; everything else as it came, byte for byte when none is in it (another client's stream_options stay). Codex's prompts and identity untouched. TestCodexOpenAIFieldsStayWithOpenAI fails without the change (the relay's 400 "invalid codex request"). go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 19:23:34 +08:00
  • 52a0d799d6 routing: a group can be routed by hand, its model picked on its card (#317, @azir12345: pick the channel as CC Switch does) — a group's routing may now be Manual: every request goes to the one member picked (pick in the group's JSON; the first when none or one no longer in it), over that member's own accounts or keys, and the others and the rules wait (kept, not dropped) until another routing is chosen; none takes over when it fails. On Routing, a manual group's card lists its models as pills, the picked one marked by a dot (role radio), and clicking another saves the group with that pick without opening its editor or moving the page; its rules tag says they wait. The editor offers Manual beside the other routings. magpie group pick <id> <model> (or group set <id> pick=<model>, a bare model id when it names one member) picks from the CLI; magpie groups and group show mark the pick, the TUI shows "manual → model". A renamed provider or model renames the pick. TestManualGroup, TestGroupPick and routing-manual.test.cjs (Chromium, WebKit, en/zh) fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; click-scroll, old-webkit, routing-levels, routing-steady, panel-routing, settings-groups pass. yetone 2026-09-30 19:14:07 +08:00
  • d08018e433 gateway: a gpt-6.x refusal after the ChatGPT backend's safety buffering goes on to the next account, and a refusal tries the same model's other accounts first (#248, Koohoko) — the backend's response.metadata event (safety_buffering, moderation metadata) was taken for the reply's content and let the stream through, so the response.failed bio_policy after it reached Codex as a 200 ("This content can't be shown") with nobody else asked; it is now a lead, and a stream the backend said it holds back for safety checks is held up to 4 minutes rather than 15s (gpt-6.1-sol at xhigh said nothing for 35s). A turn kept on the account that answered it had that account alone first and its member's other accounts where the member sits in the group, so a refusal went to the group's first member (Sonnet); the refused model's other keys or accounts that aren't resting now go next. TestRefusalAfterResponseMetadataMovesToNextAccount, TestSafetyBufferedStreamHeldLonger and TestRefusalTriesTheModelsOtherAccountFirst fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 19:23:08 +08:00
  • 8bf7390584 copilot: Auto asks its session with the API version VS Code sends, and an account Copilot has no Auto for is told so (#256, CakewthinSUm: "Copilot Auto: 404 Not Found") — signed in from magpie (the editors' sign-in), the POST {api}/models/session went out with no X-GitHub-Api-Version, which VS Code's Copilot Chat puts on every CAPI request (@vscode/copilot-api 0.2.19 _mixinHeaders: 2025-10-01, AutoModels among the types); it now carries 2025-10-01 (the Copilot CLI's sign-in keeps its own 2026-07-01). VS Code's session answer names no selected_model, only available_models, and it takes the first it knows: magpie does the same when none is named. A 404 however asked falls back to the first model the account may pick by hand, sent without a session, for 10 minutes; with none, the error says Copilot doesn't offer Auto to this account. TestCopilotAutoSessionAsVSCode and TestCopilotAutoUnavailable fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 19:20:33 +08:00
  • 68f9daa4fa library: an agent's own copy of a library skill gives way to it, and one that differs is settled from the warning (StringKe, JasonLeeForOnly on Discord: after Bring in all, "Claude Code already has a skill of its own called impeccable", 这里没有强制覆盖的能力) — a skill is brought in from the agent with the very folder and given to the agents that had that folder; another agent's copy (CC Switch copies a skill into each agent) was listed as "differs in" and left out, and giving the skill to it, or a copy put back into an agent after its folder became magpie's link (by CC Switch or whatever installed it), was a hard failure with no way out. A folder there holding the same files as the library's (bytes compared; .DS_Store, .git and magpie's copy mark aside) is now set aside into backups/<when>/<agent>/skills and the library's linked in its place; a skill brought in takes the agents with such a copy too, which are no longer said to differ; a move that copied it all but couldn't remove the folder brings it in all the same, what was left set aside. One that differs keeps the warning, now in the reader's language with "Use the library's" (the agent's set aside, the library's linked) and "Keep <agent>'s" (the agent, and any reading the same folder, taken off the skill) on its row — skills/use-library and skills/keep-own, magpie library skill use-library|keep-own <name> <agent>, which the CLI suggests under the problem. Backups holding a skill set aside are never pruned. TestOwnSkillInTheWay, TestSameTree, TestPruneKeepsSkillsSetAside and own-skill.test.cjs (Chromium, WebKit, en/zh) fail without the change; TestSharedAgentsSkills now expects the byte copy to be the library's. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; own-skill, import-all-skills, library-items, shared-skills, market-have, click-scroll, old-webkit pass. yetone 2026-09-30 19:21:10 +08:00
  • 7926dcc226 gui: a plugin's sign-in picker keeps its question readable, and a plugin's provider shows its vendor's icon (the user: 这个 UI 为啥这样 / 这里必须要有真实 icon) — Devin's plugin names its ways long ("Paste an existing Devin session token…"), and the buttons, kept on one line beside the question, pushed it into a column a character wide and ran off the sheet; the ways now wrap under the question, each wrapping its own label. A plugin's provider showed a plain box for any vendor outside OpenCode's few; it now takes the icon the plugin market lists for its package, else for a listed plugin of the same provider (Devin, Zed, Kiro…), read from the list fetched last, the cached copy or the built-in one, never the network. TestMarketIcon and plugin-signin.test.cjs (question squeezed to 12% of the box) fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./internal/plugin ./internal/gui ./internal/provider pass; plugin-signin, plugin-market, old-webkit, click-scroll pass. yetone 2026-09-30 19:33:52 +08:00
  • 221607b5b9 library: the Library's MCP servers go to Hermes and eight other agents (EUPH on Discord: Hermes gets skills but no MCP) — agents with a skills folder had no MCP target, so the MCP editor had nowhere to write for them. Now Hermes ($HERMES_HOME/config.yaml mcp_servers, comments and other keys kept), omp (agent/mcp.json), Kimi Code (mcp.json), Devin (mcp_config.json), Grok Build (config.toml [mcp_servers.*], no SSE), Droid (~/.factory/mcp.json), Qoder and Qoder CN (settings.json), Cline (cline_mcp_settings.json or $CLINE_MCP_SETTINGS_PATH) and Command Code (mcp.json, no SSE) take them, each in the schema its own source reads; a user's own keys on magpie's entries survive an edit and their own servers show to bring in. WorkBuddy, OpenHanako and fx still get none: the first two run a server only once approved or switched on inside them, and fx drops its whole file over one entry it refuses. Each format was read back by the agent's own CLI in a sandbox HOME (hermes, kimi, devin, droid, qodercli, cline, cmd, grok). TestHermesMCP, TestHermesMCPFound and TestAgentMCPFiles fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; library-items, shared-skills, click-scroll, old-webkit pass. yetone 2026-09-30 19:14:57 +08:00
  • fe78829092 Per-model preferences: the machinery three changes share (#288) Comic Chang 2026-09-30 19:14:55 +08:00
  • 8a4283256d gui: a plugin's README reads as it does on GitHub (这里的Markdown你没有渲染) — a link inside bold (**Curated by [Numman Ali](…)**) was shown as its source, and a badge, a picture in a link ([![npm version](…)](…)), as ![npm version](…) text; bold and italics now hold links and code, a badge goes whole, a link written as HTML (<a href>) is a link, and a link to one of the README's headings ([Install](#-quick-start), GitHub's anchors) goes to it in the page instead of nowhere. The publisher line under the name ends in an ellipsis rather than cut, and a box drawn in │ and ─ joins up. plugin-market.test.cjs (Chromium, WebKit, en/zh) fails without the change; old-webkit, click-scroll pass. go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test ./internal/gui ./internal/plugin pass. yetone 2026-09-30 19:07:31 +08:00
  • e54ebf397a accounts: signing in again to an agent's own account removed in magpie brings it back (#320) — removing the account an agent CLI is signed in to (Command Code, Kiro, Devin, Grok, Copilot…) only hides it, and a sign-in from magpie to that same account was dropped as its duplicate with the account still hidden: the sign-in said done, and "signed in, but magpie can't list it". The hidden mark now comes off. TestCommandCodeSignInAgainToRemovedOwn fails without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 18:47:00 +08:00
  • 597c347ba8 gui: the Mac window opens on the Space you are on, and closing it in full screen leaves no black Space (StringKe on Discord) — magpie keeps no window position, so what stuck was macOS's own: the window, made with only full-screen-primary, belonged to the Space it was last shown on and Open took the user there; restarted to update while another app was full screen, it joined that app's Space for good. It now also moves to the active Space whenever shown (130, can still go full screen: checked in AppKit, enter and exit both report). Closing a full-screen window hid it where it was, leaving its full-screen Space empty and black; it now leaves full screen first and hides on WindowDidExitFullScreen (3s fallback), and an Open meanwhile keeps it. TestMainWindowFollowsActiveSpace and TestCloseStepLeavesFullscreen fail without the change. go vet, go build (darwin GUI), go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 18:41:02 +08:00
  • 2ce745a850 tray: the menu bar bird is smaller (@SherlockYoYo on X: 菜单栏icon可以再优化一下吗,感觉这只鸟有些大) — drawn to the edges of its 22pt square it was a full 22pt wide, bigger than the menu bar's own glyphs, and its flap frames were cut off at the sides; build/icon/gen.go now draws it at .8 about the middle (trayK), about 18pt by 14pt, the still bird and every flap frame alike. TestTrayIconSize fails without the change. go vet, go build (darwin GUI), go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 18:31:05 +08:00
  • c4d3fffee9 gui: back on Routing, only the requests still under way fly (#302), and a busy gateway costs the page less (#308) — a hidden or covered window draws no frames, and may not say it is hidden, while each request that came meanwhile still began its flight and waited for a frame; back in sight they all flew at once, a flock of magpies. New requests now play only in sight; coming back (another tab left, or no frame for over 1s) ends every stale flight, draws the stage as it is and flies the requests still under way (at most 4); a replay's clock goes on at most 250ms a frame. Every trace update redrew the whole page, the request list made again whole: renderAll now draws at most once a frame and not out of sight, request rows are kept by id while what they say is the same, the list's and accounts' heads made once and their text set only when it changes, the log's head and steps drawn only when they change, a batch of new requests syncs the stage once, the clock's formats made once. Under a 4x CPU throttle at 40 updates/s, long tasks went from 2.2–2.4s to 0.7–1.0s, frame p95 from 100–133ms to 50–67ms, DOM nodes from 20–27k to 4–5k. routing-flood.test.cjs and routing-busy.test.cjs (Chromium, WebKit, en/zh) fail without the change. routing-*, panel-routing, click-scroll, old-webkit pass. yetone 2026-09-30 18:16:55 +08:00
  • 6c5ed2acf5 agents: CC Switch's provider tables in Codex's config go through magpie too, and the Library brings in every skill found at once (JasonLeeForOnly on Discord: after moving from CC Switch, Codex threads still went to the relay, "model not found" for a magpie model) — CC Switch writes a [model_providers.custom] table (cc-switch, cc-switch-N in older versions) and moves every third-party Codex thread onto it, and a reopened thread takes the provider it was saved with, not model_provider; magpie left those tables pointing at the relay. While a magpie model is on, signed in or not, their base_url is magpie's /v1, the relay's kept in the stash and the table's other keys as they were; a table a profile names, and cc-switch-official, are left alone; Codex's own model or a reset puts the URL back, unless the table was changed since; one pointed away again is named on the agent row and taken back on sync. The Skills tab's "In your agents" gets Bring in all (2+ found), one library write, one that fails named and the others brought in. TestCodexTakesCCSwitchTables, TestImportSkills and import-all-skills.test.cjs (Chromium, WebKit, en/zh) fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; click-scroll, old-webkit, shared-skills pass. yetone 2026-09-30 18:16:20 +08:00
  • b6a34effc6 gateway: a tool's images reach the model on a Claude subscription (smart-lty on Discord: Read of a PNG, browser screenshots came back as text only) — the bridge answered Claude Code's MCP tools/call with the result's text alone, dropping the images parseAnthropic kept in the result, and an image a Chat client sends beside its tool message was never taken; a new run's prompt wrote tool results as text too. A result's images now go as MCP image content (data, mimeType; the type read from the bytes when not given), which Claude Code 2.1.285 hands its model as image blocks; one known only by URL is named in text; an image sent beside the results goes with the result before it; a new run's prompt carries them as image blocks. TestSubscriptionToolResultImages fails without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 18:00:41 +08:00
  • c4ae3ca77d gateway: a Responses client's include goes on to a Responses provider (#315), and the Routing list says what a DeepSeek chat's GPT calls were (#314) — the rebuilt request had no include but magpie's own web_search_call.action.sources, so a relay that asks for Codex's reasoning.encrypted_content refused it; the client's include now goes on in its order, deduped, sources added once (not on api.x.ai), reasoning.encrypted_content only with reasoning (OpenAI refuses it without). A DeepSeek chat in Codex showed codex/gpt calls: magpie's own web searches for a model that can't search, and Codex's title of a new chat, made on a thread of its own, marked by thread_source in x-codex-turn-metadata, not x-openai-subagent. callKind now reads thread_source (not user/subagent) and tags magpie's SearchAgent calls web_search, which carry the agent and model searched for; the list tags them Web search and Title, a search's detail naming whom it was for. TestCallKindThreadSource, TestWebSearchCallSaysWhose, TestResponsesKeepsInclude, TestCodexSearchKeepsInclude and routing-side-calls.test.cjs (Chromium, WebKit, en/zh) fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; routing-kind, click-scroll, old-webkit pass. yetone 2026-09-30 18:00:20 +08:00
  • 98cbea0ffb agents: Pi's models go to PI_CODING_AGENT_DIR (#304), and the Codex app offers magpie's models' efforts (#310) — Pi keeps settings.json and models.json in PI_CODING_AGENT_DIR when set (~ expanded; @earendil-works/pi-coding-agent config.js), and magpie wrote ~/.pi/agent regardless; omp is read by its own rules (PI_CONFIG_DIR, OMP_PROFILE/PI_PROFILE, then PI_CODING_AGENT_DIR), and the library's Pi and omp targets follow. The Codex app's model picker offers only the efforts in [desktop] enabled-reasoning-efforts of config.toml (ChatGPT.app 26.924: default low…xhigh, ultra, persistent), so a magpie model's max or minimal was never offered; routed through magpie, the efforts its models take are added to the user's list (or the default), nothing else changed, only values the app knows (it drops the setting for any other), comments kept, nothing written when nothing is missing. TestPiAgentDir, TestOmpAgentDir and TestCodexDesktopEfforts fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 17:58:33 +08:00
  • fb6c1e175b gui: a Discover card says Add again once its server or skill is removed (#300), and hovering today's bar in the daily trend keeps its tooltip (#309) — every library change went through change(), which redrew the library only; the market's "Added" marks were refreshed on window focus alone, so removing a server or skill, adding or renaming one in the editor, or pasting several left them stale. take() is now the one way the page accepts a library: when the servers' or skills' names change it clears the marks of those gone, redraws the market and fetches it again. RemoveServer drops the server's icon from library.json, unless another server runs the same thing. The Sessions tab re-reads every 15s, and with an agent at work today's numbers change, so the chart was rebuilt and today's bar under the pointer replaced, its tooltip with it; a redraw with the same days, metric and locale now updates the bars in place (heights, titles, peak). market-have.test.cjs and sessions-today.test.cjs (Chromium, WebKit, en/zh) and TestRemoveServerDropsItsIcon fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; sessions-overview, click-scroll, old-webkit, library-items, shared-skills pass. yetone 2026-09-30 17:58:32 +08:00
  • cd7b7a042f sessions: omp's local sessions are in Usage › Sessions (#303), and the GLM Coding Plans take Codex's Responses as they are (#306) — omp (oh-my-pi) keeps Pi's session jsonl (v3) under ~/.omp/agent/sessions (and profiles' and $XDG_DATA_HOME/omp's) with a title line, title changes, model_usage for calls outside the chat, provider/model changes and subagent/advisor transcripts beside the file; they are read through Pi's parser, subagents counted in their session, a fork's copied entries in the original only, resumed by omp --resume <id>. The zhipu and zai Coding Plan regions get their Responses base (open.bigmodel.cn/api/v1, api.z.ai/api/v1, per their Codex docs), so Codex's requests go there as they are instead of rebuilt for Chat; Chat and Claude Code routes are unchanged. TestOmp, TestDirsMore and TestGLMCodingPlanResponses fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 17:58:35 +08:00
  • 9ec237d4e6 gui: a Plugins tab, a market to find and install provider plugins in (在产品里要有插件市场功能,整个插件市场要美观易用), and a way to it from the providers list (供应商列表里有个精致优雅的按钮) — Discover lists the magpie community's plugins, then OpenCode's community's by weekly downloads, each card with its logo, publisher, summary, downloads, version and one button that takes it all the way: Install (Bun fetched first if need be), Sign in, Signed in; a package not on npm yet says Coming soon. Typing searches the list and, after a pause, npm, with the field keeping its focus. A card opens the plugin's page: version, downloads, licence, updated, what it signs in to, npm/source/homepage links, and its README (no images, HTML or scripts; only http(s) links, opened outside). Installed lists each plugin with its providers' sign-ins, a newer version to update to, Update all, switch off and remove; Settings' Plugins section moves here. The list comes from registry.json in magpie-community/plugins, kept for 6 hours, falling back to the copy fetched last and then the one built in (MAGPIE_PLUGIN_MARKET overrides, "off" never asks). Under Add provider a "More subscriptions in Plugins" pill opens it; the add sheet ends in a Plugins tile, and a search that finds nothing offers to look for a plugin. The header, seven tabs now, draws them in at the narrowest window. plugin-market.test.cjs (Chromium, WebKit, en/zh) and market_test.go fail without the change; add-button, plugin-signin, usage-ledger, text-size, old-webkit, click-scroll pass. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 17:57:37 +08:00
  • 7e454bba9b agents: Claude Code on a magpie model is told the model's context window (#311: its auto-compact settings stay as they were for another model) — Claude Code takes any model it doesn't know by name (all but Claude's own) for 200K, and CLAUDE_CODE_AUTO_COMPACT_WINDOW is only ever the smaller of its value and that, so a 128K model compacted too late and a 400K one far too early; CLAUDE_AUTOCOMPACT_PCT_OVERRIDE is a share of the window and holds for any model (read in Claude Code 2.1.285). magpie now writes CLAUDE_CODE_MAX_CONTEXT_TOKENS, the window Claude Code takes those names for, from the model's known context (a group's smallest), with the model: another model's replaces it, one magpie doesn't know the window of, a switch back to a Claude model or a reset removes it; with a [1m] main model, the smallest of the tiers not marked. A value the user set, or changed magpie's to, is left as it is (magpie keeps the one it wrote). TestClaudeContextWindow fails without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 17:44:41 +08:00
  • 91f10f929f gui: the tray menu is in the page's language (#301: 界面设为中文,托盘菜单仍是英文) — its lines were English in Go, which never read the language setting. Open, Version, Restart to Update (to v) and Quit now follow Settings › Language: en or zh as set, with System the system's (macOS AppleLanguages, Windows' preferred UI language, LANG elsewhere), Chinese for any zh; changing it in Settings relabels the menu at once. TestTrayMenuLabels and TestSettingsLangRelabelsTray fail without the change. go vet, go build (darwin GUI), go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. yetone 2026-09-30 17:44:42 +08:00