From 6648a8a2ec37c8e2d16c2f658988ba2fbbc2fc4b Mon Sep 17 00:00:00 2001 From: yetone Date: Fri, 25 Sep 2026 05:34:44 +0800 Subject: [PATCH] =?UTF-8?q?cli:=20a=20model=20typed=20as=20another=20agent?= =?UTF-8?q?=20spells=20it=20is=20put=20the=20way=20this=20one=20does=20?= =?UTF-8?q?=E2=80=94=20magpie/copilot/gpt-6=20for=20Codex,=20which=20names?= =?UTF-8?q?=20catalog=20models=20copilot/gpt-6,=20and=20copilot/gpt-6=20fo?= =?UTF-8?q?r=20Pi,=20which=20names=20them=20magpie/copilot/gpt-6=20?= =?UTF-8?q?=E2=80=94=20rather=20than=20written=20as=20it=20is,=20where=20C?= =?UTF-8?q?odex=20took=20it=20for=20one=20of=20OpenAI's=20own=20and=20aske?= =?UTF-8?q?d=20OpenAI=20for=20it;=20a=20magpie/=E2=80=A6=20model=20the=20c?= =?UTF-8?q?atalog=20doesn't=20have=20is=20refused,=20and=20a=20model=20the?= =?UTF-8?q?=20agent's=20picker=20doesn't=20list=20is=20still=20taken=20as?= =?UTF-8?q?=20it=20is?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/agent/agent.go | 29 ++++++++++++++++++++++++++++ internal/agent/spell_test.go | 37 ++++++++++++++++++++++++++++++++++++ main.go | 4 ++++ 3 files changed, 70 insertions(+) create mode 100644 internal/agent/spell_test.go diff --git a/internal/agent/agent.go b/internal/agent/agent.go index 3870747e..80064d7b 100644 --- a/internal/agent/agent.go +++ b/internal/agent/agent.go @@ -156,3 +156,32 @@ func ids(as []*Agent) []string { sort.Strings(s) return s } + +// Spell puts a value typed for field key the way this agent spells it: a +// catalog model is "copilot/gpt-6" in some agents and "magpie/copilot/gpt-6" +// in others, and either is taken in both. A value the picker offers as is +// stays, and so does one it doesn't know (a model the agent reaches on its +// own that isn't listed); a "magpie/…" value the catalog doesn't have is an +// error rather than a model the agent would ask its own vendor for. +func (a *Agent) Spell(key, v string) (string, error) { + f := a.Field(key) + if f == nil || f.Options == nil || v == "" { + return v, nil + } + opts := f.Options(a.Values()) + for _, o := range opts { + if o.Value == v { + return v, nil + } + } + ref, prefixed := strings.CutPrefix(v, magpieID+"/") + for _, o := range opts { + if o.Ref != "" && o.Ref == ref { + return o.Value, nil + } + } + if prefixed { + return "", fmt.Errorf("%s isn't a model in magpie's catalog (magpie models lists them)", ref) + } + return v, nil +} diff --git a/internal/agent/spell_test.go b/internal/agent/spell_test.go new file mode 100644 index 00000000..ec7fa864 --- /dev/null +++ b/internal/agent/spell_test.go @@ -0,0 +1,37 @@ +package agent + +import "testing" + +func TestSpell(t *testing.T) { + opts := func(prefix string) func(map[string]string) []Option { + return func(map[string]string) []Option { + return []Option{ + {Value: "gpt-6"}, + {Value: prefix + "copilot/gpt-6-sol", Ref: "copilot/gpt-6-sol"}, + } + } + } + get := func() string { return "" } + bare := &Agent{Fields: []Field{{Key: "model", Get: get, Options: opts("")}}} + prefixed := &Agent{Fields: []Field{{Key: "model", Get: get, Options: opts("magpie/")}}} + for _, c := range []struct { + a *Agent + in, out string + err bool + }{ + {bare, "copilot/gpt-6-sol", "copilot/gpt-6-sol", false}, + {bare, "magpie/copilot/gpt-6-sol", "copilot/gpt-6-sol", false}, + {prefixed, "copilot/gpt-6-sol", "magpie/copilot/gpt-6-sol", false}, + {prefixed, "magpie/copilot/gpt-6-sol", "magpie/copilot/gpt-6-sol", false}, + {bare, "gpt-6", "gpt-6", false}, + {bare, "some-unlisted-model", "some-unlisted-model", false}, + {bare, "", "", false}, + {bare, "magpie/copilot/nope", "", true}, + {prefixed, "magpie/copilot/nope", "", true}, + } { + got, err := c.a.Spell("model", c.in) + if got != c.out || (err != nil) != c.err { + t.Errorf("%q: got %q, %v; want %q, err %v", c.in, got, err, c.out, c.err) + } + } +} diff --git a/main.go b/main.go index d7e2d2e1..43a164d2 100644 --- a/main.go +++ b/main.go @@ -192,6 +192,10 @@ func set(a *agent.Agent, key, value string) error { } return fmt.Errorf("%s has no field %q (fields: %s)", a.Name, key, strings.Join(keys, ", ")) } + value, err := a.Spell(f.Key, value) + if err != nil { + return err + } if err := f.Set(value); err != nil { return err }