@team-agent/installer 0.5.106 → 0.5.108

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/adapters.rs +1 -1
  4. package/crates/team-agent/src/cli/emit.rs +3 -3
  5. package/crates/team-agent/src/cli/mod.rs +87 -4
  6. package/crates/team-agent/src/cli/models.rs +252 -3
  7. package/crates/team-agent/src/cli/spec.rs +1 -1
  8. package/crates/team-agent/src/cli/status_port/brief.rs +155 -37
  9. package/crates/team-agent/src/cli/tests/base.rs +112 -225
  10. package/crates/team-agent/src/cli/tests/shutdown_kill_plan.rs +184 -0
  11. package/crates/team-agent/src/cli/tests/status_brief.rs +624 -0
  12. package/crates/team-agent/src/compiler/tests.rs +46 -59
  13. package/crates/team-agent/src/leader/tests/byte_findings.rs +1 -14
  14. package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +57 -173
  15. package/crates/team-agent/src/lifecycle/launch/pi_mcp_extension.js +226 -0
  16. package/crates/team-agent/src/lifecycle/launch/quick_start.rs +0 -37
  17. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +0 -9
  18. package/crates/team-agent/src/lifecycle/tests/fixtures/pi_native_mcp_host.mjs +71 -0
  19. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +0 -66
  20. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +0 -392
  21. package/crates/team-agent/src/lifecycle/tests/lifecycle_lock.rs +0 -5
  22. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +2 -361
  23. package/crates/team-agent/src/lifecycle/tests/pi_dual_entry_red.rs +1 -16
  24. package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +20 -112
  25. package/crates/team-agent/src/lifecycle/tests/pi_fork_session_inheritance_red.rs +1 -12
  26. package/crates/team-agent/src/lifecycle/tests/pi_native_mcp_capability_red.rs +546 -0
  27. package/crates/team-agent/src/lifecycle/tests.rs +1 -0
  28. package/crates/team-agent/src/lifecycle/worker_command_context.rs +11 -54
  29. package/crates/team-agent/src/messaging/tests/wave2.rs +2 -302
  30. package/crates/team-agent/src/model/name_similarity.rs +52 -67
  31. package/crates/team-agent/src/model/task_graph.rs +37 -124
  32. package/crates/team-agent/src/model/yaml/tests.rs +46 -165
  33. package/crates/team-agent/src/provider/model_catalog.rs +166 -3
  34. package/crates/team-agent/src/provider/testdata/cursor-list-models-native.stdout +250 -0
  35. package/crates/team-agent/src/provider/testdata/grok-models-authenticated.stdout +9 -0
  36. package/crates/team-agent/src/provider/testdata/grok-models-unauthenticated.stdout +7 -0
  37. package/crates/team-agent/src/provider/tests/adapter.rs +0 -20
  38. package/crates/team-agent/src/provider/tests/classify.rs +106 -198
  39. package/crates/team-agent/src/tmux_backend/tests.rs +178 -501
  40. package/crates/team-agent/src/transport/tests/wire.rs +0 -55
  41. package/package.json +4 -4
