@integrity-labs/agt-cli 0.28.29 → 0.28.31

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.
@@ -22,7 +22,7 @@ import {
22
22
  provisionStopHook,
23
23
  requireHost,
24
24
  safeWriteJsonAtomic
25
- } from "../chunk-FIB2OQLF.js";
25
+ } from "../chunk-EJIU6AD6.js";
26
26
  import {
27
27
  getProjectDir as getProjectDir2,
28
28
  getReadyTasks,
@@ -1303,6 +1303,64 @@ async function runConnectivityProbes(integrations, options = {}) {
1303
1303
  return { reports, due: due.length, probed: batch.length, skipped };
1304
1304
  }
1305
1305
 
1306
+ // src/lib/dependency-recovery-ledger.ts
1307
+ function ledgerKey(kind, label) {
1308
+ return `${kind}:${label}`;
1309
+ }
1310
+ var DependencyRecoveryLedger = class {
1311
+ /** code_name → (`${kind}:${label}` → entry). */
1312
+ byAgent = /* @__PURE__ */ new Map();
1313
+ /**
1314
+ * Fold one connectivity-probe round's verdicts into the ledger. `down`
1315
+ * records (or re-arms) the dependency; `ok` marks an already-recorded one
1316
+ * recovered; anything else is left untouched (non-escalating, so it neither
1317
+ * opens nor closes an incident).
1318
+ */
1319
+ record(codeName, verdicts) {
1320
+ for (const v of verdicts) {
1321
+ if (v.status === "down") {
1322
+ const entries = this.entriesFor(codeName);
1323
+ const key = ledgerKey(v.kind, v.label);
1324
+ const existing = entries.get(key);
1325
+ if (existing) existing.recovered = false;
1326
+ else entries.set(key, { kind: v.kind, label: v.label, recovered: false });
1327
+ } else if (v.status === "ok") {
1328
+ const entry = this.byAgent.get(codeName)?.get(ledgerKey(v.kind, v.label));
1329
+ if (entry) entry.recovered = true;
1330
+ }
1331
+ }
1332
+ }
1333
+ /**
1334
+ * The dependencies that went down and have since read `ok` again — the
1335
+ * close-the-loop set for this agent's auto-resume. Read-only; the caller
1336
+ * {@link clear}s the agent once the resume that consumes this succeeds.
1337
+ */
1338
+ collectRecovered(codeName) {
1339
+ const entries = this.byAgent.get(codeName);
1340
+ if (!entries) return [];
1341
+ const out = [];
1342
+ for (const e of entries.values()) {
1343
+ if (e.recovered) out.push({ kind: e.kind, label: e.label });
1344
+ }
1345
+ return out;
1346
+ }
1347
+ /**
1348
+ * Drop an agent's ledger — call when its trip clears so the next trip diffs
1349
+ * from a clean slate (and unrecovered/deleted deps don't linger forever).
1350
+ */
1351
+ clear(codeName) {
1352
+ this.byAgent.delete(codeName);
1353
+ }
1354
+ entriesFor(codeName) {
1355
+ let entries = this.byAgent.get(codeName);
1356
+ if (!entries) {
1357
+ entries = /* @__PURE__ */ new Map();
1358
+ this.byAgent.set(codeName, entries);
1359
+ }
1360
+ return entries;
1361
+ }
1362
+ };
1363
+
1306
1364
  // src/lib/cli-probe.ts
1307
1365
  import { execFile } from "child_process";
1308
1366
  var DEFAULT_TIMEOUT_MS = 8e3;
@@ -5430,6 +5488,7 @@ var autoResumeInFlight = /* @__PURE__ */ new Set();
5430
5488
  var AUTO_RESUME_SELF_WINDOW_MS = 12e4;
5431
5489
  var autoResumeLoggedSkips = /* @__PURE__ */ new Map();
5432
5490
  var autoResumeStandDowns = /* @__PURE__ */ new Set();
5491
+ var dependencyRecoveryLedger = new DependencyRecoveryLedger();
5433
5492
  var killPausedCodeNames = /* @__PURE__ */ new Set();
5434
5493
  var BACK_ONLINE_GREETING_GUIDANCE = " When you reconnect, if you tell anyone you are back, start that message with a \u{1F44B} wave emoji and do not use a \u{1F7E2} green-light emoji.";
5435
5494
  function maybeAutoResume(agent) {
@@ -5473,6 +5532,7 @@ function maybeAutoResume(agent) {
5473
5532
  autoResumeMarkers.set(codeName, { trippedAt, autoResumedAt: Date.now() });
5474
5533
  restartBreaker.clear(codeName);
5475
5534
  reportedTrips.delete(codeName);
5535
+ dependencyRecoveryLedger.clear(codeName);
5476
5536
  state6 = {
5477
5537
  ...state6,
5478
5538
  circuitBreakerTrips: restartBreaker.serialize(),
@@ -5550,14 +5610,20 @@ async function maybeResumeReconcile(agent) {
5550
5610
  log(
5551
5611
  `[resume-reconciler] agent=${codeName} decision=resume healthyCycles=${decision.healthyCycles} trippedAt=${new Date(trippedAt).toISOString()} (ENG-6383)`
5552
5612
  );
5613
+ const recoveredDependencies = dependencyRecoveryLedger.collectRecovered(codeName);
5553
5614
  const res = await api.post(
5554
5615
  "/host/circuit-breaker/auto-resume",
5555
- { agent_id: agent.agent_id, tripped_at: new Date(trippedAt).toISOString() }
5616
+ {
5617
+ agent_id: agent.agent_id,
5618
+ tripped_at: new Date(trippedAt).toISOString(),
5619
+ ...recoveredDependencies.length > 0 ? { recovered_dependencies: recoveredDependencies } : {}
5620
+ }
5556
5621
  );
5557
5622
  if (res.resumed) {
5558
5623
  autoResumeMarkers.set(codeName, { trippedAt, autoResumedAt: Date.now() });
5559
5624
  restartBreaker.clear(codeName);
5560
5625
  reportedTrips.delete(codeName);
5626
+ dependencyRecoveryLedger.clear(codeName);
5561
5627
  state6 = {
5562
5628
  ...state6,
5563
5629
  circuitBreakerTrips: restartBreaker.serialize(),
@@ -5881,6 +5947,14 @@ async function runAgentConnectivityProbes(agent, integrations, projectDir) {
5881
5947
  agent_id: agent.agent_id,
5882
5948
  results: result.reports
5883
5949
  });
5950
+ const labelById = new Map(integrations.map((i) => [i.id, i.definition_id]));
5951
+ dependencyRecoveryLedger.record(
5952
+ agent.code_name,
5953
+ result.reports.flatMap((r) => {
5954
+ const label = labelById.get(r.integration_id);
5955
+ return label ? [{ kind: "integration", label, status: r.status }] : [];
5956
+ })
5957
+ );
5884
5958
  log(
5885
5959
  `Connectivity probe for '${agent.code_name}': probed=${result.probed} reported=${result.reports.length} due=${result.due}`
5886
5960
  );
@@ -6072,7 +6146,7 @@ var cachedMaintenanceWindow = null;
6072
6146
  var lastVersionCheckAt = 0;
6073
6147
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
6074
6148
  var lastResponsivenessProbeAt = 0;
6075
- var agtCliVersion = true ? "0.28.29" : "dev";
6149
+ var agtCliVersion = true ? "0.28.31" : "dev";
6076
6150
  function resolveBrewPath(execFileSync4) {
6077
6151
  try {
6078
6152
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();