@team-agent/installer 0.4.11 → 0.5.1

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 (80) 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 +98 -5
  6. package/crates/team-agent/src/cli/mod.rs +2 -0
  7. package/crates/team-agent/src/cli/named_address.rs +864 -0
  8. package/crates/team-agent/src/cli/send.rs +104 -0
  9. package/crates/team-agent/src/cli/tests/leader_watch.rs +1 -0
  10. package/crates/team-agent/src/cli/tests/mod.rs +1 -0
  11. package/crates/team-agent/src/cli/tests/named_address.rs +455 -0
  12. package/crates/team-agent/src/cli/tests/status_send.rs +1 -0
  13. package/crates/team-agent/src/cli/types.rs +4 -0
  14. package/crates/team-agent/src/compiler.rs +11 -20
  15. package/crates/team-agent/src/coordinator/orphan.rs +2 -2
  16. package/crates/team-agent/src/coordinator/runtime_detectors.rs +5 -4
  17. package/crates/team-agent/src/coordinator/steps/abnormal.rs +1776 -2
  18. package/crates/team-agent/src/coordinator/steps/mod.rs +19 -0
  19. package/crates/team-agent/src/coordinator/tests/a0_lostupdate.rs +78 -7
  20. package/crates/team-agent/src/coordinator/tests/abnormal.rs +195 -0
  21. package/crates/team-agent/src/coordinator/tick.rs +31 -932
  22. package/crates/team-agent/src/diagnose/orphans.rs +66 -8
  23. package/crates/team-agent/src/layout/worker_window_helpers.rs +5 -7
  24. package/crates/team-agent/src/leader/provider_attribution.rs +7 -5
  25. package/crates/team-agent/src/leader/rediscover.rs +1 -11
  26. package/crates/team-agent/src/lifecycle/launch/plan.rs +19 -8
  27. package/crates/team-agent/src/lifecycle/launch.rs +135 -58
  28. package/crates/team-agent/src/lifecycle/lock.rs +302 -0
  29. package/crates/team-agent/src/lifecycle/mod.rs +1 -0
  30. package/crates/team-agent/src/lifecycle/profile_smoke.rs +1 -11
  31. package/crates/team-agent/src/lifecycle/restart/agent.rs +169 -113
  32. package/crates/team-agent/src/lifecycle/restart/common.rs +108 -17
  33. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +165 -32
  34. package/crates/team-agent/src/lifecycle/restart/remove.rs +16 -2
  35. package/crates/team-agent/src/lifecycle/restart/selection.rs +2 -1
  36. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +6 -0
  37. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +3 -3
  38. package/crates/team-agent/src/lifecycle/tests/lifecycle_lock.rs +321 -0
  39. package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +35 -5
  40. package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +802 -0
  41. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +675 -0
  42. package/crates/team-agent/src/lifecycle/tests.rs +3 -0
  43. package/crates/team-agent/src/lifecycle/types.rs +8 -0
  44. package/crates/team-agent/src/mcp_server/lifecycle_tools/state_status.rs +24 -9
  45. package/crates/team-agent/src/mcp_server/tools.rs +157 -68
  46. package/crates/team-agent/src/messaging/activity.rs +43 -18
  47. package/crates/team-agent/src/messaging/delivery.rs +161 -97
  48. package/crates/team-agent/src/messaging/helpers.rs +1 -0
  49. package/crates/team-agent/src/messaging/leader_receiver.rs +22 -1
  50. package/crates/team-agent/src/messaging/results.rs +34 -9
  51. package/crates/team-agent/src/messaging/scheduler.rs +52 -9
  52. package/crates/team-agent/src/model/spec.rs +10 -6
  53. package/crates/team-agent/src/provider/adapter.rs +10 -1038
  54. package/crates/team-agent/src/provider/adapters/claude.rs +3 -8
  55. package/crates/team-agent/src/provider/adapters/copilot.rs +2 -5
  56. package/crates/team-agent/src/provider/classify.rs +23 -48
  57. package/crates/team-agent/src/provider/command.rs +16 -7
  58. package/crates/team-agent/src/provider/faults.rs +93 -53
  59. package/crates/team-agent/src/provider/session/capture.rs +4 -15
  60. package/crates/team-agent/src/provider/session_scan/claude.rs +309 -0
  61. package/crates/team-agent/src/provider/session_scan/codex.rs +40 -0
  62. package/crates/team-agent/src/provider/session_scan/common.rs +350 -0
  63. package/crates/team-agent/src/provider/session_scan/copilot.rs +202 -0
  64. package/crates/team-agent/src/provider/session_scan.rs +65 -27
  65. package/crates/team-agent/src/provider/tests/faults.rs +80 -0
  66. package/crates/team-agent/src/provider/types.rs +33 -1
  67. package/crates/team-agent/src/provider/wire.rs +171 -1
  68. package/crates/team-agent/src/state/identity.rs +242 -57
  69. package/crates/team-agent/src/state/identity_keys.rs +9 -12
  70. package/crates/team-agent/src/state/mod.rs +5 -1
  71. package/crates/team-agent/src/state/owner_gate.rs +59 -15
  72. package/crates/team-agent/src/state/ownership.rs +12 -11
  73. package/crates/team-agent/src/state/paths.rs +13 -6
  74. package/crates/team-agent/src/state/persist.rs +671 -128
  75. package/crates/team-agent/src/state/projection.rs +240 -49
  76. package/crates/team-agent/src/state/selector.rs +11 -5
  77. package/crates/team-agent/src/tmux_backend/tests.rs +51 -2
  78. package/crates/team-agent/src/tmux_backend.rs +42 -5
  79. package/crates/team-agent/src/transport/test_support.rs +55 -6
  80. package/package.json +4 -4
