Files
magpie/internal/provider/plugin_context_test.go
T
yetone a0d41044bb providers: a provider's model list says the context window agents are told — the one set on it, else models.dev's for a prefixed id — not only its vendor's list's (Discord, ARNO on v0.1.815: provider的上下文窗口覆盖功能好像失效了。cline插件的模型都没有默认的上下文窗口大小 … 如zai/glm-5.3-flash,cline-free/mimo-v2.6-flash) — the Providers page's models (providerInfo's modelJSON.Context) took catalog.Model.Context as the vendor's list or the plugin gave it, while the catalog's entries (entryFor: /v1/models, every agent's config, routing) take the window the user set (Provider.ContextOf) over it, and models.dev's for the id (catalog.ContextOf, which already reads zai/glm-5.3-flash as glm-5.3-flash) where the list says none. So a window set in the editor or with magpie model context reached agents but not the page, the agents' model pickers (which read the same list) or a chip's 1M tag, and a model listed with no window — Cline's plugin gives every model 0 (fixed in its 0.1.2), a relay's prefixed ids — showed none. The window is now one function, Provider.WindowOf (the user's, else ListedWindow: the list's, else models.dev's), which entryFor and providerInfo both read; the page is also told the window before the user's (listed), which the context field's "Each model's most" pick compares against, so a model set to its most still offers it. Lookups by a prefixed id were not broken: in the owner's config 14 of 794 models had no window on the page and one from models.dev for agents (Gemini's, Kiro's auto), the same split. TestProviderModelWindowSaid (a relay serving zai/glm-5.3-flash and own-model: the page says 1M before a window is set and 200K/64K after, as Served does) fails on the old code (the page said 0 where agents were told 1000000); TestPluginModelWindow (Cline's plugin with cline-pass/glm-5.3-flash, cline-free/mimo-v2.6-flash: models.dev's window, then the one set) guards the plugin path, which was already right for agents. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass; model-rate and editor-short-window pass in WebKit. Not tried with the reporter's Cline account; an agent already running keeps the window it started with until it rereads its config.
2026-10-04 13:36:54 +08:00

88 lines
3.1 KiB
Go

package provider
import (
"encoding/json"
"os"
"path/filepath"
"testing"
"github.com/yetone/magpie/internal/catalog"
"github.com/yetone/magpie/internal/plugin"
"github.com/yetone/magpie/internal/settings"
)
// clinePlugin is Cline's plugin signed in, its models as its feed lists
// them: ids with Cline's own prefixes and no window, as models.dev knows
// them under their makers.
func clinePlugin(t *testing.T) {
t.Helper()
claudeHome(t)
t.Setenv("MAGPIE_BUN", "")
os.MkdirAll(filepath.Dir(catalog.CachePath()), 0o755)
os.WriteFile(catalog.CachePath(), []byte(`{
"zai":{"id":"zai","models":{"glm-5.3-flash":{"id":"glm-5.3-flash","limit":{"context":1000000,"output":131072}}}},
"xiaomi":{"id":"xiaomi","models":{"mimo-v2.6-flash":{"id":"mimo-v2.6-flash","limit":{"context":1048576,"output":131072}}}}}`), 0o644)
catalog.Reset()
t.Cleanup(catalog.Reset)
spec := "@magpie-community/opencode-cline-auth"
write := func(name string, v any) {
t.Helper()
b, _ := json.Marshal(v)
os.MkdirAll(settings.Dir(), 0o700)
if err := os.WriteFile(filepath.Join(settings.Dir(), name), b, 0o600); err != nil {
t.Fatal(err)
}
}
write("plugins.json", map[string]any{"plugins": []map[string]any{{"spec": spec}}})
write("plugin-auth.json", map[string]map[string]any{"cline": {"type": "api", "key": "sk-cline-1234"}})
plugin.UseCached([]plugin.Provider{{ID: "cline", Spec: spec, Name: "Cline",
Methods: []plugin.Method{{Type: "api", Label: "API key"}},
Accounts: []plugin.Account{{Key: "cline", Type: "api"}},
Models: []plugin.Model{
{ID: "cline-pass/glm-5.3-flash", Name: "GLM 5.3 Flash (ClinePass)"},
{ID: "cline-free/mimo-v2.6-flash", Name: "MiMo V2.6 Flash (free)", Free: true},
{ID: "stealth/space-bunny-alpha", Name: "Space Bunny Alpha", Context: 1_000_000},
}}})
t.Cleanup(func() { plugin.UseCached(nil) })
}
func pluginWindow(t *testing.T, id string) int {
t.Helper()
for _, e := range Served() {
if e.ID == id {
return e.Context
}
}
t.Fatalf("no %s in %v", id, IDs())
return 0
}
// A plugin's model listed without a window (Cline's feed says none) takes
// the one models.dev gives its model under the vendor's prefix, and the
// window the user sets on the provider over both (ARNO on Discord, v0.1.815).
func TestPluginModelWindow(t *testing.T) {
clinePlugin(t)
p, err := Find("cline")
if err != nil {
t.Fatal(err)
}
for id, want := range map[string]int{"cline/cline-pass/glm-5.3-flash": 1_000_000, "cline/cline-free/mimo-v2.6-flash": 1_048_576, "cline/stealth/space-bunny-alpha": 1_000_000} {
if got := pluginWindow(t, id); got != want {
t.Errorf("%s: %d, want %d", id, got, want)
}
}
if err := SetContext(*p, "cline-free/mimo-v2.6-flash", 400_000); err != nil {
t.Fatal(err)
}
if got := pluginWindow(t, "cline/cline-free/mimo-v2.6-flash"); got != 400_000 {
t.Errorf("set: %d", got)
}
// the page lists it so too (gui's providerInfo reads WindowOf)
p, _ = Find("cline")
for _, m := range p.Available() {
if m.ID == "cline-free/mimo-v2.6-flash" && (p.WindowOf(m) != 400_000 || ListedWindow(m) != 1_048_576) {
t.Errorf("WindowOf %d, ListedWindow %d", p.WindowOf(m), ListedWindow(m))
}
}
}