@team-agent/installer 0.5.17 → 0.5.19
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 +2 -1
- package/crates/team-agent/src/cli/diagnose.rs +185 -0
- package/crates/team-agent/src/cli/mod.rs +46 -1
- package/crates/team-agent/src/cli/status_port.rs +5 -0
- package/crates/team-agent/src/cli/tests/lane_c.rs +17 -7
- package/crates/team-agent/src/coordinator/backoff.rs +15 -14
- package/crates/team-agent/src/coordinator/health.rs +142 -12
- package/crates/team-agent/src/coordinator/tests/basics.rs +4 -0
- package/crates/team-agent/src/coordinator/tests/mod.rs +3 -0
- package/crates/team-agent/src/coordinator/tick.rs +70 -68
- package/crates/team-agent/src/coordinator/types.rs +47 -0
- package/crates/team-agent/src/diagnose/orphans.rs +35 -13
- package/crates/team-agent/src/lifecycle/restart/agent.rs +4 -2
- package/crates/team-agent/src/lifecycle/restart/common.rs +6 -3
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +34 -20
- package/crates/team-agent/src/lifecycle/tests/lifecycle_lock.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +133 -11
- package/crates/team-agent/src/lifecycle/types.rs +54 -0
- package/crates/team-agent/src/messaging/results.rs +7 -0
- package/package.json +4 -4
|
@@ -449,10 +449,13 @@ fn window_present_in_live(
|
|
|
449
449
|
false
|
|
450
450
|
}
|
|
451
451
|
|
|
452
|
-
pub(super) fn start_coordinator_for_workspace(
|
|
452
|
+
pub(super) fn start_coordinator_for_workspace(
|
|
453
|
+
workspace: &Path,
|
|
454
|
+
team_key: Option<&str>,
|
|
455
|
+
) -> Result<crate::lifecycle::CoordinatorStartSummary, LifecycleError> {
|
|
453
456
|
let workspace = crate::coordinator::WorkspacePath::new(workspace.to_path_buf());
|
|
454
|
-
crate::coordinator::
|
|
455
|
-
.map(|report| report
|
|
457
|
+
crate::coordinator::health::start_coordinator_with_team(&workspace, team_key)
|
|
458
|
+
.map(|report| crate::lifecycle::CoordinatorStartSummary::from_start_report(&report))
|
|
456
459
|
.map_err(|e| LifecycleError::StatePersist(e.to_string()))
|
|
457
460
|
}
|
|
458
461
|
|
|
@@ -590,6 +590,7 @@ fn restart_with_selected_team_and_transport(
|
|
|
590
590
|
&successful_agents,
|
|
591
591
|
&failed_agents,
|
|
592
592
|
"fail",
|
|
593
|
+
None,
|
|
593
594
|
)?;
|
|
594
595
|
return Ok(RestartReport::Failed {
|
|
595
596
|
session_name,
|
|
@@ -606,6 +607,7 @@ fn restart_with_selected_team_and_transport(
|
|
|
606
607
|
&successful_agents,
|
|
607
608
|
&failed_agents,
|
|
608
609
|
"fail",
|
|
610
|
+
None,
|
|
609
611
|
)?;
|
|
610
612
|
return Ok(RestartReport::Failed {
|
|
611
613
|
session_name,
|
|
@@ -824,6 +826,7 @@ fn restart_with_selected_team_and_transport(
|
|
|
824
826
|
&successful_agents,
|
|
825
827
|
&failed_agents,
|
|
826
828
|
"fail",
|
|
829
|
+
None,
|
|
827
830
|
)?;
|
|
828
831
|
return Ok(RestartReport::Failed {
|
|
829
832
|
session_name,
|
|
@@ -833,7 +836,9 @@ fn restart_with_selected_team_and_transport(
|
|
|
833
836
|
});
|
|
834
837
|
}
|
|
835
838
|
drop(lifecycle_lock);
|
|
836
|
-
let
|
|
839
|
+
let coordinator =
|
|
840
|
+
start_coordinator_for_workspace(&selected.run_workspace, Some(&selected.team_key))?;
|
|
841
|
+
let coordinator_started = coordinator.ok;
|
|
837
842
|
wait_restart_readiness_or_timeout(
|
|
838
843
|
&selected.run_workspace,
|
|
839
844
|
&state,
|
|
@@ -862,6 +867,7 @@ fn restart_with_selected_team_and_transport(
|
|
|
862
867
|
&successful_agents,
|
|
863
868
|
&failed_agents,
|
|
864
869
|
"partial",
|
|
870
|
+
Some(&coordinator),
|
|
865
871
|
)?;
|
|
866
872
|
// 0.3.30 Bug 1: auto-attach on partial restart too — workers that did
|
|
867
873
|
// come up still need a leader_receiver pane to deliver report_result.
|
|
@@ -875,6 +881,7 @@ fn restart_with_selected_team_and_transport(
|
|
|
875
881
|
agents: successful_agents,
|
|
876
882
|
failed_agents,
|
|
877
883
|
coordinator_started,
|
|
884
|
+
coordinator,
|
|
878
885
|
next_actions,
|
|
879
886
|
attach_commands,
|
|
880
887
|
});
|
|
@@ -884,6 +891,7 @@ fn restart_with_selected_team_and_transport(
|
|
|
884
891
|
&successful_agents,
|
|
885
892
|
&failed_agents,
|
|
886
893
|
"ok",
|
|
894
|
+
Some(&coordinator),
|
|
887
895
|
)?;
|
|
888
896
|
// 0.3.30 Bug 1: auto-attach leader from caller's TMUX_PANE if available.
|
|
889
897
|
// Mirrors quick-start's seed_launched_owner_from_env behaviour: a restart
|
|
@@ -900,6 +908,7 @@ fn restart_with_selected_team_and_transport(
|
|
|
900
908
|
session_name,
|
|
901
909
|
agents: successful_agents,
|
|
902
910
|
coordinator_started,
|
|
911
|
+
coordinator,
|
|
903
912
|
next_actions,
|
|
904
913
|
attach_commands,
|
|
905
914
|
})
|
|
@@ -1953,27 +1962,32 @@ fn write_restart_completed_event(
|
|
|
1953
1962
|
successful_agents: &[RestartedAgent],
|
|
1954
1963
|
failed_agents: &[RestartFailedAgent],
|
|
1955
1964
|
rc: &str,
|
|
1965
|
+
coordinator: Option<&crate::lifecycle::CoordinatorStartSummary>,
|
|
1956
1966
|
) -> Result<(), LifecycleError> {
|
|
1967
|
+
let mut payload = serde_json::json!({
|
|
1968
|
+
"rc": rc,
|
|
1969
|
+
"status": rc,
|
|
1970
|
+
"successful_agents": successful_agents
|
|
1971
|
+
.iter()
|
|
1972
|
+
.map(|agent| agent.agent_id.as_str())
|
|
1973
|
+
.collect::<Vec<_>>(),
|
|
1974
|
+
"failed_agents": failed_agents
|
|
1975
|
+
.iter()
|
|
1976
|
+
.map(|failure| serde_json::json!({
|
|
1977
|
+
"agent_id": failure.agent_id.as_str(),
|
|
1978
|
+
"phase": failure.phase,
|
|
1979
|
+
"error": failure.error,
|
|
1980
|
+
}))
|
|
1981
|
+
.collect::<Vec<_>>(),
|
|
1982
|
+
});
|
|
1983
|
+
if let (Some(object), Some(coordinator)) = (payload.as_object_mut(), coordinator) {
|
|
1984
|
+
object.insert(
|
|
1985
|
+
"coordinator".to_string(),
|
|
1986
|
+
crate::lifecycle::coordinator_start_summary_value(coordinator),
|
|
1987
|
+
);
|
|
1988
|
+
}
|
|
1957
1989
|
crate::event_log::EventLog::new(workspace)
|
|
1958
|
-
.write(
|
|
1959
|
-
"restart.completed",
|
|
1960
|
-
serde_json::json!({
|
|
1961
|
-
"rc": rc,
|
|
1962
|
-
"status": rc,
|
|
1963
|
-
"successful_agents": successful_agents
|
|
1964
|
-
.iter()
|
|
1965
|
-
.map(|agent| agent.agent_id.as_str())
|
|
1966
|
-
.collect::<Vec<_>>(),
|
|
1967
|
-
"failed_agents": failed_agents
|
|
1968
|
-
.iter()
|
|
1969
|
-
.map(|failure| serde_json::json!({
|
|
1970
|
-
"agent_id": failure.agent_id.as_str(),
|
|
1971
|
-
"phase": failure.phase,
|
|
1972
|
-
"error": failure.error,
|
|
1973
|
-
}))
|
|
1974
|
-
.collect::<Vec<_>>(),
|
|
1975
|
-
}),
|
|
1976
|
-
)
|
|
1990
|
+
.write("restart.completed", payload)
|
|
1977
1991
|
.map(|_| ())
|
|
1978
1992
|
.map_err(|e| LifecycleError::StatePersist(e.to_string()))
|
|
1979
1993
|
}
|
|
@@ -242,7 +242,7 @@ fn r2_lifecycle_lock_exists_precondition() {
|
|
|
242
242
|
assert_public_operation(&rebuild, "restart");
|
|
243
243
|
let drop_idx = rebuild.find("drop(lifecycle_lock);").unwrap();
|
|
244
244
|
let coordinator_idx = rebuild
|
|
245
|
-
.find("start_coordinator_for_workspace(&selected.run_workspace)")
|
|
245
|
+
.find("start_coordinator_for_workspace(&selected.run_workspace, Some(&selected.team_key))")
|
|
246
246
|
.unwrap();
|
|
247
247
|
let readiness_idx = rebuild.find("wait_restart_readiness_or_timeout(").unwrap();
|
|
248
248
|
assert!(
|
|
@@ -478,7 +478,6 @@ impl EnvVarGuard {
|
|
|
478
478
|
}
|
|
479
479
|
Self { key, previous }
|
|
480
480
|
}
|
|
481
|
-
|
|
482
481
|
}
|
|
483
482
|
|
|
484
483
|
impl Drop for EnvVarGuard {
|
|
@@ -581,6 +580,9 @@ fn normalize_string(text: String, ctx: &mut NormalizeCtx, key: Option<&str>) ->
|
|
|
581
580
|
if key_is_timestamp(key) {
|
|
582
581
|
return json!("<TS>");
|
|
583
582
|
}
|
|
583
|
+
if text == crate::packaging::Version::current().as_str() {
|
|
584
|
+
return json!("<VERSION>");
|
|
585
|
+
}
|
|
584
586
|
if key.contains("endpoint") && value_looks_like_endpoint_path(&text) {
|
|
585
587
|
return json!("<SOCKET>");
|
|
586
588
|
}
|
|
@@ -602,6 +604,7 @@ fn normalize_string(text: String, ctx: &mut NormalizeCtx, key: Option<&str>) ->
|
|
|
602
604
|
|
|
603
605
|
fn normalize_path_string(text: &str, ctx: &NormalizeCtx) -> String {
|
|
604
606
|
let mut out = text.to_string();
|
|
607
|
+
out = normalize_team_agent_binary_path(&out);
|
|
605
608
|
for alias in &ctx.workspace_aliases {
|
|
606
609
|
out = out.replace(alias, "<WORKSPACE>");
|
|
607
610
|
}
|
|
@@ -609,7 +612,6 @@ fn normalize_path_string(text: &str, ctx: &NormalizeCtx) -> String {
|
|
|
609
612
|
for alias in &ctx.temp_aliases {
|
|
610
613
|
out = out.replace(alias, "<TMP>");
|
|
611
614
|
}
|
|
612
|
-
out = normalize_team_agent_binary_path(&out);
|
|
613
615
|
out = normalize_tmux_socket_dir(&out);
|
|
614
616
|
normalize_socket_token(&out)
|
|
615
617
|
}
|
|
@@ -622,7 +624,7 @@ fn value_looks_like_endpoint_path(text: &str) -> bool {
|
|
|
622
624
|
}
|
|
623
625
|
|
|
624
626
|
fn normalize_team_agent_binary_path(text: &str) -> String {
|
|
625
|
-
let mut out = text
|
|
627
|
+
let mut out = replace_known_team_agent_binary_paths(text);
|
|
626
628
|
// 0.5.0 hermetic 教训「环境路径类 token 化」的直接延伸
|
|
627
629
|
// (leader msg_6ee04cf5aee8):归一化改为结构判据,不绑路径前缀。
|
|
628
630
|
// 用户 CARGO_TARGET_DIR 可以指到任意目录(默认 `<repo>/target`,
|
|
@@ -642,6 +644,30 @@ fn normalize_team_agent_binary_path(text: &str) -> String {
|
|
|
642
644
|
out
|
|
643
645
|
}
|
|
644
646
|
|
|
647
|
+
fn replace_known_team_agent_binary_paths(text: &str) -> String {
|
|
648
|
+
let mut out = text.to_string();
|
|
649
|
+
for alias in known_team_agent_binary_path_aliases() {
|
|
650
|
+
out = out.replace(&alias, "<TEAM_AGENT_BIN>");
|
|
651
|
+
}
|
|
652
|
+
out
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
fn known_team_agent_binary_path_aliases() -> Vec<String> {
|
|
656
|
+
let mut aliases = Vec::new();
|
|
657
|
+
if let Some(path) = option_env!("CARGO_BIN_EXE_team-agent") {
|
|
658
|
+
push_path_alias(&mut aliases, PathBuf::from(path));
|
|
659
|
+
}
|
|
660
|
+
if let Some(path) = std::env::var_os("CARGO_BIN_EXE_team-agent") {
|
|
661
|
+
push_path_alias(&mut aliases, PathBuf::from(path));
|
|
662
|
+
}
|
|
663
|
+
if let Ok(path) = std::env::current_exe() {
|
|
664
|
+
push_path_alias(&mut aliases, path);
|
|
665
|
+
}
|
|
666
|
+
aliases.sort_by(|a, b| b.len().cmp(&a.len()).then_with(|| a.cmp(b)));
|
|
667
|
+
aliases.dedup();
|
|
668
|
+
aliases
|
|
669
|
+
}
|
|
670
|
+
|
|
645
671
|
/// Structural (path-prefix-independent) normalization for
|
|
646
672
|
/// `/…/deps/team_agent-<hex>(.exe)?` occurrences. Scans the input for
|
|
647
673
|
/// every `/deps/team_agent-` marker and rewrites the containing
|
|
@@ -750,17 +776,31 @@ fn normalize_tmux_uid_with_prefix(mut text: String, prefix: &str) -> String {
|
|
|
750
776
|
}
|
|
751
777
|
|
|
752
778
|
fn normalize_socket_token(text: &str) -> String {
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
779
|
+
const CONTEXT: &str = "/tmux-<UID>/";
|
|
780
|
+
let mut out = String::with_capacity(text.len());
|
|
781
|
+
let mut search_from = 0;
|
|
782
|
+
while let Some(offset) = text[search_from..].find(CONTEXT) {
|
|
783
|
+
let context_start = search_from + offset;
|
|
784
|
+
let token_start = context_start + CONTEXT.len();
|
|
785
|
+
if !text[token_start..].starts_with("ta-") {
|
|
786
|
+
out.push_str(&text[search_from..token_start]);
|
|
787
|
+
search_from = token_start;
|
|
788
|
+
continue;
|
|
789
|
+
}
|
|
790
|
+
let end = text[token_start..]
|
|
756
791
|
.find(|c: char| !(c.is_ascii_alphanumeric() || c == '-'))
|
|
757
|
-
.map(|offset|
|
|
758
|
-
.unwrap_or_else(||
|
|
759
|
-
if end ==
|
|
760
|
-
|
|
792
|
+
.map(|offset| token_start + offset)
|
|
793
|
+
.unwrap_or_else(|| text.len());
|
|
794
|
+
if end == token_start + 3 {
|
|
795
|
+
out.push_str(&text[search_from..end]);
|
|
796
|
+
search_from = end;
|
|
797
|
+
continue;
|
|
761
798
|
}
|
|
762
|
-
out.
|
|
799
|
+
out.push_str(&text[search_from..token_start]);
|
|
800
|
+
out.push_str("ta-<SOCKET>");
|
|
801
|
+
search_from = end;
|
|
763
802
|
}
|
|
803
|
+
out.push_str(&text[search_from..]);
|
|
764
804
|
out
|
|
765
805
|
}
|
|
766
806
|
|
|
@@ -801,3 +841,85 @@ fn pretty(value: &Value) -> String {
|
|
|
801
841
|
text.push('\n');
|
|
802
842
|
text
|
|
803
843
|
}
|
|
844
|
+
|
|
845
|
+
#[test]
|
|
846
|
+
fn phase_golden_normalizer_maps_custom_cargo_target_deps_binary_before_tmp_aliasing() {
|
|
847
|
+
let ctx = NormalizeCtx {
|
|
848
|
+
workspace_aliases: Vec::new(),
|
|
849
|
+
temp_aliases: vec!["/Volumes/nvme/tmp".to_string()],
|
|
850
|
+
pane_ids: BTreeMap::new(),
|
|
851
|
+
};
|
|
852
|
+
let input = concat!(
|
|
853
|
+
"mcp_servers.team_orchestrator.command=\"",
|
|
854
|
+
"/Volumes/nvme/tmp/ta-0517-target/debug/deps/team_agent-c924abc123",
|
|
855
|
+
"\""
|
|
856
|
+
);
|
|
857
|
+
|
|
858
|
+
assert_eq!(
|
|
859
|
+
normalize_path_string(input, &ctx),
|
|
860
|
+
"mcp_servers.team_orchestrator.command=\"<TEAM_AGENT_BIN>\"",
|
|
861
|
+
"custom CARGO_TARGET_DIR binary paths must normalize to <TEAM_AGENT_BIN> before tmp/socket tokenization"
|
|
862
|
+
);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
#[test]
|
|
866
|
+
fn phase_golden_normalizer_maps_current_test_binary_to_team_agent_marker() {
|
|
867
|
+
let ctx = NormalizeCtx {
|
|
868
|
+
workspace_aliases: Vec::new(),
|
|
869
|
+
temp_aliases: vec!["/Volumes/nvme/tmp".to_string()],
|
|
870
|
+
pane_ids: BTreeMap::new(),
|
|
871
|
+
};
|
|
872
|
+
let input = format!(
|
|
873
|
+
"mcp_servers.team_orchestrator.command=\"{}\"",
|
|
874
|
+
std::env::current_exe()
|
|
875
|
+
.expect("current test binary path")
|
|
876
|
+
.display()
|
|
877
|
+
);
|
|
878
|
+
|
|
879
|
+
assert_eq!(
|
|
880
|
+
normalize_path_string(&input, &ctx),
|
|
881
|
+
"mcp_servers.team_orchestrator.command=\"<TEAM_AGENT_BIN>\"",
|
|
882
|
+
"actual test argv0/current_exe path must normalize to <TEAM_AGENT_BIN>"
|
|
883
|
+
);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
#[test]
|
|
887
|
+
fn phase_golden_normalizer_does_not_treat_cargo_target_dir_as_socket_token() {
|
|
888
|
+
let ctx = NormalizeCtx {
|
|
889
|
+
workspace_aliases: Vec::new(),
|
|
890
|
+
temp_aliases: vec!["/Volumes/nvme/tmp".to_string()],
|
|
891
|
+
pane_ids: BTreeMap::new(),
|
|
892
|
+
};
|
|
893
|
+
|
|
894
|
+
assert_eq!(
|
|
895
|
+
normalize_path_string("/Volumes/nvme/tmp/ta-0517-target/build.log", &ctx),
|
|
896
|
+
"<TMP>/ta-0517-target/build.log",
|
|
897
|
+
"ta-* directory names outside tmux socket context must not be rewritten as ta-<SOCKET>"
|
|
898
|
+
);
|
|
899
|
+
assert_eq!(
|
|
900
|
+
normalize_path_string("tmux -S /tmp/tmux-501/ta-a60d10b25edd attach", &ctx),
|
|
901
|
+
"tmux -S <TMP>/tmux-<UID>/ta-<SOCKET> attach",
|
|
902
|
+
"real tmux socket paths still need stable socket tokenization"
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
#[test]
|
|
907
|
+
fn phase_golden_normalizer_maps_current_version_by_value_only() {
|
|
908
|
+
let mut ctx = NormalizeCtx {
|
|
909
|
+
workspace_aliases: Vec::new(),
|
|
910
|
+
temp_aliases: Vec::new(),
|
|
911
|
+
pane_ids: BTreeMap::new(),
|
|
912
|
+
};
|
|
913
|
+
let current = crate::packaging::Version::current().as_str().to_string();
|
|
914
|
+
|
|
915
|
+
assert_eq!(
|
|
916
|
+
normalize_string(current.clone(), &mut ctx, Some("arbitrary_field")),
|
|
917
|
+
json!("<VERSION>"),
|
|
918
|
+
"current binary version values must normalize without depending on field names"
|
|
919
|
+
);
|
|
920
|
+
assert_eq!(
|
|
921
|
+
normalize_string(format!("version={current}"), &mut ctx, Some("binary_version")),
|
|
922
|
+
json!(format!("version={current}")),
|
|
923
|
+
"version normalization must be exact-value based, not a broad substring or field-name rewrite"
|
|
924
|
+
);
|
|
925
|
+
}
|
|
@@ -83,6 +83,52 @@ impl PlanId {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
87
|
+
pub struct CoordinatorStartSummary {
|
|
88
|
+
pub ok: bool,
|
|
89
|
+
pub status: String,
|
|
90
|
+
pub pid: Option<u32>,
|
|
91
|
+
pub binary_path: Option<String>,
|
|
92
|
+
pub binary_version: Option<String>,
|
|
93
|
+
pub rotation_reason: Option<String>,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
impl CoordinatorStartSummary {
|
|
97
|
+
pub fn from_start_report(report: &crate::coordinator::StartReport) -> Self {
|
|
98
|
+
Self {
|
|
99
|
+
ok: report.ok,
|
|
100
|
+
status: coordinator_start_status_wire(report.status).to_string(),
|
|
101
|
+
pid: report.pid.map(|pid| pid.get()),
|
|
102
|
+
binary_path: report.binary_path.clone(),
|
|
103
|
+
binary_version: report.binary_version.clone(),
|
|
104
|
+
rotation_reason: report.rotation_reason.clone(),
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fn coordinator_start_status_wire(status: crate::coordinator::StartOutcome) -> &'static str {
|
|
110
|
+
match status {
|
|
111
|
+
crate::coordinator::StartOutcome::AlreadyRunning => "already_running",
|
|
112
|
+
crate::coordinator::StartOutcome::RestartIncompatibleStopFailed => {
|
|
113
|
+
"restart_incompatible_stop_failed"
|
|
114
|
+
}
|
|
115
|
+
crate::coordinator::StartOutcome::SchemaIncompatible => "schema_incompatible",
|
|
116
|
+
crate::coordinator::StartOutcome::Started => "started",
|
|
117
|
+
crate::coordinator::StartOutcome::StartedAfterRotation => "started_after_rotation",
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
pub fn coordinator_start_summary_value(summary: &CoordinatorStartSummary) -> serde_json::Value {
|
|
122
|
+
serde_json::json!({
|
|
123
|
+
"ok": summary.ok,
|
|
124
|
+
"status": summary.status,
|
|
125
|
+
"pid": summary.pid,
|
|
126
|
+
"binary_path": summary.binary_path,
|
|
127
|
+
"binary_version": summary.binary_version,
|
|
128
|
+
"rotation_reason": summary.rotation_reason,
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
|
|
86
132
|
impl std::fmt::Display for PlanId {
|
|
87
133
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
88
134
|
f.write_str(&self.0)
|
|
@@ -649,7 +695,11 @@ pub enum RestartReport {
|
|
|
649
695
|
Restarted {
|
|
650
696
|
session_name: SessionName,
|
|
651
697
|
agents: Vec<RestartedAgent>,
|
|
698
|
+
/// Compatibility field: true means the coordinator requirement is
|
|
699
|
+
/// satisfied. The structured `coordinator` summary carries started vs
|
|
700
|
+
/// already-running vs rotated detail.
|
|
652
701
|
coordinator_started: bool,
|
|
702
|
+
coordinator: CoordinatorStartSummary,
|
|
653
703
|
next_actions: Vec<String>,
|
|
654
704
|
attach_commands: Vec<String>,
|
|
655
705
|
},
|
|
@@ -659,7 +709,11 @@ pub enum RestartReport {
|
|
|
659
709
|
session_name: SessionName,
|
|
660
710
|
agents: Vec<RestartedAgent>,
|
|
661
711
|
failed_agents: Vec<RestartFailedAgent>,
|
|
712
|
+
/// Compatibility field: true means the coordinator requirement is
|
|
713
|
+
/// satisfied. The structured `coordinator` summary carries started vs
|
|
714
|
+
/// already-running vs rotated detail.
|
|
662
715
|
coordinator_started: bool,
|
|
716
|
+
coordinator: CoordinatorStartSummary,
|
|
663
717
|
next_actions: Vec<String>,
|
|
664
718
|
attach_commands: Vec<String>,
|
|
665
719
|
},
|
|
@@ -301,12 +301,19 @@ fn start_report_value(report: &crate::coordinator::StartReport) -> serde_json::V
|
|
|
301
301
|
}
|
|
302
302
|
crate::coordinator::StartOutcome::SchemaIncompatible => "schema_incompatible",
|
|
303
303
|
crate::coordinator::StartOutcome::Started => "started",
|
|
304
|
+
crate::coordinator::StartOutcome::StartedAfterRotation => "started_after_rotation",
|
|
304
305
|
};
|
|
305
306
|
let mut value = serde_json::json!({
|
|
306
307
|
"ok": report.ok,
|
|
307
308
|
"pid": report.pid.map(|p| p.get()),
|
|
308
309
|
"status": status,
|
|
310
|
+
"binary_path": report.binary_path.clone(),
|
|
311
|
+
"binary_version": report.binary_version.clone(),
|
|
312
|
+
"rotation_reason": report.rotation_reason.clone(),
|
|
309
313
|
});
|
|
314
|
+
if let Some(previous_pid) = report.previous_pid {
|
|
315
|
+
value["previous_pid"] = serde_json::json!(previous_pid.get());
|
|
316
|
+
}
|
|
310
317
|
if let Some(log) = &report.log {
|
|
311
318
|
value["log"] = serde_json::json!(log.to_string_lossy().to_string());
|
|
312
319
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@team-agent/installer",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.19",
|
|
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.5.
|
|
24
|
-
"@team-agent/cli-darwin-x64": "0.5.
|
|
25
|
-
"@team-agent/cli-linux-x64": "0.5.
|
|
23
|
+
"@team-agent/cli-darwin-arm64": "0.5.19",
|
|
24
|
+
"@team-agent/cli-darwin-x64": "0.5.19",
|
|
25
|
+
"@team-agent/cli-linux-x64": "0.5.19"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"postinstall": "node npm/bincheck.mjs",
|