16 Commits
Author SHA1 Message Date
yetone c4476d5658 library: skills from GitHub are checked as the skills page opens, and one changed here is marked and asked about before an update replaces it (#1449)
YangZhiqiang98 asked (#1449) that the Library find which skills have
updates and update them. magpie already checked skills from GitHub (a
market install among them) by hand and could update them, but an update
deleted the library's folder, so a skill the user had changed (by hand,
through an agent's link, or in an agent's copy not yet taken in) was lost
without a word, and nothing checked unless the user pressed Check.

- A skill is "changed here" when its library folder no longer hashes to
  what was fetched (Finder's .DS_Store aside), or an agent's copy was
  edited since its mark and not yet taken in (editState, skill_changed.go).
  The view says so (SkillView.edited) and the row shows "Changed here".
- UpdateSkill refuses such a skill with *EditedError unless told to
  replace it. The row's Update asks in the page first (Keep mine / Update;
  Update sends replace). Update N, the group's Update N and the CLI's
  update-all leave it as it is and say so. The CLI takes
  `magpie library skill update <name> --replace-edits`.
- The version an update replaces is moved to the backups when it was
  changed, or when it can't be told (a skill with no hash from before).
- View.checkDue: no check since magpie started, or none for 12 hours. The
  page then runs the check once by itself as the skills open, and says
  only what there is to update or add.

Not checked, by design: skills the skills CLI manages (`npx skills
update` updates them; magpie only groups them), linked local folders,
skills imported from an agent with no source, and From-only skills have
no remote; CC Switch-installed skills can still be updated by hand.

Verified:
- go test -tags nogui ./... (sandbox HOME); new TestUpdateKeepsASkillChangedHere,
  TestUpdateKeepsACopyEditedInAnAgent, TestUpdateKeepsWhatItCantTell,
  TestCheckDue, TestCheckSkillsMarksItDone, all from httptest. With
  editState forced to "not changed" the first three fail.
- gofmt -l, go vet, GOOS=linux and GOOS=windows go vet -tags nogui on
  ./internal/library ./internal/gui ./internal/tui .
- GUI: new skill-update-edited.test.cjs (Chromium and WebKit, 860 and
  400px, en and zh; no scroll on click; fails with the row's ask removed),
  plus the 22 other library skill tests, gui-ja, gui-de, gui-zh-tw,
  i18n-keys and click-scroll: 262 pass.
- Real use in a sandbox HOME with github.com/anthropics/skills: installed
  pdf and docx, the real check said both current; an edit through Claude
  Code's link was refused by `skill update pdf`, skipped by `skill update`
  (docx updated), replaced by `--replace-edits` with the edit in
  backups/<time>/library/skills/pdf; docx edited later shows edited, a
  .DS_Store doesn't.
2026-10-10 09:14:35 +08:00
yetone aad799eae6 library: an RTK release winget or Homebrew doesn't have yet says "v0.51.0 is out · waiting for winget" with no Upgrade, until it does (#1025, Fermin214)
On Windows, RTK installed by winget was 0.50.0 and GitHub had 0.51.0, which winget didn't yet. Library → RTK showed "v0.51.0 可升级" with Upgrade; Upgrade ran winget upgrade, which rightly said "winget's RTK is 0.50.0 so far…", and the card went back to "可升级" with Upgrade. The card compared rtk's version only with GitHub's latest release, never with what the package manager that installed it has, and the upgrade's answer was forgotten as soon as the card was read again.

RTKView.CheckLatest now also asks, when the latest release is newer than this rtk and it was installed by winget or Homebrew, what that package manager has: winget show --id rtk-ai.rtk --exact (the version is the first one after the line naming the package, as winget's labels are in the system's language), and brew info --json=v2 rtk without auto-update, as the Agents page's CLI updates read Homebrew. An upgrade through either records the version it left as the newest that package manager has. The answer is kept six hours (a failure fifteen minutes) and is asked again after that. When it has nothing newer than this rtk, the view says waiting (winget or Homebrew) and waitingHas. The card then shows "v{v} is out · waiting for {via}" (zh "v{v} 已发布 · 等待 {via}", ja, de), with a tooltip saying what it has, and no Upgrade button. Once it has the release, Upgrade is back. A package manager that can't be asked, or doesn't say, leaves Upgrade offered as before. GET /api/library/rtk runs the whole check within its 3s budget. magpie library rtk prints the same. Cargo (built from rtk's repository) and rtk's own script (its GitHub releases) can't lag, so they are unchanged. The Agents page's CLI updates already compare with the installing channel's own latest (Homebrew's or npm's), so they don't have this bug. The Japanese "v{v} is out" is shortened to "v{v} 公開済み", because with Upgrade beside it the card head overflowed at 440px.

TestRTKWaitsForWinget (a fake winget whose show prints Chinese labels: unaskable leaves Upgrade; asked, it waits; the reporter's upgrade waits with the "so far" note, and so does the card read again; winget given 0.51.0 and asked again, Upgrade is back and works) and the extended TestRTKUpgradeBrew (Homebrew's 0.49.0 after brew upgrade waits, on the card read again too) fail without the change (waiting <nil>) and pass. TestRTKChannelVersion covers winget show in English, German and Chinese with spinner frames, no package, and brew info's JSON. -race -count=10 on them. library-rtk-upgrade.test.cjs's new test (Upgrade finds winget behind: the waiting tag, no button, the note; a reload still waits; winget has it: Upgrade back; card head and page fit at 440px) fails without the library.js change and passes on Chromium and WebKit in en, zh, ja and de. i18n-keys, gui-ja, gui-de and the library-rtk-* tests pass on both engines. go test -tags nogui ./internal/..., go vet, gofmt -l, darwin, linux (nogui) and windows builds pass. Not tried with a real winget or on Windows: winget show's output is taken from its documented format, and the version line is assumed to follow the package line in every language.
2026-10-06 20:56:52 +08:00
yetone 4c170cbad6 library, gui: DeepSeek Harness is listed under Library › RTK with why RTK has no hook for it, not left out (lc on Discord) — RTK rewrites the shell command an agent is about to run, and dsh's hooks can only allow or deny one (its Claude Code bridge drops updatedInput; deepseek-harness's pre-tool-input-rewrite is only proposed), and rtk 0.51's init has no --agent dsh (rtk-ai/rtk#3847; the open #3934 only adds AGENTS.md text, which rewrites nothing). So the RTK tab left dsh out and it read as magpie not seeing it. rtkNoHook names it with the reason: the row has a No RTK hook tag (zh/ja/de) and a switch that can't be turned on, magpie library rtk prints the reason, and on/off for dsh answer it instead of "rtk has no hook for dsh". TestRTKNoHookListed and library-rtk-nohook.test.cjs (Chromium, WebKit, en/zh) are new and fail without the change. go vet, go build (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui ./... under a temp HOME pass (TestProvidersAnswerWhileListsComeIn and TestUserPath failed once under the full run's load and pass on their own). 2026-10-06 02:24:53 +08:00
yetone 3c7ceb68f4 library, gui, cli: skills can be given to the agents as copies rather than links, for every agent or one (#896, ADabbler) — the Library linked each skill into the agents (a copy only where it couldn't link: Windows without the right to make links, WSL, Claude Desktop), and some want each agent to have a folder of its own. Skills › under the list, "Give skills as: Links | Copies" sets the library's way (library.json copySkills), and By agent gives an agent its own way (skillHow: Library's way / Links / Copies; Claude Desktop and WSL only ever take copies and have no switch). A copy is the whole skill folder with the .magpie-library marker, made by the same swap as before (.name.magpie-next, the old one set aside), so it is known for magpie's: taking a skill away removes magpie's copy and never a folder of the user's by that name. Switching makes each enabled skill again in place: a link becomes a copy; a copy becomes a link (made beside it and swapped in; a copy edited by hand is kept with the backups first). Where a link can't be made (Windows without the right) it stays a copy, as before. A copy follows the library's skill on every sync (at start, and after any change in the Library) as before; one that differs now (the library's folder edited by hand) is marked "Copy out of date" on the skill, saying in which agents, and a click copies it again. CLI: magpie library skill how link|copy [agent], magpie library skill how default <agent>. en/zh/ja/de. TestSkillHow (temp HOME: links at first, bad ways refused, copies marked, Read's how and copySkills, behind after a hand edit and cleared by a sync, codex its own way, an edited copy kept in the backups, back to the library's way, the user's own same-name folder and own skill untouched both ways, a copy removed with its skill) fails without the change; TestSkillCopyFollowsTheLibrary and TestSkillCopySwapSurvivesAnUndeletableFile now ask for copies rather than leave a copy where links are given, which is made a link again now. skill-how.test.cjs (WebKit, en and zh: the bar, Links/Copies posted with the note and status, the out-of-date tag with its agents and a click syncing without opening the skill, By agent's sheet with Claude Desktop's copies-only row and no switch, an agent's way posted and back to the library's, By agent (1), no select, no scroll, no left border) fails without it. Every Library and skill GUI test and click-scroll 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:46:55 +08:00
yetone 680ca5508f library: RTK's savings are read from rtk gain's stdout alone, a count rtk couldn't give says why instead of "Nothing saved yet", and the page says whose commands the count is (#741 part 2, on Windows with magpie 0.1.807, RTK 0.51.0 and Codex: the RTK card said 还没有节省记录 while rtk gain in a terminal listed savings) — ReadRTK ran rtk gain --daily --format json with CombinedOutput and json.Unmarshal'd the lot, and took any error, from rtk or from the JSON, for nothing saved. rtk writes warnings to stderr with the JSON on stdout — on Windows the console code page it has no decoder for (warn_unmapped_codepage), a command it couldn't resolve, a history table it found damaged — and any of them in front of the "{" made the output unreadable, so the card said nothing was saved however much was. rtkGain now runs it with stdout and stderr apart (stdin closed, 30s at most), parses stdout from its first "{" to its last "}" (a notice printed ahead of it is passed over), and when rtk fails or prints no summary it can read, gainErr says so with what rtk said ("rtk gain: <last lines>", "rtk gain printed no summary magpie can read: …"), shown on the card as "magpie couldn't read what RTK saved: <why>" and by magpie library as "what rtk saved isn't known". magpie counts no agent itself: the figure is rtk gain's, global, every command any agent or terminal ran through RTK on this computer, and the card now says that after it, so an empty one isn't read as magpie counting only some agents. On Windows, Codex with its Windows sandbox on (config.toml's [windows] sandbox = "elevated"/"unelevated", or the older elevated_windows_sandbox / experimental_windows_sandbox features, and not danger-full-access) runs its commands as its CodexSandbox account, whose own %LOCALAPPDATA%\rtk\history.db keeps what RTK saved there, or with a restricted token that can't write the user's — either way not in the rtk gain the user runs; ReadRTK reports that as codexSandbox, and the card (and magpie library) says why what Codex saves isn't counted. The count is read again each time the RTK tab is opened, so commands run since show without restarting magpie. TestRTKGainRead uses a fake rtk: a code-page warning on stderr with JSON on stdout (read — the old CombinedOutput code says nothing saved), a notice line before the JSON, zero commands, an rtk that exits 1, and one that prints no JSON, with the exact gainErr; TestCodexSandbox covers each config form. library-rtk-gain.test.cjs (webkit) checks the reason and the scope line, the Codex sandbox note, and that reopening the tab re-reads the count, in English and Chinese. go vet, builds (darwin, GOOS=linux -tags nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass, as do the Library and click-scroll GUI tests. Not tried on the reporter's machine: which stderr line broke it there isn't known (the card now shows it if it's still there), and the Codex sandbox account's separate history is from Codex's and RTK's source, not seen on a real Windows Codex. 2026-10-04 12:15:40 +08:00
yetone 9848a9062a library: RTK says when rtk isn't on the PATH the agents get, and puts it there when asked (#601, Moody-Sin: magpie好像没有正确安装RTK — Pi said "RTK disabled: rtk binary not found in PATH" while the Library showed RTK working) — rtk's hooks run it by name (Pi's extension probes rtk --version and turns itself off when that fails; Claude Code's and Codex's are rtk hook …; the commands they rewrite to are rtk git status and so on), but magpie looked for rtk in more places than an agent's PATH: ~/.local/bin and ~/.cargo/bin, which the app adds to its own PATH whether the user's shell has them or not (rtk's own install.sh puts it in ~/.local/bin and only warns when that isn't on PATH), and WinGet\Links on Windows, which winget doesn't always link into. So rtk was "installed", the agents were switched on with it by its whole path, and none of them could run it. Now the PATH a terminal opened now has is read — the login shell's (proc.LoginPath, the one UserPath already asks for, kept a minute) or on Windows the registry's (moved from provider's registryPath) — and when rtk isn't in it the RTK card says so, with what Put RTK on PATH will do, and each agent that has rtk is tagged Not on PATH (不在 PATH 中). Put RTK on PATH (magpie library rtk path) links rtk into the first of ~/.local/bin, ~/bin, /opt/homebrew/bin, /usr/local/bin, linuxbrew's bin, ~/.cargo/bin that is on that PATH and writable, or on Windows adds rtk's own folder to the user's PATH in the registry (a link needs Developer Mode, and a copy is left behind when winget upgrades rtk; winget's package folder doesn't change across upgrades) and tells Explorer; with no such folder it says which folder to add to PATH in the shell profile — shell profiles are never edited. rtk is also found in winget's package folder (WinGet\Packages\rtk-ai.rtk_*), and rtk's script upgrades a linked rtk where the link points, not over the link. TestRTKOffPath and library-rtk-path.test.cjs (en, zh) fail without the change. go vet ./internal/..., go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build and vet, go test -tags nogui -count=1 ./... under a temp HOME pass but the known TestFXInState flake. The Windows registry path is built, not run on Windows. 2026-10-03 02:38:17 +08:00
yetoneandClaude Opus 5.5 03b4cadb1f library: Remove all beside Turn all on/off takes every skill out of the library at once (#449) — a library of many skills could only be emptied a row's Remove at a time. Remove all, in red, asks in the page first, naming the agents that lose the skills, the projects magpie placed them in, the folders that go to magpie's backups and those of the user's own that are only unlinked; Cancel sends nothing. Confirming sends every name in one call, library.RemoveSkills, which takes each as RemoveSkill does, the folders kept aside together under one backup; one that can't be taken out stays, and is said, while the rest go. magpie library skill rm --all does the same, asking y/N on a terminal and, with none, only with --yes. TestRemoveSkills and TestLibrarySkillRmAll fail without the change, as does remove-all-skills.test.cjs (Chromium and WebKit, English and Chinese); click-scroll, old-webkit, every-skill pass. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (bar the known Claude account flake TestClaudeSignedOut).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 00:47:15 +08:00
yetone 68f9daa4fa library: an agent's own copy of a library skill gives way to it, and one that differs is settled from the warning (StringKe, JasonLeeForOnly on Discord: after Bring in all, "Claude Code already has a skill of its own called impeccable", 这里没有强制覆盖的能力) — a skill is brought in from the agent with the very folder and given to the agents that had that folder; another agent's copy (CC Switch copies a skill into each agent) was listed as "differs in" and left out, and giving the skill to it, or a copy put back into an agent after its folder became magpie's link (by CC Switch or whatever installed it), was a hard failure with no way out. A folder there holding the same files as the library's (bytes compared; .DS_Store, .git and magpie's copy mark aside) is now set aside into backups/<when>/<agent>/skills and the library's linked in its place; a skill brought in takes the agents with such a copy too, which are no longer said to differ; a move that copied it all but couldn't remove the folder brings it in all the same, what was left set aside. One that differs keeps the warning, now in the reader's language with "Use the library's" (the agent's set aside, the library's linked) and "Keep <agent>'s" (the agent, and any reading the same folder, taken off the skill) on its row — skills/use-library and skills/keep-own, magpie library skill use-library|keep-own <name> <agent>, which the CLI suggests under the problem. Backups holding a skill set aside are never pruned. TestOwnSkillInTheWay, TestSameTree, TestPruneKeepsSkillsSetAside and own-skill.test.cjs (Chromium, WebKit, en/zh) fail without the change; TestSharedAgentsSkills now expects the byte copy to be the library's. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; own-skill, import-all-skills, library-items, shared-skills, market-have, click-scroll, old-webkit pass. 2026-09-30 19:42:43 +08:00
yetone 5b43bdd61c library: RTK's version is kept up to date from magpie, and what it saved is drawn day by day (这里要能够管理RTK的版本,比如给它升级,以及能够看到RTK省token的趋势) — the RTK card shows its latest release beside the installed one (read from where github.com/rtk-ai/rtk/releases/latest redirects, as RTK's install.sh does, the API as fallback; kept six hours) and, when newer, an Upgrade button that brings it up the way it was installed: brew upgrade rtk for Homebrew's (in a Cellar; Homebrew updated first), winget upgrade on Windows, cargo install --git again for cargo's, and RTK's own script again, into the same folder (RTK_INSTALL_DIR), for one it put elsewhere; when Homebrew's formula is still behind the release, that is said. Also magpie library rtk upgrade. Under the totals, a chart of what RTK saved each day (week by week past 92 days) over 30 days, 90 days or all it has recorded: each bar the commands' whole output, the part saved above what still went to the model, the range's own total beside it — from rtk gain --daily --format json (RTK 0.28 on), which carries the summary too. Tested with a fake Homebrew rtk behind its release and a fake script install, and against the real rtk 0.28.2 and its history in a sandbox magpie (GitHub says 0.50.0); the upgrade itself not run on this machine 2026-09-29 01:01:25 +08:00
yetone a90e9ae4e5 library: every skill from GitHub is updated with one click — the Library's skills page has Update all beside the skills in the library (and magpie library skill update with no name does it from the command line): each repository is fetched once however many of its skills there are, the agents are written once, and a skill that couldn't be fetched is said while the rest are updated all the same. Asked for on Discord 2026-09-27 04:21:14 +08:00
yetone 8630e4c62a tui: the routing page (3, was groups) does what the app's Routing view does — an open group lists its rules under its models, one list: n adds a rule typed as magpie group rule add takes it (use=<model> tokens=200k images effort=… agents=… intent="…" classifier=<model> at=<n>), ↵ types one again in place, J/K moves it, d twice removes it; c picks the classifier, s how long a conversation stays, x the context agents are told, R renames the group (the page follows it); a found group that was removed is listed last and u brings it back; smart routing is shown as smart, not in order, and o goes round all four. The library page adds too: a adds an MCP server (a URL, or a command) or skills from a GitHub repository or a folder, e changes a server (its env, headers and agents kept), u fetches a skill from GitHub again, s syncs the library into the agents. The rule parsing moves to provider (ParseRule, RuleWords, Rule.Line) and a typed server to library (ServerOf), for the CLI and the TUI alike. Asked on Discord 2026-09-26 23:08:58 +08:00
yetone 0218eeb5ca rtk: an agent left with the hook of an rtk that isn't installed (never was, or removed since) is shown with RTK missing — its shell commands fail — and can still be switched off: magpie takes out just what rtk's installer put in (the hook in settings.json / hooks.json, RTK.md and the @RTK.md line, Gemini's hook script, Copilot's instructions block, the OpenCode / Pi / OMP extension, Hermes' plugin) itself, needing no rtk, the files kept aside first; rtk's own uninstaller is no longer used, which deleted Gemini's GEMINI.md whole and took Claude Code, OpenCode and Cursor away together. Gemini is given rtk hook-only, so the user's GEMINI.md isn't written over. Install RTK on the page (and magpie library rtk install) installs rtk with Homebrew, winget on Windows, or rtk's own script into ~/.local/bin, only when clicked 2026-09-26 21:53:05 +08:00
yetone 631e4c3096 library: RTK (rtk-ai.app) can be switched on per agent — a Library tab lists the agents RTK has a hook for (Claude Code, Codex, Gemini CLI, OpenCode, Cursor, Copilot, Pi, OMP, Hermes), each with a switch that runs RTK's own installer (rtk init -g …) for it, keeping the files it edits aside first; which have it is read from their files, and the tab says RTK's version and the tokens it saved. RTK's installers for OpenCode and Cursor give it to Claude Code too, and its uninstaller for Claude Code or OpenCode takes all three: magpie keeps each switch to its own agent. magpie library rtk [on|off <agent>] does it from the CLI. Asked on X 2026-09-26 19:25:23 +08:00
yetone c0e6d985de library: ZCode gets the library — its instructions go to ~/.zcode/AGENTS.md, its skills to ~/.zcode/skills and its MCP servers to ~/.zcode/cli/config.json's mcp.servers, where ZCode's own MCP settings keep them (a server of the user's there, and the file's other keys, stay as they are). magpie library … agents no longer takes an agent it has no place in for that: an unknown one, or one without MCP (omp) or instructions (Cursor), is refused with why, instead of recorded and given nothing (asked on Discord) 2026-09-26 16:18:56 +08:00
yetone 0f9d60db07 library: the MCP servers an agent's app writes into its config itself (Codex's node_repl and cua_repl, run from inside its install) are told apart — not offered to bring in, shown as the agent's own and left as they are; magpie library lists what agents have that the library doesn't 2026-09-26 14:34:53 +08:00
yetone 530734ff46 library: magpie library from the command line, and the app writes the library into the agents when it starts — there was no library command (status, sync, instructions get/set/agents, mcp add/agents/rm, skill agents/rm now), and Sync ran only from the page's button, so an agent installed or a file edited since kept what it had until the Library page was visited 2026-09-26 01:38:37 +08:00