Files
magpie/internal/agent
yetone 531dc0aa33 claude: a Claude model runs to its own window in Claude Code, not 272K, and magpie model compact on|off is the Long conversations switch from the terminal (Max on Discord: a [1m] model's context stopped at 272K, magpie wrote CLAUDE_CODE_AUTO_COMPACT_WINDOW back when it was taken out, and there seemed to be no way to change it) — on magpie, Claude Code was told CLAUDE_CODE_AUTO_COMPACT_WINDOW=272000 whatever its model, so a [1m] Claude model compacted at 272K, though Anthropic runs it to 1M (the cap was meant for other vendors' long windows: Chen's DeepSeek turns of ~550K). Now a main model that is one of Anthropic's Claude models, from whichever provider, has the env left out (magpie's own value taken away), and Claude Code compacts at the model's own window; another vendor's model of a longer window keeps the 272K cap unless Settings → Long conversations is on Full window. A value the user writes there is still kept. The switch was only in the app's Settings; magpie model compact [on|off] (alias full-context) shows and sets it, and the Settings row's description says how Claude models are treated (en, zh, ja, de). TestClaudeCompactWindow (a Claude [1m] model gets no 272000, set and synced; another vendor's after it is capped again) and TestModelCompactCmd fail on the old code. The Long conversations row read right in WebKit, en and zh. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass (TestClaudeFailureKeepsClaudeCodesStatus flaked once under load, passes alone).
2026-10-05 00:09:49 +08:00
..
agent: Codex on a routing group's model name is still connected, not "switched off it outside magpie" (#750, Windows 11, magpie 0.1.812, Codex 0.160.0: Codex set to group/auto-gpt-6-1-sol in magpie, its config.toml then reading model = "gpt-6.1-sol" with openai_base_url still magpie's gateway, and the Agents page kept saying 在 magpie 之外被从 … 切走了 with 重新接入, coming back a while after each reconnect) — the gateway takes a model's name without a provider in it as the group of that model (provider.GroupFor: gpt-6.1-sol is group/auto-gpt-6-1-sol), so Codex's requests still went to the group; but Drift compared the field with what magpie recorded setting (applied.json) by string, and gpt-6.1-sol is neither that nor one of magpie's models by magpieValue (isMagpie wants a provider/model id, and Codex's options list it as its own or not at all), so it read as "replaced". What writes gpt-6.1-sol into config.toml is not magpie (no agent path writes a group's model name; set writes the group id as picked) and wasn't found — the Codex app persisting its thread's model by its own name is the likely one — which is why it came back after each reapply. Drift now passes over a field whose value and magpie's recorded one reach the same routing group, one by the group's id and one by its model's name (sameGroup, groupNamed: a group/… id as it is, "magpie/" taken off, else GroupFor); Codex's internal wired() and Agent.Wired (through a new Agent.Routed hook, Codex's routed(): openai_base_url or magpie as its provider) count the group's model name as magpie's only when magpie set that group on the field and Codex's config still sends its model to the gateway, so a Codex taken off magpie on gpt-6.1-sol is not connected, and a Codex's own gpt-5.5 that happens to have an auto group is no more magpie's than before (failover's base URL is untouched). Disconnect takes the field off the group's model name as it does off the group's id (back to Codex's default), rather than leaving Codex asking OpenAI for gpt-6.1-sol. Another group's model (gpt-6.1) or one no group has (gpt-5.5) is still "replaced". The reporter's ask to say which setting differs: the drift's detail already names it ("model is …, not … as magpie set it", the base URL or provider table for unwired) in the status line's and the Apply again pill's tooltip; that is left as it is. Tests: TestCodexGroupByItsModelName (two providers serving gpt-6.1-sol and gpt-6.1, signed in with ChatGPT and with an API key: group/auto-gpt-6-1-sol set, then config.toml's model rewritten to gpt-6.1-sol — Wired and no drift; no route to magpie — not wired; gpt-6.1 and gpt-5.5 — replaced) and TestCodexGroupByItsModelNameDisconnect fail on the old code (not wired, drift replaced, gpt-6.1-sol and the base URL left after Disconnect) and pass. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried on Windows or with the reporter's Codex and groups; not checked: what in Codex rewrites the model to gpt-6.1-sol.
2026-10-04 13:11:23 +08:00
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.
2026-10-03 16:01:53 +08:00
agent: Cursor Private Inference, which magpie finds by its product.json and starts on magpie with a command its row copies, and whose /models gives each model's api_types and capabilities (#299, mamba on Discord) — the build (Cursor 3.23.x, the same app name, bundle id and ~/.cursor as Cursor) runs its agent locally and asks the endpoint in CURSOR_LOCAL_AGENT_BASE_URL / CURSOR_LOCAL_AGENT_API_KEY when its Open configuration has none; mamba confirmed it works with any account pointed at magpie. magpie writes nothing of Cursor's (its settings share Cursor's state.vscdb): the Agents page lists it when an app's product.json says "Cursor Private Inference" (/Applications, ~/Applications; %LOCALAPPDATA%\Programs on Windows; /opt and the like on Linux), and its row's one control, Copy launch command (复制启动命令), copies CURSOR_LOCAL_AGENT_BASE_URL=<gateway>/v1 CURSOR_LOCAL_AGENT_API_KEY=magpie-cursor-local '<app>' (PowerShell on Windows); in the tray panel the row copies it. Its notice says to quit it first (a second start hands over to the running one) and that a base URL in Open configuration comes first. /v1/models asked with its key gives each model api_types (the APIs its provider serves it on, all three for a group or a translated one; it asks Anthropic Messages only when no OpenAI one is listed) and capabilities (context_length, max_output_tokens, supports_vision); any other client's list is unchanged. usage.AgentOf matches a name before a UA prefix, so cursor-local isn't counted as Cursor. TestCursorLocal, TestCursorLocalModels and cursor-local-launch.test.cjs (WebKit, en and zh) fail on the old code; agy-launch and agent-* GUI tests pass on WebKit. Not tried with the real app (not installed here). go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-04 23:38:19 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
agent: JetBrains Air reaches magpie's models through a Magpie ACP agent (OnurBen on Discord: Air's model picker should list magpie and its routing groups, as AI Assistant's OpenAI-compatible provider does) — Air's own agents (Claude Agent, Codex, Gemini CLI, Junie) run on the accounts under Settings | Account | AI Providers, a sign-in or an API key with no base URL to point at magpie (AIR-4541 asks for one); what Air does take is any Agent Client Protocol agent listed in acp.json in its config folder (~/Library/Application Support/JetBrains/Air, $XDG_CONFIG_HOME/JetBrains/Air, %APPDATA%\JetBrains\Air) under agent_servers, and the models an agent reports at session/new are its model menu. The new air agent's model field adds one there, Magpie: OpenCode's ACP server (opencode acp, by its full path when found on PATH or in ~/.opencode/bin, as Air may not have the shell's PATH) with OPENCODE_CONFIG naming magpie-opencode.json beside acp.json, which holds magpie's provider, the model picked as the one a task starts on (and small_model) and enabled_providers [magpie], so the menu lists magpie's models and routing groups only; the user's own acp.json agents are kept, and disconnecting takes out that entry and that file. Sync keeps the provider's models current, Check reports the entry taken out by hand (set again puts it back) or the wiring changed, the notice says to pick Magpie in a new Air task, or to install OpenCode first when there is none; a model that isn't magpie's is refused, as Air's own agents are picked in Air. Icon: Air's wordmark from jetbrains.com; zh strings for the notices; README row. Checked with OpenCode 2.0.20's opencode acp under a sandbox HOME, as Air would start it: session/new's model option lists magpie/group/gpt-6-luna and magpie/openai/gpt-6.1-sol only, current the configured one (OPENCODE_CONFIG, OPENCODE_CONFIG_DIR, OPENCODE_CONFIG_CONTENT and the global config all do). Known gap, OpenCode's: with a provider's key set in the environment it starts with (OPENAI_API_KEY, ANTHROPIC_API_KEY, DEEPSEEK_API_KEY, even a dummy one), 2.0.20's ACP server lists that provider and none of its config's providers, model or enabled_providers, from any config file, project one included; an empty key or a credential in its auth.json doesn't. Not tried in Air itself. TestAirAddsMagpieAgent, TestAirWithoutOpenCode, TestAirCheckAndSync; go vet, builds (darwin nogui, GOOS=windows, GOOS=linux nogui) and go test -tags nogui -count=1 ./internal/agent/ ./internal/gui/ under a temp HOME pass.
2026-10-04 09:02:44 +08:00
agent: Alma is told which of magpie's models reason, so it offers thinking for every Codex model (#730, Magixyne: Alma's magpie provider listed codex/gpt-5.5, gpt-5.6-luna/-sol/-terra and gpt-6-astra with vision and tools only, no reasoning, and no thinking to pick) — magpie put its catalog into Alma with PUT /api/providers/:id/models as ids and names alone, and Alma (0.4.155, checked read-only in its app.asar out/main/index.js) works a model's capabilities out by its id: a models.dev entry (provider:id or bare id), a fuzzy one by substring only at chat time, then heuristics (a gpt-5 id gets vision); magpie's ids (codex/gpt-5.5) aren't models.dev's, so a Codex model came out reasoning false, and its getModels/getProviderModels add reasoningLevels only to a model that reasons. A model whose id models.dev happens to hold (openrouter-style ids) did reason, hence "部分模型". Alma's PUT keeps each availableModels entry's capabilityOverrides as sent (the ones it had when none are), and Lf lays them over what it worked out, in the provider list, the model picker and the chat request (Lt/Mt read capabilityOverrides.reasoning and reasoningLevels). almaModels now sends each model's capabilityOverrides (almaCaps): reasoning true for a model that thinks (Reasoning or levels), reasoningLevels as those of its levels Alma knows (low, medium, high, xhigh, max, Alma's own list for a provider's /models, in its order; none sent for a model with a thinking switch alone), vision when magpie takes its images, contextWindow and maxOutputTokens (maxTokens) when known; a model magpie knows nothing of gets none, so Alma keeps its own. An override the user set in Alma that magpie says nothing of (functionCalling, pricing) is sent back with magpie's laid over it (almaWithOverrides), and almaSameModels also compares magpie's keys, so a provider an older magpie filled is told on the next Sync and one already told isn't written again. The fake Alma in alma_test.go keeps overrides as Alma's handler does. TestAlmaToldReasoning (a gpt-5.5 with xhigh, minimal, low, medium, high, ultra → low, medium, high, xhigh; a switch-only thinker → reasoning alone; glm-4.6 → no reasoning, its window; nothing written when told; an older magpie's provider told again with the user's functionCalling and pricing kept) fails on the old code (gpt-5.5: null) and passes. go vet ./internal/..., go build -tags nogui ./..., GOOS=windows and GOOS=linux builds and go test -tags nogui ./internal/agent/ (its TestMain sandboxes HOME) pass; the full go test under a temp HOME was not run here (the sandbox refused the HOME override). Not tried in the reporter's Alma: magpie writes the overrides on its next sync of Alma's provider, and Alma shows them when its provider page is opened again.
2026-10-04 08:13:58 +08:00
agent: Alma is told which of magpie's models reason, so it offers thinking for every Codex model (#730, Magixyne: Alma's magpie provider listed codex/gpt-5.5, gpt-5.6-luna/-sol/-terra and gpt-6-astra with vision and tools only, no reasoning, and no thinking to pick) — magpie put its catalog into Alma with PUT /api/providers/:id/models as ids and names alone, and Alma (0.4.155, checked read-only in its app.asar out/main/index.js) works a model's capabilities out by its id: a models.dev entry (provider:id or bare id), a fuzzy one by substring only at chat time, then heuristics (a gpt-5 id gets vision); magpie's ids (codex/gpt-5.5) aren't models.dev's, so a Codex model came out reasoning false, and its getModels/getProviderModels add reasoningLevels only to a model that reasons. A model whose id models.dev happens to hold (openrouter-style ids) did reason, hence "部分模型". Alma's PUT keeps each availableModels entry's capabilityOverrides as sent (the ones it had when none are), and Lf lays them over what it worked out, in the provider list, the model picker and the chat request (Lt/Mt read capabilityOverrides.reasoning and reasoningLevels). almaModels now sends each model's capabilityOverrides (almaCaps): reasoning true for a model that thinks (Reasoning or levels), reasoningLevels as those of its levels Alma knows (low, medium, high, xhigh, max, Alma's own list for a provider's /models, in its order; none sent for a model with a thinking switch alone), vision when magpie takes its images, contextWindow and maxOutputTokens (maxTokens) when known; a model magpie knows nothing of gets none, so Alma keeps its own. An override the user set in Alma that magpie says nothing of (functionCalling, pricing) is sent back with magpie's laid over it (almaWithOverrides), and almaSameModels also compares magpie's keys, so a provider an older magpie filled is told on the next Sync and one already told isn't written again. The fake Alma in alma_test.go keeps overrides as Alma's handler does. TestAlmaToldReasoning (a gpt-5.5 with xhigh, minimal, low, medium, high, ultra → low, medium, high, xhigh; a switch-only thinker → reasoning alone; glm-4.6 → no reasoning, its window; nothing written when told; an older magpie's provider told again with the user's functionCalling and pricing kept) fails on the old code (gpt-5.5: null) and passes. go vet ./internal/..., go build -tags nogui ./..., GOOS=windows and GOOS=linux builds and go test -tags nogui ./internal/agent/ (its TestMain sandboxes HOME) pass; the full go test under a temp HOME was not run here (the sandbox refused the HOME override). Not tried in the reporter's Alma: magpie writes the overrides on its next sync of Alma's provider, and Alma shows them when its provider page is opened again.
2026-10-04 08:13:58 +08:00
agent: Alma is told which of magpie's models reason, so it offers thinking for every Codex model (#730, Magixyne: Alma's magpie provider listed codex/gpt-5.5, gpt-5.6-luna/-sol/-terra and gpt-6-astra with vision and tools only, no reasoning, and no thinking to pick) — magpie put its catalog into Alma with PUT /api/providers/:id/models as ids and names alone, and Alma (0.4.155, checked read-only in its app.asar out/main/index.js) works a model's capabilities out by its id: a models.dev entry (provider:id or bare id), a fuzzy one by substring only at chat time, then heuristics (a gpt-5 id gets vision); magpie's ids (codex/gpt-5.5) aren't models.dev's, so a Codex model came out reasoning false, and its getModels/getProviderModels add reasoningLevels only to a model that reasons. A model whose id models.dev happens to hold (openrouter-style ids) did reason, hence "部分模型". Alma's PUT keeps each availableModels entry's capabilityOverrides as sent (the ones it had when none are), and Lf lays them over what it worked out, in the provider list, the model picker and the chat request (Lt/Mt read capabilityOverrides.reasoning and reasoningLevels). almaModels now sends each model's capabilityOverrides (almaCaps): reasoning true for a model that thinks (Reasoning or levels), reasoningLevels as those of its levels Alma knows (low, medium, high, xhigh, max, Alma's own list for a provider's /models, in its order; none sent for a model with a thinking switch alone), vision when magpie takes its images, contextWindow and maxOutputTokens (maxTokens) when known; a model magpie knows nothing of gets none, so Alma keeps its own. An override the user set in Alma that magpie says nothing of (functionCalling, pricing) is sent back with magpie's laid over it (almaWithOverrides), and almaSameModels also compares magpie's keys, so a provider an older magpie filled is told on the next Sync and one already told isn't written again. The fake Alma in alma_test.go keeps overrides as Alma's handler does. TestAlmaToldReasoning (a gpt-5.5 with xhigh, minimal, low, medium, high, ultra → low, medium, high, xhigh; a switch-only thinker → reasoning alone; glm-4.6 → no reasoning, its window; nothing written when told; an older magpie's provider told again with the user's functionCalling and pricing kept) fails on the old code (gpt-5.5: null) and passes. go vet ./internal/..., go build -tags nogui ./..., GOOS=windows and GOOS=linux builds and go test -tags nogui ./internal/agent/ (its TestMain sandboxes HOME) pass; the full go test under a temp HOME was not run here (the sandbox refused the HOME override). Not tried in the reporter's Alma: magpie writes the overrides on its next sync of Alma's provider, and Alma shows them when its provider page is opened again.
2026-10-04 08:13:58 +08:00
library: an agent whose folder is a file isn't written, and skills reach 13 more agents with one link in ~/.agents/skills for those that share it (neiko on Discord: with DeepSeek Harness not installed the Library kept failing on "open ~/.dsh/AGENTS.md: not a directory" and ~/.dsh/config.yaml; inaction: the skills list is short of the Agents page, Kimi Code has none). An agent counted as there when its folder path existed or its command was on PATH, never asking whether the path was a folder — a file at ~/.dsh, or another dsh, made DeepSeek Harness look installed. Now an agent whose folder is a file (or under one) isn't detected (agent.Taken; Goose's, Cindy's and Claude Desktop's own checks want a folder too), a Library target leaves out each place a file stands in the way of, one with none left isn't listed, and an agent given no MCP server with none of magpie's isn't read. Skills: Kimi Code, Goose and Cindy get ~/.agents/skills (Kimi's ~/.config/agents/skills when there, as Kimi reads it first; never ~/.kimi/skills, which would hide Claude Code's from it); Command Code, Devin, Hermes, Droid, Cline, Qoder, Qoder CN, Grok, WorkBuddy, Hanako and fx their own skills folder; Kimi, Goose and Grok a project's .agents/skills. The shared folder is filled first, and an agent that reads ~/.agents/skills besides its own (Codex, Gemini CLI, OpenCode, Crush, DeepSeek Harness and those above) gets no second link to a skill already there. Tested with new taken_test.go (neiko's two errors without the change) and agent_skills_test.go (skills folders, written once, a shared skill imported for Kimi), in sandbox HOMEs; library-items and shared-skills 24/24 in Chromium and WebKit; go vet, go build (-tags nogui, GOOS=linux, GOOS=windows), go test -tags nogui ./... pass. Not tried with real Kimi Code, Goose or Cindy.
2026-09-30 14:40:41 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
claude: a Claude model runs to its own window in Claude Code, not 272K, and magpie model compact on|off is the Long conversations switch from the terminal (Max on Discord: a [1m] model's context stopped at 272K, magpie wrote CLAUDE_CODE_AUTO_COMPACT_WINDOW back when it was taken out, and there seemed to be no way to change it) — on magpie, Claude Code was told CLAUDE_CODE_AUTO_COMPACT_WINDOW=272000 whatever its model, so a [1m] Claude model compacted at 272K, though Anthropic runs it to 1M (the cap was meant for other vendors' long windows: Chen's DeepSeek turns of ~550K). Now a main model that is one of Anthropic's Claude models, from whichever provider, has the env left out (magpie's own value taken away), and Claude Code compacts at the model's own window; another vendor's model of a longer window keeps the 272K cap unless Settings → Long conversations is on Full window. A value the user writes there is still kept. The switch was only in the app's Settings; magpie model compact [on|off] (alias full-context) shows and sets it, and the Settings row's description says how Claude models are treated (en, zh, ja, de). TestClaudeCompactWindow (a Claude [1m] model gets no 272000, set and synced; another vendor's after it is capped again) and TestModelCompactCmd fail on the old code. The Long conversations row read right in WebKit, en and zh. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass (TestClaudeFailureKeepsClaudeCodesStatus flaked once under load, passes alone).
2026-10-05 00:09:49 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
2026-10-04 20:33:12 +08:00
claude: a Claude model runs to its own window in Claude Code, not 272K, and magpie model compact on|off is the Long conversations switch from the terminal (Max on Discord: a [1m] model's context stopped at 272K, magpie wrote CLAUDE_CODE_AUTO_COMPACT_WINDOW back when it was taken out, and there seemed to be no way to change it) — on magpie, Claude Code was told CLAUDE_CODE_AUTO_COMPACT_WINDOW=272000 whatever its model, so a [1m] Claude model compacted at 272K, though Anthropic runs it to 1M (the cap was meant for other vendors' long windows: Chen's DeepSeek turns of ~550K). Now a main model that is one of Anthropic's Claude models, from whichever provider, has the env left out (magpie's own value taken away), and Claude Code compacts at the model's own window; another vendor's model of a longer window keeps the 272K cap unless Settings → Long conversations is on Full window. A value the user writes there is still kept. The switch was only in the app's Settings; magpie model compact [on|off] (alias full-context) shows and sets it, and the Settings row's description says how Claude models are treated (en, zh, ja, de). TestClaudeCompactWindow (a Claude [1m] model gets no 272000, set and synced; another vendor's after it is capped again) and TestModelCompactCmd fail on the old code. The Long conversations row read right in WebKit, en and zh. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass (TestClaudeFailureKeepsClaudeCodesStatus flaked once under load, passes alone).
2026-10-05 00:09:49 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
codex: on magpie API, Codex's own model as the default keeps magpie as its provider and magpie's models in its picker (#701, nullburn: Codex 选回原生默认模型后,第三方模型目录消失(已选择 magpie API)) — with Codex's sign-in set to magpie API, picking one of Codex's own models (gpt-6-luna) as its default in the Agents row ran unroute(): model_provider, model_catalog_json, openai_base_url and magpie-models.json all went, so every third-party model left Codex's picker while the row still said magpie API; and choosing magpie API while on Codex's own model wired nothing (login.Set only re-ran set for a magpie model). Now, on magpie API, Codex's own model goes as magpie serves it on the ChatGPT account there (codexOwnViaMagpie: gpt-6-luna -> codex/gpt-6-luna, the entries shown to Codex first), so set() takes the magpie branch and only the default changes; the picker's OpenAI group offers those ids under their own names (Label gpt-6-luna) so the value matches; one magpie doesn't serve (the ChatGPT subscription off in magpie) is refused with a message naming both ways out, the config untouched, rather than quietly unwired; choosing magpie API on Codex's own model wires it at once; Sync wires a config an older magpie left so (#701's: model = "gpt-6-luna", sign-in api). Back on ChatGPT, a codex/… default turns into Codex's own model again, straight to OpenAI as before (codexOwnOf); the ChatGPT sign-in's paths are otherwise unchanged. TestCodexAPIKeepsMagpieOnOwnModel (api on an own model, magpie model then own model again, picker values, refusal, back to ChatGPT) and TestCodexAPISyncWiresOwnModel fail on the old code and pass; TestCodexProviderAlsoSetsBaseURL's api case now expects magpie to stay wired on Codex's own model. End to end in a temp HOME with a copy of a real models_cache.json: api, fake/m1, then gpt-6-luna leaves model = "codex/gpt-6-luna" with model_provider, model_catalog_json and openai_base_url, and codex-cli 0.160.0's codex debug models with CODEX_HOME on that sandbox (gateway ports pointed at :1) lists fake/m1 beside codex/gpt-6-luna and the other codex/ models. 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 or with a turn sent through a real ChatGPT account.
2026-10-03 23:40:06 +08:00
agent: Codex on a routing group's model name is still connected, not "switched off it outside magpie" (#750, Windows 11, magpie 0.1.812, Codex 0.160.0: Codex set to group/auto-gpt-6-1-sol in magpie, its config.toml then reading model = "gpt-6.1-sol" with openai_base_url still magpie's gateway, and the Agents page kept saying 在 magpie 之外被从 … 切走了 with 重新接入, coming back a while after each reconnect) — the gateway takes a model's name without a provider in it as the group of that model (provider.GroupFor: gpt-6.1-sol is group/auto-gpt-6-1-sol), so Codex's requests still went to the group; but Drift compared the field with what magpie recorded setting (applied.json) by string, and gpt-6.1-sol is neither that nor one of magpie's models by magpieValue (isMagpie wants a provider/model id, and Codex's options list it as its own or not at all), so it read as "replaced". What writes gpt-6.1-sol into config.toml is not magpie (no agent path writes a group's model name; set writes the group id as picked) and wasn't found — the Codex app persisting its thread's model by its own name is the likely one — which is why it came back after each reapply. Drift now passes over a field whose value and magpie's recorded one reach the same routing group, one by the group's id and one by its model's name (sameGroup, groupNamed: a group/… id as it is, "magpie/" taken off, else GroupFor); Codex's internal wired() and Agent.Wired (through a new Agent.Routed hook, Codex's routed(): openai_base_url or magpie as its provider) count the group's model name as magpie's only when magpie set that group on the field and Codex's config still sends its model to the gateway, so a Codex taken off magpie on gpt-6.1-sol is not connected, and a Codex's own gpt-5.5 that happens to have an auto group is no more magpie's than before (failover's base URL is untouched). Disconnect takes the field off the group's model name as it does off the group's id (back to Codex's default), rather than leaving Codex asking OpenAI for gpt-6.1-sol. Another group's model (gpt-6.1) or one no group has (gpt-5.5) is still "replaced". The reporter's ask to say which setting differs: the drift's detail already names it ("model is …, not … as magpie set it", the base URL or provider table for unwired) in the status line's and the Apply again pill's tooltip; that is left as it is. Tests: TestCodexGroupByItsModelName (two providers serving gpt-6.1-sol and gpt-6.1, signed in with ChatGPT and with an API key: group/auto-gpt-6-1-sol set, then config.toml's model rewritten to gpt-6.1-sol — Wired and no drift; no route to magpie — not wired; gpt-6.1 and gpt-5.5 — replaced) and TestCodexGroupByItsModelNameDisconnect fail on the old code (not wired, drift replaced, gpt-6.1-sol and the base URL left after Disconnect) and pass. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried on Windows or with the reporter's Codex and groups; not checked: what in Codex rewrites the model to gpt-6.1-sol.
2026-10-04 13:11:23 +08:00
toml: Codex's config.toml with a multi-line array (notify = [ … ]) is edited right, and an edit that fails leaves every file as it was (#253 kerwinliu00001: "edited TOML is invalid: line 2, column 1: incomplete number", config.toml left with model_provider gone and [model_providers.magpie] added but no model) — the top-level key edits (GetTOMLTop, SetTOMLTop, DelTOMLTop) went line by line with regexes: a new key went after the last line that looked like key = …, which for notify = [ was inside the array; key = value lines inside a multi-line string were read as keys and a line starting with [ as a table; replacing or deleting a multi-line value touched only its first line. They now locate the top-level keys with the TOML parser, as the table edits already did, each with its value's whole range however many lines it takes (parseTOMLFile, the unnamed root table beside the tables); SetTOMLTop finds all its keys in the file as read and writes once. A file the parser refuses is still read line by line, so a broken config keeps showing its model, and writes to it are refused untouched. And a pick is several writes (Codex: drop model_provider, add magpie's provider table, set openai_base_url and model), each checked, so one failing left the earlier ones on disk: edit.Atomically(fn, paths…) puts each file back to its bytes and mode, or removes one it created, when fn fails, and every field set and Sync of Codex (config.toml and magpie-models.json, so Codex in WSL too), Kimi and Grok goes through it, as do Codex's MCP server writes (putCodex, delCodex). Tested in temp dirs and a temp HOME: the reporter's file read, set and deleted directly and through Codex's model field (signed in, with model_provider and model above the array, with magpie as the provider), the array's text kept and the TOML valid, and back to a Codex model; nested arrays, trailing commas, comments in arrays, [x] and a = b in strings, an inline table in an array; """ and ''' strings holding model = … and [table] lines not read as keys, new keys after their closing quotes, one deleted whole; a forced failure of Codex's last write leaving config.toml byte-identical; TestAtomically. They fail on main (the Codex ones with the reporter's error). go vet ./internal/..., go build -tags nogui (and GOOS=linux, GOOS=windows) and go test -tags nogui ./... pass. Not tried against a real ~/.codex, in WSL or in the GUI; multi-line inline tables (TOML 1.1) are refused by the parser and so left untouched with an error.
2026-09-30 09:31:59 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
agent: Codex's subagents can start at an effort of their own, and Claude Code's subagents can have a model of their own (#468, #469) — Codex reads [agents] default_subagent_reasoning_effort, the effort a spawned subagent starts at when the spawn names none (openai/codex core/src/agent/child_config.rs, config_toml.rs; in codex 0.159.2), and magpie never wrote it. Codex gets a subagent effort field: a square beside its subagents' one that opens the effort slider, unset said to mean the session's effort, or the subagent model's own default. Codex refuses a spawn at a level the subagents' model lacks, so only one it has is taken, and one a new subagent or main model lacks is dropped. Claude Code takes the Agent call's model, then the agent's frontmatter, then CLAUDE_CODE_SUBAGENT_MODEL, then the session's (2.1.287); magpie wrote that env only by itself, the main model while every tier followed it. It gets a subagents field, offered once routed through magpie, whose model outlives a new main model and a tier of its own; unset, the env is written as before. Claude Code has no setting for its subagents' effort beyond each agent's own frontmatter, and omp's task role already takes a thinking level, so neither changes. TestCodexSubagentEffort, TestClaudeSubagentModel and subagent-effort.test.cjs fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; subagent-effort, omp-roles, claude-effort, panel-effort, agent-layout, model-pick, click-scroll, old-webkit pass.
2026-10-02 03:18:26 +08:00
codex: on magpie API, Codex's own model as the default keeps magpie as its provider and magpie's models in its picker (#701, nullburn: Codex 选回原生默认模型后,第三方模型目录消失(已选择 magpie API)) — with Codex's sign-in set to magpie API, picking one of Codex's own models (gpt-6-luna) as its default in the Agents row ran unroute(): model_provider, model_catalog_json, openai_base_url and magpie-models.json all went, so every third-party model left Codex's picker while the row still said magpie API; and choosing magpie API while on Codex's own model wired nothing (login.Set only re-ran set for a magpie model). Now, on magpie API, Codex's own model goes as magpie serves it on the ChatGPT account there (codexOwnViaMagpie: gpt-6-luna -> codex/gpt-6-luna, the entries shown to Codex first), so set() takes the magpie branch and only the default changes; the picker's OpenAI group offers those ids under their own names (Label gpt-6-luna) so the value matches; one magpie doesn't serve (the ChatGPT subscription off in magpie) is refused with a message naming both ways out, the config untouched, rather than quietly unwired; choosing magpie API on Codex's own model wires it at once; Sync wires a config an older magpie left so (#701's: model = "gpt-6-luna", sign-in api). Back on ChatGPT, a codex/… default turns into Codex's own model again, straight to OpenAI as before (codexOwnOf); the ChatGPT sign-in's paths are otherwise unchanged. TestCodexAPIKeepsMagpieOnOwnModel (api on an own model, magpie model then own model again, picker values, refusal, back to ChatGPT) and TestCodexAPISyncWiresOwnModel fail on the old code and pass; TestCodexProviderAlsoSetsBaseURL's api case now expects magpie to stay wired on Codex's own model. End to end in a temp HOME with a copy of a real models_cache.json: api, fake/m1, then gpt-6-luna leaves model = "codex/gpt-6-luna" with model_provider, model_catalog_json and openai_base_url, and codex-cli 0.160.0's codex debug models with CODEX_HOME on that sandbox (gateway ports pointed at :1) lists fake/m1 beside codex/gpt-6-luna and the other codex/ models. 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 or with a turn sent through a real ChatGPT account.
2026-10-03 23:40:06 +08:00
codex: when the ChatGPT account runs out of its allowance after a magpie model was picked, magpie becomes Codex's provider, and goes back beside the sign-in when the allowance is back (#540: once the Codex 5-hour/weekly quota is used up, a third-party model through magpie sends nothing in new or old sessions; Dazzle-sys: the session was on the magpie model all along, the quota went elsewhere) — the Codex desktop app refuses to send for a ChatGPT account that is out of its allowance before any request is made, whichever model the turn is on, so a magpie model beside the sign-in (openai_base_url, ChatGPT mode) is blocked with it; Codex's open-source core and TUI only report a usage limit after a response, the block is the app's, keyed on the account. bd5bf422 made magpie the provider (model_provider = "magpie", model_catalog_json; the app-server's getAuthStatus then answers requires_openai_auth false, the app's API state) only when a model was picked while the account was already out, so an allowance running out later left Codex as it was. KeepOnAnAccountWithRoom now also looks, every 5 minutes, whether the active Codex account is out (CodexUsedUp, now read through LoginUsage's cache, fetched at most once a minute, as the agents' sync asks it on every catalog sync) and tells the agents' sync when that changes (noteCodexUsedUp → catalog.Touched); Codex's Sync then sets the magpie model again, which wires it as the provider while the account is out, marked codex.out in the stash, and puts it back beside the sign-in once the allowance is back, only where it was moved for that (a provider asked for with sign-in "api" stays). Threads started on Codex's own provider and reopened may still be held by the app; the Codex app may need a restart to take the new config. agent's TestMain stubs codexUsedUp so no test asks OpenAI. TestCodexRunsOutAfterPick (ChatGPT mode, then out: provider; out again: stays; back: beside the sign-in; api stays) fails without the change; TestNoteCodexUsedUp checks only a change is told. No request was made to OpenAI. 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.
2026-10-02 16:48:26 +08:00
agent: Codex on a routing group's model name is still connected, not "switched off it outside magpie" (#750, Windows 11, magpie 0.1.812, Codex 0.160.0: Codex set to group/auto-gpt-6-1-sol in magpie, its config.toml then reading model = "gpt-6.1-sol" with openai_base_url still magpie's gateway, and the Agents page kept saying 在 magpie 之外被从 … 切走了 with 重新接入, coming back a while after each reconnect) — the gateway takes a model's name without a provider in it as the group of that model (provider.GroupFor: gpt-6.1-sol is group/auto-gpt-6-1-sol), so Codex's requests still went to the group; but Drift compared the field with what magpie recorded setting (applied.json) by string, and gpt-6.1-sol is neither that nor one of magpie's models by magpieValue (isMagpie wants a provider/model id, and Codex's options list it as its own or not at all), so it read as "replaced". What writes gpt-6.1-sol into config.toml is not magpie (no agent path writes a group's model name; set writes the group id as picked) and wasn't found — the Codex app persisting its thread's model by its own name is the likely one — which is why it came back after each reapply. Drift now passes over a field whose value and magpie's recorded one reach the same routing group, one by the group's id and one by its model's name (sameGroup, groupNamed: a group/… id as it is, "magpie/" taken off, else GroupFor); Codex's internal wired() and Agent.Wired (through a new Agent.Routed hook, Codex's routed(): openai_base_url or magpie as its provider) count the group's model name as magpie's only when magpie set that group on the field and Codex's config still sends its model to the gateway, so a Codex taken off magpie on gpt-6.1-sol is not connected, and a Codex's own gpt-5.5 that happens to have an auto group is no more magpie's than before (failover's base URL is untouched). Disconnect takes the field off the group's model name as it does off the group's id (back to Codex's default), rather than leaving Codex asking OpenAI for gpt-6.1-sol. Another group's model (gpt-6.1) or one no group has (gpt-5.5) is still "replaced". The reporter's ask to say which setting differs: the drift's detail already names it ("model is …, not … as magpie set it", the base URL or provider table for unwired) in the status line's and the Apply again pill's tooltip; that is left as it is. Tests: TestCodexGroupByItsModelName (two providers serving gpt-6.1-sol and gpt-6.1, signed in with ChatGPT and with an API key: group/auto-gpt-6-1-sol set, then config.toml's model rewritten to gpt-6.1-sol — Wired and no drift; no route to magpie — not wired; gpt-6.1 and gpt-5.5 — replaced) and TestCodexGroupByItsModelNameDisconnect fail on the old code (not wired, drift replaced, gpt-6.1-sol and the base URL left after Disconnect) and pass. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried on Windows or with the reporter's Codex and groups; not checked: what in Codex rewrites the model to gpt-6.1-sol.
2026-10-04 13:11:23 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
wsl: OpenCode, Kimi Code, omp and the other CLIs magpie sets up through a file in the home are set up in WSL distros too (#515: on Windows only Codex, Pi, OmO and Claude Code were found in a distro) — fourteen agents join wslKinds, each found by its folder under the distro's $HOME or its command on the distro's own PATH, and listed as <name> · WSL <distro> (opencode@wsl:Ubuntu…): OpenCode (~/.config/opencode, opencode), MiMo Code (~/.config/mimocode, mimo), Kimi Code (~/.kimi-code, kimi; the old kimi-cli's ~/.kimi where that is all there is, found by the command), omp (~/.omp/agent, omp), Crush (~/.config/crush/crush.json, Linux's place, not Windows' LOCALAPPDATA), Hermes Agent (~/.hermes), Grok Build (~/.grok, by its folder alone, as on this machine), Droid (~/.factory), fx (~/.fx, by its folder alone: fx is also the JSON viewer), Command Code (~/.commandcode), MiniMax Code's mcode (~/.minimax), Muse Code (~/.config/muse), Qoder and Qoder CN (~/.qoder, ~/.qoder-cn). Each is its host constructor at a place (opencodeIn, kimiIn, ompIn, crushIn, hermesIn, grokIn, droidIn, fxIn, commandCodeIn, miniMaxIn, museIn, qoderIn/qoderCNIn; the host's opencode(home, cfg) and the rest wrap them), so it writes the same keys and schema as on this machine, but the gateway as the distro reaches it (place.gw/v1: 127.0.0.1 when mirrored, Windows' address under NAT) in its provider, its Check and its Sync, and its folder at the default, as the distro's variables (OPENCODE_CONFIG_DIR, KIMI_CODE_HOME, HERMES_HOME, FACTORY_HOME_OVERRIDE, MINIMAX_DATA_DIR, QODER_CONFIG_DIR…) aren't read (place.getenv is "" there); OpenChamber, a Windows app, isn't looked at for a distro's OpenCode, and omp there, whose version isn't known, gets xhigh rather than a max an older omp refuses. Their notices are the restart advice of their own, as for Codex. A stopped distro's agent is built without looking at its files (place.cold: exists/isDir are false, so the defaults are taken), its options read none (wslOwnAsleep, kimiOwnOptions/ompOwnOptions/miniMaxOwnOptions without a file), and a pick, once the distro is started, builds the agent again warm, so it writes the file the agent reads — an opencode.jsonc already there, ~/.kimi for kimi-cli — not the default. Left out: Gemini CLI and Antigravity (a key lent through .env, a launch command), dsh (profiles and .env), Devin (no gateway; its model list from the devin command on this machine), Goose (no magpie routing; its name is pressly's goose too), Cursor and Copilot (no magpie routing), and the apps (Cline, Hanako, WorkBuddy, ZCode, Claude Desktop, OpenChamber, Alma, Cindy); and the library's skills, MCP and instructions for the new WSL agents, which wslTargetOf still gives only Claude Code, Codex, Pi and OmO. Nothing ran on Windows or in a real WSL. wsl_more_test.go, on fake distro roots under temp dirs with the host's variables pointed elsewhere: TestWSLProbeFindsMoreAgents (each folder and command in the probe, none for grok and fx, kimi-cli by its command), TestWSLMoreAgentsDiscovered (all fourteen listed, no command, UA or aliases), TestWSLMoreAgentsPick (each agent, mirrored and NAT: its file in the distro names the distro's gateway, no 127.0.0.1 under NAT, Check passes, Sync keeps it, the notice; this machine's home and the folders its variables name untouched), TestWSLMoreAgentsStopped (nothing asked nor opened, the last value shown, options, a pick starts the distro and writes there) fail without the change; TestWSLStoppedPickFindsItsFiles fails without the warm rebuild (the pick wrote a second opencode.json beside the .jsonc). go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and vet ./internal/..., GOOS=windows go test -c ./internal/agent/ ./internal/library/, and go test -tags nogui -count=1 ./... under a temp HOME pass (TestFXInState failed once on its TempDir cleanup race, passes on the rerun; untouched).
2026-10-02 14:16:38 +08:00
agent: 重开 Codex 后生效 goes once Codex is reopened, whatever Codex itself writes to config.toml after, and a Codex daemon of another home isn't counted (#729, Sun1090 on Codex 0.160.0: the Codex row stayed "已接入 · 重开 Codex 后生效" after ChatGPT and magpie were both restarted) — Agent.Stale counted every process matching (^|/)codex( |$) that started over a second before config.toml's or magpie-models.json's mtime, and Codex writes config.toml itself (each project it is opened in gets a [projects."…"] trust_level, a notice seen, the model picked in its app; this Mac's has 10919 project tables), so a Codex reopened after magpie's change was stale again at its first such write, as was one that never missed anything; and the pattern also took the app-server daemons Codex 0.160 leaves running with ppid 1 for another CODEX_HOME (<home>/.codex/packages/app-server-daemon/…/codex app-server --managed-daemon, days old on this Mac). Stale now compares a copy's start with when magpie last changed what the agent reads at start: a digest of it (Codex: model_provider, model_catalog_json, openai_base_url, the [model_providers.magpie] table and magpie-models.json; Claude Code: env and model in settings.json) is kept in the stash with the files' latest write at the time it was first seen, so neither the agent's own writes nor magpie starting again move it; a magpie change (a new list, connecting) still gives a new time and the notice. A process whose command runs from another home's .codex (or .claude) dir is skipped. pgrep/ps sit behind a var (running), ps now giving etime and command. TestCodexStaleOnlyForMagpiesChange (ChatGPT's Codex reopened an hour ago and another home's daemon: 0; Codex trusting a project: 0; magpie's list changed: 1, and 1 again from a fresh Agent) fails on the old logic at both the daemon and Codex's own write, and passes. go vet ./internal/..., builds (darwin -tags nogui, GOOS=linux, GOOS=windows internal/agent) and go test -tags nogui ./internal/agent pass (its TestMain sandboxes HOME; the HOME override itself was refused here). Not tried in the reporter's app: a Codex already flagged clears once it is reopened after this build has read the digest, one more reopen at most after updating.
2026-10-04 07:47:06 +08:00
agent: 重开 Codex 后生效 goes once Codex is reopened, whatever Codex itself writes to config.toml after, and a Codex daemon of another home isn't counted (#729, Sun1090 on Codex 0.160.0: the Codex row stayed "已接入 · 重开 Codex 后生效" after ChatGPT and magpie were both restarted) — Agent.Stale counted every process matching (^|/)codex( |$) that started over a second before config.toml's or magpie-models.json's mtime, and Codex writes config.toml itself (each project it is opened in gets a [projects."…"] trust_level, a notice seen, the model picked in its app; this Mac's has 10919 project tables), so a Codex reopened after magpie's change was stale again at its first such write, as was one that never missed anything; and the pattern also took the app-server daemons Codex 0.160 leaves running with ppid 1 for another CODEX_HOME (<home>/.codex/packages/app-server-daemon/…/codex app-server --managed-daemon, days old on this Mac). Stale now compares a copy's start with when magpie last changed what the agent reads at start: a digest of it (Codex: model_provider, model_catalog_json, openai_base_url, the [model_providers.magpie] table and magpie-models.json; Claude Code: env and model in settings.json) is kept in the stash with the files' latest write at the time it was first seen, so neither the agent's own writes nor magpie starting again move it; a magpie change (a new list, connecting) still gives a new time and the notice. A process whose command runs from another home's .codex (or .claude) dir is skipped. pgrep/ps sit behind a var (running), ps now giving etime and command. TestCodexStaleOnlyForMagpiesChange (ChatGPT's Codex reopened an hour ago and another home's daemon: 0; Codex trusting a project: 0; magpie's list changed: 1, and 1 again from a fresh Agent) fails on the old logic at both the daemon and Codex's own write, and passes. go vet ./internal/..., builds (darwin -tags nogui, GOOS=linux, GOOS=windows internal/agent) and go test -tags nogui ./internal/agent pass (its TestMain sandboxes HOME; the HOME override itself was refused here). Not tried in the reporter's app: a Codex already flagged clears once it is reopened after this build has read the digest, one more reopen at most after updating.
2026-10-04 07:47:06 +08:00
agent: Cursor Private Inference, which magpie finds by its product.json and starts on magpie with a command its row copies, and whose /models gives each model's api_types and capabilities (#299, mamba on Discord) — the build (Cursor 3.23.x, the same app name, bundle id and ~/.cursor as Cursor) runs its agent locally and asks the endpoint in CURSOR_LOCAL_AGENT_BASE_URL / CURSOR_LOCAL_AGENT_API_KEY when its Open configuration has none; mamba confirmed it works with any account pointed at magpie. magpie writes nothing of Cursor's (its settings share Cursor's state.vscdb): the Agents page lists it when an app's product.json says "Cursor Private Inference" (/Applications, ~/Applications; %LOCALAPPDATA%\Programs on Windows; /opt and the like on Linux), and its row's one control, Copy launch command (复制启动命令), copies CURSOR_LOCAL_AGENT_BASE_URL=<gateway>/v1 CURSOR_LOCAL_AGENT_API_KEY=magpie-cursor-local '<app>' (PowerShell on Windows); in the tray panel the row copies it. Its notice says to quit it first (a second start hands over to the running one) and that a base URL in Open configuration comes first. /v1/models asked with its key gives each model api_types (the APIs its provider serves it on, all three for a group or a translated one; it asks Anthropic Messages only when no OpenAI one is listed) and capabilities (context_length, max_output_tokens, supports_vision); any other client's list is unchanged. usage.AgentOf matches a name before a UA prefix, so cursor-local isn't counted as Cursor. TestCursorLocal, TestCursorLocalModels and cursor-local-launch.test.cjs (WebKit, en and zh) fail on the old code; agy-launch and agent-* GUI tests pass on WebKit. Not tried with the real app (not installed here). go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-04 23:38:19 +08:00
agent: Cursor Private Inference, which magpie finds by its product.json and starts on magpie with a command its row copies, and whose /models gives each model's api_types and capabilities (#299, mamba on Discord) — the build (Cursor 3.23.x, the same app name, bundle id and ~/.cursor as Cursor) runs its agent locally and asks the endpoint in CURSOR_LOCAL_AGENT_BASE_URL / CURSOR_LOCAL_AGENT_API_KEY when its Open configuration has none; mamba confirmed it works with any account pointed at magpie. magpie writes nothing of Cursor's (its settings share Cursor's state.vscdb): the Agents page lists it when an app's product.json says "Cursor Private Inference" (/Applications, ~/Applications; %LOCALAPPDATA%\Programs on Windows; /opt and the like on Linux), and its row's one control, Copy launch command (复制启动命令), copies CURSOR_LOCAL_AGENT_BASE_URL=<gateway>/v1 CURSOR_LOCAL_AGENT_API_KEY=magpie-cursor-local '<app>' (PowerShell on Windows); in the tray panel the row copies it. Its notice says to quit it first (a second start hands over to the running one) and that a base URL in Open configuration comes first. /v1/models asked with its key gives each model api_types (the APIs its provider serves it on, all three for a group or a translated one; it asks Anthropic Messages only when no OpenAI one is listed) and capabilities (context_length, max_output_tokens, supports_vision); any other client's list is unchanged. usage.AgentOf matches a name before a UA prefix, so cursor-local isn't counted as Cursor. TestCursorLocal, TestCursorLocalModels and cursor-local-launch.test.cjs (WebKit, en and zh) fail on the old code; agy-launch and agent-* GUI tests pass on WebKit. Not tried with the real app (not installed here). go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-04 23:38:19 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
agents: Disconnect from magpie takes out everything magpie wrote into an agent's config and puts back what it had before (Fate on Discord: 移除由Magpie写入的配置,也就是重置功能,这个好像不是很明显。初步体验好像是选择默认就会清除写入的配置吗?希望能有一个更直接的交互动作,来代表移除由Magpie写入的配置。) — there was no one action for it, and picking Default isn't it: Default is the agent as installed, and for Codex, Claude Code and Gemini CLI it also forgets the stash, so the user's own provider or relay (model_provider + its table, ANTHROPIC_BASE_URL/AUTH_TOKEN, GOOGLE_GEMINI_BASE_URL/GEMINI_API_KEY and sign-in) was lost rather than put back. agent.Disconnect reuses each agent's own restore path: a new Agent.Unwire, for those three, runs the unroute their own-model pick already used (codex.go and claude.go have it pulled out of set as unroute; gemini.go's was there) and then forgets the stash, and every other field magpie set — each one reading a magpie value, or the value applied.json recorded and Unwire left — is set to "" through its own Set, which for every other agent unstashes what it had. applied.json forgets the agent (Keep), so no drift says it was switched off magpie. Agent.Wired (magpie or a magpie model in any field) goes to the GUI as agentJSON.wired; an agent magpie isn't in is left byte for byte. POST /api/agents/disconnect/{id} runs it under edit.Atomically as Sync and the fields' Sets are.
2026-10-03 02:42:09 +08:00
agents: Factory's Droid CLI is an agent magpie sets up (#242 tasselx) — droid keeps its settings in ~/.factory/settings.json ($FACTORY_HOME_OVERRIDE/.factory when set), its BYOK models the customModels array ({model, displayName, baseUrl, apiKey, provider "anthropic" | "openai" (Responses) | "generic-chat-completion-api", maxOutputTokens, noImageSupport …}), picked as "custom:<id>". Picking a catalog model through magpie appends one entry per catalog model after the user's own (so their ids never move), each with an explicit id "custom:magpie/<provider>/<model>", the catalog's label as displayName, the gateway and token magpie, its context (maxContextLimit) and output when known, noImageSupport always written (droid takes a Chat Completions model as blind otherwise), and the API its provider speaks natively so the gateway relays it as it is: Responses → "openai" at /v1, Messages → "anthropic" at the gateway root (Anthropic's SDK adds /v1), anything else "generic-chat-completion-api" at /v1; and sets sessionDefaultSettings.model. The model shows in magpie as magpie/<ref>; the user's sessionDefaultSettings.model is stashed and put back on reset (a top-level "model", the docs' spelling, is left alone and is what droid falls back to), magpie's entries go and an emptied customModels or sessionDefaultSettings with them; everything else in the file, the user's entries included, is kept byte for byte. The picker offers the user's own custom models by the id droid gives them (its "id", else the displayName with whitespace as dashes and a count of the same name before it), including the legacy ~/.factory/config.json custom_models, which magpie never writes. Sync rewrites magpie's entries as providers change; Check reports a missing entry or a changed baseUrl/apiKey; its requests are Droid's in usage (User-Agent factory-cli/<version>). Icon is Factory's own favicon glyph (factory.ai/favicon.svg); lobehub has none. From the docs: docs.factory.ai/cli/byok/overview (customModels fields, the three providers, config.json legacy snake_case merged under settings.json), /cli/configuration/settings (model, sessionDefaultSettings.*), /droid-exec/overview (custom:<Display-Name>-<index>). Verified by reading the shipped droid 0.229.0 bundle (@factory/cli-linux-x64, unpacked, never installed or run): the zod schema of an entry (also id, index, maxContextLimit, enableThinking, reasoningEffort, bedrock-converse), ids as custom:${displayName.trim().replace(/\s+/g,"-")}-${n} with n counting equal names, an entry's own id winning, the lookup by id, top-level model/reasoningEffort/specModeModel moved into sessionDefaultSettings only when unset there, getModel reading sessionDefaultSettings.model, noImageSupport defaulting by provider, FACTORY_HOME_OVERRIDE, and BYOK requests carrying factory-cli/<version>. Tested in a sandbox HOME (internal/agent/droid_test.go): set/sync/reset on a settings.json as droid leaves it with a Groq BYOK model (its entry byte-identical, the file restored exactly), each protocol's provider and baseUrl, a moved baseUrl caught by Check and healed by Sync, picking the user's own model while on magpie's, no file at all, a top-level model, FACTORY_HOME_OVERRIDE and legacy config.json ids (custom:Local-Qwen-0/-1) offered and never written. go build -tags nogui (and GOOS=linux, GOOS=windows) and go test -tags nogui ./... pass (TestClaudeSignedOut and TestClaudeAccountNamedAsItsLogin flaked under load and pass alone). Not tried with a real droid: whether droid's /model lists the entries, that it reaches the gateway on each protocol, and how it sends thinking for a custom model (magpie sets no reasoningEffort/enableThinking) are unverified.
2026-09-30 02:35:59 +08:00
wsl: OpenCode, Kimi Code, omp and the other CLIs magpie sets up through a file in the home are set up in WSL distros too (#515: on Windows only Codex, Pi, OmO and Claude Code were found in a distro) — fourteen agents join wslKinds, each found by its folder under the distro's $HOME or its command on the distro's own PATH, and listed as <name> · WSL <distro> (opencode@wsl:Ubuntu…): OpenCode (~/.config/opencode, opencode), MiMo Code (~/.config/mimocode, mimo), Kimi Code (~/.kimi-code, kimi; the old kimi-cli's ~/.kimi where that is all there is, found by the command), omp (~/.omp/agent, omp), Crush (~/.config/crush/crush.json, Linux's place, not Windows' LOCALAPPDATA), Hermes Agent (~/.hermes), Grok Build (~/.grok, by its folder alone, as on this machine), Droid (~/.factory), fx (~/.fx, by its folder alone: fx is also the JSON viewer), Command Code (~/.commandcode), MiniMax Code's mcode (~/.minimax), Muse Code (~/.config/muse), Qoder and Qoder CN (~/.qoder, ~/.qoder-cn). Each is its host constructor at a place (opencodeIn, kimiIn, ompIn, crushIn, hermesIn, grokIn, droidIn, fxIn, commandCodeIn, miniMaxIn, museIn, qoderIn/qoderCNIn; the host's opencode(home, cfg) and the rest wrap them), so it writes the same keys and schema as on this machine, but the gateway as the distro reaches it (place.gw/v1: 127.0.0.1 when mirrored, Windows' address under NAT) in its provider, its Check and its Sync, and its folder at the default, as the distro's variables (OPENCODE_CONFIG_DIR, KIMI_CODE_HOME, HERMES_HOME, FACTORY_HOME_OVERRIDE, MINIMAX_DATA_DIR, QODER_CONFIG_DIR…) aren't read (place.getenv is "" there); OpenChamber, a Windows app, isn't looked at for a distro's OpenCode, and omp there, whose version isn't known, gets xhigh rather than a max an older omp refuses. Their notices are the restart advice of their own, as for Codex. A stopped distro's agent is built without looking at its files (place.cold: exists/isDir are false, so the defaults are taken), its options read none (wslOwnAsleep, kimiOwnOptions/ompOwnOptions/miniMaxOwnOptions without a file), and a pick, once the distro is started, builds the agent again warm, so it writes the file the agent reads — an opencode.jsonc already there, ~/.kimi for kimi-cli — not the default. Left out: Gemini CLI and Antigravity (a key lent through .env, a launch command), dsh (profiles and .env), Devin (no gateway; its model list from the devin command on this machine), Goose (no magpie routing; its name is pressly's goose too), Cursor and Copilot (no magpie routing), and the apps (Cline, Hanako, WorkBuddy, ZCode, Claude Desktop, OpenChamber, Alma, Cindy); and the library's skills, MCP and instructions for the new WSL agents, which wslTargetOf still gives only Claude Code, Codex, Pi and OmO. Nothing ran on Windows or in a real WSL. wsl_more_test.go, on fake distro roots under temp dirs with the host's variables pointed elsewhere: TestWSLProbeFindsMoreAgents (each folder and command in the probe, none for grok and fx, kimi-cli by its command), TestWSLMoreAgentsDiscovered (all fourteen listed, no command, UA or aliases), TestWSLMoreAgentsPick (each agent, mirrored and NAT: its file in the distro names the distro's gateway, no 127.0.0.1 under NAT, Check passes, Sync keeps it, the notice; this machine's home and the folders its variables name untouched), TestWSLMoreAgentsStopped (nothing asked nor opened, the last value shown, options, a pick starts the distro and writes there) fail without the change; TestWSLStoppedPickFindsItsFiles fails without the warm rebuild (the pick wrote a second opencode.json beside the .jsonc). go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and vet ./internal/..., GOOS=windows go test -c ./internal/agent/ ./internal/library/, and go test -tags nogui -count=1 ./... under a temp HOME pass (TestFXInState failed once on its TempDir cleanup race, passes on the rerun; untouched).
2026-10-02 14:16:38 +08:00
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.
2026-10-03 18:17:11 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
wsl: OpenCode, Kimi Code, omp and the other CLIs magpie sets up through a file in the home are set up in WSL distros too (#515: on Windows only Codex, Pi, OmO and Claude Code were found in a distro) — fourteen agents join wslKinds, each found by its folder under the distro's $HOME or its command on the distro's own PATH, and listed as <name> · WSL <distro> (opencode@wsl:Ubuntu…): OpenCode (~/.config/opencode, opencode), MiMo Code (~/.config/mimocode, mimo), Kimi Code (~/.kimi-code, kimi; the old kimi-cli's ~/.kimi where that is all there is, found by the command), omp (~/.omp/agent, omp), Crush (~/.config/crush/crush.json, Linux's place, not Windows' LOCALAPPDATA), Hermes Agent (~/.hermes), Grok Build (~/.grok, by its folder alone, as on this machine), Droid (~/.factory), fx (~/.fx, by its folder alone: fx is also the JSON viewer), Command Code (~/.commandcode), MiniMax Code's mcode (~/.minimax), Muse Code (~/.config/muse), Qoder and Qoder CN (~/.qoder, ~/.qoder-cn). Each is its host constructor at a place (opencodeIn, kimiIn, ompIn, crushIn, hermesIn, grokIn, droidIn, fxIn, commandCodeIn, miniMaxIn, museIn, qoderIn/qoderCNIn; the host's opencode(home, cfg) and the rest wrap them), so it writes the same keys and schema as on this machine, but the gateway as the distro reaches it (place.gw/v1: 127.0.0.1 when mirrored, Windows' address under NAT) in its provider, its Check and its Sync, and its folder at the default, as the distro's variables (OPENCODE_CONFIG_DIR, KIMI_CODE_HOME, HERMES_HOME, FACTORY_HOME_OVERRIDE, MINIMAX_DATA_DIR, QODER_CONFIG_DIR…) aren't read (place.getenv is "" there); OpenChamber, a Windows app, isn't looked at for a distro's OpenCode, and omp there, whose version isn't known, gets xhigh rather than a max an older omp refuses. Their notices are the restart advice of their own, as for Codex. A stopped distro's agent is built without looking at its files (place.cold: exists/isDir are false, so the defaults are taken), its options read none (wslOwnAsleep, kimiOwnOptions/ompOwnOptions/miniMaxOwnOptions without a file), and a pick, once the distro is started, builds the agent again warm, so it writes the file the agent reads — an opencode.jsonc already there, ~/.kimi for kimi-cli — not the default. Left out: Gemini CLI and Antigravity (a key lent through .env, a launch command), dsh (profiles and .env), Devin (no gateway; its model list from the devin command on this machine), Goose (no magpie routing; its name is pressly's goose too), Cursor and Copilot (no magpie routing), and the apps (Cline, Hanako, WorkBuddy, ZCode, Claude Desktop, OpenChamber, Alma, Cindy); and the library's skills, MCP and instructions for the new WSL agents, which wslTargetOf still gives only Claude Code, Codex, Pi and OmO. Nothing ran on Windows or in a real WSL. wsl_more_test.go, on fake distro roots under temp dirs with the host's variables pointed elsewhere: TestWSLProbeFindsMoreAgents (each folder and command in the probe, none for grok and fx, kimi-cli by its command), TestWSLMoreAgentsDiscovered (all fourteen listed, no command, UA or aliases), TestWSLMoreAgentsPick (each agent, mirrored and NAT: its file in the distro names the distro's gateway, no 127.0.0.1 under NAT, Check passes, Sync keeps it, the notice; this machine's home and the folders its variables name untouched), TestWSLMoreAgentsStopped (nothing asked nor opened, the last value shown, options, a pick starts the distro and writes there) fail without the change; TestWSLStoppedPickFindsItsFiles fails without the warm rebuild (the pick wrote a second opencode.json beside the .jsonc). go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and vet ./internal/..., GOOS=windows go test -c ./internal/agent/ ./internal/library/, and go test -tags nogui -count=1 ./... under a temp HOME pass (TestFXInState failed once on its TempDir cleanup race, passes on the rerun; untouched).
2026-10-02 14:16:38 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
wsl: OpenCode, Kimi Code, omp and the other CLIs magpie sets up through a file in the home are set up in WSL distros too (#515: on Windows only Codex, Pi, OmO and Claude Code were found in a distro) — fourteen agents join wslKinds, each found by its folder under the distro's $HOME or its command on the distro's own PATH, and listed as <name> · WSL <distro> (opencode@wsl:Ubuntu…): OpenCode (~/.config/opencode, opencode), MiMo Code (~/.config/mimocode, mimo), Kimi Code (~/.kimi-code, kimi; the old kimi-cli's ~/.kimi where that is all there is, found by the command), omp (~/.omp/agent, omp), Crush (~/.config/crush/crush.json, Linux's place, not Windows' LOCALAPPDATA), Hermes Agent (~/.hermes), Grok Build (~/.grok, by its folder alone, as on this machine), Droid (~/.factory), fx (~/.fx, by its folder alone: fx is also the JSON viewer), Command Code (~/.commandcode), MiniMax Code's mcode (~/.minimax), Muse Code (~/.config/muse), Qoder and Qoder CN (~/.qoder, ~/.qoder-cn). Each is its host constructor at a place (opencodeIn, kimiIn, ompIn, crushIn, hermesIn, grokIn, droidIn, fxIn, commandCodeIn, miniMaxIn, museIn, qoderIn/qoderCNIn; the host's opencode(home, cfg) and the rest wrap them), so it writes the same keys and schema as on this machine, but the gateway as the distro reaches it (place.gw/v1: 127.0.0.1 when mirrored, Windows' address under NAT) in its provider, its Check and its Sync, and its folder at the default, as the distro's variables (OPENCODE_CONFIG_DIR, KIMI_CODE_HOME, HERMES_HOME, FACTORY_HOME_OVERRIDE, MINIMAX_DATA_DIR, QODER_CONFIG_DIR…) aren't read (place.getenv is "" there); OpenChamber, a Windows app, isn't looked at for a distro's OpenCode, and omp there, whose version isn't known, gets xhigh rather than a max an older omp refuses. Their notices are the restart advice of their own, as for Codex. A stopped distro's agent is built without looking at its files (place.cold: exists/isDir are false, so the defaults are taken), its options read none (wslOwnAsleep, kimiOwnOptions/ompOwnOptions/miniMaxOwnOptions without a file), and a pick, once the distro is started, builds the agent again warm, so it writes the file the agent reads — an opencode.jsonc already there, ~/.kimi for kimi-cli — not the default. Left out: Gemini CLI and Antigravity (a key lent through .env, a launch command), dsh (profiles and .env), Devin (no gateway; its model list from the devin command on this machine), Goose (no magpie routing; its name is pressly's goose too), Cursor and Copilot (no magpie routing), and the apps (Cline, Hanako, WorkBuddy, ZCode, Claude Desktop, OpenChamber, Alma, Cindy); and the library's skills, MCP and instructions for the new WSL agents, which wslTargetOf still gives only Claude Code, Codex, Pi and OmO. Nothing ran on Windows or in a real WSL. wsl_more_test.go, on fake distro roots under temp dirs with the host's variables pointed elsewhere: TestWSLProbeFindsMoreAgents (each folder and command in the probe, none for grok and fx, kimi-cli by its command), TestWSLMoreAgentsDiscovered (all fourteen listed, no command, UA or aliases), TestWSLMoreAgentsPick (each agent, mirrored and NAT: its file in the distro names the distro's gateway, no 127.0.0.1 under NAT, Check passes, Sync keeps it, the notice; this machine's home and the folders its variables name untouched), TestWSLMoreAgentsStopped (nothing asked nor opened, the last value shown, options, a pick starts the distro and writes there) fail without the change; TestWSLStoppedPickFindsItsFiles fails without the warm rebuild (the pick wrote a second opencode.json beside the .jsonc). go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and vet ./internal/..., GOOS=windows go test -c ./internal/agent/ ./internal/library/, and go test -tags nogui -count=1 ./... under a temp HOME pass (TestFXInState failed once on its TempDir cleanup race, passes on the rerun; untouched).
2026-10-02 14:16:38 +08:00
agents: Pi's model picker lists the models of its openai-codex sign-in from Pi's own registry, and its Default says it lets Pi pick (#709) — Pi's native options came from models.dev by provider id, and models.dev has no openai-codex (Pi's "OpenAI Codex (legacy)" ChatGPT sign-in), so a Pi signed in to both openai and openai-codex was offered openai/… only. Pi's (and OmO's) own options now come first from the model registry in the package Pi was installed from: the pi command on PATH leads to @earendil-works/pi-coding-agent, and pi-ai's dist/providers/data/<provider>.json (Pi 1.0) is read as is, in its order, chat models only (no gpt-image-2), memoized by the file's stamp — the list Pi's /model offers, which moves with every Pi update. A provider the registry doesn't have keeps models.dev's list; openai-codex with no registry in reach falls back to Codex CLI's models_cache.json (the same ChatGPT backend); models.dev's openai list isn't mapped onto it. The rows are openai-codex/<model> under "OpenAI Codex" with OpenAI's logo, a row each beside openai/<model> of the same name; picking one writes defaultProvider=openai-codex, defaultModel=<model> as before. omp shared the gap for its current model's provider (ownOptions): it now reads omp's own catalog (@oh-my-pi/pi-catalog src/models.json, non-chat kinds left out); omp's signed-in providers that aren't the current one are still #341's. Default in Pi's and OmO's model picker now says "clears the default model; Pi picks one on its own" (zh 清除显式默认模型,由 Pi 自动选择; no ja table exists), other agents' still say what they ship with. TestPiOffersItsOwnOpenAICodexModels (a fake npm-linked Pi 1.0 install, temp HOME and PI_CODING_AGENT_DIR, auth.json with openai and openai-codex oauth test metadata), TestPiOpenAICodexWithoutItsRegistry and TestOmpOffersItsOwnOpenAICodexModels fail on the old code (no openai-codex rows) and pass; pi-default-note.test.cjs (webkit, en/zh) fails on the old app.js and passes; agent-disconnect, agent-models and agent-model-groups GUI tests pass. Read-only against this machine's real installs: Pi 1.0.0 gives openai-codex 9 models and openai 44, omp's catalog openai-codex 8. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestProvidersAnswerWhileListsComeIn, TestClaudeSignedOut, TestClaudeAccountNamedAsItsLogin and TestClaudeIdentityServedWhileAsked, timing tests that pass alone. Not tried in the GUI with real Pi sign-ins, nor with a Pi older than 1.0 (no data folder: models.dev and Codex CLI's list as before) or a Windows npm shim.
2026-10-04 01:53:58 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
wsl: OpenCode, Kimi Code, omp and the other CLIs magpie sets up through a file in the home are set up in WSL distros too (#515: on Windows only Codex, Pi, OmO and Claude Code were found in a distro) — fourteen agents join wslKinds, each found by its folder under the distro's $HOME or its command on the distro's own PATH, and listed as <name> · WSL <distro> (opencode@wsl:Ubuntu…): OpenCode (~/.config/opencode, opencode), MiMo Code (~/.config/mimocode, mimo), Kimi Code (~/.kimi-code, kimi; the old kimi-cli's ~/.kimi where that is all there is, found by the command), omp (~/.omp/agent, omp), Crush (~/.config/crush/crush.json, Linux's place, not Windows' LOCALAPPDATA), Hermes Agent (~/.hermes), Grok Build (~/.grok, by its folder alone, as on this machine), Droid (~/.factory), fx (~/.fx, by its folder alone: fx is also the JSON viewer), Command Code (~/.commandcode), MiniMax Code's mcode (~/.minimax), Muse Code (~/.config/muse), Qoder and Qoder CN (~/.qoder, ~/.qoder-cn). Each is its host constructor at a place (opencodeIn, kimiIn, ompIn, crushIn, hermesIn, grokIn, droidIn, fxIn, commandCodeIn, miniMaxIn, museIn, qoderIn/qoderCNIn; the host's opencode(home, cfg) and the rest wrap them), so it writes the same keys and schema as on this machine, but the gateway as the distro reaches it (place.gw/v1: 127.0.0.1 when mirrored, Windows' address under NAT) in its provider, its Check and its Sync, and its folder at the default, as the distro's variables (OPENCODE_CONFIG_DIR, KIMI_CODE_HOME, HERMES_HOME, FACTORY_HOME_OVERRIDE, MINIMAX_DATA_DIR, QODER_CONFIG_DIR…) aren't read (place.getenv is "" there); OpenChamber, a Windows app, isn't looked at for a distro's OpenCode, and omp there, whose version isn't known, gets xhigh rather than a max an older omp refuses. Their notices are the restart advice of their own, as for Codex. A stopped distro's agent is built without looking at its files (place.cold: exists/isDir are false, so the defaults are taken), its options read none (wslOwnAsleep, kimiOwnOptions/ompOwnOptions/miniMaxOwnOptions without a file), and a pick, once the distro is started, builds the agent again warm, so it writes the file the agent reads — an opencode.jsonc already there, ~/.kimi for kimi-cli — not the default. Left out: Gemini CLI and Antigravity (a key lent through .env, a launch command), dsh (profiles and .env), Devin (no gateway; its model list from the devin command on this machine), Goose (no magpie routing; its name is pressly's goose too), Cursor and Copilot (no magpie routing), and the apps (Cline, Hanako, WorkBuddy, ZCode, Claude Desktop, OpenChamber, Alma, Cindy); and the library's skills, MCP and instructions for the new WSL agents, which wslTargetOf still gives only Claude Code, Codex, Pi and OmO. Nothing ran on Windows or in a real WSL. wsl_more_test.go, on fake distro roots under temp dirs with the host's variables pointed elsewhere: TestWSLProbeFindsMoreAgents (each folder and command in the probe, none for grok and fx, kimi-cli by its command), TestWSLMoreAgentsDiscovered (all fourteen listed, no command, UA or aliases), TestWSLMoreAgentsPick (each agent, mirrored and NAT: its file in the distro names the distro's gateway, no 127.0.0.1 under NAT, Check passes, Sync keeps it, the notice; this machine's home and the folders its variables name untouched), TestWSLMoreAgentsStopped (nothing asked nor opened, the last value shown, options, a pick starts the distro and writes there) fail without the change; TestWSLStoppedPickFindsItsFiles fails without the warm rebuild (the pick wrote a second opencode.json beside the .jsonc). go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and vet ./internal/..., GOOS=windows go test -c ./internal/agent/ ./internal/library/, and go test -tags nogui -count=1 ./... under a temp HOME pass (TestFXInState failed once on its TempDir cleanup race, passes on the rerun; untouched).
2026-10-02 14:16:38 +08:00
provider: Antigravity's models at several levels are one model with those levels (#150: 统一 Antigravity 模型变体与客户端推理档位的映射) — Antigravity lists gemini-3.7-flash-low, -medium and -high as three models, "Gemini 3.7 Flash (Low)" …, so a client picked a level twice: once in the model, once as its reasoning effort, with no telling which won. Now ids that are one id with an effort word after it (-low, -medium, -high, -extra-low, -minimal, -xhigh) are one model, gemini-3.7-flash "Gemini 3.7 Flash", declaring only the levels there are (low,medium,high; Gemini 3.1 Pro low,high), so Codex, Pi and the rest get reasoning levels for it. The level a variant is at is what Antigravity's name says where each name says a different one (gemini-3.5-flash-extra-low is "(Low)", gemini-3.5-flash-low "(Medium)"), else its id's word; a model only named like another (gemini-3-flash-agent, "Gemini 3.5 Flash (High)"; gemini-pro-agent) or with no sibling (gpt-oss-120b-medium) stays as listed. A request asks for the variant the effort picks, an effort it lacks at the nearest level (xhigh is high; medium on low/high is high); with none asked, the id without a level if Antigravity has one, else high — what Gemini 3 does unasked — else the highest. A variant's request carries no thinkingLevel, so the id and the level can't disagree. An old variant id still works: as named with no effort, and moved to the effort asked for. Saved picks and agents set to a variant (antigravity/gemini-3.7-flash-high) are moved to the family, at that level where the agent's own is unset, as Cursor's are. For Gemini 3 models without variants, medium now goes as medium to Flash (which takes minimal/low/medium/high) and still as high to Pro (low/high). Tested against the list an account's fetchAvailableModels gave (sandbox cache)
2026-09-28 20:10:00 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
wsl: OpenCode, Kimi Code, omp and the other CLIs magpie sets up through a file in the home are set up in WSL distros too (#515: on Windows only Codex, Pi, OmO and Claude Code were found in a distro) — fourteen agents join wslKinds, each found by its folder under the distro's $HOME or its command on the distro's own PATH, and listed as <name> · WSL <distro> (opencode@wsl:Ubuntu…): OpenCode (~/.config/opencode, opencode), MiMo Code (~/.config/mimocode, mimo), Kimi Code (~/.kimi-code, kimi; the old kimi-cli's ~/.kimi where that is all there is, found by the command), omp (~/.omp/agent, omp), Crush (~/.config/crush/crush.json, Linux's place, not Windows' LOCALAPPDATA), Hermes Agent (~/.hermes), Grok Build (~/.grok, by its folder alone, as on this machine), Droid (~/.factory), fx (~/.fx, by its folder alone: fx is also the JSON viewer), Command Code (~/.commandcode), MiniMax Code's mcode (~/.minimax), Muse Code (~/.config/muse), Qoder and Qoder CN (~/.qoder, ~/.qoder-cn). Each is its host constructor at a place (opencodeIn, kimiIn, ompIn, crushIn, hermesIn, grokIn, droidIn, fxIn, commandCodeIn, miniMaxIn, museIn, qoderIn/qoderCNIn; the host's opencode(home, cfg) and the rest wrap them), so it writes the same keys and schema as on this machine, but the gateway as the distro reaches it (place.gw/v1: 127.0.0.1 when mirrored, Windows' address under NAT) in its provider, its Check and its Sync, and its folder at the default, as the distro's variables (OPENCODE_CONFIG_DIR, KIMI_CODE_HOME, HERMES_HOME, FACTORY_HOME_OVERRIDE, MINIMAX_DATA_DIR, QODER_CONFIG_DIR…) aren't read (place.getenv is "" there); OpenChamber, a Windows app, isn't looked at for a distro's OpenCode, and omp there, whose version isn't known, gets xhigh rather than a max an older omp refuses. Their notices are the restart advice of their own, as for Codex. A stopped distro's agent is built without looking at its files (place.cold: exists/isDir are false, so the defaults are taken), its options read none (wslOwnAsleep, kimiOwnOptions/ompOwnOptions/miniMaxOwnOptions without a file), and a pick, once the distro is started, builds the agent again warm, so it writes the file the agent reads — an opencode.jsonc already there, ~/.kimi for kimi-cli — not the default. Left out: Gemini CLI and Antigravity (a key lent through .env, a launch command), dsh (profiles and .env), Devin (no gateway; its model list from the devin command on this machine), Goose (no magpie routing; its name is pressly's goose too), Cursor and Copilot (no magpie routing), and the apps (Cline, Hanako, WorkBuddy, ZCode, Claude Desktop, OpenChamber, Alma, Cindy); and the library's skills, MCP and instructions for the new WSL agents, which wslTargetOf still gives only Claude Code, Codex, Pi and OmO. Nothing ran on Windows or in a real WSL. wsl_more_test.go, on fake distro roots under temp dirs with the host's variables pointed elsewhere: TestWSLProbeFindsMoreAgents (each folder and command in the probe, none for grok and fx, kimi-cli by its command), TestWSLMoreAgentsDiscovered (all fourteen listed, no command, UA or aliases), TestWSLMoreAgentsPick (each agent, mirrored and NAT: its file in the distro names the distro's gateway, no 127.0.0.1 under NAT, Check passes, Sync keeps it, the notice; this machine's home and the folders its variables name untouched), TestWSLMoreAgentsStopped (nothing asked nor opened, the last value shown, options, a pick starts the distro and writes there) fail without the change; TestWSLStoppedPickFindsItsFiles fails without the warm rebuild (the pick wrote a second opencode.json beside the .jsonc). go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and vet ./internal/..., GOOS=windows go test -c ./internal/agent/ ./internal/library/, and go test -tags nogui -count=1 ./... under a temp HOME pass (TestFXInState failed once on its TempDir cleanup race, passes on the rerun; untouched).
2026-10-02 14:16:38 +08:00
agents: Pi's model picker lists the models of its openai-codex sign-in from Pi's own registry, and its Default says it lets Pi pick (#709) — Pi's native options came from models.dev by provider id, and models.dev has no openai-codex (Pi's "OpenAI Codex (legacy)" ChatGPT sign-in), so a Pi signed in to both openai and openai-codex was offered openai/… only. Pi's (and OmO's) own options now come first from the model registry in the package Pi was installed from: the pi command on PATH leads to @earendil-works/pi-coding-agent, and pi-ai's dist/providers/data/<provider>.json (Pi 1.0) is read as is, in its order, chat models only (no gpt-image-2), memoized by the file's stamp — the list Pi's /model offers, which moves with every Pi update. A provider the registry doesn't have keeps models.dev's list; openai-codex with no registry in reach falls back to Codex CLI's models_cache.json (the same ChatGPT backend); models.dev's openai list isn't mapped onto it. The rows are openai-codex/<model> under "OpenAI Codex" with OpenAI's logo, a row each beside openai/<model> of the same name; picking one writes defaultProvider=openai-codex, defaultModel=<model> as before. omp shared the gap for its current model's provider (ownOptions): it now reads omp's own catalog (@oh-my-pi/pi-catalog src/models.json, non-chat kinds left out); omp's signed-in providers that aren't the current one are still #341's. Default in Pi's and OmO's model picker now says "clears the default model; Pi picks one on its own" (zh 清除显式默认模型,由 Pi 自动选择; no ja table exists), other agents' still say what they ship with. TestPiOffersItsOwnOpenAICodexModels (a fake npm-linked Pi 1.0 install, temp HOME and PI_CODING_AGENT_DIR, auth.json with openai and openai-codex oauth test metadata), TestPiOpenAICodexWithoutItsRegistry and TestOmpOffersItsOwnOpenAICodexModels fail on the old code (no openai-codex rows) and pass; pi-default-note.test.cjs (webkit, en/zh) fails on the old app.js and passes; agent-disconnect, agent-models and agent-model-groups GUI tests pass. Read-only against this machine's real installs: Pi 1.0.0 gives openai-codex 9 models and openai 44, omp's catalog openai-codex 8. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestProvidersAnswerWhileListsComeIn, TestClaudeSignedOut, TestClaudeAccountNamedAsItsLogin and TestClaudeIdentityServedWhileAsked, timing tests that pass alone. Not tried in the GUI with real Pi sign-ins, nor with a Pi older than 1.0 (no data folder: models.dev and Codex CLI's list as before) or a Windows npm shim.
2026-10-04 01:53:58 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
agent: the disconnect preview right on Windows, and the Codex panel says what connecting does (owner: 去 Windows 测试机上测一下 / 是不是需要界面上解释一下现在的逻辑) — on the Windows test box Claude Code's and OpenCode's disconnect previews were empty though both were connected. Claude: the dry run's temporary home has no ~/.codex/auth.json, so a codex/… model wasn't magpie's there; the magpie asking now writes the providers it has on into that home and the dry run takes their models as magpie's (TestDryRunKnowsTheAskersProviders). OpenCode: magpie/codex/gpt-6.1-sol, a model its copy of magpie's list didn't have yet, read as not connected and Disconnect left it on magpie; a magpie/… value whose model magpie routes is magpie's (TestOpenCodeOnAModelNotInItsList). The preview pairs a line going back only with one as deep (Claude's model, not a modelPicker row) and doesn't mask …_TOKENS counts. The Codex panel, joined: 「重开 Codex 后,/model 里自己的模型照旧,magpie 的模型也在里面。」, and 新会话默认 says 「和 Codex 的 /model 是同一个选择,在哪边改都行」 rather than 「不设就用 Codex 自己上次的选择」 beside a value (/api/state: joined). On Windows (sandbox USERPROFILE/APPDATA, real accounts): previews for Claude, OpenCode, Codex and Gemini; disconnecting all four restored them (Claude back to opus, Gemini to Google sign-in, Codex keeps its [model_providers.magpie] by design), real ~/.claude untouched; real Claude Code requests via yylx/claude-opus-5-5 and codex/gpt-5.5 answered. The new tests fail on the old code. go vet, builds (darwin, GOOS=linux, GOOS=windows), go test -tags nogui -count=1 ./... under a temp HOME and the 34 agent GUI tests pass but cli-update, menu-scroll and old-webkit, which fail on main too.
2026-10-04 02:05:10 +08:00
agent: OpenCode is told a magpie model reasons when it thinks with no levels to pick, or has low, medium and high (#725, Sun1090: OpenCode's tooltip for mimo-v2.6-flash-free · opencode-zen said 推理: 不支持推理, where OpenCode's own Zen says it reasons) — the opencode block magpie writes into opencode.json never set reasoning, and OpenCode 1 (1.18.34, npm's latest) takes a model of a provider models.dev doesn't list (magpie) as reasoning only when the config says so (provider.ts: model.reasoning ?? false). models.dev lists Zen's mimo-v2.6-flash-free reasoning: true with no reasoning_options, so it has no levels, and magpieModels didn't hand agents the entry's Reasoning (the flag #402 added for /v1/models), so nothing could say it thinks. magpieModels now carries Reasoning, and OpenCode's block (and its WSL, mimocode and OpenChamber forms) sets "reasoning": true through openCodeReasons: a model that thinks with no levels, or one whose levels hold low, medium and high. OpenCode 1 adds low, medium and high of its own to a reasoning model's variants (ProviderTransform.variants, merged under the config's), checked under a sandbox HOME with 1.18.34's opencode models magpie --verbose: reasoning true with variants {} lists low, medium, high, and with low and max lists low, medium, high, max. So a model with other levels (deepseek-v4-flash-free's low, high, max) is left unmarked, as before, rather than offered levels it doesn't have; a "disabled" variant would hide them in 1 but OpenCode 2 (OpenChamber's) reads it as a variant of its own. A levelless thinker gets low, medium and high, as under OpenCode's own provider, and the gateway asks a model with a thinking switch alone no more than high (fitFor). OpenCode 2 doesn't read the flag. TestOpenCodeZenModelReasons (Zen's models from a models.dev cache: mimo-v2.6-flash-free and laguna-s-2.1-free marked, deepseek-v4-flash-free and ling-2.6-flash-free not) fails on the old code and passes. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried in the reporter's OpenCode app; OpenCode reads its config at start, so one already open shows it after it is reopened.
2026-10-04 07:21:48 +08:00
agents: Pencil (pen.dev) is an agent magpie sets up, its custom models in ~/.pencil/models.json (徐小小 on Discord: Pencil keeps its custom model file at ~/.pencil/models.json, in Pi's format) — Pencil's settings take a custom provider on OpenAI Completions, OpenAI Responses or Anthropic Messages (docs.pen.dev, Authentication), Pi's openai-completions, openai-responses and anthropic-messages, set for the provider as a whole, and its models.json is Pi's: {"providers":{"<id>":{"name","baseUrl","api","models":[{"id","name","reasoning","input","cost":{input,output,cacheRead,cacheWrite},"contextWindow","maxTokens","compat"}]}}}. The new pencil agent (pencil.go) adds magpie there as the provider "magpie": baseUrl the gateway's /v1, api openai-completions, apiKey magpie-pencil (its User-Agent isn't known, so its requests are told by the key), and every model as Pi's entry — Pi's model loop is now piModelJSON, shared — without a model's own api and baseUrl, which Pi reads but Pencil's own editor never writes, so every model goes to the gateway's Chat endpoint whatever Pencil makes of them; each model carries every field Pencil writes for one, Pi's defaults (128K window, 16K out) where magpie knows none, no cost and an empty compat. The model is picked in Pencil's agent composer, not in a file known to magpie, so its field is "provider", as for WorkBuddy and ZCode: whether magpie's models are in Pencil's picker; the user's other providers, their keys and Pencil's other keys stay, off takes only magpie's out, and the catalog sync rewrites it only where it is. It is found by ~/.pencil (the app's and pen.dev's CLI's) or, on a Mac, Pencil.app / pen.dev.app in /Applications or ~/Applications; not by a command, pencil and pen being common names. After a change it asks for Pencil to be restarted when Pencil is running (and always on Windows, where that can't be told): whether it reloads models.json on its own isn't known. No official icon with a licence that allows it was found, so it has the generic one. Nothing of Pencil's was downloaded or run; whether Pencil reads a model's thinkingLevelMap, a settings file naming a default model, and its paths on Windows and Linux (taken as ~/.pencil, as Node's homedir gives) aren't verified. TestPencilModels (the reporter's file with a key and a key of Pencil's: kept through on, sync and off; magpie's provider decoded strictly as Pencil's format, every model's fields of their types, no per-model api or baseUrl; found only with ~/.pencil; among All()) and TestStateListsPencil (the page's state lists Pencil with its provider field once ~/.pencil is there, not before) fail without the change. 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 (TestClaudeSignedOut failed once on its 5 s wait, passes alone; untouched).
2026-10-02 14:43:06 +08:00
agents: Pencil (pen.dev) is an agent magpie sets up, its custom models in ~/.pencil/models.json (徐小小 on Discord: Pencil keeps its custom model file at ~/.pencil/models.json, in Pi's format) — Pencil's settings take a custom provider on OpenAI Completions, OpenAI Responses or Anthropic Messages (docs.pen.dev, Authentication), Pi's openai-completions, openai-responses and anthropic-messages, set for the provider as a whole, and its models.json is Pi's: {"providers":{"<id>":{"name","baseUrl","api","models":[{"id","name","reasoning","input","cost":{input,output,cacheRead,cacheWrite},"contextWindow","maxTokens","compat"}]}}}. The new pencil agent (pencil.go) adds magpie there as the provider "magpie": baseUrl the gateway's /v1, api openai-completions, apiKey magpie-pencil (its User-Agent isn't known, so its requests are told by the key), and every model as Pi's entry — Pi's model loop is now piModelJSON, shared — without a model's own api and baseUrl, which Pi reads but Pencil's own editor never writes, so every model goes to the gateway's Chat endpoint whatever Pencil makes of them; each model carries every field Pencil writes for one, Pi's defaults (128K window, 16K out) where magpie knows none, no cost and an empty compat. The model is picked in Pencil's agent composer, not in a file known to magpie, so its field is "provider", as for WorkBuddy and ZCode: whether magpie's models are in Pencil's picker; the user's other providers, their keys and Pencil's other keys stay, off takes only magpie's out, and the catalog sync rewrites it only where it is. It is found by ~/.pencil (the app's and pen.dev's CLI's) or, on a Mac, Pencil.app / pen.dev.app in /Applications or ~/Applications; not by a command, pencil and pen being common names. After a change it asks for Pencil to be restarted when Pencil is running (and always on Windows, where that can't be told): whether it reloads models.json on its own isn't known. No official icon with a licence that allows it was found, so it has the generic one. Nothing of Pencil's was downloaded or run; whether Pencil reads a model's thinkingLevelMap, a settings file naming a default model, and its paths on Windows and Linux (taken as ~/.pencil, as Node's homedir gives) aren't verified. TestPencilModels (the reporter's file with a key and a key of Pencil's: kept through on, sync and off; magpie's provider decoded strictly as Pencil's format, every model's fields of their types, no per-model api or baseUrl; found only with ~/.pencil; among All()) and TestStateListsPencil (the page's state lists Pencil with its provider field once ~/.pencil is there, not before) fail without the change. 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 (TestClaudeSignedOut failed once on its 5 s wait, passes alone; untouched).
2026-10-02 14:43:06 +08:00
agents: Pi's model picker lists the models of its openai-codex sign-in from Pi's own registry, and its Default says it lets Pi pick (#709) — Pi's native options came from models.dev by provider id, and models.dev has no openai-codex (Pi's "OpenAI Codex (legacy)" ChatGPT sign-in), so a Pi signed in to both openai and openai-codex was offered openai/… only. Pi's (and OmO's) own options now come first from the model registry in the package Pi was installed from: the pi command on PATH leads to @earendil-works/pi-coding-agent, and pi-ai's dist/providers/data/<provider>.json (Pi 1.0) is read as is, in its order, chat models only (no gpt-image-2), memoized by the file's stamp — the list Pi's /model offers, which moves with every Pi update. A provider the registry doesn't have keeps models.dev's list; openai-codex with no registry in reach falls back to Codex CLI's models_cache.json (the same ChatGPT backend); models.dev's openai list isn't mapped onto it. The rows are openai-codex/<model> under "OpenAI Codex" with OpenAI's logo, a row each beside openai/<model> of the same name; picking one writes defaultProvider=openai-codex, defaultModel=<model> as before. omp shared the gap for its current model's provider (ownOptions): it now reads omp's own catalog (@oh-my-pi/pi-catalog src/models.json, non-chat kinds left out); omp's signed-in providers that aren't the current one are still #341's. Default in Pi's and OmO's model picker now says "clears the default model; Pi picks one on its own" (zh 清除显式默认模型,由 Pi 自动选择; no ja table exists), other agents' still say what they ship with. TestPiOffersItsOwnOpenAICodexModels (a fake npm-linked Pi 1.0 install, temp HOME and PI_CODING_AGENT_DIR, auth.json with openai and openai-codex oauth test metadata), TestPiOpenAICodexWithoutItsRegistry and TestOmpOffersItsOwnOpenAICodexModels fail on the old code (no openai-codex rows) and pass; pi-default-note.test.cjs (webkit, en/zh) fails on the old app.js and passes; agent-disconnect, agent-models and agent-model-groups GUI tests pass. Read-only against this machine's real installs: Pi 1.0.0 gives openai-codex 9 models and openai 44, omp's catalog openai-codex 8. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but TestProvidersAnswerWhileListsComeIn, TestClaudeSignedOut, TestClaudeAccountNamedAsItsLogin and TestClaudeIdentityServedWhileAsked, timing tests that pass alone. Not tried in the GUI with real Pi sign-ins, nor with a Pi older than 1.0 (no data folder: models.dev and Codex CLI's list as before) or a Windows npm shim.
2026-10-04 01:53:58 +08:00
pi: magpie's models carry their cost, and a prompt-cache lifetime where Pi's request is relayed as it is (#781, Kenoia: Pi's cacheWarming never warmed a magpie model, "cache lifetime unavailable", and every cost was zero) — Pi weighs warming a model's cache by its cost and promptCache, and magpie's models.json entries had neither. Each entry now has cost (input, output, cacheRead, cacheWrite in USD per million) at what a call costs the user, as the usage pages count it (provider.EffectivePriceIn: the user's own price, else the provider's list price, else its maker's); a group is priced when every member costs the same and none runs in a fast mode, else it is left without. promptCache is declared only where the gateway relays Pi's request as sent, at the short end of what the vendor publishes: a Claude on Anthropic's Messages API {short 300, long 3600} (5 minutes, or an hour with a 1h cache_control), a GPT on OpenAI's Responses API {short 300} (24h retention is only some models'); a Claude subscription, which runs through Claude Code and caches on its own, and other vendors declare none. With a copy of the owner's real config, 109 of 201 entries got a cost (OpenAI API GPTs, OpenRouter, DeepSeek, groups such as auto-gpt-6-sol, auto-claude-opus-5-5, auto-kimi-k3), the OpenAI API's 24 GPTs on openai-responses got promptCache {short 300}, and groups with mixed members (test, semantic) none. TestPiCostAndPromptCache 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.
2026-10-04 18:53:41 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
wsl: OpenCode, Kimi Code, omp and the other CLIs magpie sets up through a file in the home are set up in WSL distros too (#515: on Windows only Codex, Pi, OmO and Claude Code were found in a distro) — fourteen agents join wslKinds, each found by its folder under the distro's $HOME or its command on the distro's own PATH, and listed as <name> · WSL <distro> (opencode@wsl:Ubuntu…): OpenCode (~/.config/opencode, opencode), MiMo Code (~/.config/mimocode, mimo), Kimi Code (~/.kimi-code, kimi; the old kimi-cli's ~/.kimi where that is all there is, found by the command), omp (~/.omp/agent, omp), Crush (~/.config/crush/crush.json, Linux's place, not Windows' LOCALAPPDATA), Hermes Agent (~/.hermes), Grok Build (~/.grok, by its folder alone, as on this machine), Droid (~/.factory), fx (~/.fx, by its folder alone: fx is also the JSON viewer), Command Code (~/.commandcode), MiniMax Code's mcode (~/.minimax), Muse Code (~/.config/muse), Qoder and Qoder CN (~/.qoder, ~/.qoder-cn). Each is its host constructor at a place (opencodeIn, kimiIn, ompIn, crushIn, hermesIn, grokIn, droidIn, fxIn, commandCodeIn, miniMaxIn, museIn, qoderIn/qoderCNIn; the host's opencode(home, cfg) and the rest wrap them), so it writes the same keys and schema as on this machine, but the gateway as the distro reaches it (place.gw/v1: 127.0.0.1 when mirrored, Windows' address under NAT) in its provider, its Check and its Sync, and its folder at the default, as the distro's variables (OPENCODE_CONFIG_DIR, KIMI_CODE_HOME, HERMES_HOME, FACTORY_HOME_OVERRIDE, MINIMAX_DATA_DIR, QODER_CONFIG_DIR…) aren't read (place.getenv is "" there); OpenChamber, a Windows app, isn't looked at for a distro's OpenCode, and omp there, whose version isn't known, gets xhigh rather than a max an older omp refuses. Their notices are the restart advice of their own, as for Codex. A stopped distro's agent is built without looking at its files (place.cold: exists/isDir are false, so the defaults are taken), its options read none (wslOwnAsleep, kimiOwnOptions/ompOwnOptions/miniMaxOwnOptions without a file), and a pick, once the distro is started, builds the agent again warm, so it writes the file the agent reads — an opencode.jsonc already there, ~/.kimi for kimi-cli — not the default. Left out: Gemini CLI and Antigravity (a key lent through .env, a launch command), dsh (profiles and .env), Devin (no gateway; its model list from the devin command on this machine), Goose (no magpie routing; its name is pressly's goose too), Cursor and Copilot (no magpie routing), and the apps (Cline, Hanako, WorkBuddy, ZCode, Claude Desktop, OpenChamber, Alma, Cindy); and the library's skills, MCP and instructions for the new WSL agents, which wslTargetOf still gives only Claude Code, Codex, Pi and OmO. Nothing ran on Windows or in a real WSL. wsl_more_test.go, on fake distro roots under temp dirs with the host's variables pointed elsewhere: TestWSLProbeFindsMoreAgents (each folder and command in the probe, none for grok and fx, kimi-cli by its command), TestWSLMoreAgentsDiscovered (all fourteen listed, no command, UA or aliases), TestWSLMoreAgentsPick (each agent, mirrored and NAT: its file in the distro names the distro's gateway, no 127.0.0.1 under NAT, Check passes, Sync keeps it, the notice; this machine's home and the folders its variables name untouched), TestWSLMoreAgentsStopped (nothing asked nor opened, the last value shown, options, a pick starts the distro and writes there) fail without the change; TestWSLStoppedPickFindsItsFiles fails without the warm rebuild (the pick wrote a second opencode.json beside the .jsonc). go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and vet ./internal/..., GOOS=windows go test -c ./internal/agent/ ./internal/library/, and go test -tags nogui -count=1 ./... under a temp HOME pass (TestFXInState failed once on its TempDir cleanup race, passes on the rerun; untouched).
2026-10-02 14:16:38 +08:00
providers: a model a vendor names its own way is merged with the same model from other providers — by its id as Volcengine Ark spells it, or by the model the user says it is the same as in Names & levels (kyzhouxu, #583: 火山引擎获取到的默认 ds 4.1 flash 模型的名称跟其他供应商的名称不一样,没有自动合并到同一个模型分组) — the groups magpie finds merged a model by its id lowercased, its vendor prefix and an eight-digit date taken off and a version's dot made a dash, so Ark's deepseek-v4-1-flash-260910 (a six-digit YYMMDD snapshot) was a group of its own beside ali-tp's deepseek-v4.1-flash. sameModel now also takes off Ark's YYMMDD (a year from 23 to 39, a month and a day that are one), Vertex's "@YYYYMMDD", reads Fireworks' "p" between digits (deepseek-v4p1) as the dot and "_" as "-"; -flash, -thinking, ":batch", a four-digit release (qwen's -2507, kimi-k2-0905) and a number that is no date (-128000, -261301) stay apart. For an id no rule matches (an Ark endpoint id, a relay's own name), each model in a provider's Names & levels now has a "Same as" (等同于) box, its placeholder the name it is merged by now: the model it is the same as, as any vendor spells it, staged in draft.modelPrefs and made with the provider's Save like the other prefs (Cancel drops it, Restore default empties it, nothing sent or redrawn or scrolled before the Save). It is kept in settings' ModelSameAs by "<provider>/<model>" (renamed with the provider like every Model* map), set by provider.SetModelSame (its own id however spelt keeps nothing; a model the provider doesn't serve, or a name of no model, is refused) and taken by autoGroups, AutoStandIn and the agents' reseat (AutoGroupOf); the agents are told once. TestSameModelVendorSpellings (Ark, Fireworks, Vertex, underscores, and pairs that must stay apart) and TestModelSameAsMergesFoundGroup (c/ep-sol-x joins auto-sol once said, GroupFor("sol") finds it, back out when cleared, refusals) are new; TestProviderSaveModelPrefs covers a Save's same; provider-same-as.test.cjs (WebKit, en and zh: placeholder, staging, unsaved, Restore default, Cancel, one Save carrying exactly the changes, no scroll, Chinese for each string) fails without the change and passes with it; provider-levels-save and provider-detect pass. 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.
2026-10-02 23:39:40 +08:00
pi: magpie's models carry their cost, and a prompt-cache lifetime where Pi's request is relayed as it is (#781, Kenoia: Pi's cacheWarming never warmed a magpie model, "cache lifetime unavailable", and every cost was zero) — Pi weighs warming a model's cache by its cost and promptCache, and magpie's models.json entries had neither. Each entry now has cost (input, output, cacheRead, cacheWrite in USD per million) at what a call costs the user, as the usage pages count it (provider.EffectivePriceIn: the user's own price, else the provider's list price, else its maker's); a group is priced when every member costs the same and none runs in a fast mode, else it is left without. promptCache is declared only where the gateway relays Pi's request as sent, at the short end of what the vendor publishes: a Claude on Anthropic's Messages API {short 300, long 3600} (5 minutes, or an hour with a 1h cache_control), a GPT on OpenAI's Responses API {short 300} (24h retention is only some models'); a Claude subscription, which runs through Claude Code and caches on its own, and other vendors declare none. With a copy of the owner's real config, 109 of 201 entries got a cost (OpenAI API GPTs, OpenRouter, DeepSeek, groups such as auto-gpt-6-sol, auto-claude-opus-5-5, auto-kimi-k3), the OpenAI API's 24 GPTs on openai-responses got promptCache {short 300}, and groups with mixed members (test, semantic) none. TestPiCostAndPromptCache 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.
2026-10-04 18:53:41 +08:00
gateway: every full id of a Claude family Claude Code names goes to its tier's model, served by a provider of the user's or not (KevinXC on Discord, v0.1.665, T3 Code 0.0.45 over Claude Code 2.1.287: claude-haiku-4-5, claude-opus-5, claude-fable-5 and claude-sonnet-4-6 went to the haiku/opus/fable/sonnet tiers, but claude-fable-5-1, claude-sonnet-5 and claude-sonnet-5-5 went to the Claude account, 429 "requires usage credits" / "weekly limit") — the stand-in (4cbd96a3) was only asked for a model magpie shows no entry for, so a full id a provider of the user's serves bare (the Claude account lists claude-sonnet-5, claude-fable-5-1, …; a found auto-<model> group has it too) went there, while one none listed went to the tier: which tier a model reached depended on what the user's providers happen to list, not on the model. T3 Code names every model by its full id rather than Claude Code's alias, so it hit both. Now an id of the opus, sonnet, haiku or fable family (claudeFamily: claude-<family>-<any version>[-date][1m], and claude-3-5-sonnet-… alike, so a release magpie has never heard of is one too) from Claude Code routed through magpie goes to the model its tier is set to before groups or providers are looked at, count_tokens counting it there too. Kept as asked: a provider's "anth/claude-…", another agent's request, Claude Code not routed through magpie (StandIn says nothing), a routing group of the user's own named by the id (one magpie found, auto-…, was never picked for it), and the main model when Claude Code's ANTHROPIC_MODEL is that very id. A tier at an effort of its own (#536, "fake/sol:high[1m]") now reaches its model at that level through a stand-in too, where it was looked up whole and refused. TestClaudeTierStandInByFamily (claude-haiku-4-5, -20251001, claude-haiku-5, claude-opus-5, -5-5, -5-5[1m], claude-opus-6, claude-fable-5, -5-1, -5-1[1m], claude-sonnet-4-6, -5, -5-5, -5-5-20261001, claude-3-5-sonnet-20241022 through /v1/messages, beside a provider serving seven of them bare) fails without the change for the nine served ones; TestClaudeStandIn gains the families and the main model. 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 (TestDevinSignedInOnlyInMagpie, a known flake, aside).
2026-10-02 23:50:42 +08:00
models: Provider in model names has a third way, a name the user gave used just as they wrote it (#92 marsxxl: v0.1.591 的 Codex 下拉里自定义名称又带上了 · WorkBuddy / · Claude Code) — 559ce021 (#203) had a custom name keep " · <provider>" after it like any other, so "Opus 5.5" read "Opus 5.5 · Claude Code" in every list Labels feeds (Codex's model_catalog_json and the gateway's Codex /models, Pi's, OpenCode's, ZCode's, OMP's, Muse's), while #92 had been promised the name as written. Both are kept: the setting is now Off / Not on names I set (自定义名称不带供应商) / On. On stays the default and keeps #203's behaviour, so nobody's list changes unasked; own leaves a name the user gave as it is and a vendor's name with its provider's; off is #335's plain names. Stored as plainOwnNames beside plainNames, so a settings.json of before reads as it did (plainNames: true is off). POST /api/settings/plain-names takes mode on|own|off (a body of on alone still works), magpie model suffix on|own|off, a Settings save keeps it, and /v1/models' magpie_label now follows the setting through Labels as the agents' lists do. The row's hint is one line that fits (en, zh), and its zh name says 供应商 as the rest of the app. Prompts and headers are unchanged. TestSuffixMode, TestSuffixModesReachAgentFiles (Codex model_catalog_json and Pi models.json), TestModelsListSuffixModes (/v1/models magpie_label) and model-suffix-own.test.cjs (Chromium and WebKit, en and zh) fail without the change; TestModelName and TestModelNameAndLevelsReachAgentFiles keep #203's assertions. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (TestConfiguredModelsAdvertiseImageInput load-flaky, passes alone); plain-names, click-scroll, old-webkit pass.
2026-10-01 23:20:57 +08:00
agent: OpenCode and OpenChamber list a magpie model's reasoning levels weakest first, not alphabetically (#713, Hu9956 on v0.1.780: 思考 offered 默认, High, Low, Max, Medium, Ultra, Xhigh, where other providers in the same OpenCode go by strength and MiniMax Code had magpie's in order) — openCodeVariants returned a map[string]any, which encoding/json writes with its keys sorted, so each model's variants object in opencode.json came out high, low, max, medium, ultra, xhigh, and OpenCode builds its variant list from the object in key order (checked with OpenCode 1.18.34: opencode models --verbose under a sandbox HOME/XDG dirs keeps a config's variants in the file's order, alphabetical or by strength; it doesn't sort them itself). openCodeVariants now returns an orderedJSON (a key/value list whose MarshalJSON writes keys as given) of the model's efforts put weakest first by gateway.ByStrength, the gateway's effortRank order (none, minimal, low, medium, high, xhigh, max, ultra; a level it doesn't know after them, stably), so a level appended after max (ultra) lands last too; edit.SetJSON keeps the custom marshaller's order when it indents the block. An opencode.json an older magpie wrote would have stayed alphabetical, as Sync's sameJSON compares decoded values and took it for the same block: OpenCode's (and its WSL and mimocode forms', through openCodeLike) and OpenChamber's Sync now use syncJSONInOrder, which also rewrites the block when its tokens, keys included, don't read in the same order as magpie's (sameOrder), and leaves one in order alone; the other agents' syncs are as before. TestOpenCodeVariants now checks the marshalled bytes (weakest first, an out-of-order list sorted, none as {}), and TestOpenCodeVariantsInOrder writes opencode.json under a temp HOME and checks the raw file lists low, medium, high, xhigh, max, ultra, that a block in the old alphabetical order is put in order by Sync and that a second Sync leaves the file byte for byte; both fail on the old code, and the Sync half fails with plain syncJSON. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried in OpenCode's or OpenChamber's own picker with the reporter's setup; OpenCode reads its config at start, so one already open shows the new order after it is reopened.
2026-10-04 03:19:37 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass.
2026-10-01 23:15:07 +08:00
agents: each agent's CLI shows its version and updates in one click (#202 JoeyMa-zh: Agents 页面增加"更新 CLI"功能 — 检查各 agent CLI 的版本并一键更新) — the Agents page now puts each CLI's installed version after its name (read with <cli> --version, 10s timeout, no stdin) and, when a newer one is out and magpie can tell how it was installed, a small "Update to x.y.z" pill. How it was installed comes from the resolved binary: the vendor's own installer first (Claude Code's ~/.local/share/claude/versions → claude update, Codex standalone → codex update, ~/.opencode/bin → opencode upgrade), then a global node_modules (bun, pnpm, else npm, run as npm install -g --prefix <prefix> pkg@latest with that prefix's npm, and only where the prefix is writable), then a Homebrew formula or cask allowlisted per agent (brew upgrade [--cask]); anything else shows the version alone, with no button. The latest comes from the npm registry or brew info --json=v2 (no auto-update), cached 6h (15min after a failure); installed versions are cached by the binary's path, size and mtime. GET /api/agents/cli waits at most 3s and says pending, and the page asks again; POST /api/agents/cli/{id} runs the update (one at a time per agent, 10min cap), reads the version again and says so if it did not change, or gives the command's last lines when it fails. The pill goes busy in place and the page never scrolls; not in the tray panel. zh strings added. Tested with a new internal/agent/cliupdate_test.go (version order and parsing; npm/bun/pnpm/brew formula and cask/native installs, a read-only prefix, a local node_modules and unknown binaries in a fake PATH; an update against a fake registry and updater) and a new internal/gui/tests/cli-update.test.cjs in Chromium and WebKit (versions, pills only where magpie can update, row heights, an update with the view scrolled, a failing one, zh). No real update was run. go build (nogui, GOOS=windows, GOOS=linux), go test -tags nogui ./... and the GUI tests pass
2026-09-29 17:56:43 +08:00
agents: each agent's CLI shows its version and updates in one click (#202 JoeyMa-zh: Agents 页面增加"更新 CLI"功能 — 检查各 agent CLI 的版本并一键更新) — the Agents page now puts each CLI's installed version after its name (read with <cli> --version, 10s timeout, no stdin) and, when a newer one is out and magpie can tell how it was installed, a small "Update to x.y.z" pill. How it was installed comes from the resolved binary: the vendor's own installer first (Claude Code's ~/.local/share/claude/versions → claude update, Codex standalone → codex update, ~/.opencode/bin → opencode upgrade), then a global node_modules (bun, pnpm, else npm, run as npm install -g --prefix <prefix> pkg@latest with that prefix's npm, and only where the prefix is writable), then a Homebrew formula or cask allowlisted per agent (brew upgrade [--cask]); anything else shows the version alone, with no button. The latest comes from the npm registry or brew info --json=v2 (no auto-update), cached 6h (15min after a failure); installed versions are cached by the binary's path, size and mtime. GET /api/agents/cli waits at most 3s and says pending, and the page asks again; POST /api/agents/cli/{id} runs the update (one at a time per agent, 10min cap), reads the version again and says so if it did not change, or gives the command's last lines when it fails. The pill goes busy in place and the page never scrolls; not in the tray panel. zh strings added. Tested with a new internal/agent/cliupdate_test.go (version order and parsing; npm/bun/pnpm/brew formula and cask/native installs, a read-only prefix, a local node_modules and unknown binaries in a fake PATH; an update against a fake registry and updater) and a new internal/gui/tests/cli-update.test.cjs in Chromium and WebKit (versions, pills only where magpie can update, row heights, an update with the view scrolled, a failing one, zh). No real update was run. go build (nogui, GOOS=windows, GOOS=linux), go test -tags nogui ./... and the GUI tests pass
2026-09-29 17:56:43 +08:00
agents: whether WSL is in mirrored networking is asked of WSL itself (wslinfo --networking-mode), and a UTF-16 .wslconfig is read (lgtm on Discord: told "WSL Ubuntu isn't in mirrored networking … pointed at Windows (http://192.168.16.1:3425)", while their WSL has always been in Mirrored) — magpie decided it by %UserProfile%\.wslconfig alone, read as UTF-8: a .wslconfig Notepad saved as "Unicode" (UTF-16, which WSL reads) said nothing, a "[wsl2] # comment" header ended the section, and mirrored set anywhere magpie didn't read was missed — so a really mirrored distro was pointed at its default route, which under mirrored is the LAN router, not Windows. The probe each running distro already gets now also prints wslinfo --networking-mode (WSL 2.0 on), kept as the distro's Net ("mirrored", "nat", …) and deciding Mirrored; .wslconfig decides only when there is no wslinfo, and is read as UTF-8, UTF-16LE (BOM or not) or UTF-16BE. A distro seen stopped is probed again once it runs, so WSL restarted in another mode is seen without restarting magpie. The notice says what it knows: "WSL Ubuntu is in nat networking, not mirrored, …", or, without wslinfo, that magpie couldn't ask and .wslconfig doesn't set it — never "isn't in mirrored" on .wslconfig's word alone. TestWSLConfigUTF16 (UTF-8, its BOM, UTF-16LE with and without BOM, UTF-16BE; fails without the change for the UTF-16 three), TestParseProbeNet, TestWSLNetworkingFromWslinfo (wslinfo mirrored with no .wslconfig is 127.0.0.1; wslinfo nat beats a .wslconfig saying mirrored; the fallback either way and its notice) and TestWSLReprobedAfterStop are new. The probe run through the real wsl.exe on a Windows 11 box (WSL 2.6.1, a NAT distro) read net:nat. 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.
2026-10-03 00:17:13 +08:00
sessions: the Sessions page and local usage read the agents in WSL too, and resume one there through wsl.exe (lgtm on Discord: magpie can't detect the session lists of agents inside WSL?) — on Windows magpie already finds the WSL distros an agent is set up in (internal/agent's wslDistros, the distro user's home as \\wsl.localhost\<distro>\home\<user>), but the session reader only looked at this computer's own ~/.claude, ~/.codex and ~/.pi. Now internal/agent hands those homes to the sessions package (sessions.WSLHomes, set in init, no second discovery), and the sessions of Claude Code, Codex and Pi in each distro are listed beside this computer's, with Session.WSL naming the distro: a "WSL <distro>" badge on the Sessions page's rows and the management page, a WSL line in the details, " · WSL <distro>" in the API's name. Resume runs in the distro: wsl.exe -d '<distro>' --cd '<cwd>' -e sh -lc 'exec ${SHELL:-sh} -lic ''claude --resume <id>''' (the user's own shell, so the agent's PATH is there; no double quotes, which PowerShell 5.1 mangles). Their calls count in local usage (callFiles). Reading a distro over \\wsl.localhost is slow and opening a file in a stopped distro starts it, so the files are listed in the background, at most every 30 s, the listing kept in sessions-wsl.json; the page waits for it only the first time ever (up to 3 s); a stopped distro's sessions stay listed as last read and nothing in it is opened (the parse cache and call shards keep them). magpie doesn't delete a session in WSL: the checkbox and Delete are off for them, with a note to delete them there, and sessions.Delete refuses. OpenCode in WSL isn't read (its SQLite over \\wsl.localhost isn't reliable). zh strings added. TestWSLSessionsListed, TestWSLStoppedDistroKept and TestWSLNoneWithoutHomes (internal/sessions) and TestWSLSessionsOfTheDistro (internal/agent, FakeWSL: a Claude Code session in a fake Ubuntu is listed with its distro and the wsl.exe resume line) 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. Not tried on a real WSL with agent sessions: the Windows test box's distros have no Claude Code, Codex or Pi sessions; the resume line wasn't run in PowerShell, and the pages weren't opened in a browser.
2026-10-03 23:55:18 +08:00
agent: ZCode's magpie provider pointed at a magpie on another machine keeps that address and key when magpie syncs its models (Discord, 悠悠哥: ZCode connected in a local magpie for its model list, then its base URL and API key changed by hand in ZCode to a magpie deployed on a NAS, kept going back to the local gateway's, they guessed on each update) — ZCode's Sync, which runs whenever magpie's models change and brings the provider in ~/.zcode/v2/config.json and the rule in provider_config.json up to date, wrote options.baseURL/apiKey and config.api.baseUrl/access.apiKey as gateway.URL() and gateway.Token every time. A sync now keeps an address the provider holds whose host isn't this machine's loopback (onAnotherMachine: an http(s) URL with a host other than localhost, a loopback or unspecified IP), with its key (magpie's token where it has none), and refreshes only the models; one on loopback still follows the gateway, so a magpie on another port keeps rewiring it. Picking magpie in the agent's provider field (Set) points it at this magpie as before. TestZCodeKeepsRemoteAddress: a NAS address kept by a sync in both files while a new model arrives, a loopback one moved to the gateway, connecting in magpie resets a NAS one, and onAnotherMachine's cases. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried in ZCode itself with the reporter's NAS; the models listed are this magpie's, so one the NAS's magpie doesn't serve is refused there.
2026-10-04 11:45:08 +08:00
agent: ZCode's magpie provider pointed at a magpie on another machine keeps that address and key when magpie syncs its models (Discord, 悠悠哥: ZCode connected in a local magpie for its model list, then its base URL and API key changed by hand in ZCode to a magpie deployed on a NAS, kept going back to the local gateway's, they guessed on each update) — ZCode's Sync, which runs whenever magpie's models change and brings the provider in ~/.zcode/v2/config.json and the rule in provider_config.json up to date, wrote options.baseURL/apiKey and config.api.baseUrl/access.apiKey as gateway.URL() and gateway.Token every time. A sync now keeps an address the provider holds whose host isn't this machine's loopback (onAnotherMachine: an http(s) URL with a host other than localhost, a loopback or unspecified IP), with its key (magpie's token where it has none), and refreshes only the models; one on loopback still follows the gateway, so a magpie on another port keeps rewiring it. Picking magpie in the agent's provider field (Set) points it at this magpie as before. TestZCodeKeepsRemoteAddress: a NAS address kept by a sync in both files while a new model arrives, a loopback one moved to the gateway, connecting in magpie resets a NAS one, and onAnotherMachine's cases. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried in ZCode itself with the reporter's NAS; the models listed are this magpie's, so one the NAS's magpie doesn't serve is refused there.
2026-10-04 11:45:08 +08:00