@integrity-labs/agt-cli 0.28.21 → 0.28.23

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-5BEMWOTM.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-34CY65FC.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-LQJ5E4IF.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-UKOL6GWJ.js.map
@@ -22,7 +22,7 @@ import {
22
22
  provisionStopHook,
23
23
  requireHost,
24
24
  safeWriteJsonAtomic
25
- } from "../chunk-NGZVHSI3.js";
25
+ } from "../chunk-JFSOYKVJ.js";
26
26
  import {
27
27
  getProjectDir as getProjectDir2,
28
28
  getReadyTasks,
@@ -64,7 +64,7 @@ import {
64
64
  takeWatchdogGiveUpCount,
65
65
  takeZombieDetection,
66
66
  transcriptActivityAgeSeconds
67
- } from "../chunk-BKO5PJZ7.js";
67
+ } from "../chunk-IHPN6AX7.js";
68
68
  import {
69
69
  FLAGS_SCHEMA_VERSION,
70
70
  KANBAN_CHECK_COMMAND,
@@ -89,6 +89,7 @@ import {
89
89
  probeComposioAccount,
90
90
  probeComposioMcpToolCall,
91
91
  probeHttpProvider,
92
+ probeMcpHttp,
92
93
  resolveAvatarEnvUrl,
93
94
  resolveChannels,
94
95
  resolveConnectivityProbe,
@@ -96,7 +97,7 @@ import {
96
97
  sumTranscriptUsageInWindow,
97
98
  worseConnectivityOutcome,
98
99
  wrapScheduledTaskPrompt
99
- } from "../chunk-3HZSMDEW.js";
100
+ } from "../chunk-SN2G4B2Z.js";
100
101
  import {
101
102
  parsePsRows,
102
103
  reapOrphanChannelMcps
@@ -1303,111 +1304,11 @@ async function runConnectivityProbes(integrations, options = {}) {
1303
1304
  return { reports, due: due.length, probed: batch.length, skipped };
1304
1305
  }
1305
1306
 
1306
- // src/lib/mcp-probe-client.ts
1307
- var MCP_ACCEPT = "application/json, text/event-stream";
1308
- var DEFAULT_TIMEOUT_MS = 1e4;
1309
- async function parseRpc(res, expectedId) {
1310
- const ct = res.headers.get("content-type") ?? "";
1311
- if (ct.includes("text/event-stream")) {
1312
- const text = await res.text();
1313
- let dataLines = [];
1314
- for (const rawLine of text.split(/\r?\n/)) {
1315
- if (rawLine.startsWith("data:")) {
1316
- dataLines.push(rawLine.slice(5).trimStart());
1317
- continue;
1318
- }
1319
- if (rawLine === "" && dataLines.length > 0) {
1320
- try {
1321
- const msg2 = JSON.parse(dataLines.join("\n"));
1322
- if (("result" in msg2 || "error" in msg2) && msg2["id"] === expectedId) return msg2;
1323
- } catch {
1324
- }
1325
- dataLines = [];
1326
- }
1327
- }
1328
- return null;
1329
- }
1330
- const msg = await res.json().catch(() => null);
1331
- if (msg && ("result" in msg || "error" in msg) && msg["id"] === expectedId) return msg;
1332
- return msg;
1333
- }
1334
- function httpStatusOutcome(status, step) {
1335
- if (status === 401 || status === 403) {
1336
- return { status: "down", message: `MCP ${step} unauthorized (${status}) \u2014 reconnect required` };
1337
- }
1338
- if (status >= 500) {
1339
- return { status: "transient_error", message: `MCP ${step} returned ${status}` };
1340
- }
1341
- return { status: "down", message: `MCP ${step} returned ${status}` };
1342
- }
1343
- async function probeMcpHttp(config2, fetchImpl = fetch) {
1344
- const timeoutMs = config2.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1345
- const baseHeaders = {
1346
- ...config2.headers ?? {},
1347
- "Content-Type": "application/json",
1348
- Accept: MCP_ACCEPT
1349
- };
1350
- try {
1351
- const initRes = await fetchImpl(config2.url, {
1352
- method: "POST",
1353
- headers: baseHeaders,
1354
- body: JSON.stringify({
1355
- jsonrpc: "2.0",
1356
- id: 1,
1357
- method: "initialize",
1358
- params: {
1359
- protocolVersion: "2025-03-26",
1360
- capabilities: {},
1361
- clientInfo: { name: "augmented-connectivity-probe", version: "1.0.0" }
1362
- }
1363
- }),
1364
- signal: AbortSignal.timeout(timeoutMs)
1365
- });
1366
- if (!initRes.ok) return httpStatusOutcome(initRes.status, "initialize");
1367
- const sessionId = initRes.headers.get("mcp-session-id");
1368
- await parseRpc(initRes, 1);
1369
- const sessionHeaders = { ...baseHeaders, ...sessionId ? { "Mcp-Session-Id": sessionId } : {} };
1370
- const initializedRes = await fetchImpl(config2.url, {
1371
- method: "POST",
1372
- headers: sessionHeaders,
1373
- body: JSON.stringify({ jsonrpc: "2.0", method: "notifications/initialized" }),
1374
- signal: AbortSignal.timeout(5e3)
1375
- });
1376
- if (!initializedRes.ok) return httpStatusOutcome(initializedRes.status, "initialized");
1377
- await initializedRes.text().catch(() => "");
1378
- const listRes = await fetchImpl(config2.url, {
1379
- method: "POST",
1380
- headers: sessionHeaders,
1381
- body: JSON.stringify({ jsonrpc: "2.0", id: 2, method: "tools/list" }),
1382
- signal: AbortSignal.timeout(timeoutMs)
1383
- });
1384
- if (!listRes.ok) return httpStatusOutcome(listRes.status, "tools/list");
1385
- const rpc = await parseRpc(listRes, 2);
1386
- if (rpc && "error" in rpc) {
1387
- const err = rpc["error"];
1388
- return { status: "down", message: `MCP tools/list error: ${err?.message ?? "unknown"}` };
1389
- }
1390
- const result = rpc?.["result"];
1391
- const toolCount = Array.isArray(result?.tools) ? result.tools.length : void 0;
1392
- return {
1393
- status: "ok",
1394
- message: toolCount !== void 0 ? `${toolCount} tools` : "reachable",
1395
- ...toolCount !== void 0 ? { details: { toolCount } } : {}
1396
- };
1397
- } catch (err) {
1398
- const isAbort = err?.name === "TimeoutError" || err?.name === "AbortError";
1399
- return {
1400
- status: "transient_error",
1401
- message: isAbort ? `MCP handshake timed out after ${timeoutMs / 1e3}s` : `MCP handshake failed: ${err.message}`
1402
- };
1403
- }
1404
- }
1405
-
1406
1307
  // src/lib/cli-probe.ts
1407
1308
  import { execFile } from "child_process";
1408
- var DEFAULT_TIMEOUT_MS2 = 8e3;
1309
+ var DEFAULT_TIMEOUT_MS = 8e3;
1409
1310
  function runCliProbe(binary, args, opts = {}) {
1410
- const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
1311
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1411
1312
  return new Promise((resolve) => {
1412
1313
  execFile(
1413
1314
  binary,
@@ -4147,6 +4048,11 @@ async function processOne(flag, opts) {
4147
4048
  const reasonSuffix = flag.source === "agent" && flag.reason ? ` reason="${flag.reason}"` : "";
4148
4049
  opts.log(`[restart-handler] Restarting tmux session for '${flag.codeName}' (source: ${flag.source})${reasonSuffix}`);
4149
4050
  opts.stopSession(flag.codeName, flag);
4051
+ if (opts.reportRestartEvent) {
4052
+ void opts.reportRestartEvent(flag).catch((err) => {
4053
+ opts.log(`[restart-handler] restart-event report failed for '${flag.codeName}': ${err.message}`);
4054
+ });
4055
+ }
4150
4056
  await sendAck(flag, opts, `\u{1F504} Restart initiated for \`${flag.codeName}\` \u2014 the replacement session is being created.`);
4151
4057
  }
4152
4058
  async function sendAck(flag, opts, text) {
@@ -5143,6 +5049,16 @@ function readMcpHttpServerConfig(projectDir, serverKey, env) {
5143
5049
  return null;
5144
5050
  }
5145
5051
  }
5052
+ function deriveMcpServerKey(input) {
5053
+ const kind = resolveConnectivityProbe({
5054
+ definitionId: input.definitionId,
5055
+ sourceType: input.sourceType,
5056
+ authType: input.authType,
5057
+ connectivityTest: input.connectivityTest ?? null
5058
+ }).kind;
5059
+ if (kind !== "mcp_tools_list" && kind !== "managed_composite") return void 0;
5060
+ return input.definitionId.replace(/[^a-z0-9]/gi, "_").toLowerCase();
5061
+ }
5146
5062
  async function runAgentConnectivityProbes(agent, integrations, projectDir) {
5147
5063
  if (integrations.length === 0) return;
5148
5064
  const probeEnv = { ...process.env };
@@ -5219,24 +5135,31 @@ async function runAgentConnectivityProbes(agent, integrations, projectDir) {
5219
5135
  };
5220
5136
  const intervalSec = Number(process.env.AGT_CONNECTIVITY_PROBE_INTERVAL_SECONDS) || 3600;
5221
5137
  const result = await runConnectivityProbes(
5222
- integrations.map((i) => ({
5223
- id: i.id,
5224
- definition_id: i.definition_id,
5225
- scope: i.scope,
5226
- auth_type: i.auth_type,
5227
- source_type: i.source_type ?? null,
5228
- credentials: i.credentials,
5229
- last_connectivity_check_at: i.last_connectivity_check_at ?? null,
5230
- // ENG-5665: for managed (Composio) + mcp_server toolkits the connectivity
5231
- // probe is an MCP `tools/list` against the agent's wired server. Derive the
5232
- // .mcp.json server key the same way the managed-toolkit writer does
5233
- // (definition_id === toolkit_id, sanitised: non-alnum '_', lowercased —
5234
- // e.g. 'composio_outlook'). The executor looks this up in .mcp.json; an
5235
- // unresolvable key degrades to transient_error, never a false 'down'.
5236
- mcp_server_key: i.source_type === "managed" || i.source_type === "mcp_server" ? i.definition_id.replace(/[^a-z0-9]/gi, "_").toLowerCase() : void 0,
5237
- // ENG-6242: forward the prescribed connectivity-test tool to the executor.
5238
- connectivity_test: i.connectivity_test ?? null
5239
- })),
5138
+ integrations.map((i) => {
5139
+ const sourceType = i.source_type ?? null;
5140
+ return {
5141
+ id: i.id,
5142
+ definition_id: i.definition_id,
5143
+ scope: i.scope,
5144
+ auth_type: i.auth_type,
5145
+ source_type: sourceType,
5146
+ credentials: i.credentials,
5147
+ last_connectivity_check_at: i.last_connectivity_check_at ?? null,
5148
+ // ENG-5665 / ENG-6396: for any integration whose probe is an MCP
5149
+ // `tools/list` against the agent's wired server (managed/Composio,
5150
+ // mcp_server, or a remote-MCP OAuth provider like granola), derive the
5151
+ // .mcp.json server key. The executor looks this up in .mcp.json; an
5152
+ // unresolvable key degrades to transient_error, never a false 'down'.
5153
+ mcp_server_key: deriveMcpServerKey({
5154
+ definitionId: i.definition_id,
5155
+ sourceType,
5156
+ authType: i.auth_type,
5157
+ connectivityTest: i.connectivity_test ?? null
5158
+ }),
5159
+ // ENG-6242: forward the prescribed connectivity-test tool to the executor.
5160
+ connectivity_test: i.connectivity_test ?? null
5161
+ };
5162
+ }),
5240
5163
  { probeDeps, intervalMs: intervalSec * 1e3 }
5241
5164
  );
5242
5165
  if (result.reports.length > 0) {
@@ -5265,6 +5188,16 @@ function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason, gate
5265
5188
  if (breakerReason) {
5266
5189
  recordRestartForBreaker(codeName, breakerReason);
5267
5190
  }
5191
+ if (breakerReason && breakerReason !== "agent-requested" && breakerReason !== "channel-restart-flag") {
5192
+ const restartAgentId = agentState.codeNameToAgentId.get(codeName);
5193
+ if (restartAgentId) {
5194
+ void api.post("/host/restart-event", {
5195
+ agent_id: restartAgentId,
5196
+ source: breakerReason,
5197
+ reason: breakerReason
5198
+ }).catch((err) => log(`[restart-event] report failed for '${codeName}': ${err.message}`));
5199
+ }
5200
+ }
5268
5201
  }
5269
5202
  function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
5270
5203
  const currentHash = projectMcpHash(codeName, projectDir);
@@ -5429,7 +5362,7 @@ var cachedMaintenanceWindow = null;
5429
5362
  var lastVersionCheckAt = 0;
5430
5363
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
5431
5364
  var lastResponsivenessProbeAt = 0;
5432
- var agtCliVersion = true ? "0.28.21" : "dev";
5365
+ var agtCliVersion = true ? "0.28.23" : "dev";
5433
5366
  function resolveBrewPath(execFileSync4) {
5434
5367
  try {
5435
5368
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -6509,6 +6442,25 @@ async function pollCycle() {
6509
6442
  } finally {
6510
6443
  clearTimeout(timer);
6511
6444
  }
6445
+ },
6446
+ // ENG-6399: report the restart to audit_log via POST /host/restart-event.
6447
+ // Maps the flag's transport `source` onto the canonical audit source: the
6448
+ // in-session self-restart (request_restart, ENG-6229) is 'agent-self-request';
6449
+ // a channel /restart (slack/telegram) is 'channel-command'. Best-effort —
6450
+ // restart-handler calls this fire-and-forget so a reporting failure never
6451
+ // blocks the restart.
6452
+ reportRestartEvent: async (flag) => {
6453
+ const agentId = agentState.codeNameToAgentId.get(flag.codeName);
6454
+ if (!agentId) {
6455
+ log(`[restart-handler] no agent_id for '${flag.codeName}' \u2014 skipping restart-event report`);
6456
+ return;
6457
+ }
6458
+ const source = flag.source === "agent" ? "agent-self-request" : flag.source === "unknown" ? "unknown" : "channel-command";
6459
+ void api.post("/host/restart-event", {
6460
+ agent_id: agentId,
6461
+ source,
6462
+ ...flag.reason ? { reason: flag.reason } : {}
6463
+ }).catch((err) => log(`[restart-event] report failed for '${flag.codeName}': ${err.message}`));
6512
6464
  }
6513
6465
  });
6514
6466
  } catch (err) {
@@ -6538,7 +6490,7 @@ async function pollCycle() {
6538
6490
  }
6539
6491
  try {
6540
6492
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
6541
- const { collectDiagnostics } = await import("../persistent-session-5BEMWOTM.js");
6493
+ const { collectDiagnostics } = await import("../persistent-session-34CY65FC.js");
6542
6494
  const diagCodeNames = [...agentState.persistentSessionAgents];
6543
6495
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
6544
6496
  let tailscaleHostname;
@@ -6632,7 +6584,7 @@ async function pollCycle() {
6632
6584
  const {
6633
6585
  collectResponsivenessProbes,
6634
6586
  getResponsivenessIntervalMs
6635
- } = await import("../responsiveness-probe-JP4HLFYU.js");
6587
+ } = await import("../responsiveness-probe-KKWPOZSX.js");
6636
6588
  const probeIntervalMs = getResponsivenessIntervalMs();
6637
6589
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
6638
6590
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -6664,7 +6616,7 @@ async function pollCycle() {
6664
6616
  collectResponsivenessProbes,
6665
6617
  livePendingInboundOldestAgeSeconds,
6666
6618
  parkPendingInbound
6667
- } = await import("../responsiveness-probe-JP4HLFYU.js");
6619
+ } = await import("../responsiveness-probe-KKWPOZSX.js");
6668
6620
  const { getProjectDir: wedgeProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
6669
6621
  const wedgeNow = /* @__PURE__ */ new Date();
6670
6622
  const liveAgents = agentState.persistentSessionAgents;
@@ -11255,7 +11207,7 @@ async function processClaudePairSessions(agents) {
11255
11207
  killPairSession,
11256
11208
  pairTmuxSession,
11257
11209
  finalizeClaudePairOnboarding
11258
- } = await import("../claude-pair-runtime-LQJ5E4IF.js");
11210
+ } = await import("../claude-pair-runtime-UKOL6GWJ.js");
11259
11211
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
11260
11212
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
11261
11213
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -12199,6 +12151,7 @@ export {
12199
12151
  claudeManagedSettingsPath,
12200
12152
  deliverScheduledCardResult,
12201
12153
  deliverScheduledTaskOutput,
12154
+ deriveMcpServerKey,
12202
12155
  deriveScheduledTaskNotify,
12203
12156
  ensureClaudeManagedSettings,
12204
12157
  extractCharterSlackPeers,