@team-agent/installer 0.5.64 → 0.5.66

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 (105) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/Cargo.toml +5 -0
  4. package/crates/team-agent/src/cli/adapters.rs +6 -1
  5. package/crates/team-agent/src/cli/emit.rs +15 -0
  6. package/crates/team-agent/src/cli/mod.rs +9 -8
  7. package/crates/team-agent/src/cli/send/presentation.rs +1 -0
  8. package/crates/team-agent/src/cli/spec.rs +3 -0
  9. package/crates/team-agent/src/cli/tests/compile.rs +1 -1
  10. package/crates/team-agent/src/cli/tests/mod.rs +33 -2
  11. package/crates/team-agent/src/cli/tests/run_delegation.rs +1 -1
  12. package/crates/team-agent/src/cli/tests/status_send.rs +13 -3
  13. package/crates/team-agent/src/cli/tests/verb_validate.rs +1 -1
  14. package/crates/team-agent/src/cli/types.rs +7 -0
  15. package/crates/team-agent/src/compiler/tests.rs +23 -20
  16. package/crates/team-agent/src/compiler.rs +25 -5
  17. package/crates/team-agent/src/conpty/backend.rs +16 -0
  18. package/crates/team-agent/src/coordinator/health.rs +17 -0
  19. package/crates/team-agent/src/coordinator/steps/abnormal.rs +55 -2
  20. package/crates/team-agent/src/db/migration.rs +2 -1
  21. package/crates/team-agent/src/db/schema.rs +16 -8
  22. package/crates/team-agent/src/leader/lease.rs +1 -2
  23. package/crates/team-agent/src/leader/start.rs +175 -10
  24. package/crates/team-agent/src/leader/tests/team_in_team_state_scope_red.rs +1 -1
  25. package/crates/team-agent/src/lifecycle/launch/add_agent.rs +0 -2
  26. package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +7 -2
  27. package/crates/team-agent/src/lifecycle/launch/agent_state.rs +137 -2
  28. package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +1 -2
  29. package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +5 -0
  30. package/crates/team-agent/src/lifecycle/launch/spawn.rs +39 -2
  31. package/crates/team-agent/src/lifecycle/launch/spec_state.rs +105 -48
  32. package/crates/team-agent/src/lifecycle/launch/state_projection.rs +0 -2
  33. package/crates/team-agent/src/lifecycle/launch.rs +117 -21
  34. package/crates/team-agent/src/lifecycle/restart/agent.rs +89 -3
  35. package/crates/team-agent/src/lifecycle/restart/common.rs +9 -12
  36. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +59 -15
  37. package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +1 -1
  38. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +4 -4
  39. package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +1 -1
  40. package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +2 -2
  41. package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +4 -4
  42. package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +24 -32
  43. package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +2 -2
  44. package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +13 -11
  45. package/crates/team-agent/src/lifecycle/tests/core.rs +0 -18
  46. package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +1 -1
  47. package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +1 -1
  48. package/crates/team-agent/src/lifecycle/tests/f032_startup_prompt_best_effort_red.rs +1 -1
  49. package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +3 -0
  50. package/crates/team-agent/src/lifecycle/tests/host_cotenant_death_p0_contract.rs +3 -3
  51. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +2 -2
  52. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +17 -30
  53. package/crates/team-agent/src/lifecycle/tests/lifecycle_rollback_red.rs +1 -1
  54. package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +4 -4
  55. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +1 -1
  56. package/crates/team-agent/src/lifecycle/tests/quick_start_worker_readiness_red.rs +2 -2
  57. package/crates/team-agent/src/lifecycle/tests/restart_build_before_destroy_0540_contract.rs +1 -1
  58. package/crates/team-agent/src/lifecycle/tests/restart_liveness_red.rs +1 -1
  59. package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +1 -1
  60. package/crates/team-agent/src/lifecycle/tests/restart_session_capture_red.rs +2 -2
  61. package/crates/team-agent/src/lifecycle/tests/resume_recover_red.rs +1 -1
  62. package/crates/team-agent/src/lifecycle/tests/stale_team_saveconflict_contract.rs +1 -1
  63. package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +11 -7
  64. package/crates/team-agent/src/lifecycle/tests/status_credential_redaction_contract.rs +3 -3
  65. package/crates/team-agent/src/lifecycle/tests/subprep_codex_trust_roundtrip_red.rs +1 -1
  66. package/crates/team-agent/src/lifecycle/tests/swallow_batch4_semantics_red.rs +1 -1
  67. package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +1 -1
  68. package/crates/team-agent/src/lifecycle/tests/team_in_team_sibling_quick_start_red.rs +1 -1
  69. package/crates/team-agent/src/lifecycle/tests/team_in_team_state_scope_red.rs +1 -1
  70. package/crates/team-agent/src/lifecycle/tests/team_key_retirement_txn_red.rs +1 -1
  71. package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +1 -1
  72. package/crates/team-agent/src/lifecycle/tests/upgrade_compat_0211_red.rs +1 -1
  73. package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +2 -2
  74. package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +1 -1
  75. package/crates/team-agent/src/lifecycle/tests.rs +11 -7
  76. package/crates/team-agent/src/lifecycle/types.rs +0 -2
  77. package/crates/team-agent/src/lifecycle/worker_command_context.rs +115 -22
  78. package/crates/team-agent/src/mcp_server/helpers.rs +1 -0
  79. package/crates/team-agent/src/messaging/delivery.rs +29 -0
  80. package/crates/team-agent/src/messaging/helpers.rs +2 -0
  81. package/crates/team-agent/src/messaging/leader_receiver.rs +12 -0
  82. package/crates/team-agent/src/messaging/mod.rs +2 -0
  83. package/crates/team-agent/src/messaging/results.rs +5 -0
  84. package/crates/team-agent/src/messaging/send.rs +9 -0
  85. package/crates/team-agent/src/messaging/tests/main_preserved.rs +1 -1
  86. package/crates/team-agent/src/messaging/tests/runtime.rs +32 -0
  87. package/crates/team-agent/src/messaging/types.rs +2 -0
  88. package/crates/team-agent/src/messaging/wait.rs +366 -0
  89. package/crates/team-agent/src/messaging/watchers.rs +153 -6
  90. package/crates/team-agent/src/model/spec.rs +129 -6
  91. package/crates/team-agent/src/model/testdata/spec_invalid_a.yaml +3 -1
  92. package/crates/team-agent/src/model/testdata/team.spec.golden.yaml +3 -1
  93. package/crates/team-agent/src/model/testdata/team.spec.yaml +3 -1
  94. package/crates/team-agent/src/provider/adapters/claude.rs +5 -2
  95. package/crates/team-agent/src/provider/adapters/codex.rs +5 -2
  96. package/crates/team-agent/src/provider/adapters/copilot.rs +5 -2
  97. package/crates/team-agent/src/provider/bypass_flags.rs +80 -0
  98. package/crates/team-agent/src/provider/mod.rs +2 -0
  99. package/crates/team-agent/src/tmux_backend.rs +35 -12
  100. package/crates/team-agent/src/transport/test_support.rs +20 -0
  101. package/crates/team-agent/src/transport.rs +28 -11
  102. package/package.json +4 -4
  103. package/crates/team-agent/src/lifecycle/launch/approval.rs +0 -134
  104. package/crates/team-agent/src/lifecycle/tests/codex_mcp_approval_inheritance_red.rs +0 -1187
  105. package/crates/team-agent/src/lifecycle/tests/worker_dangerous_bypass_argv_red.rs +0 -327
