@team-agent/installer 0.5.77 → 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/crates/team-agent/src/cli/adapters.rs +161 -29
- package/crates/team-agent/src/cli/diagnose.rs +333 -68
- package/crates/team-agent/src/cli/emit.rs +24 -8
- package/crates/team-agent/src/cli/mod.rs +543 -98
- package/crates/team-agent/src/cli/models.rs +362 -32
- 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/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/tests/missing_subcommands.rs +62 -8
- package/crates/team-agent/src/cli/tests/named_address.rs +70 -0
- 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 +492 -33
- 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/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 +65 -18
- 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 +996 -66
- 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/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 -4
- 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 +3 -2
- 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 +54 -9
- 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/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 +8 -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/provider/adapters/cursor_agent.rs +2 -5
- package/crates/team-agent/src/state/persist.rs +97 -1
- package/crates/team-agent/src/state/repository.rs +29 -0
- package/crates/team-agent/src/test_support/models_timeout_fixture.rs +43 -21
- 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
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
|
@@ -183,10 +183,18 @@ fn quickstart_human(value: &Value) -> String {
|
|
|
183
183
|
append_reminder(out, crate::cli::QUICK_START_REMINDER)
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
fn append_send_guidance(value: &mut Value, workspace: &Path, team: Option<&str>) {
|
|
187
|
-
|
|
186
|
+
pub(crate) fn append_send_guidance(value: &mut Value, workspace: &Path, team: Option<&str>) {
|
|
187
|
+
let existing = value.get("summary").and_then(Value::as_str) == Some("existing runtime");
|
|
188
|
+
if value.get("ok").and_then(Value::as_bool) != Some(true) && !existing {
|
|
188
189
|
return;
|
|
189
190
|
}
|
|
191
|
+
let team = value
|
|
192
|
+
.get("team")
|
|
193
|
+
.and_then(Value::as_str)
|
|
194
|
+
.filter(|team| !team.is_empty())
|
|
195
|
+
.map(str::to_string)
|
|
196
|
+
.or_else(|| team.map(str::to_string));
|
|
197
|
+
let team = team.as_deref();
|
|
190
198
|
let agents = value
|
|
191
199
|
.get("agent_ids")
|
|
192
200
|
.and_then(Value::as_array)
|
|
@@ -204,11 +212,36 @@ fn append_send_guidance(value: &mut Value, workspace: &Path, team: Option<&str>)
|
|
|
204
212
|
}
|
|
205
213
|
}
|
|
206
214
|
|
|
215
|
+
#[cfg(test)]
|
|
216
|
+
pub(crate) fn split_shell_argv(command: &str) -> Vec<String> {
|
|
217
|
+
let mut argv = Vec::new();
|
|
218
|
+
let mut current = String::new();
|
|
219
|
+
let mut chars = command.chars().peekable();
|
|
220
|
+
let mut quote: Option<char> = None;
|
|
221
|
+
while let Some(ch) = chars.next() {
|
|
222
|
+
match (quote, ch) {
|
|
223
|
+
(None, '\'') | (None, '"') => quote = Some(ch),
|
|
224
|
+
(Some(q), c) if c == q => quote = None,
|
|
225
|
+
(None, c) if c.is_whitespace() => {
|
|
226
|
+
if !current.is_empty() {
|
|
227
|
+
argv.push(std::mem::take(&mut current));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
(_, c) => current.push(c),
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if !current.is_empty() {
|
|
234
|
+
argv.push(current);
|
|
235
|
+
}
|
|
236
|
+
argv
|
|
237
|
+
}
|
|
238
|
+
|
|
207
239
|
pub(crate) fn send_command(agent: &str, workspace: &Path, team: Option<&str>) -> Option<String> {
|
|
208
240
|
let workspace = workspace.to_str()?;
|
|
209
241
|
let mut command = format!(
|
|
210
|
-
"team-agent send {}
|
|
242
|
+
"team-agent send {} {} --workspace {}",
|
|
211
243
|
shell_quote(agent),
|
|
244
|
+
shell_quote("MESSAGE"),
|
|
212
245
|
shell_quote(workspace)
|
|
213
246
|
);
|
|
214
247
|
if let Some(team) = team {
|
|
@@ -528,6 +561,42 @@ pub fn cmd_allow_peer_talk(args: &AllowPeerTalkArgs) -> Result<CmdResult, CliErr
|
|
|
528
561
|
|
|
529
562
|
/// `cmd_diagnose`(`parser.py:298`)。
|
|
530
563
|
pub fn cmd_diagnose(args: &DiagnoseArgs) -> Result<CmdResult, CliError> {
|
|
564
|
+
let team_hint = args
|
|
565
|
+
.team
|
|
566
|
+
.as_deref()
|
|
567
|
+
.filter(|team| !team.is_empty())
|
|
568
|
+
.unwrap_or("current");
|
|
569
|
+
// Check the caller-supplied workspace before RuntimeOnly synthesis or
|
|
570
|
+
// transport setup, which can create `.team` paths and make an empty
|
|
571
|
+
// directory look like an unbound team.
|
|
572
|
+
if !crate::cli::diagnose::workspace_has_existing_team_runtime(&args.workspace, team_hint) {
|
|
573
|
+
let (issues, suggested_repairs) =
|
|
574
|
+
crate::cli::diagnose::missing_team_runtime_issues_and_repairs(team_hint);
|
|
575
|
+
let event_log = args
|
|
576
|
+
.workspace
|
|
577
|
+
.join(".team")
|
|
578
|
+
.join("logs")
|
|
579
|
+
.join("events.jsonl");
|
|
580
|
+
return Ok(CmdResult::from_json(
|
|
581
|
+
json!({
|
|
582
|
+
"event_log": event_log.to_string_lossy().to_string(),
|
|
583
|
+
"issues": issues,
|
|
584
|
+
"ok": false,
|
|
585
|
+
"providers": provider_doctor_checks(),
|
|
586
|
+
"runtime": {
|
|
587
|
+
"workspace": args.workspace.to_string_lossy().to_string(),
|
|
588
|
+
"team_key": team_hint,
|
|
589
|
+
"session_name": Value::Null,
|
|
590
|
+
"leader_receiver": Value::Null,
|
|
591
|
+
"agent_count": 0,
|
|
592
|
+
"message_count": 0,
|
|
593
|
+
"result_count": 0,
|
|
594
|
+
},
|
|
595
|
+
"suggested_repairs": suggested_repairs,
|
|
596
|
+
}),
|
|
597
|
+
args.json,
|
|
598
|
+
));
|
|
599
|
+
}
|
|
531
600
|
let selected = crate::state::selector::resolve_active_team(
|
|
532
601
|
&args.workspace,
|
|
533
602
|
args.team.as_deref(),
|
|
@@ -556,7 +625,12 @@ pub fn cmd_diagnose(args: &DiagnoseArgs) -> Result<CmdResult, CliError> {
|
|
|
556
625
|
)),
|
|
557
626
|
};
|
|
558
627
|
let (issues, suggested_repairs) =
|
|
559
|
-
diagnose_runtime_for_workspace(
|
|
628
|
+
diagnose_runtime_for_workspace(
|
|
629
|
+
&selected.run_workspace,
|
|
630
|
+
&state,
|
|
631
|
+
backend.as_ref(),
|
|
632
|
+
Some(selected.team_key.as_str()),
|
|
633
|
+
);
|
|
560
634
|
let ok = issues.as_array().is_some_and(Vec::is_empty);
|
|
561
635
|
Ok(CmdResult::from_json(
|
|
562
636
|
json!({
|
|
@@ -1347,17 +1421,24 @@ pub fn cmd_restart(args: &RestartArgs) -> Result<CmdResult, CliError> {
|
|
|
1347
1421
|
|
|
1348
1422
|
/// `cmd_start_agent`(`commands.py:348`)。
|
|
1349
1423
|
pub fn cmd_start_agent(args: &StartAgentArgs) -> Result<CmdResult, CliError> {
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1424
|
+
let mut value = lifecycle_port::start_agent(
|
|
1425
|
+
&args.workspace,
|
|
1426
|
+
&args.agent,
|
|
1427
|
+
args.force,
|
|
1428
|
+
!args.no_display,
|
|
1429
|
+
args.allow_fresh,
|
|
1430
|
+
args.team.as_deref(),
|
|
1431
|
+
)?;
|
|
1432
|
+
if value.get("agent_ids").is_none() {
|
|
1433
|
+
if let Some(object) = value.as_object_mut() {
|
|
1434
|
+
object.insert(
|
|
1435
|
+
"agent_ids".to_string(),
|
|
1436
|
+
json!([args.agent.as_str()]),
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
append_send_guidance(&mut value, &args.workspace, args.team.as_deref());
|
|
1441
|
+
Ok(CmdResult::from_json(value, args.json))
|
|
1361
1442
|
}
|
|
1362
1443
|
|
|
1363
1444
|
/// `cmd_stop_agent`(`commands.py:359`)。
|
|
@@ -1384,17 +1465,24 @@ pub fn cmd_reset_agent(args: &ResetAgentArgs) -> Result<CmdResult, CliError> {
|
|
|
1384
1465
|
|
|
1385
1466
|
/// `cmd_add_agent`(`commands.py:373`)。
|
|
1386
1467
|
pub fn cmd_add_agent(args: &AddAgentArgs) -> Result<CmdResult, CliError> {
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1468
|
+
let mut value = lifecycle_port::add_agent(
|
|
1469
|
+
&args.workspace,
|
|
1470
|
+
&args.agent,
|
|
1471
|
+
&args.role_file,
|
|
1472
|
+
!args.no_display,
|
|
1473
|
+
args.team.as_deref(),
|
|
1474
|
+
args.force,
|
|
1475
|
+
)?;
|
|
1476
|
+
if value.get("agent_ids").is_none() {
|
|
1477
|
+
if let Some(object) = value.as_object_mut() {
|
|
1478
|
+
object.insert(
|
|
1479
|
+
"agent_ids".to_string(),
|
|
1480
|
+
json!([args.agent.as_str()]),
|
|
1481
|
+
);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
append_send_guidance(&mut value, &args.workspace, args.team.as_deref());
|
|
1485
|
+
Ok(CmdResult::from_json(value, args.json))
|
|
1398
1486
|
}
|
|
1399
1487
|
|
|
1400
1488
|
/// `cmd_fork_agent`(`commands.py:383`)。
|
|
@@ -1540,8 +1628,10 @@ pub fn cmd_doctor(args: &DoctorArgs) -> Result<CmdResult, CliError> {
|
|
|
1540
1628
|
mod tests {
|
|
1541
1629
|
#![allow(clippy::unwrap_used)]
|
|
1542
1630
|
|
|
1543
|
-
use super::{
|
|
1544
|
-
|
|
1631
|
+
use super::{
|
|
1632
|
+
agent_pane_id, append_send_guidance, quickstart_human, send_command, split_shell_argv,
|
|
1633
|
+
};
|
|
1634
|
+
use serde_json::{json, Value};
|
|
1545
1635
|
use std::path::{Path, PathBuf};
|
|
1546
1636
|
|
|
1547
1637
|
// E13:happy 人类输出必须带 attach 块(此前 else 分支只打 summary 丢 attach_commands)。
|
|
@@ -1585,13 +1675,37 @@ mod tests {
|
|
|
1585
1675
|
);
|
|
1586
1676
|
}
|
|
1587
1677
|
|
|
1678
|
+
#[test]
|
|
1679
|
+
fn send_command_message_is_one_argv_token() {
|
|
1680
|
+
let command = send_command(
|
|
1681
|
+
"worker name; echo unsafe",
|
|
1682
|
+
Path::new("/tmp/my workspace"),
|
|
1683
|
+
Some("team-a"),
|
|
1684
|
+
)
|
|
1685
|
+
.unwrap();
|
|
1686
|
+
let argv = split_shell_argv(&command);
|
|
1687
|
+
assert_eq!(
|
|
1688
|
+
argv,
|
|
1689
|
+
[
|
|
1690
|
+
"team-agent",
|
|
1691
|
+
"send",
|
|
1692
|
+
"worker name; echo unsafe",
|
|
1693
|
+
"MESSAGE",
|
|
1694
|
+
"--workspace",
|
|
1695
|
+
"/tmp/my workspace",
|
|
1696
|
+
"--team",
|
|
1697
|
+
"team-a"
|
|
1698
|
+
]
|
|
1699
|
+
);
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1588
1702
|
#[test]
|
|
1589
1703
|
fn send_guidance_is_copyable_and_preserves_explicit_scope() {
|
|
1590
1704
|
let command = send_command("worker name; echo unsafe", Path::new("/tmp/my workspace"), Some("team-a"))
|
|
1591
1705
|
.unwrap();
|
|
1592
1706
|
assert_eq!(
|
|
1593
1707
|
command,
|
|
1594
|
-
"team-agent send 'worker name; echo unsafe'
|
|
1708
|
+
"team-agent send 'worker name; echo unsafe' MESSAGE --workspace '/tmp/my workspace' --team team-a"
|
|
1595
1709
|
);
|
|
1596
1710
|
}
|
|
1597
1711
|
|
|
@@ -1625,6 +1739,24 @@ mod tests {
|
|
|
1625
1739
|
assert!(value.get("send_commands").is_none());
|
|
1626
1740
|
}
|
|
1627
1741
|
|
|
1742
|
+
#[test]
|
|
1743
|
+
fn existing_runtime_gets_canonical_send_guidance() {
|
|
1744
|
+
let mut value = json!({
|
|
1745
|
+
"ok": false,
|
|
1746
|
+
"summary": "existing runtime",
|
|
1747
|
+
"agent_ids": ["worker"]
|
|
1748
|
+
});
|
|
1749
|
+
append_send_guidance(&mut value, Path::new("/tmp/ws"), Some("team-a"));
|
|
1750
|
+
let command = value
|
|
1751
|
+
.pointer("/send_commands/0")
|
|
1752
|
+
.and_then(Value::as_str)
|
|
1753
|
+
.unwrap();
|
|
1754
|
+
assert!(command.contains("send worker"));
|
|
1755
|
+
assert!(command.contains("--team team-a"));
|
|
1756
|
+
let parts: Vec<&str> = command.split_whitespace().collect();
|
|
1757
|
+
assert_eq!(parts[3], "MESSAGE");
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1628
1760
|
#[test]
|
|
1629
1761
|
fn agent_pane_id_resolves_session_window_even_with_recorded_pane_id() {
|
|
1630
1762
|
let state = json!({
|