125 lines
3.9 KiB
Go
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"])
|
|
}
|
|
}
|