From c0cbf90eebfac3a95dee2cb5c4bc7e9853f4786f Mon Sep 17 00:00:00 2001 From: yetone Date: Fri, 25 Sep 2026 23:53:59 +0800 Subject: [PATCH] =?UTF-8?q?agent(zcode):=20ZCode=20is=20an=20agent=20?= =?UTF-8?q?=E2=80=94=20its=20provider=20field=20puts=20every=20magpie=20mo?= =?UTF-8?q?del=20in=20ZCode's=20own=20model=20picker,=20as=20a=20provider?= =?UTF-8?q?=20named=20magpie=20in=20~/.zcode/v2/config.json=20(kind=20anth?= =?UTF-8?q?ropic,=20asked=20at=20the=20gateway's=20/v1/messages),=20kept?= =?UTF-8?q?=20in=20step=20with=20the=20catalog=20like=20OpenCode's=20list,?= =?UTF-8?q?=20and=20taken=20out=20again=20when=20cleared;=20its=20requests?= =?UTF-8?q?=20are=20known=20by=20the=20ZCode/=20User-Agent=20(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + internal/agent/agents.go | 1 + internal/agent/zcode.go | 74 +++++++++++++++++++++++++ internal/agent/zcode_test.go | 81 ++++++++++++++++++++++++++++ internal/gui/assets/app.js | 4 +- internal/gui/assets/icons/zcode.png | Bin 0 -> 8170 bytes site/public/docs/start.html | 2 +- site/public/docs/zh/start.html | 2 +- site/public/icons/zcode.png | Bin 0 -> 8170 bytes site/public/index.html | 1 + 10 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 internal/agent/zcode.go create mode 100644 internal/agent/zcode_test.go create mode 100644 internal/gui/assets/icons/zcode.png create mode 100644 site/public/icons/zcode.png diff --git a/README.md b/README.md index c262e00b..11ec7ba1 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ and there is a terminal version (`magpie tui`) and a plain CLI. | Devin | `~/.config/devin/config.json` (`%APPDATA%\devin\config.json` on Windows) | model | | Hermes Agent | `~/.hermes/config.yaml` (`$HERMES_HOME`) | model | | Grok Build | `~/.grok/config.toml` (`$GROK_HOME`) | model, effort | +| ZCode | `~/.zcode/v2/config.json` | provider (magpie's models in ZCode's picker) | Provider-scoped agents (OpenCode, Pi, Goose, Crush, omp, Hermes Agent) take `provider/model`. Only agents that are installed or configured are shown. diff --git a/internal/agent/agents.go b/internal/agent/agents.go index 5c9897fd..d154f0ba 100644 --- a/internal/agent/agents.go +++ b/internal/agent/agents.go @@ -64,6 +64,7 @@ func All() []*Agent { devin(home, cfg), hermes(home), grok(home), + zcode(home), } } diff --git a/internal/agent/zcode.go b/internal/agent/zcode.go new file mode 100644 index 00000000..f85ab683 --- /dev/null +++ b/internal/agent/zcode.go @@ -0,0 +1,74 @@ +package agent + +import ( + "path/filepath" + + "github.com/yetone/magpie/internal/edit" + "github.com/yetone/magpie/internal/gateway" +) + +// ZCode (Zhipu's desktop app) keeps its model providers in +// ~/.zcode/v2/config.json, OpenCode's provider shape with a kind of its own: +// +// {"provider":{"magpie":{"name":"magpie","kind":"anthropic", +// "options":{"apiKey":"magpie","baseURL":"http://127.0.0.1:3425"}, +// "enabled":true,"source":"custom", +// "models":{"":{"name":…,"limit":{"context":…},"modalities":{…}}}}}} +// +// An anthropic provider is asked at baseURL + /v1/messages. The model is +// picked per task in ZCode's own picker and kept in its window, not in a +// file, so what magpie sets is whether its models are in that picker. + +func zcode(home string) *Agent { + dir := filepath.Join(home, ".zcode") + path := filepath.Join(dir, "v2", "config.json") + key := "provider." + magpieID + return &Agent{ + ID: "zcode", Name: "ZCode", Icon: "zcode", Aliases: []string{"z-code"}, + UA: []string{"zcode"}, + Dir: dir, Path: path, + Notice: func() string { + if Running(`ZCode\.app/`, `(^|/)ZCode( |$)`) { + return "ZCode reads its providers at start-up — restart ZCode to see magpie's models in its picker." + } + return "" + }, + Sync: func() error { return syncJSON(path, key, zcodeProviderJSON) }, + Fields: []Field{{ + Key: "provider", Label: "provider", + Get: func() string { + if _, ok := edit.GetJSON(path, key); ok { + return magpieID + } + return "" + }, + Set: func(v string) error { + if v == "" { + return edit.DelJSON(path, key) + } + return edit.SetJSON(path, edit.KV{Path: key, Value: zcodeProviderJSON()}) + }, + Options: func(map[string]string) []Option { + return []Option{{Value: magpieID, Label: "magpie", Icon: "magpie", Note: "every magpie model in ZCode's picker"}} + }, + }}, + } +} + +func zcodeProviderJSON() any { + ms := map[string]any{} + for _, m := range magpieModels() { + window := m.Context + if window == 0 { + window = 200000 + } + in := []string{"text"} + if m.Images { + in = append(in, "image") + } + ms[m.ID] = map[string]any{"name": m.Name, "limit": map[string]any{"context": window}, + "modalities": map[string]any{"input": in, "output": []string{"text"}}} + } + return map[string]any{"name": "magpie", "kind": "anthropic", "enabled": true, "source": "custom", + "options": map[string]any{"apiKey": gateway.Token, "baseURL": gateway.URL()}, "models": ms} +} diff --git a/internal/agent/zcode_test.go b/internal/agent/zcode_test.go new file mode 100644 index 00000000..befe6f56 --- /dev/null +++ b/internal/agent/zcode_test.go @@ -0,0 +1,81 @@ +package agent + +import ( + "encoding/json" + "os" + "path/filepath" + "testing" + + "github.com/yetone/magpie/internal/provider" +) + +func TestZCode(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) + t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) + if err := provider.Save(provider.Provider{ID: "deepseek", Name: "DeepSeek", Chat: "https://api.deepseek.com/v1", Key: "k", Models: []string{"pro"}}); err != nil { + t.Fatal(err) + } + path := filepath.Join(home, ".zcode", "v2", "config.json") + os.MkdirAll(filepath.Dir(path), 0o755) + os.WriteFile(path, []byte(`{"provider":{"builtin:bigmodel":{"name":"Bigmodel","kind":"anthropic","enabled":true}}}`), 0o644) + read := func() map[string]any { + var c struct { + Provider map[string]map[string]any `json:"provider"` + } + b, _ := os.ReadFile(path) + if err := json.Unmarshal(b, &c); err != nil { + t.Fatalf("%v\n%s", err, b) + } + if c.Provider["builtin:bigmodel"] == nil { + t.Fatalf("ZCode's own provider went: %s", b) + } + return c.Provider["magpie"] + } + + a := zcode(home) + if !a.Detected() { + t.Fatal("not detected") + } + f := a.Field("provider") + if f.Get() != "" { + t.Fatalf("get: %q", f.Get()) + } + if err := f.Set("magpie"); err != nil { + t.Fatal(err) + } + m := read() + opts, _ := m["options"].(map[string]any) + models, _ := m["models"].(map[string]any) + pro, _ := models["deepseek/pro"].(map[string]any) + if m["kind"] != "anthropic" || m["enabled"] != true || m["source"] != "custom" || opts["apiKey"] != "magpie" || + opts["baseURL"] == "" || pro == nil || pro["limit"] == nil || pro["modalities"] == nil { + t.Fatalf("magpie provider: %v", m) + } + if f.Get() != "magpie" { + t.Fatalf("get: %q", f.Get()) + } + + // a provider added later reaches ZCode's picker + if err := provider.Save(provider.Provider{ID: "kimi", Name: "Kimi", Chat: "https://api.moonshot.cn/v1", Key: "k", Models: []string{"k2"}}); err != nil { + t.Fatal(err) + } + if err := a.Sync(); err != nil { + t.Fatal(err) + } + if models, _ := read()["models"].(map[string]any); models["kimi/k2"] == nil { + t.Fatalf("not synced: %v", models) + } + + if err := f.Set(""); err != nil { + t.Fatal(err) + } + if read() != nil || f.Get() != "" { + t.Fatal("magpie provider left behind") + } + // nothing to sync into a config that has no magpie provider + if err := a.Sync(); err != nil || read() != nil { + t.Fatal("sync added the provider") + } +} diff --git a/internal/gui/assets/app.js b/internal/gui/assets/app.js index 7dac7601..e15d0fd2 100644 --- a/internal/gui/assets/app.js +++ b/internal/gui/assets/app.js @@ -98,9 +98,9 @@ function icon(name) { return e; } if (name) { - if (name.endsWith("-color") || name === "crush") { + if (name.endsWith("-color") || name === "crush" || name === "zcode") { const img = el("img"); - img.src = `icons/${name}.${name === "crush" ? "png" : "svg"}`; + img.src = `icons/${name}.${name === "crush" || name === "zcode" ? "png" : "svg"}`; img.alt = ""; img.draggable = false; e.append(img); diff --git a/internal/gui/assets/icons/zcode.png b/internal/gui/assets/icons/zcode.png new file mode 100644 index 0000000000000000000000000000000000000000..377db60cc9239341c4d4055dadcf04eb1ba5f078 GIT binary patch literal 8170 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 live in ~/.config/magpie/providers.json, readable by you alone. magpie never reads keys from your shell environment: what you add is what it uses.

