feat: add VSCodium to vscode kinds (#926)

This commit is contained in:
Yibo Xi authored and GitHub committed 2026-10-06 11:28:31 +08:00
1 parent 9fcfbbdfee
commit 2f15623e35
4 files changed
+91 -1

No files matched your search

+13 -1
View File
@@ -222,7 +222,7 @@ Write your instructions, MCP servers and skills once. magpie writes them into ea
<table>
<tr><td>
Claude Code · Claude Desktop · Codex · Gemini CLI · OpenCode · OpenChamber · MiMo Code · Pi · Aside · OmO · Goose · Cursor CLI · Zed · VS Code Chat · VS Code Insiders · JetBrains Air · Copilot CLI · Crush · DeepSeek Harness · Command Code · fx · oh-my-pi · Devin · Hermes Agent · Mister Morph · Kimi Code · Muse Code · Empryo · MiniMax Code · Droid · Cline · Qoder · Qoder CN · Grok Build · ZCode · WorkBuddy · T3 Code · OpenHanako · AtomCode · Alma
Claude Code · Claude Desktop · Codex · Gemini CLI · OpenCode · OpenChamber · MiMo Code · Pi · Aside · OmO · Goose · Cursor CLI · Zed · VS Code Chat · VS Code Insiders · VSCodium Chat · JetBrains Air · Copilot CLI · Crush · DeepSeek Harness · Command Code · fx · oh-my-pi · Devin · Hermes Agent · Mister Morph · Kimi Code · Muse Code · Empryo · MiniMax Code · Droid · Cline · Qoder · Qoder CN · Grok Build · ZCode · WorkBuddy · T3 Code · OpenHanako · AtomCode · Alma
</td></tr>
</table>
@@ -235,6 +235,18 @@ export ANTHROPIC_BASE_URL=http://127.0.0.1:3425 ANTHROPIC_API_KEY=magpie
export GOOGLE_GEMINI_BASE_URL=http://127.0.0.1:3425 GEMINI_API_KEY=magpie
```
### VSCodium Chat
VSCodium's Chat features are disabled by default. To use the Chat model
picker with magpie, set `"chat.disableAIFeatures": false` in VSCodium's
settings and add the `defaultChatAgent` and `trustedExtensionAuthAccess`
entries required by [VSCodium's Copilot guide](https://github.com/VSCodium/vscodium/blob/master/docs/ext-github-copilot.md)
to VSCodium's `product.json`. The guide also explains how to install a
compatible GitHub Copilot Chat extension, since the Open VSX registry does
not normally provide Microsoft's extension. Restart VSCodium, or run
**Developer: Reload Window**, after changing these files. Magpie's models
then appear under the `magpie` custom endpoint group.
### Zed-compatible Agent paths
Magpie can use a Zed-compatible fork or installation whose executable or
+1
View File
@@ -81,6 +81,7 @@ func All() []*Agent {
zed(home, cfg),
vscode(home, cfg),
vscodeInsidersAgent(home, cfg),
vscodium(home, cfg),
air(home, cfg),
copilot(home),
crush(home, cfg),
+6
View File
@@ -58,6 +58,7 @@ type vscodeKind struct {
var (
vscodeStable = vscodeKind{id: "vscode", name: "VS Code", folder: "Code", bin: "code", aliases: []string{"vs-code", "copilot-chat", "vscode-chat"}, ua: []string{vscodeUA}}
vscodeInsiders = vscodeKind{id: "vscode-insiders", name: "VS Code Insiders", folder: "Code - Insiders", bin: "code-insiders", aliases: []string{"vs-code-insiders", "code-insiders"}}
vscodiumKind = vscodeKind{id: "vscodium", name: "VSCodium", folder: "VSCodium", bin: "codium", aliases: []string{"codium", "vscodium-chat"}}
)
// token is the bearer token its models send: Stable's the gateway's own,
@@ -75,6 +76,8 @@ func vscode(home, cfg string) *Agent { return vscodeOf(vscodeStable, home, cfg)
func vscodeInsidersAgent(home, cfg string) *Agent { return vscodeOf(vscodeInsiders, home, cfg) }
func vscodium(home, cfg string) *Agent { return vscodeOf(vscodiumKind, home, cfg) }
func vscodeOf(k vscodeKind, home, cfg string) *Agent {
switch runtime.GOOS {
case "darwin":
@@ -161,6 +164,9 @@ func vscodeKindAt(k vscodeKind, dir string) *Agent {
},
Notice: func() string {
if joined() {
if k.id == "vscodium" {
return "VSCodium's Chat features must be enabled (chat.disableAIFeatures=false) and its product.json must include defaultChatAgent and trustedExtensionAuthAccess for GitHub.copilot-chat. Then run Developer: Reload Window in VSCodium."
}
return "magpie's models are in " + k.name + "'s Chat model picker, under magpie, in each of its profiles (VS Code 1.122 or later). If they don't show, run Developer: Reload Window in " + k.name + "."
}
return ""
+71
View File
@@ -289,3 +289,74 @@ func TestVSCodeInsiders(t *testing.T) {
t.Fatal("disconnected, magpie's group kept")
}
}
func TestVSCodium(t *testing.T) {
syncHome(t)
c, err := Find("vscodium")
if err != nil {
t.Fatal(err)
}
vs, err := Find("vscode")
if err != nil {
t.Fatal(err)
}
if c.Name != "VSCodium" || c.Bin != "codium" || c.UA != nil || !strings.Contains(c.Dir, filepath.Join("VSCodium", "User")) {
t.Fatalf("vscodium: %+v", c)
}
for _, alias := range []string{"codium", "vscodium-chat"} {
a, err := Find(alias)
if err != nil || a.ID != "vscodium" {
t.Fatalf("Find(%q): %v %v", alias, a, err)
}
}
writeFile(t, c.Path, "{}\n")
writeFile(t, vs.Path, `{"chat.defaultModel":"gpt-5"}`+"\n")
if !c.Detected() {
t.Fatal("VSCodium not detected")
}
if err := c.Connect(); err != nil {
t.Fatal(err)
}
g, ok := edit.GetJSONItem(filepath.Join(c.Dir, "chatLanguageModels.json"), vscodeGroup)
if !ok || gjson.Get(g, "models.0.requestHeaders.Authorization").String() != "Bearer magpie-vscodium" || !c.Wired() || c.Check() != "" {
t.Fatalf("connected: %s %v %q", g, c.Wired(), c.Check())
}
if isFile(filepath.Join(vs.Dir, "chatLanguageModels.json")) || readFile(vs.Path) != `{"chat.defaultModel":"gpt-5"}`+"\n" || vs.Wired() {
t.Fatalf("VS Code touched:\n%s", readFile(vs.Path))
}
if got := usage.AgentOf("vscodium"); got != "vscodium" {
t.Fatalf("token: %q", got)
}
if err := c.Disconnect(); err != nil {
t.Fatal(err)
}
if _, ok := edit.GetJSONItem(filepath.Join(c.Dir, "chatLanguageModels.json"), vscodeGroup); ok || c.Wired() {
t.Fatal("disconnected, magpie's group kept")
}
}
func TestVSCodiumModelsUseTheirOwnVisibility(t *testing.T) {
syncHome(t)
if err := provider.Save(provider.Provider{ID: "relay", Name: "Relay", Key: "k", Chat: "http://127.0.0.1:1/v1", Models: []string{"visible", "hidden"}}); err != nil {
t.Fatal(err)
}
if err := provider.SetHiddenModels("vscodium", []string{"relay/hidden"}); err != nil {
t.Fatal(err)
}
if err := provider.SetHiddenModels("vscode", []string{"relay/visible"}); err != nil {
t.Fatal(err)
}
has := func(k vscodeKind, id string) bool {
b, err := json.Marshal(vscodeGroupJSON(k))
if err != nil {
t.Fatal(err)
}
return gjson.GetBytes(b, "models.#(id==\""+id+"\")").Exists()
}
if has(vscodiumKind, "relay/hidden") || !has(vscodiumKind, "relay/visible") {
t.Fatal("VSCodium did not use its own hidden-model list")
}
if !has(vscodeStable, "relay/hidden") || has(vscodeStable, "relay/visible") {
t.Fatal("VS Code did not retain its own hidden-model list")
}
}