@@ -1,327 +0,0 @@
1
- //! Bug 4 RED: runtime.dangerous_auto_approve must reach real Codex worker argv.
2
- //!
3
- //! The provider adapter already knows how to emit the bypass flag. Fresh launch and
4
- //! restart must pass the same resolved safety/tool context into that adapter instead
5
- //! of falling back to restricted `--ask-for-approval on-request`.
6
-
7
- #![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
8
-
9
- #[path = "../../../tests/support/hermetic.rs"]
10
- mod hermetic_guard;
11
- #[allow(dead_code)]
12
- fn _hermetic_boundary_marker(_: &hermetic_guard::HermeticTestEnv) {}
13
-
14
- use std::collections::BTreeMap;
15
- use std::path::{Path, PathBuf};
16
- use std::sync::atomic::{AtomicU64, Ordering};
17
- use std::sync::Mutex;
18
-
19
- use serde_json::json;
20
- use team_agent::lifecycle::{launch_with_transport, restart_with_transport};
21
- use team_agent::provider::{get_adapter, AuthMode, Provider};
22
- use team_agent::transport::{
23
- AttachOutcome, BackendKind, CaptureRange, CapturedText, InjectPayload, InjectReport,
24
- InjectStage, InjectVerification, Key, PaneField, PaneId, PaneInfo, SessionName, SetEnvOutcome,
25
- SpawnResult, SubmitVerification, Target, Transport, TransportError, TurnVerification,
26
- WindowName,
27
- };
28
-
29
- const CODEX_BYPASS: &str = "--dangerously-bypass-approvals-and-sandbox";
30
-
31
- #[test]
32
- fn codex_bypass_argv_is_consistent_across_adapter_launch_and_restart() {
33
- let adapter = get_adapter(Provider::Codex);
34
- let adapter_argv = adapter
35
- .build_command_with_tools(
36
- AuthMode::Subscription,
37
- None,
38
- Some("Worker"),
39
- Some("gpt-5.5"),
40
- &["mcp_team", "dangerous_auto_approve"],
41
- )
42
- .expect("adapter command");
43
- let mut failures = bypass_argv_failures(&adapter_argv, "provider adapter");
44
-
45
- let team = compiled_team_dir("launch-dangerous");
46
- let launch_transport = RecordingTransport::new();
47
- launch_with_transport(
48
- &team.join("team.spec.yaml"),
49
- false,
50
- true,
51
- true,
52
- &launch_transport,
53
- )
54
- .expect("launch fixture should spawn worker");
55
- failures.extend(bypass_argv_failures(
56
- &launch_transport.only_spawn_argv("fresh launch"),
57
- "fresh launch",
58
- ));
59
-
60
- let restart_ws = restart_workspace("restart-dangerous");
61
- let restart_transport = RecordingTransport::new();
62
- restart_with_transport(&restart_ws, true, None, &restart_transport)
63
- .expect("restart fixture should spawn worker");
64
- failures.extend(bypass_argv_failures(
65
- &restart_transport.only_spawn_argv("restart"),
66
- "restart",
67
- ));
68
-
69
- assert!(
70
- failures.is_empty(),
71
- "dangerous Codex argv contract failed:\n{}",
72
- failures.join("\n")
73
- );
74
- }
75
-
76
- fn bypass_argv_failures(argv: &[String], label: &str) -> Vec<String> {
77
- let mut failures = Vec::new();
78
- if !argv.iter().any(|arg| arg == CODEX_BYPASS) {
79
- failures.push(format!(
80
- "{label}: Codex argv must contain {CODEX_BYPASS}; argv={argv:?}"
81
- ));
82
- }
83
- if argv
84
- .iter()
85
- .any(|arg| arg == "--ask-for-approval" || arg == "--sandbox")
86
- {
87
- failures.push(format!(
88
- "{label}: bypass argv must not also contain restricted approval/sandbox flags; argv={argv:?}"
89
- ));
90
- }
91
- failures
92
- }
93
-
94
- fn compiled_team_dir(tag: &str) -> PathBuf {
95
- let team = tmp_dir(tag).join("teamdir");
96
- write_team_files(&team, "dangerteam");
97
- let spec = team_agent::compiler::compile_team(&team).unwrap();
98
- std::fs::write(
99
- team.join("team.spec.yaml"),
100
- team_agent::model::yaml::dumps(&spec),
101
- )
102
- .unwrap();
103
- team
104
- }
105
-
106
- fn restart_workspace(tag: &str) -> PathBuf {
107
- let ws = tmp_dir(tag);
108
- write_team_files(&ws, "dangerteam");
109
- let spec = team_agent::compiler::compile_team(&ws).unwrap();
110
- std::fs::write(
111
- ws.join("team.spec.yaml"),
112
- team_agent::model::yaml::dumps(&spec),
113
- )
114
- .unwrap();
115
- team_agent::state::persist::save_runtime_state(
116
- &ws,
117
- &json!({
118
- "active_team_key": "dangerteam",
119
- "session_name": "team-dangerteam",
120
- "runtime": {"dangerous_auto_approve": true},
121
- "agents": {
122
- "worker_a": {
123
- "status": "running",
124
- "provider": "codex",
125
- "auth_mode": "subscription",
126
- "role": "Worker A",
127
- "model": "gpt-5.5",
128
- "window": "worker_a",
129
- "tools": ["mcp_team"]
130
- }
131
- }
132
- }),
133
- )
134
- .unwrap();
135
- seed_healthy_coordinator(&ws);
136
- ws
137
- }
138
-
139
- fn write_team_files(team: &Path, name: &str) {
140
- std::fs::create_dir_all(team.join("agents")).unwrap();
141
- std::fs::write(
142
- team.join("TEAM.md"),
143
- format!(
144
- "---\nname: {name}\nobjective: Dangerous argv contract.\nprovider: codex\ndangerous_auto_approve: true\n---\n\nTeam.\n"
145
- ),
146
- )
147
- .unwrap();
148
- std::fs::write(
149
- team.join("agents").join("worker_a.md"),
150
- "---\nname: worker_a\nrole: Worker A\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker.\n",
151
- )
152
- .unwrap();
153
- }
154
-
155
- fn seed_healthy_coordinator(workspace: &Path) {
156
- let workspace = team_agent::coordinator::WorkspacePath::new(workspace.to_path_buf());
157
- std::fs::create_dir_all(team_agent::model::paths::runtime_dir(workspace.as_path())).unwrap();
158
- let _ = team_agent::message_store::MessageStore::open(workspace.as_path()).unwrap();
159
- let pid = team_agent::coordinator::Pid::new(std::process::id());
160
- team_agent::coordinator::write_coordinator_metadata(
161
- &workspace,
162
- pid,
163
- team_agent::coordinator::MetadataSource::Boot,
164
- )
165
- .unwrap();
166
- std::fs::write(
167
- team_agent::coordinator::coordinator_pid_path(&workspace),
168
- pid.to_string(),
169
- )
170
- .unwrap();
171
- }
172
-
173
- fn tmp_dir(tag: &str) -> PathBuf {
174
- static N: AtomicU64 = AtomicU64::new(0);
175
- let dir = std::env::temp_dir().join(format!(
176
- "ta-rs-bug4-{tag}-{}-{}",
177
- std::process::id(),
178
- N.fetch_add(1, Ordering::Relaxed)
179
- ));
180
- let _ = std::fs::remove_dir_all(&dir);
181
- std::fs::create_dir_all(&dir).unwrap();
182
- std::fs::canonicalize(dir).unwrap()
183
- }
184
-
185
- #[derive(Debug, Default)]
186
- struct RecordingTransport {
187
- spawns: Mutex<Vec<Vec<String>>>,
188
- }
189
-
190
- impl RecordingTransport {
191
- fn new() -> Self {
192
- Self::default()
193
- }
194
-
195
- fn only_spawn_argv(&self, label: &str) -> Vec<String> {
196
- let spawns = self.spawns.lock().unwrap();
197
- assert_eq!(
198
- spawns.len(),
199
- 1,
200
- "{label}: fixture should record exactly one worker spawn; spawns={spawns:?}"
201
- );
202
- spawns[0].clone()
203
- }
204
-
205
- fn spawn_result(
206
- &self,
207
- session: &SessionName,
208
- window: &WindowName,
209
- argv: &[String],
210
- ) -> SpawnResult {
211
- let mut spawns = self.spawns.lock().unwrap();
212
- spawns.push(argv.to_vec());
213
- SpawnResult {
214
- pane_id: PaneId::new(format!("%{}", spawns.len())),
215
- session: session.clone(),
216
- window: window.clone(),
217
- child_pid: None,
218
- }
219
- }
220
- }
221
-
222
- impl Transport for RecordingTransport {
223
- fn kind(&self) -> BackendKind {
224
- BackendKind::Tmux
225
- }
226
-
227
- fn spawn_first(
228
- &self,
229
- session: &SessionName,
230
- window: &WindowName,
231
- argv: &[String],
232
- _cwd: &Path,
233
- _env: &BTreeMap<String, String>,
234
- ) -> Result<SpawnResult, TransportError> {
235
- Ok(self.spawn_result(session, window, argv))
236
- }
237
-
238
- fn spawn_into(
239
- &self,
240
- session: &SessionName,
241
- window: &WindowName,
242
- argv: &[String],
243
- _cwd: &Path,
244
- _env: &BTreeMap<String, String>,
245
- ) -> Result<SpawnResult, TransportError> {
246
- Ok(self.spawn_result(session, window, argv))
247
- }
248
-
249
- fn inject(
250
- &self,
251
- _target: &Target,
252
- _payload: &InjectPayload,
253
- _submit: Key,
254
- _bracketed: bool,
255
- ) -> Result<InjectReport, TransportError> {
256
- Ok(InjectReport {
257
- stage_reached: InjectStage::Submit,
258
- inject_verification: InjectVerification::CaptureContainsToken,
259
- submit_verification: SubmitVerification::EnterSentWithoutPlaceholderCheck,
260
- turn_verification: TurnVerification::NotYetObserved,
261
- attempts: 1,
262
- submit_diagnostics: None,
263
- })
264
- }
265
-
266
- fn send_keys(&self, _target: &Target, _keys: &[Key]) -> Result<(), TransportError> {
267
- Ok(())
268
- }
269
-
270
- fn capture(
271
- &self,
272
- _target: &Target,
273
- range: CaptureRange,
274
- ) -> Result<CapturedText, TransportError> {
275
- Ok(CapturedText {
276
- text: String::new(),
277
- range,
278
- })
279
- }
280
-
281
- fn query(&self, _target: &Target, field: PaneField) -> Result<Option<String>, TransportError> {
282
- match field {
283
- PaneField::PaneWidth => Ok(Some("120".to_string())),
284
- _ => Ok(None),
285
- }
286
- }
287
-
288
- fn liveness(
289
- &self,
290
- _pane: &PaneId,
291
- ) -> Result<team_agent::transport::PaneLiveness, TransportError> {
292
- Ok(team_agent::transport::PaneLiveness::Live)
293
- }
294
-
295
- fn list_targets(&self) -> Result<Vec<PaneInfo>, TransportError> {
296
- Ok(Vec::new())
297
- }
298
-
299
- fn has_session(&self, _session: &SessionName) -> Result<bool, TransportError> {
300
- Ok(!self.spawns.lock().unwrap().is_empty())
301
- }
302
-
303
- fn list_windows(&self, _session: &SessionName) -> Result<Vec<WindowName>, TransportError> {
304
- Ok(Vec::new())
305
- }
306
-
307
- fn set_session_env(
308
- &self,
309
- _session: &SessionName,
310
- _key: &str,
311
- _value: &str,
312
- ) -> Result<SetEnvOutcome, TransportError> {
313
- Ok(SetEnvOutcome::Applied)
314
- }
315
-
316
- fn kill_session(&self, _session: &SessionName) -> Result<(), TransportError> {
317
- Ok(())
318
- }
319
-
320
- fn kill_window(&self, _target: &Target) -> Result<(), TransportError> {
321
- Ok(())
322
- }
323
-
324
- fn attach_session(&self, _session: &SessionName) -> Result<AttachOutcome, TransportError> {
325
- Ok(AttachOutcome::Attached)
326
- }
327
- }