@team-agent/installer 0.3.35 → 0.3.36

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
@@ -566,7 +566,7 @@ dependencies = [
566
566
 
567
567
  [[package]]
568
568
  name = "team-agent"
569
- version = "0.3.35"
569
+ version = "0.3.36"
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.3.35"
12
+ version = "0.3.36"
13
13
  license = "AGPL-3.0"
14
14
  rust-version = "1.95"
15
15
 
@@ -152,7 +152,7 @@ fn quickstart_human(value: &Value) -> String {
152
152
  .map(|items| items.iter().filter_map(Value::as_str).collect())
153
153
  .unwrap_or_default();
154
154
  if attach.is_empty() {
155
- return summary.to_string();
155
+ return append_reminder(summary.to_string(), crate::cli::QUICK_START_REMINDER);
156
156
  }
157
157
  let mut out = String::from(summary);
158
158
  out.push_str("\n\nattach:");
@@ -160,7 +160,15 @@ fn quickstart_human(value: &Value) -> String {
160
160
  out.push_str("\n ");
161
161
  out.push_str(cmd);
162
162
  }
163
- out
163
+ append_reminder(out, crate::cli::QUICK_START_REMINDER)
164
+ }
165
+
166
+ fn append_reminder(text: String, reminder: &str) -> String {
167
+ if text.is_empty() {
168
+ reminder.to_string()
169
+ } else {
170
+ format!("{text}\n{reminder}")
171
+ }
164
172
  }
165
173
 
166
174
  /// `cmd_compile`(`commands.py:42`)。
@@ -240,7 +248,10 @@ pub fn cmd_status_for_team(args: &StatusArgs, team: Option<&str>) -> Result<CmdR
240
248
  true,
241
249
  false,
242
250
  )?;
243
- return Ok(CmdResult::human(format_status_summary(&value)));
251
+ return Ok(CmdResult::human(append_reminder(
252
+ format_status_summary(&value),
253
+ crate::cli::STATUS_REMINDER,
254
+ )));
244
255
  }
245
256
  if args.json {
246
257
  let value = status_port::status_scoped(
@@ -252,12 +263,15 @@ pub fn cmd_status_for_team(args: &StatusArgs, team: Option<&str>) -> Result<CmdR
252
263
  )?;
253
264
  return Ok(CmdResult::from_json(value, true));
254
265
  }
255
- Ok(CmdResult::human(status_port::format_status_scoped(
256
- &selected.run_workspace,
257
- &selected.state,
258
- Some(&selected.team_key),
259
- args.agent.as_deref(),
260
- )?))
266
+ Ok(CmdResult::human(append_reminder(
267
+ status_port::format_status_scoped(
268
+ &selected.run_workspace,
269
+ &selected.state,
270
+ Some(&selected.team_key),
271
+ args.agent.as_deref(),
272
+ )?,
273
+ crate::cli::STATUS_REMINDER,
274
+ )))
261
275
  }
262
276
 
263
277
  fn status_selector_error_payload(error: &str, workspace: &Path) -> Value {
@@ -276,6 +290,7 @@ fn status_selector_error_payload(error: &str, workspace: &Path) -> Value {
276
290
  "action": "run `team-agent doctor` or inspect the log path shown here",
277
291
  "log": log_path.to_string_lossy().to_string(),
278
292
  "workspace": workspace.to_string_lossy().to_string(),
293
+ "reminder": crate::cli::STATUS_REMINDER,
279
294
  })
280
295
  }
281
296
 
@@ -1583,15 +1598,22 @@ mod tests {
1583
1598
  assert!(out.contains("team started"), "must keep summary; got {out}");
1584
1599
  assert!(out.contains("attach:"), "must render attach block; got {out}");
1585
1600
  assert!(out.contains("team-y:w1") && out.contains("team-y:w2"), "must list each attach cmd; got {out}");
1601
+ assert!(out.ends_with(crate::cli::QUICK_START_REMINDER), "must append harness reminder; got {out}");
1586
1602
  }
1587
1603
 
1588
1604
  #[test]
1589
1605
  fn e13_quickstart_human_summary_only_when_no_attach() {
1590
1606
  let value = json!({"summary": "quick-start complete"});
1591
- assert_eq!(quickstart_human(&value), "quick-start complete");
1607
+ assert_eq!(
1608
+ quickstart_human(&value),
1609
+ format!("quick-start complete\n{}", crate::cli::QUICK_START_REMINDER)
1610
+ );
1592
1611
  // 空数组也只 summary。
1593
1612
  let value2 = json!({"summary": "s", "attach_commands": []});
1594
- assert_eq!(quickstart_human(&value2), "s");
1613
+ assert_eq!(
1614
+ quickstart_human(&value2),
1615
+ format!("s\n{}", crate::cli::QUICK_START_REMINDER)
1616
+ );
1595
1617
  }
