9 Commits
Author SHA1 Message Date
yetone 7712ef8e7c gateway: a routing group is served by its name too, so a client the user typed a renamed group's name into (ZCode) reaches it rather than 404 "magpie knows no model"; magpie group set <id> name=… says the id stays and what agents ask for (MOMO on Discord)
provider.GroupFor tries the group's id and the model's spellings first, as
before, then the one group whose name (by its slug) is the id asked. A
name two groups share names neither, and a model a provider serves by
that id stays the provider's.

Verified: TestGroupAskedByItsName fails on the old GroupFor with 404
"magpie knows no model \"DS Flash\""; TestGroupRenameSaysTheIDStays fails
without the message. internal/provider and internal/gateway pass in a
sandbox HOME.
2026-10-08 18:13:11 +08:00
wizzy-yangandwizzy-yang 6f391bc8f2 provider, agent, cli: a routing group's id carries Claude Code's [1m] mark (#1000)
wherever a ref is read back from an agent's settings

An agent on a routing group is shown, on the Providers page, on each of
that group's providers — the row's middle holds one button per agent, and
`uses` is what the Routing page's "n agents routed through it" counts.
A group whose model has a 1M window is written into Claude Code's
settings with the mark Claude Code itself puts on it
(`group/auto-deepseek-v4-1-flash[1m]`), and GroupFor takes the mark off
for the gateway; the rest did not. So the group was not found, and an
agent Claude Code had on it was listed on none of the group's providers,
while every request it made went through them.

Four places read such a ref back:

- provider.GroupFinder, which the Providers page asks (agentUses)
- agent.sameModel, which moves an agent whose group is gone to the same
  model from a provider still serving it — the mark left on made the
  comparison against AutoGroupOf find nothing, and the agent stayed on a
  group nobody serves
- agent.groupNamed, which says whether two values of a field reach the
  same group, one of them read back from the agent's own settings
- the CLI's groupUses, which lists "← agent" beside a group: the marked
  id was filed under one no group has, and Claude Code was on no row

Each takes the mark off, as GroupFor does. A group's own members are not
touched: those are the group's structure, never a ref from an agent's
settings, and a [1m] there is a model's, not the group's.

group_uses_test covers the page (a group found with and without the mark,
and the row naming the agent on the group's provider); applied_test covers
groupNamed; reseat_test covers the move (the marked group ref finds the
same model elsewhere, and a group that is nobody else's still gives
nothing); groups_cli_test covers the CLI, with Claude Code's settings.json
as the reporter's reads. Each fails without its fix. go build, go vet
pass; go test ./internal/agent/ passes, and the failures that remain are
the ones a clean origin/main has too (Aside's symlinks, ~/.codex
dependence, VSCode's launchers, a flaky Zed case).

Co-authored-by: wizzy-yang <wizzy-yang@users.noreply.github.com>
2026-10-06 16:02:03 +08:00
yetone 399e5db63d gui, groups: a group's editor sets the context agents are told — its largest model's, its smallest model's, or one typed (Mikan on Discord: 路由组可以支持自定义上下文长短或者支持用户选择按照上下文长度最短的供应商还是上下文长度最長的供应商吗?) — a group told agents its largest member's window (#712), and another could only be set from the CLI. The group editor now has a Context row under Slow to start: Largest model's (as before), Smallest model's, or Custom with a box (200k, 1m, 128000), its hint naming the window agents will be told from the members' own, redrawn as members are added or taken off; a length that isn't one says so and isn't saved. Smallest is kept as smallest (Context -1, ContextSmallest), worked out as the members change, so the agent compacts before any member would turn a conversation away; a conversation too long for one member still goes on to one with room. magpie group set <id> context=smallest|largest|272k does the same. zh, ja, de strings. TestContextSetByUser (smallest, then smallest after a member leaves) fails on the old code; TestApplyGroupPairs covers context=. group-context.test.cjs (WebKit, en and zh): Largest by default with no box, Smallest saves -1 and reopens so, Custom starts at the smallest member's, a bad length shows its error, 300k saves 300000 and reopens, Largest saves 0. group-first-token and group-patterns get a taller window, the editor having grown under the fixed footer; they, group-arrange, fold, member-off, member-fast, rate-limited-sink, routing-compact, manual, levels, steady, time, unlisted-models and settings-groups 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 03:00:34 +08:00
Snowyy a3704c422b tests: keep the suite out of a real DSH_HOME, as the other homes already are (#454)
DSH_HOME beats HOME in DshDir and in dsh's own dir, so a suite that sandboxes HOME still reads and writes the developer's ~/.dsh.
2026-10-02 00:42:23 +08:00
yetone 0361189f9e test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass. 2026-10-01 23:15:07 +08:00
yetone cdd1e8e7a4 group: a group's id can change — a group magpie found is group/auto-<model>, and agents could only pick it by that; now its id (any group's) is changed in the editor or with magpie group set auto-gpt-6-astra id=gpt-6-astra: the found one stays removed under the old id, the groups that have it in them and their rules follow, and an agent set to the old id is told it needs setting again (#83). magpie groups no longer says a group in a group is not served 2026-09-26 14:14:26 +08:00
yetone d4135b55e1 group: a routing group's models can be another group — group/<id> as a member, routed in its place by its own routing and rules, so Coder can be deepseek-v4-pro then Fast, a Coder rule can send a turn to group/fast and Fast's own rules pick within it; a group can't be in itself directly or through another (refused on save, left out of the picker), groups go at most 8 deep, and one can't be removed while another has it. The Routing tab shows a group in a group as a heading with its models under it, the packet going through it, and the log says what each group's rules and classifier decided 2026-09-26 13:41:17 +08:00
yetone 925e4a6ccd provider: a provider can serve only through routing groups — ticked, its models leave the list agents pick from (and /v1/models) while the groups they are in, and a request naming provider/model, still reach them (magpie provider listed <id> no); the routing groups come first in the list; a model list fetched from the vendor can be forgotten; magpie group add under a name in use replaces that group; and the Library gives MCP servers to Claude Desktop, the ones it runs as a command — a remote one is added in its Connectors, which the page says 2026-09-25 20:11:29 +08:00
yetone b3705cbb5a cli: routing groups are made, changed and removed from the terminal too (#55), where only the Routing view could — magpie groups lists them, yours then those magpie found (a removed one named with how to bring it back, a member no provider serves now marked so, the agents set to each); magpie group add <name> models=<m1>,<m2> routing=smart|order|rotate|usage stays=auto|session|turn|off makes one, its id taken from the name and numbered past one taken as the Routing view does; magpie group set <id> k=v… changes name, routing, stays and the models — models= the whole list in order, models+= and models-= one at a time — and changing one magpie found makes it yours; magpie group rm hides one magpie found, for magpie group restore to bring back; magpie group <id> shows one. Each saves through the same code the Routing view's does, so the file holds the same group and agents' model lists follow the change. A model is its provider/model id as magpie models lists it, or a bare model id one provider serves; one no provider serves, or several do, says which it could mean, and a routing or stays value magpie has none of says the ones it has, where the saved group would have quietly gone back to the default 2026-09-25 14:06:15 +08:00