@integrity-labs/agt-cli 0.15.0 → 0.15.2

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.
@@ -4,6 +4,7 @@ import {
4
4
  appendDmFooter,
5
5
  classifyOutput,
6
6
  exchangeApiKey,
7
+ extractCommandNotFound,
7
8
  extractFrontmatter,
8
9
  getApiKey,
9
10
  getFramework,
@@ -19,7 +20,7 @@ import {
19
20
  resolveChannels,
20
21
  resolveDmTarget,
21
22
  wrapScheduledTaskPrompt
22
- } from "../chunk-WB3T6XIV.js";
23
+ } from "../chunk-IQI7XAQ6.js";
23
24
  import {
24
25
  findTaskByTemplate,
25
26
  getProjectDir,
@@ -39,7 +40,7 @@ import {
39
40
  startPersistentSession,
40
41
  stopAllSessionsAndWait,
41
42
  stopPersistentSession
42
- } from "../chunk-4CZUEGNQ.js";
43
+ } from "../chunk-IEVDKEIT.js";
43
44
 
44
45
  // src/lib/manager-worker.ts
45
46
  import { createHash } from "crypto";
@@ -1357,6 +1358,46 @@ async function ensureToolkitCli(toolkitSlug) {
1357
1358
  toolkitCliRetryAfter.set(toolkitSlug, Date.now() + TOOLKIT_INSTALL_RETRY_MS);
1358
1359
  }
1359
1360
  }