1596
1618
 
1597
1619
  #[test]
@@ -48,6 +48,9 @@ use crate::messaging::{self, AlertType, MessageTarget, SendOptions};
48
48
  use crate::model::ids::{TaskId, TeamKey};
49
49
 
50
50
  pub(crate) const COMMS_BOUNDARY_TEXT: &str = "validates live pane binding consistency and zero-token comms contracts. Does NOT perform live runtime message round-trip. (zero token, zero pollution)";
51
+ pub(crate) const QUICK_START_REMINDER: &str = "Reminder: Do not inspect raw worker terminal output during normal operation. Use team-agent status / inbox / collect instead. Wait for report_result.";
52
+ pub(crate) const SEND_REMINDER: &str = "Message delivered. Wait for the worker to report_result. Do not poll the worker terminal with capture-pane.";
53
+ pub(crate) const STATUS_REMINDER: &str = "To wait for results use --watch-result or team-agent collect. Do not capture-pane worker terminals.";
51
54
 
52
55
  pub mod adapters;
53
56
  pub mod diagnose;
@@ -2528,6 +2531,7 @@ pub mod lifecycle_port {
2528
2531
  "display_backend": display_backend,
2529
2532
  "next_actions": next_actions,
2530
2533
  "attach_commands": attach_commands,
2534
+ "reminder": crate::cli::QUICK_START_REMINDER,
2531
2535
  "readiness": readiness_json.clone(),
2532
2536
  "worker_readiness": readiness_json,
2533
2537
  })
@@ -2546,6 +2550,7 @@ pub mod lifecycle_port {
2546
2550
  "state_path": state_path.map(|p| p.to_string_lossy().to_string()),
2547
2551
  "next_actions": next_actions,
2548
2552
  "attach_commands": attach_commands,
2553
+ "reminder": crate::cli::QUICK_START_REMINDER,
2549
2554
  }),
2550
2555
  crate::lifecycle::QuickStartReport::PreflightBlocked {
2551
2556
  summary,
@@ -2558,6 +2563,7 @@ pub mod lifecycle_port {
2558
2563
  "blockers": blockers,
2559
2564
  "next_actions": next_actions,
2560
2565
  "attach_commands": attach_commands,
2566
+ "reminder": crate::cli::QUICK_START_REMINDER,
2561
2567
  }),
2562
2568
  }
2563
2569
  }
@@ -2582,6 +2588,10 @@ pub mod lifecycle_port {
2582
2588
  Some("tmux -S /tmp/tmux-501/ta-test attach -t team-teamA:worker"),
2583
2589
  "B-2: ExistingRuntime JSON must preserve attach_commands instead of only next_actions; value={value}"
2584
2590
  );
2591
+ assert_eq!(
2592
+ value.get("reminder").and_then(Value::as_str),
2593
+ Some(crate::cli::QUICK_START_REMINDER)
2594
+ );
2585
2595
  }
2586
2596
 
2587
2597
  #[test]
@@ -2598,6 +2608,20 @@ pub mod lifecycle_port {
2598
2608
  "B-2: PreflightBlocked JSON must include attach_commands: [] for schema parity with Ready/Restart; value={value}"
2599
2609
  );
2600
2610
  }
2611
+
2612
+ #[test]
2613
+ fn restart_json_includes_harness_reminder() {
2614
+ let value = restart_value(crate::lifecycle::RestartReport::RefusedResumeAtomicity {
2615
+ unresumable: Vec::new(),
2616
+ allow_fresh: false,
2617
+ error: "resume refused".to_string(),
2618
+ });
2619
+
2620
+ assert_eq!(
2621
+ value.get("reminder").and_then(Value::as_str),
2622
+ Some(crate::cli::QUICK_START_REMINDER)
2623
+ );
2624
+ }
2601
2625
  }
2602
2626
 
2603
2627
  fn restart_value(report: crate::lifecycle::RestartReport) -> Value {
@@ -2616,6 +2640,7 @@ pub mod lifecycle_port {
2616
2640
  "coordinator_started": coordinator_started,
2617
2641
  "next_actions": next_actions,
2618
2642
  "attach_commands": attach_commands,
2643
+ "reminder": crate::cli::QUICK_START_REMINDER,
2619
2644
  }),