package/Cargo.lock CHANGED
@@ -566,7 +566,7 @@ dependencies = [
566
566
 
567
567
  [[package]]
568
568
  name = "team-agent"
569
- version = "0.4.11"
569
+ version = "0.5.1"
570
570
  dependencies = [
571
571
  "anyhow",
572
572
  "chrono",
package/Cargo.toml CHANGED
@@ -9,7 +9,7 @@ members = ["crates/team-agent"]
9
9
 
10
10
  [workspace.package]
11
11
  edition = "2021"
12
- version = "0.4.11"
12
+ version = "0.5.1"
13
13
  license = "AGPL-3.0"
14
14
  rust-version = "1.95"
15
15
 
@@ -993,6 +993,7 @@ fn command_version(command: &str) -> Value {
993
993
  }
994
994
 
995
995
  fn provider_command(provider: &str) -> &str {
996
+ // E2E provider command grammar, not persisted provider identity parsing.
996
997
  match provider {
997
998
  "claude" | "claude_code" => "claude",
998
999
  "gemini" | "gemini_cli" => "gemini",
@@ -1,5 +1,6 @@
1
1
  //! diagnose/preflight/wait-ready CLI helpers.
2
2
  use super::*;
3
+ use crate::provider::wire::{command_name, provider_wire};
3
4
  use crate::transport::Transport;
4
5
 
5
6
  pub(crate) fn diagnose_runtime(state: &Value, backend: &dyn Transport) -> (Value, Value) {
@@ -781,23 +782,9 @@ pub(crate) fn provider_doctor_checks() -> Value {
781
782
  Value::Object(providers)
782
783
  }
783
784
 
784
- fn provider_wire(provider: crate::provider::Provider) -> &'static str {
785
- match provider {
786
- crate::provider::Provider::Claude => "claude",
787
- crate::provider::Provider::ClaudeCode => "claude_code",
788
- crate::provider::Provider::Codex => "codex",
789
- crate::provider::Provider::Copilot => "copilot",
790
- crate::provider::Provider::GeminiCli => "gemini_cli",
791
- crate::provider::Provider::Fake => "fake",
792
- }
793
- }
794
-
795
785
  fn provider_command(provider: crate::provider::Provider) -> &'static str {
796
786
  match provider {
797
- crate::provider::Provider::Claude | crate::provider::Provider::ClaudeCode => "claude",
798
- crate::provider::Provider::Codex => "codex",
799
- crate::provider::Provider::Copilot => "copilot",
800
- crate::provider::Provider::GeminiCli => "gemini",
801
787
  crate::provider::Provider::Fake => "team-agent fake-worker",
788
+ other => command_name(other),
802
789
  }
803
790
  }
@@ -31,7 +31,7 @@ pub fn run(argv: &[String], cwd: &Path) -> ExitCode {
31
31
  let Some(command) = argv.first().map(String::as_str) else {
32
32
  return emit_missing_subcommand_usage();
33
33
  };
34
- if command == "codex" || command == "claude" || command == "copilot" {
34
+ if is_leader_passthrough_command(command) {
35
35
  return match cmd_leader_passthrough(command, &argv[1..], cwd) {
36
36
  Ok(result) => emit_result(result),
37
37
  Err(error) => emit_cli_error(command, &argv[1..], cwd, &error),
@@ -189,6 +189,13 @@ const DISPATCH_COMMANDS: &[&str] = &[
189
189
  ];
190
190
 
191
191
  const SPEC_ONLY_HELP_COMMANDS: &[&str] = &["start", "purge-agent"];
192
+ // Command grammar, not provider identity parsing: these are top-level CLI
193
+ // passthrough verbs for starting a leader under a provider executable.
194
+ const LEADER_PASSTHROUGH_COMMANDS: &[&str] = &["codex", "claude", "copilot"];
195
+
196
+ fn is_leader_passthrough_command(command: &str) -> bool {
197
+ LEADER_PASSTHROUGH_COMMANDS.contains(&command)
198
+ }
192
199
 
193
200
  fn emit_missing_subcommand_usage() -> ExitCode {
194
201
  emit_usage_error("the following arguments are required: {codex,claude,...,doctor}");
@@ -206,7 +213,7 @@ fn is_known_subcommand(command: &str) -> bool {
206
213
  fn command_help(command: Option<&str>) -> String {
207
214
  match command {
208
215
  None => {
209
- let mut commands = vec!["codex", "claude", "copilot"];
216
+ let mut commands = LEADER_PASSTHROUGH_COMMANDS.to_vec();
210
217
  commands.extend_from_slice(DISPATCH_COMMANDS);
211
218
  commands.extend_from_slice(SPEC_ONLY_HELP_COMMANDS);
212
219
  format!(
@@ -218,7 +225,7 @@ fn command_help(command: Option<&str>) -> String {
218
225
  Some("quick-start") => "usage: team-agent quick-start [TEAMDIR] [--workspace WORKSPACE] [--name NAME] [--team-id TEAM|--team TEAM] [--yes] [--no-display] [--json]\n\ndefaults: display_backend=adaptive; set display_backend: none in TEAM.md or pass --no-display to use one worker window per agent.".to_string(),
219
226
  Some("start") => "usage: team-agent start [TEAMDIR] [--yes] [--fresh] [--json]".to_string(),
220
227
  Some("compile") => "usage: team-agent compile --team TEAM [--out FILE] [--json]".to_string(),
221
- Some("send") => "usage: team-agent send TARGET MESSAGE... [--workspace WORKSPACE] [--team TEAM] [--targets AGENTS] [--task TASK] [--sender SENDER] [--watch-result] [--requires-ack|--no-ack] [--no-wait] [--timeout SECONDS] [--confirm-human] [--message-id ID] [--json]".to_string(),
228
+ Some("send") => "usage: team-agent send TARGET MESSAGE... [--workspace WORKSPACE] [--team TEAM] [--targets AGENTS] [--to-name NAME] [--pane PANE] [--task TASK] [--sender SENDER] [--watch-result] [--requires-ack|--no-ack] [--no-wait] [--timeout SECONDS] [--confirm-human] [--message-id ID] [--json]\n\nMVP: name-based cross-workspace addressing assumes trusted local caller; no auth gate.".to_string(),
222
229
  Some("fallback-send-leader") => "usage: team-agent fallback-send-leader --workspace WORKSPACE --team TEAM --sender AGENT --message-id ID --content TEXT --primary-error ERROR [--task TASK] [--json]\n\nEmergency one-shot fallback only after a leader-bound MCP send transport failure; restart-agent after use.".to_string(),
223
230
  Some("fallback-report-result") => "usage: team-agent fallback-report-result --workspace WORKSPACE --team TEAM --agent-id AGENT --task-id TASK --result-json JSON --primary-error ERROR [--json]\n\nEmergency one-shot fallback only after a report_result MCP transport failure; persists the result DB row, then restart-agent after use.".to_string(),
224
231
  Some("allow-peer-talk") => "usage: team-agent allow-peer-talk A B [--workspace WORKSPACE] [--json]".to_string(),
@@ -276,7 +283,7 @@ fn emit_unknown_subcommand_usage(command: &str) -> ExitCode {
276
283
 
277
284
  /// 在已知子命令里找与 `input` 最接近的一个(Levenshtein ≤ 阈值)。无足够接近者 → None。
278
285
  fn nearest_subcommand(input: &str) -> Option<&'static str> {
279
- let mut candidates: Vec<&'static str> = vec!["codex", "claude", "copilot"];
286
+ let mut candidates: Vec<&'static str> = LEADER_PASSTHROUGH_COMMANDS.to_vec();
280
287
  candidates.extend_from_slice(DISPATCH_COMMANDS);
281
288
  candidates.extend_from_slice(SPEC_ONLY_HELP_COMMANDS);
282
289
  // 阈值随长度放宽,但短词收紧,避免 'x' 误配任何东西。
@@ -661,6 +668,7 @@ struct ParsedArgs {
661
668
  out: Option<PathBuf>,
662
669
  auth_mode: Option<String>,
663
670
  pane: Option<String>,
671
+ to_name: Option<String>,
664
672
  provider: Option<String>,
665
673
  message_id: Option<String>,
666
674
  content: Option<String>,
@@ -743,6 +751,7 @@ fn parse_args(args: &[String]) -> ParsedArgs {
743
751
  "--out" => parsed.out = next_arg(args, &mut i).map(PathBuf::from),
744
752
  "--auth-mode" => parsed.auth_mode = next_arg(args, &mut i),
745
753
  "--pane" => parsed.pane = next_arg(args, &mut i),
754
+ "--to-name" => parsed.to_name = next_arg(args, &mut i),
746
755
  "--provider" => parsed.provider = next_arg(args, &mut i),
747
756
  "--message-id" => parsed.message_id = next_arg(args, &mut i),
748
757
  "--content" => parsed.content = next_arg(args, &mut i),
@@ -755,6 +764,9 @@ fn parse_args(args: &[String]) -> ParsedArgs {
755
764
  other if other.starts_with("--pane=") => {
756
765
  parsed.pane = Some(other.trim_start_matches("--pane=").to_string());
757
766
  }
767
+ other if other.starts_with("--to-name=") => {
768
+ parsed.to_name = Some(other.trim_start_matches("--to-name=").to_string());
769
+ }
758
770
  other if other.starts_with("--provider=") => {
759
771
  parsed.provider = Some(other.trim_start_matches("--provider=").to_string());
760
772
  }
@@ -868,7 +880,7 @@ fn resolve_cli_path(cwd: &Path, path: &Path) -> PathBuf {
868
880
 
869
881
  fn send_args(args: &[String], cwd: &Path) -> Result<SendArgs, CliError> {
870
882
  let parsed = parse_args(args);
871
- let target = if parsed.targets.is_some() {
883
+ let target = if parsed.targets.is_some() || parsed.pane.is_some() || parsed.to_name.is_some() {
872
884
  None
873
885
  } else {
874
886
  parsed.positionals.first().cloned()
@@ -896,6 +908,7 @@ fn send_args(args: &[String], cwd: &Path) -> Result<SendArgs, CliError> {
896
908
  json: parsed.json,
897
909
  message_id: parsed.message_id,
898
910
  pane: parsed.pane.clone(),
911
+ to_name: parsed.to_name.clone(),
899
912
  })
900
913
  }
901
914
 
@@ -1595,6 +1608,8 @@ mod tests {
1595
1608
  "--workspace",
1596
1609
  "--team",
1597
1610
  "--targets",
1611
+ "--to-name",
1612
+ "--pane",
1598
1613
  "--watch-result",
1599
1614
  "--timeout",
1600
1615
  "--json",
@@ -1747,6 +1762,84 @@ mod tests {
1747
1762
  );
1748
1763
  }
1749
1764
 
1765
+ #[test]
1766
+ fn send_pane_positionals_are_message_not_target() {
1767
+ let cwd = tmp_workspace();
1768
+ let args = send_args(&cli_argv(&["--pane", "%1596", "hello"]), &cwd).unwrap();
1769
+ assert_eq!(args.pane.as_deref(), Some("%1596"));
1770
+ assert_eq!(args.target, None);
1771
+ assert_eq!(args.targets, None);
1772
+ assert_eq!(args.message, vec!["hello".to_string()]);
1773
+
1774
+ let args = send_args(
1775
+ &cli_argv(&["--pane", "%1596", "multi", "word", "message"]),
1776
+ &cwd,
1777
+ )
1778
+ .unwrap();
1779
+ assert_eq!(args.target, None);
1780
+ assert_eq!(
1781
+ args.message,
1782
+ vec![
1783
+ "multi".to_string(),
1784
+ "word".to_string(),
1785
+ "message".to_string()
1786
+ ]
1787
+ );
1788
+
1789
+ let _ = std::fs::remove_dir_all(&cwd);
1790
+ }
1791
+
1792
+ #[test]
1793
+ fn send_to_name_positionals_are_message_not_target() {
1794
+ let cwd = tmp_workspace();
1795
+ let args = send_args(&cli_argv(&["--to-name", "team-a/qa", "hello"]), &cwd).unwrap();
1796
+ assert_eq!(args.to_name.as_deref(), Some("team-a/qa"));
1797
+ assert_eq!(args.target, None);
1798
+ assert_eq!(args.targets, None);
1799
+ assert_eq!(args.message, vec!["hello".to_string()]);
1800
+
1801
+ let args = send_args(
1802
+ &cli_argv(&["--to-name=team-a/qa", "multi", "word", "message"]),
1803
+ &cwd,
1804
+ )
1805
+ .unwrap();
1806
+ assert_eq!(args.target, None);
1807
+ assert_eq!(
1808
+ args.message,
1809
+ vec![
1810
+ "multi".to_string(),
1811
+ "word".to_string(),
1812
+ "message".to_string()
1813
+ ]
1814
+ );
1815
+
1816
+ let _ = std::fs::remove_dir_all(&cwd);
1817
+ }
1818
+
1819
+ #[test]
1820
+ fn send_pane_still_rejects_to_and_empty_message() {
1821
+ let cwd = tmp_workspace();
1822
+ let args = send_args(
1823
+ &cli_argv(&["--pane", "%1596", "--to", "worker", "hello"]),
1824
+ &cwd,
1825
+ )
1826
+ .unwrap();
1827
+ let err = cmd_send(&args).unwrap_err();
1828
+ assert!(
1829
+ matches!(err, CliError::Usage(ref message) if message.contains("--pane and TARGET/--to are mutually exclusive")),
1830
+ "expected --pane/--to mutual-exclusion usage error, got {err:?}"
1831
+ );
1832
+
1833
+ let args = send_args(&cli_argv(&["--pane", "%1596"]), &cwd).unwrap();
1834
+ let err = cmd_send(&args).unwrap_err();
1835
+ assert!(
1836
+ matches!(err, CliError::Usage(ref message) if message == "--pane requires a non-empty message"),
1837
+ "expected empty-message usage error, got {err:?}"
1838
+ );
1839
+
1840
+ let _ = std::fs::remove_dir_all(&cwd);
1841
+ }
1842
+
1750
1843
  #[test]
1751
1844
  fn ux_quick_start_workspace_resolves_relative_agents_dir_inside_workspace() {
1752
1845
  let cwd = tmp_workspace();
@@ -57,6 +57,7 @@ pub mod diagnose;
57
57
  pub mod emit;
58
58
  pub mod helpers;
59
59
  pub mod leader;
60
+ pub mod named_address;
60
61
  pub mod profile;
61
62
  pub mod send;
62
63
  pub mod status;
@@ -66,6 +67,7 @@ pub use adapters::*;
66
67
  pub use diagnose::*;
67
68
  pub use emit::*;
68
69
  pub use leader::*;
70
+ pub use named_address::*;
69
71
  pub use profile::*;
70
72
  pub use send::*;
71
73
  pub use status::*;