@integrity-labs/agt-cli 0.24.0 → 0.24.3

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.
@@ -12,7 +12,7 @@ import {
12
12
  provisionOrientHook,
13
13
  provisionStopHook,
14
14
  requireHost
15
- } from "../chunk-WZTRMJM4.js";
15
+ } from "../chunk-KVIKKWXB.js";
16
16
  import {
17
17
  findTaskByTemplate,
18
18
  getProjectDir as getProjectDir2,
@@ -43,11 +43,12 @@ import {
43
43
  resolveClaudeBinary,
44
44
  sanitizeMcpJson,
45
45
  sendToAgent,
46
+ sessionTranscriptDir,
46
47
  startPersistentSession,
47
48
  stopAllSessionsAndWait,
48
49
  stopPersistentSession,
49
50
  takeZombieDetection
50
- } from "../chunk-ZKQGDH3T.js";
51
+ } from "../chunk-PNTLQKLO.js";
51
52
  import {
52
53
  KANBAN_CHECK_COMMAND,
53
54
  appendDmFooter,
@@ -55,22 +56,24 @@ import {
55
56
  extractFrontmatter,
56
57
  formatActorId,
57
58
  getFramework,
59
+ isEmptyTotals,
58
60
  isParseError,
59
61
  isResolveError,
60
62
  isSelfCompletion,
61
63
  parseDeliveryTarget,
64
+ parseTranscriptUsage,
62
65
  parseUsageBanner,
63
66
  resolveChannels,
64
67
  resolveDmTarget,
65
68
  wrapScheduledTaskPrompt
66
- } from "../chunk-HSIESZMZ.js";
69
+ } from "../chunk-ECDTRQLA.js";
67
70
 
68
71
  // src/lib/manager-worker.ts
69
72
  import { createHash as createHash2 } from "crypto";
70
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync2, chmodSync, existsSync as existsSync4, rmSync as rmSync2, readdirSync as readdirSync2, statSync, unlinkSync, copyFileSync } from "fs";
73
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync2, chmodSync, existsSync as existsSync4, rmSync as rmSync2, readdirSync as readdirSync3, statSync as statSync2, unlinkSync, copyFileSync } from "fs";
71
74
  import https from "https";
72
75
  import { execFileSync as syncExecFile } from "child_process";
73
- import { join as join5, dirname } from "path";
76
+ import { join as join6, dirname } from "path";
74
77
  import { homedir as homedir4 } from "os";
75
78
  import { fileURLToPath } from "url";
76
79
 
@@ -435,12 +438,12 @@ function reapMissingMcpSessions(args) {
435
438
  if (!missingRaw.includes(key)) liveKeys.add(key);
436
439
  }
