@team-agent/installer 0.5.75 → 0.5.78

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 (98) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/README.md +9 -0
  4. package/README.zh.md +8 -0
  5. package/crates/team-agent/src/cli/adapters.rs +184 -125
  6. package/crates/team-agent/src/cli/diagnose.rs +333 -68
  7. package/crates/team-agent/src/cli/emit.rs +59 -15
  8. package/crates/team-agent/src/cli/mod.rs +600 -134
  9. package/crates/team-agent/src/cli/models.rs +485 -44
  10. package/crates/team-agent/src/cli/named_address.rs +19 -5
  11. package/crates/team-agent/src/cli/profile.rs +35 -4
  12. package/crates/team-agent/src/cli/spec.rs +7 -2
  13. package/crates/team-agent/src/cli/status_port/brief.rs +1137 -0
  14. package/crates/team-agent/src/cli/status_port/compact.rs +12 -8
  15. package/crates/team-agent/src/cli/status_port/snapshot.rs +15 -12
  16. package/crates/team-agent/src/cli/status_port/store.rs +1 -1
  17. package/crates/team-agent/src/cli/status_port.rs +8 -0
  18. package/crates/team-agent/src/cli/tests/missing_subcommands.rs +62 -8
  19. package/crates/team-agent/src/cli/tests/mod.rs +1 -0
  20. package/crates/team-agent/src/cli/tests/named_address.rs +70 -0
  21. package/crates/team-agent/src/cli/tests/run_delegation.rs +29 -24
  22. package/crates/team-agent/src/cli/tests/status_brief.rs +691 -0
  23. package/crates/team-agent/src/cli/tests/status_send.rs +8 -2
  24. package/crates/team-agent/src/cli/tests/verb_profile.rs +81 -6
  25. package/crates/team-agent/src/cli/types.rs +1 -0
  26. package/crates/team-agent/src/leader/lease.rs +538 -41
  27. package/crates/team-agent/src/leader/owner_bind.rs +40 -12
  28. package/crates/team-agent/src/leader/rediscover/tests.rs +65 -0
  29. package/crates/team-agent/src/leader/rediscover.rs +36 -6
  30. package/crates/team-agent/src/leader/start.rs +151 -14
  31. package/crates/team-agent/src/leader/tests/wake_start_owner.rs +15 -9
  32. package/crates/team-agent/src/leader/types.rs +4 -0
  33. package/crates/team-agent/src/lifecycle/launch/add_agent.rs +28 -227
  34. package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +0 -18
  35. package/crates/team-agent/src/lifecycle/launch/cursor_mcp.rs +94 -227
  36. package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +59 -10
  37. package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +138 -14
  38. package/crates/team-agent/src/lifecycle/launch/quick_start.rs +1449 -282
  39. package/crates/team-agent/src/lifecycle/launch/readiness.rs +349 -4
  40. package/crates/team-agent/src/lifecycle/launch/spawn.rs +11 -11
  41. package/crates/team-agent/src/lifecycle/launch/spec_state.rs +35 -3
  42. package/crates/team-agent/src/lifecycle/launch/worker_env.rs +16 -0
  43. package/crates/team-agent/src/lifecycle/launch.rs +30 -7
  44. package/crates/team-agent/src/lifecycle/profile_launch.rs +37 -3
  45. package/crates/team-agent/src/lifecycle/restart/agent.rs +112 -100
  46. package/crates/team-agent/src/lifecycle/restart/common.rs +82 -52
  47. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +1002 -65
  48. package/crates/team-agent/src/lifecycle/restart.rs +2 -2
  49. package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +3 -0
  50. package/crates/team-agent/src/lifecycle/tests/b0_reader_hideone_audit_contract.rs +45 -14
  51. package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +15 -0
  52. package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +5 -0
  53. package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +11 -13
  54. package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +119 -3
  55. package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +12 -0
  56. package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +22 -0
  57. package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +12 -0
  58. package/crates/team-agent/src/lifecycle/tests/cursor_mcp_overlay.rs +265 -198
  59. package/crates/team-agent/src/lifecycle/tests/cursor_require_explicit_model_red.rs +14 -30
  60. package/crates/team-agent/src/lifecycle/tests/cursor_restart_resume_red.rs +3 -0
  61. package/crates/team-agent/src/lifecycle/tests/g1_silent_faces.rs +2 -5
  62. package/crates/team-agent/src/lifecycle/tests/grok_effort_argv_red.rs +10 -0
  63. package/crates/team-agent/src/lifecycle/tests/grok_mcp_overlay_red.rs +58 -35
  64. package/crates/team-agent/src/lifecycle/tests/grok_require_explicit_model_red.rs +10 -0
  65. package/crates/team-agent/src/lifecycle/tests/grok_restart_resume_red.rs +9 -0
  66. package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +4 -3
  67. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +0 -168
  68. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +145 -212
  69. package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +16 -2
  70. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +69 -28
  71. package/crates/team-agent/src/lifecycle/tests/pi_dual_entry_red.rs +78 -0
  72. package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +3 -0
  73. package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +51 -10
  74. package/crates/team-agent/src/lifecycle/tests/upgrade_compat_0211_red.rs +22 -10
  75. package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +50 -7
  76. package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +137 -0
  77. package/crates/team-agent/src/lifecycle/types.rs +12 -0
  78. package/crates/team-agent/src/mcp_server/wire.rs +140 -11
  79. package/crates/team-agent/src/messaging/delivery.rs +67 -8
  80. package/crates/team-agent/src/messaging/leader_channel.rs +56 -0
  81. package/crates/team-agent/src/messaging/tests/runtime.rs +10 -2
  82. package/crates/team-agent/src/messaging/watchers.rs +48 -4
  83. package/crates/team-agent/src/provider/adapters/cursor_agent.rs +2 -5
  84. package/crates/team-agent/src/state/paths.rs +17 -2
  85. package/crates/team-agent/src/state/persist.rs +97 -1
  86. package/crates/team-agent/src/state/projection.rs +18 -2
  87. package/crates/team-agent/src/state/repository.rs +29 -0
  88. package/crates/team-agent/src/state/selector.rs +23 -3
  89. package/crates/team-agent/src/test_support/models_timeout_fixture.rs +144 -0
  90. package/crates/team-agent/src/tmux_backend/tests.rs +121 -4
  91. package/crates/team-agent/src/tmux_backend.rs +208 -118
  92. package/crates/team-agent/src/transport.rs +72 -0
  93. package/crates/team-agent/src/transport_factory.rs +53 -0
  94. package/package.json +4 -5
  95. package/skills/team-agent/SKILL.md +45 -17
  96. package/skills/team-agent/command-coverage.json +4 -29
  97. package/npm/check-skill-links.mjs +0 -88
  98. package/skills/team-agent/references/team-agent-operator.md +0 -672
