1package agent
2
3import (
4 "context"
5 "encoding/json"
6 "strings"
7 "testing"
8
9 "github.com/bnema/zut/packages/provider"
10)
11
12func TestParseArgsRejectsLegacyFastModeChildFlags(t *testing.T) {
13 if _, err := ParseArgs([]string{"--fast-mode"}); err == nil {
14 t.Fatal("ParseArgs accepted removed --fast-mode child flag")
15 }
16 if _, err := ParseArgs([]string{"--no-fast-mode"}); err == nil {
17 t.Fatal("ParseArgs accepted removed --no-fast-mode child flag")
18 }
19}
20
21func TestResolveFastModeDefaultsOff(t *testing.T) {
22 t.Setenv("ZUT_HOME", t.TempDir())
23 if err := SaveConfig(Config{Provider: "openai", Model: "gpt-5"}); err != nil {
24 t.Fatal(err)
25 }
26
27 r, err := Resolve(Args{}, false)
28 if err != nil {
29 t.Fatalf("Resolve failed: %v", err)
30 }
31 if r.FastMode {
32 t.Fatal("FastMode = true by default, want false")
33 }
34}
35
36func TestResolveFastModeFromConfig(t *testing.T) {
37 t.Setenv("ZUT_HOME", t.TempDir())
38 enabled := true
39 if err := SaveConfig(Config{Provider: "openai", Model: "gpt-5", FastMode: &enabled}); err != nil {
40 t.Fatal(err)
41 }
42
43 r, err := Resolve(Args{}, false)
44 if err != nil {
45 t.Fatalf("Resolve failed: %v", err)
46 }
47 if !r.FastMode {
48 t.Fatal("FastMode = false, want true from config")
49 }
50}
51
52func TestResolveFastModeRemainsEnabledForUnsupportedProviderUntilRequest(t *testing.T) {
53 t.Setenv("ZUT_HOME", t.TempDir())
54 enabled := true
55 if err := SaveConfig(Config{Provider: "anthropic", Model: "claude-sonnet-4-5", FastMode: &enabled}); err != nil {
56 t.Fatal(err)
57 }
58
59 r, err := Resolve(Args{}, false)
60 if err != nil {
61 t.Fatalf("Resolve failed: %v", err)
62 }
63 if !r.FastMode {
64 t.Fatal("FastMode = false, want true from config")
65 }
66}
67
68func TestResolveFastModeRequiresExplicitChildOverride(t *testing.T) {
69 t.Setenv("ZUT_HOME", t.TempDir())
70 if err := SaveConfig(Config{Provider: "openai", Model: "gpt-5"}); err != nil {
71 t.Fatal(err)
72 }
73
74 r, err := Resolve(Args{FastMode: true}, false)
75 if err != nil {
76 t.Fatalf("Resolve failed: %v", err)
77 }
78 if r.FastMode {
79 t.Fatal("FastMode = true, want unmarked programmatic value to be ignored")
80 }
81}
82
83func TestResolveFastModeDurableChildDisableOverridesConfig(t *testing.T) {
84 t.Setenv("ZUT_HOME", t.TempDir())
85 enabled := true
86 if err := SaveConfig(Config{Provider: "openai", Model: "gpt-5", FastMode: &enabled}); err != nil {
87 t.Fatal(err)
88 }
89 r, err := Resolve(Args{FastModeSet: true}, false)
90 if err != nil {
91 t.Fatalf("Resolve failed: %v", err)
92 }
93 if r.FastMode {
94 t.Fatal("FastMode = true, want explicit child disable to override config")
95 }
96}
97
98func TestConfigSettingsStorePersistsFastMode(t *testing.T) {
99 t.Setenv("ZUT_HOME", t.TempDir())
100 if err := SaveConfig(Config{Theme: "dark"}); err != nil {
101 t.Fatal(err)
102 }
103
104 if err := (configSettingsStore{}).SetFastMode(true); err != nil {
105 t.Fatal(err)
106 }
107 cfg, err := LoadConfig()
108 if err != nil {
109 t.Fatal(err)
110 }
111 if cfg.FastMode == nil || !*cfg.FastMode {
112 t.Fatalf("fast_mode = %v, want true", cfg.FastMode)
113 }
114 if cfg.Theme != "dark" {
115 t.Fatalf("unrelated config changed: theme = %q, want dark", cfg.Theme)
116 }
117}
118
119func TestFastModeConfigJSONUsesSnakeCase(t *testing.T) {
120 enabled := true
121 data, err := json.Marshal(Config{FastMode: &enabled})
122 if err != nil {
123 t.Fatal(err)
124 }
125 if !strings.Contains(string(data), `"fast_mode":true`) {
126 t.Fatalf("config JSON = %s, want fast_mode", data)
127 }
128}
129
130func TestResolvedOllamaClientRejectsFastMode(t *testing.T) {
131 client := (Resolved{
132 Provider: "ollama",
133 Credential: "ollama",
134 BaseURL: "http://localhost:11434",
135 }).NewClient()
136 if client.Name() != "ollama" {
137 t.Fatalf("client name = %q, want ollama", client.Name())
138 }
139 _, err := client.Stream(context.Background(), provider.Request{Model: "local", FastMode: true})
140 if err == nil || !strings.Contains(err.Error(), "only supported for OpenAI providers") {
141 t.Fatalf("Stream error = %v, want unsupported-provider error", err)
142 }
143}