@team-agent/installer 0.5.18 → 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
CHANGED
package/Cargo.toml
CHANGED
|
@@ -732,7 +732,8 @@ pub fn cmd_diagnose(args: &DiagnoseArgs) -> Result<CmdResult, CliError> {
|
|
|
732
732
|
&selected.run_workspace,
|
|
733
733
|
)),
|
|
734
734
|
};
|
|
735
|
-
let (issues, suggested_repairs) =
|
|
735
|
+
let (issues, suggested_repairs) =
|
|
736
|
+
diagnose_runtime_for_workspace(&selected.run_workspace, &state, backend.as_ref());
|
|
736
737
|
let ok = issues.as_array().is_some_and(Vec::is_empty);
|
|
737
738
|
Ok(CmdResult::from_json(
|
|
738
739
|
json!({
|
|
@@ -165,6 +165,125 @@ pub(crate) fn diagnose_runtime(state: &Value, backend: &dyn Transport) -> (Value
|
|
|
165
165
|
(Value::Array(issues), Value::Array(repairs))
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
pub(crate) fn diagnose_runtime_for_workspace(
|
|
169
|
+
workspace: &std::path::Path,
|
|
170
|
+
state: &Value,
|
|
171
|
+
backend: &dyn Transport,
|
|
172
|
+
) -> (Value, Value) {
|
|
173
|
+
let (mut issues, mut repairs) = diagnose_runtime(state, backend);
|
|
174
|
+
append_coordinator_health_issue(workspace, state, &mut issues, &mut repairs);
|
|
175
|
+
(issues, repairs)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
fn append_coordinator_health_issue(
|
|
179
|
+
workspace: &std::path::Path,
|
|
180
|
+
state: &Value,
|
|
181
|
+
issues: &mut Value,
|
|
182
|
+
repairs: &mut Value,
|
|
183
|
+
) {
|
|
184
|
+
let workspace = crate::coordinator::WorkspacePath::new(workspace.to_path_buf());
|
|
185
|
+
let health = crate::coordinator::coordinator_health(&workspace);
|
|
186
|
+
let Some(id) = coordinator_issue_id(state, &health) else {
|
|
187
|
+
return;
|
|
188
|
+
};
|
|
189
|
+
if let Some(items) = issues.as_array_mut() {
|
|
190
|
+
items.push(coordinator_issue_value(id, &health, workspace.as_path()));
|
|
191
|
+
}
|
|
192
|
+
if let Some(items) = repairs.as_array_mut() {
|
|
193
|
+
items.push(coordinator_repair_hint(id, &health));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
fn coordinator_issue_id(
|
|
198
|
+
state: &Value,
|
|
199
|
+
health: &crate::coordinator::HealthReport,
|
|
200
|
+
) -> Option<&'static str> {
|
|
201
|
+
match health.status {
|
|
202
|
+
crate::coordinator::CoordinatorHealthStatus::Stale
|
|
203
|
+
| crate::coordinator::CoordinatorHealthStatus::InvalidPid => {
|
|
204
|
+
Some("coordinator_unavailable")
|
|
205
|
+
}
|
|
206
|
+
crate::coordinator::CoordinatorHealthStatus::Running => {
|
|
207
|
+
if !health.metadata_ok {
|
|
208
|
+
return match health.metadata_mismatch_reason.as_deref() {
|
|
209
|
+
Some(
|
|
210
|
+
"binary_identity_missing"
|
|
211
|
+
| "binary_version_mismatch"
|
|
212
|
+
| "binary_path_mismatch",
|
|
213
|
+
) => Some("coordinator_stale_identity"),
|
|
214
|
+
Some(_) | None => Some("coordinator_unavailable"),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
if !health.schema.ok {
|
|
218
|
+
Some("coordinator_schema_incompatible")
|
|
219
|
+
} else {
|
|
220
|
+
None
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
crate::coordinator::CoordinatorHealthStatus::Missing => {
|
|
224
|
+
coordinator_expected(state).then_some("coordinator_unavailable")
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
fn coordinator_issue_value(
|
|
230
|
+
id: &str,
|
|
231
|
+
health: &crate::coordinator::HealthReport,
|
|
232
|
+
workspace: &std::path::Path,
|
|
233
|
+
) -> Value {
|
|
234
|
+
json!({
|
|
235
|
+
"id": id,
|
|
236
|
+
"status": coordinator_status_wire(health.status),
|
|
237
|
+
"pid": health.pid.map(|pid| pid.get()),
|
|
238
|
+
"metadata_ok": health.metadata_ok,
|
|
239
|
+
"metadata_mismatch_reason": health.metadata_mismatch_reason.clone(),
|
|
240
|
+
"binary_path": health.current_binary_identity.binary_path.clone(),
|
|
241
|
+
"binary_version": health.current_binary_identity.binary_version.clone(),
|
|
242
|
+
"schema_ok": health.schema.ok,
|
|
243
|
+
"coordinator_log": crate::coordinator::coordinator_log_path(
|
|
244
|
+
&crate::coordinator::WorkspacePath::new(workspace.to_path_buf())
|
|
245
|
+
)
|
|
246
|
+
.to_string_lossy()
|
|
247
|
+
.to_string(),
|
|
248
|
+
})
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
fn coordinator_repair_hint(id: &str, _health: &crate::coordinator::HealthReport) -> Value {
|
|
252
|
+
let hint_action = match id {
|
|
253
|
+
"coordinator_schema_incompatible" => "team-agent repair-state --schema",
|
|
254
|
+
_ => "team-agent restart",
|
|
255
|
+
};
|
|
256
|
+
json!({
|
|
257
|
+
"issue": id,
|
|
258
|
+
"action_required": true,
|
|
259
|
+
"advisory": true,
|
|
260
|
+
"broken_class": id,
|
|
261
|
+
"hint_action": hint_action,
|
|
262
|
+
"dedupe_key": id,
|
|
263
|
+
"action": format!("{hint_action} # diagnose only reports coordinator health; it does not start, stop, or rotate the coordinator"),
|
|
264
|
+
})
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
fn coordinator_expected(state: &Value) -> bool {
|
|
268
|
+
state
|
|
269
|
+
.get("session_name")
|
|
270
|
+
.and_then(Value::as_str)
|
|
271
|
+
.is_some_and(|session| !session.is_empty())
|
|
272
|
+
|| state
|
|
273
|
+
.get("agents")
|
|
274
|
+
.and_then(Value::as_object)
|
|
275
|
+
.is_some_and(|agents| !agents.is_empty())
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
fn coordinator_status_wire(status: crate::coordinator::CoordinatorHealthStatus) -> &'static str {
|
|
279
|
+
match status {
|
|
280
|
+
crate::coordinator::CoordinatorHealthStatus::Missing => "missing",
|
|
281
|
+
crate::coordinator::CoordinatorHealthStatus::InvalidPid => "invalid_pid",
|
|
282
|
+
crate::coordinator::CoordinatorHealthStatus::Running => "running",
|
|
283
|
+
crate::coordinator::CoordinatorHealthStatus::Stale => "stale",
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
168
287
|
fn topology_repair_hint(issue: &str) -> Value {
|
|
169
288
|
json!({
|
|
170
289
|
"issue": issue,
|
|
@@ -246,6 +365,72 @@ mod tests {
|
|
|
246
365
|
path
|
|
247
366
|
}
|
|
248
367
|
|
|
368
|
+
fn coordinator_health_fixture(
|
|
369
|
+
status: crate::coordinator::CoordinatorHealthStatus,
|
|
370
|
+
metadata_mismatch_reason: Option<&str>,
|
|
371
|
+
schema_ok: bool,
|
|
372
|
+
) -> crate::coordinator::HealthReport {
|
|
373
|
+
crate::coordinator::HealthReport {
|
|
374
|
+
ok: matches!(status, crate::coordinator::CoordinatorHealthStatus::Running)
|
|
375
|
+
&& metadata_mismatch_reason.is_none()
|
|
376
|
+
&& schema_ok,
|
|
377
|
+
status,
|
|
378
|
+
pid: Some(crate::coordinator::Pid::new(std::process::id())),
|
|
379
|
+
metadata: None,
|
|
380
|
+
metadata_ok: metadata_mismatch_reason.is_none(),
|
|
381
|
+
metadata_mismatch_reason: metadata_mismatch_reason.map(ToString::to_string),
|
|
382
|
+
current_binary_identity: crate::coordinator::CoordinatorBinaryIdentity {
|
|
383
|
+
binary_path: "/current/team-agent".to_string(),
|
|
384
|
+
binary_version: env!("CARGO_PKG_VERSION").to_string(),
|
|
385
|
+
},
|
|
386
|
+
schema: crate::coordinator::SchemaHealth {
|
|
387
|
+
ok: schema_ok,
|
|
388
|
+
schema_version: crate::db::schema::SCHEMA_VERSION,
|
|
389
|
+
error: None,
|
|
390
|
+
action: None,
|
|
391
|
+
},
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
#[test]
|
|
396
|
+
fn coordinator_issue_id_maps_stale_pid_to_unavailable() {
|
|
397
|
+
let health = coordinator_health_fixture(
|
|
398
|
+
crate::coordinator::CoordinatorHealthStatus::Stale,
|
|
399
|
+
None,
|
|
400
|
+
true,
|
|
401
|
+
);
|
|
402
|
+
assert_eq!(
|
|
403
|
+
coordinator_issue_id(&json!({"session_name": "team-fixture"}), &health),
|
|
404
|
+
Some("coordinator_unavailable")
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
#[test]
|
|
409
|
+
fn coordinator_issue_id_maps_binary_identity_to_stale_identity() {
|
|
410
|
+
let health = coordinator_health_fixture(
|
|
411
|
+
crate::coordinator::CoordinatorHealthStatus::Running,
|
|
412
|
+
Some("binary_version_mismatch"),
|
|
413
|
+
true,
|
|
414
|
+
);
|
|
415
|
+
assert_eq!(
|
|
416
|
+
coordinator_issue_id(&json!({"session_name": "team-fixture"}), &health),
|
|
417
|
+
Some("coordinator_stale_identity")
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
#[test]
|
|
422
|
+
fn coordinator_issue_id_maps_schema_failure_to_schema_incompatible() {
|
|
423
|
+
let health = coordinator_health_fixture(
|
|
424
|
+
crate::coordinator::CoordinatorHealthStatus::Running,
|
|
425
|
+
None,
|
|
426
|
+
false,
|
|
427
|
+
);
|
|
428
|
+
assert_eq!(
|
|
429
|
+
coordinator_issue_id(&json!({"session_name": "team-fixture"}), &health),
|
|
430
|
+
Some("coordinator_schema_incompatible")
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
|
|
249
434
|
#[test]
|
|
250
435
|
fn diagnose_surfaces_codex_session_identity_mismatch() {
|
|
251
436
|
let workspace =
|
|
@@ -695,6 +695,9 @@ pub enum RestartReport {
|
|
|
695
695
|
Restarted {
|
|
696
696
|
session_name: SessionName,
|
|
697
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.
|
|
698
701
|
coordinator_started: bool,
|
|
699
702
|
coordinator: CoordinatorStartSummary,
|
|
700
703
|
next_actions: Vec<String>,
|
|
@@ -706,6 +709,9 @@ pub enum RestartReport {
|
|
|
706
709
|
session_name: SessionName,
|
|
707
710
|
agents: Vec<RestartedAgent>,
|
|
708
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.
|
|
709
715
|
coordinator_started: bool,
|
|
710
716
|
coordinator: CoordinatorStartSummary,
|
|
711
717
|
next_actions: Vec<String>,
|
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",
|