Files
magpie/internal/agent
yetone 17f790b145 agent: five package-level twins nothing calls are gone — isCodexGateway, ccProviderJSON, fxProvider, hermesProvider and writeMiniMaxEntry
Each was a one-line wrapper of its *At function for the local gateway.
The callers moved to closures of the same name over the agent's own
address (at.v1(), at.gw()), which shadow the package function, so the
wrappers were reached by nothing, tests included (deadcode -test). Their
doc comments now sit on the *At functions, and isCodexGatewayOn has its
own again: it had been left above codexKeptGateway.

go vet (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui
./internal/agent under a temp HOME pass.
2026-10-06 04:04:47 +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: an agent's own provider named as one of magpie's isn't magpie's, in every agent that spells a model provider/model (the rest of #835) — OpenHanako's own deepseek/deepseek-v4-pro read as magpie's deepseek, and so did a model of any agent's own provider whose name magpie has a provider by: Pi's, Crush's, Hermes's, OpenCode's relay/glm-4.6 with magpie's relay had the row connected on the agent's own model, and Disconnect from magpie put that model back and left the row connected. An agent says how magpie's values are spelled in it (Spelled, replacing #835's Prefixed): magpie/<ref> for Antigravity CLI, Pi, OmO, Aside, Goose, Zed, VS Code, Crush, DeepSeek Harness, Command Code, fx, omp, Hermes, Mister Morph, Kimi Code, Empryo, MiniMax Code, Droid, Qoder, Qoder CN, Grok Build, AtomCode, Cline and OpenHanako, whose every Get spells magpie's so (a sandbox Set of magpie/relay/glm-4.6 read back as that in each); for OpenCode, MiMo Code and OpenChamber also a provider of the config's own that sends to magpie's gateway, as openCodeRef names a model there. A stopped WSL distro's agent keeps its live one's. Left as they are: Claude Code, Claude Desktop, Codex, Gemini CLI, Cursor, Copilot, Devin (magpie's are bare refs there), Muse Code (a model with / is magpie's by design: Meta's have none), Alma (its own are providerId:model), Air (magpie's only). TestOwnProviderNamedAsMagpies (26 agents: own relay/glm-4.6 not connected, Connect, Disconnect puts it back and the row is off) fails on the old code in each; TestOpenCodeGatewayProviderIsMagpies. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 06:49:45 +08:00
…
agent, gui: Claude Code taken off magpie by Default goes under Not set up and says Default (EZN7L2C3, #834 on v0.1.920) — picking Default and confirming Use default left the row up among the connected ones while it said Not connected, its model read Pick a model and its list had magpie's models alone. Default takes Claude Code's tiers and subagent model out with magpie's endpoint; Apply recorded only the field picked, so those read as changed outside magpie (replaced drift) and the drift kept the row up. Apply now records every field magpie set before that the change moves too. An agent not connected whose list has models of its own (Claude Code's, asked of Anthropic directly) now says what it is on, its Default or its own model, and lists everything as when connected: Default, its own models, magpie's. TestClaudeDefaultLeavesNoDrift (fails on the old code: drift replaced opus; a tier changed outside magpie is still said to be); claude-default-off.test.cjs (WebKit, en and zh: folded under Not set up, switch off, Default shown, Default current with the direct and via-magpie models listed, no scroll; fails on the old code: Pick a model / 选模型). agent-path-same, agent-leave-magpie, claude-picker-fold, claude-direct, agent-start-pick, model-rate, unlisted-models, agent-connect, agent-field-names, pi-default-note, click-scroll, desktop-model-menu, model-pick, favorite-star, agent-disconnect, agent-layout, gui-ja and gui-de pass on WebKit. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 06:40:46 +08:00
2026-10-04 20:33:12 +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
agent, gui: Codex left on model_provider = "magpie" with no [model_providers.magpie] loads its config again, and connecting with nothing in magpie says what to do, in the reader's language (Tystem on Discord) — the Codex app said "无法加载 config.toml … Model provider magpie not found", magpie showed Codex as not connected on "deepseek-flash", and its switch answered only "Codex can't be connected to magpie", in English. Codex looks model_provider up in [model_providers.*] as it loads config.toml (codex-rs: "Model provider {id} not found"), so the key without the table keeps it from loading any config, a new thread too, not just an old one. magpie never writes one without the other: it takes model_provider out whenever it steps out as the provider (disconnect, Unwire, a model of Codex's own, Join) and keeps the table so the threads started on magpie still open. That is unchanged, and TestCodexSteppingOutLeavesNoHalfState now covers it. Another tool or a hand edit had taken the table away. Sync, at magpie's start and whenever the catalog changes, now writes the table back whenever the config names magpie as its provider, at the top or in a profile, and has no table, whether Codex is connected or not. Check reports that state too. A config magpie can't parse is still only reported, never written to. A Connect that finds none of magpie's models because no provider or subscription has been added answers agent.NoModelsError, "Add a provider or subscription in magpie first, then connect Codex". /api answers it with code no_models and the agent's name, which app.js says through t() (en/zh/ja/de). docs/reference.md no longer says the table goes with a native model. TestCodexProviderWithoutTable (top and profile: Check says so, Sync writes the table) and TestConnectWithNoModels in internal/agent, TestAgentConnectNoModels in internal/gui, and agent-connect-no-models.test.cjs (WebKit, en/zh/ja/de: the toast in the reader's language, the switch back off, no scroll, no native dialog) are new and fail without the change; the latter's en case passes either way, as the server's message is English. Chromium wouldn't launch on this machine for this test or the existing agent-connect.test.cjs. TestCodexSyncAddsBaseURLToProvider now expects the table added to a hand-made provider that had none. go vet, go build (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui ./... under a temp HOME pass. In the first full run, internal/gui's TestProvidersAnswerWhileListsComeIn and internal/proc's TestUserPath failed under load; both passed alone and in the second full run.
2026-10-05 21:09:13 +08:00
agent, gui: Codex's row has a square for the model it writes its memories with (Yc on Discord) — Codex sums each thread up with gpt-5.6-luna and consolidates its memories with gpt-5.6-terra (medium), whatever model it runs, and nothing in magpie could change that. Codex reads both from config.toml's [memories] extract_model and consolidation_model (codex-rs/config/src/types.rs; the defaults are memory_extraction_preferred_model / memory_consolidation_preferred_model in model-provider). Codex's row now has a memories square beside the subagents' one, opening the app's model picker: a model picked writes both keys, Default removes them (and a [memories] table left empty), the user's other [memories] keys stay. A model of magpie's is offered and taken only while Codex runs through magpie, as for subagents, and is removed when Codex steps out of magpie or is disconnected, since Codex could no longer find it. Unset, its title says what Codex uses. en/zh/ja/de. TestCodexMemoriesModel and TestCodexMemoriesUnwire (temp HOME) fail without the change; codex-memories.test.cjs (WebKit, en and zh: the square and its unset title, no square with nothing to pick, the model picker with Default first, a pick posted and lit, Default posts "", no select, no scroll, no left border) fails without it. subagent-effort, click-scroll, codex-titles, agent-start-pick and desktop-tiers pass in WebKit. go vet, go build (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui ./... under a temp HOME pass.
2026-10-05 19:11:34 +08:00
agent, gui: Codex left on model_provider = "magpie" with no [model_providers.magpie] loads its config again, and connecting with nothing in magpie says what to do, in the reader's language (Tystem on Discord) — the Codex app said "无法加载 config.toml … Model provider magpie not found", magpie showed Codex as not connected on "deepseek-flash", and its switch answered only "Codex can't be connected to magpie", in English. Codex looks model_provider up in [model_providers.*] as it loads config.toml (codex-rs: "Model provider {id} not found"), so the key without the table keeps it from loading any config, a new thread too, not just an old one. magpie never writes one without the other: it takes model_provider out whenever it steps out as the provider (disconnect, Unwire, a model of Codex's own, Join) and keeps the table so the threads started on magpie still open. That is unchanged, and TestCodexSteppingOutLeavesNoHalfState now covers it. Another tool or a hand edit had taken the table away. Sync, at magpie's start and whenever the catalog changes, now writes the table back whenever the config names magpie as its provider, at the top or in a profile, and has no table, whether Codex is connected or not. Check reports that state too. A config magpie can't parse is still only reported, never written to. A Connect that finds none of magpie's models because no provider or subscription has been added answers agent.NoModelsError, "Add a provider or subscription in magpie first, then connect Codex". /api answers it with code no_models and the agent's name, which app.js says through t() (en/zh/ja/de). docs/reference.md no longer says the table goes with a native model. TestCodexProviderWithoutTable (top and profile: Check says so, Sync writes the table) and TestConnectWithNoModels in internal/agent, TestAgentConnectNoModels in internal/gui, and agent-connect-no-models.test.cjs (WebKit, en/zh/ja/de: the toast in the reader's language, the switch back off, no scroll, no native dialog) are new and fail without the change; the latter's en case passes either way, as the server's message is English. Chromium wouldn't launch on this machine for this test or the existing agent-connect.test.cjs. TestCodexSyncAddsBaseURLToProvider now expects the table added to a hand-made provider that had none. go vet, go build (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui ./... under a temp HOME pass. In the first full run, internal/gui's TestProvidersAnswerWhileListsComeIn and internal/proc's TestUserPath failed under load; both passed alone and in the second full run.
2026-10-05 21:09:13 +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 is connected by its row's switch, as other agents are, with no command to run (mamba on Discord: 这个单独搞个启动命令和别的供应商格格不入啊) — its Open configuration's base URL and key are kept in the state.vscdb regular Cursor shares, and are regular Cursor's own override settings too, so magpie still writes nothing of Cursor's. It sets CURSOR_LOCAL_AGENT_BASE_URL (<gateway>/v1) and CURSOR_LOCAL_AGENT_API_KEY (magpie-cursor-local), which only this build reads, for the user: launchctl setenv on the Mac (apps opened from the Dock or Finder from then on have them), HKCU\Environment plus a WM_SETTINGCHANGE on Windows, ~/.config/environment.d/magpie-cursor-local.conf (from the next login) and systemctl --user set-environment on Linux; switched off, it clears them. magpie notes it in cursor-local.env in its config folder, which the row reads as connected, and sets them again whenever it serves the gateway (launchd forgets them at a restart; the port may have changed). The row has the provider field (magpie) and the connect switch; connecting says to quit the app and open it again, and that a base URL in Open configuration still comes first. The launch command stays as the square beside it, for a start from a shell. TestCursorLocalConnects (connect sets them, a serve sets them again, disconnect clears them, off a serve sets nothing) fails on the old code; cursor-local-launch.test.cjs now checks the switch connects it with no command copied (WebKit, en and zh); agy-launch passes. Not tried with the real app (not installed here), and launchctl/the registry are not touched under tests. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 00:18:22 +08:00
agent: Cursor Private Inference is connected by its row's switch, as other agents are, with no command to run (mamba on Discord: 这个单独搞个启动命令和别的供应商格格不入啊) — its Open configuration's base URL and key are kept in the state.vscdb regular Cursor shares, and are regular Cursor's own override settings too, so magpie still writes nothing of Cursor's. It sets CURSOR_LOCAL_AGENT_BASE_URL (<gateway>/v1) and CURSOR_LOCAL_AGENT_API_KEY (magpie-cursor-local), which only this build reads, for the user: launchctl setenv on the Mac (apps opened from the Dock or Finder from then on have them), HKCU\Environment plus a WM_SETTINGCHANGE on Windows, ~/.config/environment.d/magpie-cursor-local.conf (from the next login) and systemctl --user set-environment on Linux; switched off, it clears them. magpie notes it in cursor-local.env in its config folder, which the row reads as connected, and sets them again whenever it serves the gateway (launchd forgets them at a restart; the port may have changed). The row has the provider field (magpie) and the connect switch; connecting says to quit the app and open it again, and that a base URL in Open configuration still comes first. The launch command stays as the square beside it, for a start from a shell. TestCursorLocalConnects (connect sets them, a serve sets them again, disconnect clears them, off a serve sets nothing) fails on the old code; cursor-local-launch.test.cjs now checks the switch connects it with no command copied (WebKit, en and zh); agy-launch passes. Not tried with the real app (not installed here), and launchctl/the registry are not touched under tests. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 00:18:22 +08:00
agent: Cursor Private Inference is connected by its row's switch, as other agents are, with no command to run (mamba on Discord: 这个单独搞个启动命令和别的供应商格格不入啊) — its Open configuration's base URL and key are kept in the state.vscdb regular Cursor shares, and are regular Cursor's own override settings too, so magpie still writes nothing of Cursor's. It sets CURSOR_LOCAL_AGENT_BASE_URL (<gateway>/v1) and CURSOR_LOCAL_AGENT_API_KEY (magpie-cursor-local), which only this build reads, for the user: launchctl setenv on the Mac (apps opened from the Dock or Finder from then on have them), HKCU\Environment plus a WM_SETTINGCHANGE on Windows, ~/.config/environment.d/magpie-cursor-local.conf (from the next login) and systemctl --user set-environment on Linux; switched off, it clears them. magpie notes it in cursor-local.env in its config folder, which the row reads as connected, and sets them again whenever it serves the gateway (launchd forgets them at a restart; the port may have changed). The row has the provider field (magpie) and the connect switch; connecting says to quit the app and open it again, and that a base URL in Open configuration still comes first. The launch command stays as the square beside it, for a start from a shell. TestCursorLocalConnects (connect sets them, a serve sets them again, disconnect clears them, off a serve sets nothing) fails on the old code; cursor-local-launch.test.cjs now checks the switch connects it with no command copied (WebKit, en and zh); agy-launch passes. Not tried with the real app (not installed here), and launchctl/the registry are not touched under tests. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 00:18:22 +08:00
agent: Cursor Private Inference is connected by its row's switch, as other agents are, with no command to run (mamba on Discord: 这个单独搞个启动命令和别的供应商格格不入啊) — its Open configuration's base URL and key are kept in the state.vscdb regular Cursor shares, and are regular Cursor's own override settings too, so magpie still writes nothing of Cursor's. It sets CURSOR_LOCAL_AGENT_BASE_URL (<gateway>/v1) and CURSOR_LOCAL_AGENT_API_KEY (magpie-cursor-local), which only this build reads, for the user: launchctl setenv on the Mac (apps opened from the Dock or Finder from then on have them), HKCU\Environment plus a WM_SETTINGCHANGE on Windows, ~/.config/environment.d/magpie-cursor-local.conf (from the next login) and systemctl --user set-environment on Linux; switched off, it clears them. magpie notes it in cursor-local.env in its config folder, which the row reads as connected, and sets them again whenever it serves the gateway (launchd forgets them at a restart; the port may have changed). The row has the provider field (magpie) and the connect switch; connecting says to quit the app and open it again, and that a base URL in Open configuration still comes first. The launch command stays as the square beside it, for a start from a shell. TestCursorLocalConnects (connect sets them, a serve sets them again, disconnect clears them, off a serve sets nothing) fails on the old code; cursor-local-launch.test.cjs now checks the switch connects it with no command copied (WebKit, en and zh); agy-launch passes. Not tried with the real app (not installed here), and launchctl/the registry are not touched under tests. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 00:18:22 +08:00
agent: an agent's own provider named as one of magpie's isn't magpie's, in every agent that spells a model provider/model (the rest of #835) — OpenHanako's own deepseek/deepseek-v4-pro read as magpie's deepseek, and so did a model of any agent's own provider whose name magpie has a provider by: Pi's, Crush's, Hermes's, OpenCode's relay/glm-4.6 with magpie's relay had the row connected on the agent's own model, and Disconnect from magpie put that model back and left the row connected. An agent says how magpie's values are spelled in it (Spelled, replacing #835's Prefixed): magpie/<ref> for Antigravity CLI, Pi, OmO, Aside, Goose, Zed, VS Code, Crush, DeepSeek Harness, Command Code, fx, omp, Hermes, Mister Morph, Kimi Code, Empryo, MiniMax Code, Droid, Qoder, Qoder CN, Grok Build, AtomCode, Cline and OpenHanako, whose every Get spells magpie's so (a sandbox Set of magpie/relay/glm-4.6 read back as that in each); for OpenCode, MiMo Code and OpenChamber also a provider of the config's own that sends to magpie's gateway, as openCodeRef names a model there. A stopped WSL distro's agent keeps its live one's. Left as they are: Claude Code, Claude Desktop, Codex, Gemini CLI, Cursor, Copilot, Devin (magpie's are bare refs there), Muse Code (a model with / is magpie's by design: Meta's have none), Alma (its own are providerId:model), Air (magpie's only). TestOwnProviderNamedAsMagpies (26 agents: own relay/glm-4.6 not connected, Connect, Disconnect puts it back and the row is off) fails on the old code in each; TestOpenCodeGatewayProviderIsMagpies. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 06:49:45 +08:00
…
agent: an agent's own provider named as one of magpie's isn't magpie's, in every agent that spells a model provider/model (the rest of #835) — OpenHanako's own deepseek/deepseek-v4-pro read as magpie's deepseek, and so did a model of any agent's own provider whose name magpie has a provider by: Pi's, Crush's, Hermes's, OpenCode's relay/glm-4.6 with magpie's relay had the row connected on the agent's own model, and Disconnect from magpie put that model back and left the row connected. An agent says how magpie's values are spelled in it (Spelled, replacing #835's Prefixed): magpie/<ref> for Antigravity CLI, Pi, OmO, Aside, Goose, Zed, VS Code, Crush, DeepSeek Harness, Command Code, fx, omp, Hermes, Mister Morph, Kimi Code, Empryo, MiniMax Code, Droid, Qoder, Qoder CN, Grok Build, AtomCode, Cline and OpenHanako, whose every Get spells magpie's so (a sandbox Set of magpie/relay/glm-4.6 read back as that in each); for OpenCode, MiMo Code and OpenChamber also a provider of the config's own that sends to magpie's gateway, as openCodeRef names a model there. A stopped WSL distro's agent keeps its live one's. Left as they are: Claude Code, Claude Desktop, Codex, Gemini CLI, Cursor, Copilot, Devin (magpie's are bare refs there), Muse Code (a model with / is magpie's by design: Meta's have none), Alma (its own are providerId:model), Air (magpie's only). TestOwnProviderNamedAsMagpies (26 agents: own relay/glm-4.6 not connected, Connect, Disconnect puts it back and the row is off) fails on the old code in each; TestOpenCodeGatewayProviderIsMagpies. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 06:49:45 +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
agent, gui: an agent whose CLI is gone while its settings are left says so, and Install another agent offers it again (evilgaoshu, #843: 卸载了 DeepSeek Harness,但 ~/.dsh 还在,Agents 页面依然把它当作已安装列出来,也不会出现在 Install another agent 里) — an agent was here when its config or folder was, so dsh, uninstalled with ~/.dsh kept, was listed as installed, and Install another agent left out every agent listed. Agent.CLIMissing: its folder or config is here, its CLI isn't, neither on PATH nor where users' tools go (proc.FindTool, as #839's Claude Code is found on Windows); only for an agent that is its CLI and has an install command magpie knows, not one whose folder an app or editor extension keeps too (Codex, Claude Code, Gemini CLI, OpenCode, Cline, Goose), nor a WSL one. Its row stays, settings kept and nothing deleted, with "CLI not found" where its version goes (its tooltip names the folder and points to the install command), and Install another agent lists it, marked "CLI not found" under its name. dsh now has its npm package, @deepseek-ai/dsh, so it is offered with npm install -g @deepseek-ai/dsh, and its version and updates show like the other CLIs'. zh, ja, de strings. TestCLIMissing (dsh with ~/.dsh and no dsh is missing and offered; codex's folder, an agent not here, a WSL one aren't; dsh in ~/.local/bin off PATH isn't) fails on the old code; agent-cli-missing.test.cjs (WebKit, en and zh: the row's note, its height kept, Install another agent lists it with its command) fails on the old code. agent-update-all, agent-layout, agent-start-pick, click-scroll, gui-ja, gui-de and import-row pass on WebKit. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 09:25:01 +08:00
agent, gui: an agent whose CLI is gone while its settings are left says so, and Install another agent offers it again (evilgaoshu, #843: 卸载了 DeepSeek Harness,但 ~/.dsh 还在,Agents 页面依然把它当作已安装列出来,也不会出现在 Install another agent 里) — an agent was here when its config or folder was, so dsh, uninstalled with ~/.dsh kept, was listed as installed, and Install another agent left out every agent listed. Agent.CLIMissing: its folder or config is here, its CLI isn't, neither on PATH nor where users' tools go (proc.FindTool, as #839's Claude Code is found on Windows); only for an agent that is its CLI and has an install command magpie knows, not one whose folder an app or editor extension keeps too (Codex, Claude Code, Gemini CLI, OpenCode, Cline, Goose), nor a WSL one. Its row stays, settings kept and nothing deleted, with "CLI not found" where its version goes (its tooltip names the folder and points to the install command), and Install another agent lists it, marked "CLI not found" under its name. dsh now has its npm package, @deepseek-ai/dsh, so it is offered with npm install -g @deepseek-ai/dsh, and its version and updates show like the other CLIs'. zh, ja, de strings. TestCLIMissing (dsh with ~/.dsh and no dsh is missing and offered; codex's folder, an agent not here, a WSL one aren't; dsh in ~/.local/bin off PATH isn't) fails on the old code; agent-cli-missing.test.cjs (WebKit, en and zh: the row's note, its height kept, Install another agent lists it with its command) fails on the old code. agent-update-all, agent-layout, agent-start-pick, click-scroll, gui-ja, gui-de and import-row pass on WebKit. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 09:25:01 +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
agent: an omp in WSL under NAT gets the gateway's network key, and one bun installed is found and asked its version (whqtian on Discord: a WSL omp connected only once auth: none was swapped for the key by hand, and Kimi K3's max still read xhigh) — a distro not in mirrored networking reaches the gateway at Windows' address (172.23.80.1), where a request without a named key is turned away, yet magpie wrote auth: none there too. Its models.yml now carries the key the gateway is shared on the network with (access.LANSecret: the default LAN key, "" while nothing is shared or it is off) in place of auth: none; an omp on loopback stays keyless. The probe asked omp its version only when sh -l found it on PATH, but bun's and nvm's installers put theirs on PATH in ~/.bashrc, which sh -l doesn't read: the version stayed unknown and max was offered as xhigh, as for an omp older than 16.4.0. It now also looks in ~/.bun/bin, ~/.local/bin, ~/.npm-global/bin, ~/.volta/bin, pnpm's, nvm's, mise's and asdf's folders, and runs --version with the command's folder on PATH, where bun's #!/usr/bin/env bun finds bun. TestOmpKeyBeyondLoopback (NAT address shared or not, loopback, localhost) and TestWSLProbeFindsBunOmp (the probe script run with a bun-installed omp off PATH; fails on the old script: no bin, no version). go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but for TestSavedButSignedOutClaudeServed, which timed out once under load and passes 3 of 3 alone.
2026-10-05 14:40:49 +08:00
…
agent: an omp in WSL under NAT gets the gateway's network key, and one bun installed is found and asked its version (whqtian on Discord: a WSL omp connected only once auth: none was swapped for the key by hand, and Kimi K3's max still read xhigh) — a distro not in mirrored networking reaches the gateway at Windows' address (172.23.80.1), where a request without a named key is turned away, yet magpie wrote auth: none there too. Its models.yml now carries the key the gateway is shared on the network with (access.LANSecret: the default LAN key, "" while nothing is shared or it is off) in place of auth: none; an omp on loopback stays keyless. The probe asked omp its version only when sh -l found it on PATH, but bun's and nvm's installers put theirs on PATH in ~/.bashrc, which sh -l doesn't read: the version stayed unknown and max was offered as xhigh, as for an omp older than 16.4.0. It now also looks in ~/.bun/bin, ~/.local/bin, ~/.npm-global/bin, ~/.volta/bin, pnpm's, nvm's, mise's and asdf's folders, and runs --version with the command's folder on PATH, where bun's #!/usr/bin/env bun finds bun. TestOmpKeyBeyondLoopback (NAT address shared or not, loopback, localhost) and TestWSLProbeFindsBunOmp (the probe script run with a bun-installed omp off PATH; fails on the old script: no bin, no version). go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but for TestSavedButSignedOutClaudeServed, which timed out once under load and passes 3 of 3 alone.
2026-10-05 14:40:49 +08:00
agent: an omp in WSL under NAT gets the gateway's network key, and one bun installed is found and asked its version (whqtian on Discord: a WSL omp connected only once auth: none was swapped for the key by hand, and Kimi K3's max still read xhigh) — a distro not in mirrored networking reaches the gateway at Windows' address (172.23.80.1), where a request without a named key is turned away, yet magpie wrote auth: none there too. Its models.yml now carries the key the gateway is shared on the network with (access.LANSecret: the default LAN key, "" while nothing is shared or it is off) in place of auth: none; an omp on loopback stays keyless. The probe asked omp its version only when sh -l found it on PATH, but bun's and nvm's installers put theirs on PATH in ~/.bashrc, which sh -l doesn't read: the version stayed unknown and max was offered as xhigh, as for an omp older than 16.4.0. It now also looks in ~/.bun/bin, ~/.local/bin, ~/.npm-global/bin, ~/.volta/bin, pnpm's, nvm's, mise's and asdf's folders, and runs --version with the command's folder on PATH, where bun's #!/usr/bin/env bun finds bun. TestOmpKeyBeyondLoopback (NAT address shared or not, loopback, localhost) and TestWSLProbeFindsBunOmp (the probe script run with a bun-installed omp off PATH; fails on the old script: no bin, no version). go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but for TestSavedButSignedOutClaudeServed, which timed out once under load and passes 3 of 3 alone.
2026-10-05 14:40:49 +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: an agent's own provider named as one of magpie's isn't magpie's, in every agent that spells a model provider/model (the rest of #835) — OpenHanako's own deepseek/deepseek-v4-pro read as magpie's deepseek, and so did a model of any agent's own provider whose name magpie has a provider by: Pi's, Crush's, Hermes's, OpenCode's relay/glm-4.6 with magpie's relay had the row connected on the agent's own model, and Disconnect from magpie put that model back and left the row connected. An agent says how magpie's values are spelled in it (Spelled, replacing #835's Prefixed): magpie/<ref> for Antigravity CLI, Pi, OmO, Aside, Goose, Zed, VS Code, Crush, DeepSeek Harness, Command Code, fx, omp, Hermes, Mister Morph, Kimi Code, Empryo, MiniMax Code, Droid, Qoder, Qoder CN, Grok Build, AtomCode, Cline and OpenHanako, whose every Get spells magpie's so (a sandbox Set of magpie/relay/glm-4.6 read back as that in each); for OpenCode, MiMo Code and OpenChamber also a provider of the config's own that sends to magpie's gateway, as openCodeRef names a model there. A stopped WSL distro's agent keeps its live one's. Left as they are: Claude Code, Claude Desktop, Codex, Gemini CLI, Cursor, Copilot, Devin (magpie's are bare refs there), Muse Code (a model with / is magpie's by design: Meta's have none), Alma (its own are providerId:model), Air (magpie's only). TestOwnProviderNamedAsMagpies (26 agents: own relay/glm-4.6 not connected, Connect, Disconnect puts it back and the row is off) fails on the old code in each; TestOpenCodeGatewayProviderIsMagpies. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 06:49:45 +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: 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
…
…
gui: the header's refresh reads again what the page shown draws, and no longer looks for a newer magpie (evilgaoshu, #844: 顶部刷新按钮按直觉应该是「刷新当前页面」,检查更新是低频操作,不必占用顶部一个常驻按钮) — the round ↻ refreshed the model lists and checked for an update whatever page was shown. Now on Agents it looks for the agents on this computer again: POST /api/agents/rescan (agent.Rescan forgets the answers kept a while because asking was slow: Cursor Private Inference's apps folder, WSL's distro list and failed probes, Alma's server) and draws the list, Install another agent and the CLI versions afresh, so one just installed or removed, or changed outside magpie, shows at once. On Usage it reads the page now, the allowances too (as its Refresh now); in the panel, Agents rescans, Allowances reads the allowances and Usage the requests; on Providers and every other page it refreshes the model lists as before. Its tooltip says what it reads on the page shown (zh, ja, de strings). A newer magpie is looked for by magpie's own timer and Settings › About's Check, as before. TestRescanLooksAgain (an app installed after magpie looked is found only after the half minute without it) and refresh-page.test.cjs (WebKit, en and zh, window and panel: tooltip per page, Agents rescans and a new agent shows and leaves Install another agent, Usage reads the allowances afresh, Providers syncs, never an update check, no click moves the page) fail on the old code; sync-update.test.cjs, which asserted the old update check, is replaced by it. sync-spin, update-hide, update-check, click-scroll, gui-ja, gui-de, usage-card-refresh and agent-update-all pass on WebKit. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 09:26:30 +08:00
gui: the header's refresh reads again what the page shown draws, and no longer looks for a newer magpie (evilgaoshu, #844: 顶部刷新按钮按直觉应该是「刷新当前页面」,检查更新是低频操作,不必占用顶部一个常驻按钮) — the round ↻ refreshed the model lists and checked for an update whatever page was shown. Now on Agents it looks for the agents on this computer again: POST /api/agents/rescan (agent.Rescan forgets the answers kept a while because asking was slow: Cursor Private Inference's apps folder, WSL's distro list and failed probes, Alma's server) and draws the list, Install another agent and the CLI versions afresh, so one just installed or removed, or changed outside magpie, shows at once. On Usage it reads the page now, the allowances too (as its Refresh now); in the panel, Agents rescans, Allowances reads the allowances and Usage the requests; on Providers and every other page it refreshes the model lists as before. Its tooltip says what it reads on the page shown (zh, ja, de strings). A newer magpie is looked for by magpie's own timer and Settings › About's Check, as before. TestRescanLooksAgain (an app installed after magpie looked is found only after the half minute without it) and refresh-page.test.cjs (WebKit, en and zh, window and panel: tooltip per page, Agents rescans and a new agent shows and leaves Install another agent, Usage reads the allowances afresh, Providers syncs, never an update check, no click moves the page) fail on the old code; sync-update.test.cjs, which asserted the old update check, is replaced by it. sync-spin, update-hide, update-check, click-scroll, gui-ja, gui-de, usage-card-refresh and agent-update-all pass on WebKit. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-05 09:26:30 +08:00
…
…
perf: magpie opens and shows the Agents page in a fraction of the time it took (Junjie Zhou on Discord: 8 个 agent 30 个 provider … 每次我打开的时候都会很慢,要好几秒。setting 页面秒进后 我切换到 agent 就有问题) — at start, writing the agents' model lists (agent.SyncCatalog) built every provider's catalog thousands of times with nothing held, each build reading migrations.json, settings and groups again: 6000+ file reads and ~8.5s of CPU in the first 8s with the owner's 30-odd providers, all competing with the first /api/state and the Agents page. Now SyncCatalog, magpieModels and main's start-up moves run under provider.Hold, migrations, groups, settings and a provider's fetched models are held for a second like the rest, and filememo.Hold lets a GET /api/* not stat a file it confirmed unchanged within the last second (any magpie write, Changed() or a recent mtime still reads it again). A big ~/.codex/config.toml parsed in quadratic time (the TOML parser's Shape counts newlines from the start for every key): a 3 MB one took 5.4s, now 0.04s (tomlShaper). theInstalled reads through edit.Read's memo. Measured with a copy of the owner's magpie config and agent configs under a sandbox HOME, the real server in WebKit: CPU in the first 8s 8.59s → 0.39s, page up 475 → 75ms, Agents rows drawn 775 → 325ms after start; the agents' written model files are unchanged (pi byte for byte, opencode the same models). TestTOMLShaperMatchesParser, TestTOMLBigFileParsesInLinearTime (fails on the old code), TestHold (filememo), TestHoldReadsMigrationsOnce. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui ./... under a temp HOME pass.
2026-10-05 03:02:40 +08:00
agent: an omp in WSL under NAT gets the gateway's network key, and one bun installed is found and asked its version (whqtian on Discord: a WSL omp connected only once auth: none was swapped for the key by hand, and Kimi K3's max still read xhigh) — a distro not in mirrored networking reaches the gateway at Windows' address (172.23.80.1), where a request without a named key is turned away, yet magpie wrote auth: none there too. Its models.yml now carries the key the gateway is shared on the network with (access.LANSecret: the default LAN key, "" while nothing is shared or it is off) in place of auth: none; an omp on loopback stays keyless. The probe asked omp its version only when sh -l found it on PATH, but bun's and nvm's installers put theirs on PATH in ~/.bashrc, which sh -l doesn't read: the version stayed unknown and max was offered as xhigh, as for an omp older than 16.4.0. It now also looks in ~/.bun/bin, ~/.local/bin, ~/.npm-global/bin, ~/.volta/bin, pnpm's, nvm's, mise's and asdf's folders, and runs --version with the command's folder on PATH, where bun's #!/usr/bin/env bun finds bun. TestOmpKeyBeyondLoopback (NAT address shared or not, loopback, localhost) and TestWSLProbeFindsBunOmp (the probe script run with a bun-installed omp off PATH; fails on the old script: no bin, no version). go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but for TestSavedButSignedOutClaudeServed, which timed out once under load and passes 3 of 3 alone.
2026-10-05 14:40:49 +08:00
agent: an omp in WSL under NAT gets the gateway's network key, and one bun installed is found and asked its version (whqtian on Discord: a WSL omp connected only once auth: none was swapped for the key by hand, and Kimi K3's max still read xhigh) — a distro not in mirrored networking reaches the gateway at Windows' address (172.23.80.1), where a request without a named key is turned away, yet magpie wrote auth: none there too. Its models.yml now carries the key the gateway is shared on the network with (access.LANSecret: the default LAN key, "" while nothing is shared or it is off) in place of auth: none; an omp on loopback stays keyless. The probe asked omp its version only when sh -l found it on PATH, but bun's and nvm's installers put theirs on PATH in ~/.bashrc, which sh -l doesn't read: the version stayed unknown and max was offered as xhigh, as for an omp older than 16.4.0. It now also looks in ~/.bun/bin, ~/.local/bin, ~/.npm-global/bin, ~/.volta/bin, pnpm's, nvm's, mise's and asdf's folders, and runs --version with the command's folder on PATH, where bun's #!/usr/bin/env bun finds bun. TestOmpKeyBeyondLoopback (NAT address shared or not, loopback, localhost) and TestWSLProbeFindsBunOmp (the probe script run with a bun-installed omp off PATH; fails on the old script: no bin, no version). go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but for TestSavedButSignedOutClaudeServed, which timed out once under load and passes 3 of 3 alone.
2026-10-05 14:40:49 +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