@@ -16,6 +16,8 @@
16
16
  use std::collections::BTreeSet;
17
17
  use std::fs::OpenOptions;
18
18
  use std::io::{Read, Write};
19
+ #[cfg(test)]
20
+ use std::cell::RefCell;
19
21
  use std::os::unix::fs::{OpenOptionsExt, PermissionsExt};
20
22
  use std::path::{Path, PathBuf};
21
23
  use std::process::{Command, Stdio};
@@ -588,6 +590,116 @@ fn executable_file_type(path: &Path) -> Result<PiExecutableFileType, ProviderErr
588
590
  }
589
591
  }
590
592
 
593
+ #[cfg(test)]
594
+ #[derive(Debug, Default)]
595
+ pub(crate) struct PiCatalogTestObservation {
596
+ pub(crate) spawn_count: usize,
597
+ pub(crate) argv: Vec<String>,
598
+ pub(crate) parent_pid: Option<u32>,
599
+ pub(crate) parent_exit_success: Option<bool>,
600
+ pub(crate) parent_exit_code: Option<i32>,
601
+ pub(crate) reader_timeout: bool,
602
+ }
603
+
604
+ #[cfg(test)]
605
+ struct PiCatalogTestContext {
606
+ receipt: PathBuf,
607
+ helper_mode: Option<String>,
608
+ observation: PiCatalogTestObservation,
609
+ }
610
+
611
+ #[cfg(test)]
612
+ thread_local! {
613
+ static PI_CATALOG_TEST_CONTEXT: RefCell<Option<PiCatalogTestContext>> = RefCell::new(None);
614
+ }
615
+
616
+ #[cfg(test)]
617
+ pub(crate) fn with_pi_catalog_test_observation<T>(
618
+ receipt: &Path,
619
+ helper_mode: Option<&str>,
620
+ action: impl FnOnce() -> T,
621
+ ) -> (T, PiCatalogTestObservation) {
622
+ PI_CATALOG_TEST_CONTEXT.with(|slot| {
623
+ assert!(slot
624
+ .replace(Some(PiCatalogTestContext {
625
+ receipt: receipt.to_path_buf(),
626
+ helper_mode: helper_mode.map(str::to_owned),
627
+ observation: PiCatalogTestObservation::default(),
628
+ }))
629
+ .is_none());
630
+ let result = action();
631
+ let context = slot.take().expect("Pi catalog test context");
632
+ (result, context.observation)
633
+ })
634
+ }
635
+
636
+ #[cfg(test)]
637
+ fn observe_pi_catalog_test(f: impl FnOnce(&mut PiCatalogTestContext)) {
638
+ PI_CATALOG_TEST_CONTEXT.with(|slot| {
639
+ if let Some(context) = slot.borrow_mut().as_mut() {
640
+ f(context);
641
+ }
642
+ });
643
+ }
644
+
645
+ fn spawn_catalog_reader(
646
+ stdout: std::process::ChildStdout,
647
+ max_bytes: u64,
648
+ ) -> mpsc::Receiver<(std::io::Result<usize>, Vec<u8>)> {
649
+ let (sender, receiver) = mpsc::channel();
650
+ std::thread::spawn(move || {
651
+ let mut bytes = Vec::new();
652
+ let result = stdout.take(max_bytes + 1).read_to_end(&mut bytes);
653
+ let _ = sender.send((result, bytes));
654
+ });
655
+ receiver
656
+ }
657
+
658
+ fn finish_catalog_reader(
659
+ receiver: mpsc::Receiver<(std::io::Result<usize>, Vec<u8>)>,
660
+ status: std::process::ExitStatus,
661
+ timeout: Duration,
662
+ max_bytes: u64,
663
+ ) -> Result<Vec<u8>, String> {
664
+ let (result, bytes) = match receiver.recv_timeout(timeout) {
665
+ Ok(value) => value,
666
+ Err(_) => {
667
+ #[cfg(test)]
668
+ observe_pi_catalog_test(|context| context.observation.reader_timeout = true);
669
+ return Err("Pi model catalog command timed out".to_string());
670
+ }
671
+ };
672
+ if !status.success() {
673
+ return Err("Pi model catalog command failed".into());
674
+ }
675
+ result.map_err(|_| "Pi model catalog could not be read".to_string())?;
676
+ if bytes.len() as u64 > max_bytes {
677
+ return Err("Pi model catalog exceeds the bounded output limit".into());
678
+ }
679
+ Ok(bytes)
680
+ }
681
+
682
+ #[cfg(test)]
683
+ pub(crate) fn run_pi_catalog_after_parent_exit_for_test(
684
+ stdout: std::process::ChildStdout,
685
+ parent_pid: u32,
686
+ status: std::process::ExitStatus,
687
+ timeout: Duration,
688
+ max_bytes: u64,
689
+ ) -> Result<Vec<u8>, String> {
690
+ observe_pi_catalog_test(|context| {
691
+ context.observation.parent_pid = Some(parent_pid);
692
+ context.observation.parent_exit_success = Some(status.success());
693
+ context.observation.parent_exit_code = status.code();
694
+ });
695
+ finish_catalog_reader(
696
+ spawn_catalog_reader(stdout, max_bytes),
697
+ status,
698
+ timeout,
699
+ max_bytes,
700
+ )
701
+ }
702
+
591
703
  /// Discover candidates with one PATH-first catalog observation. This deliberately
