main
15
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9bb2a467e4 |
agent: Snow CLI is an agent magpie sets up: a magpie profile in ~/.snow, made the active one, that Snow App takes in with "Sync Snow CLI API config" (#1457)
Snow CLI (npm snow-ai, MIT, MayDay-wpf/snow-cli) keeps one profile per file under ~/.snow/profiles (or $SNOW_CONFIG_DIR), names the active one in active-profile.json, and copies it over config.json at every start, headless `snow --ask` included. Each profile is the whole snowcfg: base URL, key, request method and models. Snow App (MayDay-wpf/snow-app) reads ~/.snow/profiles/*.json when "Sync Snow CLI API config" is pressed. magpie writes profiles/magpie.json from the profile the user was on (their settings kept, Snow's OAuth sign-in left out): baseUrlMode base at the gateway's /v1, requestMethod chat, the agent's key, the model as advancedModel and basicModel, and the catalog's window and output (200000 and 64000 when not known, the output cut to the window). It makes that profile active and copies it to config.json. The profile the user was on, whether there was an active-profile.json at all, and a magpie.json of their own are stashed; Disconnect, `magpie snow default`, or picking a model of one of the user's profiles puts those back. A Snow from before profiles (config.json alone) gets the default.json Snow itself would make, so its next start doesn't take magpie's config for the user's. Check reports a base URL, key or request method moved off magpie's; Sync rewrites the profile on a port move. A WSL distro's ~/.snow is found and written the same way. Registered: agents.go, the WSL kinds, SNOW_CONFIG_DIR in agentenv, the npm update spec (snow-ai), the icon (Snow App's own, trimmed to 96px), README, docs/reference.md, docs/subsystems/agent-wiring.md, the site's agent list and start.html (en, zh, ja). Run: - go test -tags nogui ./... in a scratch HOME: 44 packages ok. New: TestSnow, TestSnowOwnProfile, TestSnowNoProfiles, TestSnowUsersMagpieProfile, TestSnowCheckSync, TestAgentSnowDefault; snow added to TestOwnProviderNamedAsMagpies, the WSL more-agents tests and TestMaxTokensWithinContextWindow. All fail before this commit (no agent "snow"). - go vet -tags nogui for darwin, linux and windows; gofmt -l clean. - Real Snow CLI 0.9.2 in a sandbox HOME against a sandbox magpie (`magpie serve` on 127.0.0.1:3571, a fake OpenAI upstream on 3561): `magpie snow fake/pro` made the magpie profile active, `snow --ask` answered through the gateway (POST /v1/chat/completions, model pro, logged as agent snow), and `magpie snow default` left profiles, active-profile.json and config.json byte-identical to before. - GUI: agent-layout, agent-connect, agent-models-picker, agent-field-names and models-add-and-icons in Chromium and WebKit; a Snow CLI row checked at 520-960px in en, zh, zh-TW, ja and de in both engines. No new GUI strings. |
||
|
|
dec951229c |
agent: Grok Build installed by xAI's installer shows its newest version and offers grok update, and its version is read again after each update (xiaoxiaofeixz on Discord: Grok at C:\Users\<user>\.grok\bin\grok.exe)
Grok Build had no cliSpec and no Bin (grok is also Homebrew's regex tool), so the Agents page showed nothing about its CLI: no version, no newest, no update. xAI's installers (read from https://x.ai/cli/install.ps1 and install.sh): - install.ps1 copies grok.exe (and agent.exe) into %USERPROFILE%\.grok\bin and puts that on the user PATH; no junction, no versioned folder. grok update copies the new grok.exe over it (the running one renamed to grok.exe.old), so its size and time change. - install.sh links ~/.grok/bin/grok to ../downloads/grok-<platform>; grok update downloads ../downloads/grok-<version>-<platform> and relinks, a new real path per version. - The newest version of a channel is the body of x.ai/cli/<channel> (stable, alpha, enterprise; GCS fallback), the channel kept under [cli] in ~/.grok/config.toml. cliSpec gains `at` (where the vendor installer puts the CLI under home, read there instead of PATH for an agent with no Bin) and `latest` (the newest its own updater installs, for a CLI not on npm). grok's spec: at .grok/bin/grok(.exe), self = grok update for a real path under .grok/bin or .grok/downloads, latest = grokLatest (channel pointer, 6h memo per channel). TestGrokInstalled builds the platform's installer layout under a temp HOME/USERPROFILE with a fake grok on PATH, a served channel pointer and fake version/update runs: PATH's grok isn't taken; 1.0.46 shows 1.0.50 and "grok update" (grok.exe update on Windows); the update reads 1.0.50; grok's own update outside magpie (auto_update) is read again; the alpha channel's newest is alpha's. It fails without the grok spec (macOS and the Windows box: "before: {Version: ...} false") and passes with it. Real use: macOS, a sandbox HOME with the real grok 1.0.46 in install.sh's layout: CLI() said 1.0.46 / 1.0.50 / grok update, UpdateCLI ran the real grok update and read 1.0.50 (~/.grok untouched). Windows box (10.0.0.132, sandboxed USERPROFILE/APPDATA/LOCALAPPDATA): the real grok-1.0.46 exe at home\.grok\bin\grok.exe, same result through a real grok update; the real profile's .grok, LocalAppData\grok and user PATH unchanged. There TestGrokInstalled, TestCodexInstallPs1Junctions and TestHowInstalledWindowsShim pass. Siblings: Claude's install.ps1 lands in ~/.local/bin/claude.exe (already matched); Cursor's and Qoder's Windows installers make no junctions or links, and those agents have no cliSpec (not in scope); opencode has no install.ps1 (404); Factory's refused the fetch (403), droid has no cliSpec either. go test -tags nogui ./internal/agent (temp HOME), gofmt -l, go vet, and GOOS=linux / GOOS=windows go vet -tags nogui ./internal/agent pass. |
||
|
|
3691c2047d |
plugin, agent: bun is given a SOCKS proxy through the bridge, so a plugin installs with only a SOCKS system proxy (#1409)
With only a SOCKS system proxy on macOS (127.0.0.1:4401), every plugin
install failed: netproxy.Env put socks5://… in bun add's *_PROXY, and Bun
takes only http:// and https:// proxies, so it stopped with
"UnsupportedProxyProtocol downloading package manifest". The plugin
host's own fetches already went through netproxy.Bridge (hostEnv), but
bunCommand, which runs bun add, update and remove, did not.
- netproxy.EnvForBun rewrites a SOCKS5 HTTPS_PROXY/HTTP_PROXY/ALL_PROXY
(any case) to the loopback HTTP bridge in front of it; others as they are.
- bunCommand uses it, so add, update, remove and the host's run all get it.
- Sibling: an agent CLI installed with bun is updated by `bun add -g`
with the same env (updateEnv in cliupdate.go); npm is left as it is.
- provider-plugins.md says so.
Run:
- TestInstallThroughSOCKSProxy (real bun 1.4.2, fake registry, SOCKS
proxy only): on the old bunCommand it fails with the reporter's exact
"error: UnsupportedProxyProtocol downloading package manifest"; passes
with the fix, through the SOCKS proxy.
- TestEnvForBunBridgesSystemSOCKS (system SOCKS proxy via Env) and
TestUpdateWithBunBridgesSOCKS fail with EnvForBun / the bun branch
broken ("bun is given …socks5://…"), pass with it.
- Real use: a throwaway test with a real SOCKS5 server and only
*_PROXY=socks5://… installed @magpie-community/opencode-cursor-auth
0.2.2 from registry.npmjs.org through it; on the old code the same
failed as UnsupportedProxyProtocol. Scratch HOME, not committed.
- gofmt -l clean; go vet ./...; GOOS=linux go vet -tags nogui ./...;
GOOS=windows go vet ./...; go build; GOOS=linux go build -tags nogui;
GOOS=windows go build; go test -tags nogui ./... (scratch HOME) all ok.
|
||
|
|
98236edd77 |
agent: Codex installed by install.ps1 on Windows shows its newest version and offers codex update, and its version is read again after each update (xiaoxiaofeixz on Discord: 不会自动检测最新的版本)
Codex's install.ps1 puts %LOCALAPPDATA%\Programs\OpenAI\Codex\bin on PATH. That folder is a junction to ~\.codex\packages\standalone\current\bin, and current is a junction to releases\<version>-<target>, retargeted by each update. filepath.EvalSymlinks leaves junctions alone since Go 1.23, so magpie saw the binary only as ...\Programs\OpenAI\Codex\bin\codex.exe: - howInstalled didn't find .codex/packages/standalone in its path, so the Agents page showed the version with no newest version and no update. - installedVersion's stamp was that unchanged path plus size and mtime. npm's archive, which install.ps1's legacy layout copies from, gives every version's codex.exe the same 1985 mtime. So a new release was asked again only if its size happened to differ, else after the 24h memo. proc.RealPath is now the path Windows opens (GetFinalPathNameByHandle), junctions followed, and filepath.EvalSymlinks elsewhere. cliupdate's howInstalled and installedVersion and proc.Version use it. TestCodexInstallPs1Junctions (Windows) builds install.ps1's layout with mklink /J, two releases whose codex.exe have the same bytes and mtime. It checks that codex is recognized as self-updated (codex update) and that retargeting current makes the version asked again. On the Windows box (10.0.0.132, sandboxed USERPROFILE/APPDATA/LOCALAPPDATA) it fails on the old code (howInstalled nil; "0.161.0" after the update) and passes on the new. The rest of the agent package fails on Windows with the same 17 tests before and after (TestFolderVarsAreListed, TestAside*, TestVSCodium, ...), which CI never runs there. `codex update` on Windows is in codex.exe 0.162.0 (win32-x64): it runs install.ps1. The layout was read from https://chatgpt.com/codex/install.ps1. Not tried with a real install.ps1 install (it rewrites the user's PATH in the registry). go test -tags nogui ./internal/agent ./internal/proc ./internal/provider ./internal/library (macOS), gofmt, and go vet for GOOS=linux and windows pass. |
||
|
|
ae24bcfcfb |
agent, gui: Codex's row on the Agents page shows its desktop app's version beside its CLI's ("CLI 0.130.0", "App 26.930.31730"), and the app's alone where no CLI is on PATH (#1334, laacmilan)
The app's version is read from /Applications or ~/Applications
ChatGPT.app (or Codex.app) Contents/Info.plist, taken only when its bundle
id is com.openai.codex, so the ChatGPT chat app (com.openai.chat) isn't
taken for it. macOS only: the Windows Store package isn't read yet. The
app chip's tooltip says it reads the same settings as the CLI, so
connecting Codex connects both. At narrow widths the chip ellipsizes, and
below 250px it gives way so the name keeps its room.
Verified: TestCodexAppVersion fails without the CLI() change ("the app
alone, no CLI"); agent-app-version.test.cjs fails 12/16 without the app.js
change and passes 16/16 with it, Chromium and WebKit, en/zh/ja/de, at 980,
560 and 440px. agent-cli-missing, agent-connect, agent-field-names,
agent-layout, agent-update-all, cli-update, click-scroll, gui-ja, gui-de,
i18n-keys pass in both engines. internal/agent passes in Linux Docker
(non-root); full ./... on macOS; vet darwin/linux/windows. Read
26.930.51102 from the real /Applications/ChatGPT.app on this Mac. Not
tried on the reporter's machine.
|
||
|
|
a711f428ad |
agent: CodeBuddy Code (Tencent's CLI, codebuddy/cbc, the China edition too) is an agent that uses magpie's models (#980, yujianbinm) — the CLI (npm @tencent-ai/codebuddy-code 2.161.4, one package for codebuddy.ai and codebuddy.cn, CODEBUDDY_INTERNET_ENVIRONMENT=internal) takes models of one's own from ~/.codebuddy/models.json ($CODEBUDDY_CONFIG_DIR), the format WorkBuddy reads, hot-reloaded, and starts a session on settings.json's "model". magpie now writes its models there as WorkBuddy's are written (vendor magpie, key magpie-codebuddy, url the gateway's /v1/chat/completions), keeping the user's own entries, their order, a model turned off and availableModels (magpie's ids added when the list is there), and sets "model" to the pick, the user's other settings kept; one of CodeBuddy's own models, or default, takes magpie's models out again. A new models.json is {"models":[…]} as CodeBuddy's docs give it. workbuddyWrite becomes buddyWrite(agent), the same writer for both. CODEBUDDY_CONFIG_DIR joins agentenv.Vars; cliupdate knows the npm package. TestCodeBuddyCode (user's model, availableModels and settings kept; magpie pick; sync; back to own; default) and TestCodeBuddyCodeNewFile fail without the agent ("no codebuddy agent") and pass; -race -count=5 on the CodeBuddy/WorkBuddy tests. End to end, the real CLI 2.161.4 under a temp HOME with CODEBUDDY_INTERNET_ENVIRONMENT=internal and no CodeBuddy sign-in: magpie codebuddy magpie/mock/pro against a sandbox gateway on 3462, then codebuddy -p with no --model, answered through the gateway from a mock upstream, and magpie's usage counted it under CodeBuddy Code (the CLI sends "CLI/2.161.4 CodeBuddy/2.161.4", so it is told by its key); magpie codebuddy default took it out. A bare-list models.json is read by the CLI too. Not tried with a real CodeBuddy account or a real model vendor. go test ./internal/agent/ ./internal/agentenv/ ./internal/usage/ ., go vet, darwin, linux (nogui) and windows builds pass.
|
||
|
|
4183f516bf | agent, provider: a CLI whose --version fails isn't run again until it changes, and an npm CLI's version is read from its package (#864) — macOS put up 「已阻止恶意软件:未打开 "codex"」 each time magpie's window opened: the codex magpie finds was asked its version every ten minutes (the model list's client version) and again with the Agents page (a failure retried after ten minutes), and macOS stops a program XProtect flags with that alert on every start. proc.Version is the one way both ask now: an npm CLI (…/node_modules/@openai/codex/bin/codex.js) has its package.json's version read and isn't run at all; any other is run with --version, and a run that ran and said nothing, or couldn't start, isn't made again until the binary's path, size or mtime changes (a reinstall); one cut off by the timeout is. A CLI that answered is asked as before. TestCodexVersionNotRerun (a codex that exits 137 run once over three ten-minute refreshes; an npm codex's version read, not run) fails on the old code (run 3 times); TestVersionRunsOnce. TestUpdateCLI and the agent and provider tests pass. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass but for TestClientGoneRecordedAsCanceled, which passes alone (-count=3). | ||
|
|
5268a3308e | 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. | ||
|
|
c530fce7ae |
agent: AtomCode follow-ups from the #736 review (#758)
* agent: AtomCode follow-ups from the #736 review — the account's provider is openai-compatible, the documented preset for a custom endpoint (requests verified flowing with base_url/api_key set on 5.2.1); the bare models.magpie/ prefix is gone, a bare key cannot hold a slash so it matched nothing; an effort set while the model table is gone is refused instead of writing a fresh table of nothing but reasoning_effort (Drift already says the table is gone); and the CLI-update comment carries the installer's Windows path (.local\bin\atomcode.exe) for when a self-updater returns. TestAtomcodeEffortWithoutModelTableIsRefused fails on the previous head (the orphan table was written); TestAtomcodeWiring wants provider = "openai-compatible". * agent: clearing AtomCode's effort on a gone model table is a no-op, not an error — the missing-table check ran before the clear, so what writes nothing was refused with the pick-again message; only setting an effort needs the table (a fresh one of nothing but reasoning_effort would be an orphan). TestAtomcodeEffortWithoutModelTableIsRefused also clears while the table is gone and wants the config byte for byte. --------- Co-authored-by: googya <118465+googya@users.noreply.github.com> |
||
|
|
8031edc78b |
agent: AtomCode support — one provider account, one model table per catalog model, as its own sign-in writes (#736)
* agent: AtomCode is wired like its own CodingPlan sign-in — one provider account, one model table per catalog model
AtomCode (atomgit.com/atomgit_atomcode/atomcode, AtomGit's open Rust terminal agent) keeps its settings in ~/.atomcode/config.toml ($ATOMCODE_HOME). Its account schema, what its own CodingPlan sign-in writes, is one [provider_accounts."magpie"] table at the gateway's /v1 (protocol openai, gateway.TokenFor("atomcode") as the key, so a request is its agent's even when the UA is overridden) and one [models."magpie/<provider>/<model>"] table per catalog model: the model string goes to the gateway as it is to resolve, with the model's context window (AtomCode compacts as it nears it; a 128000 one is told when the model's isn't known, and an output above the told window is cut to it), its output limit, vision and reasoning_effort_levels; reasoning_effort rides on the table once the user picks one. Picking a model points default_provider and default_model at it — default_model wins when both are set, as atomcode reads it — and stashes the defaults the user had; stepping out puts them back. The picker offers the user's own model tables and the catalog via magpie; the Library gives AtomCode its ATOMCODE.md, its mcp.json (omp's shape) and skills/; its UA is atomcode/<version>.
Found against a real atomcode 5.2.1: the documented legacy [providers.*] tables work, but its own sign-in writes the account schema, so magpie writes that; reasoning_effort, max_tokens and supports_vision were verified to reach the request from the model table, and default_model to win over default_provider. Verified end to end on a real install: atomcode --provider "magpie/…" answered through the gateway, and the Agents page shows the tile, its picker and the Usage attribution. TestAtomcodeWiring, TestAtomcodeRestoresOwnDefaults and TestAtomcodeSync fail on the old code; TestDriftUnwiredEveryAgent and TestUnsetAgentsReadEmpty cover it from All(). go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./internal/agent ./internal/library ./internal/agentenv pass; the plugin-host and timing failures of the full ./... run fail on main without this change too.
* tweak
* agent: AtomCode's config is matched by its own spellings, and Sync keeps the effort — AtomCode rewrites its config through serde on every /model and /cd, and that writes the account header bare ([provider_accounts.magpie]) where magpie wrote it quoted, so after the first rewrite Check read the wiring as gone, Sync and every pick appended a second account table (edited TOML is invalid: table magpie already exists) and clearing left the unquoted table and its api_key behind. The account is now matched by exact name in its three spellings (quoted, bare, literal — magpie-2 stays out) and the model tables by their decoded keys (kimiModelKey, replacing atomcodeModelName), through a new SetTOMLTablesMatching that takes exact names beside prefixes; SetTOMLTables delegates with none, unchanged. Sync carries each magpie model table's reasoning_effort over when rewriting — it ran at every gateway start and catalog change and dropped both an effort picked in magpie and one picked with AtomCode's /effort, and picking another model cleared every table's. The effort Set validates against the levels AtomCode knows (low, medium, high, xhigh, max — its clamp_effort_to_levels drops none, minimal and ultra), a model without levels offers none now, and the low/medium/high fallback is gone with it. supports_vision is written explicitly false, where AtomCode otherwise guesses from the model name. The user's legacy [providers.*] entries join the picker, a stashed default_model naming one comes back on Disconnect, and picking one sets default_provider and takes default_model out, as the legacy shape reads. site docs (en, zh, ja) list AtomCode. TestAtomcodeSync rewrites the config into the bare and single-quoted spellings before Sync and again before clearing and fails on the old code (drift reported, effort dropped, unquoted table left behind); TestAtomcodeLegacyProvidersArePickableAndRestored and TestAtomcodeEffortLevelsMatchAgentSupport are new. Reported by yetone on #736. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./internal/agent ./internal/edit pass.
* agent: TestAtomcodeWiring picks an effort through the field too — the write side of the validation the last commit added (a level AtomCode knows lands as reasoning_effort on the model table, one it does not know is refused) had no coverage left: the test only read back what AtomCode's own /effort had written. provider.SetModelEfforts gives fake/m1 levels to offer.
* agent: Disconnect puts AtomCode's default_provider back only where AtomCode still has it — the restore checked the stash's value was not magpie's but not that the table it names was still there, so a table the user had deleted in between came back as a dangling default (the account schema's default_provider names a model table, the legacy shape a [providers.*] one; own answers for both). The default_model branch checked already. TestAtomcodeRestoresOwnDefaults deletes the stashed provider's model table before clearing and fails on the old code.
* agent: AtomCode joins the CLI updates — npm @atomgit.com/atomcode, the brew cask atomcode, and the curl script's ~/.local/bin/atomcode updating itself with atomcode upgrade, so the Agents page shows its version and a newer one as the other agents' do (#736). TestHowInstalled covers the npm prefix, the cask and the self-updating installer.
* agent: AtomCode's self-updater waits for its install paths to be confirmed — the branch recognized a binary under ~/.local/bin as `atomcode upgrade`, on a docs page, while the README shows another path and the command has not been driven outside the help text; the reviewer asked for it removed until the standalone command and the script's real default are settled. npm and the brew cask stay, with their tests; a comment marks what is pending.
---------
Co-authored-by: googya <118465+googya@users.noreply.github.com>
|
||
|
|
cb82822f3d | source: add opt-in China mirror fallback (#566) | ||
|
|
ec4ee5a3a4 |
fix(proc): end what a CLI probe started, on its timeout and when magpie exits (#414)
* fix(proc): end what a CLI probe started, on its timeout and when magpie exits The probes that ask an agent's CLI something (claude auth status, cursor-agent about/models/status, the --version checks) ran through proc.CommandContext, which on its timeout kills only the command itself. A CLI that is a script (a version manager's wrapper, a shim) left what it had started running, adopted by init; and a probe still asking when magpie exited (a one-shot command, an update, a restart) was left whole, with nothing to end it. With Omarchy's mise wrappers stuck in their exec loop (omacom/omarchy#7234) that was five processes holding about half a core each for up to six hours. proc.ProbeContext gives such a probe a session of its own on Unix, as StartTree does, and its context ending kills the whole group. Probes still running are listed, and proc.EndProbes kills them when magpie exits (after run in main) or puts a new version in its place (update.Reexec). On Windows a probe is killed alone, as before, a job being joined only once the command has started. TestProbeTimeoutEndsWhatItStarted and TestEndProbes fail without the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(proc): end probes on a terminal's signals and on a Mac's quit Review of the first change: a probe leading its own session no longer gets the Ctrl+C, hang-up or SIGTERM sent to magpie's terminal or service, and magpie ending on the signal never reached EndProbes, so the probe was left to init where before it died with magpie. main now catches SIGINT, SIGTERM and SIGHUP, ends the probes and exits as the signal would have (128+n). A signal magpie was started ignoring (nohup, a background job) stays ignored. The account sign-in and plugin commands, which end themselves on Ctrl+C, go through interruptContext and are left to do so. On a Mac the desktop app's quit ([NSApp terminate:], also the restart to update) exits without returning to main, so OnShutdown ends the probes. TestProbeTimeoutEndsWhatItStarted ended its probe on a 500ms timeout, which on a Mac could come before the script had written its child's pid (6 of 10 runs failed in review). It now ends the context once that pid is read, the same Cancel path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: let the app and the TUI quit on a signal their own way Review of the signal handling: endProbesOnSignal exited ahead of Wails and bubbletea, which quit on SIGINT and SIGTERM themselves. `magpie tray` exited 143 without OnShutdown (no downloaded update installed, and sessions.Saved skipped in main), and `magpie tui` left the terminal on its alternate screen with the cursor hidden. The app's and the TUI's entry points now hand the signals back (ownSignals): the app's OnShutdown ends the probes, and the TUI comes back to main, which ends them too. A one-shot command keeps the handler. TestOwnSignalsHandsThemBack fails without the change (magpie exited 143 before the command could quit its own way); TestSignalExits keeps the one-shot behavior. childPid waited 3s for a script just written to start its child, which a busy Mac can exceed (2 of 3 full runs failed in review). It waits 30s now and, should the probe end first, says the probe's error rather than "the script started nothing". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep SIGHUP for the app and the TUI, and die of the signal ownSignals handed SIGHUP back along with SIGINT and SIGTERM, but neither Wails nor bubbletea handles it: the terminal closing under the TUI or an app started from a shell ended magpie on the spot, and its probes, in a session of their own, out of the hang-up's reach, kept running (before this PR they were in the terminal's group and ended with it). SIGHUP now stays with endProbesOnSignal. A tray under a pty whose terminal closes left 2 processes before, none now. The handler asked whether a command was ending itself on Ctrl+C only after EndProbes, which can take up to a second; a sign-in done in the meantime got magpie ended in the middle of its own cleanup. It is asked first. It exited 128+n, which a shell takes for a child that handled the signal: a loop running magpie went on to the next run on Ctrl+C. It now dies of the signal (handling reset, the signal sent again); Windows, which can't send one, still exits with the code. agentProbe and agentCommand share withProxy; the Windows probeGroup comment no longer says EndProbes ends what a shim started. TestOwnSignalsKeepsHangUp and TestInterruptWhileEndingProbes fail without the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: hand signals to the TUI and the app only once they listen Review: runTUI handed SIGINT and SIGTERM back before tui.Run, whose newModel asks agents' CLIs (claude auth status, up to 5s) before bubbletea listens for signals. Ctrl+C, SIGTERM or SIGINT while it loaded ended magpie by Go's default and left the probe and its child running. tui.Run now takes ready, called once the model is made, and runTUI passes ownSignals. The app had the same window: runGUI handed them back before gui.Run, which starts the backend (probes included) before Wails' Run starts listening. ownSignals is now gui.Started, called on ApplicationStarted, which Wails emits after its signal handler is set up. A tray sent SIGTERM 0.05s after starting, a probe under way, left 2 processes before and none now; one sent it once started still quits through OnShutdown (exit 0). TestTUIKeepsSignalsWhileLoading fails without the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
04f374fa8c |
agent: OmO (oh-my-openagent, omo-ai), a fork of Pi that keeps its own ~/.omo/agent, gets its own row: a magpie model sets settings.json's defaultProvider/defaultModel and magpie's provider in models.json there as Pi's does, $OMO_CODING_AGENT_DIR / $SENPI_CODING_AGENT_DIR are honoured, the Library writes its AGENTS.md, mcp.json and skills, and omo update updates it (#264 rhyme227). Pi's own ~/.pi is left alone. piIn becomes piLike(at, id, name, dir) so both share one wiring. Tested with omo_test.go in agent and library (fail without the change); go vet, go build -tags nogui (darwin, GOOS=linux, GOOS=windows), go test -tags nogui ./... pass.
|
||
|
|
be4298b294 | library: Pi 0.99's own MCP — with Pi 0.99 or later on PATH and no MCP extension replacing it, MCP servers go in the mcp.json Pi reads itself, in its shape (command/args/env, url/headers, no adapter transport keys; SSE refused, which it has none of) (Discord feedback, 何似在人间: Pi now has native MCP) — Pi 0.99 (extensions/mcp/config.ts) reads mcpServers from <agent dir>/mcp.json, unless pi-mcp-adapter or pi-mcp-extension is installed (now also found in Pi's extensions folder) or settings.json has -builtin:mcp; then the files are as before. Servers magpie or the user had in mcp-adapter.json, which nothing reads now, are moved into mcp.json, the adapter's settings and anything mcp.json has differently left where they are and still found, both files backed up and written together (edit.Atomically). Without an adapter found, mcp.json is no longer moved to mcp-adapter.json, since it may be Pi's own. agent.InstalledVersion asks the CLI on PATH, once per binary. Tested with TestPiMCPNative in a sandbox HOME with a fake pi on PATH: 0.98 writes mcp-adapter.json, 0.99 moves the servers over with the user's fields kept, writes and removes in Pi's shape, SSE refused, the adapter (listed or in extensions) or -builtin:mcp keeps the old file; TestPiNativeVersions, TestInstalledVersion. go vet ./internal/..., go build -tags nogui (and GOOS=linux, GOOS=windows) and go test -tags nogui ./... pass. Not tried with a real Pi 0.99. | ||
|
|
fe2269288c |
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
|