@integrity-labs/agt-cli 0.8.9 → 0.9.1

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.
@@ -9,7 +9,7 @@ import {
9
9
  provisionStopHook,
10
10
  requireHost,
11
11
  resolveChannels
12
- } from "../chunk-55TMBRXT.js";
12
+ } from "../chunk-AMB6FJLZ.js";
13
13
  import {
14
14
  findTaskByTemplate,
15
15
  getProjectDir,
@@ -18,46 +18,24 @@ import {
18
18
  markTaskFired,
19
19
  syncTasksToScheduler
20
20
  } from "../chunk-2TSCVXHE.js";
21
+ import {
22
+ getProjectDir as getProjectDir2,
23
+ injectMessage,
24
+ isSessionHealthy,
25
+ resetRestartCount,
26
+ sanitizeMcpJson,
27
+ startPersistentSession,
28
+ stopAllSessionsAndWait,
29
+ stopPersistentSession
30
+ } from "../chunk-HTBIKZKS.js";
21
31
 
22
32
  // src/lib/manager-worker.ts
23
33
  import { createHash } from "crypto";
24
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync2, rmSync, readdirSync, statSync, unlinkSync } from "fs";
34
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync, readdirSync, statSync, unlinkSync, copyFileSync } from "fs";
25
35
  import https from "https";
26
- import { join as join2 } from "path";
27
-
28
- // src/lib/mcp-sanitize.ts
29
- import { readFileSync, writeFileSync } from "fs";
30
- function sanitizeMcpJson(mcpConfigPath, apiHost) {
31
- try {
32
- const mcpRaw = JSON.parse(readFileSync(mcpConfigPath, "utf-8"));
33
- const servers = mcpRaw.mcpServers;
34
- if (!servers) return false;
35
- let changed = false;
36
- for (const [key, val] of Object.entries(servers)) {
37
- if (typeof val?.url !== "string") continue;
38
- if (val.url.startsWith("/")) {
39
- if (apiHost) {
40
- val.url = `${apiHost}${val.url}`;
41
- changed = true;
42
- } else {
43
- delete servers[key];
44
- changed = true;
45
- continue;
46
- }
47
- }
48
- const url = val.url;
49
- delete val.url;
50
- delete val.type;
51
- val.command = "npx";
52
- val.args = ["-y", "mcp-remote", url, "--allow-http"];
53
- changed = true;
54
- }
55
- if (changed) writeFileSync(mcpConfigPath, JSON.stringify(mcpRaw, null, 2));
56
- return changed;
57
- } catch {
58
- return false;
59
- }
60
- }
36
+ import { join, dirname } from "path";
37
+ import { homedir } from "os";
38
+ import { fileURLToPath } from "url";
61
39
 
62
40
  // src/lib/gateway-client.ts
63
41
  import { EventEmitter } from "events";
@@ -328,345 +306,6 @@ var GatewayClientPool = class extends EventEmitter {
328
306
  }
329
307
  };
330
308
 