@@ -0,0 +1,250 @@
1
+ Available models
2
+
3
+ auto - Auto (default)
4
+ gpt-5.3-codex-low - Codex 5.3 Low
5
+ gpt-5.3-codex-low-fast - Codex 5.3 Low Fast
6
+ gpt-5.3-codex - Codex 5.3
7
+ gpt-5.3-codex-fast - Codex 5.3 Fast
8
+ gpt-5.3-codex-high - Codex 5.3 High
9
+ gpt-5.3-codex-high-fast - Codex 5.3 High Fast
10
+ gpt-5.3-codex-xhigh - Codex 5.3 Extra High
11
+ gpt-5.3-codex-xhigh-fast - Codex 5.3 Extra High Fast
12
+ gpt-5.2 - GPT-5.2
13
+ composer-2.5 - Composer 2.5
14
+ claude-opus-5-thinking-high - Claude Opus 5 1M Thinking
15
+ claude-opus-5-thinking-high-fast - Claude Opus 5 1M Thinking Fast
16
+ gpt-5.6-sol-high - GPT-5.6 Sol 1M High
17
+ gpt-5.6-sol-high-fast - GPT-5.6 Sol 1M High Fast
18
+ gpt-5.6-sol-xhigh - GPT-5.6 Sol 1M Extra High
19
+ gpt-5.6-sol-xhigh-fast - GPT-5.6 Sol 1M Extra High Fast
20
+ claude-fable-5-thinking-high - Claude Fable 5 1M Thinking (NO ZDR)
21
+ claude-fable-5-thinking-xhigh - Claude Fable 5 1M Extra High Thinking (NO ZDR)
22
+ cursor-grok-4.5-high - Grok 4.5
23
+ cursor-grok-4.5-high-fast - Grok 4.5 Fast
24
+ gemini-3.7-flash-high - Gemini 3.7 Flash
25
+ claude-sonnet-5-thinking-high - Claude Sonnet 5 1M Thinking
26
+ claude-sonnet-5-thinking-xhigh - Claude Sonnet 5 1M Extra High Thinking
27
+ gpt-5.6-luna-high - GPT-5.6 Luna 1M High
28
+ grok-4.7-low - Grok 4.7 Low
29
+ grok-4.7-low-fast - Grok 4.7 Low Fast​​
30
+ grok-4.7-medium - Grok 4.7 Medium
31
+ grok-4.7-medium-fast - Grok 4.7 Medium Fast​​
32
+ grok-4.7-high - Grok 4.7 High
33
+ grok-4.7-high-fast - Grok 4.7 High Fast​​
34
+ grok-4.7-xhigh - Grok 4.7 Extra High
35
+ grok-4.7-xhigh-fast - Grok 4.7 Extra High Fast​​
36
+ cursor-grok-4.6-low - Grok 4.6 Low
37
+ cursor-grok-4.6-low-fast - Grok 4.6 Low Fast
38
+ cursor-grok-4.6-medium - Grok 4.6 Medium
39
+ cursor-grok-4.6-medium-fast - Grok 4.6 Medium Fast
40
+ cursor-grok-4.6-high - Grok 4.6
41
+ cursor-grok-4.6-high-fast - Grok 4.6 Fast
42
+ cursor-grok-4.6-xhigh - Grok 4.6 Extra High
43
+ cursor-grok-4.6-xhigh-fast - Grok 4.6 Extra High Fast
44
+ composer-2.5-fast - Composer 2.5 Fast
45
+ claude-opus-5-5-low - Claude Opus 5.5 1M Low
46
+ claude-opus-5-5-low-fast - Claude Opus 5.5 1M Low Fast
47
+ claude-opus-5-5-medium - Claude Opus 5.5 1M
48
+ claude-opus-5-5-medium-fast - Claude Opus 5.5 1M Fast
49
+ claude-opus-5-5-high - Claude Opus 5.5 1M High
50
+ claude-opus-5-5-high-fast - Claude Opus 5.5 1M High Fast
51
+ claude-opus-5-5-xhigh - Claude Opus 5.5 1M Extra High
52
+ claude-opus-5-5-xhigh-fast - Claude Opus 5.5 1M Extra High Fast
53
+ claude-opus-5-5-max - Claude Opus 5.5 1M Max
54
+ claude-opus-5-5-max-fast - Claude Opus 5.5 1M Max Fast
55
+ claude-opus-5-low - Claude Opus 5 1M Low
56
+ claude-opus-5-low-fast - Claude Opus 5 1M Low Fast
57
+ claude-opus-5-medium - Claude Opus 5 1M Medium
58
+ claude-opus-5-medium-fast - Claude Opus 5 1M Medium Fast
59
+ claude-opus-5-high - Claude Opus 5 1M
60
+ claude-opus-5-high-fast - Claude Opus 5 1M Fast
61
+ claude-opus-5-thinking-low - Claude Opus 5 1M Low Thinking
62
+ claude-opus-5-thinking-low-fast - Claude Opus 5 1M Low Thinking Fast
63
+ claude-opus-5-thinking-medium - Claude Opus 5 1M Medium Thinking
64
+ claude-opus-5-thinking-medium-fast - Claude Opus 5 1M Medium Thinking Fast
65
+ claude-opus-5-thinking-xhigh - Claude Opus 5 1M Extra High Thinking
66
+ claude-opus-5-thinking-xhigh-fast - Claude Opus 5 1M Extra High Thinking Fast
67
+ claude-opus-5-thinking-max - Claude Opus 5 1M Max Thinking
68
+ claude-opus-5-thinking-max-fast - Claude Opus 5 1M Max Thinking Fast
69
+ claude-opus-4-8-low - Claude Opus 4.8 1M Low
70
+ claude-opus-4-8-low-fast - Claude Opus 4.8 1M Low Fast
71
+ claude-opus-4-8-medium - Claude Opus 4.8 1M Medium
72
+ claude-opus-4-8-medium-fast - Claude Opus 4.8 1M Medium Fast
73
+ claude-opus-4-8-high - Claude Opus 4.8 1M
74
+ claude-opus-4-8-high-fast - Claude Opus 4.8 1M Fast
75
+ claude-opus-4-8-xhigh - Claude Opus 4.8 1M Extra High
76
+ claude-opus-4-8-xhigh-fast - Claude Opus 4.8 1M Extra High Fast
77
+ claude-opus-4-8-max - Claude Opus 4.8 1M Max
78
+ claude-opus-4-8-max-fast - Claude Opus 4.8 1M Max Fast
79
+ claude-opus-4-8-thinking-low - Claude Opus 4.8 1M Low Thinking
80
+ claude-opus-4-8-thinking-low-fast - Claude Opus 4.8 1M Low Thinking Fast
81
+ claude-opus-4-8-thinking-medium - Claude Opus 4.8 1M Medium Thinking
82
+ claude-opus-4-8-thinking-medium-fast - Claude Opus 4.8 1M Medium Thinking Fast
83
+ claude-opus-4-8-thinking-high - Claude Opus 4.8 1M Thinking
84
+ claude-opus-4-8-thinking-high-fast - Claude Opus 4.8 1M Thinking Fast
85
+ claude-opus-4-8-thinking-xhigh - Claude Opus 4.8 1M Extra High Thinking
86
+ claude-opus-4-8-thinking-xhigh-fast - Claude Opus 4.8 1M Extra High Thinking Fast
87
+ claude-opus-4-8-thinking-max - Claude Opus 4.8 1M Max Thinking
88
+ claude-opus-4-8-thinking-max-fast - Claude Opus 4.8 1M Max Thinking Fast
89
+ gpt-5.6-sol-none - GPT-5.6 Sol 1M None
90
+ gpt-5.6-sol-none-fast - GPT-5.6 Sol 1M None Fast
91
+ gpt-5.6-sol-low - GPT-5.6 Sol 1M Low
92
+ gpt-5.6-sol-low-fast - GPT-5.6 Sol 1M Low Fast
93
+ gpt-5.6-sol-medium - GPT-5.6 Sol 1M
94
+ gpt-5.6-sol-medium-fast - GPT-5.6 Sol 1M Fast
95
+ gpt-5.6-sol-max - GPT-5.6 Sol 1M Max
96
+ gpt-5.6-sol-max-fast - GPT-5.6 Sol 1M Max Fast
97
+ gpt-5.5-none - GPT-5.5 1M None
98
+ gpt-5.5-none-fast - GPT-5.5 None Fast
99
+ gpt-5.5-low - GPT-5.5 1M Low
100
+ gpt-5.5-low-fast - GPT-5.5 Low Fast
101
+ gpt-5.5-medium - GPT-5.5 1M
102
+ gpt-5.5-medium-fast - GPT-5.5 Fast
103
+ gpt-5.5-high - GPT-5.5 1M High
104
+ gpt-5.5-high-fast - GPT-5.5 High Fast
105
+ gpt-5.5-extra-high - GPT-5.5 1M Extra High
106
+ gpt-5.5-extra-high-fast - GPT-5.5 Extra High Fast
107
+ claude-fable-5-1-low - Claude Fable 5.1 1M Low (NO ZDR)
108
+ claude-fable-5-1-medium - Claude Fable 5.1 1M Medium (NO ZDR)
109
+ claude-fable-5-1-high - Claude Fable 5.1 1M (NO ZDR)
110
+ claude-fable-5-1-xhigh - Claude Fable 5.1 1M Extra High (NO ZDR)
111
+ claude-fable-5-1-max - Claude Fable 5.1 1M Max (NO ZDR)
112
+ claude-fable-5-1-thinking-low - Claude Fable 5.1 1M Low Thinking (NO ZDR)
113
+ claude-fable-5-1-thinking-medium - Claude Fable 5.1 1M Medium Thinking (NO ZDR)
114
+ claude-fable-5-1-thinking-high - Claude Fable 5.1 1M Thinking (NO ZDR)
115
+ claude-fable-5-1-thinking-xhigh - Claude Fable 5.1 1M Extra High Thinking (NO ZDR)
116
+ claude-fable-5-1-thinking-max - Claude Fable 5.1 1M Max Thinking (NO ZDR)
117
+ claude-fable-5-low - Claude Fable 5 1M Low (NO ZDR)
118
+ claude-fable-5-medium - Claude Fable 5 1M Medium (NO ZDR)
119
+ claude-fable-5-high - Claude Fable 5 1M (NO ZDR)
120
+ claude-fable-5-xhigh - Claude Fable 5 1M Extra High (NO ZDR)
121
+ claude-fable-5-max - Claude Fable 5 1M Max (NO ZDR)
122
+ claude-fable-5-thinking-low - Claude Fable 5 1M Low Thinking (NO ZDR)
123
+ claude-fable-5-thinking-medium - Claude Fable 5 1M Medium Thinking (NO ZDR)
124
+ claude-fable-5-thinking-max - Claude Fable 5 1M Max Thinking (NO ZDR)
125
+ cursor-grok-4.5-low - Grok 4.5 Low
126
+ cursor-grok-4.5-low-fast - Grok 4.5 Low Fast
127
+ cursor-grok-4.5-medium - Grok 4.5 Medium
128
+ cursor-grok-4.5-medium-fast - Grok 4.5 Medium Fast
129
+ gemini-3.8-flash-low - Gemini 3.8 Flash Low
130
+ gemini-3.8-flash-medium - Gemini 3.8 Flash Medium
131
+ gemini-3.8-flash-high - Gemini 3.8 Flash High
132
+ gemini-3.7-flash-low - Gemini 3.7 Flash Low
133
+ gemini-3.7-flash-medium - Gemini 3.7 Flash Medium
134
+ muse-spark-1.3-minimal - Muse Spark 1.3 1M Minimal
135
+ muse-spark-1.3-low - Muse Spark 1.3 1M Low
136
+ muse-spark-1.3-medium - Muse Spark 1.3 1M Medium
137
+ muse-spark-1.3-high - Muse Spark 1.3 1M
138
+ muse-spark-1.3-xhigh - Muse Spark 1.3 1M Extra High
139
+ muse-spark-1.3-max - Muse Spark 1.3 1M Max
140
+ gpt-5.6-terra-none - GPT-5.6 Terra 1M None
141
+ gpt-5.6-terra-none-fast - GPT-5.6 Terra 1M None Fast
142
+ gpt-5.6-terra-low - GPT-5.6 Terra 1M Low
143
+ gpt-5.6-terra-low-fast - GPT-5.6 Terra 1M Low Fast
144
+ gpt-5.6-terra-medium - GPT-5.6 Terra 1M
145
+ gpt-5.6-terra-medium-fast - GPT-5.6 Terra 1M Fast
146
+ gpt-5.6-terra-high - GPT-5.6 Terra 1M High
147
+ gpt-5.6-terra-high-fast - GPT-5.6 Terra 1M High Fast
148
+ gpt-5.6-terra-xhigh - GPT-5.6 Terra 1M Extra High
149
+ gpt-5.6-terra-xhigh-fast - GPT-5.6 Terra 1M Extra High Fast
150
+ gpt-5.6-terra-max - GPT-5.6 Terra 1M Max
151
+ gpt-5.6-terra-max-fast - GPT-5.6 Terra 1M Max Fast
152
+ claude-sonnet-5-5-low - Claude Sonnet 5.5 Low
153
+ claude-sonnet-5-5-medium - Claude Sonnet 5.5 Medium
154
+ claude-sonnet-5-5-high - Claude Sonnet 5.5 High
155
+ claude-sonnet-5-5-xhigh - Claude Sonnet 5.5 Extra High
156
+ claude-sonnet-5-5-max - Claude Sonnet 5.5 Max
157
+ claude-sonnet-5-low - Claude Sonnet 5 1M Low
158
+ claude-sonnet-5-medium - Claude Sonnet 5 1M Medium
159
+ claude-sonnet-5-high - Claude Sonnet 5 1M
160
+ claude-sonnet-5-xhigh - Claude Sonnet 5 1M Extra High
161
+ claude-sonnet-5-max - Claude Sonnet 5 1M Max
162
+ claude-sonnet-5-thinking-low - Claude Sonnet 5 1M Low Thinking
163
+ claude-sonnet-5-thinking-medium - Claude Sonnet 5 1M Medium Thinking
164
+ claude-sonnet-5-thinking-max - Claude Sonnet 5 1M Max Thinking
165
+ claude-4.6-sonnet-medium - Claude Sonnet 4.6 1M
166
+ claude-4.6-sonnet-medium-thinking - Claude Sonnet 4.6 1M Thinking
167
+ claude-opus-4-7-low - Claude Opus 4.7 1M Low
168
+ claude-opus-4-7-low-fast - Claude Opus 4.7 1M Low Fast
169
+ claude-opus-4-7-medium - Claude Opus 4.7 1M Medium
170
+ claude-opus-4-7-medium-fast - Claude Opus 4.7 1M Medium Fast
171
+ claude-opus-4-7-high - Claude Opus 4.7 1M High
172
+ claude-opus-4-7-high-fast - Claude Opus 4.7 1M High Fast
173
+ claude-opus-4-7-xhigh - Claude Opus 4.7 1M
174
+ claude-opus-4-7-xhigh-fast - Claude Opus 4.7 1M Fast
175
+ claude-opus-4-7-max - Claude Opus 4.7 1M Max
176
+ claude-opus-4-7-max-fast - Claude Opus 4.7 1M Max Fast
177
+ claude-opus-4-7-thinking-low - Claude Opus 4.7 1M Low Thinking
178
+ claude-opus-4-7-thinking-low-fast - Claude Opus 4.7 1M Low Thinking Fast
179
+ claude-opus-4-7-thinking-medium - Claude Opus 4.7 1M Medium Thinking
180
+ claude-opus-4-7-thinking-medium-fast - Claude Opus 4.7 1M Medium Thinking Fast
181
+ claude-opus-4-7-thinking-high - Claude Opus 4.7 1M High Thinking
182
+ claude-opus-4-7-thinking-high-fast - Claude Opus 4.7 1M High Thinking Fast
183
+ claude-opus-4-7-thinking-xhigh - Claude Opus 4.7 1M Thinking
184
+ claude-opus-4-7-thinking-xhigh-fast - Claude Opus 4.7 1M Thinking Fast
185
+ claude-opus-4-7-thinking-max - Claude Opus 4.7 1M Max Thinking
186
+ claude-opus-4-7-thinking-max-fast - Claude Opus 4.7 1M Max Thinking Fast
187
+ gpt-5.4-low - GPT-5.4 1M Low
188
+ gpt-5.4-medium - GPT-5.4 1M
189
+ gpt-5.4-medium-fast - GPT-5.4 Fast
190
+ gpt-5.4-high - GPT-5.4 1M High
191
+ gpt-5.4-high-fast - GPT-5.4 High Fast
192
+ gpt-5.4-xhigh - GPT-5.4 1M Extra High
193
+ gpt-5.4-xhigh-fast - GPT-5.4 Extra High Fast
194
+ claude-4.6-opus-high - Claude Opus 4.6 1M
195
+ claude-4.6-opus-max - Claude Opus 4.6 1M Max
196
+ claude-4.6-opus-high-thinking - Claude Opus 4.6 1M Thinking
197
+ claude-4.6-opus-max-thinking - Claude Opus 4.6 1M Max Thinking
198
+ claude-4.5-opus-high - Claude Opus 4.5
199
+ claude-4.5-opus-high-thinking - Claude Opus 4.5 Thinking
200
+ gpt-5.2-low - GPT-5.2 Low
201
+ gpt-5.2-low-fast - GPT-5.2 Low Fast
202
+ gpt-5.2-fast - GPT-5.2 Fast
203
+ gpt-5.2-high - GPT-5.2 High
204
+ gpt-5.2-high-fast - GPT-5.2 High Fast
205
+ gpt-5.2-xhigh - GPT-5.2 Extra High
206
+ gpt-5.2-xhigh-fast - GPT-5.2 Extra High Fast
207
+ gpt-5.6-luna-none - GPT-5.6 Luna 1M None
208
+ gpt-5.6-luna-none-fast - GPT-5.6 Luna 1M None Fast
209
+ gpt-5.6-luna-low - GPT-5.6 Luna 1M Low (current)
210
+ gpt-5.6-luna-low-fast - GPT-5.6 Luna 1M Low Fast
211
+ gpt-5.6-luna-medium - GPT-5.6 Luna 1M
212
+ gpt-5.6-luna-medium-fast - GPT-5.6 Luna 1M Fast
213
+ gpt-5.6-luna-high-fast - GPT-5.6 Luna 1M High Fast
214
+ gpt-5.6-luna-xhigh - GPT-5.6 Luna 1M Extra High
215
+ gpt-5.6-luna-xhigh-fast - GPT-5.6 Luna 1M Extra High Fast
216
+ gpt-5.6-luna-max - GPT-5.6 Luna 1M Max
217
+ gpt-5.6-luna-max-fast - GPT-5.6 Luna 1M Max Fast
218
+ gemini-3.6-flash-minimal - Gemini 3.6 Flash Minimal
219
+ gemini-3.6-flash-low - Gemini 3.6 Flash Low
220
+ gemini-3.6-flash-medium - Gemini 3.6 Flash Medium
221
+ gemini-3.6-flash-high - Gemini 3.6 Flash
222
+ gemini-3.1-pro - Gemini 3.1 Pro
223
+ gpt-5.4-mini-none - GPT-5.4 Mini None
224
+ gpt-5.4-mini-low - GPT-5.4 Mini Low
225
+ gpt-5.4-mini-medium - GPT-5.4 Mini
226
+ gpt-5.4-mini-high - GPT-5.4 Mini High
227
+ gpt-5.4-mini-xhigh - GPT-5.4 Mini Extra High
228
+ gpt-5.4-nano-none - GPT-5.4 Nano None
229
+ gpt-5.4-nano-low - GPT-5.4 Nano Low
230
+ gpt-5.4-nano-medium - GPT-5.4 Nano
231
+ gpt-5.4-nano-high - GPT-5.4 Nano High
232
+ gpt-5.4-nano-xhigh - GPT-5.4 Nano Extra High
233
+ claude-4.5-sonnet - Claude Sonnet 4.5
234
+ claude-4.5-sonnet-thinking - Claude Sonnet 4.5 Thinking
235
+ gpt-5.1-low - GPT-5.1 Low
236
+ gpt-5.1 - GPT-5.1
237
+ gpt-5.1-high - GPT-5.1 High
238
+ gemini-3-flash - Gemini 3 Flash
239
+ gemini-3.5-flash - Gemini 3.5 Flash
240
+ claude-4-sonnet - Claude Sonnet 4
241
+ claude-4-sonnet-thinking - Claude Sonnet 4 Thinking
242
+ gpt-5-mini - GPT-5 Mini
243
+ kimi-k3-low - Kimi K3 Low
244
+ kimi-k3-high - Kimi K3 High
245
+ kimi-k3-max - Kimi K3
246
+ kimi-k2.7-code - Kimi K2.7 Code
247
+ glm-5.2-high - GLM 5.2
248
+ glm-5.2-max - GLM 5.2 Max
249
+
250
+ Tip: use --model <id> (or /model <id> in interactive mode) to switch. Parameterized models also accept quoted overrides, e.g. --model 'claude-opus-4-8[context=1m,effort=high,fast=false]'.
@@ -0,0 +1,9 @@
1
+ You are logged in with grok.com.
2
+
3
+ Default model: grok-4.6
4
+
5
+ Available models:
6
+ - grok-4.7
7
+ - grok-4.7-build-fast
8
+ - grok-4.5
9
+ * grok-4.6 (default)
@@ -0,0 +1,7 @@
1
+ You are not authenticated.
2
+
3
+ Default model: grok-4.7
4
+
5
+ Available models:
6
+ * grok-4.7 (default)
7
+ - grok-4.6
@@ -403,26 +403,6 @@ fn test_cursor_agent_accepts_mcp_config_without_putting_it_on_argv() {
403
403
  );
