From fe2603ff4f3d7d64244a0317538081a81eade61e Mon Sep 17 00:00:00 2001 From: yetone Date: Mon, 5 Oct 2026 00:56:43 +0800 Subject: [PATCH] =?UTF-8?q?agent:=20Claude=20Code's=20model=20set=20back?= =?UTF-8?q?=20to=20its=20default=20puts=20back=20the=20endpoint=20and=20to?= =?UTF-8?q?ken=20the=20user=20had=20before=20magpie=20and=20leaves=20them?= =?UTF-8?q?=20(=5F=5Fjingling=20on=20X:=20=E6=8E=A5=E5=85=A5=E5=90=8E?= =?UTF-8?q?=E8=B7=91=20magpie=20claude=20model=20default=EF=BC=8C=E4=BC=9A?= =?UTF-8?q?=E6=8A=8A=E5=8E=9F=E6=9D=A5=E7=9A=84=20ANTHROPIC=5FBASE=5FURL?= =?UTF-8?q?=20=E5=92=8C=20token=20=E4=B9=9F=E5=88=A0=E6=8E=89=EF=BC=8C?= =?UTF-8?q?=E4=B9=8B=E5=90=8E=E5=86=8D=20default=20=E4=B9=9F=E6=81=A2?= =?UTF-8?q?=E5=A4=8D=E4=B8=8D=E4=BA=86=EF=BC=8C=E5=A4=8D=E7=8E=B0=E4=BA=86?= =?UTF-8?q?=E4=B8=A4=E6=AC=A1)=20=E2=80=94=20the=20model=20field's=20defau?= =?UTF-8?q?lt=20deleted=20every=20env=20key=20magpie=20writes,=20the=20use?= =?UTF-8?q?r's=20own=20ANTHROPIC=5FBASE=5FURL=20and=20ANTHROPIC=5FAUTH=5FT?= =?UTF-8?q?OKEN=20among=20them,=20and=20forgot=20the=20stash=20that=20kept?= =?UTF-8?q?=20them=20from=20before=20magpie,=20so=20Disconnect=20after=20i?= =?UTF-8?q?t=20had=20nothing=20to=20put=20back.=20It=20now=20takes=20magpi?= =?UTF-8?q?e=20out=20as=20Disconnect=20does=20(its=20endpoint,=20token,=20?= =?UTF-8?q?tiers=20and=20window,=20the=20user's=20endpoint=20and=20token?= =?UTF-8?q?=20put=20back=20from=20the=20stash)=20and=20deletes=20only=20mo?= =?UTF-8?q?del;=20an=20endpoint=20the=20user=20set=20themselves,=20wired?= =?UTF-8?q?=20or=20not,=20stays,=20as=20the=20Agents=20page's=20default=20?= =?UTF-8?q?option=20(Claude=20Code=20=C2=B7=20their=20host)=20says.=20magp?= =?UTF-8?q?ie's=20env=20left=20at=20a=20gateway=20address=20since=20change?= =?UTF-8?q?d=20(its=20token)=20still=20goes.=20In=20a=20sandbox=20HOME=20w?= =?UTF-8?q?ith=20the=20release=20binary:=20settings.json=20with=20//=20min?= =?UTF-8?q?e,=20model=20opus,=20env=20ANTHROPIC=5FBASE=5FURL=20https://api?= =?UTF-8?q?.deepseek.com/anthropic=20and=20a=20token;=20magpie=20claude=20?= =?UTF-8?q?deepseek/deepseek-chat,=20then=20magpie=20claude=20model=20defa?= =?UTF-8?q?ult:=20the=20comment,=20base=20URL=20and=20token=20back,=20mode?= =?UTF-8?q?l=20gone;=20magpie=20claude=20default=20after=20it=20leaves=20t?= =?UTF-8?q?hem.=20TestAgentModelDefaultKeepsTheEndpointBefore=20fails=20on?= =?UTF-8?q?=20the=20old=20code.=20go=20vet,=20builds=20(darwin,=20GOOS=3Dl?= =?UTF-8?q?inux=20nogui,=20GOOS=3Dwindows)=20and=20go=20test=20-tags=20nog?= =?UTF-8?q?ui=20-count=3D1=20./...=20under=20a=20temp=20HOME=20pass.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agent_default_cli_test.go | 48 +++++++++++++++++++++++++++++++++++++++ internal/agent/claude.go | 28 +++++++++++------------ 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/agent_default_cli_test.go b/agent_default_cli_test.go index b32510ed..1f8fb855 100644 --- a/agent_default_cli_test.go +++ b/agent_default_cli_test.go @@ -43,3 +43,51 @@ func TestAgentDefaultPutsBackTheModelBefore(t *testing.T) { t.Fatalf("the model field's default leaves Claude Code as installed:\n%s", s) } } + +// `magpie claude model default` on a Claude Code wired into magpie puts +// back the endpoint and token the user had before magpie and leaves them: +// it took them away, and Disconnect after it had nothing to put back +// (__jingling on X, twice). +func TestAgentModelDefaultKeepsTheEndpointBefore(t *testing.T) { + groupsHome(t) + t.Setenv("CLAUDE_CONFIG_DIR", "") + path := filepath.Join(os.Getenv("HOME"), ".claude", "settings.json") + os.MkdirAll(filepath.Dir(path), 0o755) + own := "{\n \"model\": \"opus\",\n \"env\": {\n \"ANTHROPIC_BASE_URL\": \"https://relay.example.com\",\n \"ANTHROPIC_AUTH_TOKEN\": \"sk-mine\"\n }\n}\n" + if err := os.WriteFile(path, []byte(own), 0o644); err != nil { + t.Fatal(err) + } + read := func() string { + b, _ := os.ReadFile(path) + return string(b) + } + mine := func(when string) { + t.Helper() + s := read() + if !strings.Contains(s, `"ANTHROPIC_BASE_URL": "https://relay.example.com"`) || !strings.Contains(s, `"ANTHROPIC_AUTH_TOKEN": "sk-mine"`) { + t.Fatalf("%s: the user's own endpoint and token are gone:\n%s", when, s) + } + } + if err := run([]string{"claude", "a/m"}); err != nil { + t.Fatal(err) + } + if s := read(); strings.Contains(s, "relay.example.com") { + t.Fatalf("not wired:\n%s", s) + } + if err := run([]string{"claude", "model", "default"}); err != nil { + t.Fatal(err) + } + mine("model default") + if s := read(); strings.Contains(s, `"model"`) { + t.Fatalf("model default kept a model:\n%s", s) + } + if err := run([]string{"claude", "default"}); err != nil { + t.Fatal(err) + } + mine("default after it") + // unwired, a field's default leaves the user's own endpoint too + if err := run([]string{"claude", "model", "default"}); err != nil { + t.Fatal(err) + } + mine("model default unwired") +} diff --git a/internal/agent/claude.go b/internal/agent/claude.go index 1839ee1a..c451e67a 100644 --- a/internal/agent/claude.go +++ b/internal/agent/claude.go @@ -563,24 +563,22 @@ func claudeIn(at place) *Agent { var writeTiers func(main string, tiers map[string]string) error set := func(v string) error { if v == "" { - // Claude Code as installed: Anthropic's own endpoint and model + // Claude Code's own model, on the endpoint the user had before + // magpie: magpie steps out, putting back their endpoint and + // token, which stay theirs (__jingling on X: magpie claude + // model default took their ANTHROPIC_BASE_URL and token away + // for good) + if _, err := unroute(); err != nil { + return err + } keys := []string{"model"} - for _, k := range claudeEnv { - keys = append(keys, "env."+k) + if env("ANTHROPIC_AUTH_TOKEN") == gateway.Token { + // magpie's, left at a gateway address since changed + for _, k := range claudeEnv { + keys = append(keys, "env."+k) + } } forget(at.key("claude.model"), at.key("claude.base_url"), at.key("claude.auth_token"), mainKey) - if err := dropWindow(); err != nil { - return err - } - if err := dropCompact(); err != nil { - return err - } - if err := dropCaps(); err != nil { - return err - } - if err := dropPicker(); err != nil { - return err - } return edit.DelJSON(path, keys...) } if isMagpie(v) {