@integrity-labs/agt-cli 0.15.27 → 0.15.33

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
  resolveChannels,
23
23
  resolveDmTarget,
24
24
  wrapScheduledTaskPrompt
25
- } from "../chunk-4DJTQWSS.js";
25
+ } from "../chunk-6J5SG6JQ.js";
26
26
  import {
27
27
  findTaskByTemplate,
28
28
  getProjectDir,
@@ -42,11 +42,11 @@ import {
42
42
  startPersistentSession,
43
43
  stopAllSessionsAndWait,
44
44
  stopPersistentSession
45
- } from "../chunk-S3SFU5IM.js";
45
+ } from "../chunk-AFUG4KD3.js";
46
46
 
47
47
  // src/lib/manager-worker.ts
48
48
  import { createHash } from "crypto";
49
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, appendFileSync, mkdirSync as mkdirSync2, chmodSync, existsSync as existsSync2, rmSync as rmSync2, readdirSync as readdirSync2, statSync, unlinkSync, copyFileSync } from "fs";
49
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, chmodSync, existsSync as existsSync2, rmSync as rmSync2, readdirSync as readdirSync2, statSync, unlinkSync, copyFileSync } from "fs";
50
50
  import https from "https";
51
51
  import { execFileSync as syncExecFile } from "child_process";
52
52
  import { join as join3, dirname } from "path";
