@team-agent/installer 0.4.10 → 0.5.0

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 (74) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/adapters.rs +1 -0
  4. package/crates/team-agent/src/cli/diagnose.rs +2 -15
  5. package/crates/team-agent/src/cli/emit.rs +62 -4
  6. package/crates/team-agent/src/compiler.rs +11 -20
  7. package/crates/team-agent/src/coordinator/orphan.rs +2 -2
  8. package/crates/team-agent/src/coordinator/runtime_detectors.rs +5 -4
  9. package/crates/team-agent/src/coordinator/steps/abnormal.rs +1776 -2
  10. package/crates/team-agent/src/coordinator/steps/mod.rs +19 -0
  11. package/crates/team-agent/src/coordinator/tests/a0_lostupdate.rs +78 -7
  12. package/crates/team-agent/src/coordinator/tests/abnormal.rs +195 -0
  13. package/crates/team-agent/src/coordinator/tick.rs +31 -932
  14. package/crates/team-agent/src/diagnose/orphans.rs +66 -8
  15. package/crates/team-agent/src/layout/worker_window_helpers.rs +5 -7
  16. package/crates/team-agent/src/leader/provider_attribution.rs +7 -5
  17. package/crates/team-agent/src/leader/rediscover.rs +1 -11
  18. package/crates/team-agent/src/leader/start.rs +169 -25
  19. package/crates/team-agent/src/lifecycle/launch/plan.rs +19 -8
  20. package/crates/team-agent/src/lifecycle/launch.rs +135 -58
  21. package/crates/team-agent/src/lifecycle/lock.rs +302 -0
  22. package/crates/team-agent/src/lifecycle/mod.rs +1 -0
  23. package/crates/team-agent/src/lifecycle/profile_smoke.rs +1 -11
  24. package/crates/team-agent/src/lifecycle/restart/agent.rs +436 -121
  25. package/crates/team-agent/src/lifecycle/restart/common.rs +108 -17
  26. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +165 -32
  27. package/crates/team-agent/src/lifecycle/restart/remove.rs +16 -2
  28. package/crates/team-agent/src/lifecycle/restart/selection.rs +2 -1
  29. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +193 -0
  30. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +3 -3
  31. package/crates/team-agent/src/lifecycle/tests/lifecycle_lock.rs +321 -0
  32. package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +54 -15
  33. package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +802 -0
  34. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +648 -0
  35. package/crates/team-agent/src/lifecycle/tests.rs +3 -0
  36. package/crates/team-agent/src/lifecycle/types.rs +8 -0
  37. package/crates/team-agent/src/lifecycle/worker_command_context.rs +24 -34
  38. package/crates/team-agent/src/mcp_server/lifecycle_tools/state_status.rs +24 -9
  39. package/crates/team-agent/src/mcp_server/tools.rs +157 -68
  40. package/crates/team-agent/src/messaging/activity.rs +43 -18
  41. package/crates/team-agent/src/messaging/delivery.rs +161 -97
  42. package/crates/team-agent/src/messaging/helpers.rs +1 -0
  43. package/crates/team-agent/src/messaging/leader_receiver.rs +22 -1
  44. package/crates/team-agent/src/messaging/results.rs +34 -9
  45. package/crates/team-agent/src/messaging/scheduler.rs +52 -9
  46. package/crates/team-agent/src/model/spec.rs +10 -6
  47. package/crates/team-agent/src/provider/adapter.rs +10 -1038
  48. package/crates/team-agent/src/provider/adapters/claude.rs +3 -8
  49. package/crates/team-agent/src/provider/adapters/copilot.rs +2 -5
  50. package/crates/team-agent/src/provider/classify.rs +23 -48
  51. package/crates/team-agent/src/provider/command.rs +16 -7
  52. package/crates/team-agent/src/provider/faults.rs +93 -53
  53. package/crates/team-agent/src/provider/session/capture.rs +4 -15
  54. package/crates/team-agent/src/provider/session_scan/claude.rs +309 -0
  55. package/crates/team-agent/src/provider/session_scan/codex.rs +40 -0
  56. package/crates/team-agent/src/provider/session_scan/common.rs +350 -0
  57. package/crates/team-agent/src/provider/session_scan/copilot.rs +202 -0
  58. package/crates/team-agent/src/provider/session_scan.rs +65 -27
  59. package/crates/team-agent/src/provider/tests/faults.rs +80 -0
  60. package/crates/team-agent/src/provider/types.rs +33 -1
  61. package/crates/team-agent/src/provider/wire.rs +171 -1
  62. package/crates/team-agent/src/state/identity.rs +242 -57
  63. package/crates/team-agent/src/state/identity_keys.rs +9 -12
  64. package/crates/team-agent/src/state/mod.rs +5 -1
  65. package/crates/team-agent/src/state/owner_gate.rs +59 -15
  66. package/crates/team-agent/src/state/ownership.rs +12 -11
  67. package/crates/team-agent/src/state/paths.rs +13 -6
  68. package/crates/team-agent/src/state/persist.rs +671 -128
  69. package/crates/team-agent/src/state/projection.rs +240 -49
  70. package/crates/team-agent/src/state/selector.rs +11 -5
  71. package/crates/team-agent/src/tmux_backend/tests.rs +51 -2
  72. package/crates/team-agent/src/tmux_backend.rs +42 -5
  73. package/crates/team-agent/src/transport/test_support.rs +55 -6
  74. package/package.json +4 -4
