Commit Graph
Select branches
Hide Pull Requests
main
Select branches
Hide Pull Requests
main
-
b43544b27a
gui: the quota curves can be turned off, picked once in the allowances' head, and the cards drawing them are calmer (ARNO on Discord: 新版本加上了额度走势后,额度面板变得非常混乱和难以观看了) — since
9ccabdfbevery account on the Usage page had its own "2 days | Cycle" segmented control over its curve, so a card with two accounts carried two, there was no way to have none, and the tray's cards drew a thin line each. The range is now one pick in the allowances' head, beside Hide accounts, in the app's own menu (Trends: Off / 2 days / Cycle; 走势:关闭 / 2 天 / 本周期), remembered in magpie.quotaRange as the range was. Off draws no curve on any card, the tray panel's thin lines included; the panel follows a pick made in the window at once (storage event) and keeps it after a restart. The cards themselves: an account after a curve's legend wasn't set apart by the rule every other section gets (the next email sat right under the legend), now it is; the plot is 52px rather than 64; a window far shorter than the span drawn (a 5-hour one over a week's cycle, an all but upright comb) is drawn faint and without its upright even burn; a legend key never breaks inside (a long name ends in …); the curve's head names its range in small print instead of holding the control. quota-curve.test.cjs fails on the old code (no pick in the head, a control on every card, no Off, the 5-hour window's even burn over the week, no rule before the second account) and passes: Off removes every curve without moving the page or the pick, survives a reload, and the tray's line goes when Off is set from another window and stays gone after its reload. In WebKit: quota-curve, click-scroll, panel-usage, usage-fold, account-mask and mobile-web pass; before/after screenshots with seven subscriptions (two Claude, two Codex, Antigravity's five windows, GLM, Kimi) in en and zh, window, tray and a 390px web view. go vet, builds (darwin, GOOS=linux -tags nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestProvidersAnswerWhileListsComeIn, TestUserPath and TestClaudeSignedOut, timing tests that pass alone.
yetone
2026-10-03 19:11:15 +08:00 -
1baad0d2d4
plugin: pi packages are plugins as OpenCode's are — a pi coding agent package (its extensions) adds providers to magpie: their models, their sign-in, renewals and requests (owner: 我希望全面兼容 pi 插件!!!!!!!!!!) — a package is pi's when its package.json has a "pi" manifest, the "pi-package" keyword, or pi-coding-agent among its dependencies (IsPi, mirrored in host.js). Adding or updating one installs @earendil-works/pi-coding-agent beside it, and the plugin host loads every pi package through pi's own loader (pi.js: discoverAndLoadExtensions and ModelRuntime, with the credentials kept in plugin-auth.json), so an extension's registerCommand, registerTool and pi.on are taken and left unused, and its registerProvider calls become magpie providers. A provider's models keep their context, output, images and the reasoning levels their thinkingLevelMap allows; its OAuth login runs as pi runs it, each onPrompt asked in magpie's sign-in in turn, onAuth's page opened, a later prompt being the code pasted back; a provider with apiKey takes a key; magpie renews through refreshToken and saves the result. Requests arrive as Anthropic Messages and go to pi's stream: system and tools, images, tool results, thinking budgets and effort as the nearest level the model has (and the least it allows when it can't turn thinking off: Antigravity's gpt-oss refused requests without one), max_tokens held to the model's; the answer comes back as Messages SSE or JSON with thinking and its signature, redacted thinking, tool calls (their thought signatures kept for the next turn), usage, and a failure before anything is said as the vendor's status with Retry-After. The Plugins page's search also finds pi packages that bring a provider. Tried with the owner's real Antigravity account through pi-antigravity, next to the Grok OpenCode plugin in the same host: 14 models listed, Gemini streaming with usage, Claude Sonnet thinking with signatures, gpt-oss, tool round trips on gemini-3.8-flash, gemini-3.1-pro and claude-sonnet-4-6, a 400 and Antigravity's 429 passed on with their status. A Claude Code turn didn't get through: Antigravity answers 429 to any system prompt with Claude Code's billing header or its "Claude agent" line, through magpie's built-in Antigravity just the same. TestPiPackage (a fake pi package: models, an OAuth login asking twice with a wrong code then a right one, a key, streaming and JSON answers, thinking and tool signatures back, a 429, a renewal) and TestSearchFindsPiPackages pass. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestClaudeRunEndsWhenTheClientLeaves, TestProvidersAnswerWhileListsComeIn and TestSavedButSignedOutClaudeServed, timing tests that pass alone.
yetone
2026-10-03 19:12:16 +08:00 -
a742ee10b3
antigravity: a Gemini reply that says nothing is an error, asked again, not a turn ended as it should (#667: antigravity/gemini-3.8-flash handed pi content [] and zero usage as a normal stop, the agent's run ending mid-task; #636 Bug 3) — Antigravity's Code Assist stream (and any Gemini one) now and then ends with a STOP and no parts, with only reasoning, or with no candidate at all. translate passed the decoder's KStop on and finished the client's stream as it does any reply: Chat's finish_reason "stop" and [DONE], Anthropic's end_turn and message_stop, Responses' response.completed, and a non-streamed reply of 200 with no content — nothing an agent can tell from an answer, and nothing the holdWriter took for a failure, so nobody asked again. Now a reply from a Gemini upstream (CodeAssist, Gemini) holds its end (KStop, KUsage) until something is said in it — text, a call, a search, an image — and one that ended with nothing said, not cut at its length nor by a safety filter (still a refusal, #248), ends with an error event, "<provider>: an empty reply (the model answered nothing; try again)", or a 502 when not streamed. As a 502 before any content it is held, asked again of the same account (lastRetries) or of the next one, and an agent told it retries rather than ends its turn, as Cursor's and Devin's empty replies already are. Other upstreams aren't changed: Claude ending a turn with nothing after a tool's result is its answer. TestGeminiEmptyReplyIsAnError (Factory's Gemini route, which shares the decoder and translate: STOP with no parts, only reasoning, no candidate; Chat, Anthropic and Responses streamed and Chat not; asked again; text and reasoning cut at MAX_TOKENS still go as they came) fails on the old code with the issue's wire shape and passes. Against the owner's real Antigravity account in a sandbox gateway (temp HOME, port 3488): a prompt asking gemini-3.8-flash-low for no output gave, on the old build, finish_reason stop with no content 3/3, and on this one the error event after the retries 3/3; ordinary replies on Chat (streamed and not), Anthropic and Responses, and a bash tool call, are unchanged. go vet, builds (darwin, GOOS=linux -tags nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass (a first run had TestClaudeAccountNamedAsItsLogin and an internal/gui fetching test fail, timing tests that passed on the rerun).
yetone
2026-10-03 19:05:49 +08:00 -
e61d1da9ce
gateway: a model that won't be made to call a tool is asked again with the call left to it (#668: OmO's first turn forces its todo tool, and Claude Opus 5.5 answers 400) — the issue reads the 400 as Anthropic wanting additionalProperties:false on every object of a named tool's schema; it doesn't. Against Anthropic's API (the owner's Claude subscription) the same two tools, schemas without additionalProperties, with tool_choice {type:"tool"} are taken by claude-sonnet-4-5, claude-opus-4-8, claude-opus-5 and claude-sonnet-5, and refused by claude-opus-5-5, claude-sonnet-5-5 and claude-fable-5-1 with
tool_choice: type "tool" and "any" are not supported for this model., with or without additionalProperties:false on every object; OpenRouter (Anthropic, Bedrock, Azure, Claude Platform on AWS) answers the same. Anthropic says "tools.N.custom: For 'object' type, 'additionalProperties' must be explicitly set to false" only of a tool sent with strict:true, auto or forced alike, and buildAnthropic sends no strict; the reporter's own capture shows none either, so it is the vendor behind their Claude Pro endpoint holding the forced tool to strict mode. Either way the 400 came from forcing the call on a model that can't be forced, and it was relayed as is, with no fallback. forwardTranslated now asks again when a forced tool_choice (a named tool, or required) is turned away with either error: the call is left to the model (auto), only the named tool offered, as the Claude subscription's bridge does, and the provider isn't sent a forced choice for that model again (unfit, as reasoning-off refusals are). Schemas are unchanged. TestForcedToolChoiceRefused (Chat to an Anthropic-only provider, with each error) fails on the old code. Through a sandbox gateway on an Anthropic-only copy of the owner's OpenRouter provider, a Chat request forcing todo to anthropic/claude-opus-5.5 answered 400 with the old build and a todo call with this one, twice. go vet ./internal/..., builds (darwin, GOOS=linux -tags nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestProvidersAnswerWhileListsComeIn, a timing test that passes alone. A Chat client on a Chat endpoint (passthrough, e.g. OpenRouter's chat) is not changed.
yetone
2026-10-03 19:03:53 +08:00 -
ebcd5281c2
gui: open matching allowance cards from macOS menu-bar quotas (#662)
lizhuo
2026-10-03 19:01:13 +08:00 -
8c652a83f7
antigravity: its 429 to Claude Code's system prompt says it isn't a quota (#666: Claude Desktop 调用 antigravity 恒定报 429) — Antigravity answers "Resource has been exhausted (e.g. check quota)" to any request whose systemInstruction holds Claude Code's billing line (x-anthropic-billing-header: …) or the Agent SDK's identity line (You are a Claude agent, built on Anthropic's Claude Agent SDK.), on every model (gemini-3.8/3.7 flash, 3.5 flash lite, 2.5 flash, claude-sonnet-4-6, gpt-oss), whatever the quota left, while the same words in a message go through. Claude Desktop's chats run the Agent SDK and carry both, so they always failed, while its title requests (no system prompt) and Codex on the same account answered. Not the session id (magpie already sends request.sessionId as -<uint63>), thinking signatures (never sent back) or the User-Agent. magpie doesn't hide the lines from Google; the gateway now adds to such a 429 that it is no quota and that Antigravity turns away Claude Code's and the Agent SDK's system prompt, so no one chases a quota. Reproduced on the owner's real Antigravity account with Claude Code 2.1.288 through a sandbox gateway (11/11 429; system field removed 200; either line alone 429). TestAntigravityTurnsAwayClaudeCodesSystemPrompt. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 18:39:29 +08:00 -
a85b2434ab
models: reasoning levels are borrowed again for models Azure also hosts, and a routing group keeps its members' levels when one thinks with none to pick from (ARNO on Discord: routing group在接入harness的时候,没有设置reasoning_efforts。我发现是之前很多能自动推导reasoning_efforts列表的模型现在都推导失败了) — the Azure OpenAI preset (
c35471cf, Catalog "azure, openai") was taken for a maker, so models.dev's azure list was the maker's word on every model it hosts: Kimi K2.5, DeepSeek V3.2 and R1, Grok 4.20/4.1 Fast Reasoning, listed there with no levels, took none on a relay or custom provider (and the gateway capped them at high as levelless), where the providers listing any give low…high, none/high and the rest. Azure is now marked Hosts, as Groq and Ollama Cloud are; its own provider still takes its own list's word. And groupEntries narrowed a group to the levels every member has, so one member that thinks with no levels (a thinking switch, a Claude 4.5 with a budget alone, OpenRouter's qwen3.8-omni-flash) left the group none and dsh's route wrote it without reasoningEfforts; such a member is now skipped as an unknown one is, since the gateway sends it the effort asked, no more than high (fitFor). The same Entry.Efforts feeds dsh, Codex's catalog, Pi and OpenCode. On a copy of the owner's config and models.dev cache: no plain model loses levels; group/auto-claude-haiku-4-5 and -sonnet-4-5 get low/medium/high/max again (they had them on 09-30), group/auto-qwen3-8-omni-flash none/low/medium/xhigh; across models.dev, the 34 ids Azure emptied (kimi-k2.5, deepseek-v3.2, deepseek-r1, grok-4-20-reasoning …) borrow again. TestHostListIsNoMakersWord (provider) and TestDshGroupHasItsMembersLevels (agent: the group's dsh entry has reasoningEfforts and the thinking field offers low/high/max) fail on the old code. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 18:15:47 +08:00 -
dd03e431c1
mcpauth: a sign-in asks for offline_access when the authorization server offers it, so Vercel's MCP stays signed in (#615: "vercel老是掉"; Neon, Notion and Supabase stay) — mcp.vercel.com's resource metadata names only the scope "openid" (its 401 names none), and magpie asked for exactly that; its authorization server, https://vercel.com, is an OpenID provider whose scopes_supported lists offline_access, and Vercel's docs say that scope is what issues a refresh token (access tokens last an hour; refresh tokens 30 days, single use, rotated). So magpie's Vercel sign-in had no refresh token, and an hour later Token found it due with nothing to renew it by and marked it dead: "sign in again". Neon (no scopes, refresh by default), Notion ("default") and Supabase (its own scopes) give a refresh token without it. Now discovery adds offline_access to the scope asked for (authorize and registration) when the authorization server's metadata lists it and the scope named any; a sign-in that names no scope keeps the server's default. A rotated refresh token was already saved. The test fake gains OpenID, a Vercel-like server (resource names only "openid", no scope in the 401, refresh token only with offline_access); TestSignInAsksForOfflineAccess fails on the old code (scope "openid", no refresh token, ErrExpired at the first renewal) and passes. A Vercel sign-in made before this has no refresh token and has to be made again once. go vet, builds (darwin, GOOS=linux -tags nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestProvidersAnswerWhileListsComeIn and TestUserPath, timing tests that pass alone. Not tried with a real Vercel account.
yetone
2026-10-03 18:08:42 +08:00 -
9416a6040a
site: the Omarchy intent hit shot reads as its caption — the classifier in 964 ms, glm-5.3 in 5.6 s (owner: 改一改吧) — the shot said 961/972 ms and 5.5 s; re-shot in tokyo-night and catppuccin-latte, retried until the routing card said 964 ms and 5.6 s, en and zh from the same request. Same sizes, so SHOTS is unchanged.
yetone
2026-10-03 18:07:42 +08:00 -
a345af91e5
gui: a plugin card's Update chip updates the plugin (莫 on Discord: 显示更新但是好像没有更新按钮) — on Plugins › Discover a card whose plugin has a newer version showed an "Update" chip that looked like a button and did nothing (a click opened the plugin's page); the Update button was only on the Installed tab. The chip is now that button: it names the version ("Update to v0.0.9" / "更新到 v0.0.9"), updates the plugin without opening its page, shows Updating… meanwhile and goes once it is current, and is disabled while another plugin action runs or the plugin is off. plugin-card-update.test.cjs (en, zh) fails on the old code (no button) and passes; plugin-updates, plugin-market and plugin-check-updates still pass (WebKit).
yetone
2026-10-03 18:04:38 +08:00 -
191700c4fa
gateway: a reply that only thought and then failed is the failure, not an empty 200 — a client asking for the whole reply (not a stream) got 200 with null content and zero usage when the provider thought, then failed with nothing said: the collector's error counted only when no parts came at all, and thinking is a part. Cursor's plugin ends such a turn with "an empty reply" (composer-2.5 with no system prompt, 1 in ~5 on a 45k-token prompt): streamed, the client saw that error; whole, an empty answer it didn't ask again. Now an error with nothing but thinking before it is answered as the error (502, or its own status), in translated replies and Claude Code's. TestThinkingThenErrorIsAnError fails on the old code. Against the real Cursor account in a sandbox: 8 whole requests (chat and Messages) to cursor/composer-2.5, the one that only thought answers 502 "Cursor: an empty reply", the rest as before. Also found while testing Cursor's overflow: a 303,700-token prompt to composer-2.5 / gpt-5.2 (200k) comes back 400 context_length_exceeded after one try (Cursor answers 502 "No system prompt found"); 34k–52k prompts answer with usage. go vet, builds (darwin, GOOS=linux -tags nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 18:01:00 +08:00 -
ac1a8a4f85
gui: Trae CN's plugin shows Trae's logo (owner: trae cn plugin 没有 logo) — the registry gives it the icon "trae", which magpie didn't have, so its tile and provider row had none. Adds lobe-icons' mono TRAE mark as icons/trae.svg (taking the text colour, as qoder's does). TestMarketIconsAreBundled checks every icon the built-in list, the older plugins and the registry name is among the GUI's pictures; it fails without trae.svg. Seen on the Plugins page of a sandbox built from this tree. go vet, builds (darwin, GOOS=linux -tags nogui, GOOS=windows) and go test -tags nogui ./internal/plugin ./internal/gui pass.
yetone
2026-10-03 17:47:07 +08:00 -
33e59f93da
images: a ChatGPT account that won't draw hands the drawing to the next account on (#545) — /v1/images/generations and /v1/images/edits asked only the account a subscription is pinned to, so when chatgpt.com answered its plan 403 {"detail":"Forbidden"} magpie gave up, though a Plus account further down drew it (moving that one to the top fixed it for the user). A subscription's drawing now goes over its accounts in the order its text requests do (candidates, without fallback models, as count_tokens takes them): a 401, 402, 403 or 429 from one asks the next, and only when every one refuses is the last refusal returned. The account that drew is the one recorded in usage. An account set aside for text because its model list lacks the image model while another's is unknown is asked last. A refusal of images alone rests no account for text, and API-key providers draw as before. TestCodexDrawMovesToNextAccount (acct-1 403, acct-2 200) fails on the old code (403) and passes; no account rests after it, and the next drawing asks acct-1 first again. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./internal/gateway/ ./internal/provider/ under a temp HOME pass (gateway and provider, then the whole module). Not tried with real accounts.
yetone
2026-10-03 17:27:00 +08:00 -
ba1e3f2803
site: the Omarchy picker shot shows what its alt says — Codex's picker listing DeepSeek, Kimi and GLM models (owner: 其他页面的截图也检查一下有没有对不上的) — the old shot opened the picker on Routing groups and covered the Codex row, so neither Codex nor Kimi/GLM showed; it is re-shot in tokyo-night and catppuccin-latte with the Codex row (DeepSeek V4 Pro) above the menu and the list at DEEPSEEK, KIMI and ZHIPU GLM, 880x1320. SHOTS picker follows. Checked in the omarchy VM's Chromium: index.html takes /img/omarchy/picker-*.png at its own ratio in both themes and the hero lays out as before. The other Omarchy shots (add, agents, import, panel, providers, routing, usage, nested routing, intent) already matched their alts.
yetone
2026-10-03 17:28:13 +08:00 -
c96a4ba9ac
site: /download links work again — since the release notes change (
e5f8ff60) latest() returns { rel, degraded }, and /download still read .assets off that, so every download link (/download, /download/mac, /download/linux, /download/windows…) answered 500 (Cloudflare 1101) while /api/latest worked. /download now takes the release from got.rel. A test for /download/linux (302 to the asset) and an unknown platform (404) fails on the old code and passes; node --test site/*.test.mjs passes.
yetone
2026-10-03 17:20:58 +08:00 -
96e3ef6948
site: the update feed reads only what this worker kept in the edge cache —
e5f8ff60changed the shape of the cached newest release and release list but kept their names, so the entries the previous worker had put there were read as the new shape and /api/latest and /api/notes answered 500 until they ran out (up to 5 minutes after the deploy). The cache names now carry a version (__v2/), a hit is used only in the shape expected, and a cache that can't be read or written is a miss, not an error. A worker test seeds the old entries (and malformed new ones): it fails one5f8ff60and passes. node --test site/ passes.
yetone
2026-10-03 17:17:34 +08:00 -
ed586dab15
site: the Omarchy intent-hit shot shows what its caption says — Live's aihubmix/glm-5.3 answering, deepseek-flash telling the intent (owner: 能否对上) — the Omarchy version of intent-routing-hit had Zhipu GLM answer and DeepSeek's deepseek-v4-flash classify, while the page's caption (en/zh/ja) and its plain shot name a custom provider Live with aihubmix/glm-5.3, deepseek/deepseek-v4-pro and deepseek/deepseek-flash. Reshot in the omarchy VM with Live (a pretend relay) holding those three, Coder in that order, rule 2 "writing or fixing tests" sending the turn to live/aihubmix/glm-5.3 and live/deepseek/deepseek-flash telling it in about 0.96 s; tokyo-night and catppuccin-latte, en and zh. The English shot is taller (1220), omarchy.js has its size. Checked in the VM: /docs/intent, /docs/zh/intent and /docs/ja/intent load it at the image's own ratio in both themes.
yetone
2026-10-03 17:16:07 +08:00 -
e5f8ff6026
site, gui: release notes survive GitHub limiting usemagpie.ai, and a failure to get them says so, apart from a release without any (#661) — /api/notes answered 503 {"error":"no releases"} with Cache-Control public, max-age=300 whenever GitHub's API limited the worker's shared IP, and /api/latest fell back to the release page's redirect with notes "" (kept 300 s too), so the update window had nothing to show. The worker now: never keeps an error (503 is no-store); takes the notes from GitHub's releases feed (releases.atom, not API-limited) when the API says no, turning its HTML back into the markdown the app draws and putting back the <!-- lang:zh --> marker GitHub strips (before the first Chinese heading after an English one); keeps the last whole answer for 30 days in the edge cache and serves it (merged with the feed's newer releases) when GitHub fails; keeps a degraded answer 60 s instead of 300; and sends a GITHUB_TOKEN secret to the API where one is set (none is yet). In the app, /api/whatsnew says error (and the release page's url) when the notes couldn't be had, and Settings' What's new opens a dialog saying "Couldn't load the release notes" with Try again and "Open the release page" (through the app), or "No release notes provided." with the release page and no retry for a version with none, instead of a passing toast; en/zh. Tests that fail on the old code and pass: site/worker.test.mjs (API limited: notes from the feed in either language, briefly kept; all of GitHub down: 503 no-store, then the last whole answer; the token sent), TestWhatsNewTellsFailureFromNone, and whats-new-failed.test.cjs (WebKit, en/zh: failure with retry and link, retry showing the notes, none without retry, no click moves the page). The feed parser was tried on the real releases.atom (v0.1.730–739: English and Chinese split as the API's bodies are). go vet, builds (darwin, GOOS=linux, GOOS=windows), go test -tags nogui -count=1 ./... under a temp HOME, node --test site/ and whats-new.test.cjs pass.
yetone
2026-10-03 17:12:45 +08:00 -
0c6b4c290a
sessions: preserve Windows link kinds and only copy cross-device moves (#663)
Zhizhen He
2026-10-03 17:11:26 +08:00 -
a9368c301f
site: the nested-routing and intent-routing shots in Omarchy's look too (owner: 把嵌套路由和意图路由的截图也补上) — on Omarchy the docs' Start page (en/zh/ja) shows nested-routing, and the Intent page shows intent-rules, intent-routing-hit and intent-trace (en/zh, ja takes the English) as magpie draws them there, in tokyo-night (dark) and catppuccin-latte (light). They were shot in the omarchy VM's Chromium against a sandbox magpie with pretend vendors: the Coder group with an intent rule judged by Groq llama-3.1-8b-instant, a request routed by it (the trace's timings real), and Coder holding the group Fast. omarchy.js now matches shot names with a hyphen (intent-rules-zh-dark: name intent-rules, -zh) and knows these four, each with its own Chinese height. Checked in the VM: /docs/start, /docs/zh/start, /docs/ja/start, /docs/intent, /docs/zh/intent and /docs/ja/intent under ?omarchy=tokyo-night and catppuccin-latte load /img/omarchy/<name>(-zh)-<mode>.png with the image's own ratio.
yetone
2026-10-03 17:05:29 +08:00 -
ae6b4c9335
gui: a subscription with several accounts shows one of them on Usage and in the tray panel, the others behind "Show N more accounts" (whqtian on Discord: 我这个workbuddy只有4个账号,其实大多数情况下,我不需要显示全部的账号信息,你只要显示一个账号信息即可,其他的可以点击展开再看) — every provider's card listed each account's meters, credits and curve one under another, so four WorkBuddy accounts took the page. Now a card with several accounts shows the one that answered through the gateway last (lastServedAt), else the first, with "Show 3 more accounts" / 展开其余 3 个账号 under it; opened, all are shown in their order with "Show fewer accounts" / 收起其余账号. Opened is remembered by provider (localStorage magpie.usageOpen), for the window and the tray panel alike, each following the other as it is turned; a provider with one account has no button. The folded accounts stay in the page, hidden, so Hide accounts masks them as before; the line between accounts is drawn only after one in sight. The click keeps the page where it is (backToReader). usage-fold.test.cjs (WebKit, en and zh: 4 accounts show the last-served one and the button, opening shows all without moving the page, remembered after a reload, one account has no button, masking covers them, the panel folds the same and the window follows it) fails on the old code and passes; quota-families and quota-pools open the panel's second Antigravity account first. account-mask, quota-curve, click-scroll, mask-emails, credit-days, balance-parts, usage-arrange, panel-usage, tray-usages and usage-accounts pass; the GUI tests failing here fail the same on origin/main. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 16:50:28 +08:00 -
37809ac722
usage: WorkBuddy's credits are said beside their share — on the Routing page, the Usage page and the menu bar, used or left as the share is (#659)
yetone
2026-10-03 16:45:45 +08:00 -
901084e3cc
site: on Omarchy the screenshots are magpie on Omarchy (owner: 各个截图能否也换成 magpie 在 Omarchy 下面的截图?) — magpie's own windows shot in the omarchy VM (magpie web, a sandbox HOME, pretend vendors behind a local proxy) in tokyo-night for the dark look and catppuccin-latte for the light one: add, agents, import, routing and usage in English and Chinese, panel, picker and providers in English, 26 images under img/omarchy/. In the Omarchy look omarchy.js puts them in place of the page's own, keeping each image's width and taking the new one's height; nested-routing and the intent shots keep the page's. Tried in the VM's Chromium against the site served locally: home, start (en, zh, ja) and import (en, zh) in both themes load the Omarchy shots at their own proportions, intent keeps its own.
yetone
2026-10-03 16:43:55 +08:00 -
52e2af1a75
factory: the mover takes plugin 0.1.14, which adapts Claude Code 2.1.288's runtime context sent as a system message of text blocks (#658)
yetone
2026-10-03 16:34:07 +08:00 -
e7cd1e6e98
gateway: GLM searches on its Responses API (#660)

Kagari Mimiandhazukisendai
2026-10-03 16:28:57 +08:00 -
b3ab3e42e9
gateway: a request well past the model's window that a vendor turns away without saying why reaches the agent as too long, at once; Qoder's plugin to 0.2.4 for its token usage (found testing real accounts) — Devin answered a conversation of about 300k tokens for swe-1.7-lightning (a 202,752 window) with a 502 "We are currently experiencing capacity issues…", Qoder one of 1.8M for qmodel (1M) with a 400 "Error in upstream response", each answered at a size the model holds; magpie asked Devin's again in place three times and handed the agent a 502 api_error, so Claude Code and Codex never compacted. tooLongUnsaid (fallback.go) takes a 400/413/422/5xx that says nothing of quota, a rate limit, the account, the model or the conversation's length, for a request whose estimate is 1.2 times the model's window or more (the user's context, else the catalog's; estimate counts four bytes a token, which most text runs under: Devin counted 173,954 tokens of one estimated at 151,851), as one too long: "prompt is too long: about N tokens, more than <model>'s context window of M (<vendor> answered <status>: …)", sent the agent's way (context_length_exceeded, Anthropic's "prompt is too long"), not asked again of it or another account, and nobody rests. TestOverflowTheVendorDidntSay fails on the old code (a 502 asked three times, a 400 handed on) and passes; a request near the window, a small one, a 429, a 401 and a used-up balance keep their errors. Qoder's plugin read its stream only up to the finish, and Qoder sends the usage in a chunk of its own after it, so every Qoder request was counted as 0 tokens: @magpie-community/opencode-qoder-auth 0.2.4 reads it, and the mover's min is raised to it. Tried with real accounts in a sandbox magpie: Devin (chat and Anthropic) and Qoder now give 400 context_length_exceeded after one try, a WorkBuddy and Kiro overflow as before, small requests to all three answer, and Qoder reports its tokens (streamed, not, and with a tool call). go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but a provider timing test that passes rerun.
yetone
2026-10-03 16:14:38 +08:00 -
f1224a055e
sync: a backup on a slow line is no longer cut off at 2 minutes; a server that stops moving is (#657, irx999: a 43 MB backup with many skills to a WebDAV server on a 2.4 Mbps VPS, 305 KB/s, needs 2.4 minutes and every sync failed) — a sync had a fixed deadline in all (2 minutes from the gateway's loop and magpie webdav/s3 sync, 90 s from Settings › Sync now), so a large backup on a slow line never got through, however steadily it moved. WebDAV and S3 requests now go through a watchdog instead (stall.go): the backup's GET and PUT fail once nothing has moved either way for 60 s, each byte of the body sent or read putting it back, and after a PUT's body is all handed over the answer gets 60 s on top of as long as the write took (at least 4 minutes), for what still sits in the system's buffers to leave; the other requests (PROPFIND, MKCOL, HEAD, MOVE, DELETE) have 30 s in all. A stall says so ("the server sent and took nothing for 1m0s (PUT)"). Sync now and the CLI have no deadline; the gateway's loop keeps an hour as a backstop; a wait for another magpie's sync stays 30 s. TestSlowTransferIsNotCutShort (20 MB up and down at a steady trickle, over 5 times the watchdog each way), TestStalledTransferFailsPromptly (a server stopping mid-PUT and mid-GET fails within a second) and TestMetadataRequestHasALimit fail on the old code (no watchdog: the stalled ones hang) and pass. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried against a real slow WebDAV server.
yetone
2026-10-03 16:09:59 +08:00 -
b6467c9551
codex: Ultra on GPT-6.1 Sol wherever it is served, Copilot's too, with Codex's agents taking parts of the task (#656) — Codex offers Ultra on a model whose entry lists "ultra", and on a thread at multi-agent V2 hands parts of the task to agents of its own; its catalog (models-manager/models.json) lists it for gpt-6.1-sol, gpt-6-sol, gpt-6-astra, gpt-5.6-sol and gpt-5.6-terra, not the Lunas, which stop at max. magpie listed Copilot's gpt-6.1-sol only up to max, so Codex had no Ultra for it. Now an entry for one of those models (by the id the vendor serves: openai/…, dated snapshots) that reaches max lists ultra too, in Codex's catalog and /v1/models, and its Codex entry says multi_agent_version v2, as Codex's own does; GPT-6 Luna still stops at max. A ChatGPT account's entry stays as the backend lists it, and a group with a ChatGPT account in it offers ultra but isn't told V2 (its lead's subagent tasks come sealed, #141); the "subagents on any model" setting still stamps v1 on OpenAI's entries. Ultra is no API's level: the gateway now always sends max for it (fitEffort), even to a model whose list says ultra. Subagent tasks with web_search kept (the translated path) were fixed in v0.1.689 (#613); TestCopilotUltraSubagentWithWebSearch now covers it against a stub Copilot: the lead's spawn_agent comes back with plain arguments and encrypted_function_args [], no "encrypted" goes upstream, and the subagent's agent_message reaches Copilot as text. TestCopilotSolOffersUltra (sol has ultra in /v1/models and Codex's catalog with v2, luna not; ultra goes to Copilot as max, with and without web_search) and TestUltraIsSentAsMax fail on the old code; TestUltraOnModelsThatOfferIt and TestUltraEntriesSayV2 cover entries, groups and the catalog. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried in the Codex App with a real Copilot account.
yetone
2026-10-03 16:08:20 +08:00 -
22e305b481
site: the Omarchy chip shows on the first visit too — Omarchy was found (the font loaded) before <body> existed, so the chip had nowhere to go and nothing drew it later; render now waits for the body. Tried in the omarchy VM's Chromium with a fresh profile: tokyo-night and the chip on the first load.
yetone
2026-10-03 16:06:32 +08:00 -
6cab11673e
vision: a model whose list says nothing of images is given the image described, and the description is in Routing as its own call (Discord, Fate: since v0.1.725 images reach a text-only model in Codex, but it reads them badly and Routing shows no call to the Vision model) —
19e239c7tells agents every model takes images while a describer is set, but the gateway described an image only for a model whose list says explicitly it takes none (ImageInput false); a model the vendor's /models says nothing of (ImageInput nil — most API keys' models, which magpie counts text-only and agents were told so before) had the image sent on as it came, so the text-only upstream got the raw image (dropped, or read by whatever it does with it) and the Vision model was never asked. Now, while a describer is set, a model that isn't known to see (its catalog entry's Images: the list's answer, the user's override, else models.dev) is given the description, on every API (Responses and Codex's /backend-api/codex, Chat, Anthropic, Gemini), for its current turn, older turns and tool results (function_call_output's input_image), and as a routing group's member (blindTo). Without a describer an unknown model is passed images as before. The description was already a call through the gateway (agent magpie-vision) but untied to anything; it now has kind "vision" ("Image description" in Routing, zh 图片描述), For naming the agent and model it described for, and the request's session, so it shows in that conversation's Routing beside the turn. The describer's prompt (every text transcribed, layout, values) and the image (sent whole, never downscaled) were already right. TestModelNotKnownToSeeIsGivenTheDescription (data: and https input_image on /v1/responses and the Codex backend path, Chat), TestModelNotKnownToSeeToolAndGroupImages and TestDescriptionIsInRouting fail on the old code and pass. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestUserPath, TestCodexVersion, TestClaudeRunEndsWhenTheClientLeaves and davsync, timing tests under load that pass alone and in their packages rerun. Not tried in the Codex App with a real account.
yetone
2026-10-03 16:05:13 +08:00 -
27925fc266
provider: OpenCode Zen's Jev routes groups on System One, and a preset's or a subscription's model can be asked on the API picked (Discord, 01huadalang: Zen's "Jev free" was asked as a chat model and failed with no way to switch; OpenCode Go's DeepSeek V4.1 Flash answers on Responses too, and magpie asked it on chat alone, while a custom provider could pick) — Jev isn't an Anthropic model: OpenCode's docs (anomalyco/opencode packages/web/src/content/docs/zen.mdx) list jev-1.13 and jev-1.13-free at https://opencode.ai/zen/v1/systemone alone, and models.dev has no entry for it; asked keyless, Zen answers it there and errors on chat, messages and responses. The opencode-zen preset now has Decide (https://opencode.ai/zen/v1), making Zen a mixed decision provider (#609): Jev is left out of agents' models and is a routing groups' classifier, the free one when Zen is used without a key; a Zen provider saved before gets Decide back in Normalize. Zen's and Go's other models already take their API from models.dev's npm package (catalog.APIOf), which matches the docs. The per-model API custom providers have (settings ModelAPIs, the gateway's Provider.APIs) now reaches presets and subscriptions with more than one API: ModelAPI no longer refuses an account, APIs() is the pick or ListedAPIs (what the vendor's list says, sent to the editor as a model's auto); the editor's model chip has "Asked on: Auto…" on its right-click, opening the app's menu (Auto says what the vendor's list says, then each API the provider has), tagging the chip with the pick, staged and sent with Save as modelPrefs, the page not moved; Names & levels' API row shows for subscriptions too. English and Chinese. TestOpenCodeZenJevDecides and TestPresetAndSubscriptionModelAPI fail on the old code and pass; internal/gui/tests/model-api-preset.test.cjs (WebKit, en/zh) covers the menu, no <select>, no left-border accent, no scroll, the Save's modelPrefs, a subscription's tag and a single-API provider with nothing to pick, and fails on the old assets. A sandbox magpie (keyless Zen) answered POST /v1/systemone with opencode-zen/jev-1.13-free (noul 0.44) and chat on mimo-v2.6-flash-free, Jev not in /v1/models. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestUserPath, a timing test that passes alone; provider-levels-scroll.test.cjs fails the same on origin/main. Not tried with a paid Zen/Go key.
yetone
2026-10-03 16:03:29 +08:00 -
8f385e113b
site: usemagpie.ai draws itself in Omarchy's look on Omarchy, in the theme Omarchy has on (owner: 整个官网和文档页面能否智能识别是不是 Omarchy 在访问,如果是 Omarchy 在访问,那么整个页面风格能否变成 Omarchy 风格?而且能够适配当前 Omarchy 就更牛逼了) — every page (home, /import, the docs in en/zh/ja) loads omarchy.js in a Linux desktop browser only; it tells Omarchy by its font (a page may load local("omarchy"), which Omarchy installs system-wide and nothing else has), remembers it, and from then on paints before the page shows: the theme's palette, the system monospace (Omarchy's font), square corners, no shadows or glass, a solid bar, buttons and what's chosen in the accent, images framed in it. Until magpie tells the theme it takes Omarchy's default (tokyo-night, or catppuccin-latte on a light desktop). magpie's gateway answers GET /v1/magpie/omarchy (name, mode, stamp and the CSS variables magpie's own windows use) to this machine only, readable only by usemagpie.ai (CORS + Private Network Access; MAGPIE_SITE_ORIGIN adds an origin to try the site locally), 404 off Omarchy. The page asks it by itself only once the browser allows it to reach this computer; a chip in the corner (Omarchy's logo and the theme) asks once on a click, lists the 22 built-in themes to pick one, and turns the look off; ?omarchy=1|0|<theme> sets it anywhere. Followed while the page shows: a theme set in Omarchy's menu comes through in about 3 s. Tried in the omarchy VM's Chromium 152 with this magpie (nogui serve): detection, the home page and zh docs in tokyo-night, the chip's menu, following the computer, and omarchy-theme-set catppuccin-latte repainting the open page light. TestOmarchyThemeForTheSite covers 404 off Omarchy, the theme and its CORS for usemagpie.ai only, LAN refused and the preflight. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. The permission prompt from the public site wasn't clicked through in a real browser.
yetone
2026-10-03 16:00:51 +08:00 -
123594489a
plugin: a host stopped mid-renewal saves the new token first, and two hosts never write each other's sign-ins away — a stopped host (quit, plugin update, restart) was killed 2 s after stdin closed even while it renewed a sign-in through auth.refresh, after the vendor had spent the old refresh token, so the account was signed out; and while a host restarts the old one and the new one both rewrote all of plugin-auth.json from what each had read, so one host's save could drop the other's accounts or newer token. host.js now tells magpie how many renewals are under way (event "renewing"), and stop gives a host still renewing after the 2 s up to 15 s in all, until the renewal is saved; with none it stops as fast as before. Every change to plugin-auth.json (setAuth, removeAuth, settle, take, auth.set, a renewal's save, and magpie's SignOut when no host runs) is made under plugin-auth.json.lock (O_EXCL, broken when older than 10 s), reading the file afresh and changing only its own accounts; a renewal's save checks under the lock that the stored sign-in is still the one it renewed, so an older host never writes a stale token over a newer one. TestStopLetsARenewalEnd (a 4 s refresh, the host restarted in the middle: old code kept the spent token) and TestTwoHostsKeepEachOthersSignIns (two hosts saving 40 accounts each at once: old code lost 38 of 80) fail on the old code and pass; TestStopWithoutRenewalIsQuick keeps the quick stop. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestProvidersAnswerWhileListsComeIn and TestClaudeSignedOut, timing tests that pass alone and in their packages rerun. Not tried with real plugin accounts.
yetone
2026-10-03 15:47:08 +08:00 -
8b23ed03c6
antigravity: models as Antigravity lists them — its picker's order, its context, output and images (0000FF on Discord: Antigravity offers Claude Opus 5.5 and Sonnet 5.5, magpie still shows 4.6) — magpie already lists Antigravity's models live from fetchAvailableModels, with no Claude allowlist; the backend doesn't offer 5.5 yet: the signed-in account's list today (prod and daily, hub 2.19.1) has only claude-opus-4-6-thinking and claude-sonnet-4-6, generateContent answers 404 for claude-opus-5-5, claude-sonnet-5-5 and their -thinking ids, CLIProxyAPI's antigravity registry and Antigravity-Manager have no 5.5, and the AI Developers Forum still asks Google to add it (2026-09-30); agy 1.2.16 names claude-opus-5-5@default only for the enterprise Vertex gateway. So no ids are guessed in; what changes is how a model Google adds arrives: the list was sorted by id (Opus 4.6 before any 5.5) and took context from magpie's catalog by id (Anthropic's 1M, where Antigravity gives Claude 250k) and images from "not gpt-oss". Now models() follows agentModelSorts (the picker's order, newest first; models not in it after, by id), and each model keeps the maxTokens, maxOutputTokens and supportsImages Antigravity gives it; quota windows keep their order. TestAntigravityModelsAsItListsThem fails on the old code (id order, no limits, a text-only model said to see). Against the real account in a temp HOME: Gemini 3.8/3.7/3.6 Flash first, Claude at 250000/64000, GPT-OSS 131072 without images. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestProvidersAnswerWhileListsComeIn and TestUserPath, timing tests that pass alone.
yetone
2026-10-03 15:44:54 +08:00 -
e144db09c2
gui: the Usage page's cards are arranged as the Agents page's rows are, by dragging their logos (owner: 用量页面能否支持供应商排序?像 agents 页面一样)
yetone
2026-10-03 15:42:25 +08:00 -
2c2ba3eb60
gui: the Hide accounts buttons have their tooltip, and once on it says how to show the accounts again (#653)
yetone
2026-10-03 15:33:04 +08:00 -
19e239c7bf
vision: while a model that sees describes images, agents are told every model takes them (Discord, Fate: with Settings › Vision set, a text-only model in Codex still said it "does not support image input") — the gateway already described an image for a text-only model on every wire format, but the agents were told the model was text-only (Codex input_modalities ["text"], opencode modalities, dsh/omp input, droid NoImageSupport, cline/zed/qoder/workbuddy flags…), so they turned the image away before magpie was asked. provider.Described, set by the gateway to whether seer() finds a describer (Vision names one, or Automatic finds a model that sees; not with Vision off), makes magpieModels (every agent's model file) and codexListed (the ChatGPT backend's /models list and its ETag) say images for every model; Vision changed in Settings rewrites the agents' lists (catalog.Touched). TestDescribedModelsTakeImagesInAgentsLists (Codex list, input_modalities, tag) and TestDescribedModelTakesImages (agent files) fail on the old code and pass; TestDshModelLimits and TestMiniMaxCode turn Vision off to keep testing a text-only model as such. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried in the Codex App with a real account.
yetone
2026-10-03 15:25:40 +08:00 -
919ceb3a68
provider: Bailian's decision model as a routing preset, and System One for custom providers (#647, Aimer779: Alibaba Cloud Bailian's decision-model-preview speaks TypeSafe's System One at POST <root>/systemone, and magpie only took it from TypeSafe's Jev) — a new preset, Bailian Decision Model (qwen icon, decide-only like TypeSafe Jev), asks decision-model-preview at its plan's root: Workspace · Beijing / Workspace · Singapore (https://{WorkspaceId}.<region>.maas.aliyuncs.com/compatible-mode/v1, the editor asks for the workspace ID and fills it in) or Token Plan · Beijing (token-plan.cn-beijing…, sk-sp- keys). Saving with the workspace still unfilled is refused, both in the editor and in provider.Add. A Bailian host has no /models for it, so its list is the one model, checked by a System One ask. A custom provider can now be a System One API: the CLI's decide=<root> (with models=… named anything, not only jev-*), workspace= and region=/plan= for a preset's plan; the editor's API seg has a fourth option, System One, whose Detect APIs posts a test question to <root>/systemone with the model typed, and a decide-only custom provider passes the "base URL is needed" check. A decide-only provider's first model is what it is asked as (Jev() no longer assumes jev-*), and its models stay routing groups' classifiers, never agents'. TestBailianDecisionPreset, TestCustomSystemOne, TestProviderSystemOne and TestProviderDecidePairs fail on the old code (undefined BailianDecision / DetectDecide, unknown decide=); internal/gui/tests/system-one.test.cjs (webkit, en/zh) covers the workspace, the Singapore and Token Plan plans, TypeSafe's unchanged editor and a custom System One detected and added. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestProvidersAnswerWhileListsComeIn, a timing test that passes alone. Not tried against a real Bailian key.
yetone
2026-10-03 15:17:57 +08:00 -
9ccabdfbd8
usage: quota cards draw what was left over time, against an even burn, and the tray card its cycle's line (#651, songlairui) — each reading magpie makes anyway of a subscription's windows (and of a plan bought with a key) is kept as a point in quota-history.json beside the config: provider, account, window, when read, percent left, the window's start and reset — no token, no prompt. A failed reading, one kept from before (As of), an unlimited window and a model family's aren't kept; Antigravity's pools are kept by pool. Within a cycle points are 5 minutes apart at least and a run of one figure is its two ends; a cycle ends where the window starts again (its reset passed, or moved further than the time between two readings, so a rolling window's isn't one). 45 days and 6000 points a window are kept. The Usage page's card has, under its meters, a line a window (several tiers of one account on one chart), broken at each reset, a dashed even burn from each window's start to its reset and an upright now line, with 2 days / Cycle (the account's longest current window, start to reset) in the app's segmented control, remembered, turning every card without moving the page. The tray's card has a thin line of its first window's current cycle. GET /v1/magpie/quotas/history (?days=, ?provider=, ?user=; local or LAN with the key, as /v1/magpie/quotas) and /api/usage/quotas/history serve it; /v1/magpie/quotas and
magpie quotastay snapshots. Computers sharing usage (WebDAV/S3, Settings › Sync › usage) put their history beside their days, sealed, as <id>.magpie-quotas, and merge the others': the union by account, window and time, two points within 30 s the newer, nothing twice however often they sync; an older magpie never reads the file. TestQuotaHistoryRecords, TestQuotaHistoryCycles, TestMergeQuotaHistory, TestQuotasHistory and TestQuotaHistorySharedBetweenComputers cover recording, cycles, pruning, merge, the API and two computers on one WebDAV folder; quota-curve.test.cjs (WebKit, en/zh, light and dark) the curves, the toggle, no curve without readings, and the tray's line (Chromium doesn't start in this sandbox). go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried with real accounts; pay-as-you-go balances aren't drawn.
yetone
2026-10-03 15:10:58 +08:00 -
c91529f9aa
ci: the UI preview scrolls to what a PR changes further down a page (owner: 录屏的时候,有时候需要录制的功能区需要滚动到下面才能看到,但是现在并不会滚动,导致录制的内容里完全没有 PR 所修改的功能) — the recorder reached an element with Playwright's scrollIntoViewIfNeeded, a scroll no reader asked for, which magpie puts back (scrollOnPurpose / backToReader in app.js), so the page stayed at its top; a shot's target was only a clip of the screen, never scrolled to, so a close-up of something below the fold showed the window's foot instead; and a scroll step turned the wheel wherever the mouse was. bringIntoView now wheels each view that hides the element, innermost first, in small notches with the drawn mouse over it, until it is in the middle (or at the top when taller): click, hover, type and a shot's target use it, and a scroll step takes "to" (a selector to bring into view). The planner's outlines mark elements past the fold of their view "(below the fold)" and its guide says a shot without a target shows only the screen. PLAN_FILE walks a given plan instead of asking DeepSeek. Tried against a sandbox magpie web with six providers and a fixed plan (a shot of Hermes Agent's models button, clicking it, scrolling to a Gateway row): the old recorder's close-up showed the list's foot without Hermes and its Gateway shot the page's top; the new one centres both, the menu opens at Hermes, and the video shows each scroll.
yetone
2026-10-03 15:17:58 +08:00 -
860ed6618d
plugins: a 「国内镜像」 switch on the Plugins page downloads the list, plugins and Bun from mirrors in China first (Discord, akic404: GitHub/npm are slow from the mainland; asked for ghproxy) — Plugins › Mirrors in China, off by default, kept in settings (chinaMirror). On, source asks a copy of the very file before its official address: npm's registry (packages, versions, search) at registry.npmmirror.com, Bun's release zips at registry.npmmirror.com/-/binary/bun, and the community registry.json at cdn.jsdelivr.net/gh/magpie-community/plugins@<branch>; bun add gets BUN_CONFIG_REGISTRY=npmmirror unless the environment names a registry. No proxy: gh-proxy (MAGPIE_MIRRORS' GitHub fallback) handles nothing the switch sends, since a proxy could hand back other code. A mirror asked first that can't answer (404/403/5xx, e.g. a version it hasn't synced) falls through to the official address; npm's weekly downloads stay api.npmjs.org's (npmmirror counts its own). Checked by hand: npmmirror's bun-v1.4.2 darwin-aarch64 zip has the SHA-256 pinned in bun.go, jsDelivr's registry.json is byte-identical to raw.githubusercontent's, and bun 1.4.2 add through npmmirror locks the same sha512 integrity npmjs gives. TestChinaFirst, TestChinaComesFirst, TestChinaMirrorAnswers, TestChinaMirrorsMissIsAskedOfficially, TestDoFaithful, TestBunInstallsFromChinaMirror and TestPluginsMirrorSwitch cover it. A live run with the switch on fetched the list from jsDelivr, npm info from npmmirror and Bun from npmmirror (checksum passed); a sandbox magpie web showed the switch in the Plugins head, saved it, kept it after a reload, and a click didn't move the page. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried from inside mainland China.
yetone
2026-10-03 15:14:42 +08:00 -
b84b203256
sessions: Droid's (Factory CLI) sessions are listed, with what they spent and
droid --resume <id>(Discord, 谟竭: "magpie中会话功能中不显示droid 这个agent") — the Sessions view read no droid sessions at all. droid keeps each under ~/.factory/sessions (or $FACTORY_HOME_OVERRIDE/.factory), a folder per cwd (older ones in sessions/ itself): <id>.jsonl starts with a session_start (id, title, cwd/lastCwd, parent + forkedAtMessageId for a fork, callingSessionId for a subagent or /btw), then message events with an ISO timestamp and Anthropic-style content; <id>.settings.json holds the running tokenUsage (inputTokens without the cache, outputTokens with thinking) for its model. The title is the first typed prompt (tagged reminders skipped), else droid's; prompts, replies and tool calls count; a subagent's spend counts in the session that called it, a fork skips the lines it copied; custom:<id> models are priced as the model their customModels entry asks for (magpie's own custom:magpie/<ref> → <ref>), else the id without droid's -[x]-N tail. The total isn't split by turn, so it counts on the day of the last message. Format read from droid 0.231.0's own code. TestDroid fails on the old code (0 sessions) and passes; go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried against a real droid session (no Factory account on this machine).
yetone
2026-10-03 15:08:38 +08:00 -
154c7e8d96
gateway: a Gemini functionResponse is the user's turn whatever role it came under, so agy's conversations end with the user's turn (#650, pwu4: Antigravity through a remote magpie answered from the second turn "Requests ending with a model turn are not supported") — Antigravity CLI, captured against a stub, sends each tool's result as {"role":"model","parts":[{"functionResponse":…}]} right after the call. parseGemini kept it in an assistant message, so once a turn ran a tool the request ended with the model's turn: straight to Code Assist, or through another magpie over Anthropic Messages (Chat and Responses happened to put it right). A functionResponse now starts a user message of its own, and the parts around it keep their role and order. TestAgyToolResultsAreTheUsers (agy's captured shape, with and without a tool, direct and via Anthropic, Chat and Responses) fails on the old code. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried against real Antigravity.
yetone
2026-10-03 15:04:34 +08:00 -
52ac04d8da
gateway: a tool whose input_schema has anyOf/oneOf/allOf at its root reaches Anthropic-protocol vendors as an object, and moved Factory users get the plugin that keeps its constraints (#646, tedestar; magpie-community/plugins#12, SadWood) Codex's codex_app automation_update takes an anyOf of objects at its root, and Claude models behind Factory answered every request offering it with 400 "input_schema does not support oneOf, allOf, or anyOf at the top level". Factory is a moved subscription, so the fix that reaches users is the plugin: factory 0.1.13 (SadWood's #12) nests such a schema under one "arguments" property, constraints intact, and unwraps the calls on the way back; migrate_factory.go's min is 0.1.13, so keepMovedCurrent updates moved users. The built-in Anthropic outbound (buildAnthropic) now does what Grok's objectRoot did: provider.ObjectRoot, shared, merges a root allOf's branches and the object branches of a root anyOf/oneOf (a field each requires stays required), following local $refs; a schema without a root combinator is sent byte for byte. TestAnthropicToolSchemaRoot fails on the old code. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestClaudeSignInOverStaleCredentials, a timing test that passes alone (3/3). Not tried against a real Factory account.
yetone
2026-10-03 15:02:55 +08:00 -
e32c49ff76
fix(gui): keep library All chip stable during hover (#648)
Snowyy
2026-10-03 15:01:33 +08:00 -
e2a22596cc
update: What's new leaves out the Chinese notes' 安装 section too (#649) — every release's notes end with an Install section that StripInstall takes out, but it matched only the English heading, so with magpie in Chinese each release in What's new repeated 从 usemagpie.ai 下载… StripInstall now knows the heading in each language the notes come in (Install, 安装, 安裝, インストール); a bullet that merely mentions 安装 stays. TestStripInstall covers it and fails on the old code.
yetone
2026-10-03 14:59:58 +08:00 -
11a09d418c
gateway: every vendor's "too long" reaches the agent as context_length_exceeded and fails over to nobody, and a spent budget isn't asked again in place (owner: 继续做第 4 项,错误分类接入 failover) — pi's two tables (packages/ai/src/utils/overflow.ts, retry.ts) against magpie's classifier: 15 of pi's 25 overflow texts weren't known, so the agent got the vendor's words and didn't compact, and four were worse: Kimi's "exceeded model token limit" rested the account as out of quota, and z.ai's model_context_window_exceeded, Ollama's "prompt too long; exceeded max context length" and "token limit exceeded" went to every other account in turn (quotaWords' "exceeded"). tooLongRe takes pi's patterns (request_too_large, Gemini, xAI, Groq, OpenRouter, Together, llama.cpp, LM Studio, Copilot, MiniMax, Kimi, DS4, z.ai, Ollama, DashScope), and overflowed (a 400/413/422 saying so) is neither retryable nor a quota or credit failure, so nobody rests and it is answered at once. "out of budget" / "budget exceeded|exhausted" are a used-up plan: a 429 was a rate limit asked three times in place, a 400 was answered without trying the next account. TestEveryVendorsOverflow and TestOutOfBudgetIsntRetriedInPlace fail on the old code (26 failures). Real accounts, sandbox magpie, a 2.2M-token request: Qoder's "invalid params, context window exceeds limit" came back from the old build as 413 api_error with no code (Claude Code and Codex wouldn't compact) and is now 400 context_length_exceeded / Anthropic "prompt is too long: …"; WorkBuddy, WorkBuddy AI, Kiro and Grok (SuperGrok) answer context_length_exceeded too, and ordinary requests through each still answer. go vet, GOOS=linux/windows builds and go test -tags nogui -count=1 ./... under a temp HOME pass. Silent overflow (usage past the window on a 200) isn't detected: the reply is already the agent's by then.
yetone
2026-10-03 14:55:34 +08:00 -
eb7c45ac9f
codex: a Settings switch has Codex's OpenAI models say multi-agent V1, so a GPT lead's subagents can run on magpie's other models (#141, congee949: with "v1" in the entry and multi_agent_v2 off, the Codex App's GPT lead spawned V1 subagents on Opus/Grok groups and they ran there) — Settings › "Codex subagents on any model", off by default. On, the ChatGPT backend's /models list magpie passes Codex (and the cached one it falls back to), the codex/ entries and the GPT routing groups (the Fast ones) in model_catalog_json say multi_agent_version "v1"; nothing else in an entry changes, base_instructions untouched. The setting is in CodexListTag as a "v1." prefix (so neither tag is found inside the other), so ETag and X-Models-Etag change and Codex asks again; catalog.Touched rewrites the catalog. Codex keeps the stamped list in models_cache.json, so the backend's own versions are kept in codex-agent-versions.json (from each fresh list, and from an unstamped cache) and CacheEntries puts them back when the cache's ETag is a stamped one: turned off, gpt-6 is "v2" again and a model the backend gave none has none. Codex's features.multi_agent_v2=true still wins, and a thread keeps its version. TestCodexAgentsV1Entries, TestCodexAgentsV1CacheRestores, TestCodexModelsAgentsV1 cover on/off/revert and the ETag; go vet, builds (darwin, linux, windows) and go test ./... under a temp HOME pass. Not tried in the Codex App.
yetone
2026-10-03 14:35:35 +08:00 -
69368007b0
termux: support Android builds and installation (#644)

XYenonandAmp
2026-10-03 14:29:32 +08:00 -
18e6cb8140
gateway: a ChatGPT account's Automatic image model is gpt-image-2, the one Codex CLI asks for, and chatgpt.com's 403 says what it likely means (#545) — Automatic picked gpt-image-2.5 as the newest, but Codex CLI only ever asks the images API for gpt-image-2, and a plan may be refused other models: azir12345's images with no model set came back "chatgpt.com: 403 Forbidden: {"detail":"Forbidden"}". Image requests also send Codex's x-codex-image-turn-id (codex-rs ext/image-generation). gpt-image-2.5 stays pickable in Settings → Images. TestCodexAccountDraws (Automatic) and the new TestCodexDrawRefused fail on the old code and pass. go vet, builds (darwin, GOOS=linux, GOOS=windows) pass; go test -tags nogui ./... under a temp HOME passes but TestProvidersAnswerWhileListsComeIn, TestUserPath and TestClaudeSignedOut, timing tests that pass alone. Not tried against a real ChatGPT account, so whether 2.5 is what was refused is unconfirmed.
yetone
2026-10-03 14:28:53 +08:00 -
243c5a0429
gateway: ModelScope's image models draw, on its async task API, one at a time (#645) — Qwen/Qwen-Image-2.1 at api-inference.modelscope.cn always came back "drew nothing": its images API answers without OpenAI's data (a task_id, or images[].url), so nothing was read and a 502 was made of it. A provider at ModelScope (the preset or one added by hand) now starts a task with X-ModelScope-Async-Mode, asks GET /tasks/<id> with X-ModelScope-Task-Type: image_generation until SUCCEED (output_images) or FAILED, and reads a sync answer's images too. It is sent model, prompt and size only, and an edit's images as image_url. ModelScope holds one task per user, so magpie draws there one image at a time per key, n of them in turn, and asks again after 3/8/15 s when told the queue is full or 429. A failed task, or any images API answer with no image, now says what the vendor said (vendorMessage reads ModelScope's errors.message) instead of "drew nothing". TestModelScopeDraws, TestModelScopeOneAtATime, TestModelScopeQueueFull, TestModelScopeSaysWhy and TestImagesAPINoImageSaysWhy run against a stub of ModelScope's API and fail on the old code. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and go test -tags nogui -count=1 ./... under a temp HOME pass but TestUserPath, a timing test that passes alone. Not tried against the real ModelScope.
yetone
2026-10-03 14:28:43 +08:00 -
2f937f3f39
fix: defer unfinished session trace roots until completion (#633)
mofelee
2026-10-03 14:28:10 +08:00 -
84554e57e7
library: Claude Desktop takes skills, into Cowork's skills-plugin with their manifest entries (#638) — Desktop had MCP servers only and showed as "has no skills folder". Every account's local-agent-mode-sessions/skills-plugin/<org>/<account> (one with a manifest.json or .claude-plugin/plugin.json, in Claude and Claude-3p alike, no id hard-coded) gets a copy of each skill it is given — a real folder, as Cowork won't read a linked skill's other files from outside the plugin — and an entry in manifest.json (skillId, name, description from SKILL.md, creatorType user, syncManaged false, updatedAt, enabled), which Desktop lists from. The other entries and keys, and an entry's enabled and other fields, stay; times are written as the manifest's are (ms or ISO). A name Desktop has of its own (built in, or made there) is left and reported. The copy carries magpie's mark with the hash of what was copied: it is made again when the library's skill changes, left as it is once changed in Desktop (reported), and set aside into the backups rather than deleted when the library stops giving it; only magpie's copies and entries are ever taken out, and magpie's entry whose folder went gets it back. Desktop's own skills aren't offered to bring in. The Skills tab says Desktop shows changes once its window is reloaded (⌘R / Ctrl+R). TestClaudeDesktopSkills (two accounts, Claude and Claude-3p) and library-desktop-skills.test.cjs (WebKit, en/zh) cover it. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried with a real Claude Desktop.
yetone
2026-10-03 13:51:33 +08:00 -
960e611a79
fix(davsync): sync independent gateway key changes (#643)
TryWorld
2026-10-03 13:49:32 +08:00 -
090f7733ef
gateway: Antigravity's Gemini variants think with tools again, and a call the model writes out as text is a call (#636) — a variant id (gemini-3.8-flash-high, the one an effort picks for gemini-3.8-flash) went with includeThoughts but no thinkingLevel since
2baad536, and told no level it all but stopped thinking once the request had tools and gave none of it back, where the -tiered id, sent a level, kept it. A variant is now told the level its id says (Flash minimal/low/medium/high, Pro's minimal as low, xhigh as high), so the id and the level still agree. The Code Assist decoder takes Gemini's namespace off a call's name (default_api:bash → bash), and a call written out in the reply's text, "…imports!call:default_api:bash{command:cat x}", becomes the tool call it meant (arguments as JSON members, <ctrl46>-quoted, or bare key:value), the text before it kept; text that only might start one is held until it is one or isn't, and an unfinished one stays text. Upstream 502/503 were already errors (HTTP status, or an error event mid-stream), not changed. TestCodeAssistAntigravityLevels and TestCodeAssistTextCalls fail without it. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried against a real Antigravity account.
yetone
2026-10-03 13:38:09 +08:00 -
181a9591bf
providers: oMLX is a local-server preset — its :8000 server speaks Chat, Responses and Anthropic Messages and asks no key on a loopback bind, so it joins Ollama and LM Studio in the add sheet's On this machine section instead of being typed as a custom provider (no issue: the gap was simply that oMLX, an OpenAI-compatible MLX server for Apple Silicon, was missing a preset). TestOmlxPreset fails without the change (no omlx preset). go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui -count=1 ./... under a temp HOME pass but for TestBunThroughBridge, which fails on a clean tree too (a local bun, unrelated to this change). (#635)
erlinerd
2026-10-03 13:36:43 +08:00 -
65c0c346fd
provider: moved Factory takes plugin 0.1.12, which reaches Factory again from Claude Code with a global CLAUDE.md or a SessionStart hook, and from Claude Desktop (#634) — Factory refused the instructions reminder's "(user's private global instructions for all projects)", Claude 5's runtime context after a SessionStart hook's output (as a system message or folded into the user's turn), and the model line inside Claude Desktop's system prompt; plugins f28aac3 adapts the three, published. keepMovedCurrent updates moved users. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 13:34:09 +08:00 -
e2d6762464
fix(backup): restore saved provider priority order (#642)
TryWorld
2026-10-03 13:33:19 +08:00 -
5850ce21a6
fix(accounts): separate usage deduplication from results (#641)
TryWorld
2026-10-03 13:33:12 +08:00 -
28a0b65225
fix(library): preserve sign-ins on rejected MCP renames (#640)
TryWorld
2026-10-03 13:33:05 +08:00 -
f24e41178d
fix(edit): keep JSONC inserts out of leading comments (#639)
TryWorld
2026-10-03 13:32:58 +08:00 -
94008ce66f
update: say so when the
magpiecommand is a copy the app left behind (#623)
erlinerdandClaude Code
2026-10-03 13:32:42 +08:00 -
21d5d1c43a
test(update): execute native Windows install checks in CI (#637)
TryWorld
2026-10-03 13:28:16 +08:00 -
2e3fffe794
tray: the Mac's menu bar icon stays lit while the panel is open (#629)
Liken Tan
2026-10-03 12:53:23 +08:00 -
ec3c64c140
claude: pass output_config.format to Claude subscription runs as --json-schema (#627)


2026-10-03 12:51:57 +08:00 -
1ca56a9ad8
fix(update): roll back failed Windows binary installs (#632)
TryWorld
2026-10-03 12:51:51 +08:00 -
c90e66f7bb
test(settings): shorten hard-link save stress test (#630)
TryWorld
2026-10-03 12:51:45 +08:00 -
48c496d049
agents: turning ultracode or an effort on no longer folds every other agent away (开启 claude code 开启 ultracode 后为啥其他 agent 就不见了啊?) — the Agents list shows every agent while none is set up, and once one is, folds those nothing is set on under Show N more. Set up was any field with a value, so Claude Code's ultracode toggle — how its own model runs, not a model magpie picked — counted, and the seventeen others went under Show 17 more at the click. Now a model, a provider or a role set counts; ultracode and the efforts (effort/thinking, a tier's, the subagents') don't. The fold is decided in app.js alone (the tray panel draws the same; Go and the TUI have no such rule). tests/agent-tweak-fold.test.cjs (chromium and webkit): clicking ultracode on, or an effort, a tier's effort, a subagent effort set alone, keeps all four agents drawn with no Show more; a model set folds the other three. 12/12 pass; against the old app.js 10 fail
yetone
2026-10-03 12:47:20 +08:00 -
5ca143bff3
provider: Claude usage reads the reset times Claude Code 2.1.285 on prints, "Oct 9, 2:59pm (UTC)" with a comma where "at" was (#631) — claudeResetTime took only "Oct 9 at 2:59pm", so the weekly windows lost their reset time. It now takes "Jan 2, 3:04pm", "Jan 2, 3pm" and the same with a year; TestParseClaudeUsage covers them (fails without the change). go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 12:45:15 +08:00 -
dff14ff465
gui: the panel's reads build the catalog once per request (owner: 这个应该是 magpie API 慢, on a Discord report that the window renders slowly) — provider.Resolve rebuilt every provider's catalog (24 providers, 270 models: 35-90ms) for each model it was asked about, and /api/state and /api/groups resolve one for every agent and row; plugin.Cached re-read the plugins' files for each PluginOf, and resolveIn's fallbacks read All() and every provider's Available() again. A GET under /api/ now holds what it builds (provider.Hold: the entries, the plugins, All, which providers list a model) for the request, at most 1s while requests overlap; a save drops it (catalog.Touched → catalog.Forget, plugin.OnChange, setMigration, and any non-GET request). Outside a request nothing is held, so the gateway and tests behave as before. On the owner's config: state 4.2s → 0.42s, groups 6.7s → 0.26s, providers 1.4s → 0.33s. Sandbox (fixed build, GETs looping): a model saved through /api/provider/save is in providers, groups and state at once and gone after the restore. TestHoldBuildsOnce, TestHoldSeesWrites (fails with Forget unset). go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 12:36:15 +08:00 -
b41090f8fa
site: /docs/import's presets are the app's (owner: 需要, after the zh page's missing ones) — the link builder and the Presets chips in English, Chinese and Japanese were behind internal/provider/presets.go: kimi-code(-cn), stepfun(-cn), xiaomi, tencent-tokenhub(-cn), qwen-token-plan, bedrock, clinepass, kilo, commandcode, pipellm and cherryin were missing, and so were the plans of zhipu, zai, stepfun, xiaomi, baidu-qianfan, huaweicloud and bedrock. All 47 importable presets are now listed in the app's order, each with its regions (the first, the default, as no region=); azure and remote-magpie (an address of the user's own) and the Jev routers (no models) are left out. yylx loses its Default option, which was its first region, auto, again. Every preset and region link the three pages build parses with provider.ParseImport (70 links); WebKit at 320/390/1280: 47 options and chips, regions switch and land in the link, nothing scrolls sideways.
yetone
2026-10-03 12:31:05 +08:00 -
3e024957a5
provider: moved Factory, Grok, Kiro, MiMo, Qoder and WorkBuddy take the plugin versions that renew their sign-ins ahead of time through auth.refresh (owner: 把社区插件都迁移到 auth.refresh) — factory 0.1.11, grok 0.1.6, kiro 0.1.6, mimo 0.1.6, qoder 0.2.3, workbuddy 0.1.7 (plugins c64f555..319eee2, published): each gives auth.refresh with a refreshLead above its own check before a request, under the same one-refresh-at-a-time as that check, so magpie renews an account once before its requests, models and usage ask, and a refresh token is never spent twice. Kiro and WorkBuddy throw every failure plainly, as their built-ins never marked an account; the others mark a refusal signIn "expired" as their request paths already did. keepMovedCurrent updates moved users to them. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass; go test -tags nogui -count=1 ./... under a temp HOME passes but TestProvidersAnswerWhileListsComeIn, TestUserPath and TestClaudeSignedOut, timing tests that failed under load 11 and pass alone.
yetone
2026-10-03 12:13:15 +08:00 -
a3ee3b9240
gui: simplify OTLP settings and make export consent readable (#628)
mofelee
2026-10-03 12:09:29 +08:00 -
0a10be9cf9
agents: T3 Code gets a Thinking switch beside Reasoning for magpie's models (owner: T3 的 thinking 开关也加上吧) — each magpie custom model that thinks at some level (an effort other than none) now carries T3's boolean "thinking" option descriptor, on at first, as T3's own Claude Haiku has it. T3's Claude adapter sets Claude Code's alwaysThinkingEnabled from it, and Claude Code's requests with thinking off reach the gateway with none (thinking.disabled for non-Anthropic models), so the switch turns reasoning off. A model with Claude Code levels keeps its Reasoning pick, and Haiku-like ones get the switch alone. TestT3CodeEfforts covers it; t3Format accepts boolean descriptors. Not tried in a running T3 Code.
yetone
2026-10-03 11:58:08 +08:00 -
369fc1659d
site: the Chinese link builder offers the presets the English and Japanese ones do — 百度千帆 baidu-qianfan, 腾讯云 Token Plan, 华为云 MaaS and 火山方舟 volcengine with its Coding Plan / Agent Plan / 按量付费 regions were missing from /docs/zh/import's preset list. WebKit: the four are listed, volcengine shows its regions and builds #preset=volcengine®ion=agent, baidu-qianfan hides the region picker.
yetone
2026-10-03 11:54:22 +08:00 -
3c79152eb4
site: docs in Japanese (/docs/ja), and contents that work on a phone (owner: 文档也要支持日语,另外,文档要有友好的目录,在手机端也要有友好的目录) — /docs/ja/{start,intent,plugins,import} translate the English pages; every docs page gets the home page's language menu (English / 中文 / 日本語, the lang cookie) and a ja hreflang, /docs/ja opens the guide, and /ja/'s docs links go to the Japanese pages. docs.js (shared, replacing each page's inline scrollspy) builds the contents: every docs page, the current one's sections under it, the section being read marked with a pill (no left border); the list is sticky and scrolls on its own. Under 900px, where the contents were simply hidden (and under 600px the nav links too, so a phone had no way around the docs), a bar under the nav names the section being read and opens the contents as a menu that closes on a pick, a tap outside or Escape. The nav links give way to the contents under 1000px, long inline code wraps under 1100px, and .doc keeps .wrap's side padding (601-1168px ran the text to the screen's edge). node --test worker.test.mjs passes (/docs/ja redirect added); WebKit at 320-1280, light and dark, en/zh/ja: nothing scrolls sideways, the menu opens, jumps and closes, the bar follows the reading position.
yetone
2026-10-03 11:26:23 +08:00 -
7d7175cfb1
fix: preserve Langfuse coverage for first and auxiliary calls (#599)
mofelee
2026-10-03 11:21:10 +08:00 -
edab6ed492
settings: save atomically and preserve unreadable configuration (#621)
TryWorld
2026-10-03 11:21:04 +08:00 -
c221b9e2a9
davsync: a damaged file on the server is rebuilt, not failed on forever (#607)

尔立andClaude Code
2026-10-03 11:20:57 +08:00 -
6953627b10
agents: DeepSeek Harness in a WSL distro (lgtm on Discord: wsl中安装的dsh,目前magpie还是扫描不到,可以添加上吗?) — dsh was this machine's only: dsh(home) read DSH_HOME and wrote the gateway's own address. It is now dshAt(place), as Empryo and the others are: its home is the distro's ~/.dsh (a distro's DSH_HOME can't be read), and the gateway it names in a profile's route, the legacy llm-deepseek entry and Check is the place's (gw threaded through dshSync, dshSet, dshSetEffort, dshCheck and the route writers). wslKinds lists it (dir .dsh, bin dsh); a stopped distro's thinking options come from magpie alone, as its patch lists can't be looked at. KeepDshWired stays this machine's: a distro's route is written again on a sync. TestWSLDshProfiles (a profile's route names 172.20.0.1, a sync and dshWiredOnce leave it) and dsh in wslMore (probe, pick, stopped) fail without it. go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 11:16:12 +08:00 -
e1e3d7e29a
gateway: a rule naming a model that a group in the group has too sends the turn to it (#625, Koohoko: a group of group/x (Opus, Astra) and Astra on its own, a rule for Astra came out unready — "没有可用的账号或 Key" — and Opus answered; the same with Sol on 0.1.697) — a model met again is kept where it was first (provider's membersIn), so with the group listed ahead of it Astra was a member of that group only, and a rule naming Astra found no member of its own: unready, sent on to the rules after it (the group, Opus first). named counts as the rule's member a model a group in the group has where the group names it too, in ruleMembers, the rules after it (Then) and the member contexts a rule's tokens go by; Unready is the one going first not being the rule's own, and Instead the rule after it whose member it is. And with the rule's model going first, the rules of the group it is kept in (nestedRules) no longer pick another over it (modelRuled). TestRuleNamesAModelAGroupInItHasToo fails without either part (unready, from the group's first). go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui -count=1 ./... under a temp HOME pass (timeouts under full-suite load pass alone).
yetone
2026-10-03 11:12:06 +08:00 -
7f29f1ba14
provider: a Codex reset about to run out unused is spent shortly before it does (#624, jyuuroku16: 快到重置卡到期时间前,自动使用重置卡) — Auto-use only spent a reset once the account's week was used up and no other account could answer, so a reset the account never got that far for ran out unused. For the accounts with Auto-use on, the gateway now goes over them every 10 minutes (KeepResetsFromRunningOut): within 3 hours of the soonest reset running out (the credits' expires_at, already read for the card), if any of the account's windows has been used, it spends that reset — UseCodexReset spends the one that runs out first, so a longer-lasting one is kept. Nothing used means nothing to start again, and it is left to run out. An account is read only when there may be something to do: at most every 6 hours, at 3 hours before a reset runs out, every 10 minutes inside those 3 hours, 30 minutes after a failure. It doesn't count against the week's one reset (a reset lost anyway takes none of it) and spends under the same lock. Auto-use's tooltips (en, zh) say so. TestResetSpentBeforeItRunsOut, TestResetExpiryRetriesLater, TestSpendExpiringCodexResets (a fake ChatGPT: off → never read; on → the soon one spent, not the later one; the next pass doesn't read again); dropping the windows-used or the lead check fails them. go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui -count=1 ./... under a temp HOME pass but for the known flakes (each passes alone).
yetone
2026-10-03 11:11:22 +08:00 -
280797ecf6
perf: reuse model settings and coalesce classifier calls (#622)
Snowyy
2026-10-03 10:39:44 +08:00 -
23166a7d42
gateway: a custom tool's call magpie hands Codex has a ctc_ id, and a magpie model or group on OpenAI's API gets call ids OpenAI takes (Lullaby on Discord: Invalid 'input[155].id': 'fc_18da5b9a10256a3e00000011'. Expected an ID that begins with 'tsc'. 这个问题貌似还是没有修复, then "Expected an ID that begins with 'ctc'", auto-compaction failing with it) — two causes. A vendor's apply_patch, translated to Codex's custom_tool_call, was given an fc_ id as a function call is (itemPrefix), and OpenAI turns away a custom_tool_call whose id isn't a ctc_ one. And the tsc_ rename (
1a9c4ca6) ran only for Codex's own models: a magpie model or routing group relayed to OpenAI's API on a key (passthrough) sent the session's fc_ ids as they were. The id kinds are now one table, openaiItemPrefix (tool_search_call tsc_, custom_tool_call ctc_, the two OpenAI's errors name): calls are minted with them in the stream and the rendered reply, and callItemIDs (was searchCallIDs) renames fc_X to tsc_X / ctc_X before Codex's own /responses and /responses/compact and before a passthrough to an openai.com host, call_ids and the rest of the body byte for byte. A ChatGPT account's request keeps no ids (provider.codexInput), so it is left alone. TestCustomToolCallHasCtcID, TestMagpieModelOpenAICallIDs (a fake OpenAI behind the provider's proxy answering the same 400s, direct and through a group) and TestCodexOwnModelCustomCallIDs (turn and compaction) fail without the change; TestCustomCallIDsUntouched keeps a clean request byte for byte. go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 10:26:33 +08:00 -
9e1e0dbd87
gateway: an image model's picture reaches a Gemini client (#620, tao-bai: antigravity/gemini-3.1-flash-image 返回 parts: []) — through /v1beta generateContent and streamGenerateContent the answer came back with no parts, though candidatesTokenCount (1567) said the image was made. The IR had no event for a picture the model made: codeAssistDecoder (Antigravity, Gemini CLI and Factory's Gemini route) turned functionCall, thought and text parts into events and dropped inlineData, and geminiParts / geminiEncoder had nothing to write it back as. A new KImage event (Name the media type, Text the base64) carries it; the collector keeps it as an Image part, and the Gemini renderer and stream encoder send it as inlineData in its place among the text. A thought image (a draft, thought: true) stays with the reasoning and isn't sent, as before; thought text and signatures are untouched. Chat, Responses and Anthropic clients still don't get the picture (their renderers skip Image parts). TestGeminiImageModelReturnsItsImage (a fake Factory Gemini upstream, generateContent) and TestCodeAssistStreamsImages (Code Assist chunks through the Gemini stream encoder) fail without it with parts: []. Not tried against a real Antigravity account; the image part's thoughtSignature isn't returned to the client, so multi-turn image editing on Gemini 3 image models may still need it. go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 10:24:03 +08:00 -
abec0cae1c
gateway: a reasoning effort changed mid-thread keeps the upstream's cached prompt on GPT-6 (#617) — an agent switching effort changed the request's reasoning.effort, and with it the prefix OpenAI caches. OpenAI's Responses API takes the change as an input item instead (developers.openai.com/api/docs/guides/reasoning, "Change reasoning mid-conversation": {"type":"configuration_update","reasoning":{"effort":…}} before the next user message, the request-level effort unchanged, GPT-6 family). For a GPT-6 model through a ChatGPT account or OpenAI's own API, asked in Responses, magpie keeps per thread (conversation, prompt_cache_key, account, model) the effort it started at and where each change went: the top stays at the first effort, and the updates are put back at the same places on every later request (before the turn's first user message, else at the input's end; a turn asked again at another effort replaces its own update). A history that isn't the last one with more after it (compaction, edits), previous_response_id, truncation auto, context_management, a request without an effort or an agent sending its own updates goes as the agent sent it and starts the thread again — what every request cost before. An upstream that answers 400 to a request with updates is asked again as the agent sent it (trace: update); if that one goes, the account and model get no updates for a day. Other vendors (forVendor strips the items anyway) and older models are untouched. A preview, off unless MAGPIE_EFFORT_UPDATES=on, until it is seen on the real backends: one that took the item and ignored it would leave an effort change doing nothing, unseen. Tests: TestEffortChangeKeepsTheCache, TestEffortUpdateRefused (both fail with it off), TestTakesEffortUpdates, TestEffortChangeOtherVendor against a fake ChatGPT backend. Not tried against the real ChatGPT backend or OpenAI API: whether the backend honours the item (rather than ignoring it) and cached_tokens across a switch are unverified. go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 09:57:07 +08:00 -
d50651a1b6
gateway: a Codex subagent's sealed task goes to the routing group's ChatGPT account that answered its lead, not turned away (#619)
yetone
2026-10-03 09:51:22 +08:00 -
cb82822f3d
source: add opt-in China mirror fallback (#566)
YAYOI27
2026-10-03 09:50:59 +08:00 -
bf0f3e3f73
library: a remote MCP server signed in once in magpie is used by every agent without signing in again (#615) — a streamable-HTTP server behind OAuth (Neon, Notion, Supabase) had each agent run its own sign-in. The server's editor now has Sign in: magpie finds the authorization server from the server's 401 (RFC 9728 protected-resource metadata, RFC 8414/OIDC metadata, else the 2025-03 /authorize, /token, /register at its origin), registers itself (RFC 7591, a 127.0.0.1 redirect), opens the browser with PKCE S256 and the resource, and keeps the tokens in mcp-signins.json beside its other account secrets (0600, never the keychain). While signed in, the agents are given the gateway's /mcp/<name> for that server, without the Authorization the library has for it; the gateway passes POST (JSON or event stream), the GET stream and DELETE on with the Mcp-Session-Id and magpie's token, renews it 2 minutes before it runs out and once on a 401, one renewal per server at a time, and a sign-in the server won't renew is answered 502 "sign in to it again" (never a 401 the agent would act on). Signing out, a new URL or an SSE server gives the agents the server's own address as before; a rename keeps the sign-in and removing the server drops it. /mcp/ is local-only or LAN-shared with the key, and refuses a request with an Origin or a Host not naming this computer, so a web page can't borrow the sign-in through the browser (form posts, DNS rebinding), and isn't counted as busy or key-limited. WSL agents are given their distro's gateway address. The row says Signed in or Sign-in ran out; zh strings added. Tests: TestSignIn, TestSignInWithoutMetadata, TestSignInPage, TestNothingToSignIn, TestTokenRenewsBeforeItRunsOut (8 calls, 1 renewal), TestRenewRefused, TestRenewRefusedForGood, TestMCPProxy, TestMCPProxyStaysHere, TestMCPProxyNotForWebPages (fails without the Origin/Host check), TestSignedInServerGoesThroughMagpie against a local fake OAuth+MCP server; mcp-signin.test.cjs (webkit, en and zh). Not tried against a real Neon/Notion/Supabase sign-in. go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 09:36:04 +08:00 -
05bc2ffb92
provider: Cursor's plugin is kept at 0.1.8 or newer (plugins #11) — catalog entries are written as CallDynamicTool calls the model answers in, and a thinking-only turn is retried as an empty reply instead of ending the session. keepMovedCurrent updates moved users. go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui -count=1 ./... under a temp HOME pass.
yetone
2026-10-03 08:45:55 +08:00 -
7c583b32dd
provider: a Grok subscription is given every function's parameters as an object at the root (Fate on Discord: Codex through Grok fails "[invalid_client_tool_schema] mcp__codex_app__automation_update: tool parameter root must be an object type (root schema is an anyOf/oneOf union with a non-object branch)") — grokBody, which the Grok plugin's requests go through too, merges an anyOf/oneOf root's object branches (local $refs read): their properties, the fields all of them require; the other branches go. TestGrokBodyObjectRoot fails without it.
yetone
2026-10-03 07:31:35 +08:00 -
290062679d
gui: Show on a hidden agent nothing is set on says it stays under Not set up (Fate on Discord: the Agents panel's hide, show and restore aren't intuitive) — it moved from Hidden to Not set up, still folded, and the status said "Idle shown" while it stayed out of sight. It now says it stays under Not set up until a model is picked for it; one with a model set still says shown. show-unset-agent.test.cjs fails without it (WebKit, en and zh).
yetone
2026-10-03 07:26:29 +08:00 -
49ee7d82d9
fix(agent/codex): recognize CC Switch official OpenAI mirror for grouping and failover (#504) (#579)
Luis Araya
2026-10-02 16:48:49 -06:00 -
0ebce8b4ed
gateway: a translated Responses request doesn't ask the upstream to seal a tool's arguments (#613) — Codex marks spawn_agent's message "encrypted"; its calls go back to Codex as unsealed (encrypted_function_args []), so an upstream honouring the mark would hand the subagent ciphertext as its message. The marks are left out of the tools sent (unsealed). TestNamespacedCallKeepsArgsWhenSearchTakesOver checks the upstream isn't asked to seal.
yetone
2026-10-03 06:10:29 +08:00 -
71f9884ee7
gateway: a call from a Responses upstream keeps the arguments its finished call holds (#613) — Codex offers web_search beside its namespaced tools; on a provider not set to search by itself the request is translated rather than relayed, and spawn_agent (every namespaced tool) came back with arguments {}: the decoder took the argument deltas once any came, and dropped what output_item.done / function_call_arguments.done held. A call's arguments are now given once it is done, the fuller of the deltas and its done events (JSON first); a stream that ends with a call open gives what it has. TestNamespacedCallKeepsArgsWhenSearchTakesOver (the issue's request, stream and not: arguments {} without the fix), TestResponsesCallArgsFromDone.
yetone
2026-10-03 06:08:57 +08:00 -
77cc49543d
gui: a provider's models with none picked are drawn as served (#614: the one model unticked and saved was still "1 model" on the card) — with no pick agents are served the vendor's list, up to 24 of it, while the editor drew those chips plain, as if left out. They are now drawn as served (dashed, .auto), their title says why, and the hint says how to show agents none: tick Only through routing groups, or switch the provider off. provider-none-picked.test.cjs (WebKit, en+zh).
yetone
2026-10-03 06:05:06 +08:00 -
b878f17dc1
groups: a member can be switched off (#feedback on Discord: 希望路由组里的模型可以直接通过checkbox控制是否启用,测试路由规则的时候需要频繁的添加和删除路由组里的模型很麻烦,而且会丢失顺序) — each member in the group editor has a switch; one switched off (Group.Off) keeps its place in the order and its rules but is sent nothing until switched on again, a rule naming it falls to the group's order as for a member not ready. The card says (off) after it. A member whose reasoning changes or that is renamed stays off; a manual group sends to its pick whatever is off; switching every member of a routed group off is refused. TestGroupMemberOff, group-member-off.test.cjs (WebKit, en+zh).
yetone
2026-10-03 04:57:01 +08:00 -
f1ff6ce03a
providers: Qwen Token Plan (Jeremy on Discord: 千问的TokenPlan和dashscope是分开的endpoint) — Alibaba Cloud Bailian's Token Plan (personal and team) is a preset of its own at token-plan.maas.qianwenaiapi.com, chat completions at /compatible-mode/v1 and Anthropic messages at /apps/anthropic, on its own sk-sp- key that DashScope's pay-as-you-go hosts don't take. Its models are given as the plan's overview lists its text ones, for when the host lists none. Not tried with a real plan key. TestQwenTokenPlan.
yetone
2026-10-03 04:50:46 +08:00 -
bafdd6954b
agents: Empryo (#612) — picking a magpie model in Empryo adds a "magpie" provider at the gateway to ~/.empryo/config.json's providers (baseURL + modelsAPI, no envVar) and sets defaultModel to magpie/<catalog id>; the user's defaultModel is stashed and put back on leaving, magpie's provider goes again, and a file magpie made is removed when empty. The user's own providers and keys are left alone. The gateway now answers GET /v1 (and /v1/) with its info, as Empryo lists a keyless provider only when its baseURL answers. Also on WSL. Built from Empryo's docs and its public v2 code, not run against the Empryo binary. TestEmpryo, TestBaseURLAnswers (GET /v1 was 404 before).
yetone
2026-10-03 04:44:37 +08:00 -
564f8782c7
provider: keep conversation models on mixed decision providers (#609)

XYenonandAmp
2026-10-03 04:06:02 +08:00