@integrity-labs/agt-cli 0.28.236 → 0.28.238

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.
@@ -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-LVDRHYX7.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-HTOCDCII.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-2ZFH6K4I.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-A4P6E7U5.js.map
@@ -37,7 +37,7 @@ import {
37
37
  requireHost,
38
38
  safeWriteJsonAtomic,
39
39
  setConfigHash
40
- } from "../chunk-ND3HG32M.js";
40
+ } from "../chunk-D4HUKRER.js";
41
41
  import {
42
42
  getProjectDir as getProjectDir2,
43
43
  getReadyTasks,
@@ -122,7 +122,7 @@ import {
122
122
  takeZombieDetection,
123
123
  transcriptActivityAgeSeconds,
124
124
  writeEgressAllowlist
125
- } from "../chunk-PYVEJMY2.js";
125
+ } from "../chunk-P7TUBBQL.js";
126
126
  import {
127
127
  reapOrphanChannelMcps
128
128
  } from "../chunk-XWVM4KPK.js";
@@ -3416,6 +3416,74 @@ async function execFilePromiseLong(cmd, args, opts) {
3416
3416
  });
3417
3417
  }
3418
3418
 
3419
+ // src/lib/manager/restart-timing.ts
3420
+ var pendingRequested = /* @__PURE__ */ new Map();
3421
+ var tracks = /* @__PURE__ */ new Map();
3422
+ var REQUESTED_TTL_MS = 5 * 6e4;
3423
+ function fmtMs(ms) {
3424
+ return `${Math.round(ms)}ms`;
3425
+ }
3426
+ function noteRestartRequested(codeName, requestedAtIso, now = Date.now()) {
3427
+ const requestedAtMs = Date.parse(requestedAtIso);
3428
+ if (Number.isNaN(requestedAtMs)) return;
3429
+ pendingRequested.set(codeName, { requestedAtMs, notedAtMs: now });
3430
+ }
3431
+ function beginRestartTiming(codeName, opts, log2, now = Date.now()) {
3432
+ const pending = pendingRequested.get(codeName);
3433
+ pendingRequested.delete(codeName);
3434
+ const requestedAtMs = pending && now - pending.notedAtMs <= REQUESTED_TTL_MS ? pending.requestedAtMs : null;
3435
+ tracks.set(codeName, {
3436
+ reason: opts.reason,
3437
+ requestedAtMs,
3438
+ startedAtMs: now,
3439
+ injectDelayMs: opts.injectDelayMs,
3440
+ delivered: opts.delivered,
3441
+ stopAtMs: null
3442
+ });
3443
+ const parts = [
3444
+ `reason="${opts.reason}"`,
3445
+ `delivered=${opts.delivered === null ? "unknown" : opts.delivered}`,
3446
+ `injectDelayMs=${opts.injectDelayMs ?? "n/a"}`
3447
+ ];
3448
+ if (requestedAtMs !== null) {
3449
+ parts.push(`pickup=${fmtMs(now - requestedAtMs)} (request->render)`);
3450
+ }
3451
+ log2(`[restart-timing] '${codeName}' begin ${parts.join(" ")}`);
3452
+ }
3453
+ function markRestartStopped(codeName, log2, now = Date.now()) {
3454
+ const track = tracks.get(codeName);
3455
+ if (!track) return;
3456
+ track.stopAtMs = now;
3457
+ log2(
3458
+ `[restart-timing] '${codeName}' stop +${fmtMs(now - track.startedAtMs)} (schedule->stop; inject/gate delay)`
3459
+ );
3460
+ }
3461
+ function finishRestartTiming(codeName, outcome, detail, log2, now = Date.now()) {
3462
+ const track = tracks.get(codeName);
3463
+ if (!track) return;
3464
+ tracks.delete(codeName);
3465
+ const originMs = track.requestedAtMs ?? track.startedAtMs;
3466
+ const originLabel = track.requestedAtMs !== null ? "request->tools-live" : "schedule->tools-live";
3467
+ const totalMs = now - originMs;
3468
+ const stopToBound = track.stopAtMs !== null ? now - track.stopAtMs : null;
3469
+ const suffix = detail ? ` (${detail})` : "";
3470
+ if (outcome === "tools-bound") {
3471
+ const boundPart = stopToBound !== null ? `+${fmtMs(stopToBound)} (stop->bound: respawn + MCP bind)` : `(no stop observed)`;
3472
+ log2(
3473
+ `[restart-timing] '${codeName}' tools-bound ${boundPart} \u2014 total ${fmtMs(totalMs)} (${originLabel})${suffix}`
3474
+ );
3475
+ } else {
3476
+ const boundPart = stopToBound !== null ? `+${fmtMs(stopToBound)} since stop` : `(no stop observed)`;
3477
+ log2(
3478
+ `[restart-timing] '${codeName}' FAILED to bind ${boundPart} \u2014 total ${fmtMs(totalMs)} (${track.requestedAtMs !== null ? "request" : "schedule"}->give-up)${suffix}`
3479
+ );
3480
+ }
3481
+ }
3482
+ function clearRestartTiming(codeName) {
3483
+ tracks.delete(codeName);
3484
+ pendingRequested.delete(codeName);
3485
+ }
3486
+
3419
3487
  // src/lib/manager/model.ts
