@integrity-labs/agt-cli 0.28.558 → 0.28.560

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.
@@ -45,7 +45,7 @@ import {
45
45
  resolveConnectivityProbe,
46
46
  worseConnectivityOutcome,
47
47
  wrapScheduledTaskPrompt
48
- } from "./chunk-TBP245GG.js";
48
+ } from "./chunk-AN7V4OG6.js";
49
49
  import {
50
50
  parsePsRows
51
51
  } from "./chunk-XWVM4KPK.js";
@@ -5643,7 +5643,7 @@ function exchangeFailureKind(err) {
5643
5643
  }
5644
5644
 
5645
5645
  // src/lib/api-client.ts
5646
- var agtCliVersion = true ? "0.28.558" : "dev";
5646
+ var agtCliVersion = true ? "0.28.560" : "dev";
5647
5647
  var lastConfigHash = null;
5648
5648
  function setConfigHash(hash) {
5649
5649
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -9008,4 +9008,4 @@ export {
9008
9008
  managerInstallSystemUnitCommand,
9009
9009
  managerUninstallSystemUnitCommand
9010
9010
  };
9011
- //# sourceMappingURL=chunk-JXMFOFLO.js.map
9011
+ //# sourceMappingURL=chunk-C2GQLZ4F.js.map
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
100
100
  return { ok: true };
101
101
  } catch {
102
102
  }
103
- const { resolveClaudeBinary } = await import("./persistent-session-WX4ILTCF.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-7P5B6Z4M.js");
104
104
  const claudeBin = resolveClaudeBinary();
105
105
  const pairEnv = {
106
106
  ...process.env,
@@ -373,4 +373,4 @@ export {
373
373
  startClaudePair,
374
374
  submitClaudePairCode
375
375
  };
376
- //# sourceMappingURL=claude-pair-runtime-OASMES54.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-D4BXRU2P.js.map
@@ -53,7 +53,7 @@ import {
53
53
  safeWriteJsonAtomic,
54
54
  setConfigHash,
55
55
  tripClass
56
- } from "../chunk-JXMFOFLO.js";
56
+ } from "../chunk-C2GQLZ4F.js";
57
57
  import {
58
58
  getProjectDir as getProjectDir2,
59
59
  getReadyTasks,
@@ -181,7 +181,7 @@ import {
181
181
  toOpencodeModel,
182
182
  transcriptActivityAgeSeconds,
183
183
  writeEgressAllowlist
184
- } from "../chunk-TBP245GG.js";
184
+ } from "../chunk-AN7V4OG6.js";
185
185
  import {
186
186
  reapOrphanChannelMcps
187
187
  } from "../chunk-XWVM4KPK.js";