331
- // src/lib/persistent-session.ts
332
- import { spawn, execSync, execFileSync } from "child_process";
333
- import { join, dirname } from "path";
334
- import { homedir } from "os";
335
- import { existsSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync } from "fs";
336
- import { fileURLToPath } from "url";
337
- function collectMcpServerNames(mcpConfigPath, channelsConfigPath) {
338
- const names = [];
339
- for (const path of [mcpConfigPath, channelsConfigPath]) {
340
- if (!existsSync(path)) continue;
341
- try {
342
- const data = JSON.parse(readFileSync2(path, "utf-8"));
343
- const servers = data.mcpServers;
344
- if (servers) names.push(...Object.keys(servers));
345
- } catch {
346
- }
347
- }
348
- return names;
349
- }
350
- var _acpxBin = null;
351
- function getAcpxBin() {
352
- if (_acpxBin) return _acpxBin;
353
- const moduleDir = dirname(fileURLToPath(import.meta.url));
354
- let dir = moduleDir;
355
- for (let i = 0; i < 6; i++) {
356
- const candidate = join(dir, "node_modules", ".bin", "acpx");
357
- if (existsSync(candidate)) {
358
- _acpxBin = candidate;
359
- return _acpxBin;
360
- }
361
- const parent = dirname(dir);
362
- if (parent === dir) break;
363
- dir = parent;
364
- }
365
- try {
366
- execSync("which acpx", { stdio: "ignore" });
367
- _acpxBin = "acpx";
368
- return _acpxBin;
369
- } catch {
370
- return "";
371
- }
372
- }
373
- var sessions = /* @__PURE__ */ new Map();
374
- function startPersistentSession(config2) {
375
- const existing = sessions.get(config2.codeName);
376
- if (existing && existing.status === "running") {
377
- return existing;
378
- }
379
- const restartCount = existing?.restartCount ?? 0;
380
- if (existing?.status === "crashed" && existing.startedAt) {
381
- const backoffMs = Math.min(5e3 * Math.pow(2, restartCount), 6e4);
382
- if (Date.now() - existing.startedAt < backoffMs) {
383
- return existing;
384
- }
385
- }
386
- const session = {
387
- codeName: config2.codeName,
388
- startedAt: null,
389
- restartCount,
390
- status: "starting"
391
- };
392
- sessions.set(config2.codeName, session);
393
- spawnSession(config2, session);
394
- return session;
395
- }
396
- function spawnSession(config2, session) {
397
- const { codeName, projectDir, mcpConfigPath, claudeMdPath, channels, devChannels, apiHost, log: log2 } = config2;
398
- const tmuxSession = `agt-${codeName}`;
399
- log2(`[persistent-session] Starting tmux session '${tmuxSession}' for '${codeName}'`);
400
- try {
401
- sanitizeMcpJson(mcpConfigPath, apiHost);
402
- writeAcpxConfig(config2);
403
- try {
404
- execSync(`tmux kill-session -t ${tmuxSession} 2>/dev/null`, { stdio: "ignore" });
405
- } catch {
406
- }
407
- const args = [];
408
- if (channels.length > 0) args.push("--channels", ...channels);
409
- if (devChannels.length > 0) args.push("--dangerously-load-development-channels", ...devChannels);
410
- args.push("--mcp-config", mcpConfigPath);
411
- const channelsConfigPath = join(projectDir, ".mcp-channels.json");
412
- if (existsSync(channelsConfigPath)) args.push("--mcp-config", channelsConfigPath);
413
- if (existsSync(claudeMdPath)) args.push("--system-prompt-file", claudeMdPath);
414
- args.push("--allow-dangerously-skip-permissions");
415
- args.push("--dangerously-skip-permissions");
416
- args.push("--strict-mcp-config");
417
- args.push("--name", tmuxSession);
418
- const mcpServerNames = collectMcpServerNames(mcpConfigPath, channelsConfigPath);
419
- const mcpPatterns = mcpServerNames.map((name) => `mcp__${name.replace(/-/g, "_")}__*`);
420
- const allowedTools = [
421
- ...mcpPatterns,
422
- "Bash",
423
- "Read",
424
- "Write",
425
- "Edit",
426
- "Grep",
427
- "Glob",
428
- "Agent",
429
- "Skill"
430
- ].join(",");
431
- args.push("--allowedTools", allowedTools);
432
- let envPrefix = "";
433
- const envIntegrationsPath = join(projectDir, ".env.integrations");
434
- if (existsSync(envIntegrationsPath)) {
435
- try {
436
- const envContent = readFileSync2(envIntegrationsPath, "utf-8");
437
- const envVars = envContent.split("\n").filter((line) => line && !line.startsWith("#") && line.includes("=")).map((line) => {
438
- const eqIdx = line.indexOf("=");
439
- const key = line.slice(0, eqIdx);
440
- const value = line.slice(eqIdx + 1);
441
- return `${key}=${JSON.stringify(value)}`;
442
- }).join(" ");
443
- if (envVars) envPrefix = `${envVars} `;
444
- } catch {
445
- }
446
- }
447
- const initPrompt = "You are now online. Wait for messages from your channels (Telegram, Slack) and respond to them. Use your kanban tools to track work.";
448
- const claudeCmd = `${envPrefix}claude ${JSON.stringify(initPrompt)} ${args.map((a) => a.includes(" ") || a.includes("*") ? JSON.stringify(a) : a).join(" ")}`;
449
- const child = spawn("tmux", [
450
- "new-session",
451
- "-d",
452
- "-s",
453
- tmuxSession,
454
- "-c",
455
- projectDir,
456
- claudeCmd
457
- ], {
458
- cwd: projectDir,
459
- stdio: ["ignore", "pipe", "pipe"],
460
- env: process.env
461
- });
462
- child.on("close", (code) => {
463
- if (code !== 0) {
464
- log2(`[persistent-session] Failed to create tmux session for '${codeName}' (exit ${code})`);
465
- session.status = "crashed";
466
- session.startedAt = Date.now();
467
- session.restartCount++;
468
- return;
469
- }
470
- log2(`[persistent-session] tmux session '${tmuxSession}' created for '${codeName}'`);
471
- acceptDialogs(tmuxSession, codeName, log2).catch(() => {
472
- });
473
- });
474
- child.on("error", (err) => {
475
- log2(`[persistent-session] Failed to start tmux for '${codeName}': ${err.message}`);
476
- session.status = "crashed";
477
- session.startedAt = Date.now();
478
- session.restartCount++;
479
- });
480
- session.startedAt = Date.now();
481
- session.status = "running";
482
- session.restartCount = 0;
483
- } catch (err) {
484
- log2(`[persistent-session] Failed to start session for '${codeName}': ${err.message}`);
485
- session.status = "crashed";
486
- session.startedAt = Date.now();
487
- session.restartCount++;
488
- }
489
- }
490
- async function acceptDialogs(tmuxSession, codeName, log2) {
491
- for (let i = 0; i < 15; i++) {
492
- await new Promise((r) => setTimeout(r, 2e3));
493
- try {
494
- const screen = execSync(`tmux capture-pane -t ${tmuxSession} -p 2>/dev/null`, { encoding: "utf-8" });
495
- if (screen.includes("Yes, I trust this folder")) {
496
- execSync(`tmux send-keys -t ${tmuxSession} Enter`, { stdio: "ignore" });
497
- log2(`[persistent-session] Auto-accepted workspace trust for '${codeName}'`);
498
- continue;
499
- }
500
- if (screen.includes("I am using this for local development")) {
501
- execSync(`tmux send-keys -t ${tmuxSession} Enter`, { stdio: "ignore" });
502
- log2(`[persistent-session] Auto-accepted dev channels for '${codeName}'`);
503
- continue;
504
- }
505
- if (screen.includes("Enter to confirm") && screen.includes("MCP")) {
506
- execSync(`tmux send-keys -t ${tmuxSession} Enter`, { stdio: "ignore" });
507
- log2(`[persistent-session] Auto-accepted MCP servers for '${codeName}'`);
508
- continue;
509
- }
510
- if (screen.includes("Yes, I accept") && screen.includes("Bypass Permissions")) {
511
- execSync(`tmux send-keys -t ${tmuxSession} 2`, { stdio: "ignore" });
512
- await new Promise((r) => setTimeout(r, 300));
513
- execSync(`tmux send-keys -t ${tmuxSession} Enter`, { stdio: "ignore" });
514
- log2(`[persistent-session] Auto-accepted bypass permissions for '${codeName}'`);
515
- continue;
516
- }
517
- if (screen.includes("\u276F") && !screen.includes("Enter to confirm")) {
518
- log2(`[persistent-session] Session ready for '${codeName}' \u2014 no more dialogs`);
519
- break;
520
- }
521
- } catch {
522
- break;
523
- }
524
- }
525
- }
526
- async function injectMessage(codeName, type, content, meta, log2) {
527
- const _log = log2 ?? ((_) => {
528
- });
529
- const session = sessions.get(codeName);
530
- if (!session || session.status !== "running") {
531
- _log(`[inject] SKIP '${codeName}' \u2014 session ${session ? `status=${session.status}` : "not found in Map"}`);
532
- return false;
533
- }
534
- const prefix = meta?.task_name ? `[Task: ${meta.task_name}] ` : "";
535
- const text = prefix + content;
536
- const projectDir = getProjectDir2(codeName);
537
- const acpx = getAcpxBin();
538
- if (acpx) {
539
- try {
540
- const tmpDir = join(projectDir, ".claude");
541
- mkdirSync(tmpDir, { recursive: true });
542
- const tmpFile = join(tmpDir, ".agt-inject-prompt.txt");
543
- writeFileSync2(tmpFile, text);
544
- _log(`[inject] acpx exec (fire-and-forget): cwd=${projectDir}, file=${tmpFile}`);
545
- const child = spawn(acpx, ["claude", "exec", "-f", tmpFile], {
546
- cwd: projectDir,
547
- stdio: "ignore",
548
- detached: true
549
- });
550
- child.on("error", (err) => {
551
- _log(`[inject] acpx spawn error for '${codeName}': ${err.message}`);
552
- });
553
- child.unref();
554
- return true;
555
- } catch (err) {
556
- _log(`[inject] acpx exec failed for '${codeName}': ${err.message}`);
557
- }
558
- } else {
559
- _log(`[inject] acpx binary not found \u2014 falling back to tmux send-keys`);
560
- }
561
- try {
562
- execFileSync("tmux", ["send-keys", "-t", `agt-${codeName}`, text, "Enter"], { stdio: "ignore" });
563
- _log(`[inject] tmux send-keys sent for '${codeName}' \u2014 unverified (returning false)`);
564
- return false;
565
- } catch (err) {
566
- _log(`[inject] tmux send-keys failed for '${codeName}': ${err.message}`);
567
- return false;
568
- }
569
- }
570
- function stopPersistentSession(codeName, log2) {
571
- const session = sessions.get(codeName);
572
- if (!session) return;
573
- log2(`[persistent-session] Stopping session for '${codeName}'`);
574
- session.status = "stopped";
575
- try {
576
- execSync(`tmux kill-session -t agt-${codeName} 2>/dev/null`, { stdio: "ignore" });
577
- } catch {
578
- }
579
- try {
580
- const acpx = getAcpxBin();
581
- if (acpx) {
582
- execFileSync(acpx, ["claude", "sessions", "close", `agt-${codeName}`], {
583
- cwd: getProjectDir2(codeName),
584
- timeout: 5e3,
585
- stdio: "ignore"
586
- });
587
- }
588
- } catch {
589
- }
590
- sessions.delete(codeName);
591
- }
592
- function isSessionHealthy(codeName) {
593
- const tmuxSession = `agt-${codeName}`;
594
- try {
595
- execSync(`tmux has-session -t ${tmuxSession} 2>/dev/null`, { stdio: "ignore" });
596
- } catch {
597
- const session2 = sessions.get(codeName);
598
- if (session2 && session2.status === "running") {
599
- session2.status = "crashed";
600
- }
601
- return false;
602
- }
603
- if (!sessions.has(codeName)) {
604
- sessions.set(codeName, {
605
- codeName,
606
- startedAt: Date.now(),
607
- restartCount: 0,
608
- status: "running"
609
- });
610
- }
611
- const session = sessions.get(codeName);
612
- if (session.status !== "running") {
613
- session.status = "running";
614
- }
615
- return true;
616
- }
617
- function resetRestartCount(codeName) {
618
- const session = sessions.get(codeName);
619
- if (session) session.restartCount = 0;
620
- }
621
- async function stopAllSessionsAndWait(log2, opts) {
622
- const codeNames = [...sessions.keys()];
623
- if (codeNames.length === 0) return;
624
- for (const codeName of codeNames) {
625
- stopPersistentSession(codeName, log2);
626
- }
627
- await new Promise((resolve) => setTimeout(resolve, Math.min(opts.timeoutMs, 2e3)));
628
- }
629
- function getProjectDir2(codeName) {
630
- return join(homedir(), ".augmented", codeName, "project");
631
- }
632
- function writeAcpxConfig(config2) {
633
- const { projectDir, mcpConfigPath, claudeMdPath, channels, devChannels } = config2;
634
- const claudeArgs = [];
635
- if (channels.length > 0) claudeArgs.push("--channels", ...channels);
636
- if (devChannels.length > 0) claudeArgs.push("--dangerously-load-development-channels", ...devChannels);
637
- claudeArgs.push("--mcp-config", mcpConfigPath);
638
- const channelsConfigPath = join(projectDir, ".mcp-channels.json");
639
- if (existsSync(channelsConfigPath)) claudeArgs.push("--mcp-config", channelsConfigPath);
640
- if (existsSync(claudeMdPath)) claudeArgs.push("--system-prompt-file", claudeMdPath);
641
- claudeArgs.push("--allow-dangerously-skip-permissions");
642
- claudeArgs.push("--dangerously-skip-permissions");
643
- claudeArgs.push("--strict-mcp-config");
644
- const mcpServerNames2 = collectMcpServerNames(mcpConfigPath, channelsConfigPath);
645
- const mcpPatterns2 = mcpServerNames2.map((name) => `mcp__${name.replace(/-/g, "_")}__*`);
646
- const allowedTools2 = [...mcpPatterns2, "Bash", "Read", "Write", "Edit", "Grep", "Glob", "Agent", "Skill"].join(",");
647
- claudeArgs.push("--allowedTools", allowedTools2);
648
- const acpCmd = `npx -y @agentclientprotocol/claude-agent-acp ${claudeArgs.map((a) => a.includes(" ") || a.includes("*") ? JSON.stringify(a) : a).join(" ")}`;
649
- const envIntegrationsPath = join(projectDir, ".env.integrations");
650
- const wrapperPath = join(projectDir, ".claude", "acpx-agent.sh");
651
- const wrapperLines = ["#!/usr/bin/env bash"];
652
- if (existsSync(envIntegrationsPath)) {
653
- wrapperLines.push(`set -a`, `source ${JSON.stringify(envIntegrationsPath)}`, `set +a`);
654
- }
655
- wrapperLines.push(`exec ${acpCmd}`);
656
- mkdirSync(join(projectDir, ".claude"), { recursive: true });
657
- writeFileSync2(wrapperPath, wrapperLines.join("\n") + "\n", { mode: 493 });
658
- const acpxConfig = {
659
- defaultAgent: "claude",
660
- defaultPermissions: "approve-all",
661
- agents: {
662
- claude: {
663
- command: wrapperPath
664
- }
665
- }
666
- };
667
- writeFileSync2(join(projectDir, ".acpxrc.json"), JSON.stringify(acpxConfig, null, 2));
668
- }
669
-
670
309
  // src/lib/realtime-chat.ts
