@team-agent/installer 0.5.81 → 0.5.83

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 CHANGED
@@ -581,7 +581,7 @@ dependencies = [
581
581
 
582
582
  [[package]]
583
583
  name = "team-agent"
584
- version = "0.5.81"
584
+ version = "0.5.83"
585
585
  dependencies = [
586
586
  "anyhow",
587
587
  "chrono",
package/Cargo.toml CHANGED
@@ -9,7 +9,7 @@ members = ["crates/team-agent", "crates/win-conpty-phase0", "crates/conpty-trans
9
9
 
10
10
  [workspace.package]
11
11
  edition = "2021"
12
- version = "0.5.81"
12
+ version = "0.5.83"
13
13
  license = "AGPL-3.0"
14
14
  rust-version = "1.95"
15
15
 
@@ -218,7 +218,7 @@ fn dispatch(command: &str, args: &[String], cwd: &Path) -> Result<ExitCode, CliE
218
218
  // resolve short/qualified/hash-qualified names to a canonical
219
219
  // (workspace, team_key) tuple and delegates to the E6 named-leader
220
220
  // delivery path — no separate route authority.
221
- "leaders" => cmd_leaders(&leaders_args(args, cwd)).map(emit_result),
221
+ "leaders" => cmd_leaders(&leaders_args(args, cwd)?).map(emit_result),
222
222
  "models" => cmd_models(&models_args(args)?).map(emit_result),
223
223
  "validate" => cmd_validate(&validate_args(args, cwd)).map(emit_result),
224
224
  "install-skill" => cmd_install_skill(&install_skill_args(args)?).map(emit_result),
@@ -324,7 +324,15 @@ pub(crate) fn default_help() -> String {
324
324
  append_help_section(
325
325
  &mut out,
326
326
  "Core",
327
- &["quick-start", "send", "status", "collect", "results", "models"],
327
+ &[
328
+ "quick-start",
329
+ "send",
330
+ "status",
331
+ "collect",
332
+ "results",
333
+ "models",
334
+ "leaders",
335
+ ],
328
336
  );
329
337
  append_help_section(
330
338
  &mut out,
@@ -411,6 +419,7 @@ fn command_help(command: Option<&str>) -> String {
411
419
  Some("allow-peer-talk") => "usage: team-agent allow-peer-talk A B [--workspace WORKSPACE] [--json]".to_string(),
412
420
  Some("status") => "usage: team-agent status [AGENT] [--workspace WORKSPACE] [--team TEAM] [--summary|--json] [--detail]\n\n输出七字段:name/provider/runtime_status/activity/health/session_name/tmux_command;人读与 --json 使用同一投影。缺少可靠定位或 nodeprobe 证据时显示 unknown;tmux_command 可复制到对应目标。--summary/--detail 仅保留兼容性,不增加诊断字段。".to_string(),
413
421
  Some("models") => "usage: team-agent models --provider pi [--search TEXT] [--json]\n\nPrints models.v1 exact role_model entries; each entry includes current=true|false. Catalog readiness is reported as auth=ok|not_ready with auth_basis=catalog_visibility.".to_string(),
422
+ Some("leaders") => "usage: team-agent leaders [QUERY|--search TEXT] [--all|--stale] [--json] | --prune [--dry-run] [--json]\n\nLists LIVE leaders by default. Use --all to include retained STALE entries, --stale to inspect only STALE entries, QUERY or --search TEXT to match workspace/team/name fields, and --prune to remove only entries proven terminal by canonical state. --dry-run is valid only with --prune.".to_string(),
414
423
  Some("stop") => compat_hidden_help("stop", "usage: team-agent stop [--workspace WORKSPACE] [--team TEAM] [--keep-logs] [--json]"),
415
424
  Some("shutdown") => "usage: team-agent shutdown [--workspace WORKSPACE] [--team TEAM] [--keep-logs] [--json]".to_string(),
416
425
  Some("restart") => "usage: team-agent restart [WORKSPACE] [--team TEAM] [--allow-fresh] [--session-converge-deadline SECONDS] [--json] [--detail]".to_string(),
@@ -1683,9 +1692,109 @@ fn sessions_args(args: &[String], cwd: &Path) -> SessionsArgs {
1683
1692
  }
1684
1693
  }
1685
1694
 
1686
- fn leaders_args(args: &[String], _cwd: &Path) -> LeadersArgs {
1687
- let parsed = parse_args(args);
1688
- LeadersArgs { json: parsed.json }
1695
+ fn leaders_args(args: &[String], _cwd: &Path) -> Result<LeadersArgs, CliError> {
1696
+ let mut view = None;
1697
+ let mut query = None;
1698
+ let mut prune = false;
1699
+ let mut dry_run = false;
1700
+ let mut json = false;
1701
+ let mut i = 0usize;
1702
+ while i < args.len() {
1703
+ let arg = &args[i];
1704
+ match arg.as_str() {
1705
+ "--json" => json = true,
1706
+ "--all" => {
1707
+ if view.replace(LeadersView::All).is_some() {
1708
+ return Err(CliError::Usage(
1709
+ "leaders accepts only one of --all or --stale".to_string(),
1710
+ ));
1711
+ }
1712
+ }
1713
+ "--stale" => {
1714
+ if view.replace(LeadersView::Stale).is_some() {
1715
+ return Err(CliError::Usage(
1716
+ "leaders accepts only one of --all or --stale".to_string(),
1717
+ ));
1718
+ }
1719
+ }
1720
+ "--prune" => {
1721
+ if prune {
1722
+ return Err(CliError::Usage(
1723
+ "leaders accepts --prune at most once".to_string(),
1724
+ ));
1725
+ }
1726
+ prune = true;
1727
+ }
1728
+ "--dry-run" => dry_run = true,
1729
+ "--search" => {
1730
+ let Some(value) = args.get(i.saturating_add(1)) else {
1731
+ return Err(CliError::Usage(
1732
+ "leaders --search requires TEXT".to_string(),
1733
+ ));
1734
+ };
1735
+ if value.starts_with('-') {
1736
+ return Err(CliError::Usage(
1737
+ "leaders --search requires TEXT".to_string(),
1738
+ ));
1739
+ }
1740
+ i = i.saturating_add(1);
1741
+ if query.replace(value.clone()).is_some() {
1742
+ return Err(CliError::Usage(
1743
+ "leaders accepts only one QUERY or --search TEXT".to_string(),
1744
+ ));
1745
+ }
1746
+ }
1747
+ value if value.starts_with("--search=") => {
1748
+ let value = value.trim_start_matches("--search=").to_string();
1749
+ if query.replace(value).is_some() {
1750
+ return Err(CliError::Usage(
1751
+ "leaders accepts only one QUERY or --search TEXT".to_string(),
1752
+ ));
1753
+ }
1754
+ }
1755
+ value if value.starts_with('-') => {
1756
+ return Err(CliError::Usage(format!(
1757
+ "unknown leaders argument: {value}"
1758
+ )))
1759
+ }
1760
+ value => {
1761
+ if query.replace(value.to_string()).is_some() {
1762
+ return Err(CliError::Usage(
1763
+ "leaders accepts only one QUERY or --search TEXT".to_string(),
1764
+ ));
1765
+ }
1766
+ }
1767
+ }
1768
+ i = i.saturating_add(1);
1769
+ }
1770
+ if query
1771
+ .as_deref()
1772
+ .is_some_and(|value| value.trim().is_empty())
1773
+ {
1774
+ return Err(CliError::Usage("leaders QUERY cannot be blank".to_string()));
1775
+ }
1776
+ if prune && view.is_some() {
1777
+ return Err(CliError::Usage(
1778
+ "leaders --prune cannot be combined with --all or --stale".to_string(),
1779
+ ));
1780
+ }
1781
+ if prune && query.is_some() {
1782
+ return Err(CliError::Usage(
1783
+ "leaders --prune cannot be combined with QUERY or --search".to_string(),
1784
+ ));
1785
+ }
1786
+ if dry_run && !prune {
1787
+ return Err(CliError::Usage(
1788
+ "leaders --dry-run requires --prune".to_string(),
1789
+ ));
1790
+ }
1791
+ Ok(LeadersArgs {
1792
+ view: view.unwrap_or(LeadersView::Live),
1793
+ query,
1794
+ prune,
1795
+ dry_run,
1796
+ json,
1797
+ })
1689
1798
  }
1690
1799
 
1691
1800
  fn validate_args(args: &[String], cwd: &Path) -> ValidateArgs {
@@ -1935,6 +2044,37 @@ mod tests {
1935
2044
  .collect()
1936
2045
  }
1937
2046
 
2047
+ #[test]
2048
+ fn leaders_parser_supports_views_and_search() {
2049
+ let parsed = leaders_args(
2050
+ &cli_argv(&["--all", "--search", "Wiki", "--json"]),
2051
+ Path::new("."),
2052
+ )
2053
+ .unwrap();
2054
+ assert_eq!(parsed.view, LeadersView::All);
2055
+ assert_eq!(parsed.query.as_deref(), Some("Wiki"));
2056
+ assert!(!parsed.prune);
2057
+ assert!(!parsed.dry_run);
2058
+ assert!(parsed.json);
2059
+ }
2060
+
2061
+ #[test]
2062
+ fn leaders_parser_rejects_invalid_search_and_prune_combinations() {
2063
+ for args in [
2064
+ cli_argv(&["one", "two"]),
2065
+ cli_argv(&["one", "--search", "two"]),
2066
+ cli_argv(&["--search", " "]),
2067
+ cli_argv(&["--dry-run"]),
2068
+ cli_argv(&["--prune", "--stale"]),
2069
+ cli_argv(&["--prune", "--search", "x"]),
2070
+ ] {
2071
+ assert!(
2072
+ leaders_args(&args, Path::new(".")).is_err(),
2073
+ "args={args:?}"
2074
+ );
2075
+ }
2076
+ }
2077
+
1938
2078
  #[test]
1939
2079
  fn command_specs_have_unique_names_and_valid_aliases() {
1940
2080
  let mut names = std::collections::BTreeSet::new();
@@ -2031,6 +2171,16 @@ mod tests {
2031
2171
  }
2032
2172
  }
2033
2173
 
2174
+ #[test]
2175
+ fn leaders_help_publishes_selectors_and_prune() {
2176
+ let help = command_help(Some("leaders"));
2177
+ assert!(help.contains("--all"));
2178
+ assert!(help.contains("--stale"));
2179
+ assert!(help.contains("--search TEXT"));
2180
+ assert!(help.contains("--prune"));
2181
+ assert!(help.contains("--dry-run"));
2182
+ }
2183
+
2034
2184
  #[test]
2035
2185
  fn compat_hidden_help_has_sunset_action() {
2036
2186
  for command in ["stop", "restart-agent", "start", "init"] {