From 6fb05259d7a3294ca006f01002e675d7f3e16329 Mon Sep 17 00:00:00 2001 From: yetone Date: Mon, 5 Oct 2026 06:35:59 +0800 Subject: [PATCH] =?UTF-8?q?agent:=20OpenHanako's=20own=20provider=20named?= =?UTF-8?q?=20as=20one=20of=20magpie's=20isn't=20magpie's,=20so=20Disconne?= =?UTF-8?q?ct=20from=20magpie=20takes=20it=20off=20and=20the=20row=20says?= =?UTF-8?q?=20Not=20connected=20(Hu9956,=20#835)=20=E2=80=94=20OpenHanako?= =?UTF-8?q?=20spells=20every=20model=20provider/id,=20its=20own=20provider?= =?UTF-8?q?s'=20as=20magpie's=20(magpie/),=20and=20a=20value=20of=20i?= =?UTF-8?q?ts=20own=20DeepSeek,=20deepseek/deepseek-v4-pro,=20read=20as=20?= =?UTF-8?q?magpie's=20deepseek/deepseek-v4-pro=20because=20magpie=20has=20?= =?UTF-8?q?a=20provider=20of=20that=20name.=20So=20the=20row=20stayed=20?= =?UTF-8?q?=E5=B7=B2=E6=8E=A5=E5=85=A5=20on=20it:=20Disconnect=20put=20bac?= =?UTF-8?q?k=20the=20model=20the=20agent=20had=20before=20(its=20own=20dee?= =?UTF-8?q?pseek/deepseek-v4-pro),=20took=20magpie's=20provider=20out,=20a?= =?UTF-8?q?nd=20the=20row=20still=20read=20as=20connected,=20on=20and=20on?= =?UTF-8?q?.=20An=20agent=20can=20now=20say=20what=20each=20of=20magpie's?= =?UTF-8?q?=20values=20in=20it=20starts=20with=20(Prefixed,=20magpie/=20fo?= =?UTF-8?q?r=20OpenHanako);=20a=20value=20without=20it=20is=20the=20agent'?= =?UTF-8?q?s=20own,=20never=20magpie's.=20TestHanakoOwnProviderNamedAsMagp?= =?UTF-8?q?ies=20(own=20relay/glm-4.6=20with=20magpie's=20relay:=20not=20w?= =?UTF-8?q?ired,=20Connect,=20Disconnect=20puts=20it=20back=20and=20the=20?= =?UTF-8?q?row=20is=20off)=20fails=20on=20the=20old=20code.=20go=20vet,=20?= =?UTF-8?q?builds=20(darwin,=20GOOS=3Dlinux=20nogui,=20GOOS=3Dwindows)=20a?= =?UTF-8?q?nd=20go=20test=20-tags=20nogui=20-count=3D1=20./...=20under=20a?= =?UTF-8?q?=20temp=20HOME=20pass.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/agent/agent.go | 6 ++++++ internal/agent/applied.go | 2 +- internal/agent/hanako.go | 3 +++ internal/agent/hanako_test.go | 38 +++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/internal/agent/agent.go b/internal/agent/agent.go index 82186179..870f6868 100644 --- a/internal/agent/agent.go +++ b/internal/agent/agent.go @@ -176,6 +176,12 @@ type Agent struct { // names, never taken for one of magpie's models nor moved by what // matches the picker (RenameRefs moves the names in it). SplitSuffix func(v string) (model, suffix string, one bool) + // Prefixed, when set, is what each of magpie's values in the agent's + // fields starts with ("magpie/", its provider there): a value without + // it is a model of one of the agent's own providers, never magpie's, + // even when magpie has a provider of the same name (OpenHanako's own + // deepseek/deepseek-v4-pro, #835). + Prefixed string // detect, when set, says whether the agent is here in place of looking // for its files and binary: a distro's, probed once. detect func() bool diff --git a/internal/agent/applied.go b/internal/agent/applied.go index e81bfa05..220472d2 100644 --- a/internal/agent/applied.go +++ b/internal/agent/applied.go @@ -207,7 +207,7 @@ func magpieValue(a *Agent, f Field, v string, vals map[string]string) bool { return false } v, _, one := a.split(v) - if !one { + if !one || a.Prefixed != "" && !strings.HasPrefix(v, a.Prefixed) { return false } if isMagpie(v) { diff --git a/internal/agent/hanako.go b/internal/agent/hanako.go index 8895b2b4..d94de326 100644 --- a/internal/agent/hanako.go +++ b/internal/agent/hanako.go @@ -91,6 +91,9 @@ func hanako(home string) *Agent { // what its provider client sends, though the key names it first UA: []string{"hanaagent"}, Dir: dir, Path: path, + // its own providers' models are provider/id as magpie's are: one + // is magpie's only on magpie's provider + Prefixed: magpieID + "/", Sync: func() error { cur, ok := hanakoCurrent(dir) if !ok || hanakoSame(cur, hanakoProvider()) { diff --git a/internal/agent/hanako_test.go b/internal/agent/hanako_test.go index d32535d2..75767df4 100644 --- a/internal/agent/hanako_test.go +++ b/internal/agent/hanako_test.go @@ -461,3 +461,41 @@ func TestHanakoKey(t *testing.T) { t.Fatal(k) } } + +// One of OpenHanako's own providers named as one of magpie's (its own +// DeepSeek, and magpie's deepseek): its model isn't magpie's, so the row +// isn't connected on it, and Disconnect from magpie puts it back and is +// done, rather than leaving the row connected on the model it went back to +// (Hu9956, #835). +func TestHanakoOwnProviderNamedAsMagpies(t *testing.T) { + home, dir := hanakoTestHome(t) + catalogPath := filepath.Join(dir, "provider-catalog.json") + // the user's own relay provider, which magpie has one of too + hanakoWrite(t, catalogPath, `{"catalogVersion":2,"providers":{"relay":{"base_url":"https://x/v1","api":"openai-completions","api_key":"k","models":["glm-4.6"]}}}`, 0o600) + hanakoWrite(t, filepath.Join(dir, "user", "preferences.json"), `{"primaryAgent":"hana"}`, 0o644) + cfg := filepath.Join(dir, "agents", "hana", "config.yaml") + hanakoWrite(t, cfg, "models:\n chat:\n id: glm-4.6\n provider: relay\n", 0o644) + + a := hanako(home) + if a.Wired() { + t.Fatal("its own relay/glm-4.6 reads as magpie's") + } + if err := a.Connect(); err != nil { + t.Fatal(err) + } + if !a.Wired() { + t.Fatalf("not wired after connect: %v", a.Values()) + } + if err := a.Disconnect(); err != nil { + t.Fatal(err) + } + if chat, raw := hanakoChatOf(t, cfg); chat["id"] != "glm-4.6" || chat["provider"] != "relay" { + t.Fatalf("disconnected config:\n%s", raw) + } + if _, ok := hanakoCurrent(dir); ok { + t.Fatal("magpie's provider is still there") + } + if a.Wired() { + t.Fatalf("still connected after Disconnect: %v", a.Values()) + } +}