@@ -10,7 +10,9 @@ use crate::transport::{PaneId, Transport};
10
10
 
11
11
  use super::delivery::{deliver_stored_message, handle_trust_retry_needed};
12
12
  use super::helpers::{parse_scheduled_kind, status_wire};
13
- use super::{AlertType, MessagingError, ScheduledKind, TrustRetryPayload, TRUST_RETRY_MAX_ATTEMPTS};
13
+ use super::{
14
+ AlertType, MessagingError, ScheduledKind, TrustRetryPayload, TRUST_RETRY_MAX_ATTEMPTS,
15
+ };
14
16
 
15
17
  /// `_fire_due_scheduled_events` (`scheduler.py:41`):coordinator tick 的调度器心脏 —— 分派到期
16
18
  /// `send`/`health_ping`/`trust_retry` ([`ScheduledKind`] 穷尽 match),send 失败有界重试。
@@ -50,9 +52,15 @@ pub fn fire_due_scheduled_events(
50
52
  let outcome = deliver_stored_message(
51
53
  workspace,
52
54
  Some(&target),
53
- payload.get("content").and_then(|v| v.as_str()).unwrap_or(""),
55
+ payload
56
+ .get("content")
57
+ .and_then(|v| v.as_str())
58
+ .unwrap_or(""),
54
59
  None,
55
- payload.get("sender").and_then(|v| v.as_str()).unwrap_or("leader"),
60
+ payload
61
+ .get("sender")
62
+ .and_then(|v| v.as_str())
63
+ .unwrap_or("leader"),
56
64
  payload
57
65
  .get("requires_ack")
58
66
  .and_then(|v| v.as_bool())
@@ -61,7 +69,10 @@ pub fn fire_due_scheduled_events(
61
69
  .get("wait_visible")
62
70
  .and_then(|v| v.as_bool())
63
71
  .unwrap_or(false),
64
- payload.get("timeout").and_then(|v| v.as_f64()).unwrap_or(30.0),
72
+ payload
73
+ .get("timeout")
74
+ .and_then(|v| v.as_f64())
75
+ .unwrap_or(30.0),
65
76
  None,
66
77
  )?;
67
78
  serde_json::json!({
@@ -114,7 +125,10 @@ pub fn fire_due_scheduled_events(
114
125
 
115
126
  let (status, result_json) = match fire_one() {
116
127
  Ok(result) => {
117
- let ok = result.get("ok").and_then(serde_json::Value::as_bool).unwrap_or(false);
128
+ let ok = result
129
+ .get("ok")
130
+ .and_then(serde_json::Value::as_bool)
131
+ .unwrap_or(false);
118
132
  (if ok { "done" } else { "failed" }, result.to_string())
119
133
  }
120
134
  Err(error) => {
@@ -242,7 +256,26 @@ pub fn stuck_cancel(
242
256
  },
243
257
  );
244
258
  }
245
- crate::state::persist::save_runtime_state(workspace, &state)?;
259
+ crate::state::persist::save_runtime_state_reapplying_after_conflict(
260
+ workspace,
261
+ &state,
262
+ |latest| {
263
+ for kind in &alert_types {
264
+ upsert_suppression(
265
+ latest,
266
+ SuppressionRecord {
267
+ team: &team,
268
+ agent_id,
269
+ alert_type: kind,
270
+ suppressed_by,
271
+ suppressed_at: &now,
272
+ assigned_task_ids: assigned.clone(),
273
+ delivered_message_ids: delivered.clone(),
274
+ },
275
+ );
276
+ }
277
+ },
278
+ )?;
246
279
  crate::event_log::EventLog::new(workspace).write(
247
280
  "coordinator.idle_alert_suppressed",
248
281
  serde_json::json!({
@@ -273,7 +306,11 @@ fn active_team_key(workspace: &Path, state: &serde_json::Value) -> String {
273
306
  .and_then(serde_json::Value::as_str)
274
307
  .filter(|team| !team.is_empty())
275
308
  .map(ToString::to_string)
276
- .or_else(|| workspace.file_name().map(|name| name.to_string_lossy().to_string()))
309
+ .or_else(|| {
310
+ workspace
311
+ .file_name()
312
+ .map(|name| name.to_string_lossy().to_string())
313
+ })
277
314
  .unwrap_or_else(|| "current".to_string())
278
315
  }
279
316
 
@@ -284,8 +321,14 @@ fn assigned_task_ids(state: &serde_json::Value, agent_id: &str) -> Vec<String> {
284
321
  .map(|tasks| {
285
322
  tasks
286
323
  .iter()
287
- .filter(|task| task.get("assignee").and_then(serde_json::Value::as_str) == Some(agent_id))
288
- .filter_map(|task| task.get("id").and_then(serde_json::Value::as_str).map(ToString::to_string))
324
+ .filter(|task| {
325
+ task.get("assignee").and_then(serde_json::Value::as_str) == Some(agent_id)
326
+ })
327
+ .filter_map(|task| {
328
+ task.get("id")
329
+ .and_then(serde_json::Value::as_str)
330
+ .map(ToString::to_string)
331
+ })
289
332
  .collect()
290
333
  })
291
334
  .unwrap_or_default();
@@ -18,6 +18,7 @@ use crate::model::ids::TaskId;
18
18
  use crate::model::task_graph::{find_dependency_cycle, TaskNode};
19
19
  use crate::model::yaml::Value as Yaml;
20
20
  use crate::model::{permissions, yaml};
21
+ use crate::provider::wire::{is_claude_family, parse_canonical_provider};
21
22
 
22
23
  /// result_envelope_v1 顶层 required(= allowed)。
23
24
  const RESULT_REQUIRED: &[&str] = &[
@@ -175,9 +176,6 @@ fn result_schema_errors(envelope: &Value) -> Vec<String> {
175
176
  const ROOT_KEYS: &[&str] = &[
176
177
  "version", "team", "leader", "agents", "routing", "communication", "runtime", "context", "tasks",
177
178
  ];
178
- // Copilot 一期加入白名单(design §B compiler.py:249-251 同位 + cr verdict 总裁,
179
- // MUST-NOT-7 跨厂商等价 — 设计 / cr 已落地 26 约束)。
180
- const SUPPORTED_PROVIDERS: &[&str] = &["claude", "claude_code", "codex", "copilot", "gemini_cli", "fake"];
181
179
  const AUTH_MODES: &[&str] = &["subscription", "official_api", "compatible_api"];
182
180
  const VALID_DISPLAY_BACKENDS: &[&str] = &[
183
181
  "none", "tmux_attach", "iterm", "ghostty", "ghostty_window", "ghostty_workspace", "adaptive",
@@ -326,7 +324,7 @@ fn check_agent(agent: &Yaml, path: &str, errors: &mut Vec<String>) {
326
324
  }
327
325
  Some(effort) if effort.is_claude_only() => {
328
326
  let provider = agent.get("provider").and_then(Yaml::as_str).unwrap_or("");
329
- if !matches!(provider, "claude" | "claude_code") {
327
+ if !parse_canonical_provider(provider).is_some_and(is_claude_family) {
330
328
  errors.push(format!(
331
329
  "{path}/effort: effort '{raw}' is only supported by claude/claude_code (provider: {provider})"
332
330
  ));
@@ -476,13 +474,19 @@ fn semantic_errors(spec: &Yaml, base_dir: &Path) -> Vec<String> {
476
474
  }
477
475
 
478
476
  let leader_provider = leader.and_then(|l| l.get("provider"));
479
- if !leader_provider.and_then(Yaml::as_str).is_some_and(|p| SUPPORTED_PROVIDERS.contains(&p)) {
477
+ if !leader_provider
478
+ .and_then(Yaml::as_str)
479
+ .is_some_and(|p| parse_canonical_provider(p).is_some())
480
+ {
480
481
  e.push(format!("/leader/provider: unknown provider {}", py_repr(leader_provider)));
481
482
  }
482
483
 
483
484
  for (idx, agent) in agents.iter().enumerate() {
484
485
  let provider = agent.get("provider");
485
- if !provider.and_then(Yaml::as_str).is_some_and(|p| SUPPORTED_PROVIDERS.contains(&p)) {
486
+ if !provider
487
+ .and_then(Yaml::as_str)
488
+ .is_some_and(|p| parse_canonical_provider(p).is_some())
489
+ {
486
490
  e.push(format!("/agents/{idx}/provider: unknown provider {}", py_repr(provider)));
487
491
  }
488
492
  if let Some(auth) = agent.get("auth_mode") {