2 · Pick a model for each agent

-

The Agents tab has a row for each agent installed or configured on this machine. magpie knows Claude Code, Codex, Gemini CLI, OpenCode, Pi, Goose, Cursor, Copilot CLI, Crush, DeepSeek Harness, Command Code, omp, Devin, Hermes Agent and Grok Build.

+

The Agents tab has a row for each agent installed or configured on this machine. magpie knows Claude Code, Codex, Gemini CLI, OpenCode, Pi, Goose, Cursor, Copilot CLI, Crush, DeepSeek Harness, Command Code, omp, Devin, Hermes Agent, Grok Build and ZCode.

The Agents tab: one row per agent with the model it uses, and saved profiles at the bottom diff --git a/site/public/docs/zh/start.html b/site/public/docs/zh/start.html index 0796969a..87e218a4 100644 --- a/site/public/docs/zh/start.html +++ b/site/public/docs/zh/start.html @@ -114,7 +114,7 @@

密钥保存在 ~/.config/magpie/providers.json,只有你自己可读。magpie 从不读取 shell 环境变量里的密钥:你添加什么,它就用什么。

2 · 给每个 Agent 选模型

-

Agent 标签页里,本机装了或配置过的每个 Agent 各占一行。magpie 支持 Claude Code、Codex、Gemini CLI、OpenCode、Pi、Goose、Cursor、Copilot CLI、Crush、DeepSeek Harness、Command Code、omp、Devin、Hermes Agent 和 Grok Build。

+

Agent 标签页里,本机装了或配置过的每个 Agent 各占一行。magpie 支持 Claude Code、Codex、Gemini CLI、OpenCode、Pi、Goose、Cursor、Copilot CLI、Crush、DeepSeek Harness、Command Code、omp、Devin、Hermes Agent、Grok Build 和 ZCode。

Agent 页:每个 Agent 一行,显示当前模型,底部是保存的方案 diff --git a/site/public/icons/zcode.png b/site/public/icons/zcode.png new file mode 100644 index 0000000000000000000000000000000000000000..377db60cc9239341c4d4055dadcf04eb1ba5f078 GIT binary patch literal 8170 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
  • Hermes Agent
  • Grok Build
  • +
  • ZCode
  • Every model