671
310
  import { createClient } from "@supabase/supabase-js";
672
311
  var client = null;
@@ -909,8 +548,8 @@ function stopRealtimeChat() {
909
548
  var GATEWAY_PORT_BASE = 18800;
910
549
  var GATEWAY_PORT_STEP = 10;
911
550
  var GATEWAY_PORT_MAX = 18899;
912
- var AUGMENTED_DIR = join2(process.env["HOME"] ?? "/tmp", ".augmented");
913
- var GATEWAY_PORTS_FILE = join2(AUGMENTED_DIR, "gateway-ports.json");
551
+ var AUGMENTED_DIR = join(process.env["HOME"] ?? "/tmp", ".augmented");
552
+ var GATEWAY_PORTS_FILE = join(AUGMENTED_DIR, "gateway-ports.json");
914
553
  var config = null;
915
554
  var running = false;
916
555
  var pollTimer = null;
@@ -987,24 +626,24 @@ async function ensureFrameworkBinary(frameworkId) {
987
626
  if (frameworkId !== "claude-code") return;
988
627
  if (frameworkBinaryChecked.has(frameworkId)) return;
989
628
  frameworkBinaryChecked.add(frameworkId);
990
- const { execFileSync: execFileSync2 } = await import("child_process");
629
+ const { execFileSync } = await import("child_process");
991
630
  let brewPath;
992
631
  try {
993
- brewPath = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
632
+ brewPath = execFileSync("which", ["brew"], { timeout: 5e3 }).toString().trim();
994
633
  } catch {
995
634
  log("Homebrew not found \u2014 cannot auto-install/upgrade Claude Code. Install manually: https://claude.ai/download");
996
635
  return;
997
636
  }
998
637
  let claudeExists = false;
999
638
  try {
1000
- execFileSync2("which", ["claude"], { timeout: 5e3 });
639
+ execFileSync("which", ["claude"], { timeout: 5e3 });
1001
640
  claudeExists = true;
1002
641
  } catch {
1003
642
  }
1004
643
  if (!claudeExists) {
1005
644
  log("Claude Code binary not found \u2014 installing via Homebrew...");
1006
645
  try {
1007
- execFileSync2(brewPath, ["install", "--cask", "claude-code"], {
646
+ execFileSync(brewPath, ["install", "--cask", "claude-code"], {
1008
647
  timeout: 12e4,
1009
648
  stdio: "pipe"
1010
649
  });
@@ -1013,7 +652,7 @@ async function ensureFrameworkBinary(frameworkId) {
1013
652
  return;
1014
653
  }
1015
654
  try {
1016
- execFileSync2("which", ["claude"], { timeout: 5e3 });
655
+ execFileSync("which", ["claude"], { timeout: 5e3 });
1017
656
  log("Claude Code installed successfully");
1018
657
  } catch {
1019
658
  log("Claude Code install completed but binary not found on PATH \u2014 you may need to restart your terminal");
@@ -1021,7 +660,7 @@ async function ensureFrameworkBinary(frameworkId) {
1021
660
  } else {
1022
661
  log("Checking for Claude Code updates...");
1023
662
  try {
1024
- const output = execFileSync2(brewPath, ["upgrade", "--cask", "claude-code"], {
663
+ const output = execFileSync(brewPath, ["upgrade", "--cask", "claude-code"], {
1025
664
  timeout: 12e4,
1026
665
  stdio: "pipe"
1027
666
  }).toString();
@@ -1039,7 +678,7 @@ async function ensureFrameworkBinary(frameworkId) {
1039
678
  }
1040
679
  }
1041
680
  }
1042
- agentRuntimeAuthenticated = checkClaudeAuth(execFileSync2);
681
+ agentRuntimeAuthenticated = checkClaudeAuth(execFileSync);
1043
682
  }
1044
683
  var UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
1045
684
  var selfUpdateChecked = false;
@@ -1053,21 +692,21 @@ async function checkAndUpdateCli() {
1053
692
  if (!isHomebrew && !cliPath.includes("node_modules")) return;
1054
693
  const { homedir: homedir2 } = await import("os");
1055
694
  const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
1056
- const markerPath = join2(homedir2(), ".augmented", ".last-update-check");
695
+ const markerPath = join(homedir2(), ".augmented", ".last-update-check");
1057
696
  try {
1058
697
  const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
1059
698
  if (Date.now() - lastCheck < UPDATE_CHECK_INTERVAL_MS) return;
1060
699
  } catch {
1061
700
  }
1062
- const { execFileSync: execFileSync2 } = await import("child_process");
701
+ const { execFileSync } = await import("child_process");
1063
702
  let brewPath;
1064
703
  try {
1065
- brewPath = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
704
+ brewPath = execFileSync("which", ["brew"], { timeout: 5e3 }).toString().trim();
1066
705
  } catch {
1067
706
  return;
1068
707
  }
1069
708
  try {
1070
- const outdated = execFileSync2(brewPath, ["outdated", "--json=v2"], {
709
+ const outdated = execFileSync(brewPath, ["outdated", "--json=v2"], {
1071
710
  timeout: 3e4,
1072
711
  encoding: "utf-8"
1073
712
  });
@@ -1078,7 +717,7 @@ async function checkAndUpdateCli() {
1078
717
  const latest = agtOutdated.current_version ?? "unknown";
1079
718
  log(`[self-update] agt CLI update available: ${installed} \u2192 ${latest}. Upgrading...`);
1080
719
  try {
1081
- execFileSync2(brewPath, ["upgrade", "integrity-labs/tap/agt"], {
720
+ execFileSync(brewPath, ["upgrade", "integrity-labs/tap/agt"], {
1082
721
  timeout: 12e4,
1083
722
  stdio: "pipe"
1084
723
  });
@@ -1094,9 +733,9 @@ async function checkAndUpdateCli() {
1094
733
  } catch {
1095
734
  }
1096
735
  }
1097
- function checkClaudeAuth(execFileSync2) {
736
+ function checkClaudeAuth(execFileSync) {
1098
737
  try {
1099
- const authOutput = execFileSync2("claude", ["auth", "status"], { timeout: 1e4, stdio: "pipe" }).toString().trim();
738
+ const authOutput = execFileSync("claude", ["auth", "status"], { timeout: 1e4, stdio: "pipe" }).toString().trim();
1100
739
  let loggedIn = null;
1101
740
  try {
1102
741
  const parsed = JSON.parse(authOutput);
@@ -1121,14 +760,14 @@ function checkClaudeAuth(execFileSync2) {
1121
760
  }
1122
761
  function loadGatewayPorts() {
1123
762
  try {
1124
- return JSON.parse(readFileSync3(GATEWAY_PORTS_FILE, "utf-8"));
763
+ return JSON.parse(readFileSync(GATEWAY_PORTS_FILE, "utf-8"));
1125
764
  } catch {
1126
765
  return {};
1127
766
  }
1128
767
  }
1129
768
  function saveGatewayPorts(ports) {
1130
- mkdirSync2(AUGMENTED_DIR, { recursive: true });
1131
- writeFileSync3(GATEWAY_PORTS_FILE, JSON.stringify(ports, null, 2));
769
+ mkdirSync(AUGMENTED_DIR, { recursive: true });
770
+ writeFileSync(GATEWAY_PORTS_FILE, JSON.stringify(ports, null, 2));
1132
771
  }
1133
772
  function allocatePort(codeName) {
1134
773
  const ports = loadGatewayPorts();
@@ -1150,11 +789,11 @@ function freePort(codeName) {
1150
789
  saveGatewayPorts(ports);
1151
790
  }
1152
791
  }
1153
- var STATE_FILE = join2(process.env["HOME"] ?? "/tmp", ".augmented", "manager-state.json");
792
+ var STATE_FILE = join(process.env["HOME"] ?? "/tmp", ".augmented", "manager-state.json");
1154
793
  function send(msg) {
1155
794
  if (msg.type === "state-update") {
1156
795
  try {
1157
- writeFileSync3(STATE_FILE, JSON.stringify(msg.state, null, 2));
796
+ writeFileSync(STATE_FILE, JSON.stringify(msg.state, null, 2));
1158
797
  } catch {
1159
798
  }
1160
799
  }
@@ -1176,7 +815,7 @@ function sha256(content) {
1176
815
  }
1177
816
  function hashFile(filePath) {
1178
817
  try {
1179
- const content = readFileSync3(filePath, "utf-8");
818
+ const content = readFileSync(filePath, "utf-8");
1180
819
  return sha256(content);
1181
820
  } catch {
1182
821
  return null;
@@ -1184,10 +823,10 @@ function hashFile(filePath) {
1184
823
  }
1185
824
  async function migrateToProfiles() {
1186
825
  const homeDir = process.env["HOME"] ?? "/tmp";
1187
- const sharedConfigPath = join2(homeDir, ".openclaw", "openclaw.json");
826
+ const sharedConfigPath = join(homeDir, ".openclaw", "openclaw.json");
1188
827
  let sharedConfig;
1189
828
  try {
1190
- sharedConfig = JSON.parse(readFileSync3(sharedConfigPath, "utf-8"));
829
+ sharedConfig = JSON.parse(readFileSync(sharedConfigPath, "utf-8"));
1191
830
  } catch {
1192
831
  return;
1193
832
  }
@@ -1200,19 +839,19 @@ async function migrateToProfiles() {
1200
839
  const codeName = agentEntry["id"];
1201
840
  if (!codeName) continue;
1202
841
  if (codeName === "main") continue;
1203
- const profileDir = join2(homeDir, `.openclaw-${codeName}`);
1204
- if (existsSync2(join2(profileDir, "openclaw.json"))) continue;
842
+ const profileDir = join(homeDir, `.openclaw-${codeName}`);
843
+ if (existsSync(join(profileDir, "openclaw.json"))) continue;
1205
844
  log(`Migrating agent '${codeName}' to per-agent profile`);
1206
845
  if (adapter.seedProfileConfig) {
1207
846
  adapter.seedProfileConfig(codeName);
1208
847
  }
1209
- const sharedAuthDir = join2(homeDir, ".openclaw", "agents", codeName, "agent");
1210
- const profileAuthDir = join2(profileDir, "agents", codeName, "agent");
1211
- const authFile = join2(sharedAuthDir, "auth-profiles.json");
1212
- if (existsSync2(authFile)) {
1213
- mkdirSync2(profileAuthDir, { recursive: true });
1214
- const authContent = readFileSync3(authFile, "utf-8");
1215
- writeFileSync3(join2(profileAuthDir, "auth-profiles.json"), authContent);
848
+ const sharedAuthDir = join(homeDir, ".openclaw", "agents", codeName, "agent");
849
+ const profileAuthDir = join(profileDir, "agents", codeName, "agent");
850
+ const authFile = join(sharedAuthDir, "auth-profiles.json");
851
+ if (existsSync(authFile)) {
852
+ mkdirSync(profileAuthDir, { recursive: true });
853
+ const authContent = readFileSync(authFile, "utf-8");
854
+ writeFileSync(join(profileAuthDir, "auth-profiles.json"), authContent);
1216
855
  }
1217
856
  allocatePort(codeName);
1218
857
  migrated++;
@@ -1250,7 +889,7 @@ function readGatewayToken(codeName) {
1250
889
  }
1251
890
  const homeDir = process.env["HOME"] ?? "/tmp";
1252
891
  try {
1253
- const cfg = JSON.parse(readFileSync3(join2(homeDir, `.openclaw-${codeName}`, "openclaw.json"), "utf-8"));
892
+ const cfg = JSON.parse(readFileSync(join(homeDir, `.openclaw-${codeName}`, "openclaw.json"), "utf-8"));
1254
893
  return cfg?.gateway?.auth?.token;
1255
894
  } catch {
1256
895
  return void 0;
@@ -1259,10 +898,10 @@ function readGatewayToken(codeName) {
1259
898
  var GATEWAY_HUNG_TIMEOUT_MS = 5 * 6e4;
1260
899
  function isGatewayHung(codeName) {
1261
900
  const homeDir = process.env["HOME"] ?? "/tmp";
1262
- const jobsPath = join2(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
1263
- if (!existsSync2(jobsPath)) return false;
901
+ const jobsPath = join(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
902
+ if (!existsSync(jobsPath)) return false;
1264
903
  try {
1265
- const data = JSON.parse(readFileSync3(jobsPath, "utf-8"));
904
+ const data = JSON.parse(readFileSync(jobsPath, "utf-8"));
1266
905
  const jobs = data.jobs ?? data;
1267
906
  if (!Array.isArray(jobs)) return false;
1268
907
  const now = Date.now();
@@ -1295,19 +934,19 @@ async function ensureGatewayRunning(codeName, adapter) {
1295
934
  }
1296
935
  await new Promise((r) => setTimeout(r, 2e3));
1297
936
  const homeDir = process.env["HOME"] ?? "/tmp";
1298
- const cronJobsPath = join2(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
937
+ const cronJobsPath = join(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
1299
938
  clearStaleCronRunState(cronJobsPath);
1300
939
  } else {
1301
940
  if (status.port) {
1302
941
  try {
1303
942
  const homeDir = process.env["HOME"] ?? "/tmp";
1304
- const configPath = join2(homeDir, `.openclaw-${codeName}`, "openclaw.json");
1305
- if (existsSync2(configPath)) {
1306
- const cfg = JSON.parse(readFileSync3(configPath, "utf-8"));
943
+ const configPath = join(homeDir, `.openclaw-${codeName}`, "openclaw.json");
944
+ if (existsSync(configPath)) {
945
+ const cfg = JSON.parse(readFileSync(configPath, "utf-8"));
1307
946
  if (cfg.gateway?.port !== status.port) {
1308
947
  if (!cfg.gateway) cfg.gateway = {};
1309
948
  cfg.gateway.port = status.port;
1310
- writeFileSync3(configPath, JSON.stringify(cfg, null, 2));
949
+ writeFileSync(configPath, JSON.stringify(cfg, null, 2));
1311
950
  }
1312
951
  }
1313
952
  } catch {
@@ -1327,12 +966,12 @@ async function ensureGatewayRunning(codeName, adapter) {
1327
966
  gatewaysStartedThisCycle.add(codeName);
1328
967
  try {
1329
968
  const homeDir = process.env["HOME"] ?? "/tmp";
1330
- const configPath = join2(homeDir, `.openclaw-${codeName}`, "openclaw.json");
1331
- if (existsSync2(configPath)) {
1332
- const cfg = JSON.parse(readFileSync3(configPath, "utf-8"));
969
+ const configPath = join(homeDir, `.openclaw-${codeName}`, "openclaw.json");
970
+ if (existsSync(configPath)) {
971
+ const cfg = JSON.parse(readFileSync(configPath, "utf-8"));
1333
972
  if (!cfg.gateway) cfg.gateway = {};
1334
973
  cfg.gateway.port = port;
1335
- writeFileSync3(configPath, JSON.stringify(cfg, null, 2));
974
+ writeFileSync(configPath, JSON.stringify(cfg, null, 2));
1336
975
  }
1337
976
  } catch {
1338
977
  }
@@ -1436,11 +1075,32 @@ async function pollCycle() {
1436
1075
  }
1437
1076
  try {
1438
1077
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
1078
+ const { collectDiagnostics } = await import("../persistent-session-ZCB562FN.js");
1079
+ const diagCodeNames = [...persistentSessionAgents];
1080
+ const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
1081
+ let tailscaleHostname;
1082
+ try {
1083
+ const { execSync: es } = await import("child_process");
1084
+ const tsJson = es("tailscale status --self --json 2>/dev/null", {
1085
+ encoding: "utf-8",
1086
+ timeout: 3e3
1087
+ }).trim();
1088
+ const ts = JSON.parse(tsJson);
1089
+ tailscaleHostname = ts.Self?.DNSName?.replace(/\.$/, "") || void 0;
1090
+ } catch {
1091
+ try {
1092
+ const { execSync: es } = await import("child_process");
1093
+ tailscaleHostname = es("hostname", { encoding: "utf-8", timeout: 1e3 }).trim();
1094
+ } catch {
1095
+ }
1096
+ }
1439
1097
  await api.post("/host/heartbeat", {
1440
1098
  host_id: hostId,
1441
1099
  framework_version: cachedFrameworkVersion ?? void 0,
1442
1100
  host_security: detectHostSecurity() ?? void 0,
1443
- agent_runtime_authenticated: agentRuntimeAuthenticated
1101
+ agent_runtime_authenticated: agentRuntimeAuthenticated,
1102
+ agent_diagnostics: agentDiagnostics,
1103
+ hostname: tailscaleHostname
1444
1104
  });
1445
1105
  } catch (err) {
1446
1106
  log(`Heartbeat failed: ${err.message}`);
@@ -1499,7 +1159,7 @@ async function pollCycle() {
1499
1159
  const adapter = resolveAgentFramework(prev.codeName);
1500
1160
  await stopGatewayIfRunning(prev.codeName, adapter);
1501
1161
  freePort(prev.codeName);
1502
- const agentDir = join2(config.configDir, prev.codeName, "provision");
1162
+ const agentDir = join(config.configDir, prev.codeName, "provision");
1503
1163
  await cleanupAgentFiles(prev.codeName, agentDir);
1504
1164
  clearAgentCaches(prev.agentId, prev.codeName);
1505
1165
  }
@@ -1566,7 +1226,7 @@ async function processAgent(agent, agentStates) {
1566
1226
  agentFrameworkCache.set(agent.code_name, agent.framework);
1567
1227
  }
1568
1228
  const now = (/* @__PURE__ */ new Date()).toISOString();
1569
- const agentDir = join2(config.configDir, agent.code_name, "provision");
1229
+ const agentDir = join(config.configDir, agent.code_name, "provision");
1570
1230
  const adapter = resolveAgentFramework(agent.code_name);
1571
1231
  if (agent.status === "draft" || agent.status === "paused") {
1572
1232
  log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
@@ -1717,9 +1377,9 @@ async function processAgent(agent, agentStates) {
1717
1377
  try {
1718
1378
  const artifacts = generateArtifacts(agent, refreshData, frameworkAdapter);
1719
1379
  const changedFiles = [];
1720
- mkdirSync2(agentDir, { recursive: true });
1380
+ mkdirSync(agentDir, { recursive: true });
1721
1381
  for (const artifact of artifacts) {
1722
- const filePath = join2(agentDir, artifact.relativePath);
1382
+ const filePath = join(agentDir, artifact.relativePath);
1723
1383
  const newHash = sha256(artifact.content);
1724
1384
  const existingHash = hashFile(filePath);
1725
1385
  if (newHash !== existingHash) {
@@ -1727,19 +1387,19 @@ async function processAgent(agent, agentStates) {
1727
1387
  }
1728
1388
  }
1729
1389
  if (changedFiles.length > 0) {
1730
- const isFirst = !existsSync2(join2(agentDir, "CHARTER.md"));
1390
+ const isFirst = !existsSync(join(agentDir, "CHARTER.md"));
1731
1391
  const verb = isFirst ? "Provisioning" : "Updating";
1732
1392
  const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
1733
1393
  log(`${verb} '${agent.code_name}': ${fileNames}`);
1734
1394
  for (const file of changedFiles) {
1735
- writeFileSync3(join2(agentDir, file.relativePath), file.content);
1395
+ writeFileSync(join(agentDir, file.relativePath), file.content);
1736
1396
  }
1737
1397
  lastProvisionAt = (/* @__PURE__ */ new Date()).toISOString();
1738
1398
  knownVersions.set(agent.agent_id, { charterVersion, toolsVersion });
1739
1399
  const trackedFiles = frameworkAdapter.driftTrackedFiles();
1740
1400
  const hashes = /* @__PURE__ */ new Map();
1741
1401
  for (const file of trackedFiles) {
1742
- const h = hashFile(join2(agentDir, file));
1402
+ const h = hashFile(join(agentDir, file));
1743
1403
  if (h) hashes.set(file, h);
1744
1404
  }
1745
1405
  writtenHashes.set(agent.agent_id, hashes);
@@ -1783,10 +1443,10 @@ async function processAgent(agent, agentStates) {
1783
1443
  }
1784
1444
  let lastDriftCheckAt = now;
1785
1445
  const written = writtenHashes.get(agent.agent_id);
1786
- if (written && existsSync2(agentDir)) {
1446
+ if (written && existsSync(agentDir)) {
1787
1447
  const driftedFiles = [];
1788
1448
  for (const [file, expectedHash] of written) {
1789
- const localHash = hashFile(join2(agentDir, file));
1449
+ const localHash = hashFile(join(agentDir, file));
1790
1450
  if (localHash && localHash !== expectedHash) {
1791
1451
  driftedFiles.push(file);
1792
1452
  }
@@ -1797,7 +1457,7 @@ async function processAgent(agent, agentStates) {
1797
1457
  try {
1798
1458
  const localHashes = {};
1799
1459
  for (const file of driftedFiles) {
1800
- localHashes[file] = hashFile(join2(agentDir, file));
1460
+ localHashes[file] = hashFile(join(agentDir, file));
1801
1461
  }
1802
1462
  await api.post("/host/drift", {
1803
1463
  agent_id: agent.agent_id,
@@ -1950,11 +1610,11 @@ async function processAgent(agent, agentStates) {
1950
1610
  }
1951
1611
  if (frameworkAdapter.removeMcpServer) {
1952
1612
  try {
1953
- const { readFileSync: readFileSync4 } = await import("fs");
1954
- const { join: join3 } = await import("path");
1613
+ const { readFileSync: readFileSync2 } = await import("fs");
1614
+ const { join: join2 } = await import("path");
1955
1615
  const { homedir: homedir2 } = await import("os");
1956
- const mcpPath = join3(homedir2(), ".augmented", "agents", agent.code_name, "provision", ".mcp.json");
1957
- const mcpConfig = JSON.parse(readFileSync4(mcpPath, "utf-8"));
1616
+ const mcpPath = join2(homedir2(), ".augmented", "agents", agent.code_name, "provision", ".mcp.json");
1617
+ const mcpConfig = JSON.parse(readFileSync2(mcpPath, "utf-8"));
1958
1618
  if (mcpConfig.mcpServers) {
1959
1619
  const managedPrefixes = ["composio-", "one-", "nango-", "paragon-"];
1960
1620
  for (const key of Object.keys(mcpConfig.mcpServers)) {
@@ -2007,18 +1667,18 @@ async function processAgent(agent, agentStates) {
2007
1667
  "@tobilu/qmd"
2008
1668
  ]);
2009
1669
  if (intHash !== prevIntHash) {
2010
- const { execFileSync: execFileSync2 } = await import("child_process");
1670
+ const { execFileSync } = await import("child_process");
2011
1671
  for (const tool of capData.cliTools) {
2012
1672
  if (!ALLOWED_CLI_PACKAGES.has(tool.package)) {
2013
1673
  log(`Skipping CLI tool '${tool.package}' for '${agent.code_name}' \u2014 not on the allowed packages list`);
2014
1674
  continue;
2015
1675
  }
2016
1676
  try {
2017
- execFileSync2("which", [tool.binary], { stdio: "ignore" });
1677
+ execFileSync("which", [tool.binary], { stdio: "ignore" });
2018
1678
  } catch {
2019
1679
  log(`Installing CLI tool '${tool.package}' for '${agent.code_name}'...`);
2020
1680
  try {
2021
- execFileSync2("npm", ["install", "-g", tool.package], { stdio: "ignore", timeout: 6e4 });
1681
+ execFileSync("npm", ["install", "-g", tool.package], { stdio: "ignore", timeout: 6e4 });
2022
1682
  log(`CLI tool '${tool.binary}' installed successfully`);
2023
1683
  } catch (installErr) {
2024
1684
  log(`Failed to install CLI tool '${tool.package}': ${installErr.message}`);
@@ -2026,8 +1686,8 @@ async function processAgent(agent, agentStates) {
2026
1686
  }
2027
1687
  if (tool.binary === "qmd") {
2028
1688
  try {
2029
- const agentDir2 = join2(process.env["HOME"] ?? "/tmp", ".augmented", agent.code_name);
2030
- execFileSync2("qmd", ["collection", "add", agent.code_name, "project"], {
1689
+ const agentDir2 = join(process.env["HOME"] ?? "/tmp", ".augmented", agent.code_name);
1690
+ execFileSync("qmd", ["collection", "add", agent.code_name, "project"], {
2031
1691
  stdio: "ignore",
2032
1692
  timeout: 3e4,
2033
1693
  cwd: agentDir2
@@ -2087,8 +1747,8 @@ async function processAgent(agent, agentStates) {
2087
1747
  if (agent.status === "active") {
2088
1748
  if (frameworkAdapter.installPlugin) {
2089
1749
  try {
2090
- const pluginPath = join2(process.cwd(), "packages", "openclaw-plugin-augmented", "src", "index.ts");
2091
- if (existsSync2(pluginPath)) {
1750
+ const pluginPath = join(process.cwd(), "packages", "openclaw-plugin-augmented", "src", "index.ts");
1751
+ if (existsSync(pluginPath)) {
2092
1752
  frameworkAdapter.installPlugin(agent.code_name, "augmented", pluginPath, {
2093
1753
  agtHost: requireHost(),
2094
1754
  agtApiKey: getApiKey() ?? void 0,
@@ -2203,10 +1863,10 @@ async function processAgent(agent, agentStates) {
2203
1863
  lastWorkTriggerAt.set(agent.code_name, triggerTs);
2204
1864
  if (agentFw === "openclaw" && gatewayRunning && gatewayPort) {
2205
1865
  const homeDir = process.env["HOME"] ?? "/tmp";
2206
- const jobsPath = join2(homeDir, `.openclaw-${agent.code_name}`, "cron", "jobs.json");
2207
- if (existsSync2(jobsPath)) {
1866
+ const jobsPath = join(homeDir, `.openclaw-${agent.code_name}`, "cron", "jobs.json");
1867
+ if (existsSync(jobsPath)) {
2208
1868
  try {
2209
- const jobsData = JSON.parse(readFileSync3(jobsPath, "utf-8"));
1869
+ const jobsData = JSON.parse(readFileSync(jobsPath, "utf-8"));
2210
1870
  const kanbanJob = (jobsData.jobs ?? []).find(
2211
1871
  (j) => typeof j.name === "string" && j.name.includes("kanban-work")
2212
1872
  );
@@ -2351,19 +2011,19 @@ function cleanupStaleSessions(codeName) {
2351
2011
  lastCleanupAt.set(codeName, Date.now());
2352
2012
  const homeDir = process.env["HOME"] ?? "/tmp";
2353
2013
  for (const agentDir of ["main", codeName]) {
2354
- const sessionsDir = join2(homeDir, `.openclaw-${codeName}`, "agents", agentDir, "sessions");
2014
+ const sessionsDir = join(homeDir, `.openclaw-${codeName}`, "agents", agentDir, "sessions");
2355
2015
  cleanupCronSessions(sessionsDir, CRON_SESSION_KEEP_COUNT);
2356
2016
  }
2357
- const cronRunsDir = join2(homeDir, `.openclaw-${codeName}`, "cron", "runs");
2017
+ const cronRunsDir = join(homeDir, `.openclaw-${codeName}`, "cron", "runs");
2358
2018
  cleanupOldFiles(cronRunsDir, CRON_RUN_RETENTION_DAYS, ".jsonl");
2359
- const cronJobsPath = join2(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
2019
+ const cronJobsPath = join(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
2360
2020
  clearStaleCronRunState(cronJobsPath);
2361
2021
  }
2362
2022
  function cleanupCronSessions(sessionsDir, keepCount) {
2363
- const indexPath = join2(sessionsDir, "sessions.json");
2364
- if (!existsSync2(indexPath)) return;
2023
+ const indexPath = join(sessionsDir, "sessions.json");
2024
+ if (!existsSync(indexPath)) return;
2365
2025
  try {
2366
- const raw = readFileSync3(indexPath, "utf-8");
2026
+ const raw = readFileSync(indexPath, "utf-8");
2367
2027
  const index = JSON.parse(raw);
2368
2028
  const cronRunKeys = Object.keys(index).filter((k) => k.includes(":cron:") && k.includes(":run:")).map((k) => ({
2369
2029
  key: k,
@@ -2376,9 +2036,9 @@ function cleanupCronSessions(sessionsDir, keepCount) {
2376
2036
  for (const entry of toDelete) {
2377
2037
  delete index[entry.key];
2378
2038
  if (entry.sessionId) {
2379
- const sessionFile = join2(sessionsDir, `${entry.sessionId}.jsonl`);
2039
+ const sessionFile = join(sessionsDir, `${entry.sessionId}.jsonl`);
2380
2040
  try {
2381
- if (existsSync2(sessionFile)) {
2041
+ if (existsSync(sessionFile)) {
2382
2042
  unlinkSync(sessionFile);
2383
2043
  deletedFiles++;
2384
2044
  }
@@ -2398,8 +2058,8 @@ function cleanupCronSessions(sessionsDir, keepCount) {
2398
2058
  delete index[parentKey];
2399
2059
  if (parentSessionId) {
2400
2060
  try {
2401
- const f = join2(sessionsDir, `${parentSessionId}.jsonl`);
2402
- if (existsSync2(f)) {
2061
+ const f = join(sessionsDir, `${parentSessionId}.jsonl`);
2062
+ if (existsSync(f)) {
2403
2063
  unlinkSync(f);
2404
2064
  deletedFiles++;
2405
2065
  }
@@ -2408,7 +2068,7 @@ function cleanupCronSessions(sessionsDir, keepCount) {
2408
2068
  }
2409
2069
  }
2410
2070
  }
2411
- writeFileSync3(indexPath, JSON.stringify(index));
2071
+ writeFileSync(indexPath, JSON.stringify(index));
2412
2072
  if (toDelete.length > 0) {
2413
2073
  log(`Cleaned ${toDelete.length} cron session(s) and ${deletedFiles} file(s) from ${sessionsDir}`);
2414
2074
  }
@@ -2417,9 +2077,9 @@ function cleanupCronSessions(sessionsDir, keepCount) {
2417
2077
  }
2418
2078
  var STALE_RUN_TIMEOUT_MS = 5 * 6e4;
2419
2079
  function clearStaleCronRunState(jobsPath) {
2420
- if (!existsSync2(jobsPath)) return;
2080
+ if (!existsSync(jobsPath)) return;
2421
2081
  try {
2422
- const raw = readFileSync3(jobsPath, "utf-8");
2082
+ const raw = readFileSync(jobsPath, "utf-8");
2423
2083
  const data = JSON.parse(raw);
2424
2084
  const jobs = data.jobs ?? data;
2425
2085
  if (!Array.isArray(jobs)) return;
@@ -2444,19 +2104,19 @@ function clearStaleCronRunState(jobsPath) {
2444
2104
  }
2445
2105
  }
2446
2106
  if (changed) {
2447
- writeFileSync3(jobsPath, JSON.stringify(data, null, 2));
2107
+ writeFileSync(jobsPath, JSON.stringify(data, null, 2));
2448
2108
  }
2449
2109
  } catch {
2450
2110
  }
2451
2111
  }
2452
2112
  function cleanupOldFiles(dir, maxAgeDays, ext) {
2453
- if (!existsSync2(dir)) return;
2113
+ if (!existsSync(dir)) return;
2454
2114
  const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3;
2455
2115
  let removed = 0;
2456
2116
  try {
2457
2117
  for (const f of readdirSync(dir)) {
2458
2118
  if (!f.endsWith(ext)) continue;
2459
- const fullPath = join2(dir, f);
2119
+ const fullPath = join(dir, f);
2460
2120
  try {
2461
2121
  const st = statSync(fullPath);
2462
2122
  if (st.mtimeMs < cutoff) {
@@ -2547,16 +2207,16 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
2547
2207
  }
2548
2208
  async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
2549
2209
  const projectDir = getProjectDir(codeName);
2550
- const mcpConfigPath = join2(projectDir, ".mcp.json");
2210
+ const mcpConfigPath = join(projectDir, ".mcp.json");
2551
2211
  sanitizeMcpJson(mcpConfigPath, requireHost());
2552
2212
  try {
2553
- const claudeMdPath = join2(projectDir, "CLAUDE.md");
2213
+ const claudeMdPath = join(projectDir, "CLAUDE.md");
2554
2214
  const serverNames = [];
2555
- const channelsConfigPath = join2(projectDir, ".mcp-channels.json");
2215
+ const channelsConfigPath = join(projectDir, ".mcp-channels.json");
2556
2216
  for (const p of [mcpConfigPath, channelsConfigPath]) {
2557
- if (existsSync2(p)) {
2217
+ if (existsSync(p)) {
2558
2218
  try {
2559
- const d = JSON.parse(readFileSync3(p, "utf-8"));
2219
+ const d = JSON.parse(readFileSync(p, "utf-8"));
2560
2220
  if (d.mcpServers) serverNames.push(...Object.keys(d.mcpServers));
2561
2221
  } catch {
2562
2222
  }
@@ -2573,19 +2233,17 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
2573
2233
  mcpConfigPath,
2574
2234
  "--strict-mcp-config",
2575
2235
  "--allowedTools",
2576
- allowedTools,
2577
- "--allow-dangerously-skip-permissions",
2578
- "--dangerously-skip-permissions"
2236
+ allowedTools
2579
2237
  ];
2580
- if (existsSync2(channelsConfigPath)) claudeArgs.push("--mcp-config", channelsConfigPath);
2581
- if (existsSync2(claudeMdPath)) {
2238
+ if (existsSync(channelsConfigPath)) claudeArgs.push("--mcp-config", channelsConfigPath);
2239
+ if (existsSync(claudeMdPath)) {
2582
2240
  claudeArgs.push("--system-prompt-file", claudeMdPath);
2583
2241
  }
2584
2242
  const childEnv = { ...process.env };
2585
- const envIntPath = join2(projectDir, ".env.integrations");
2586
- if (existsSync2(envIntPath)) {
2243
+ const envIntPath = join(projectDir, ".env.integrations");
2244
+ if (existsSync(envIntPath)) {
2587
2245
  try {
2588
- for (const line of readFileSync3(envIntPath, "utf-8").split("\n")) {
2246
+ for (const line of readFileSync(envIntPath, "utf-8").split("\n")) {
2589
2247
  if (!line || line.startsWith("#") || !line.includes("=")) continue;
2590
2248
  const eqIdx = line.indexOf("=");
2591
2249
  childEnv[line.slice(0, eqIdx)] = line.slice(eqIdx + 1);
@@ -2688,8 +2346,8 @@ var persistentSessionAgents = /* @__PURE__ */ new Set();
2688
2346
  async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
2689
2347
  const codeName = agent.code_name;
2690
2348
  const projectDir = getProjectDir2(codeName);
2691
- const mcpConfigPath = join2(projectDir, ".mcp.json");
2692
- const claudeMdPath = join2(projectDir, "CLAUDE.md");
2349
+ const mcpConfigPath = join(projectDir, ".mcp.json");
2350
+ const claudeMdPath = join(projectDir, "CLAUDE.md");
2693
2351
  const channelConfigs = refreshData.channel_configs;
2694
2352
  const channels = [];
2695
2353
  const devChannels = [];
@@ -2705,8 +2363,8 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
2705
2363
  }
2706
2364
  }
2707
2365
  if (!agentRuntimeAuthenticated) {
2708
- const { execFileSync: execFileSync2 } = await import("child_process");
2709
- agentRuntimeAuthenticated = checkClaudeAuth(execFileSync2);
2366
+ const { execFileSync } = await import("child_process");
2367
+ agentRuntimeAuthenticated = checkClaudeAuth(execFileSync);
2710
2368
  if (!agentRuntimeAuthenticated) {
2711
2369
  log(`[persistent-session] Skipping '${codeName}' \u2014 Claude Code not authenticated`);
2712
2370
  return;
@@ -3022,13 +2680,13 @@ async function processDirectChatMessage(agent, msg) {
3022
2680
  if (fw === "claude-code") {
3023
2681
  const { getProjectDir: ccProjectDir } = await import("../claude-scheduler-VFBZFE6U.js");
3024
2682
  const projDir = ccProjectDir(agent.codeName);
3025
- const mcpConfigPath = join2(projDir, ".mcp.json");
3026
- const channelsConfigPath = join2(projDir, ".mcp-channels.json");
2683
+ const mcpConfigPath = join(projDir, ".mcp.json");
2684
+ const channelsConfigPath = join(projDir, ".mcp-channels.json");
3027
2685
  const serverNames = [];
3028
2686
  for (const p of [mcpConfigPath, channelsConfigPath]) {
3029
- if (existsSync2(p)) {
2687
+ if (existsSync(p)) {
3030
2688
  try {
3031
- const d = JSON.parse(readFileSync3(p, "utf-8"));
2689
+ const d = JSON.parse(readFileSync(p, "utf-8"));
3032
2690
  if (d.mcpServers) serverNames.push(...Object.keys(d.mcpServers));
3033
2691
  } catch {
3034
2692
  }
@@ -3047,16 +2705,16 @@ async function processDirectChatMessage(agent, msg) {
3047
2705
  "--allowedTools",
3048
2706
  allowedTools
3049
2707
  ];
3050
- if (existsSync2(channelsConfigPath)) chatArgs.push("--mcp-config", channelsConfigPath);
3051
- const chatClaudeMd = join2(projDir, "CLAUDE.md");
3052
- if (existsSync2(chatClaudeMd)) {
2708
+ if (existsSync(channelsConfigPath)) chatArgs.push("--mcp-config", channelsConfigPath);
2709
+ const chatClaudeMd = join(projDir, "CLAUDE.md");
2710
+ if (existsSync(chatClaudeMd)) {
3053
2711
  chatArgs.push("--system-prompt-file", chatClaudeMd);
3054
2712
  }
3055
- const envIntPath = join2(projDir, ".env.integrations");
2713
+ const envIntPath = join(projDir, ".env.integrations");
3056
2714
  const childEnv = { ...process.env };
3057
- if (existsSync2(envIntPath)) {
2715
+ if (existsSync(envIntPath)) {
3058
2716
  try {
3059
- for (const line of readFileSync3(envIntPath, "utf-8").split("\n")) {
2717
+ for (const line of readFileSync(envIntPath, "utf-8").split("\n")) {
3060
2718
  if (!line || line.startsWith("#") || !line.includes("=")) continue;
3061
2719
  const eqIdx = line.indexOf("=");
3062
2720
  childEnv[line.slice(0, eqIdx)] = line.slice(eqIdx + 1);
@@ -3328,12 +2986,12 @@ function getBuiltInSkillContent(skillId) {
3328
2986
  if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
3329
2987
  try {
3330
2988
  const candidates = [
3331
- join2(process.cwd(), "skills", skillId, "SKILL.md"),
3332
- join2(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "skills", skillId, "SKILL.md")
2989
+ join(process.cwd(), "skills", skillId, "SKILL.md"),
2990
+ join(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "skills", skillId, "SKILL.md")
3333
2991
  ];
3334
2992
  for (const candidate of candidates) {
3335
- if (existsSync2(candidate)) {
3336
- const content = readFileSync3(candidate, "utf-8");
2993
+ if (existsSync(candidate)) {
2994
+ const content = readFileSync(candidate, "utf-8");
3337
2995
  const files = [{ relativePath: "SKILL.md", content }];
3338
2996
  builtInSkillCache.set(skillId, files);
3339
2997
  return files;
@@ -3749,7 +3407,7 @@ function generateArtifacts(agent, refreshData, adapter) {
3749
3407
  return provisionOutput.artifacts;
3750
3408
  }
3751
3409
  async function cleanupAgentFiles(codeName, agentDir) {
3752
- if (existsSync2(agentDir)) {
3410
+ if (existsSync(agentDir)) {
3753
3411
  try {
3754
3412
  rmSync(agentDir, { recursive: true, force: true });
3755
3413
  log(`Removed provision directory for '${codeName}'`);
@@ -3808,8 +3466,8 @@ var caffeinateProc = null;
3808
3466
  async function startCaffeinate() {
3809
3467
  if (process.platform !== "darwin") return;
3810
3468
  try {
3811
- const { spawn: spawn2 } = await import("child_process");
3812
- caffeinateProc = spawn2("caffeinate", ["-dims"], {
3469
+ const { spawn } = await import("child_process");
3470
+ caffeinateProc = spawn("caffeinate", ["-dims"], {
3813
3471
  stdio: "ignore",
3814
3472
  detached: false
3815
3473
  });
@@ -3860,8 +3518,8 @@ async function killAllAgtTmuxSessions() {
3860
3518
  ["list-sessions", "-F", "#{session_name}"],
3861
3519
  { timeout: 2e3, stdin: "ignore" }
3862
3520
  );
3863
- const sessions2 = output.trim().split("\n").filter((s) => s.startsWith("agt-"));
3864
- for (const session of sessions2) {
3521
+ const sessions = output.trim().split("\n").filter((s) => s.startsWith("agt-"));
3522
+ for (const session of sessions) {
3865
3523
  try {
3866
3524
  await execFilePromiseLong("tmux", ["kill-session", "-t", session], {
3867
3525
  timeout: 2e3,
@@ -3871,8 +3529,8 @@ async function killAllAgtTmuxSessions() {
3871
3529
  } catch {
3872
3530
  }
3873
3531
  }
3874
- if (sessions2.length > 0) {
3875
- log(`Cleaned up ${sessions2.length} agt-* tmux session(s)`);
3532
+ if (sessions.length > 0) {
3533
+ log(`Cleaned up ${sessions.length} agt-* tmux session(s)`);
3876
3534
  }
3877
3535
  } catch {
3878
3536
  }
@@ -3900,8 +3558,41 @@ async function stopPolling() {
3900
3558
  }
3901
3559
  function startManager(opts) {
3902
3560
  config = opts;
3561
+ deployMcpAssets();
3903
3562
  startPolling();
3904
3563
  }
3564
+ function deployMcpAssets() {
3565
+ const targetDir = join(homedir(), ".augmented", "_mcp");
3566
+ mkdirSync(targetDir, { recursive: true });
3567
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
3568
+ let mcpSourceDir = "";
3569
+ let dir = moduleDir;
3570
+ for (let i = 0; i < 6; i++) {
3571
+ const candidate = join(dir, "mcp");
3572
+ if (existsSync(join(candidate, "index.js"))) {
3573
+ mcpSourceDir = candidate;
3574
+ break;
3575
+ }
3576
+ const parent = dirname(dir);
3577
+ if (parent === dir) break;
3578
+ dir = parent;
3579
+ }
3580
+ if (!mcpSourceDir) {
3581
+ log("[manager] MCP assets not found in CLI package \u2014 skipping deployment");
3582
+ return;
3583
+ }
3584
+ for (const file of ["index.js", "slack-channel.js"]) {
3585
+ const src = join(mcpSourceDir, file);
3586
+ const dst = join(targetDir, file);
3587
+ if (!existsSync(src)) continue;
3588
+ try {
3589
+ copyFileSync(src, dst);
3590
+ } catch (err) {
3591
+ log(`[manager] Failed to deploy ${file}: ${err.message}`);
3592
+ }
3593
+ }
3594
+ log(`[manager] MCP assets deployed to ${targetDir}`);
3595
+ }
3905
3596
  async function stopManager() {
3906
3597
  await stopPolling();
3907
3598
  }