@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.
- package/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/crates/team-agent/src/cli/adapters.rs +1 -0
- package/crates/team-agent/src/cli/diagnose.rs +2 -15
- package/crates/team-agent/src/cli/emit.rs +98 -5
- package/crates/team-agent/src/cli/mod.rs +2 -0
- package/crates/team-agent/src/cli/named_address.rs +864 -0
- package/crates/team-agent/src/cli/send.rs +104 -0
- package/crates/team-agent/src/cli/tests/leader_watch.rs +1 -0
- package/crates/team-agent/src/cli/tests/mod.rs +1 -0
- package/crates/team-agent/src/cli/tests/named_address.rs +455 -0
- package/crates/team-agent/src/cli/tests/status_send.rs +1 -0
- package/crates/team-agent/src/cli/types.rs +4 -0
- package/crates/team-agent/src/compiler.rs +11 -20
- package/crates/team-agent/src/coordinator/orphan.rs +2 -2
- package/crates/team-agent/src/coordinator/runtime_detectors.rs +5 -4
- package/crates/team-agent/src/coordinator/steps/abnormal.rs +1776 -2
- package/crates/team-agent/src/coordinator/steps/mod.rs +19 -0
- package/crates/team-agent/src/coordinator/tests/a0_lostupdate.rs +78 -7
- package/crates/team-agent/src/coordinator/tests/abnormal.rs +195 -0
- package/crates/team-agent/src/coordinator/tick.rs +31 -932
- package/crates/team-agent/src/diagnose/orphans.rs +66 -8
- package/crates/team-agent/src/layout/worker_window_helpers.rs +5 -7
- package/crates/team-agent/src/leader/provider_attribution.rs +7 -5
- package/crates/team-agent/src/leader/rediscover.rs +1 -11
- package/crates/team-agent/src/lifecycle/launch/plan.rs +19 -8
- package/crates/team-agent/src/lifecycle/launch.rs +135 -58
- package/crates/team-agent/src/lifecycle/lock.rs +302 -0
- package/crates/team-agent/src/lifecycle/mod.rs +1 -0
- package/crates/team-agent/src/lifecycle/profile_smoke.rs +1 -11
- package/crates/team-agent/src/lifecycle/restart/agent.rs +169 -113
- package/crates/team-agent/src/lifecycle/restart/common.rs +108 -17
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +165 -32
- package/crates/team-agent/src/lifecycle/restart/remove.rs +16 -2
- package/crates/team-agent/src/lifecycle/restart/selection.rs +2 -1
- package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +6 -0
- package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +3 -3
- package/crates/team-agent/src/lifecycle/tests/lifecycle_lock.rs +321 -0
- package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +35 -5
- package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +802 -0
- package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +675 -0
- package/crates/team-agent/src/lifecycle/tests.rs +3 -0
- package/crates/team-agent/src/lifecycle/types.rs +8 -0
- package/crates/team-agent/src/mcp_server/lifecycle_tools/state_status.rs +24 -9
- package/crates/team-agent/src/mcp_server/tools.rs +157 -68
- package/crates/team-agent/src/messaging/activity.rs +43 -18
- package/crates/team-agent/src/messaging/delivery.rs +161 -97
- package/crates/team-agent/src/messaging/helpers.rs +1 -0
- package/crates/team-agent/src/messaging/leader_receiver.rs +22 -1
- package/crates/team-agent/src/messaging/results.rs +34 -9
- package/crates/team-agent/src/messaging/scheduler.rs +52 -9
- package/crates/team-agent/src/model/spec.rs +10 -6
- package/crates/team-agent/src/provider/adapter.rs +10 -1038
- package/crates/team-agent/src/provider/adapters/claude.rs +3 -8
- package/crates/team-agent/src/provider/adapters/copilot.rs +2 -5
- package/crates/team-agent/src/provider/classify.rs +23 -48
- package/crates/team-agent/src/provider/command.rs +16 -7
- package/crates/team-agent/src/provider/faults.rs +93 -53
- package/crates/team-agent/src/provider/session/capture.rs +4 -15
- package/crates/team-agent/src/provider/session_scan/claude.rs +309 -0
- package/crates/team-agent/src/provider/session_scan/codex.rs +40 -0
- package/crates/team-agent/src/provider/session_scan/common.rs +350 -0
- package/crates/team-agent/src/provider/session_scan/copilot.rs +202 -0
- package/crates/team-agent/src/provider/session_scan.rs +65 -27
- package/crates/team-agent/src/provider/tests/faults.rs +80 -0
- package/crates/team-agent/src/provider/types.rs +33 -1
- package/crates/team-agent/src/provider/wire.rs +171 -1
- package/crates/team-agent/src/state/identity.rs +242 -57
- package/crates/team-agent/src/state/identity_keys.rs +9 -12
- package/crates/team-agent/src/state/mod.rs +5 -1
- package/crates/team-agent/src/state/owner_gate.rs +59 -15
- package/crates/team-agent/src/state/ownership.rs +12 -11
- package/crates/team-agent/src/state/paths.rs +13 -6
- package/crates/team-agent/src/state/persist.rs +671 -128
- package/crates/team-agent/src/state/projection.rs +240 -49
- package/crates/team-agent/src/state/selector.rs +11 -5
- package/crates/team-agent/src/tmux_backend/tests.rs +51 -2
- package/crates/team-agent/src/tmux_backend.rs +42 -5
- package/crates/team-agent/src/transport/test_support.rs +55 -6
- package/package.json +4 -4
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
|
@@ -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
|
|
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 =
|
|
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> =
|
|
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::*;
|