437
440
  for (const key of liveKeys) {
438
- const state4 = presenceReaperState.get(stateKey(codeName, key));
439
- if (state4) {
440
- state4.attempts = 0;
441
- state4.lastSeenLiveAt = now();
442
- state4.lastAttemptedSessionStartedAt = null;
443
- state4.gaveUpLogged = false;
441
+ const state5 = presenceReaperState.get(stateKey(codeName, key));
442
+ if (state5) {
443
+ state5.attempts = 0;
444
+ state5.lastSeenLiveAt = now();
445
+ state5.lastAttemptedSessionStartedAt = null;
446
+ state5.gaveUpLogged = false;
444
447
  }
445
448
  }
446
449
  if (missing.length === 0) {
@@ -455,24 +458,24 @@ function reapMissingMcpSessions(args) {
455
458
  const active = [];
456
459
  for (const key of missing) {
457
460
  const sk = stateKey(codeName, key);
458
- const state4 = presenceReaperState.get(sk) ?? {
461
+ const state5 = presenceReaperState.get(sk) ?? {
459
462
  attempts: 0,
460
463
  lastSeenLiveAt: null,
461
464
  lastAttemptedSessionStartedAt: null,
462
465
  gaveUpLogged: false
463
466
  };
464
- if (state4.lastAttemptedSessionStartedAt !== sessionStartedAt) {
465
- state4.attempts += 1;
466
- state4.lastAttemptedSessionStartedAt = sessionStartedAt;
467
+ if (state5.lastAttemptedSessionStartedAt !== sessionStartedAt) {
468
+ state5.attempts += 1;
469
+ state5.lastAttemptedSessionStartedAt = sessionStartedAt;
467
470
  }
468
- presenceReaperState.set(sk, state4);
469
- if (state4.attempts > MAX_PRESENCE_RESTART_ATTEMPTS) {
471
+ presenceReaperState.set(sk, state5);
472
+ if (state5.attempts > MAX_PRESENCE_RESTART_ATTEMPTS) {
470
473
  givenUp.push(key);
471
- if (!state4.gaveUpLogged) {
474
+ if (!state5.gaveUpLogged) {
472
475
  log2(
473
476
  `[mcp-presence-reaper] giving up on '${codeName}:${key}' after ${MAX_PRESENCE_RESTART_ATTEMPTS} consecutive failed restarts \u2014 declared but never recovers (likely orphaned config; see ENG-5279)`
474
477
  );
475
- state4.gaveUpLogged = true;
478
+ state5.gaveUpLogged = true;
476
479
  if (onGiveUp) {
477
480
  try {
478
481
  onGiveUp(codeName, key);
@@ -710,14 +713,115 @@ async function maybeReportUsageBanner(args) {
710
713
  }
711
714
  }
712
715
 
713
- // src/lib/activity-cache-monitor.ts
714
- import { existsSync, readFileSync } from "fs";
715
- import { homedir } from "os";
716
+ // src/lib/token-usage-monitor.ts
717
+ import { readdirSync, readFileSync, statSync } from "fs";
716
718
  import { join } from "path";
717
719
  var MIN_CHECK_INTERVAL_MS2 = 6e4;
718
- var STATS_CACHE_PATH = join(homedir(), ".claude", "stats-cache.json");
720
+ var TRANSCRIPT_MTIME_WINDOW_MS = 2 * 24 * 60 * 60 * 1e3;
721
+ var MAX_ENTRIES_PER_POST = 200;
722
+ var state2 = /* @__PURE__ */ new Map();
723
+ async function maybeReportTokenUsage(args) {
724
+ const { api: api2, codeName, agentId, log: log2 } = args;
725
+ const now = args.now ?? /* @__PURE__ */ new Date();
726
+ const nowMs = now.getTime();
727
+ const existing = state2.get(codeName);
728
+ if (existing && nowMs - existing.lastCheckedAt < MIN_CHECK_INTERVAL_MS2) {
729
+ return;
730
+ }
731
+ const dir = args.transcriptDir ?? sessionTranscriptDir(getProjectDir(codeName));
732
+ const files = existing?.files ?? /* @__PURE__ */ new Map();
733
+ const next = { files, lastCheckedAt: nowMs };
734
+ let dirEntries;
735
+ try {
736
+ dirEntries = readdirSync(dir);
737
+ } catch {
738
+ state2.set(codeName, next);
739
+ return;
740
+ }
741
+ const pending = [];
742
+ for (const name of dirEntries) {
743
+ if (!name.endsWith(".jsonl")) continue;
744
+ const sessionId = name.slice(0, -".jsonl".length);
745
+ if (!sessionId) continue;
746
+ const path = join(dir, name);
747
+ let st;
748
+ try {
749
+ st = statSync(path);
750
+ } catch {
751
+ continue;
752
+ }
753
+ if (!st.isFile()) continue;
754
+ if (nowMs - st.mtimeMs > TRANSCRIPT_MTIME_WINDOW_MS) continue;
755
+ const fp = { mtimeMs: st.mtimeMs, size: st.size };
756
+ const seen = files.get(sessionId);
757
+ if (seen && seen.mtimeMs === fp.mtimeMs && seen.size === fp.size) {
758
+ continue;
759
+ }
760
+ let content;
761
+ try {
762
+ content = readFileSync(path, "utf-8");
763
+ } catch (err) {
764
+ log2(`[token-usage] read failed for '${codeName}/${name}': ${err.message}`);
765
+ continue;
766
+ }
767
+ const parsed = parseTranscriptUsage(content);
768
+ for (const [model, totals] of parsed.byModel) {
769
+ if (isEmptyTotals(totals)) continue;
770
+ pending.push({
771
+ sessionId,
772
+ fp,
773
+ entry: {
774
+ session_id: sessionId,
775
+ model,
776
+ input_tokens: totals.inputTokens,
777
+ output_tokens: totals.outputTokens,
778
+ cache_creation_tokens: totals.cacheCreationTokens,
779
+ cache_read_tokens: totals.cacheReadTokens,
780
+ session_started_at: parsed.sessionStartedAt,
781
+ last_observed_at: parsed.lastObservedAt
782
+ }
783
+ });
784
+ }
785
+ if (![...parsed.byModel.values()].some((t) => !isEmptyTotals(t))) {
786
+ files.set(sessionId, fp);
787
+ }
788
+ }
789
+ if (pending.length === 0) {
790
+ state2.set(codeName, next);
791
+ return;
792
+ }
793
+ let reported = 0;
794
+ for (let i = 0; i < pending.length; i += MAX_ENTRIES_PER_POST) {
795
+ const batch = pending.slice(i, i + MAX_ENTRIES_PER_POST);
796
+ try {
797
+ await api2.post("/host/token-usage", {
798
+ agent_id: agentId,
799
+ framework: "claude-code",
800
+ source: "transcript_jsonl",
801
+ entries: batch.map((b) => b.entry)
802
+ });
803
+ for (const b of batch) {
804
+ files.set(b.sessionId, b.fp);
805
+ }
806
+ reported += batch.length;
807
+ } catch (err) {
808
+ log2(`[token-usage] POST failed for '${codeName}': ${err.message}`);
809
+ }
810
+ }
811
+ if (reported > 0) {
812
+ log2(`[token-usage] reported ${reported} entr${reported === 1 ? "y" : "ies"} for '${codeName}'`);
813
+ }
814
+ state2.set(codeName, next);
815
+ }
816
+
817
+ // src/lib/activity-cache-monitor.ts
818
+ import { existsSync, readFileSync as readFileSync2 } from "fs";
819
+ import { homedir } from "os";
820
+ import { join as join2 } from "path";
821
+ var MIN_CHECK_INTERVAL_MS3 = 6e4;
822
+ var STATS_CACHE_PATH = join2(homedir(), ".claude", "stats-cache.json");
719
823
  var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
720
- var state2 = { lastObservedDate: null, lastCheckedAt: 0 };
824
+ var state3 = { lastObservedDate: null, lastCheckedAt: 0 };
721
825
  function selectNewDailyRows(raw, lastObservedDate) {
722
826
  let parsed;
723
827
  try {
@@ -756,24 +860,24 @@ async function maybeReportActivityCache(args) {
756
860
  const { api: api2, log: log2 } = args;
757
861
  const now = args.now ?? /* @__PURE__ */ new Date();
758
862
  const nowMs = now.getTime();
759
- if (nowMs - state2.lastCheckedAt < MIN_CHECK_INTERVAL_MS2) return;
760
- state2.lastCheckedAt = nowMs;
863
+ if (nowMs - state3.lastCheckedAt < MIN_CHECK_INTERVAL_MS3) return;
864
+ state3.lastCheckedAt = nowMs;
761
865
  if (!existsSync(STATS_CACHE_PATH)) {
762
866
  return;
763
867
  }
764
868
  let raw;
765
869
  try {
766
- raw = readFileSync(STATS_CACHE_PATH, "utf-8");
870
+ raw = readFileSync2(STATS_CACHE_PATH, "utf-8");
767
871
  } catch (err) {
768
872
  log2(`[activity-cache] readFileSync failed: ${err.message}`);
769
873
  return;
770
874
  }
771
- const rows = selectNewDailyRows(raw, state2.lastObservedDate);
875
+ const rows = selectNewDailyRows(raw, state3.lastObservedDate);
772
876
  if (rows.length === 0) return;
773
877
  for (const row of rows) {
774
878
  try {
775
879
  await api2.post("/host/activity-observations", row);
776
- state2.lastObservedDate = row.date;
880
+ state3.lastObservedDate = row.date;
777
881
  } catch (err) {
778
882
  log2(
779
883
  `[activity-cache] POST /host/activity-observations failed for date=${row.date}: ${err.message}`
@@ -1213,7 +1317,7 @@ var GatewayClientPool = class extends EventEmitter {
1213
1317
  // src/lib/claude-auth-detect.ts
1214
1318
  import { readFile, readdir } from "fs/promises";
1215
1319
  import { homedir as homedir2, platform } from "os";
1216
- import { join as join2 } from "path";
1320
+ import { join as join3 } from "path";
1217
1321
  import { execFile } from "child_process";
1218
1322
  import { promisify } from "util";
1219
1323
  var execFileAsync = promisify(execFile);
@@ -1228,8 +1332,8 @@ async function detectClaudeAuth() {
1228
1332
  }
1229
1333
  async function findClaudeCredentialsPaths() {
1230
1334
  const candidates = [
1231
- join2(homedir2(), ".claude", ".credentials.json"),
1232
- join2(homedir2(), ".claude", "credentials.json")
1335
+ join3(homedir2(), ".claude", ".credentials.json"),
1336
+ join3(homedir2(), ".claude", "credentials.json")
1233
1337
  ];
1234
1338
  const isLinuxRoot = platform() === "linux" && typeof process.getuid === "function" && process.getuid() === 0;
1235
1339
  if (isLinuxRoot) {
@@ -1237,8 +1341,8 @@ async function findClaudeCredentialsPaths() {
1237
1341
  const entries = await readdir("/home", { withFileTypes: true });
1238
1342
  for (const entry of entries) {
1239
1343
  if (!entry.isDirectory()) continue;
1240
- candidates.push(join2("/home", entry.name, ".claude", ".credentials.json"));
1241
- candidates.push(join2("/home", entry.name, ".claude", "credentials.json"));
1344
+ candidates.push(join3("/home", entry.name, ".claude", ".credentials.json"));
1345
+ candidates.push(join3("/home", entry.name, ".claude", "credentials.json"));
1242
1346
  }
1243
1347
  } catch {
1244
1348
  }
@@ -1330,18 +1434,18 @@ function normalize(value) {
1330
1434
  }
1331
1435
 
1332
1436
  // src/lib/channel-hash-cache.ts
1333
- import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
1334
- import { join as join3 } from "path";
1437
+ import { existsSync as existsSync2, readFileSync as readFileSync3, writeFileSync } from "fs";
1438
+ import { join as join4 } from "path";
1335
1439
  var CACHE_FILENAME = "channel-hash-cache.json";
1336
1440
  function getChannelHashCacheFile(configDir) {
1337
- return join3(configDir, CACHE_FILENAME);
1441
+ return join4(configDir, CACHE_FILENAME);
1338
1442
  }
1339
1443
  function loadChannelHashCache(target, configDir) {
1340
1444
  const path = getChannelHashCacheFile(configDir);
1341
1445
  if (!existsSync2(path)) return;
1342
1446
  let parsed;
1343
1447
  try {
1344
- parsed = JSON.parse(readFileSync2(path, "utf-8"));
1448
+ parsed = JSON.parse(readFileSync3(path, "utf-8"));
1345
1449
  } catch {
1346
1450
  return;
1347
1451
  }
@@ -1814,24 +1918,24 @@ function withScheduleLinkFooter(opts) {
1814
1918
  }
1815
1919
 
1816
1920
  // src/lib/restart-flags.ts
1817
- import { existsSync as existsSync3, mkdirSync, readdirSync, readFileSync as readFileSync3, renameSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
1921
+ import { existsSync as existsSync3, mkdirSync, readdirSync as readdirSync2, readFileSync as readFileSync4, renameSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
1818
1922
  import { homedir as homedir3 } from "os";
1819
- import { join as join4 } from "path";
1923
+ import { join as join5 } from "path";
1820
1924
  import { randomUUID } from "crypto";
1821
1925
  function restartFlagsDir() {
1822
- return join4(homedir3(), ".augmented", "restart-flags");
1926
+ return join5(homedir3(), ".augmented", "restart-flags");
1823
1927
  }
1824
1928
  function flagPath(codeName) {
1825
- return join4(restartFlagsDir(), `${codeName}.flag`);
1929
+ return join5(restartFlagsDir(), `${codeName}.flag`);
1826
1930
  }
1827
1931
  function readRestartFlags() {
1828
1932
  const dir = restartFlagsDir();
1829
1933
  if (!existsSync3(dir)) return [];
1830
1934
  const out = [];
1831
- for (const entry of readdirSync(dir)) {
1935
+ for (const entry of readdirSync2(dir)) {
1832
1936
  if (!entry.endsWith(".flag")) continue;
1833
1937
  try {
1834
- const raw = readFileSync3(join4(dir, entry), "utf8");
1938
+ const raw = readFileSync4(join5(dir, entry), "utf8");
1835
1939
  const parsed = JSON.parse(raw);
1836
1940
  if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
1837
1941
  parsed.codeName = entry.replace(/\.flag$/, "");
@@ -2347,8 +2451,8 @@ function applyRestartAcks(args) {
2347
2451
  var GATEWAY_PORT_BASE = 18800;
2348
2452
  var GATEWAY_PORT_STEP = 10;
2349
2453
  var GATEWAY_PORT_MAX = 18899;
2350
- var AUGMENTED_DIR = join5(process.env["HOME"] ?? "/tmp", ".augmented");
2351
- var GATEWAY_PORTS_FILE = join5(AUGMENTED_DIR, "gateway-ports.json");
2454
+ var AUGMENTED_DIR = join6(process.env["HOME"] ?? "/tmp", ".augmented");
2455
+ var GATEWAY_PORTS_FILE = join6(AUGMENTED_DIR, "gateway-ports.json");
2352
2456
  var CHANNEL_SWEEP_INTERVAL_MS = (() => {
2353
2457
  const raw = parseInt(process.env["AGT_CHANNEL_SWEEP_INTERVAL_MS"] ?? "", 10);
2354
2458
  if (!Number.isFinite(raw)) return 5 * 60 * 1e3;
@@ -2455,8 +2559,8 @@ var KNOWN_SAFE_TAIL_SIGNATURES = /* @__PURE__ */ new Set(["session_id_in_use"]);
2455
2559
  function shouldSkipRevokedCleanup(previousKnownStatus) {
2456
2560
  return previousKnownStatus === "revoked";
2457
2561
  }
2458
- function hasRevokedResiduals(state4) {
2459
- return state4.gatewayRunning || state4.portAllocated || state4.provisionDirExists;
2562
+ function hasRevokedResiduals(state5) {
2563
+ return state5.gatewayRunning || state5.portAllocated || state5.provisionDirExists;
2460
2564
  }
2461
2565
  var knownVersions = /* @__PURE__ */ new Map();
2462
2566
  var knownStatuses = /* @__PURE__ */ new Map();
@@ -2522,7 +2626,7 @@ var runningMcpHashes = /* @__PURE__ */ new Map();
2522
2626
  var runningMcpServerKeys = /* @__PURE__ */ new Map();
2523
2627
  function projectMcpHash(_codeName, projectDir) {
2524
2628
  try {
2525
- const raw = readFileSync4(join5(projectDir, ".mcp.json"), "utf-8");
2629
+ const raw = readFileSync5(join6(projectDir, ".mcp.json"), "utf-8");
2526
2630
  return createHash2("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
2527
2631
  } catch {
2528
2632
  return null;
@@ -2530,7 +2634,7 @@ function projectMcpHash(_codeName, projectDir) {
2530
2634
  }
2531
2635
  function projectMcpKeys(_codeName, projectDir) {
2532
2636
  try {
2533
- const raw = readFileSync4(join5(projectDir, ".mcp.json"), "utf-8");
2637
+ const raw = readFileSync5(join6(projectDir, ".mcp.json"), "utf-8");
2534
2638
  const parsed = JSON.parse(raw);
2535
2639
  const servers = parsed.mcpServers;
2536
2640
  if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
@@ -2627,7 +2731,7 @@ var codeNameToAgentId = /* @__PURE__ */ new Map();
2627
2731
  var agentChannelTokens = /* @__PURE__ */ new Map();
2628
2732
  var activeChannels = /* @__PURE__ */ new Map();
2629
2733
  var gatewaysStartedThisCycle = /* @__PURE__ */ new Set();
2630
- var state3 = {
2734
+ var state4 = {
2631
2735
  pid: process.pid,
2632
2736
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
2633
2737
  lastPollAt: null,
@@ -2684,7 +2788,7 @@ var cachedFrameworkVersion = null;
2684
2788
  var lastVersionCheckAt = 0;
2685
2789
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
2686
2790
  var lastResponsivenessProbeAt = 0;
2687
- var agtCliVersion = true ? "0.24.0" : "dev";
2791
+ var agtCliVersion = true ? "0.24.3" : "dev";
2688
2792
  function resolveBrewPath(execFileSync4) {
2689
2793
  try {
2690
2794
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -2901,7 +3005,7 @@ async function ensureFrameworkBinary(frameworkId) {
2901
3005
  var CLAUDE_CODE_UPGRADE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
2902
3006
  var claudeCodeUpgradeInFlight = false;
2903
3007
  function claudeCodeUpgradeMarkerPath() {
2904
- return join5(homedir4(), ".augmented", ".last-claude-code-upgrade-check");
3008
+ return join6(homedir4(), ".augmented", ".last-claude-code-upgrade-check");
2905
3009
  }
2906
3010
  function stampClaudeCodeUpgradeMarker() {
2907
3011
  try {
@@ -2911,7 +3015,7 @@ function stampClaudeCodeUpgradeMarker() {
2911
3015
  }
2912
3016
  function claudeCodeUpgradeThrottled() {
2913
3017
  try {
2914
- const lastCheck = parseInt(readFileSync4(claudeCodeUpgradeMarkerPath(), "utf-8").trim(), 10);
3018
+ const lastCheck = parseInt(readFileSync5(claudeCodeUpgradeMarkerPath(), "utf-8").trim(), 10);
2915
3019
  if (!Number.isFinite(lastCheck)) return false;
2916
3020
  return Date.now() - lastCheck < CLAUDE_CODE_UPGRADE_CHECK_INTERVAL_MS;
2917
3021
  } catch {
@@ -2981,7 +3085,7 @@ async function checkAndUpdateCli() {
2981
3085
  const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
2982
3086
  if (!isBrewFormula && !isNpmGlobal) return;
2983
3087
  const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
2984
- const markerPath = join5(homedir4(), ".augmented", ".last-update-check");
3088
+ const markerPath = join6(homedir4(), ".augmented", ".last-update-check");
2985
3089
  try {
2986
3090
  const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
2987
3091
  if (Date.now() - lastCheck < UPDATE_CHECK_INTERVAL_MS) return;
@@ -3145,9 +3249,9 @@ async function applyClaudeAuthToEnv(childEnv, label) {
3145
3249
  throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
3146
3250
  }
3147
3251
  childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
3148
- const claudeDir = join5(homedir4(), ".claude");
3252
+ const claudeDir = join6(homedir4(), ".claude");
3149
3253
  for (const filename of [".credentials.json", "credentials.json"]) {
3150
- const p = join5(claudeDir, filename);
3254
+ const p = join6(claudeDir, filename);
3151
3255
  if (existsSync4(p)) {
3152
3256
  try {
3153
3257
  rmSync2(p, { force: true });
@@ -3162,7 +3266,7 @@ async function applyClaudeAuthToEnv(childEnv, label) {
3162
3266
  }
3163
3267
  function loadGatewayPorts() {
3164
3268
  try {
3165
- return JSON.parse(readFileSync4(GATEWAY_PORTS_FILE, "utf-8"));
3269
+ return JSON.parse(readFileSync5(GATEWAY_PORTS_FILE, "utf-8"));
3166
3270
  } catch {
3167
3271
  return {};
3168
3272
  }
@@ -3192,10 +3296,10 @@ function freePort(codeName) {
3192
3296
  }
3193
3297
  }
3194
3298
  function getStateFile() {
3195
- return join5(config?.configDir ?? join5(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
3299
+ return join6(config?.configDir ?? join6(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
3196
3300
  }
3197
3301
  function channelHashCacheDir() {
3198
- return config?.configDir ?? join5(process.env["HOME"] ?? "/tmp", ".augmented");
3302
+ return config?.configDir ?? join6(process.env["HOME"] ?? "/tmp", ".augmented");
3199
3303
  }
3200
3304
  function loadChannelHashCache2() {
3201
3305
  loadChannelHashCache(knownChannelConfigHashes, channelHashCacheDir());
@@ -3237,7 +3341,7 @@ function log(msg) {
3237
3341
  `;
3238
3342
  if (!managerLogPath) {
3239
3343
  try {
3240
- managerLogPath = join5(homedir4(), ".augmented", "manager.log");
3344
+ managerLogPath = join6(homedir4(), ".augmented", "manager.log");
3241
3345
  mkdirSync2(dirname(managerLogPath), { recursive: true });
3242
3346
  if (existsSync4(managerLogPath)) {
3243
3347
  chmodSync(managerLogPath, 384);
@@ -3267,7 +3371,7 @@ function sha256(content) {
3267
3371
  }
3268
3372
  function hashFile(filePath) {
3269
3373
  try {
3270
- const content = readFileSync4(filePath, "utf-8");
3374
+ const content = readFileSync5(filePath, "utf-8");
3271
3375
  return sha256(content);
3272
3376
  } catch {
3273
3377
  return null;
@@ -3291,13 +3395,13 @@ function parseSkillFrontmatter(content) {
3291
3395
  return out;
3292
3396
  }
3293
3397
  async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
3294
- const { readdirSync: readdirSync3, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync4 } = await import("fs");
3295
- const skillsDir = join5(configDir, codeName, "project", ".claude", "skills");
3296
- const claudeMdPath = join5(configDir, codeName, "project", "CLAUDE.md");
3398
+ const { readdirSync: readdirSync4, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync4 } = await import("fs");
3399
+ const skillsDir = join6(configDir, codeName, "project", ".claude", "skills");
3400
+ const claudeMdPath = join6(configDir, codeName, "project", "CLAUDE.md");
3297
3401
  if (!ex(skillsDir) || !ex(claudeMdPath)) return;
3298
3402
  const entries = [];
3299
- for (const dir of readdirSync3(skillsDir).sort()) {
3300
- const skillFile = join5(skillsDir, dir, "SKILL.md");
3403
+ for (const dir of readdirSync4(skillsDir).sort()) {
3404
+ const skillFile = join6(skillsDir, dir, "SKILL.md");
3301
3405
  if (!ex(skillFile)) continue;
3302
3406
  try {
3303
3407
  const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
@@ -3345,10 +3449,10 @@ ${SKILLS_INDEX_END}`;
3345
3449
  }
3346
3450
  async function migrateToProfiles() {
3347
3451
  const homeDir = process.env["HOME"] ?? "/tmp";
3348
- const sharedConfigPath = join5(homeDir, ".openclaw", "openclaw.json");
3452
+ const sharedConfigPath = join6(homeDir, ".openclaw", "openclaw.json");
3349
3453
  let sharedConfig;
3350
3454
  try {
3351
- sharedConfig = JSON.parse(readFileSync4(sharedConfigPath, "utf-8"));
3455
+ sharedConfig = JSON.parse(readFileSync5(sharedConfigPath, "utf-8"));
3352
3456
  } catch {
3353
3457
  return;
3354
3458
  }
@@ -3361,19 +3465,19 @@ async function migrateToProfiles() {
3361
3465
  const codeName = agentEntry["id"];
3362
3466
  if (!codeName) continue;
3363
3467
  if (codeName === "main") continue;
3364
- const profileDir = join5(homeDir, `.openclaw-${codeName}`);
3365
- if (existsSync4(join5(profileDir, "openclaw.json"))) continue;
3468
+ const profileDir = join6(homeDir, `.openclaw-${codeName}`);
3469
+ if (existsSync4(join6(profileDir, "openclaw.json"))) continue;
3366
3470
  log(`Migrating agent '${codeName}' to per-agent profile`);
3367
3471
  if (adapter.seedProfileConfig) {
3368
3472
  adapter.seedProfileConfig(codeName);
3369
3473
  }
3370
- const sharedAuthDir = join5(homeDir, ".openclaw", "agents", codeName, "agent");
3371
- const profileAuthDir = join5(profileDir, "agents", codeName, "agent");
3372
- const authFile = join5(sharedAuthDir, "auth-profiles.json");
3474
+ const sharedAuthDir = join6(homeDir, ".openclaw", "agents", codeName, "agent");
3475
+ const profileAuthDir = join6(profileDir, "agents", codeName, "agent");
3476
+ const authFile = join6(sharedAuthDir, "auth-profiles.json");
3373
3477
  if (existsSync4(authFile)) {
3374
3478
  mkdirSync2(profileAuthDir, { recursive: true });
3375
- const authContent = readFileSync4(authFile, "utf-8");
3376
- writeFileSync3(join5(profileAuthDir, "auth-profiles.json"), authContent);
3479
+ const authContent = readFileSync5(authFile, "utf-8");
3480
+ writeFileSync3(join6(profileAuthDir, "auth-profiles.json"), authContent);
3377
3481
  }
3378
3482
  allocatePort(codeName);
3379
3483
  migrated++;
@@ -3411,7 +3515,7 @@ function readGatewayToken(codeName) {
3411
3515
  }
3412
3516
  const homeDir = process.env["HOME"] ?? "/tmp";
3413
3517
  try {
3414
- const cfg = JSON.parse(readFileSync4(join5(homeDir, `.openclaw-${codeName}`, "openclaw.json"), "utf-8"));
3518
+ const cfg = JSON.parse(readFileSync5(join6(homeDir, `.openclaw-${codeName}`, "openclaw.json"), "utf-8"));
3415
3519
  return cfg?.gateway?.auth?.token;
3416
3520
  } catch {
3417
3521
  return void 0;
@@ -3420,18 +3524,18 @@ function readGatewayToken(codeName) {
3420
3524
  var GATEWAY_HUNG_TIMEOUT_MS = 5 * 6e4;
3421
3525
  function isGatewayHung(codeName) {
3422
3526
  const homeDir = process.env["HOME"] ?? "/tmp";
3423
- const jobsPath = join5(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
3527
+ const jobsPath = join6(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
3424
3528
  if (!existsSync4(jobsPath)) return false;
3425
3529
  try {
3426
- const data = JSON.parse(readFileSync4(jobsPath, "utf-8"));
3530
+ const data = JSON.parse(readFileSync5(jobsPath, "utf-8"));
3427
3531
  const jobs = data.jobs ?? data;
3428
3532
  if (!Array.isArray(jobs)) return false;
3429
3533
  const now = Date.now();
3430
3534
  for (const job of jobs) {
3431
- const state4 = job.state;
3432
- if (!state4) continue;
3433
- const runStartedAt = state4.runStartedAtMs;
3434
- const isRunning = state4.status === "running" || state4.running === true;
3535
+ const state5 = job.state;
3536
+ if (!state5) continue;
3537
+ const runStartedAt = state5.runStartedAtMs;
3538
+ const isRunning = state5.status === "running" || state5.running === true;
3435
3539
  if (isRunning && runStartedAt && now - runStartedAt > GATEWAY_HUNG_TIMEOUT_MS) {
3436
3540
  return true;
3437
3541
  }
@@ -3456,15 +3560,15 @@ async function ensureGatewayRunning(codeName, adapter) {
3456
3560
  }
3457
3561
  await new Promise((r) => setTimeout(r, 2e3));
3458
3562
  const homeDir = process.env["HOME"] ?? "/tmp";
3459
- const cronJobsPath = join5(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
3563
+ const cronJobsPath = join6(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
3460
3564
  clearStaleCronRunState(cronJobsPath);
3461
3565
  } else {
3462
3566
  if (status.port) {
3463
3567
  try {
3464
3568
  const homeDir = process.env["HOME"] ?? "/tmp";
3465
- const configPath = join5(homeDir, `.openclaw-${codeName}`, "openclaw.json");
3569
+ const configPath = join6(homeDir, `.openclaw-${codeName}`, "openclaw.json");
3466
3570
  if (existsSync4(configPath)) {
3467
- const cfg = JSON.parse(readFileSync4(configPath, "utf-8"));
3571
+ const cfg = JSON.parse(readFileSync5(configPath, "utf-8"));
3468
3572
  if (cfg.gateway?.port !== status.port) {
3469
3573
  if (!cfg.gateway) cfg.gateway = {};
3470
3574
  cfg.gateway.port = status.port;
@@ -3488,9 +3592,9 @@ async function ensureGatewayRunning(codeName, adapter) {
3488
3592
  gatewaysStartedThisCycle.add(codeName);
3489
3593
  try {
3490
3594
  const homeDir = process.env["HOME"] ?? "/tmp";
3491
- const configPath = join5(homeDir, `.openclaw-${codeName}`, "openclaw.json");
3595
+ const configPath = join6(homeDir, `.openclaw-${codeName}`, "openclaw.json");
3492
3596
  if (existsSync4(configPath)) {
3493
- const cfg = JSON.parse(readFileSync4(configPath, "utf-8"));
3597
+ const cfg = JSON.parse(readFileSync5(configPath, "utf-8"));
3494
3598
  if (!cfg.gateway) cfg.gateway = {};
3495
3599
  cfg.gateway.port = port;
3496
3600
  writeFileSync3(configPath, JSON.stringify(cfg, null, 2));
@@ -3632,7 +3736,7 @@ async function pollCycle() {
3632
3736
  const now = Date.now();
3633
3737
  if (now - lastVersionCheckAt > VERSION_CHECK_INTERVAL_MS) {
3634
3738
  try {
3635
- const firstAgent = state3.agents[0];
3739
+ const firstAgent = state4.agents[0];
3636
3740
  const versionAdapter = firstAgent ? resolveAgentFramework(firstAgent.codeName) : getFramework("openclaw");
3637
3741
  if (versionAdapter.getVersion) {
3638
3742
  cachedFrameworkVersion = await versionAdapter.getVersion();
@@ -3643,7 +3747,7 @@ async function pollCycle() {
3643
3747
  }
3644
3748
  try {
3645
3749
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
3646
- const { collectDiagnostics } = await import("../persistent-session-L4YIJJML.js");
3750
+ const { collectDiagnostics } = await import("../persistent-session-JUJY46HW.js");
3647
3751
  const diagCodeNames = [...persistentSessionAgents];
3648
3752
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
3649
3753
  let tailscaleHostname;
@@ -3694,7 +3798,7 @@ async function pollCycle() {
3694
3798
  const {
3695
3799
  collectResponsivenessProbes,
3696
3800
  getResponsivenessIntervalMs
3697
- } = await import("../responsiveness-probe-YRLESO54.js");
3801
+ } = await import("../responsiveness-probe-XOEC7J5D.js");
3698
3802
  const probeIntervalMs = getResponsivenessIntervalMs();
3699
3803
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
3700
3804
  const probeCodeNames = [...persistentSessionAgents];
@@ -3754,7 +3858,7 @@ async function pollCycle() {
3754
3858
  for (const agent of agents) {
3755
3859
  const requested = agent.restart_requested_at ?? null;
3756
3860
  if (!requested) continue;
3757
- const prev = state3.agents.find((a) => a.agentId === agent.agent_id);
3861
+ const prev = state4.agents.find((a) => a.agentId === agent.agent_id);
3758
3862
  const lastProcessed = prev?.lastRestartProcessedAt ?? null;
3759
3863
  if (lastProcessed && Date.parse(lastProcessed) >= Date.parse(requested)) continue;
3760
3864
  log(`[restart] Dashboard requested restart for '${agent.code_name}' at ${requested}`);
@@ -3777,7 +3881,7 @@ async function pollCycle() {
3777
3881
  await processAgent(agent, agentStates);
3778
3882
  } catch (err) {
3779
3883
  log(`Error processing agent '${agent.code_name}': ${err.message}`);
3780
- const existing = state3.agents.find((a) => a.agentId === agent.agent_id);
3884
+ const existing = state4.agents.find((a) => a.agentId === agent.agent_id);
3781
3885
  if (existing) {
3782
3886
  agentStates.push(existing);
3783
3887
  } else {
@@ -3803,12 +3907,12 @@ async function pollCycle() {
3803
3907
  void maybeReportActivityCache({ api, log });
3804
3908
  const restartAckStateChanged = applyRestartAcks({
3805
3909
  agentStates,
3806
- priorAgents: state3.agents,
3910
+ priorAgents: state4.agents,
3807
3911
  restartAcks
3808
3912
  });
3809
3913
  if (restartAckStateChanged) {
3810
3914
  try {
3811
- const ackedState = { ...state3, agents: agentStates };
3915
+ const ackedState = { ...state4, agents: agentStates };
3812
3916
  writeFileSync3(getStateFile(), JSON.stringify(ackedState, null, 2));
3813
3917
  } catch (err) {
3814
3918
  log(`[restart] failed to persist ack immediately: ${err.message}`);
@@ -3826,7 +3930,7 @@ async function pollCycle() {
3826
3930
  } catch {
3827
3931
  }
3828
3932
  const currentIds = new Set(agents.map((a) => a.agent_id));
3829
- for (const prev of state3.agents) {
3933
+ for (const prev of state4.agents) {
3830
3934
  if (!currentIds.has(prev.agentId)) {
3831
3935
  log(`Agent '${prev.codeName}' removed from host (deleted or unassigned)`);
3832
3936
  const adapter = resolveAgentFramework(prev.codeName);
@@ -3839,7 +3943,7 @@ async function pollCycle() {
3839
3943
  }
3840
3944
  killAgentChannelProcesses(prev.codeName, { log });
3841
3945
  freePort(prev.codeName);
3842
- const agentDir = join5(adapter.getAgentDir(prev.codeName), "provision");
3946
+ const agentDir = join6(adapter.getAgentDir(prev.codeName), "provision");
3843
3947
  await cleanupAgentFiles(prev.codeName, agentDir);
3844
3948
  clearAgentCaches(prev.agentId, prev.codeName);
3845
3949
  }
@@ -3926,10 +4030,10 @@ async function pollCycle() {
3926
4030
  }
3927
4031
  } catch {
3928
4032
  }
3929
- state3 = {
3930
- ...state3,
4033
+ state4 = {
4034
+ ...state4,
3931
4035
  lastPollAt: (/* @__PURE__ */ new Date()).toISOString(),
3932
- pollCount: state3.pollCount + 1,
4036
+ pollCount: state4.pollCount + 1,
3933
4037
  agents: agentStates,
3934
4038
  // ENG-5441: serialise trip state on every poll so manager restarts
3935
4039
  // never silently clear a tripped breaker. Cheap — only tripped
@@ -3940,9 +4044,9 @@ async function pollCycle() {
3940
4044
  log(`[poll-backoff] recovered after ${consecutivePollFailures} failure(s), resuming normal interval`);
3941
4045
  consecutivePollFailures = 0;
3942
4046
  }
3943
- send({ type: "state-update", state: state3 });
4047
+ send({ type: "state-update", state: state4 });
3944
4048
  } catch (err) {
3945
- state3.errorCount++;
4049
+ state4.errorCount++;
3946
4050
  const message = err.message;
3947
4051
  log(`Poll error: ${message}`);
3948
4052
  send({ type: "error", message });
@@ -3980,10 +4084,16 @@ async function processAgent(agent, agentStates) {
3980
4084
  agentId: agent.agent_id,
3981
4085
  log
3982
4086
  });
4087
+ void maybeReportTokenUsage({
4088
+ api,
4089
+ codeName: agent.code_name,
4090
+ agentId: agent.agent_id,
4091
+ log
4092
+ });
3983
4093
  }
3984
4094
  const now = (/* @__PURE__ */ new Date()).toISOString();
3985
4095
  const adapter = resolveAgentFramework(agent.code_name);
3986
- let agentDir = join5(adapter.getAgentDir(agent.code_name), "provision");
4096
+ let agentDir = join6(adapter.getAgentDir(agent.code_name), "provision");
3987
4097
  if (agent.status === "draft" || agent.status === "paused") {
3988
4098
  if (previousKnownStatus !== agent.status) {
3989
4099
  log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
@@ -4104,7 +4214,7 @@ async function processAgent(agent, agentStates) {
4104
4214
  });
4105
4215
  } catch (err) {
4106
4216
  log(`Refresh failed for '${agent.code_name}': ${err.message}`);
4107
- const existing = state3.agents.find((a) => a.agentId === agent.agent_id);
4217
+ const existing = state4.agents.find((a) => a.agentId === agent.agent_id);
4108
4218
  agentStates.push(existing ?? {
4109
4219
  agentId: agent.agent_id,
4110
4220
  codeName: agent.code_name,
@@ -4152,7 +4262,7 @@ async function processAgent(agent, agentStates) {
4152
4262
  const frameworkId = refreshData.agent.framework ?? "openclaw";
4153
4263
  agentFrameworkCache.set(agent.code_name, frameworkId);
4154
4264
  const frameworkAdapter = getFramework(frameworkId);
4155
- agentDir = join5(frameworkAdapter.getAgentDir(agent.code_name), "provision");
4265
+ agentDir = join6(frameworkAdapter.getAgentDir(agent.code_name), "provision");
4156
4266
  cacheAgentDeliveryMetadata(agent.code_name, refreshData);
4157
4267
  if (frameworkAdapter.seedProfileConfig) {
4158
4268
  frameworkAdapter.seedProfileConfig(agent.code_name);
@@ -4160,7 +4270,7 @@ async function processAgent(agent, agentStates) {
4160
4270
  const charterVersion = refreshData.charter.version;
4161
4271
  const toolsVersion = refreshData.tools.version;
4162
4272
  const known = knownVersions.get(agent.agent_id);
4163
- let lastProvisionAt = state3.agents.find((a) => a.agentId === agent.agent_id)?.lastProvisionAt ?? null;
4273
+ let lastProvisionAt = state4.agents.find((a) => a.agentId === agent.agent_id)?.lastProvisionAt ?? null;
4164
4274
  const currentChannelIds = launchableChannelIds(refreshData.channel_configs);
4165
4275
  const previousChannelIds = knownChannels.get(agent.agent_id);
4166
4276
  const channelsChanged = !previousChannelIds || currentChannelIds.size !== previousChannelIds.size || [...currentChannelIds].some((ch) => !previousChannelIds.has(ch)) || [...previousChannelIds].some((ch) => !currentChannelIds.has(ch));
@@ -4183,7 +4293,7 @@ async function processAgent(agent, agentStates) {
4183
4293
  const changedFiles = [];
4184
4294
  mkdirSync2(agentDir, { recursive: true });
4185
4295
  for (const artifact of artifacts) {
4186
- const filePath = join5(agentDir, artifact.relativePath);
4296
+ const filePath = join6(agentDir, artifact.relativePath);
4187
4297
  let existingHash;
4188
4298
  let newHash;
4189
4299
  let writeContent = artifact.content;
@@ -4195,8 +4305,8 @@ async function processAgent(agent, agentStates) {
4195
4305
  };
4196
4306
  newHash = sha256(stripDynamicSections(artifact.content));
4197
4307
  try {
4198
- const projectClaudeMd = join5(config.configDir, agent.code_name, "project", "CLAUDE.md");
4199
- const existing = readFileSync4(projectClaudeMd, "utf-8");
4308
+ const projectClaudeMd = join6(config.configDir, agent.code_name, "project", "CLAUDE.md");
4309
+ const existing = readFileSync5(projectClaudeMd, "utf-8");
4200
4310
  existingHash = sha256(stripDynamicSections(existing));
4201
4311
  } catch {
4202
4312
  existingHash = null;
@@ -4214,7 +4324,7 @@ async function processAgent(agent, agentStates) {
4214
4324
  const generatorKeys = Object.keys(generatorServers);
4215
4325
  let existingRaw = "";
4216
4326
  try {
4217
- existingRaw = readFileSync4(filePath, "utf-8");
4327
+ existingRaw = readFileSync5(filePath, "utf-8");
4218
4328
  } catch {
4219
4329
  }
4220
4330
  const existingServers = parseMcp(existingRaw);
@@ -4236,22 +4346,22 @@ async function processAgent(agent, agentStates) {
4236
4346
  }
4237
4347
  }
4238
4348
  if (changedFiles.length > 0) {
4239
- const isFirst = !existsSync4(join5(agentDir, "CHARTER.md"));
4349
+ const isFirst = !existsSync4(join6(agentDir, "CHARTER.md"));
4240
4350
  const verb = isFirst ? "Provisioning" : "Updating";
4241
4351
  const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
4242
4352
  log(`${verb} '${agent.code_name}': ${fileNames}`);
4243
4353
  for (const file of changedFiles) {
4244
- const filePath = join5(agentDir, file.relativePath);
4354
+ const filePath = join6(agentDir, file.relativePath);
4245
4355
  mkdirSync2(dirname(filePath), { recursive: true });
4246
4356
  writeFileSync3(filePath, file.content);
4247
4357
  }
4248
4358
  try {
4249
- const provSkillsDir = join5(agentDir, ".claude", "skills");
4359
+ const provSkillsDir = join6(agentDir, ".claude", "skills");
4250
4360
  if (existsSync4(provSkillsDir)) {
4251
- for (const folder of readdirSync2(provSkillsDir)) {
4361
+ for (const folder of readdirSync3(provSkillsDir)) {
4252
4362
  if (folder.startsWith("knowledge-")) {
4253
4363
  try {
4254
- rmSync2(join5(provSkillsDir, folder), { recursive: true });
4364
+ rmSync2(join6(provSkillsDir, folder), { recursive: true });
4255
4365
  } catch {
4256
4366
  }
4257
4367
  }
@@ -4264,7 +4374,7 @@ async function processAgent(agent, agentStates) {
4264
4374
  const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
4265
4375
  const hashes = /* @__PURE__ */ new Map();
4266
4376
  for (const file of trackedFiles2) {
4267
- const h = hashFile(join5(agentDir, file));
4377
+ const h = hashFile(join6(agentDir, file));
4268
4378
  if (h) hashes.set(file, h);
4269
4379
  }
4270
4380
  writtenHashes.set(agent.agent_id, hashes);
@@ -4311,7 +4421,7 @@ async function processAgent(agent, agentStates) {
4311
4421
  if (written && existsSync4(agentDir)) {
4312
4422
  const driftedFiles = [];
4313
4423
  for (const [file, expectedHash] of written) {
4314
- const localHash = hashFile(join5(agentDir, file));
4424
+ const localHash = hashFile(join6(agentDir, file));
4315
4425
  if (localHash && localHash !== expectedHash) {
4316
4426
  driftedFiles.push(file);
4317
4427
  }
@@ -4322,7 +4432,7 @@ async function processAgent(agent, agentStates) {
4322
4432
  try {
4323
4433
  const localHashes = {};
4324
4434
  for (const file of driftedFiles) {
4325
- localHashes[file] = hashFile(join5(agentDir, file));
4435
+ localHashes[file] = hashFile(join6(agentDir, file));
4326
4436
  }
4327
4437
  await api.post("/host/drift", {
4328
4438
  agent_id: agent.agent_id,
@@ -4480,18 +4590,18 @@ async function processAgent(agent, agentStates) {
4480
4590
  if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? "openclaw") === "claude-code") {
4481
4591
  try {
4482
4592
  const agentProvisionDir = agentDir;
4483
- const projectDir = join5(homedir4(), ".augmented", agent.code_name, "project");
4593
+ const projectDir = join6(homedir4(), ".augmented", agent.code_name, "project");
4484
4594
  mkdirSync2(agentProvisionDir, { recursive: true });
4485
4595
  mkdirSync2(projectDir, { recursive: true });
4486
- const provisionMcpPath = join5(agentProvisionDir, ".mcp.json");
4487
- const projectMcpPath = join5(projectDir, ".mcp.json");
4596
+ const provisionMcpPath = join6(agentProvisionDir, ".mcp.json");
4597
+ const projectMcpPath = join6(projectDir, ".mcp.json");
4488
4598
  let mcpConfig = { mcpServers: {} };
4489
4599
  try {
4490
- mcpConfig = JSON.parse(readFileSync4(provisionMcpPath, "utf-8"));
4600
+ mcpConfig = JSON.parse(readFileSync5(provisionMcpPath, "utf-8"));
4491
4601
  if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
4492
4602
  } catch {
4493
4603
  }
4494
- const localDirectChatChannel = join5(homedir4(), ".augmented", "_mcp", "direct-chat-channel.js");
4604
+ const localDirectChatChannel = join6(homedir4(), ".augmented", "_mcp", "direct-chat-channel.js");
4495
4605
  const directChatTeamSettings = refreshData.team?.settings;
4496
4606
  const directChatTz = (() => {
4497
4607
  const tz = directChatTeamSettings?.["timezone"];
@@ -4513,7 +4623,7 @@ async function processAgent(agent, agentStates) {
4513
4623
  writeFileSync3(projectMcpPath, serialized);
4514
4624
  log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
4515
4625
  }
4516
- const staleChannelsPath = join5(projectDir, ".mcp-channels.json");
4626
+ const staleChannelsPath = join6(projectDir, ".mcp-channels.json");
4517
4627
  if (existsSync4(staleChannelsPath)) {
4518
4628
  try {
4519
4629
  rmSync2(staleChannelsPath, { force: true });
@@ -4524,7 +4634,7 @@ async function processAgent(agent, agentStates) {
4524
4634
  log(`Failed to provision direct-chat channel for '${agent.code_name}': ${err.message}`);
4525
4635
  }
4526
4636
  }
4527
- let lastSecretsProvisionAt = state3.agents.find((a) => a.agentId === agent.agent_id)?.lastSecretsProvisionAt ?? null;
4637
+ let lastSecretsProvisionAt = state4.agents.find((a) => a.agentId === agent.agent_id)?.lastSecretsProvisionAt ?? null;
4528
4638
  let secretsHash = knownSecretsHashes.get(agent.agent_id) ?? null;
4529
4639
  try {
4530
4640
  const secretsData = await api.post("/host/secrets", { agent_id: agent.agent_id });
@@ -4580,11 +4690,11 @@ async function processAgent(agent, agentStates) {
4580
4690
  const intHash = computeIntegrationsHash(integrations);
4581
4691
  const prevIntHash = knownIntegrationHashes.get(agent.agent_id);
4582
4692
  if (intHash !== prevIntHash) {
4583
- const projectDir = join5(homedir4(), ".augmented", agent.code_name, "project");
4584
- const envIntPath = join5(projectDir, ".env.integrations");
4693
+ const projectDir = join6(homedir4(), ".augmented", agent.code_name, "project");
4694
+ const envIntPath = join6(projectDir, ".env.integrations");
4585
4695
  let preWriteEnv;
4586
4696
  try {
4587
- preWriteEnv = readFileSync4(envIntPath, "utf-8");
4697
+ preWriteEnv = readFileSync5(envIntPath, "utf-8");
4588
4698
  } catch {
4589
4699
  preWriteEnv = void 0;
4590
4700
  }
@@ -4596,9 +4706,9 @@ async function processAgent(agent, agentStates) {
4596
4706
  let rotationHandled = true;
4597
4707
  if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
4598
4708
  try {
4599
- const projectMcpPath = join5(projectDir, ".mcp.json");
4600
- const postWriteEnv = readFileSync4(envIntPath, "utf-8");
4601
- const mcpContent = readFileSync4(projectMcpPath, "utf-8");
4709
+ const projectMcpPath = join6(projectDir, ".mcp.json");
4710
+ const postWriteEnv = readFileSync5(envIntPath, "utf-8");
4711
+ const mcpContent = readFileSync5(projectMcpPath, "utf-8");
4602
4712
  const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
4603
4713
  const mcpJsonForReap = JSON.parse(mcpContent);
4604
4714
  const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
@@ -4664,8 +4774,8 @@ async function processAgent(agent, agentStates) {
4664
4774
  const mcpPath = frameworkAdapter.getMcpPath(agent.code_name);
4665
4775
  if (mcpPath) {
4666
4776
  try {
4667
- const { readFileSync: readFileSync5 } = await import("fs");
4668
- const mcpConfig = JSON.parse(readFileSync5(mcpPath, "utf-8"));
4777
+ const { readFileSync: readFileSync6 } = await import("fs");
4778
+ const mcpConfig = JSON.parse(readFileSync6(mcpPath, "utf-8"));
4669
4779
  if (mcpConfig.mcpServers) {
4670
4780
  const managedPrefixes = [
4671
4781
  "composio_",
@@ -4754,7 +4864,7 @@ async function processAgent(agent, agentStates) {
4754
4864
  if (agent.status === "active") {
4755
4865
  if (frameworkAdapter.installPlugin) {
4756
4866
  try {
4757
- const pluginPath = join5(process.cwd(), "packages", "openclaw-plugin-augmented", "src", "index.ts");
4867
+ const pluginPath = join6(process.cwd(), "packages", "openclaw-plugin-augmented", "src", "index.ts");
4758
4868
  if (existsSync4(pluginPath)) {
4759
4869
  frameworkAdapter.installPlugin(agent.code_name, "augmented", pluginPath, {
4760
4870
  agtHost: requireHost(),
@@ -4820,25 +4930,25 @@ async function processAgent(agent, agentStates) {
4820
4930
  }
4821
4931
  }
4822
4932
  try {
4823
- const { readdirSync: readdirSync3, rmSync: rmSync3 } = await import("fs");
4933
+ const { readdirSync: readdirSync4, rmSync: rmSync3 } = await import("fs");
4824
4934
  const { homedir: homedir5 } = await import("os");
4825
4935
  const frameworkId2 = frameworkAdapter.id;
4826
4936
  const candidateSkillDirs = [
4827
4937
  // Claude Code — framework runtime tree
4828
- join5(homedir5(), ".augmented", agent.code_name, "skills"),
4938
+ join6(homedir5(), ".augmented", agent.code_name, "skills"),
4829
4939
  // Claude Code — project tree
4830
- join5(homedir5(), ".augmented", agent.code_name, "project", ".claude", "skills"),
4940
+ join6(homedir5(), ".augmented", agent.code_name, "project", ".claude", "skills"),
4831
4941
  // OpenClaw — framework runtime tree
4832
- join5(homedir5(), `.openclaw-${agent.code_name}`, "skills"),
4942
+ join6(homedir5(), `.openclaw-${agent.code_name}`, "skills"),
4833
4943
  // Defensive: legacy provision-side path, not currently an
4834
4944
  // install target but cheap to sweep.
4835
- join5(agentDir, ".claude", "skills")
4945
+ join6(agentDir, ".claude", "skills")
4836
4946
  ];
4837
4947
  const existingDirs = candidateSkillDirs.filter((d) => existsSync4(d));
4838
4948
  const discoveredEntries = /* @__PURE__ */ new Set();
4839
4949
  for (const dir of existingDirs) {
4840
4950
  try {
4841
- for (const entry of readdirSync3(dir)) {
4951
+ for (const entry of readdirSync4(dir)) {
4842
4952
  if (entry.startsWith("plugin-") || entry.startsWith("integration-")) {
4843
4953
  discoveredEntries.add(entry);
4844
4954
  }
@@ -4848,7 +4958,7 @@ async function processAgent(agent, agentStates) {
4848
4958
  }
4849
4959
  const removeSkillFolder = (entry, reason) => {
4850
4960
  for (const dir of existingDirs) {
4851
- const p = join5(dir, entry);
4961
+ const p = join6(dir, entry);
4852
4962
  if (existsSync4(p)) {
4853
4963
  rmSync3(p, { recursive: true, force: true });
4854
4964
  }
@@ -5009,8 +5119,8 @@ async function processAgent(agent, agentStates) {
5009
5119
  const sess = getSessionState(agent.code_name);
5010
5120
  let mcpJsonParsed = null;
5011
5121
  try {
5012
- const mcpPath = join5(getProjectDir(agent.code_name), ".mcp.json");
5013
- mcpJsonParsed = JSON.parse(readFileSync4(mcpPath, "utf-8"));
5122
+ const mcpPath = join6(getProjectDir(agent.code_name), ".mcp.json");
5123
+ mcpJsonParsed = JSON.parse(readFileSync5(mcpPath, "utf-8"));
5014
5124
  } catch {
5015
5125
  }
5016
5126
  reapMissingMcpSessions({
@@ -5159,10 +5269,10 @@ async function processAgent(agent, agentStates) {
5159
5269
  lastWorkTriggerAt.set(agent.code_name, triggerTs);
5160
5270
  if (agentFw === "openclaw" && gatewayRunning && gatewayPort) {
5161
5271
  const homeDir = process.env["HOME"] ?? "/tmp";
5162
- const jobsPath = join5(homeDir, `.openclaw-${agent.code_name}`, "cron", "jobs.json");
5272
+ const jobsPath = join6(homeDir, `.openclaw-${agent.code_name}`, "cron", "jobs.json");
5163
5273
  if (existsSync4(jobsPath)) {
5164
5274
  try {
5165
- const jobsData = JSON.parse(readFileSync4(jobsPath, "utf-8"));
5275
+ const jobsData = JSON.parse(readFileSync5(jobsPath, "utf-8"));
5166
5276
  const kanbanJob = (jobsData.jobs ?? []).find(
5167
5277
  (j) => typeof j.name === "string" && j.name.includes("kanban-work")
5168
5278
  );
@@ -5306,7 +5416,7 @@ In progress for ${age} minutes \u2014 auto-failed`).catch(() => {
5306
5416
  if (trackedFiles.length > 0 && existsSync4(agentDir)) {
5307
5417
  const hashes = /* @__PURE__ */ new Map();
5308
5418
  for (const file of trackedFiles) {
5309
- const h = hashFile(join5(agentDir, file));
5419
+ const h = hashFile(join6(agentDir, file));
5310
5420
  if (h) hashes.set(file, h);
5311
5421
  }
5312
5422
  writtenHashes.set(agent.agent_id, hashes);
@@ -5340,19 +5450,19 @@ function cleanupStaleSessions(codeName) {
5340
5450
  lastCleanupAt.set(codeName, Date.now());
5341
5451
  const homeDir = process.env["HOME"] ?? "/tmp";
5342
5452
  for (const agentDir of ["main", codeName]) {
5343
- const sessionsDir = join5(homeDir, `.openclaw-${codeName}`, "agents", agentDir, "sessions");
5453
+ const sessionsDir = join6(homeDir, `.openclaw-${codeName}`, "agents", agentDir, "sessions");
5344
5454
  cleanupCronSessions(sessionsDir, CRON_SESSION_KEEP_COUNT);
5345
5455
  }
5346
- const cronRunsDir = join5(homeDir, `.openclaw-${codeName}`, "cron", "runs");
5456
+ const cronRunsDir = join6(homeDir, `.openclaw-${codeName}`, "cron", "runs");
5347
5457
  cleanupOldFiles(cronRunsDir, CRON_RUN_RETENTION_DAYS, ".jsonl");
5348
- const cronJobsPath = join5(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
5458
+ const cronJobsPath = join6(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
5349
5459
  clearStaleCronRunState(cronJobsPath);
5350
5460
  }
5351
5461
  function cleanupCronSessions(sessionsDir, keepCount) {
5352
- const indexPath = join5(sessionsDir, "sessions.json");
5462
+ const indexPath = join6(sessionsDir, "sessions.json");
5353
5463
  if (!existsSync4(indexPath)) return;
5354
5464
  try {
5355
- const raw = readFileSync4(indexPath, "utf-8");
5465
+ const raw = readFileSync5(indexPath, "utf-8");
5356
5466
  const index = JSON.parse(raw);
5357
5467
  const cronRunKeys = Object.keys(index).filter((k) => k.includes(":cron:") && k.includes(":run:")).map((k) => ({
5358
5468
  key: k,
@@ -5365,7 +5475,7 @@ function cleanupCronSessions(sessionsDir, keepCount) {
5365
5475
  for (const entry of toDelete) {
5366
5476
  delete index[entry.key];
5367
5477
  if (entry.sessionId) {
5368
- const sessionFile = join5(sessionsDir, `${entry.sessionId}.jsonl`);
5478
+ const sessionFile = join6(sessionsDir, `${entry.sessionId}.jsonl`);
5369
5479
  try {
5370
5480
  if (existsSync4(sessionFile)) {
5371
5481
  unlinkSync(sessionFile);
@@ -5387,7 +5497,7 @@ function cleanupCronSessions(sessionsDir, keepCount) {
5387
5497
  delete index[parentKey];
5388
5498
  if (parentSessionId) {
5389
5499
  try {
5390
- const f = join5(sessionsDir, `${parentSessionId}.jsonl`);
5500
+ const f = join6(sessionsDir, `${parentSessionId}.jsonl`);
5391
5501
  if (existsSync4(f)) {
5392
5502
  unlinkSync(f);
5393
5503
  deletedFiles++;
@@ -5408,26 +5518,26 @@ var STALE_RUN_TIMEOUT_MS = 5 * 6e4;
5408
5518
  function clearStaleCronRunState(jobsPath) {
5409
5519
  if (!existsSync4(jobsPath)) return;
5410
5520
  try {
5411
- const raw = readFileSync4(jobsPath, "utf-8");
5521
+ const raw = readFileSync5(jobsPath, "utf-8");
5412
5522
  const data = JSON.parse(raw);
5413
5523
  const jobs = data.jobs ?? data;
5414
5524
  if (!Array.isArray(jobs)) return;
5415
5525
  let changed = false;
5416
5526
  const now = Date.now();
5417
5527
  for (const job of jobs) {
5418
- const state4 = job.state;
5419
- if (!state4) continue;
5420
- const runStartedAt = state4.runningAtMs ?? state4.runStartedAtMs;
5421
- const isRunning = state4.running === true || state4.status === "running";
5528
+ const state5 = job.state;
5529
+ if (!state5) continue;
5530
+ const runStartedAt = state5.runningAtMs ?? state5.runStartedAtMs;
5531
+ const isRunning = state5.running === true || state5.status === "running";
5422
5532
  if (isRunning && runStartedAt && now - runStartedAt > STALE_RUN_TIMEOUT_MS) {
5423
- state4.running = false;
5424
- delete state4.status;
5425
- delete state4.runStartedAtMs;
5426
- delete state4.currentRunId;
5533
+ state5.running = false;
5534
+ delete state5.status;
5535
+ delete state5.runStartedAtMs;
5536
+ delete state5.currentRunId;
5427
5537
  changed = true;
5428
5538
  log(`Cleared stale running state for cron job '${job.name}' (stuck for ${Math.round((now - runStartedAt) / 6e4)}min)`);
5429
5539
  } else if (isRunning && !runStartedAt) {
5430
- state4.running = false;
5540
+ state5.running = false;
5431
5541
  changed = true;
5432
5542
  log(`Cleared stale running state for cron job '${job.name}' (no start timestamp)`);
5433
5543
  }
@@ -5443,11 +5553,11 @@ function cleanupOldFiles(dir, maxAgeDays, ext) {
5443
5553
  const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3;
5444
5554
  let removed = 0;
5445
5555
  try {
5446
- for (const f of readdirSync2(dir)) {
5556
+ for (const f of readdirSync3(dir)) {
5447
5557
  if (!f.endsWith(ext)) continue;
5448
- const fullPath = join5(dir, f);
5558
+ const fullPath = join6(dir, f);
5449
5559
  try {
5450
- const st = statSync(fullPath);
5560
+ const st = statSync2(fullPath);
5451
5561
  if (st.mtimeMs < cutoff) {
5452
5562
  unlinkSync(fullPath);
5453
5563
  removed++;
@@ -5491,16 +5601,16 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
5491
5601
  enabled: t.enabled ?? true,
5492
5602
  triggered_at: t.triggered_at ?? null
5493
5603
  }));
5494
- const state5 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
5495
- claudeSchedulerStates.set(codeName, state5);
5604
+ const state6 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
5605
+ claudeSchedulerStates.set(codeName, state6);
5496
5606
  knownTasksHashes.set(agent.agent_id, combinedHash);
5497
5607
  log(`[claude-scheduler] Tasks synced for '${codeName}' (${taskInputs.length} task(s))`);
5498
5608
  }
5499
5609
  if (!claudeSchedulerStates.has(codeName)) {
5500
5610
  claudeSchedulerStates.set(codeName, loadSchedulerState(codeName));
5501
5611
  }
5502
- const state4 = claudeSchedulerStates.get(codeName);
5503
- const ready = getReadyTasks(state4, inFlightClaudeTasks);
5612
+ const state5 = claudeSchedulerStates.get(codeName);
5613
+ const ready = getReadyTasks(state5, inFlightClaudeTasks);
5504
5614
  if (ready.length === 0) return;
5505
5615
  for (const task of ready) {
5506
5616
  if ((claudeTaskConcurrency.get(codeName) ?? 0) >= MAX_CLAUDE_CONCURRENCY) break;
@@ -5589,7 +5699,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
5589
5699
  }
5590
5700
  async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
5591
5701
  const projectDir = getProjectDir2(codeName);
5592
- const mcpConfigPath = join5(projectDir, ".mcp.json");
5702
+ const mcpConfigPath = join6(projectDir, ".mcp.json");
5593
5703
  let runId = null;
5594
5704
  let kanbanItemId = null;
5595
5705
  let taskResult;
@@ -5597,11 +5707,11 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
5597
5707
  const priorRuns = await fetchPriorScheduledRuns(agentId, task.taskId);
5598
5708
  prompt = wrapScheduledTaskPrompt(prompt, { priorRuns });
5599
5709
  try {
5600
- const claudeMdPath = join5(projectDir, "CLAUDE.md");
5710
+ const claudeMdPath = join6(projectDir, "CLAUDE.md");
5601
5711
  const serverNames = [];
5602
5712
  if (existsSync4(mcpConfigPath)) {
5603
5713
  try {
5604
- const d = JSON.parse(readFileSync4(mcpConfigPath, "utf-8"));
5714
+ const d = JSON.parse(readFileSync5(mcpConfigPath, "utf-8"));
5605
5715
  if (d.mcpServers) serverNames.push(...Object.keys(d.mcpServers));
5606
5716
  } catch {
5607
5717
  }
@@ -5624,10 +5734,10 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
5624
5734
  claudeArgs.push("--system-prompt-file", claudeMdPath);
5625
5735
  }
5626
5736
  const childEnv = { ...process.env };
5627
- const envIntPath = join5(projectDir, ".env.integrations");
5737
+ const envIntPath = join6(projectDir, ".env.integrations");
5628
5738
  if (existsSync4(envIntPath)) {
5629
5739
  try {
5630
- for (const line of readFileSync4(envIntPath, "utf-8").split("\n")) {
5740
+ for (const line of readFileSync5(envIntPath, "utf-8").split("\n")) {
5631
5741
  if (!line || line.startsWith("#") || !line.includes("=")) continue;
5632
5742
  const eqIdx = line.indexOf("=");
5633
5743
  childEnv[line.slice(0, eqIdx)] = line.slice(eqIdx + 1);
@@ -5781,8 +5891,8 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
5781
5891
  }
5782
5892
  }
5783
5893
  function fireClaudeWorkTrigger(codeName, agentId, boardItems) {
5784
- const state4 = claudeSchedulerStates.get(codeName) ?? loadSchedulerState(codeName);
5785
- const kanbanTask = findTaskByTemplate(state4, "kanban-work");
5894
+ const state5 = claudeSchedulerStates.get(codeName) ?? loadSchedulerState(codeName);
5895
+ const kanbanTask = findTaskByTemplate(state5, "kanban-work");
5786
5896
  if (!kanbanTask) {
5787
5897
  log(`[claude-scheduler] Work trigger: no kanban-work task found for '${codeName}'`);
5788
5898
  return;
@@ -5811,8 +5921,8 @@ var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
5811
5921
  async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
5812
5922
  const codeName = agent.code_name;
5813
5923
  const projectDir = getProjectDir(codeName);
5814
- const mcpConfigPath = join5(projectDir, ".mcp.json");
5815
- const claudeMdPath = join5(projectDir, "CLAUDE.md");
5924
+ const mcpConfigPath = join6(projectDir, ".mcp.json");
5925
+ const claudeMdPath = join6(projectDir, "CLAUDE.md");
5816
5926
  if (restartBreaker.isTripped(codeName)) {
5817
5927
  const trip = restartBreaker.getTrip(codeName);
5818
5928
  return {
@@ -6049,9 +6159,9 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash2("sha256").
6049
6159
  } else if (!claudeSchedulerStates.has(codeName)) {
6050
6160
  claudeSchedulerStates.set(codeName, loadSchedulerState(codeName));
6051
6161
  }
6052
- const state4 = claudeSchedulerStates.get(codeName);
6053
- if (state4) {
6054
- const ready = getReadyTasks(state4, inFlightClaudeTasks);
6162
+ const state5 = claudeSchedulerStates.get(codeName);
6163
+ if (state5) {
6164
+ const ready = getReadyTasks(state5, inFlightClaudeTasks);
6055
6165
  if (ready.length > 0) {
6056
6166
  log(`[persistent-session] ${ready.length} ready task(s) for '${codeName}': ${ready.map((t) => `${t.name}(next=${t.nextFireAt ? new Date(t.nextFireAt).toISOString() : "null"})`).join(", ")}`);
6057
6167
  }
@@ -6430,11 +6540,11 @@ ${escapeXml(msg.content)}
6430
6540
  if (fw === "claude-code") {
6431
6541
  const { getProjectDir: ccProjectDir } = await import("../claude-scheduler-XHJS2MZV.js");
6432
6542
  const projDir = ccProjectDir(agent.codeName);
6433
- const mcpConfigPath = join5(projDir, ".mcp.json");
6543
+ const mcpConfigPath = join6(projDir, ".mcp.json");
6434
6544
  const serverNames = [];
6435
6545
  if (existsSync4(mcpConfigPath)) {
6436
6546
  try {
6437
- const d = JSON.parse(readFileSync4(mcpConfigPath, "utf-8"));
6547
+ const d = JSON.parse(readFileSync5(mcpConfigPath, "utf-8"));
6438
6548
  if (d.mcpServers) serverNames.push(...Object.keys(d.mcpServers));
6439
6549
  } catch {
6440
6550
  }
@@ -6453,15 +6563,15 @@ ${escapeXml(msg.content)}
6453
6563
  "--allowedTools",
6454
6564
  allowedTools
6455
6565
  ];
6456
- const chatClaudeMd = join5(projDir, "CLAUDE.md");
6566
+ const chatClaudeMd = join6(projDir, "CLAUDE.md");
6457
6567
  if (existsSync4(chatClaudeMd)) {
6458
6568
  chatArgs.push("--system-prompt-file", chatClaudeMd);
6459
6569
  }
6460
- const envIntPath = join5(projDir, ".env.integrations");
6570
+ const envIntPath = join6(projDir, ".env.integrations");
6461
6571
  const childEnv = { ...process.env };
6462
6572
  if (existsSync4(envIntPath)) {
6463
6573
  try {
6464
- for (const line of readFileSync4(envIntPath, "utf-8").split("\n")) {
6574
+ for (const line of readFileSync5(envIntPath, "utf-8").split("\n")) {
6465
6575
  if (!line || line.startsWith("#") || !line.includes("=")) continue;
6466
6576
  const eqIdx = line.indexOf("=");
6467
6577
  childEnv[line.slice(0, eqIdx)] = line.slice(eqIdx + 1);
@@ -6804,12 +6914,12 @@ function getBuiltInSkillContent(skillId) {
6804
6914
  if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
6805
6915
  try {
6806
6916
  const candidates = [
6807
- join5(process.cwd(), "skills", skillId, "SKILL.md"),
6808
- join5(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "skills", skillId, "SKILL.md")
6917
+ join6(process.cwd(), "skills", skillId, "SKILL.md"),
6918
+ join6(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "skills", skillId, "SKILL.md")
6809
6919
  ];
6810
6920
  for (const candidate of candidates) {
6811
6921
  if (existsSync4(candidate)) {
6812
- const content = readFileSync4(candidate, "utf-8");
6922
+ const content = readFileSync5(candidate, "utf-8");
6813
6923
  const files = [{ relativePath: "SKILL.md", content }];
6814
6924
  builtInSkillCache.set(skillId, files);
6815
6925
  return files;
@@ -7422,7 +7532,7 @@ async function processClaudePairSessions(agents) {
7422
7532
  killPairSession,
7423
7533
  pairTmuxSession,
7424
7534
  finalizeClaudePairOnboarding
7425
- } = await import("../claude-pair-runtime-XCFWTH6T.js");
7535
+ } = await import("../claude-pair-runtime-ZQAJOQPN.js");
7426
7536
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
7427
7537
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
7428
7538
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -7717,8 +7827,8 @@ function parseMemoryFile(raw, fallbackName) {
7717
7827
  };
7718
7828
  }
7719
7829
  async function syncMemories(agent, configDir, log2) {
7720
- const projectDir = join5(configDir, agent.code_name, "project");
7721
- const memoryDir = join5(projectDir, "memory");
7830
+ const projectDir = join6(configDir, agent.code_name, "project");
7831
+ const memoryDir = join6(projectDir, "memory");
7722
7832
  const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
7723
7833
  if (isFreshSync) {
7724
7834
  log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
@@ -7733,10 +7843,10 @@ async function syncMemories(agent, configDir, log2) {
7733
7843
  const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
7734
7844
  const currentHashes = /* @__PURE__ */ new Map();
7735
7845
  const changedMemories = [];
7736
- for (const file of readdirSync2(memoryDir)) {
7846
+ for (const file of readdirSync3(memoryDir)) {
7737
7847
  if (!file.endsWith(".md")) continue;
7738
7848
  try {
7739
- const raw = readFileSync4(join5(memoryDir, file), "utf-8");
7849
+ const raw = readFileSync5(join6(memoryDir, file), "utf-8");
7740
7850
  const fileHash = createHash2("sha256").update(raw).digest("hex").slice(0, 16);
7741
7851
  currentHashes.set(file, fileHash);
7742
7852
  if (prevHashes.get(file) === fileHash) continue;
@@ -7761,7 +7871,7 @@ async function syncMemories(agent, configDir, log2) {
7761
7871
  } catch (err) {
7762
7872
  for (const mem of changedMemories) {
7763
7873
  for (const [file] of currentHashes) {
7764
- const parsed = parseMemoryFile(readFileSync4(join5(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
7874
+ const parsed = parseMemoryFile(readFileSync5(join6(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
7765
7875
  if (parsed?.name === mem.name) currentHashes.delete(file);
7766
7876
  }
7767
7877
  }
@@ -7774,7 +7884,7 @@ async function syncMemories(agent, configDir, log2) {
7774
7884
  }
7775
7885
  }
7776
7886
  async function downloadMemories(agent, memoryDir, log2, { force }) {
7777
- const localFiles = existsSync4(memoryDir) ? readdirSync2(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
7887
+ const localFiles = existsSync4(memoryDir) ? readdirSync3(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
7778
7888
  const localListHash = createHash2("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
7779
7889
  const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
7780
7890
  const prevDownload = lastDownloadHash.get(agent.agent_id);
@@ -7796,7 +7906,7 @@ async function downloadMemories(agent, memoryDir, log2, { force }) {
7796
7906
  const mem = dbMemories.memories[i];
7797
7907
  const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
7798
7908
  const slug = rawSlug || `memory-${i}`;
7799
- const filePath = join5(memoryDir, `${slug}.md`);
7909
+ const filePath = join6(memoryDir, `${slug}.md`);
7800
7910
  const desired = `---
7801
7911
  name: ${JSON.stringify(mem.name)}
7802
7912
  type: ${mem.type}
@@ -7808,7 +7918,7 @@ ${mem.content}
7808
7918
  if (existsSync4(filePath)) {
7809
7919
  let existing = "";
7810
7920
  try {
7811
- existing = readFileSync4(filePath, "utf-8");
7921
+ existing = readFileSync5(filePath, "utf-8");
7812
7922
  } catch {
7813
7923
  }
7814
7924
  if (existing === desired) continue;
@@ -7820,7 +7930,7 @@ ${mem.content}
7820
7930
  }
7821
7931
  }
7822
7932
  if (written > 0 || overwritten > 0) {
7823
- const updatedFiles = readdirSync2(memoryDir).filter((f) => f.endsWith(".md")).sort();
7933
+ const updatedFiles = readdirSync3(memoryDir).filter((f) => f.endsWith(".md")).sort();
7824
7934
  lastLocalFileHash.set(agent.agent_id, createHash2("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
7825
7935
  log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
7826
7936
  }
@@ -8004,11 +8114,11 @@ function startManager(opts) {
8004
8114
  try {
8005
8115
  const stateFile = getStateFile();
8006
8116
  if (existsSync4(stateFile)) {
8007
- const raw = readFileSync4(stateFile, "utf-8");
8117
+ const raw = readFileSync5(stateFile, "utf-8");
8008
8118
  const parsed = JSON.parse(raw);
8009
8119
  if (Array.isArray(parsed.agents)) {
8010
- state3.agents = parsed.agents;
8011
- log(`[startup] rehydrated ${state3.agents.length} agent state(s) from ${stateFile}`);
8120
+ state4.agents = parsed.agents;
8121
+ log(`[startup] rehydrated ${state4.agents.length} agent state(s) from ${stateFile}`);
8012
8122
  }
8013
8123
  if (parsed.circuitBreakerTrips && typeof parsed.circuitBreakerTrips === "object") {
8014
8124
  restartBreaker.hydrate(parsed.circuitBreakerTrips);
@@ -8020,7 +8130,7 @@ function startManager(opts) {
8020
8130
  log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
8021
8131
  }
8022
8132
  log(
8023
- `[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join5(homedir4(), ".augmented", "manager.log")}`
8133
+ `[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join6(homedir4(), ".augmented", "manager.log")}`
8024
8134
  );
8025
8135
  warnOnConflictingKanbanModes();
8026
8136
  deployMcpAssets();
@@ -8083,14 +8193,14 @@ function restartRunningChannelMcps(basenames) {
8083
8193
  }
8084
8194
  }
8085
8195
  function deployMcpAssets() {
8086
- const targetDir = join5(homedir4(), ".augmented", "_mcp");
8196
+ const targetDir = join6(homedir4(), ".augmented", "_mcp");
8087
8197
  mkdirSync2(targetDir, { recursive: true });
8088
8198
  const moduleDir = dirname(fileURLToPath(import.meta.url));
8089
8199
  let mcpSourceDir = "";
8090
8200
  let dir = moduleDir;
8091
8201
  for (let i = 0; i < 6; i++) {
8092
- const candidate = join5(dir, "dist", "mcp");
8093
- if (existsSync4(join5(candidate, "index.js"))) {
8202
+ const candidate = join6(dir, "dist", "mcp");
8203
+ if (existsSync4(join6(candidate, "index.js"))) {
8094
8204
  mcpSourceDir = candidate;
8095
8205
  break;
8096
8206
  }
@@ -8106,7 +8216,7 @@ function deployMcpAssets() {
8106
8216
  const fileHash = (p) => {
8107
8217
  try {
8108
8218
  if (!existsSync4(p)) return null;
8109
- return createHash2("sha256").update(readFileSync4(p)).digest("hex");
8219
+ return createHash2("sha256").update(readFileSync5(p)).digest("hex");
8110
8220
  } catch {
8111
8221
  return null;
8112
8222
  }
@@ -8117,8 +8227,8 @@ function deployMcpAssets() {
8117
8227
  "telegram-channel.js"
8118
8228
  ]);
8119
8229
  for (const file of ["index.js", "slack-channel.js", "direct-chat-channel.js", "telegram-channel.js"]) {
8120
- const src = join5(mcpSourceDir, file);
8121
- const dst = join5(targetDir, file);
8230
+ const src = join6(mcpSourceDir, file);
8231
+ const dst = join6(targetDir, file);
8122
8232
  if (!existsSync4(src)) continue;
8123
8233
  const before = fileHash(dst);
8124
8234
  try {
@@ -8136,16 +8246,16 @@ function deployMcpAssets() {
8136
8246
  log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
8137
8247
  restartRunningChannelMcps(changedBasenames);
8138
8248
  }
8139
- const localMcpPath = join5(targetDir, "index.js");
8249
+ const localMcpPath = join6(targetDir, "index.js");
8140
8250
  try {
8141
- const agentsDir = join5(homedir4(), ".augmented", "agents");
8251
+ const agentsDir = join6(homedir4(), ".augmented", "agents");
8142
8252
  if (existsSync4(agentsDir)) {
8143
- for (const entry of readdirSync2(agentsDir, { withFileTypes: true })) {
8253
+ for (const entry of readdirSync3(agentsDir, { withFileTypes: true })) {
8144
8254
  if (!entry.isDirectory()) continue;
8145
8255
  for (const subdir of ["provision", "project"]) {
8146
- const mcpJsonPath = join5(agentsDir, entry.name, subdir, ".mcp.json");
8256
+ const mcpJsonPath = join6(agentsDir, entry.name, subdir, ".mcp.json");
8147
8257
  try {
8148
- const raw = readFileSync4(mcpJsonPath, "utf-8");
8258
+ const raw = readFileSync5(mcpJsonPath, "utf-8");
8149
8259
  if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
8150
8260
  const mcpConfig = JSON.parse(raw);
8151
8261
  const augServer = mcpConfig.mcpServers?.["augmented"];