1package agent
2
3import (
4 "encoding/json"
5 "os"
6 "path/filepath"
7 "testing"
8)
9
10// TestValidateAndRepairConfig_MismatchedPair simulates the bug from a
11// stale /model switch: provider=anthropic but model=kimi-for-coding
12// (which belongs to provider=kimi). The validator should rewrite the
13// model to anthropic's default and persist.
14func TestValidateAndRepairConfig_MismatchedPair(t *testing.T) {
15 home := t.TempDir()
16 t.Setenv("ZOT_HOME", home)
17
18 must := func(c Config) {
19 t.Helper()
20 b, _ := json.Marshal(c)
21 if err := os.WriteFile(filepath.Join(home, "config.json"), b, 0o644); err != nil {
22 t.Fatal(err)
23 }
24 }
25 must(Config{Provider: "anthropic", Model: "kimi-for-coding"})
26
27 ValidateAndRepairConfig()
28
29 out, err := LoadConfig()
30 if err != nil {
31 t.Fatal(err)
32 }
33 if out.Provider != "anthropic" {
34 t.Errorf("provider not preserved: %q", out.Provider)
35 }
36 if out.Model == "kimi-for-coding" {
37 t.Errorf("model not repaired; still %q", out.Model)
38 }
39 if out.Model == "" {
40 t.Errorf("model not set; expected anthropic default")
41 }
42}
43
44// TestValidateAndRepairConfig_UnknownProvider resets to anthropic and
45// clears the model when the saved provider id isn't recognised
46// (e.g. user removed it from a previous build).
47func TestValidateAndRepairConfig_UnknownProvider(t *testing.T) {
48 home := t.TempDir()
49 t.Setenv("ZOT_HOME", home)
50
51 b, _ := json.Marshal(Config{Provider: "made-up-provider", Model: "some-model"})
52 _ = os.WriteFile(filepath.Join(home, "config.json"), b, 0o644)
53
54 ValidateAndRepairConfig()
55
56 out, _ := LoadConfig()
57 if out.Provider != "anthropic" {
58 t.Errorf("provider not reset: %q", out.Provider)
59 }
60 if out.Model != "" {
61 t.Errorf("model not cleared: %q", out.Model)
62 }
63}
64
65// TestValidateAndRepairConfig_UnknownModel keeps the provider but
66// snaps the model to that provider's default when the saved id is no
67// longer in the catalog.
68func TestValidateAndRepairConfig_UnknownModel(t *testing.T) {
69 home := t.TempDir()
70 t.Setenv("ZOT_HOME", home)
71
72 b, _ := json.Marshal(Config{Provider: "anthropic", Model: "claude-deleted-model"})
73 _ = os.WriteFile(filepath.Join(home, "config.json"), b, 0o644)
74
75 ValidateAndRepairConfig()
76
77 out, _ := LoadConfig()
78 if out.Provider != "anthropic" {
79 t.Errorf("provider changed: %q", out.Provider)
80 }
81 if out.Model == "" || out.Model == "claude-deleted-model" {
82 t.Errorf("model not repaired: %q", out.Model)
83 }
84}
85
86// TestValidateAndRepairConfig_HappyPath leaves a valid config alone.
87func TestValidateAndRepairConfig_HappyPath(t *testing.T) {
88 home := t.TempDir()
89 t.Setenv("ZOT_HOME", home)
90
91 b, _ := json.Marshal(Config{Provider: "anthropic", Model: "claude-sonnet-4-5"})
92 _ = os.WriteFile(filepath.Join(home, "config.json"), b, 0o644)
93
94 ValidateAndRepairConfig()
95
96 out, _ := LoadConfig()
97 if out.Provider != "anthropic" {
98 t.Errorf("provider mutated: %q", out.Provider)
99 }
100 if out.Model != "claude-sonnet-4-5" {
101 t.Errorf("model mutated: %q", out.Model)
102 }
103}