592
704
  /// does not resolve adapters or scan wrapper chains; callers use it only for
593
705
  /// rejecting an unqualified role model before lifecycle mutation.
@@ -596,8 +708,18 @@ pub(crate) fn run_pi_catalog(
596
708
  timeout: Duration,
597
709
  max_bytes: u64,
598
710
  ) -> Result<Vec<u8>, String> {
599
- let mut child = Command::new(executable)
600
- .arg("--list-models")
711
+ let mut command = Command::new(executable);
712
+ command.arg("--list-models");
713
+ #[cfg(test)]
714
+ observe_pi_catalog_test(|context| {
715
+ context.observation.spawn_count += 1;
716
+ context.observation.argv.push("--list-models".to_string());
717
+ command.env("TEAM_AGENT_MODELS_TIMEOUT_RECEIPT", &context.receipt);
718
+ if let Some(mode) = context.helper_mode.as_deref() {
719
+ command.env("TEAM_AGENT_MODELS_TIMEOUT_MODE", mode);
720
+ }
721
+ });
722
+ let mut child = command
601
723
  .stdin(Stdio::null())
602
724
  .stdout(Stdio::piped())
603
725
  .stderr(Stdio::null())
@@ -614,27 +736,29 @@ pub(crate) fn run_pi_catalog(
614
736
  let _ = error;
615
737
  "Pi executable is unavailable on PATH".to_string()
616
738
  })?;
