Files
magpie/internal/agent/opencode_variants_test.go
T

125 lines
3.9 KiB
Go

package agent
import (
"encoding/json"
"os"
"path/filepath"
"reflect"
"testing"
"github.com/yetone/magpie/internal/catalog"
"github.com/yetone/magpie/internal/provider"
)
func TestOpenCodeVariants(t *testing.T) {
for _, c := range []struct {
efforts []string
want map[string]any
}{
{[]string{"none", "high", "max"}, map[string]any{
"none": map[string]any{"reasoningEffort": "none"},
"high": map[string]any{"reasoningEffort": "high"},
"max": map[string]any{"reasoningEffort": "max"},
}},
{[]string{"low", "medium", "high", "xhigh"}, map[string]any{
"low": map[string]any{"reasoningEffort": "low"},
"medium": map[string]any{"reasoningEffort": "medium"},
"high": map[string]any{"reasoningEffort": "high"},
"xhigh": map[string]any{"reasoningEffort": "xhigh"},
}},
// none at all: an empty set, so OpenCode 2 doesn't make low, medium
// and high of its own
{nil, map[string]any{}},
} {
if got := openCodeVariants(c.efforts); !reflect.DeepEqual(got, c.want) {
t.Errorf("%v: got %v, want %v", c.efforts, got, c.want)
}
}
}
// TestOpenCodeWritesVariants: each model of magpie's in opencode.json names
// the reasoning levels it has as variants — OpenCode 2 otherwise offers low,
// medium and high for every one — and the rest of the entry is as before.
func TestOpenCodeWritesVariants(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: "think", Name: "Think", Chat: "https://example.test/v1", Key: "key",
Models: []string{"deep", "wide", "plain"},
}); err != nil {
t.Fatal(err)
}
if err := catalog.SaveLive("think", "https://example.test/v1", []catalog.Model{
{ID: "deep", Efforts: []string{"none", "high", "max"}, Context: 1000000, Output: 64000},
{ID: "wide", Efforts: []string{"low", "medium", "high", "xhigh", "max"}},
{ID: "plain"},
}); err != nil {
t.Fatal(err)
}
path := filepath.Join(home, ".config", "opencode", "opencode.json")
writeFile(t, path, `{"theme":"dark"}`)
if err := opencode(home, filepath.Join(home, ".config")).Field("model").Set("magpie/think/deep"); err != nil {
t.Fatal(err)
}
b, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
var cfg struct {
Theme string `json:"theme"`
Model string `json:"model"`
Provider map[string]struct {
NPM string `json:"npm"`
Models map[string]map[string]any `json:"models"`
} `json:"provider"`
}
if err := json.Unmarshal(b, &cfg); err != nil {
t.Fatal(err)
}
if cfg.Theme != "dark" || cfg.Model != "magpie/think/deep" {
t.Fatalf("config: %s", b)
}
p := cfg.Provider["magpie"]
if p.NPM != "@ai-sdk/openai-compatible" {
t.Fatalf("npm %q", p.NPM)
}
levels := func(id string) []string {
t.Helper()
m, ok := p.Models[id]
if !ok {
t.Fatalf("%s missing: %s", id, b)
}
vs, ok := m["variants"].(map[string]any)
if !ok {
t.Fatalf("%s has no variants: %v", id, m)
}
var out []string
for _, e := range []string{"none", "minimal", "low", "medium", "high", "xhigh", "max"} {
if v, ok := vs[e]; ok {
if !reflect.DeepEqual(v, map[string]any{"reasoningEffort": e}) {
t.Fatalf("%s %s: %v", id, e, v)
}
out = append(out, e)
}
}
if len(out) != len(vs) {
t.Fatalf("%s: unexpected variants %v", id, vs)
}
return out
}
if got := levels("think/deep"); !reflect.DeepEqual(got, []string{"none", "high", "max"}) {
t.Fatalf("deep: %v", got)
}
if got := levels("think/wide"); !reflect.DeepEqual(got, []string{"low", "medium", "high", "xhigh", "max"}) {
t.Fatalf("wide: %v", got)
}
if got := levels("think/plain"); got != nil {
t.Fatalf("plain: %v", got)
}
if lim, _ := p.Models["think/deep"]["limit"].(map[string]any); lim["context"] != float64(1000000) {
t.Fatalf("deep limit: %v", p.Models["think/deep"])
}
}