@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.
- package/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/README.md +9 -0
- package/README.zh.md +8 -0
- package/crates/team-agent/src/cli/adapters.rs +184 -125
- package/crates/team-agent/src/cli/diagnose.rs +333 -68
- package/crates/team-agent/src/cli/emit.rs +59 -15
- package/crates/team-agent/src/cli/mod.rs +600 -134
- package/crates/team-agent/src/cli/models.rs +485 -44
- package/crates/team-agent/src/cli/named_address.rs +19 -5
- package/crates/team-agent/src/cli/profile.rs +35 -4
- package/crates/team-agent/src/cli/spec.rs +7 -2
- package/crates/team-agent/src/cli/status_port/brief.rs +1137 -0
- package/crates/team-agent/src/cli/status_port/compact.rs +12 -8
- package/crates/team-agent/src/cli/status_port/snapshot.rs +15 -12
- package/crates/team-agent/src/cli/status_port/store.rs +1 -1
- package/crates/team-agent/src/cli/status_port.rs +8 -0
- package/crates/team-agent/src/cli/tests/missing_subcommands.rs +62 -8
- package/crates/team-agent/src/cli/tests/mod.rs +1 -0
- package/crates/team-agent/src/cli/tests/named_address.rs +70 -0
- package/crates/team-agent/src/cli/tests/run_delegation.rs +29 -24
- package/crates/team-agent/src/cli/tests/status_brief.rs +691 -0
- package/crates/team-agent/src/cli/tests/status_send.rs +8 -2
- package/crates/team-agent/src/cli/tests/verb_profile.rs +81 -6
- package/crates/team-agent/src/cli/types.rs +1 -0
- package/crates/team-agent/src/leader/lease.rs +538 -41
- package/crates/team-agent/src/leader/owner_bind.rs +40 -12
- package/crates/team-agent/src/leader/rediscover/tests.rs +65 -0
- package/crates/team-agent/src/leader/rediscover.rs +36 -6
- package/crates/team-agent/src/leader/start.rs +151 -14
- package/crates/team-agent/src/leader/tests/wake_start_owner.rs +15 -9
- package/crates/team-agent/src/leader/types.rs +4 -0
- package/crates/team-agent/src/lifecycle/launch/add_agent.rs +28 -227
- package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +0 -18
- package/crates/team-agent/src/lifecycle/launch/cursor_mcp.rs +94 -227
- package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +59 -10
- package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +138 -14
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +1449 -282
- package/crates/team-agent/src/lifecycle/launch/readiness.rs +349 -4
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +11 -11
- package/crates/team-agent/src/lifecycle/launch/spec_state.rs +35 -3
- package/crates/team-agent/src/lifecycle/launch/worker_env.rs +16 -0
- package/crates/team-agent/src/lifecycle/launch.rs +30 -7
- package/crates/team-agent/src/lifecycle/profile_launch.rs +37 -3
- package/crates/team-agent/src/lifecycle/restart/agent.rs +112 -100
- package/crates/team-agent/src/lifecycle/restart/common.rs +82 -52
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +1002 -65
- package/crates/team-agent/src/lifecycle/restart.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +3 -0
- package/crates/team-agent/src/lifecycle/tests/b0_reader_hideone_audit_contract.rs +45 -14
- package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +15 -0
- package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +5 -0
- package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +11 -13
- package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +119 -3
- package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +12 -0
- package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +22 -0
- package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +12 -0
- package/crates/team-agent/src/lifecycle/tests/cursor_mcp_overlay.rs +265 -198
- package/crates/team-agent/src/lifecycle/tests/cursor_require_explicit_model_red.rs +14 -30
- package/crates/team-agent/src/lifecycle/tests/cursor_restart_resume_red.rs +3 -0
- package/crates/team-agent/src/lifecycle/tests/g1_silent_faces.rs +2 -5
- package/crates/team-agent/src/lifecycle/tests/grok_effort_argv_red.rs +10 -0
- package/crates/team-agent/src/lifecycle/tests/grok_mcp_overlay_red.rs +58 -35
- package/crates/team-agent/src/lifecycle/tests/grok_require_explicit_model_red.rs +10 -0
- package/crates/team-agent/src/lifecycle/tests/grok_restart_resume_red.rs +9 -0
- package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +4 -3
- package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +0 -168
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +145 -212
- package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +16 -2
- package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +69 -28
- package/crates/team-agent/src/lifecycle/tests/pi_dual_entry_red.rs +78 -0
- package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +3 -0
- package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +51 -10
- package/crates/team-agent/src/lifecycle/tests/upgrade_compat_0211_red.rs +22 -10
- package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +50 -7
- package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +137 -0
- package/crates/team-agent/src/lifecycle/types.rs +12 -0
- package/crates/team-agent/src/mcp_server/wire.rs +140 -11
- package/crates/team-agent/src/messaging/delivery.rs +67 -8
- package/crates/team-agent/src/messaging/leader_channel.rs +56 -0
- package/crates/team-agent/src/messaging/tests/runtime.rs +10 -2
- package/crates/team-agent/src/messaging/watchers.rs +48 -4
- package/crates/team-agent/src/provider/adapters/cursor_agent.rs +2 -5
- package/crates/team-agent/src/state/paths.rs +17 -2
- package/crates/team-agent/src/state/persist.rs +97 -1
- package/crates/team-agent/src/state/projection.rs +18 -2
- package/crates/team-agent/src/state/repository.rs +29 -0
- package/crates/team-agent/src/state/selector.rs +23 -3
- package/crates/team-agent/src/test_support/models_timeout_fixture.rs +144 -0
- package/crates/team-agent/src/tmux_backend/tests.rs +121 -4
- package/crates/team-agent/src/tmux_backend.rs +208 -118
- package/crates/team-agent/src/transport.rs +72 -0
- package/crates/team-agent/src/transport_factory.rs +53 -0
- package/package.json +4 -5
- package/skills/team-agent/SKILL.md +45 -17
- package/skills/team-agent/command-coverage.json +4 -29
- package/npm/check-skill-links.mjs +0 -88
- 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
|
|
600
|
-
|
|
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
|
|
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
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
return
|
|
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) => {
|