739
+ #[cfg(test)]
740
+ observe_pi_catalog_test(|context| context.observation.parent_pid = Some(child.id()));
617
741
  let stdout = child.stdout.take().ok_or_else(|| {
618
742
  let _ = child.kill();
619
743
  let _ = child.wait();
620
744
  "Pi model catalog output unavailable".to_string()
621
745
  })?;
622
- let (sender, receiver) = mpsc::channel();
623
- std::thread::spawn(move || {
624
- let mut bytes = Vec::new();
625
- let result = stdout.take(max_bytes + 1).read_to_end(&mut bytes);
626
- let _ = sender.send((result, bytes));
627
- });
746
+ let receiver = spawn_catalog_reader(stdout, max_bytes);
628
747
  let start = Instant::now();
629
748
  loop {
630
749
  match child.try_wait() {
631
750
  Ok(Some(status)) => {
632
- let (result, bytes) = receiver.recv_timeout(timeout.saturating_sub(start.elapsed()))
633
- .map_err(|_| "Pi model catalog command timed out".to_string())?;
634
- if !status.success() { return Err("Pi model catalog command failed".into()); }
635
- result.map_err(|_| "Pi model catalog could not be read".to_string())?;
636
- if bytes.len() as u64 > max_bytes { return Err("Pi model catalog exceeds the bounded output limit".into()); }
637
- return Ok(bytes);
751
+ #[cfg(test)]
752
+ observe_pi_catalog_test(|context| {
753
+ context.observation.parent_exit_success = Some(status.success());
754
+ context.observation.parent_exit_code = status.code();
755
+ });
756
+ return finish_catalog_reader(
757
+ receiver,
758
+ status,
759
+ timeout.saturating_sub(start.elapsed()),
760
+ max_bytes,
761
+ );
638
762
  }
639
763
  Ok(None) if start.elapsed() < timeout => std::thread::sleep(Duration::from_millis(20)),
640
764
  Ok(None) => {