3420
3488
  function resolveModelChain(refreshData) {
3421
3489
  const agent = refreshData.agent;
@@ -5975,6 +6043,7 @@ function scheduleSessionRestart(codeName, delayMs, reason, breakerReason = "hot-
5975
6043
  }
5976
6044
  }
5977
6045
  stopPersistentSession(codeName, log);
6046
+ markRestartStopped(codeName, log);
5978
6047
  runningMcpHashes.delete(codeName);
5979
6048
  recordRestartForBreaker(codeName, breakerReason);
5980
6049
  log(`[hot-reload] Session stopped for '${codeName}' \u2014 will respawn with ${reason}`);
@@ -5991,6 +6060,7 @@ function scheduleSessionRestart(codeName, delayMs, reason, breakerReason = "hot-
5991
6060
  }
5992
6061
  function cancelPendingSessionRestart(codeName) {
5993
6062
  pendingRestartVerifications.delete(codeName);
6063
+ clearRestartTiming(codeName);
5994
6064
  const existing = pendingSessionRestarts.get(codeName);
5995
6065
  if (!existing) return;
5996
6066
  clearTimeout(existing.timer);
@@ -6015,6 +6085,7 @@ function verifyPendingRestarts(now) {
6015
6085
  case "verified":
6016
6086
  pendingRestartVerifications.delete(codeName);
6017
6087
  log(`[restart-verify] '${codeName}' respawned healthy after MCP change \u2014 tools bound (ENG-6174)`);
6088
+ finishRestartTiming(codeName, "tools-bound", void 0, log, now);
6018
6089
  break;
6019
6090
  case "waiting":
6020
6091
  break;
@@ -6024,6 +6095,7 @@ function verifyPendingRestarts(now) {
6024
6095
  log(
6025
6096
  `[restart-verify] ERROR '${codeName}' did NOT respawn healthy after ${outcome.attempt} attempts following an MCP change \u2014 the live session may be stuck on its pre-restart tools. Check session health / manager.log; a manual session restart may be required (ENG-6174)`
6026
6097
  );
6098
+ finishRestartTiming(codeName, "failed", `${outcome.attempt} verify attempts`, log, now);
6027
6099
  if (shouldRemediateUnverifiedRestart(outcome, {
6028
6100
  enabled: bindRemediationEnabled(),
6029
6101
  breakerTripped: restartBreaker.isTripped(codeName)
@@ -6426,7 +6498,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
6426
6498
  var lastVersionCheckAt = 0;
6427
6499
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
6428
6500
  var lastResponsivenessProbeAt = 0;
6429
- var agtCliVersion = true ? "0.28.236" : "dev";
6501
+ var agtCliVersion = true ? "0.28.238" : "dev";
6430
6502
  function resolveBrewPath(execFileSync2) {
6431
6503
  try {
6432
6504
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -7351,7 +7423,7 @@ async function pollCycle() {
7351
7423
  }
7352
7424
  try {
7353
7425
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
7354
- const { collectDiagnostics } = await import("../persistent-session-LVDRHYX7.js");
7426
+ const { collectDiagnostics } = await import("../persistent-session-HTOCDCII.js");
7355
7427
  const diagCodeNames = [...agentState.persistentSessionAgents];
7356
7428
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
7357
7429
  let tailscaleHostname;
@@ -7499,7 +7571,7 @@ async function pollCycle() {
7499
7571
  const {
7500
7572
  collectResponsivenessProbes,
7501
7573
  getResponsivenessIntervalMs
7502
- } = await import("../responsiveness-probe-UW5TXKMS.js");
7574
+ } = await import("../responsiveness-probe-JY4C4RI4.js");
7503
7575
  const probeIntervalMs = getResponsivenessIntervalMs();
7504
7576
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
7505
7577
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -7531,7 +7603,7 @@ async function pollCycle() {
7531
7603
  collectResponsivenessProbes,
7532
7604
  livePendingInboundOldestAgeSeconds,
7533
7605
  parkPendingInbound
7534
- } = await import("../responsiveness-probe-UW5TXKMS.js");
7606
+ } = await import("../responsiveness-probe-JY4C4RI4.js");
7535
7607
  const { getProjectDir: wedgeProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
7536
7608
  const wedgeNow = /* @__PURE__ */ new Date();
7537
7609
  const liveAgents = agentState.persistentSessionAgents;
@@ -7827,7 +7899,7 @@ async function pollCycle() {
7827
7899
  if (restartedCodeNames.length > 0) {
7828
7900
  void (async () => {
7829
7901
  try {
7830
- const { collectDiagnostics } = await import("../persistent-session-LVDRHYX7.js");
7902
+ const { collectDiagnostics } = await import("../persistent-session-HTOCDCII.js");
7831
7903
  const freshDiagnostics = collectDiagnostics(restartedCodeNames);
7832
7904
  await api.post("/host/heartbeat", {
7833
7905
  host_id: hostId,
@@ -9154,6 +9226,11 @@ async function processAgent(agent, agentStates) {
9154
9226
  if (!delivered) {
9155
9227
  log(`[hot-reload] Inject notification unconfirmed for '${agent.code_name}' \u2014 proceeding with shorter delay`);
9156
9228
  }
9229
+ beginRestartTiming(
9230
+ agent.code_name,
9231
+ { reason: "new MCP servers", delivered, injectDelayMs: delay },
9232
+ log
9233
+ );
9157
9234
  scheduleSessionRestart(agent.code_name, delay, "new MCP servers");
9158
9235
  }
9159
9236
  }
@@ -10292,6 +10369,9 @@ var restartInFlight = /* @__PURE__ */ new Set();
10292
10369
  function restartReasonNeedsRender(reason) {
10293
10370
  return reason != null && reason !== "manual";
10294
10371
  }
10372
+ function restartReasonStampsTiming(reason) {
10373
+ return reason === "integration-change";
10374
+ }
10295
10375
  async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
10296
10376
  const prev = state6.agents.find((a) => a.agentId === agentId);
10297
10377
  const codeName = prev?.codeName;
@@ -10299,6 +10379,9 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
10299
10379
  const lastProcessed = prev?.lastRestartProcessedAt ?? null;
10300
10380
  if (lastProcessed != null && Date.parse(lastProcessed) >= Date.parse(requestedAt)) return;
10301
10381
  if (restartReasonNeedsRender(restartReason)) {
10382
+ if (restartReasonStampsTiming(restartReason)) {
10383
+ noteRestartRequested(codeName, requestedAt);
10384
+ }
10302
10385
  triggerEarlyPoll(`config-change reload for '${codeName}' (reason=${restartReason})`);
10303
10386
  return;
10304
10387
  }
@@ -10335,7 +10418,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
10335
10418
  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}`));
10336
10419
  void (async () => {
10337
10420
  try {
10338
- const { collectDiagnostics } = await import("../persistent-session-LVDRHYX7.js");
10421
+ const { collectDiagnostics } = await import("../persistent-session-HTOCDCII.js");
10339
10422
  await api.post("/host/heartbeat", {
10340
10423
  host_id: hostId,
10341
10424
  agent_diagnostics: collectDiagnostics([codeName])
@@ -10729,7 +10812,7 @@ async function processClaudePairSessions(agents) {
10729
10812
  killPairSession,
10730
10813
  pairTmuxSession,
10731
10814
  finalizeClaudePairOnboarding
10732
- } = await import("../claude-pair-runtime-2ZFH6K4I.js");
10815
+ } = await import("../claude-pair-runtime-A4P6E7U5.js");
10733
10816
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
10734
10817
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
10735
10818
  const killed = await killPairSession(pairTmuxSession(pairId));