@@ -1435,6 +1435,7 @@ function clearAgentCaches(agentId, codeName) {
1435
1435
  var cachedFrameworkVersion = null;
1436
1436
  var lastVersionCheckAt = 0;
1437
1437
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
1438
+ var agtCliVersion = true ? "0.15.33" : "dev";
1438
1439
  function resolveBrewPath(execFileSync2) {
1439
1440
  try {
1440
1441
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -1447,7 +1448,21 @@ function resolveBrewPath(execFileSync2) {
1447
1448
  }
1448
1449
  var toolkitCliEnsured = /* @__PURE__ */ new Set();
1449
1450
  var toolkitCliRetryAfter = /* @__PURE__ */ new Map();
1451
+ var toolkitCliFailureCount = /* @__PURE__ */ new Map();
1450
1452
  var TOOLKIT_INSTALL_RETRY_MS = 5 * 6e4;
1453
+ var TOOLKIT_INSTALL_MAX_FAILURES = 3;
1454
+ function recordToolkitFailure(toolkitSlug, reason) {
1455
+ const count = (toolkitCliFailureCount.get(toolkitSlug) ?? 0) + 1;
1456
+ toolkitCliFailureCount.set(toolkitSlug, count);
1457
+ if (count >= TOOLKIT_INSTALL_MAX_FAILURES) {
1458
+ log(`[toolkit-install] ${toolkitSlug}: ${reason} (giving up after ${count} attempts \u2014 restart the manager to retry)`);
1459
+ toolkitCliEnsured.add(toolkitSlug);
1460
+ toolkitCliRetryAfter.delete(toolkitSlug);
1461
+ } else {
1462
+ log(`[toolkit-install] ${toolkitSlug}: ${reason} (attempt ${count}/${TOOLKIT_INSTALL_MAX_FAILURES}, retrying in ${TOOLKIT_INSTALL_RETRY_MS / 6e4}m)`);
1463
+ toolkitCliRetryAfter.set(toolkitSlug, Date.now() + TOOLKIT_INSTALL_RETRY_MS);
1464
+ }
1465
+ }
1451
1466
  async function ensureToolkitCli(toolkitSlug) {
1452
1467
  if (toolkitCliEnsured.has(toolkitSlug)) return;
1453
1468
  const retryAfter = toolkitCliRetryAfter.get(toolkitSlug) ?? 0;
@@ -1464,6 +1479,7 @@ async function ensureToolkitCli(toolkitSlug) {
1464
1479
  execFileSync2("which", [binary], { timeout: 5e3, stdio: "pipe" });
1465
1480
  toolkitCliEnsured.add(toolkitSlug);
1466
1481
  toolkitCliRetryAfter.delete(toolkitSlug);
1482
+ toolkitCliFailureCount.delete(toolkitSlug);
1467
1483
  return;
1468
1484
  } catch {
1469
1485
  }
@@ -1498,7 +1514,7 @@ async function ensureToolkitCli(toolkitSlug) {
1498
1514
  const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
1499
1515
  log(`[toolkit-install] ${toolkitSlug}: installing via brew (${pkg})\u2026`);
1500
1516
  if (isRoot) {
1501
- execFileSync2("sudo", ["-u", "ec2-user", "-H", brewPath, "install", pkg], { timeout: 18e4, stdio: "pipe" });
1517
+ execFileSync2("sudo", ["-u", "ec2-user", "-H", brewPath, "install", pkg], { timeout: 18e4, stdio: "pipe", cwd: "/tmp" });
1502
1518
  } else {
1503
1519
  execFileSync2(brewPath, ["install", pkg], { timeout: 18e4, stdio: "pipe" });
1504
1520
  }
@@ -1513,8 +1529,7 @@ async function ensureToolkitCli(toolkitSlug) {
1513
1529
  }
1514
1530
  } catch (err) {
1515
1531
  const msg = err.message.slice(0, 200);
1516
- log(`[toolkit-install] ${toolkitSlug}: installer=${resolvedInstaller} failed \u2014 ${msg} (retrying in ${TOOLKIT_INSTALL_RETRY_MS / 6e4}m)`);
1517
- toolkitCliRetryAfter.set(toolkitSlug, Date.now() + TOOLKIT_INSTALL_RETRY_MS);
1532
+ recordToolkitFailure(toolkitSlug, `installer=${resolvedInstaller} failed \u2014 ${msg}`);
1518
1533
  return;
1519
1534
  }
1520
1535
  if (brewBinDir && !process.env.PATH?.split(":").includes(brewBinDir)) {
@@ -1525,15 +1540,15 @@ async function ensureToolkitCli(toolkitSlug) {
1525
1540
  log(`[toolkit-install] ${toolkitSlug}: installed \u2014 ${binary} now on PATH`);
1526
1541
  toolkitCliEnsured.add(toolkitSlug);
1527
1542
  toolkitCliRetryAfter.delete(toolkitSlug);
1543
+ toolkitCliFailureCount.delete(toolkitSlug);
1528
1544
  } catch {
1529
- log(`[toolkit-install] ${toolkitSlug}: installer=${resolvedInstaller} completed but ${binary} still not on PATH (retrying in ${TOOLKIT_INSTALL_RETRY_MS / 6e4}m)`);
1530
- toolkitCliRetryAfter.set(toolkitSlug, Date.now() + TOOLKIT_INSTALL_RETRY_MS);
1545
+ recordToolkitFailure(toolkitSlug, `installer=${resolvedInstaller} completed but ${binary} still not on PATH`);
1531
1546
  }
1532
1547
  }
1533
1548
  function runAsync(cmd, args, opts) {
1534
1549
  return new Promise((resolve, reject) => {
1535
1550
  import("child_process").then(({ spawn }) => {
1536
- const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
1551
+ const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"], cwd: opts.cwd });
1537
1552
  let stdout = "";
1538
1553
  let stderr = "";
1539
1554
  let settled = false;
@@ -1584,7 +1599,7 @@ async function ensureFrameworkBinary(frameworkId) {
1584
1599
  const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
1585
1600
  const runBrew = (args, opts) => {
1586
1601
  if (isRoot) {
1587
- return runAsync("sudo", ["-u", "ec2-user", "-H", brewPath, ...args], opts);
1602
+ return runAsync("sudo", ["-u", "ec2-user", "-H", brewPath, ...args], { ...opts, cwd: "/tmp" });
1588
1603
  }
1589
1604
  return runAsync(brewPath, args, opts);
1590
1605
  };
@@ -1812,19 +1827,15 @@ function log(msg) {
1812
1827
  const safeMsg = redactForDiskLog(msg);
1813
1828
  process.stderr.write(`[manager-worker ${ts}] ${safeMsg}
1814
1829
  `);
1815
- try {
1816
- if (!managerLogPath) {
1830
+ if (!managerLogPath) {
1831
+ try {
1817
1832
  managerLogPath = join3(homedir3(), ".augmented", "manager.log");
1818
1833
  mkdirSync2(dirname(managerLogPath), { recursive: true });
1819
- if (!existsSync2(managerLogPath)) {
1820
- appendFileSync(managerLogPath, "", { mode: 384 });
1821
- } else {
1834
+ if (existsSync2(managerLogPath)) {
1822
1835
  chmodSync(managerLogPath, 384);
1823
1836
  }
1837
+ } catch {
1824
1838
  }
1825
- appendFileSync(managerLogPath, `[manager-worker ${ts}] ${safeMsg}
1826
- `);
1827
- } catch {
1828
1839
  }
1829
1840
  }
1830
1841
  function sha256(content) {
@@ -2206,7 +2217,7 @@ async function pollCycle() {
2206
2217
  }
2207
2218
  try {
2208
2219
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
2209
- const { collectDiagnostics } = await import("../persistent-session-Q4X2KRS6.js");
2220
+ const { collectDiagnostics } = await import("../persistent-session-VRS3MFQ3.js");
2210
2221
  const diagCodeNames = [...persistentSessionAgents];
2211
2222
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
2212
2223
  let tailscaleHostname;
@@ -2242,6 +2253,7 @@ async function pollCycle() {
2242
2253
  await api.post("/host/heartbeat", {
2243
2254
  host_id: hostId,
2244
2255
  framework_version: cachedFrameworkVersion ?? void 0,
2256
+ agt_version: agtCliVersion,
2245
2257
  host_security: detectHostSecurity() ?? void 0,
2246
2258
  agent_runtime_authenticated: agentRuntimeAuthenticated,
2247
2259
  agent_diagnostics: agentDiagnostics,
@@ -5244,19 +5256,32 @@ async function reportDeliveryStatus(agentId, taskId, payload) {
5244
5256
  log(`[delivery] Failed to report delivery status for ${agentId}/${taskId}: ${err.message}`);
5245
5257
  }
5246
5258
  }
5259
+ var spawnedPairIds = /* @__PURE__ */ new Set();
5247
5260
  async function processClaudePairSessions(agents) {
5248
- if (agents.length === 0) return;
5261
+ if (agents.length === 0 && spawnedPairIds.size === 0) return;
5249
5262
  const agentIds = agents.map((a) => a.agentId);
5250
5263
  const codeNameByAgentId = new Map(agents.map((a) => [a.agentId, a.codeName]));
5251
- const pendingResp = await api.post("/host/claude-pair/pending", { agent_ids: agentIds });
5252
- if (!pendingResp.pending || pendingResp.pending.length === 0) return;
5264
+ const pendingResp = await api.post("/host/claude-pair/pending", {
5265
+ agent_ids: agentIds,
5266
+ spawned_pair_ids: Array.from(spawnedPairIds)
5267
+ });
5253
5268
  const {
5254
5269
  startClaudePair,
5255
5270
  submitClaudePairCode,
5256
5271
  spawnPairSession,
5257
5272
  killPairSession,
5258
5273
  pairTmuxSession
5259
- } = await import("../claude-pair-runtime-VXNC2VEX.js");
5274
+ } = await import("../claude-pair-runtime-5ZZVGIR3.js");
5275
+ for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
5276
+ log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
5277
+ const killed = await killPairSession(pairTmuxSession(pairId));
5278
+ if (killed) {
5279
+ spawnedPairIds.delete(pairId);
5280
+ } else {
5281
+ log(`[claude-pair] kill-session failed for pair ${pairId.slice(0, 8)} \u2014 will retry on next poll`);
5282
+ }
5283
+ }
5284
+ if (!pendingResp.pending || pendingResp.pending.length === 0) return;
5260
5285
  const TERMINAL = /* @__PURE__ */ new Set([
5261
5286
  "success",
5262
5287
  "failure",
@@ -5266,7 +5291,13 @@ async function processClaudePairSessions(agents) {
5266
5291
  async function reportAndCleanup(pairId, body) {
5267
5292
  await api.post("/host/claude-pair/result", { pair_id: pairId, ...body });
5268
5293
  if (typeof body.status === "string" && TERMINAL.has(body.status)) {
5269
- await killPairSession(pairTmuxSession(pairId));
5294
+ if (body.status === "success") {
5295
+ await new Promise((r) => setTimeout(r, 3e3));
5296
+ }
5297
+ const killed = await killPairSession(pairTmuxSession(pairId));
5298
+ if (killed) {
5299
+ spawnedPairIds.delete(pairId);
5300
+ }
5270
5301
  }
5271
5302
  }
5272
5303
  for (const session of pendingResp.pending) {
@@ -5284,6 +5315,7 @@ async function processClaudePairSessions(agents) {
5284
5315
  });
5285
5316
  continue;
5286
5317
  }
5318
+ spawnedPairIds.add(session.pair_id);
5287
5319
  log(`[claude-pair] dispatching /login (pair ${session.pair_id.slice(0, 8)})`);
5288
5320
  const result = await startClaudePair({ session: pairSession });
5289
5321
  if (result.kind === "url") {