1361
+ function runAsync(cmd, args, opts) {
1362
+ return new Promise((resolve, reject) => {
1363
+ import("child_process").then(({ spawn }) => {
1364
+ const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
1365
+ let stdout = "";
1366
+ let stderr = "";
1367
+ let settled = false;
1368
+ const timer = setTimeout(() => {
1369
+ child.kill("SIGTERM");
1370
+ if (settled) return;
1371
+ settled = true;
1372
+ reject(new Error(`${cmd} ${args.join(" ")} timed out after ${opts.timeout}ms`));
1373
+ setTimeout(() => {
1374
+ try {
1375
+ child.kill("SIGKILL");
1376
+ } catch {
1377
+ }
1378
+ }, 5e3).unref();
1379
+ }, opts.timeout);
1380
+ child.stdout?.on("data", (b) => {
1381
+ stdout += b.toString();
1382
+ });
1383
+ child.stderr?.on("data", (b) => {
1384
+ stderr += b.toString();
1385
+ });
1386
+ child.on("error", (err) => {
1387
+ if (settled) return;
1388
+ settled = true;
1389
+ clearTimeout(timer);
1390
+ reject(err);
1391
+ });
1392
+ child.on("close", (code) => {
1393
+ if (settled) return;
1394
+ settled = true;
1395
+ clearTimeout(timer);
1396
+ resolve({ code: code ?? -1, stdout, stderr });
1397
+ });
1398
+ }).catch(reject);
1399
+ });
1400
+ }
1360
1401
  async function ensureFrameworkBinary(frameworkId) {
1361
1402
  if (frameworkId !== "claude-code") return;
1362
1403
  if (frameworkBinaryChecked.has(frameworkId)) return;
@@ -1371,10 +1412,9 @@ async function ensureFrameworkBinary(frameworkId) {
1371
1412
  const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
1372
1413
  const runBrew = (args, opts) => {
1373
1414
  if (isRoot) {
1374
- const sudoArgs = ["-u", "ec2-user", "-H", brewPath, ...args];
1375
- return execFileSync2("sudo", sudoArgs, { ...opts, stdio: "pipe" }).toString();
1415
+ return runAsync("sudo", ["-u", "ec2-user", "-H", brewPath, ...args], opts);
1376
1416
  }
1377
- return execFileSync2(brewPath, args, { ...opts, stdio: "pipe" }).toString();
1417
+ return runAsync(brewPath, args, opts);
1378
1418
  };
1379
1419
  let claudeExists = existsSync("/home/linuxbrew/.linuxbrew/bin/claude");
1380
1420
  if (!claudeExists) {
@@ -1387,33 +1427,41 @@ async function ensureFrameworkBinary(frameworkId) {
1387
1427
  if (!claudeExists) {
1388
1428
  log(`Claude Code binary not found \u2014 installing via Homebrew${isRoot ? " (as ec2-user via sudo)" : ""}...`);
1389
1429
  try {
1390
- runBrew(["install", "--cask", "claude-code"], { timeout: 12e4 });
1430
+ const r = await runBrew(["install", "--cask", "claude-code"], { timeout: 12e4 });
1431
+ if (r.code !== 0) {
1432
+ log(`Claude Code install failed (exit ${r.code}): ${r.stderr.trim() || r.stdout.trim()}`);
1433
+ return;
1434
+ }
1391
1435
  } catch (err) {
1392
1436
  log(`Claude Code install failed: ${err.message}`);
1393
1437
  return;
1394
1438
  }
1439
+ const brewBinDir = dirname(brewPath);
1440
+ if (!process.env.PATH?.split(":").includes(brewBinDir)) {
1441
+ process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
1442
+ }
1395
1443
  if (existsSync("/home/linuxbrew/.linuxbrew/bin/claude")) {
1396
1444
  log("Claude Code installed successfully");
1397
1445
  } else {
1398
1446
  log("Claude Code install completed but binary not found at expected path \u2014 check brew logs");
1399
1447
  }
1400
1448
  } else {
1401
- log(`Checking for Claude Code updates${isRoot ? " (as ec2-user via sudo)" : ""}...`);
1402
- try {
1403
- const output = runBrew(["upgrade", "--cask", "claude-code"], { timeout: 12e4 });
1404
- if (output.includes("already installed") || output.includes("up-to-date")) {
1405
- log("Claude Code is already up to date");
1406
- } else {
1407
- log("Claude Code upgraded successfully");
1408
- }
1409
- } catch (err) {
1410
- const msg = err.message;
1411
- if (msg.includes("already installed") || msg.includes("up-to-date") || msg.includes("not upgraded")) {
1449
+ log(`Checking for Claude Code updates in background${isRoot ? " (as ec2-user via sudo)" : ""}...`);
1450
+ runBrew(["upgrade", "--cask", "claude-code"], { timeout: 12e4 }).then((r) => {
1451
+ const combined = `${r.stdout}
1452
+ ${r.stderr}`;
1453
+ if (r.code === 0) {
1454
+ if (combined.includes("already installed") || combined.includes("up-to-date")) {
1455
+ log("Claude Code is already up to date");
1456
+ } else {
1457
+ log("Claude Code upgraded successfully (will apply on next session start)");
1458
+ }
1459
+ } else if (combined.includes("already installed") || combined.includes("up-to-date") || combined.includes("not upgraded")) {
1412
1460
  log("Claude Code is already up to date");
1413
1461
  } else {
1414
- log(`Claude Code upgrade failed: ${msg}`);
1462
+ log(`Claude Code upgrade failed (exit ${r.code}): ${r.stderr.trim() || r.stdout.trim()}`);
1415
1463
  }
1416
- }
1464
+ }).catch((err) => log(`Claude Code upgrade failed: ${err.message}`));
1417
1465
  }
1418
1466
  agentRuntimeAuthenticated = await checkClaudeAuth();
1419
1467
  }
@@ -1944,7 +1992,7 @@ async function pollCycle() {
1944
1992
  }
1945
1993
  try {
1946
1994
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
1947
- const { collectDiagnostics } = await import("../persistent-session-GBQ3VQK3.js");
1995
+ const { collectDiagnostics } = await import("../persistent-session-ALP5DGFI.js");
1948
1996
  const diagCodeNames = [...persistentSessionAgents];
1949
1997
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
1950
1998
  let tailscaleHostname;
@@ -2901,8 +2949,10 @@ async function processAgent(agent, agentStates) {
2901
2949
  log(`Plugin hook on_install '${hook.plugin_slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
2902
2950
  } else {
2903
2951
  const stderrHash = createHash2("sha256").update(result.stderr).digest("hex").slice(0, 12);
2952
+ const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
2953
+ const missingCmdHash = missingCmd ? createHash2("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
2904
2954
  log(
2905
- `Plugin hook on_install '${hook.plugin_slug}' exited ${result.exitCode} for '${agent.code_name}' [stderr_hash=${stderrHash} stderr_len=${result.stderr.length}]`
2955
+ `Plugin hook on_install '${hook.plugin_slug}' exited ${result.exitCode} for '${agent.code_name}' ` + (missingCmdHash ? `[missing_command_hash=${missingCmdHash}] ` : "") + `[stderr_hash=${stderrHash} stderr_len=${result.stderr.length}]`
2906
2956
  );
2907
2957
  }
2908
2958
  } catch (err) {