404
404
  }
405
405
 
406
- #[test]
407
- fn test_cursor_agent_refuses_mcp_config_loudly() {
408
- // 已废除的行为:旧实现收到 mcp_config 就返回 CapabilityUnsupported
409
- // (「MCP is not implemented」),此断言证明它确实没了。
410
- let adapter = get_adapter(Provider::CursorAgent);
411
- let cfg = McpConfig {
412
- raw: serde_json::json!({
413
- "team_orchestrator": {
414
- "command": "/bin/team-agent",
415
- "args": ["mcp-server"]
416
- }
417
- }),
418
- };
419
- let result = adapter.build_command(AuthMode::Subscription, Some(&cfg), None, None);
420
- assert!(
421
- !matches!(result, Err(ProviderError::CapabilityUnsupported(_))),
422
- "feeding mcp_config must not return CapabilityUnsupported; got {result:?}"
423
- );
424
- }
425
-
426
406
  #[test]
427
407
  fn test_grok_build_command_plan_binds_expected_session_id_to_argv() {
428
408
  let adapter = get_adapter(Provider::Grok);
@@ -6,53 +6,113 @@ fn claude_open_turn() -> String {
6
6
  }
7
7
 
8
8
  #[test]
9
- fn classify_empty_text_is_unknown_never_idle() {
10
- // probe empty_text: state=unknown turn_id=None reason=unreadable_or_empty
11
- // source=session_file. BLOOD-LINE: unknown is NEVER idle (bug-071/077/085).
12
- let c = classify(Provider::ClaudeCode, "", ProcessLiveness::Unverifiable, 0.0)
13
- .expect("classify ok");
14
- assert_eq!(c.state, TurnState::Unknown);
15
- assert_eq!(c.reason, "unreadable_or_empty");
16
- assert_eq!(c.turn_id, None);
17
- assert_eq!(c.source, ClassifySource::SessionFile);
18
- // The pin the audit demands: classify(unreadable) MUST NOT be treatable as idle.
19
- assert!(
20
- !c.state.is_idle_for_takeover(),
21
- "unreadable/empty input must never be idle (C5)"
9
+ fn classify_state_table() {
10
+ use ClassifySource::{ProcessGuard, SessionFile};
11
+ use ProcessLiveness::{Alive, Unverifiable};
12
+ use Provider::{Claude, ClaudeCode, Codex};
13
+ use TurnState::{Abnormal, BlockedOnHuman, Idle, IdleInterrupted, Unknown, Working};
14
+
15
+ type Input<'a> = (Provider, &'a str, ProcessLiveness, f64);
16
+ // State, reason, turn ID, source, exact annotations, idle-for-takeover.
17
+ // None skips an originally absent assertion; Some(None) asserts no turn ID.
18
+ type Expected<'a> = (
19
+ TurnState, &'a str, Option<Option<&'a str>>, Option<ClassifySource>,
20
+ Option<&'a [&'a str]>, Option<bool>,
22
21
  );
23
- }
24
-
25
- #[test]
26
- fn classify_whitespace_only_is_unknown() {
27
- // probe whitespace_only → unknown / unreadable_or_empty.
28
- let c = classify(Provider::Claude, " \n \t \n", ProcessLiveness::Unverifiable, 0.0)
29
- .expect("classify ok");
30
- assert_eq!(c.state, TurnState::Unknown);
31
- assert_eq!(c.reason, "unreadable_or_empty");
32
- assert!(!c.state.is_idle_for_takeover());
33
- }
34
-
35
- #[test]
36
- fn classify_garbage_jsonl_is_unknown_not_idle() {
37
- // probe garbage_jsonl ("not json\n{broken"): parse yields diagnostics but
38
- // had_records=false → reason=unreadable_or_empty (the !had_records branch
39
- // wins over diagnostics; common.py:72-75). NEVER idle.
40
- let c = classify(Provider::Claude, "not json\n{broken", ProcessLiveness::Unverifiable, 0.0)
41
- .expect("classify ok");
42
- assert_eq!(c.state, TurnState::Unknown);
43
- assert_eq!(c.reason, "unreadable_or_empty");
44
- assert!(!c.state.is_idle_for_takeover());
45
- }
46
-
47
- #[test]
48
- fn classify_unrecognized_format_is_unknown() {
49
- // probe '{"foo":"bar"}': had_records=true, no lifecycle fact, NO diagnostics
50
- // → reason=no_turn_lifecycle_fact (NOT unrecognized_format — golden-confirmed).
51
- let c = classify(Provider::Claude, r#"{"foo":"bar"}"#, ProcessLiveness::Unverifiable, 0.0)
52
- .expect("classify ok");
53
- assert_eq!(c.state, TurnState::Unknown);
54
- assert_eq!(c.reason, "no_turn_lifecycle_fact");
55
- assert!(!c.state.is_idle_for_takeover());
22
+ let open = claude_open_turn();
23
+ let two = format!(
24
+ "{}\n{}",
25
+ r#"{"type":"assistant","requestId":"a","message":{"stop_reason":"tool_use"}}"#,
26
+ r#"{"type":"assistant","requestId":"b","message":{"stop_reason":"end_turn"}}"#,
27
+ );
28
+ let c14 = format!(
29
+ "{}\n{}",
30
+ r#"{"type":"assistant","requestId":"a","message":{"stop_reason":"end_turn"}}"#,
31
+ r#"{"type":"assistant","requestId":"b","message":{"stop_reason":"tool_use"}}"#,
32
+ );
33
+ let cases: &[(&str, Input<'_>, Expected<'_>)] = &[
34
+ // Unknown is NEVER idle (bug-071/077/085, C5).
35
+ ("empty",
36
+ (ClaudeCode, "", Unverifiable, 0.0),
37
+ (Unknown, "unreadable_or_empty", Some(None), Some(SessionFile), None, Some(false))),
38
+ ("whitespace",
39
+ (Claude, " \n \t \n", Unverifiable, 0.0),
40
+ (Unknown, "unreadable_or_empty", None, None, None, Some(false))),
41
+ // !had_records wins over parse diagnostics (common.py:72-75).
42
+ ("garbage_jsonl",
43
+ (Claude, "not json\n{broken", Unverifiable, 0.0),
44
+ (Unknown, "unreadable_or_empty", None, None, None, Some(false))),
45
+ // Valid record without lifecycle facts: NOT unrecognized_format.
46
+ ("unrecognized_record",
47
+ (Claude, r#"{"foo":"bar"}"#, Unverifiable, 0.0),
48
+ (Unknown, "no_turn_lifecycle_fact", None, None, None, Some(false))),
49
+ // C4: missing process identity is NEVER optimistically working.
50
+ ("open_unverifiable_identity",
51
+ (Claude, &open, Unverifiable, 0.0),
52
+ (Unknown, "process_identity_unverified", Some(Some("r1")), Some(ProcessGuard), None, Some(false))),
53
+ ("open_alive",
54
+ (Claude, &open, Alive, 0.0),
55
+ (Working, "open_turn", Some(Some("r1")), Some(SessionFile), None, None)),
56
+ ("open_unverifiable_process",
57
+ (Claude, &open, Unverifiable, 0.0),
58
+ (Unknown, "process_identity_unverified", None, None, None, Some(false))),
59
+ ("last_fact_wins",
60
+ (Claude, &two, Unverifiable, 0.0),
61
+ (Idle, "end_turn", Some(Some("b")), None, None, None)),
62
+ // C14: silence is discarded; only a dead process can demote an open turn.
63
+ ("open_beats_silence",
64
+ (Claude, &c14, Alive, 9999.0),
65
+ (Working, "open_turn", Some(Some("b")), None, None, None)),
66
+ // C12: idle_interrupted IS idle for take-over, with exact annotations.
67
+ ("claude_interrupted",
68
+ (Claude, r#"{"type":"user","uuid":"u1","message":{"content":[{"type":"text","text":"[Request interrupted by user]"}]}}"#, Unverifiable, 0.0),
69
+ (IdleInterrupted, "user_interrupt", Some(Some("u1")), None, Some(&["interrupted"]), Some(true))),
70
+ ("claude_stop_sequence",
71
+ (Claude, r#"{"type":"assistant","requestId":"r1","message":{"stop_reason":"stop_sequence"}}"#, Unverifiable, 0.0),
72
+ (Idle, "stop_sequence", None, None, None, None)),
73
+ ("codex_task_complete",
74
+ (Codex, r#"{"type":"event_msg","payload":{"type":"task_complete","turn_id":"ct1"}}"#, Unverifiable, 0.0),
75
+ (Idle, "task_complete", Some(Some("ct1")), None, None, None)),
76
+ ("codex_abort_interrupted",
77
+ (Codex, r#"{"type":"event_msg","payload":{"type":"turn_aborted","turn_id":"ct2","reason":"interrupted"}}"#, Unverifiable, 0.0),
78
+ (IdleInterrupted, "interrupted", None, None, None, None)),
79
+ // Raw abort reason must pass through, including non-interrupted errors.
80
+ ("codex_abort_error",
81
+ (Codex, r#"{"type":"event_msg","payload":{"type":"turn_aborted","turn_id":"ct3","reason":"error"}}"#, Unverifiable, 0.0),
82
+ (IdleInterrupted, "error", Some(Some("ct3")), None, None, None)),
83
+ ("codex_turn_failed",
84
+ (Codex, r#"{"jsonrpc":"2.0","method":"turn/completed","params":{"turn":{"id":"ct4","status":"failed"}}}"#, Unverifiable, 0.0),
85
+ (Abnormal, "turn_failed", Some(Some("ct4")), None, Some(&["turn_failed"]), Some(false))),
86
+ // blocked_on_human is NOT idle for take-over.
87
+ ("codex_approval",
88
+ (Codex, r#"{"jsonrpc":"2.0","method":"session/requestApproval","params":{"turnId":"ct5"}}"#, Unverifiable, 0.0),
89
+ (BlockedOnHuman, "approval_required", Some(Some("ct5")), None, Some(&["awaiting_approval"]), Some(false))),
90
+ ];
91
+ for &(id, (provider, text, liveness, silence), expected) in cases {
92
+ let c = classify(provider, text, liveness, silence)
93
+ .unwrap_or_else(|err| panic!("{id}: classify failed: {err:?}"));
94
+ let (state, reason, turn_id, source, annotations, idle) = expected;
95
+ let note = match id {
96
+ "empty" => "unreadable/empty input must never be idle (C5)",
97
+ "codex_abort_error" => "raw abort reason must pass through",
98
+ _ => "",
99
+ };
100
+ assert_eq!(c.state, state, "{id}: state");
101
+ assert_eq!(c.reason, reason, "{id}: reason; {note}");
102
+ if let Some(turn_id) = turn_id {
103
+ assert_eq!(c.turn_id.as_ref().map(TurnId::as_str), turn_id, "{id}: turn ID");
104
+ }
105
+ if let Some(source) = source {
106
+ assert_eq!(c.source, source, "{id}: source");
107
+ }
108
+ if let Some(annotations) = annotations {
109
+ let actual: Vec<_> = c.annotations.iter().map(String::as_str).collect();
110
+ assert_eq!(actual.as_slice(), annotations, "{id}: exact annotations");
111
+ }
112
+ if let Some(idle) = idle {
113
+ assert_eq!(c.state.is_idle_for_takeover(), idle, "{id}: idle-for-takeover; {note}");
114
+ }
115
+ }
56
116
  }
57
117
 
58
118
  #[test]
@@ -69,31 +129,6 @@ fn classify_claude_code_alias_normalizes_to_claude_reader() {
69
129
  assert_eq!(alias, canon, "claude_code must normalize to the claude reader");
70
130
  }
71
131
 
72
- #[test]
73
- fn classify_open_turn_with_no_process_is_unknown_not_working() {
74
- // probe open_turn_process_none: open turn + Unverifiable (None process) →
75
- // unknown / process_identity_unverified / source=process_guard, turn_id=r1.
76
- // C4: missing identity is NEVER optimistically working.
77
- let c = classify(Provider::Claude, &claude_open_turn(), ProcessLiveness::Unverifiable, 0.0)
78
- .expect("classify ok");
79
- assert_eq!(c.state, TurnState::Unknown);
80
- assert_eq!(c.reason, "process_identity_unverified");
81
- assert_eq!(c.source, ClassifySource::ProcessGuard);
82
- assert_eq!(c.turn_id, Some(TurnId::new("r1")));
83
- assert!(!c.state.is_idle_for_takeover());
84
- }
85
-
86
- #[test]
87
- fn classify_open_turn_alive_is_working() {
88
- // probe open_turn_alive: open turn + Alive → working / open_turn / source=session_file.
89
- let c = classify(Provider::Claude, &claude_open_turn(), ProcessLiveness::Alive, 0.0)
90
- .expect("classify ok");
91
- assert_eq!(c.state, TurnState::Working);
92
- assert_eq!(c.reason, "open_turn");
93
- assert_eq!(c.source, ClassifySource::SessionFile);
94
- assert_eq!(c.turn_id, Some(TurnId::new("r1")));
95
- }
96
-
97
132
  #[test]
98
133
  fn classify_open_turn_dead_is_abnormal_crashed_mid_turn() {
99
134
  // probe open_turn_dead: open turn + Dead → abnormal / crashed_mid_turn /
@@ -106,133 +141,6 @@ fn classify_open_turn_dead_is_abnormal_crashed_mid_turn() {
106
141
  assert!(c.annotations.contains(&"crashed_mid_turn".to_string()));
107
142
  }
108
143
 
109
- #[test]
110
- fn classify_open_turn_unverifiable_process_is_unknown() {
111
- // probe open_turn_unverifiable: open turn + Unverifiable →
112
- // unknown / process_identity_unverified (NOT working). NEVER idle.
113
- let c = classify(Provider::Claude, &claude_open_turn(), ProcessLiveness::Unverifiable, 0.0)
114
- .expect("classify ok");
115
- assert_eq!(c.state, TurnState::Unknown);
116
- assert_eq!(c.reason, "process_identity_unverified");
117
- assert!(!c.state.is_idle_for_takeover());
118
- }
119
-
120
- #[test]
121
- fn classify_last_lifecycle_fact_wins() {
122
- // probe last_fact_wins_complete (tool_use 'a' then end_turn 'b') →
123
- // idle / end_turn, turn_id = the LAST lifecycle fact's id ("b").
124
- let two = format!(
125
- "{}\n{}",
126
- r#"{"type":"assistant","requestId":"a","message":{"stop_reason":"tool_use"}}"#,
127
- r#"{"type":"assistant","requestId":"b","message":{"stop_reason":"end_turn"}}"#,
128
- );
129
- let c = classify(Provider::Claude, &two, ProcessLiveness::Unverifiable, 0.0)
130
- .expect("classify ok");
131
- assert_eq!(c.state, TurnState::Idle);
132
- assert_eq!(c.reason, "end_turn");
133
- assert_eq!(c.turn_id, Some(TurnId::new("b")));
134
- }
135
-
136
- #[test]
137
- fn classify_c14_open_turn_beats_silence() {
138
- // probe c14_open_after_complete_alive (end_turn 'a' then tool_use 'b', alive,
139
- // file_silence=9999) → working / open_turn, turn_id="b". Silence is DISCARDED:
140
- // only a dead process guard can demote an open turn (common.py:93-103, C14).
141
- let c14 = format!(
142
- "{}\n{}",
143
- r#"{"type":"assistant","requestId":"a","message":{"stop_reason":"end_turn"}}"#,
144
- r#"{"type":"assistant","requestId":"b","message":{"stop_reason":"tool_use"}}"#,
145
- );
146
- let c = classify(Provider::Claude, &c14, ProcessLiveness::Alive, 9999.0)
147
- .expect("classify ok");
148
- assert_eq!(c.state, TurnState::Working);
149
- assert_eq!(c.reason, "open_turn");
150
- assert_eq!(c.turn_id, Some(TurnId::new("b")));
151
- }
152
-
153
- #[test]
154
- fn classify_claude_interrupted_is_idle_interrupted_annotated() {
155
- // probe claude_interrupted ("[Request interrupted by user]") →
156
- // idle_interrupted / user_interrupt / annotations=["interrupted"], turn_id=u1.
157
- let txt = r#"{"type":"user","uuid":"u1","message":{"content":[{"type":"text","text":"[Request interrupted by user]"}]}}"#;
158
- let c = classify(Provider::Claude, txt, ProcessLiveness::Unverifiable, 0.0)
159
- .expect("classify ok");
160
- assert_eq!(c.state, TurnState::IdleInterrupted);
161
- assert_eq!(c.reason, "user_interrupt");
162
- assert_eq!(c.annotations, vec!["interrupted".to_string()]);
163
- assert_eq!(c.turn_id, Some(TurnId::new("u1")));
164
- // C12: idle_interrupted IS idle for take-over (annotated).
165
- assert!(c.state.is_idle_for_takeover());
166
- }
167
-
168
- #[test]
169
- fn classify_claude_stop_sequence_is_idle() {
170
- // probe claude_stop_sequence → idle / stop_sequence.
171
- let txt = r#"{"type":"assistant","requestId":"r1","message":{"stop_reason":"stop_sequence"}}"#;
172
- let c = classify(Provider::Claude, txt, ProcessLiveness::Unverifiable, 0.0)
173
- .expect("classify ok");
174
- assert_eq!(c.state, TurnState::Idle);
175
- assert_eq!(c.reason, "stop_sequence");
176
- }
177
-
178
- #[test]
179
- fn classify_codex_task_complete_is_idle() {
180
- // probe codex_task_complete → idle / task_complete, turn_id from payload (ct1).
181
- let txt = r#"{"type":"event_msg","payload":{"type":"task_complete","turn_id":"ct1"}}"#;
182
- let c = classify(Provider::Codex, txt, ProcessLiveness::Unverifiable, 0.0)
183
- .expect("classify ok");
184
- assert_eq!(c.state, TurnState::Idle);
185
- assert_eq!(c.reason, "task_complete");
186
- assert_eq!(c.turn_id, Some(TurnId::new("ct1")));
187
- }
188
-
189
- #[test]
190
- fn classify_codex_turn_aborted_interrupted_is_idle_interrupted() {
191
- // probe codex_turn_aborted_interrupted → idle_interrupted / interrupted.
192
- let interrupted = r#"{"type":"event_msg","payload":{"type":"turn_aborted","turn_id":"ct2","reason":"interrupted"}}"#;
193
- let c = classify(Provider::Codex, interrupted, ProcessLiveness::Unverifiable, 0.0)
194
- .expect("classify ok");
195
- assert_eq!(c.state, TurnState::IdleInterrupted);
196
- assert_eq!(c.reason, "interrupted");
197
- // probe codex_turn_aborted_other (reason="error") → idle_interrupted with the
198
- // RAW reason string passed through ("error"), turn_id=ct3.
199
- let other = r#"{"type":"event_msg","payload":{"type":"turn_aborted","turn_id":"ct3","reason":"error"}}"#;
200
- let c2 = classify(Provider::Codex, other, ProcessLiveness::Unverifiable, 0.0)
201
- .expect("classify ok");
202
- assert_eq!(c2.state, TurnState::IdleInterrupted);
203
- assert_eq!(c2.reason, "error", "raw abort reason must pass through");
204
- assert_eq!(c2.turn_id, Some(TurnId::new("ct3")));
205
- }
206
-
207
- #[test]
208
- fn classify_codex_appserver_failed_is_abnormal() {
209
- // probe codex_appserver_failed (turn.status==failed) → abnormal / turn_failed /
210
- // annotations=["turn_failed"], source=session_file, turn_id=ct4.
211
- let txt = r#"{"jsonrpc":"2.0","method":"turn/completed","params":{"turn":{"id":"ct4","status":"failed"}}}"#;
212
- let c = classify(Provider::Codex, txt, ProcessLiveness::Unverifiable, 0.0)
213
- .expect("classify ok");
214
- assert_eq!(c.state, TurnState::Abnormal);
215
- assert_eq!(c.reason, "turn_failed");
216
- assert_eq!(c.annotations, vec!["turn_failed".to_string()]);
217
- assert_eq!(c.turn_id, Some(TurnId::new("ct4")));
218
- assert!(!c.state.is_idle_for_takeover());
219
- }
220
-
221
- #[test]
222
- fn classify_codex_appserver_approval_is_blocked_on_human() {
223
- // probe codex_appserver_approval (method endswith requestApproval) →
224
- // blocked_on_human / approval_required / annotations=["awaiting_approval"], turn_id=ct5.
225
- let txt = r#"{"jsonrpc":"2.0","method":"session/requestApproval","params":{"turnId":"ct5"}}"#;
226
- let c = classify(Provider::Codex, txt, ProcessLiveness::Unverifiable, 0.0)
227
- .expect("classify ok");
228
- assert_eq!(c.state, TurnState::BlockedOnHuman);
229
- assert_eq!(c.reason, "approval_required");
230
- assert_eq!(c.annotations, vec!["awaiting_approval".to_string()]);
231
- assert_eq!(c.turn_id, Some(TurnId::new("ct5")));
232
- // blocked_on_human is NOT idle for take-over.
233
- assert!(!c.state.is_idle_for_takeover());
234
- }
235
-
236
144
  // ---- (b) idle predicate / evaluate_takeover_reminder (NoPingReason cases) ----
237
145
  //
238
146
  // Golden via /tmp/probe_idle.py (idle_predicate.evaluate_takeover_reminder).