2620
2645
  crate::lifecycle::RestartReport::Partial {
2621
2646
  session_name,
@@ -2650,6 +2675,7 @@ pub mod lifecycle_port {
2650
2675
  "coordinator_started": coordinator_started,
2651
2676
  "next_actions": next_actions,
2652
2677
  "attach_commands": attach_commands,
2678
+ "reminder": crate::cli::QUICK_START_REMINDER,
2653
2679
  }),
2654
2680
  crate::lifecycle::RestartReport::Failed {
2655
2681
  session_name,
@@ -2681,6 +2707,7 @@ pub mod lifecycle_port {
2681
2707
  })).collect::<Vec<_>>(),
2682
2708
  "next_actions": next_actions,
2683
2709
  "attach_commands": attach_commands,
2710
+ "reminder": crate::cli::QUICK_START_REMINDER,
2684
2711
  }),
2685
2712
  crate::lifecycle::RestartReport::RefusedResumeAtomicity {
2686
2713
  unresumable,
@@ -2692,6 +2719,7 @@ pub mod lifecycle_port {
2692
2719
  "allow_fresh": allow_fresh,
2693
2720
  "error": error,
2694
2721
  "unresumable": unresumable.iter().map(|w| w.agent_id.as_str()).collect::<Vec<_>>(),
2722
+ "reminder": crate::cli::QUICK_START_REMINDER,
2695
2723
  }),
2696
2724
  crate::lifecycle::RestartReport::RefusedResumeNotReady {
2697
2725
  missing,
@@ -2716,6 +2744,7 @@ pub mod lifecycle_port {
2716
2744
  "pending_agent_ids": missing.iter().map(|w| w.as_str()).collect::<Vec<_>>(),
2717
2745
  },
2718
2746
  "next_action": "rerun restart after session capture completes, or pass --allow-fresh to deliberately discard missing context",
2747
+ "reminder": crate::cli::QUICK_START_REMINDER,
2719
2748
  }),
2720
2749
  crate::lifecycle::RestartReport::RefusedInvalidFirstSendAt {
2721
2750
  invalid,
@@ -2727,6 +2756,7 @@ pub mod lifecycle_port {
2727
2756
  "allow_fresh": allow_fresh,
2728
2757
  "error": error,
2729
2758
  "invalid": invalid.iter().map(|w| w.worker_id.as_str()).collect::<Vec<_>>(),
2759
+ "reminder": crate::cli::QUICK_START_REMINDER,
2730
2760
  }),
2731
2761
  }
2732
2762
  }
@@ -22,7 +22,7 @@ pub fn cmd_send(args: &SendArgs) -> Result<CmdResult, CliError> {
22
22
  if content.is_empty() {
23
23
  return Err(CliError::Usage("--pane requires a non-empty message".to_string()));
24
24
  }
25
- let value = send_to_pane_direct(
25
+ let mut value = send_to_pane_direct(
26
26
  &args.workspace,
27
27
  pane_id,
28
28
  &content,
@@ -31,6 +31,7 @@ pub fn cmd_send(args: &SendArgs) -> Result<CmdResult, CliError> {
31
31
  args.team.as_deref(),
32
32
  args.json,
33
33
  )?;
34
+ add_send_reminder_if_ok(&mut value);
34
35
  return Ok(CmdResult::from_json(value, args.json));
35
36
  }
36
37
  let selected = crate::state::selector::resolve_active_team(
@@ -60,6 +61,7 @@ pub fn cmd_send(args: &SendArgs) -> Result<CmdResult, CliError> {
60
61
  obj.insert("watch".to_string(), watch_notice_json(&target, &opts));
61
62
  }
62
63
  }
64
+ add_send_reminder_if_ok(&mut value);
63
65
  Ok(CmdResult::from_json(value, args.json))
64
66
  }
65
67
 
@@ -471,6 +473,15 @@ fn delivery_outcome_json(
471
473
  })
472
474
  }
473
475
 
