Commit Graph
6 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 56d1665251 library: a skill an agent has of its own is removed from every agent that has it, from its row under "In your agents" (trash) or with d twice in the TUI, without bringing it into the library first (#1303, sxwedo)
Until now the only action on such a row was Bring in: removing it meant
bringing it in and then removing it from the library. RemoveFoundSkill
(skills/remove-found) takes out of each agent that has it its folder, or
its copy of the very same files, and its links; its entry in the shared
~/.agents/skills, which agents read too, and a folder of it in the
library's own folder go as well. Nothing is deleted: folders go to the
backups (setAside), links are taken away, and a folder elsewhere that the
agents only linked to stays where it is. Another skill by that name
(Others) is a different skill and stays. The page asks first and says
which agents it leaves and what stays.

TestRemoveFoundSkill (library), TestLibraryPage's new part (TUI) and
remove-found-skill.test.cjs (GUI) fail without the change. The GUI test
fails 4 of 4 with library.js from before it, and passes in Chromium and
WebKit, in en, zh, ja and de, and at 440px wide.

Run: go test -tags nogui ./internal/library ./internal/tui ./internal/gui,
and go vet for linux, windows and darwin with -tags nogui, in Docker
(golang:1.26.8, a temporary HOME). The Mac's syspolicyd held test binaries
at launch. On the Mac, in Chromium and WebKit: remove-found-skill, gui-ja,
gui-de, i18n-keys, import-all-skills, own-skill, shared-skills,
library-own-folder, library-items, remove-all-skills,
library-desktop-skills, skill-name-many-agents and mobile-web, 133 of 133.
In one earlier run of that set at load ~40, mobile-web's WebKit "idle
scripts cannot scroll" failed once. It passed 3 of 3 alone with this
change, and passed in the full rerun. Not tried: the reporter's own agents,
and a WSL agent's folder.
2026-10-08 20:00:49 +08:00
yetone 9dc0121f90 library: installing a set of skills skips the ones in the way and installs the rest; the toast names the ones already in the library and the ones skipped (lc on Discord: 安装skills的时候,没有跳过已经安装的)
installFrom stopped the whole set at the first skill whose name was taken,
and returned before change saved library.json. The folders it had already
copied for the skills before that one stayed in the library's folder,
unlisted. Every later try then failed on the first of them with "the
library's folder already has a caveman-commit in it".

Now each skill is installed on its own (InstallSkills, InstallMarketSkill
and AddNewSkills, through installChange):
- the library lists it from the same source: had already (Result.Had),
  nothing written, so the user's edits stay;
- a folder in the library's folder holding exactly its files (not a link,
  sameTree, which counts a failed read as different): listed where it is,
  as had;
- another skill by that name, listed or only a folder, or a folder that
  can't be read: left as it is, in Result.Skipped with why;
- the rest are installed (Result.Installed). Only when nothing was
  installed or had does the change fail, with the first reason.
The GUI's toast and the TUI's line say how many were installed, the ones
already in the library and each one skipped with why.

Verified (temp HOME, pinned caches):
- go vet -tags nogui ./internal/library ./internal/tui ./internal/gui .;
  GOOS=windows go build and GOOS=linux go build -tags nogui of
  internal/library and internal/tui: clean
- go test -tags nogui ./internal/library ./internal/tui ./internal/gui: ok
- with the old skills.go, market.go and skillnew.go, TestInstallSetSkipsOneInTheWay,
  TestInstallListsItsOwnLeftoverFolder (fails with lc's exact "the library's
  folder already has a caveman-commit in it") and
  TestInstallSetSkipsAnotherByTheSameName FAIL; TestSkillsFromGitHub's
  reinstall now asserts Had
- skill-install-skip.test.cjs (Chromium + WebKit, en and zh at 440px) fails
  on the old library.js ("status ok", no names) and passes now; with
  gui-ja, gui-de and 11 library GUI files, 99/100 passed, and the one that
  failed (by-agent, Chromium, at load average ~150) passes 3 times in a row
  in both engines when run alone
- not tried in the real app, or with lc's library
2026-10-08 04:57:40 +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 0f0b8fc87e gateway: Codex on one of its own models moves on to the next ChatGPT account when the one it is signed in to has used its allowance up — with more of Codex's accounts on in magpie, Codex's requests go through magpie even for its own models (openai_base_url kept, and put back or taken out as accounts are switched on or off) and are served as the codex subscription's, which fails over as its other models do; the account out of allowance rests until ChatGPT says it resets (resets_at), up to an hour at a time. Asked on Discord 2026-09-26 21:11:42 +08:00
yetone 87fb06d2f9 tui: a library page (5) — the shared instructions, MCP servers and skills magpie gives the agents, and RTK: ↵ lists the agents that can have one, each switched on or off in place; e edits the instructions in $EDITOR; the servers and skills found in the agents are listed too, i brings one into the library; d twice takes one out. The same data as the app's Library. Asked on Discord 2026-09-26 19:40:58 +08:00