@team-agent/installer 0.3.3 → 0.3.5
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 +8 -0
- package/crates/team-agent/src/cli/diagnose.rs +52 -11
- package/crates/team-agent/src/cli/emit.rs +3 -2
- package/crates/team-agent/src/cli/mod.rs +225 -80
- package/crates/team-agent/src/cli/send.rs +1 -0
- package/crates/team-agent/src/cli/status_port.rs +135 -7
- package/crates/team-agent/src/cli/tests/missing_subcommands.rs +8 -1
- package/crates/team-agent/src/cli/tests/mod.rs +1 -0
- package/crates/team-agent/src/cli/tests/shutdown_kill_plan.rs +39 -0
- package/crates/team-agent/src/cli/types.rs +5 -1
- package/crates/team-agent/src/compiler/tests.rs +2 -2
- package/crates/team-agent/src/compiler.rs +1 -1
- package/crates/team-agent/src/coordinator/backoff.rs +57 -9
- package/crates/team-agent/src/coordinator/health.rs +65 -2
- package/crates/team-agent/src/coordinator/runtime_detectors.rs +28 -16
- package/crates/team-agent/src/coordinator/tests/a0_lostupdate.rs +87 -0
- package/crates/team-agent/src/coordinator/tests/mod.rs +1 -0
- package/crates/team-agent/src/coordinator/tests/watch.rs +4 -2
- package/crates/team-agent/src/coordinator/tick.rs +195 -43
- package/crates/team-agent/src/leader/helpers.rs +2 -0
- package/crates/team-agent/src/leader/rediscover.rs +1 -0
- package/crates/team-agent/src/leader/start.rs +9 -1
- package/crates/team-agent/src/leader/takeover.rs +18 -1
- package/crates/team-agent/src/lifecycle/display.rs +3 -3
- package/crates/team-agent/src/lifecycle/launch.rs +772 -285
- package/crates/team-agent/src/lifecycle/mod.rs +1 -0
- package/crates/team-agent/src/lifecycle/profile_launch.rs +110 -4
- package/crates/team-agent/src/lifecycle/profile_smoke.rs +4 -1
- package/crates/team-agent/src/lifecycle/restart/agent.rs +16 -5
- package/crates/team-agent/src/lifecycle/restart/common.rs +35 -25
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +31 -25
- package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/core.rs +5 -5
- package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +4 -4
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +5 -3
- package/crates/team-agent/src/lifecycle/types.rs +4 -0
- package/crates/team-agent/src/lifecycle/worker_command_context.rs +361 -0
- package/crates/team-agent/src/mcp_server/lifecycle_tools/agent_ops.rs +2 -1
- package/crates/team-agent/src/mcp_server/tests/scoped.rs +14 -1
- package/crates/team-agent/src/mcp_server/tests/send.rs +15 -1
- package/crates/team-agent/src/mcp_server/tools.rs +65 -9
- package/crates/team-agent/src/mcp_server/wire.rs +2 -1
- package/crates/team-agent/src/message_store.rs +80 -0
- package/crates/team-agent/src/messaging/results.rs +76 -5
- package/crates/team-agent/src/messaging/send.rs +3 -1
- package/crates/team-agent/src/messaging/types.rs +15 -1
- package/crates/team-agent/src/messaging/watchers.rs +68 -30
- package/crates/team-agent/src/model/enums.rs +7 -1
- package/crates/team-agent/src/model/permissions.rs +7 -0
- package/crates/team-agent/src/model/spec.rs +3 -1
- package/crates/team-agent/src/provider/adapter.rs +472 -7
- package/crates/team-agent/src/provider/classify.rs +6 -2
- package/crates/team-agent/src/provider/faults.rs +3 -2
- package/crates/team-agent/src/provider/startup_prompt.rs +25 -7
- package/crates/team-agent/src/provider/types.rs +11 -0
- package/crates/team-agent/src/session_capture.rs +1 -0
- package/crates/team-agent/src/state/persist.rs +95 -19
- package/crates/team-agent/src/tmux_backend/tests.rs +8 -7
- package/crates/team-agent/src/tmux_backend.rs +134 -6
- package/crates/team-agent/src/transport.rs +32 -0
- package/package.json +4 -4
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
|
@@ -1490,6 +1490,14 @@ pub fn cmd_doctor(args: &DoctorArgs) -> Result<CmdResult, CliError> {
|
|
|
1490
1490
|
if args.fix && args.gate.is_none() {
|
|
1491
1491
|
return Err(CliError::Runtime("--fix requires --gate".to_string()));
|
|
1492
1492
|
}
|
|
1493
|
+
// swallow batch 3 ①: an unknown gate refuses explicitly (Python commands.py:234-235
|
|
1494
|
+
// `unknown doctor gate`), never an empty default-doctor green.
|
|
1495
|
+
if let Some(DoctorGate::Unknown(raw)) = &args.gate {
|
|
1496
|
+
return Ok(CmdResult::from_json(
|
|
1497
|
+
serde_json::json!({"ok": false, "status": "unknown_gate", "gate": raw}),
|
|
1498
|
+
args.json,
|
|
1499
|
+
));
|
|
1500
|
+
}
|
|
1493
1501
|
if args.comms || matches!(args.gate, Some(DoctorGate::Comms)) {
|
|
1494
1502
|
let value = crate::diagnose::comms::doctor_comms_json(&args.workspace, args.team.as_deref(), Some("comms"))?;
|
|
1495
1503
|
if !args.json {
|
|
@@ -115,7 +115,7 @@ pub(crate) fn build_preflight_report(team: &std::path::Path) -> Result<Value, Cl
|
|
|
115
115
|
let display_backend = compiled
|
|
116
116
|
.as_ref()
|
|
117
117
|
.and_then(|spec| yaml_path_str(spec, &["runtime", "display_backend"]))
|
|
118
|
-
.unwrap_or("
|
|
118
|
+
.unwrap_or("none");
|
|
119
119
|
let ghostty_required = display_backend == "ghostty_window" || display_backend == "ghostty";
|
|
120
120
|
let ghostty_path = command_path("ghostty");
|
|
121
121
|
checks.push(json!({
|
|
@@ -289,21 +289,46 @@ fn copy_optional_field(from: &Value, to: &mut Value, key: &str) {
|
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
pub(crate) fn build_wait_ready_report(workspace: &std::path::Path, timeout: f64) -> Result<Value, CliError> {
|
|
292
|
-
|
|
292
|
+
// swallow batch 3 ③: an unreadable runtime state must never read as "ready" — the
|
|
293
|
+
// read error is surfaced verbatim (state_read_error) with ready=false instead of
|
|
294
|
+
// silently degrading to an empty/stale state.
|
|
295
|
+
let selected = match crate::state::selector::resolve_active_team(
|
|
293
296
|
workspace,
|
|
294
297
|
None,
|
|
295
298
|
crate::state::selector::SelectorMode::RuntimeOnly,
|
|
296
|
-
)
|
|
297
|
-
|
|
299
|
+
) {
|
|
300
|
+
Ok(selected) => selected,
|
|
301
|
+
Err(error) => {
|
|
302
|
+
return Ok(json!({
|
|
303
|
+
"ok": false,
|
|
304
|
+
"status": "error",
|
|
305
|
+
"reason": "state_read_error",
|
|
306
|
+
"state_read_error": error.to_string(),
|
|
307
|
+
"readiness": {"ready": false},
|
|
308
|
+
"summary": "runtime state could not be read",
|
|
309
|
+
"next_actions": [json!("inspect .team/runtime/state.json (corrupt or unreadable) and retry")],
|
|
310
|
+
}));
|
|
311
|
+
}
|
|
312
|
+
};
|
|
298
313
|
let timeout = if timeout.is_finite() && timeout > 0.0 { timeout } else { 0.0 };
|
|
299
314
|
let deadline = std::time::Instant::now() + std::time::Duration::from_secs_f64(timeout);
|
|
300
315
|
let mut readiness;
|
|
316
|
+
let mut state_read_error: Option<String> = None;
|
|
301
317
|
loop {
|
|
302
|
-
let mut state = crate::state::projection::select_runtime_state(
|
|
318
|
+
let mut state = match crate::state::projection::select_runtime_state(
|
|
303
319
|
&selected.run_workspace,
|
|
304
320
|
Some(&selected.team_key),
|
|
305
|
-
)
|
|
306
|
-
|
|
321
|
+
) {
|
|
322
|
+
Ok(state) => {
|
|
323
|
+
state_read_error = None;
|
|
324
|
+
state
|
|
325
|
+
}
|
|
326
|
+
Err(error) => {
|
|
327
|
+
state_read_error = Some(error.to_string());
|
|
328
|
+
readiness = json!({"ready": false, "state_read_error": error.to_string()});
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
307
332
|
inject_tmux_session_present(&selected.run_workspace, &mut state);
|
|
308
333
|
inject_message_counts(&selected.run_workspace, &mut state)?;
|
|
309
334
|
readiness = wait_readiness(&state);
|
|
@@ -322,7 +347,15 @@ pub(crate) fn build_wait_ready_report(workspace: &std::path::Path, timeout: f64)
|
|
|
322
347
|
.and_then(Value::as_bool)
|
|
323
348
|
== Some(true);
|
|
324
349
|
let ready = readiness.get("ready").and_then(Value::as_bool) == Some(true);
|
|
325
|
-
let (ok, status, reason, summary, next_actions) = if
|
|
350
|
+
let (ok, status, reason, summary, next_actions) = if state_read_error.is_some() {
|
|
351
|
+
(
|
|
352
|
+
false,
|
|
353
|
+
"error",
|
|
354
|
+
"state_read_error",
|
|
355
|
+
"runtime state could not be read",
|
|
356
|
+
vec![json!("inspect .team/runtime/state.json (corrupt or unreadable) and retry")],
|
|
357
|
+
)
|
|
358
|
+
} else if awaiting_trust {
|
|
326
359
|
(
|
|
327
360
|
false,
|
|
328
361
|
"pending",
|
|
@@ -360,7 +393,7 @@ pub(crate) fn build_wait_ready_report(workspace: &std::path::Path, timeout: f64)
|
|
|
360
393
|
"readiness": readiness,
|
|
361
394
|
}),
|
|
362
395
|
)?;
|
|
363
|
-
|
|
396
|
+
let mut report = json!({
|
|
364
397
|
"details_log": details_log.to_string_lossy().to_string(),
|
|
365
398
|
"next_actions": next_actions,
|
|
366
399
|
"ok": ok,
|
|
@@ -368,7 +401,11 @@ pub(crate) fn build_wait_ready_report(workspace: &std::path::Path, timeout: f64)
|
|
|
368
401
|
"readiness": readiness,
|
|
369
402
|
"status": status,
|
|
370
403
|
"summary": summary,
|
|
371
|
-
})
|
|
404
|
+
});
|
|
405
|
+
if let Some(error) = state_read_error {
|
|
406
|
+
report["state_read_error"] = json!(error);
|
|
407
|
+
}
|
|
408
|
+
Ok(report)
|
|
372
409
|
}
|
|
373
410
|
|
|
374
411
|
fn inject_tmux_session_present(workspace: &std::path::Path, state: &mut Value) {
|
|
@@ -392,10 +429,12 @@ pub(crate) fn wait_readiness(state: &Value) -> Value {
|
|
|
392
429
|
let mut task_prompt_delivered = false;
|
|
393
430
|
let mut awaiting_trust_prompt = false;
|
|
394
431
|
let mut incomplete_sessions = Vec::new();
|
|
432
|
+
// A-5: a missing/unreadable leader_receiver must NOT count as attached —
|
|
433
|
+
// "unreadable is never ready" (doctor/wait-ready truthfulness rule).
|
|
395
434
|
let all_attached_receiver = state
|
|
396
435
|
.get("leader_receiver")
|
|
397
436
|
.and_then(Value::as_object)
|
|
398
|
-
.
|
|
437
|
+
.is_some_and(|receiver| {
|
|
399
438
|
receiver
|
|
400
439
|
.get("status")
|
|
401
440
|
.and_then(Value::as_str)
|
|
@@ -673,6 +712,7 @@ fn provider_wire(provider: crate::provider::Provider) -> &'static str {
|
|
|
673
712
|
crate::provider::Provider::Claude => "claude",
|
|
674
713
|
crate::provider::Provider::ClaudeCode => "claude_code",
|
|
675
714
|
crate::provider::Provider::Codex => "codex",
|
|
715
|
+
crate::provider::Provider::Copilot => "copilot",
|
|
676
716
|
crate::provider::Provider::GeminiCli => "gemini_cli",
|
|
677
717
|
crate::provider::Provider::Fake => "fake",
|
|
678
718
|
}
|
|
@@ -682,6 +722,7 @@ fn provider_command(provider: crate::provider::Provider) -> &'static str {
|
|
|
682
722
|
match provider {
|
|
683
723
|
crate::provider::Provider::Claude | crate::provider::Provider::ClaudeCode => "claude",
|
|
684
724
|
crate::provider::Provider::Codex => "codex",
|
|
725
|
+
crate::provider::Provider::Copilot => "copilot",
|
|
685
726
|
crate::provider::Provider::GeminiCli => "gemini",
|
|
686
727
|
crate::provider::Provider::Fake => "team-agent fake-worker",
|
|
687
728
|
}
|
|
@@ -200,7 +200,7 @@ fn command_help(command: Option<&str>) -> String {
|
|
|
200
200
|
)
|
|
201
201
|
}
|
|
202
202
|
Some("init") => "usage: team-agent init [--workspace WORKSPACE] [--force] [--json]".to_string(),
|
|
203
|
-
Some("quick-start") => "usage: team-agent quick-start [TEAMDIR] [--workspace WORKSPACE] [--name NAME] [--team-id TEAM|--team TEAM] [--yes] [--fresh] [--json]".to_string(),
|
|
203
|
+
Some("quick-start") => "usage: team-agent quick-start [TEAMDIR] [--workspace WORKSPACE] [--name NAME] [--team-id TEAM|--team TEAM] [--yes] [--fresh] [--json]\n\ndefaults: display_backend=none; set display_backend: adaptive in TEAM.md to opt in to adaptive display windows.".to_string(),
|
|
204
204
|
Some("start") => "usage: team-agent start [TEAMDIR] [--yes] [--fresh] [--json]".to_string(),
|
|
205
205
|
Some("compile") => "usage: team-agent compile --team TEAM [--out FILE] [--json]".to_string(),
|
|
206
206
|
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(),
|
|
@@ -963,7 +963,8 @@ fn doctor_gate(raw: Option<&str>) -> Option<DoctorGate> {
|
|
|
963
963
|
match raw {
|
|
964
964
|
Some("orphans") => Some(DoctorGate::Orphans),
|
|
965
965
|
Some("comms") => Some(DoctorGate::Comms),
|
|
966
|
-
|
|
966
|
+
Some(other) => Some(DoctorGate::Unknown(other.to_string())),
|
|
967
|
+
None => None,
|
|
967
968
|
}
|
|
968
969
|
}
|
|
969
970
|
|