@@ -275,16 +275,16 @@ function channelSecretValueHash(envEntries, channelSecretKeys) {
275
275
  // src/lib/mcp-restart-verify.ts
276
276
  var RESTART_VERIFY_DEADLINE_MS = 9e4;
277
277
  var RESTART_VERIFY_MAX_ATTEMPTS = 3;
278
- function decidePostRestartVerification(pending, sessionStartedAt, sessionHealthy, sessionRespawnId, now, opts = {}) {
278
+ function decidePostRestartVerification(pending2, sessionStartedAt, sessionHealthy, sessionRespawnId, now, opts = {}) {
279
279
  const deadlineMs = opts.deadlineMs ?? RESTART_VERIFY_DEADLINE_MS;
280
280
  const maxAttempts = opts.maxAttempts ?? RESTART_VERIFY_MAX_ATTEMPTS;
281
- if (sessionStartedAt !== null && sessionStartedAt > pending.firedAt && sessionHealthy && sessionRespawnId !== null) {
281
+ if (sessionStartedAt !== null && sessionStartedAt > pending2.firedAt && sessionHealthy && sessionRespawnId !== null) {
282
282
  return { kind: "verified" };
283
283
  }
284
- if (now - pending.firedAt < deadlineMs) {
284
+ if (now - pending2.firedAt < deadlineMs) {
285
285
  return { kind: "waiting" };
286
286
  }
287
- const attempt = pending.attempts + 1;
287
+ const attempt = pending2.attempts + 1;
288
288
  return { kind: "unverified", attempt, final: attempt >= maxAttempts };
289
289
  }
290
290
  function shouldRemediateUnverifiedRestart(outcome, ctx) {
@@ -1139,6 +1139,19 @@ function decideStaleTripClear(opts) {
1139
1139
  return { action: "clear", ageMs };
1140
1140
  }
1141
1141
 
1142
+ // src/lib/pending-suppression-reports.ts
1143
+ var pending = /* @__PURE__ */ new Map();
1144
+ function queueSuppressionReport(codeName, payload) {
1145
+ pending.set(codeName, payload);
1146
+ }
1147
+ function takeSuppressionReport(codeName, agentId) {
1148
+ const payload = pending.get(codeName);
1149
+ if (!payload) return null;
1150
+ if (!agentId) return null;
1151
+ pending.delete(codeName);
1152
+ return payload;
1153
+ }
1154
+
1142
1155
  // src/lib/resume-reconciler.ts
1143
1156
  var DEFAULT_MIN_HEALTHY_CYCLES = 2;
1144
1157
  var DEFAULT_BACKOFF_RESET_MS2 = 864e5;
@@ -2500,7 +2513,7 @@ async function maybeReportTokenUsage(args) {
2500
2513
  state2.set(codeName, next);
2501
2514
  return;
2502
2515
  }
2503
- const pending = [];
2516
+ const pending2 = [];
2504
2517
  const pendingRuns = [];
2505
2518
  for (const name of dirEntries) {
2506
2519
  if (!name.endsWith(".jsonl")) continue;
@@ -2530,7 +2543,7 @@ async function maybeReportTokenUsage(args) {
2530
2543
  const parsed = parseTranscriptUsage(content);
2531
2544
  for (const [model, totals] of parsed.byModel) {
2532
2545
  if (isEmptyTotals(totals)) continue;
2533
- pending.push({
2546
+ pending2.push({
2534
2547
  sessionId,
2535
2548
  fp,
2536
2549
  entry: {
@@ -2561,13 +2574,13 @@ async function maybeReportTokenUsage(args) {
2561
2574
  files.set(sessionId, fp);
2562
2575
  }
2563
2576
  }
2564
- if (pending.length === 0) {
2577
+ if (pending2.length === 0) {
2565
2578
  state2.set(codeName, next);
2566
2579
  return;
2567
2580
  }
2568
2581
  let reported = 0;
2569
- for (let i = 0; i < pending.length; i += MAX_ENTRIES_PER_POST) {
2570
- const batch = pending.slice(i, i + MAX_ENTRIES_PER_POST);
2582
+ for (let i = 0; i < pending2.length; i += MAX_ENTRIES_PER_POST) {
2583
+ const batch = pending2.slice(i, i + MAX_ENTRIES_PER_POST);
2571
2584
  try {
2572
2585
  await api2.post("/host/token-usage", {
2573
2586
  agent_id: agentId,
@@ -3060,30 +3073,30 @@ async function maybeEvaluateConversations(args) {
3060
3073
  return;
3061
3074
  }
3062
3075
  state3.set(codeName, { lastCheckedAt: nowMs });
3063
- let pending;
3076
+ let pending2;
3064
3077
  try {
3065
3078
  const resp = await api2.get(
3066
3079
  `/host/conversations/pending-evaluation?agent_id=${encodeURIComponent(agentId)}`
3067
3080
  );
3068
- pending = resp?.conversations ?? [];
3081
+ pending2 = resp?.conversations ?? [];
3069
3082
  } catch (err) {
3070
3083
  const msg = toHealthErrorMessage(err);
3071
3084
  log2(`[conversation-eval] ${codeName}: pending fetch failed: ${msg}`);
3072
3085
  await reportBackendHealth(api2, log2, codeName, { ok: false, error: `pending fetch: ${msg}` });
3073
3086
  return;
3074
3087
  }
3075
- if (pending.length === 0) return;
3088
+ if (pending2.length === 0) return;
3076
3089
  const dir = args.transcriptDir ?? sessionTranscriptDir(getProjectDir(codeName));
3077
3090
  const allTurns = readRecentTurns(dir, nowMs);
3078
3091
  if (allTurns.length === 0) {
3079
- for (const conv of pending) {
3092
+ for (const conv of pending2) {
3080
3093
  await reportSkip(api2, agentId, conv.conversation_id, "no_transcript", log2, codeName);
3081
3094
  }
3082
3095
  return;
3083
3096
  }
3084
3097
  let backendSucceeded = false;
3085
3098
  let backendError = null;
3086
- for (const conv of pending) {
3099
+ for (const conv of pending2) {
3087
3100
  const windowStart = Date.parse(conv.started_at) - WINDOW_PAD_MS;
3088
3101
  const windowEnd = Date.parse(conv.last_message_at) + WINDOW_PAD_MS;
3089
3102
  const turns = reconstructConversation(allTurns, conv.channel_ref, windowStart, windowEnd);
@@ -3399,26 +3412,26 @@ async function maybeExtractMemories(args) {
3399
3412
  return;
3400
3413
  }
3401
3414
  state4.set(codeName, { lastCheckedAt: nowMs });
3402
- let pending;
3415
+ let pending2;
3403
3416
  try {
3404
3417
  const resp = await api2.get(
3405
3418
  `/host/memories/pending-extraction?agent_id=${encodeURIComponent(agentId)}`
3406
3419
  );
3407
- pending = resp?.conversations ?? [];
3420
+ pending2 = resp?.conversations ?? [];
3408
3421
  } catch (err) {
3409
3422
  log2(`[memory-extract] ${codeName}: pending fetch failed: ${err.message}`);
3410
3423
  return;
3411
3424
  }
3412
- if (pending.length === 0) return;
3425
+ if (pending2.length === 0) return;
3413
3426
  const dir = args.transcriptDir ?? sessionTranscriptDir(getProjectDir(codeName));
3414
3427
  const allTurns = readRecentTurns(dir, nowMs);
3415
3428
  if (allTurns.length === 0) {
3416
- for (const conv of pending) {
3429
+ for (const conv of pending2) {
3417
3430
  await reportSkip2(api2, agentId, conv.conversation_id, log2, codeName);
3418
3431
  }
3419
3432
  return;
3420
3433
  }
3421
- for (const conv of pending) {
3434
+ for (const conv of pending2) {
3422
3435
  const windowStart = Date.parse(conv.started_at) - WINDOW_PAD_MS2;
3423
3436
  const windowEnd = Date.parse(conv.last_message_at) + WINDOW_PAD_MS2;
3424
3437
  const turns = reconstructConversation(allTurns, conv.channel_ref, windowStart, windowEnd);
@@ -4403,9 +4416,9 @@ function noteRestartRequested(codeName, requestedAtIso, now = Date.now()) {
4403
4416
  pendingRequested.set(codeName, { requestedAtMs, notedAtMs: now });
4404
4417
  }
4405
4418
  function beginRestartTiming(codeName, opts, log2, now = Date.now()) {
4406
- const pending = pendingRequested.get(codeName);
4419
+ const pending2 = pendingRequested.get(codeName);
4407
4420
  pendingRequested.delete(codeName);
4408
- const requestedAtMs = pending && now - pending.notedAtMs <= REQUESTED_TTL_MS ? pending.requestedAtMs : null;
4421
+ const requestedAtMs = pending2 && now - pending2.notedAtMs <= REQUESTED_TTL_MS ? pending2.requestedAtMs : null;
4409
4422
  tracks.set(codeName, {
4410
4423
  reason: opts.reason,
4411
4424
  requestedAtMs,
@@ -9418,6 +9431,23 @@ function recordRestartForBreaker(codeName, reason) {
9418
9431
  log(
9419
9432
  `[restart-breaker] agent=${codeName} ${tripClassName} trip SUPPRESSED by the new-agent grace (reason=${reason}${culprit}, bucket=${bucketCount});${agePart} onboarding churn must not pause a new agent, but the grace ends ${expires} \u2014 if this churn is still going then, it WILL auto-pause (ENG-8690)`
9420
9433
  );
9434
+ const suppressionPayload = {
9435
+ trip_class: tripClassName,
9436
+ bucket_key: bucketKey,
9437
+ bucket_count: bucketCount,
9438
+ // AC4 names the age specifically. `sup` is absent only on an older
9439
+ // breaker build; send null rather than a fabricated 0, which would
9440
+ // read as "brand new" and is the one wrong answer here.
9441
+ agent_age_ms: sup ? sup.agentAgeMs : null,
9442
+ grace_expires_at: result.newAgentGraceExpiresAt ?? null
9443
+ };
9444
+ queueSuppressionReport(codeName, suppressionPayload);
9445
+ if (!agentState.codeNameToAgentId.has(codeName)) {
9446
+ log(
9447
+ `[restart-breaker] agent=${codeName} suppression report DEFERRED: no agent_id known yet (cold-start before processAgent). The local suppression still applied; the report is queued and will be sent on the next poll once the id is cached (ENG-8679).`
9448
+ );
9449
+ }
9450
+ maybeReportPendingSuppression(codeName);
9421
9451
  }
9422
9452
  return;
9423
9453
  }
@@ -9447,6 +9477,16 @@ function maybeReportCurrentTrip(codeName) {
9447
9477
  log(`[circuit-breaker] Failed to report trip for '${codeName}' to API: ${err.message}`);
9448
9478
  });
9449
9479
  }
9480
+ function maybeReportPendingSuppression(codeName) {
9481
+ const agentId = agentState.codeNameToAgentId.get(codeName);
9482
+ const payload = takeSuppressionReport(codeName, agentId);
9483
+ if (!payload || !agentId) return;
9484
+ void api.post("/host/circuit-breaker/suppressed", { agent_id: agentId, ...payload }).catch((err) => {
9485
+ log(
9486
+ `[restart-breaker] agent=${codeName} suppression report failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
9487
+ );
9488
+ });
9489
+ }
9450
9490
  function maybeClearStaleTrip(agent) {
9451
9491
  const codeName = agent.code_name;
9452
9492
  const trip = restartBreaker.getTrip(codeName);
@@ -9864,12 +9904,12 @@ var BIND_REMEDIATION_MAX_CONNECTIVITY_DEFERRALS = readEnvNumber(
9864
9904
  var firstConnectUnsettledByAgent = /* @__PURE__ */ new Map();
9865
9905
  function verifyPendingRestarts(now) {
9866
9906
  if (pendingRestartVerifications.size === 0) return;
9867
- for (const [codeName, pending] of pendingRestartVerifications) {
9907
+ for (const [codeName, pending2] of pendingRestartVerifications) {
9868
9908
  const healthy = isSessionHealthy(codeName);
9869
9909
  const session = getSessionState(codeName);
9870
9910
  const startedAt = session?.startedAt ?? null;
9871
9911
  const respawnId = session?.currentSessionId ?? null;
9872
- const outcome = decidePostRestartVerification(pending, startedAt, healthy, respawnId, now);
9912
+ const outcome = decidePostRestartVerification(pending2, startedAt, healthy, respawnId, now);
9873
9913
  switch (outcome.kind) {
9874
9914
  case "verified":
9875
9915
  pendingRestartVerifications.delete(codeName);
@@ -9883,7 +9923,7 @@ function verifyPendingRestarts(now) {
9883
9923
  break;
9884
9924
  case "unverified":
9885
9925
  if (outcome.final) {
9886
- const deferrals = pending.connectivityDeferrals ?? 0;
9926
+ const deferrals = pending2.connectivityDeferrals ?? 0;
9887
9927
  if (shouldDeferBindRemediationForFirstConnect(outcome, {
9888
9928
  enabled: bindRemediationEnabled(),
9889
9929
  breakerTripped: restartBreaker.isTripped(codeName),
@@ -9894,7 +9934,7 @@ function verifyPendingRestarts(now) {
9894
9934
  })) {
9895
9935
  pendingRestartVerifications.set(codeName, {
9896
9936
  firedAt: now,
9897
- attempts: pending.attempts,
9937
+ attempts: pending2.attempts,
9898
9938
  connectivityDeferrals: deferrals + 1
9899
9939
  });
9900
9940
  log(
@@ -10542,7 +10582,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
10542
10582
  var lastVersionCheckAt = 0;
10543
10583
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
10544
10584
  var lastResponsivenessProbeAt = 0;
10545
- var agtCliVersion = true ? "0.28.558" : "dev";
10585
+ var agtCliVersion = true ? "0.28.560" : "dev";
10546
10586
  function resolveBrewPath(execFileSync2) {
10547
10587
  try {
10548
10588
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -11846,7 +11886,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
11846
11886
  if (codeNames.length === 0) return;
11847
11887
  void (async () => {
11848
11888
  try {
11849
- const { collectDiagnostics } = await import("../persistent-session-WX4ILTCF.js");
11889
+ const { collectDiagnostics } = await import("../persistent-session-7P5B6Z4M.js");
11850
11890
  await api.post("/host/heartbeat", {
11851
11891
  host_id: hostId,
11852
11892
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor)
@@ -11954,7 +11994,7 @@ async function pollCycle() {
11954
11994
  }
11955
11995
  try {
11956
11996
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
11957
- const { collectDiagnostics } = await import("../persistent-session-WX4ILTCF.js");
11997
+ const { collectDiagnostics } = await import("../persistent-session-7P5B6Z4M.js");
11958
11998
  const diagCodeNames = [...agentState.persistentSessionAgents];
11959
11999
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor) : void 0;
11960
12000
  let tailscaleHostname;
@@ -12077,7 +12117,7 @@ async function pollCycle() {
12077
12117
  collectPanelessActivityProbes,
12078
12118
  getResponsivenessIntervalMs,
12079
12119
  occupancyQualificationClassifications
12080
- } = await import("../responsiveness-probe-FKJBQ6PQ.js");
12120
+ } = await import("../responsiveness-probe-AALUPZKZ.js");
12081
12121
  const probeIntervalMs = getResponsivenessIntervalMs();
12082
12122
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
12083
12123
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -12168,7 +12208,7 @@ async function pollCycle() {
12168
12208
  collectResponsivenessProbes,
12169
12209
  livePendingInboundOldestAgeSeconds,
12170
12210
  parkPendingInbound
12171
- } = await import("../responsiveness-probe-FKJBQ6PQ.js");
12211
+ } = await import("../responsiveness-probe-AALUPZKZ.js");
12172
12212
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
12173
12213
  const wedgeNow = /* @__PURE__ */ new Date();
12174
12214
  const liveAgents = agentState.persistentSessionAgents;
@@ -12730,6 +12770,7 @@ async function processAgent(agent, agentStates) {
12730
12770
  agentState.codeNameToAgentId.set(agent.code_name, agent.agent_id);
12731
12771
  maybeClearStaleTrip(agent);
12732
12772
  maybeReportCurrentTrip(agent.code_name);
12773
+ maybeReportPendingSuppression(agent.code_name);
12733
12774
  if (agent.framework) {
12734
12775
  agentFrameworkCache.set(agent.code_name, agent.framework);
12735
12776
  }
@@ -15712,7 +15753,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
15712
15753
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
15713
15754
  void (async () => {
15714
15755
  try {
15715
- const { collectDiagnostics } = await import("../persistent-session-WX4ILTCF.js");
15756
+ const { collectDiagnostics } = await import("../persistent-session-7P5B6Z4M.js");
15716
15757
  await api.post("/host/heartbeat", {
15717
15758
  host_id: hostId,
15718
15759
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
@@ -15762,7 +15803,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
15762
15803
  }
15763
15804
  try {
15764
15805
  const hostId = await getHostId();
15765
- const { collectDiagnostics } = await import("../persistent-session-WX4ILTCF.js");
15806
+ const { collectDiagnostics } = await import("../persistent-session-7P5B6Z4M.js");
15766
15807
  await api.post("/host/heartbeat", {
15767
15808
  host_id: hostId,
15768
15809
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
@@ -16334,7 +16375,7 @@ async function processClaudePairSessions(agents) {
16334
16375
  killPairSession,
16335
16376
  pairTmuxSession,
16336
16377
  finalizeClaudePairOnboarding
16337
- } = await import("../claude-pair-runtime-OASMES54.js");
16378
+ } = await import("../claude-pair-runtime-D4BXRU2P.js");
16338
16379
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
16339
16380
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
16340
16381
  const killed = await killPairSession(pairTmuxSession(pairId));