476
+ fn add_send_reminder_if_ok(value: &mut Value) {
477
+ if value.get("ok").and_then(Value::as_bool) != Some(true) {
478
+ return;
479
+ }
480
+ if let Some(obj) = value.as_object_mut() {
481
+ obj.insert("reminder".to_string(), json!(crate::cli::SEND_REMINDER));
482
+ }
483
+ }
484
+
474
485
  fn target_json(target: &MessageTarget) -> Value {
475
486
  match target {
476
487
  MessageTarget::Single(agent) => json!(agent),
@@ -99,6 +99,7 @@ use rusqlite::params;
99
99
  "readiness": readiness,
100
100
  "coordinator": coordinator_health_value(health),
101
101
  "runtime": runtime_block,
102
+ "reminder": crate::cli::STATUS_REMINDER,
102
103
  "last_events": Value::Array(
103
104
  crate::event_log::EventLog::new(workspace)
104
105
  .tail(10)
@@ -598,6 +599,7 @@ use rusqlite::params;
598
599
  "latest_results": take_array(full.get("latest_results"), 5),
599
600
  "readiness": full.get("readiness").cloned().unwrap_or_else(|| json!({})),
600
601
  "coordinator": compact_object(full.get("coordinator"), &["status", "pid", "metadata_ok", "schema_ok"]),
602
+ "reminder": full.get("reminder").cloned().unwrap_or_else(|| json!(crate::cli::STATUS_REMINDER)),
601
603
  "last_events": take_array_tail(full.get("last_events"), 10),
602
604
  })
603
605
  }
@@ -50,10 +50,15 @@ use super::*;
50
50
  "results",
51
51
  "latest_results",
52
52
  "coordinator",
53
+ "reminder",
53
54
  "last_events",
54
55
  ] {
55
56
  assert!(obj.contains_key(key), "compact status missing key `{key}`");
56
57
  }
58
+ assert_eq!(
59
+ obj.get("reminder").and_then(|v| v.as_str()),
60
+ Some(crate::cli::STATUS_REMINDER)
61
+ );
57
62
  // seeded agent surfaces through the projection.
58
63
  assert!(
59
64
  obj["agents"].as_object().unwrap().contains_key("a1"),
@@ -65,6 +70,27 @@ use super::*;
65
70
  let _ = std::fs::remove_dir_all(&ws);
66
71
  }
67
72
 
73
+ #[test]
74
+ fn cmd_status_human_appends_harness_reminder() {
75
+ let ws = seed_status_workspace();
76
+ let args = StatusArgs {
77
+ agent: None,
78
+ workspace: ws.clone(),
79
+ detail: false,
80
+ summary: false,
81
+ json: false,
82
+ };
83
+
84
+ let r = cmd_status_for_team(&args, None).expect("status");
85
+ let text = match r.output {
86
+ CmdOutput::Human(text) => text,
87
+ other => panic!("expected human status output, got {other:?}"),
88
+ };
89
+
90
+ assert!(text.ends_with(crate::cli::STATUS_REMINDER), "{text}");
91
+ let _ = std::fs::remove_dir_all(&ws);
92
+ }
93
+
68
94
  #[test]
69
95
  fn status_port_status_reports_managed_leader_topology_and_attach_command() {
70
96
  let ws = seed_status_workspace();
@@ -255,6 +281,12 @@ use super::*;
255
281
  match r.output {
256
282
  CmdOutput::Json(ref v) => {
257
283
  assert!(v.get("ok").is_some(), "send result Json must carry `ok`");
284
+ if v.get("ok").and_then(|ok| ok.as_bool()) == Some(true) {
285
+ assert_eq!(
286
+ v.get("reminder").and_then(|reminder| reminder.as_str()),
287
+ Some(crate::cli::SEND_REMINDER)
288
+ );
289
+ }
258
290
  }
259
291
  other => panic!("cmd_send must emit Json DeliveryOutcome, got {other:?}"),
260
292
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-agent/installer",
3
- "version": "0.3.35",
3
+ "version": "0.3.36",
4
4
  "description": "npx installer for Team Agent",
5
5
  "keywords": [
6
6
  "codex",
@@ -20,9 +20,9 @@
20
20
  "team-agent-installer": "npm/install.mjs"
21
21
  },
22
22
  "optionalDependencies": {
23
- "@team-agent/cli-darwin-arm64": "0.3.35",
24
- "@team-agent/cli-darwin-x64": "0.3.35",
25
- "@team-agent/cli-linux-x64": "0.3.35"
23
+ "@team-agent/cli-darwin-arm64": "0.3.36",
24
+ "@team-agent/cli-darwin-x64": "0.3.36",
25
+ "@team-agent/cli-linux-x64": "0.3.36"
26
26
  },
27
27
  "scripts": {
28
28
  "postinstall": "node npm/bincheck.mjs",