@integrity-labs/agt-cli 0.24.0 → 0.24.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,7 @@ import {
12
12
  provisionOrientHook,
13
13
  provisionStopHook,
14
14
  requireHost
15
- } from "../chunk-WZTRMJM4.js";
15
+ } from "../chunk-BXLWLI2U.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,110 @@ 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
+ for (let i = 0; i < pending.length; i += MAX_ENTRIES_PER_POST) {
794
+ const batch = pending.slice(i, i + MAX_ENTRIES_PER_POST);
795
+ try {
796
+ await api2.post("/host/token-usage", {
797
+ agent_id: agentId,
798
+ framework: "claude-code",
799
+ source: "transcript_jsonl",
800
+ entries: batch.map((b) => b.entry)
801
+ });
802
+ for (const b of batch) {
803
+ files.set(b.sessionId, b.fp);
804
+ }
805
+ } catch (err) {
806
+ log2(`[token-usage] POST failed for '${codeName}': ${err.message}`);
807
+ }
808
+ }
809
+ state2.set(codeName, next);
810
+ }
811
+
812
+ // src/lib/activity-cache-monitor.ts
813
+ import { existsSync, readFileSync as readFileSync2 } from "fs";
814
+ import { homedir } from "os";
815
+ import { join as join2 } from "path";
816
+ var MIN_CHECK_INTERVAL_MS3 = 6e4;
817
+ var STATS_CACHE_PATH = join2(homedir(), ".claude", "stats-cache.json");
719
818
  var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
720
- var state2 = { lastObservedDate: null, lastCheckedAt: 0 };
819
+ var state3 = { lastObservedDate: null, lastCheckedAt: 0 };
721
820
  function selectNewDailyRows(raw, lastObservedDate) {
722
821
  let parsed;
723
822
  try {
@@ -756,24 +855,24 @@ async function maybeReportActivityCache(args) {
756
855
  const { api: api2, log: log2 } = args;
757
856
  const now = args.now ?? /* @__PURE__ */ new Date();
758
857
  const nowMs = now.getTime();
759
- if (nowMs - state2.lastCheckedAt < MIN_CHECK_INTERVAL_MS2) return;
760
- state2.lastCheckedAt = nowMs;
858
+ if (nowMs - state3.lastCheckedAt < MIN_CHECK_INTERVAL_MS3) return;
859
+ state3.lastCheckedAt = nowMs;
761
860
  if (!existsSync(STATS_CACHE_PATH)) {
762
861
  return;
763
862
  }
764
863
  let raw;
765
864
  try {
766
- raw = readFileSync(STATS_CACHE_PATH, "utf-8");
865
+ raw = readFileSync2(STATS_CACHE_PATH, "utf-8");
767
866
  } catch (err) {
768
867
  log2(`[activity-cache] readFileSync failed: ${err.message}`);
769
868
  return;
770
869
  }
771
- const rows = selectNewDailyRows(raw, state2.lastObservedDate);
870
+ const rows = selectNewDailyRows(raw, state3.lastObservedDate);
772
871
  if (rows.length === 0) return;
773
872
  for (const row of rows) {
774
873
  try {
775
874
  await api2.post("/host/activity-observations", row);
776
- state2.lastObservedDate = row.date;
875
+ state3.lastObservedDate = row.date;
777
876
  } catch (err) {
778
877
  log2(
779
878
  `[activity-cache] POST /host/activity-observations failed for date=${row.date}: ${err.message}`
@@ -1213,7 +1312,7 @@ var GatewayClientPool = class extends EventEmitter {
1213
1312
  // src/lib/claude-auth-detect.ts
1214
1313
  import { readFile, readdir } from "fs/promises";
1215
1314
  import { homedir as homedir2, platform } from "os";
1216
- import { join as join2 } from "path";
1315
+ import { join as join3 } from "path";
1217
1316
  import { execFile } from "child_process";
1218
1317
  import { promisify } from "util";
1219
1318
  var execFileAsync = promisify(execFile);
@@ -1228,8 +1327,8 @@ async function detectClaudeAuth() {
1228
1327
  }
1229
1328
  async function findClaudeCredentialsPaths() {
1230
1329
  const candidates = [
1231
- join2(homedir2(), ".claude", ".credentials.json"),
1232
- join2(homedir2(), ".claude", "credentials.json")
1330
+ join3(homedir2(), ".claude", ".credentials.json"),
1331
+ join3(homedir2(), ".claude", "credentials.json")
1233
1332
  ];
1234
1333
  const isLinuxRoot = platform() === "linux" && typeof process.getuid === "function" && process.getuid() === 0;
1235
1334
  if (isLinuxRoot) {
@@ -1237,8 +1336,8 @@ async function findClaudeCredentialsPaths() {
1237
1336
  const entries = await readdir("/home", { withFileTypes: true });
1238
1337
  for (const entry of entries) {
1239
1338
  if (!entry.isDirectory()) continue;
1240
- candidates.push(join2("/home", entry.name, ".claude", ".credentials.json"));
1241
- candidates.push(join2("/home", entry.name, ".claude", "credentials.json"));
1339
+ candidates.push(join3("/home", entry.name, ".claude", ".credentials.json"));
1340
+ candidates.push(join3("/home", entry.name, ".claude", "credentials.json"));
1242
1341
  }
1243
1342
  } catch {
1244
1343
  }
@@ -1330,18 +1429,18 @@ function normalize(value) {
1330
1429
  }
1331
1430
 
1332
1431
  // src/lib/channel-hash-cache.ts
1333
- import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
1334
- import { join as join3 } from "path";
1432
+ import { existsSync as existsSync2, readFileSync as readFileSync3, writeFileSync } from "fs";
1433
+ import { join as join4 } from "path";
1335
1434
  var CACHE_FILENAME = "channel-hash-cache.json";
1336
1435
  function getChannelHashCacheFile(configDir) {
1337
- return join3(configDir, CACHE_FILENAME);
1436
+ return join4(configDir, CACHE_FILENAME);
1338
1437
  }
1339
1438
  function loadChannelHashCache(target, configDir) {
1340
1439
  const path = getChannelHashCacheFile(configDir);
1341
1440
  if (!existsSync2(path)) return;
1342
1441
  let parsed;
1343
1442
  try {
1344
- parsed = JSON.parse(readFileSync2(path, "utf-8"));
1443
+ parsed = JSON.parse(readFileSync3(path, "utf-8"));
1345
1444
  } catch {
1346
1445
  return;
1347
1446
  }
@@ -1814,24 +1913,24 @@ function withScheduleLinkFooter(opts) {
1814
1913
  }
1815
1914
 
1816
1915
  // src/lib/restart-flags.ts
1817
- import { existsSync as existsSync3, mkdirSync, readdirSync, readFileSync as readFileSync3, renameSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
1916
+ import { existsSync as existsSync3, mkdirSync, readdirSync as readdirSync2, readFileSync as readFileSync4, renameSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
1818
1917
  import { homedir as homedir3 } from "os";
1819
- import { join as join4 } from "path";
1918
+ import { join as join5 } from "path";
1820
1919
  import { randomUUID } from "crypto";
1821
1920
  function restartFlagsDir() {
1822
- return join4(homedir3(), ".augmented", "restart-flags");
1921
+ return join5(homedir3(), ".augmented", "restart-flags");
1823
1922
  }
1824
1923
  function flagPath(codeName) {
1825
- return join4(restartFlagsDir(), `${codeName}.flag`);
1924
+ return join5(restartFlagsDir(), `${codeName}.flag`);
1826
1925
  }
1827
1926
  function readRestartFlags() {
1828
1927
  const dir = restartFlagsDir();
1829
1928
  if (!existsSync3(dir)) return [];
1830
1929
  const out = [];
1831
- for (const entry of readdirSync(dir)) {
1930
+ for (const entry of readdirSync2(dir)) {
1832
1931
  if (!entry.endsWith(".flag")) continue;
1833
1932
  try {
1834
- const raw = readFileSync3(join4(dir, entry), "utf8");
1933
+ const raw = readFileSync4(join5(dir, entry), "utf8");
1835
1934
  const parsed = JSON.parse(raw);
1836
1935
  if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
1837
1936
  parsed.codeName = entry.replace(/\.flag$/, "");
@@ -2347,8 +2446,8 @@ function applyRestartAcks(args) {
2347
2446
  var GATEWAY_PORT_BASE = 18800;
2348
2447
  var GATEWAY_PORT_STEP = 10;
2349
2448
  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");
2449
+ var AUGMENTED_DIR = join6(process.env["HOME"] ?? "/tmp", ".augmented");
2450
+ var GATEWAY_PORTS_FILE = join6(AUGMENTED_DIR, "gateway-ports.json");
2352
2451
  var CHANNEL_SWEEP_INTERVAL_MS = (() => {
2353
2452
  const raw = parseInt(process.env["AGT_CHANNEL_SWEEP_INTERVAL_MS"] ?? "", 10);
2354
2453
  if (!Number.isFinite(raw)) return 5 * 60 * 1e3;
@@ -2455,8 +2554,8 @@ var KNOWN_SAFE_TAIL_SIGNATURES = /* @__PURE__ */ new Set(["session_id_in_use"]);
2455
2554
  function shouldSkipRevokedCleanup(previousKnownStatus) {
2456
2555
  return previousKnownStatus === "revoked";
2457
2556
  }
2458
- function hasRevokedResiduals(state4) {
2459
- return state4.gatewayRunning || state4.portAllocated || state4.provisionDirExists;
2557
+ function hasRevokedResiduals(state5) {
2558
+ return state5.gatewayRunning || state5.portAllocated || state5.provisionDirExists;
2460
2559
  }
2461
2560
  var knownVersions = /* @__PURE__ */ new Map();
2462
2561
  var knownStatuses = /* @__PURE__ */ new Map();
@@ -2522,7 +2621,7 @@ var runningMcpHashes = /* @__PURE__ */ new Map();
2522
2621
  var runningMcpServerKeys = /* @__PURE__ */ new Map();
2523
2622
  function projectMcpHash(_codeName, projectDir) {
2524
2623
  try {
2525
- const raw = readFileSync4(join5(projectDir, ".mcp.json"), "utf-8");
2624
+ const raw = readFileSync5(join6(projectDir, ".mcp.json"), "utf-8");
2526
2625
  return createHash2("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
2527
2626
  } catch {
2528
2627
  return null;
@@ -2530,7 +2629,7 @@ function projectMcpHash(_codeName, projectDir) {
2530
2629
  }
2531
2630
  function projectMcpKeys(_codeName, projectDir) {
2532
2631
  try {
2533
- const raw = readFileSync4(join5(projectDir, ".mcp.json"), "utf-8");
2632
+ const raw = readFileSync5(join6(projectDir, ".mcp.json"), "utf-8");
2534
2633
  const parsed = JSON.parse(raw);
2535
2634
  const servers = parsed.mcpServers;
2536
2635
  if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
@@ -2627,7 +2726,7 @@ var codeNameToAgentId = /* @__PURE__ */ new Map();
2627
2726
  var agentChannelTokens = /* @__PURE__ */ new Map();
2628
2727
  var activeChannels = /* @__PURE__ */ new Map();
2629
2728
  var gatewaysStartedThisCycle = /* @__PURE__ */ new Set();
2630
- var state3 = {
2729
+ var state4 = {
2631
2730
  pid: process.pid,
2632
2731
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
2633
2732
  lastPollAt: null,
@@ -2684,7 +2783,7 @@ var cachedFrameworkVersion = null;
2684
2783
  var lastVersionCheckAt = 0;
2685
2784
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
2686
2785
  var lastResponsivenessProbeAt = 0;
2687
- var agtCliVersion = true ? "0.24.0" : "dev";
2786
+ var agtCliVersion = true ? "0.24.2" : "dev";
2688
2787
  function resolveBrewPath(execFileSync4) {
2689
2788
  try {
2690
2789
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -2901,7 +3000,7 @@ async function ensureFrameworkBinary(frameworkId) {
2901
3000
  var CLAUDE_CODE_UPGRADE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
2902
3001
  var claudeCodeUpgradeInFlight = false;
2903
3002
  function claudeCodeUpgradeMarkerPath() {
2904
- return join5(homedir4(), ".augmented", ".last-claude-code-upgrade-check");
3003
+ return join6(homedir4(), ".augmented", ".last-claude-code-upgrade-check");
2905
3004
  }
2906
3005
  function stampClaudeCodeUpgradeMarker() {
2907
3006
  try {
@@ -2911,7 +3010,7 @@ function stampClaudeCodeUpgradeMarker() {
2911
3010
  }
2912
3011
  function claudeCodeUpgradeThrottled() {
2913
3012
  try {
2914
- const lastCheck = parseInt(readFileSync4(claudeCodeUpgradeMarkerPath(), "utf-8").trim(), 10);
3013
+ const lastCheck = parseInt(readFileSync5(claudeCodeUpgradeMarkerPath(), "utf-8").trim(), 10);
2915
3014
  if (!Number.isFinite(lastCheck)) return false;
2916
3015
  return Date.now() - lastCheck < CLAUDE_CODE_UPGRADE_CHECK_INTERVAL_MS;
2917
3016
  } catch {
@@ -2981,7 +3080,7 @@ async function checkAndUpdateCli() {
2981
3080
  const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
2982
3081
  if (!isBrewFormula && !isNpmGlobal) return;
2983
3082
  const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
2984
- const markerPath = join5(homedir4(), ".augmented", ".last-update-check");
3083
+ const markerPath = join6(homedir4(), ".augmented", ".last-update-check");
2985
3084
  try {
2986
3085
  const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
2987
3086
  if (Date.now() - lastCheck < UPDATE_CHECK_INTERVAL_MS) return;
@@ -3145,9 +3244,9 @@ async function applyClaudeAuthToEnv(childEnv, label) {
3145
3244
  throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
3146
3245
  }
3147
3246
  childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
3148
- const claudeDir = join5(homedir4(), ".claude");
3247
+ const claudeDir = join6(homedir4(), ".claude");
3149
3248
  for (const filename of [".credentials.json", "credentials.json"]) {
3150
- const p = join5(claudeDir, filename);
3249
+ const p = join6(claudeDir, filename);
3151
3250
  if (existsSync4(p)) {
3152
3251
  try {
3153
3252
  rmSync2(p, { force: true });
@@ -3162,7 +3261,7 @@ async function applyClaudeAuthToEnv(childEnv, label) {
3162
3261
  }
3163
3262
  function loadGatewayPorts() {
3164
3263
  try {
3165
- return JSON.parse(readFileSync4(GATEWAY_PORTS_FILE, "utf-8"));
3264
+ return JSON.parse(readFileSync5(GATEWAY_PORTS_FILE, "utf-8"));
3166
3265
  } catch {
3167
3266
  return {};
3168
3267
  }
@@ -3192,10 +3291,10 @@ function freePort(codeName) {
3192
3291
  }
3193
3292
  }
3194
3293
  function getStateFile() {
3195
- return join5(config?.configDir ?? join5(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
3294
+ return join6(config?.configDir ?? join6(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
3196
3295
  }
3197
3296
  function channelHashCacheDir() {
3198
- return config?.configDir ?? join5(process.env["HOME"] ?? "/tmp", ".augmented");
3297
+ return config?.configDir ?? join6(process.env["HOME"] ?? "/tmp", ".augmented");
3199
3298
  }
3200
3299
  function loadChannelHashCache2() {
3201
3300
  loadChannelHashCache(knownChannelConfigHashes, channelHashCacheDir());
@@ -3237,7 +3336,7 @@ function log(msg) {
3237
3336
  `;
3238
3337
  if (!managerLogPath) {
3239
3338
  try {
3240
- managerLogPath = join5(homedir4(), ".augmented", "manager.log");
3339
+ managerLogPath = join6(homedir4(), ".augmented", "manager.log");
3241
3340
  mkdirSync2(dirname(managerLogPath), { recursive: true });
3242
3341
  if (existsSync4(managerLogPath)) {
3243
3342
  chmodSync(managerLogPath, 384);
@@ -3267,7 +3366,7 @@ function sha256(content) {
3267
3366
  }
3268
3367
  function hashFile(filePath) {
3269
3368
  try {
3270
- const content = readFileSync4(filePath, "utf-8");
3369
+ const content = readFileSync5(filePath, "utf-8");
3271
3370
  return sha256(content);
3272
3371
  } catch {
3273
3372
  return null;
@@ -3291,13 +3390,13 @@ function parseSkillFrontmatter(content) {
3291
3390
  return out;
3292
3391
  }
3293
3392
  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");
3393
+ const { readdirSync: readdirSync4, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync4 } = await import("fs");
3394
+ const skillsDir = join6(configDir, codeName, "project", ".claude", "skills");
3395
+ const claudeMdPath = join6(configDir, codeName, "project", "CLAUDE.md");
3297
3396
  if (!ex(skillsDir) || !ex(claudeMdPath)) return;
3298
3397
  const entries = [];
3299
- for (const dir of readdirSync3(skillsDir).sort()) {
3300
- const skillFile = join5(skillsDir, dir, "SKILL.md");
3398
+ for (const dir of readdirSync4(skillsDir).sort()) {
3399
+ const skillFile = join6(skillsDir, dir, "SKILL.md");
3301
3400
  if (!ex(skillFile)) continue;
3302
3401
  try {
3303
3402
  const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
@@ -3345,10 +3444,10 @@ ${SKILLS_INDEX_END}`;
3345
3444
  }
3346
3445
  async function migrateToProfiles() {
3347
3446
  const homeDir = process.env["HOME"] ?? "/tmp";
3348
- const sharedConfigPath = join5(homeDir, ".openclaw", "openclaw.json");
3447
+ const sharedConfigPath = join6(homeDir, ".openclaw", "openclaw.json");
3349
3448
  let sharedConfig;
3350
3449
  try {
3351
- sharedConfig = JSON.parse(readFileSync4(sharedConfigPath, "utf-8"));
3450
+ sharedConfig = JSON.parse(readFileSync5(sharedConfigPath, "utf-8"));
3352
3451
  } catch {
3353
3452
  return;
3354
3453
  }
@@ -3361,19 +3460,19 @@ async function migrateToProfiles() {
3361
3460
  const codeName = agentEntry["id"];
3362
3461
  if (!codeName) continue;
3363
3462
  if (codeName === "main") continue;
3364
- const profileDir = join5(homeDir, `.openclaw-${codeName}`);
3365
- if (existsSync4(join5(profileDir, "openclaw.json"))) continue;
3463
+ const profileDir = join6(homeDir, `.openclaw-${codeName}`);
3464
+ if (existsSync4(join6(profileDir, "openclaw.json"))) continue;
3366
3465
  log(`Migrating agent '${codeName}' to per-agent profile`);
3367
3466
  if (adapter.seedProfileConfig) {
3368
3467
  adapter.seedProfileConfig(codeName);
3369
3468
  }
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");
3469
+ const sharedAuthDir = join6(homeDir, ".openclaw", "agents", codeName, "agent");
3470
+ const profileAuthDir = join6(profileDir, "agents", codeName, "agent");
3471
+ const authFile = join6(sharedAuthDir, "auth-profiles.json");
3373
3472
  if (existsSync4(authFile)) {
3374
3473
  mkdirSync2(profileAuthDir, { recursive: true });
3375
- const authContent = readFileSync4(authFile, "utf-8");
3376
- writeFileSync3(join5(profileAuthDir, "auth-profiles.json"), authContent);
3474
+ const authContent = readFileSync5(authFile, "utf-8");
3475
+ writeFileSync3(join6(profileAuthDir, "auth-profiles.json"), authContent);
3377
3476
  }
3378
3477
  allocatePort(codeName);
3379
3478
  migrated++;
@@ -3411,7 +3510,7 @@ function readGatewayToken(codeName) {
3411
3510
  }
3412
3511
  const homeDir = process.env["HOME"] ?? "/tmp";
3413
3512
  try {
3414
- const cfg = JSON.parse(readFileSync4(join5(homeDir, `.openclaw-${codeName}`, "openclaw.json"), "utf-8"));
3513
+ const cfg = JSON.parse(readFileSync5(join6(homeDir, `.openclaw-${codeName}`, "openclaw.json"), "utf-8"));
3415
3514
  return cfg?.gateway?.auth?.token;
3416
3515
  } catch {
3417
3516
  return void 0;
@@ -3420,18 +3519,18 @@ function readGatewayToken(codeName) {
3420
3519
  var GATEWAY_HUNG_TIMEOUT_MS = 5 * 6e4;
3421
3520
  function isGatewayHung(codeName) {
3422
3521
  const homeDir = process.env["HOME"] ?? "/tmp";
3423
- const jobsPath = join5(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
3522
+ const jobsPath = join6(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
3424
3523
  if (!existsSync4(jobsPath)) return false;
3425
3524
  try {
3426
- const data = JSON.parse(readFileSync4(jobsPath, "utf-8"));
3525
+ const data = JSON.parse(readFileSync5(jobsPath, "utf-8"));
3427
3526
  const jobs = data.jobs ?? data;
3428
3527
  if (!Array.isArray(jobs)) return false;
3429
3528
  const now = Date.now();
3430
3529
  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;
3530
+ const state5 = job.state;
3531
+ if (!state5) continue;
3532
+ const runStartedAt = state5.runStartedAtMs;
3533
+ const isRunning = state5.status === "running" || state5.running === true;
3435
3534
  if (isRunning && runStartedAt && now - runStartedAt > GATEWAY_HUNG_TIMEOUT_MS) {
3436
3535
  return true;
3437
3536
  }
@@ -3456,15 +3555,15 @@ async function ensureGatewayRunning(codeName, adapter) {
3456
3555
  }
3457
3556
  await new Promise((r) => setTimeout(r, 2e3));
3458
3557
  const homeDir = process.env["HOME"] ?? "/tmp";
3459
- const cronJobsPath = join5(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
3558
+ const cronJobsPath = join6(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
3460
3559
  clearStaleCronRunState(cronJobsPath);
3461
3560
  } else {
3462
3561
  if (status.port) {
3463
3562
  try {
3464
3563
  const homeDir = process.env["HOME"] ?? "/tmp";
3465
- const configPath = join5(homeDir, `.openclaw-${codeName}`, "openclaw.json");
3564
+ const configPath = join6(homeDir, `.openclaw-${codeName}`, "openclaw.json");
3466
3565
  if (existsSync4(configPath)) {
3467
- const cfg = JSON.parse(readFileSync4(configPath, "utf-8"));
3566
+ const cfg = JSON.parse(readFileSync5(configPath, "utf-8"));
3468
3567
  if (cfg.gateway?.port !== status.port) {
3469
3568
  if (!cfg.gateway) cfg.gateway = {};
3470
3569
  cfg.gateway.port = status.port;
@@ -3488,9 +3587,9 @@ async function ensureGatewayRunning(codeName, adapter) {
3488
3587
  gatewaysStartedThisCycle.add(codeName);
3489
3588
  try {
3490
3589
  const homeDir = process.env["HOME"] ?? "/tmp";
3491
- const configPath = join5(homeDir, `.openclaw-${codeName}`, "openclaw.json");
3590
+ const configPath = join6(homeDir, `.openclaw-${codeName}`, "openclaw.json");
3492
3591
  if (existsSync4(configPath)) {
3493
- const cfg = JSON.parse(readFileSync4(configPath, "utf-8"));
3592
+ const cfg = JSON.parse(readFileSync5(configPath, "utf-8"));
3494
3593
  if (!cfg.gateway) cfg.gateway = {};
3495
3594
  cfg.gateway.port = port;
3496
3595
  writeFileSync3(configPath, JSON.stringify(cfg, null, 2));
@@ -3632,7 +3731,7 @@ async function pollCycle() {
3632
3731
  const now = Date.now();
3633
3732
  if (now - lastVersionCheckAt > VERSION_CHECK_INTERVAL_MS) {
3634
3733
  try {
3635
- const firstAgent = state3.agents[0];
3734
+ const firstAgent = state4.agents[0];
3636
3735
  const versionAdapter = firstAgent ? resolveAgentFramework(firstAgent.codeName) : getFramework("openclaw");
3637
3736
  if (versionAdapter.getVersion) {
3638
3737
  cachedFrameworkVersion = await versionAdapter.getVersion();
@@ -3643,7 +3742,7 @@ async function pollCycle() {
3643
3742
  }
3644
3743
  try {
3645
3744
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
3646
- const { collectDiagnostics } = await import("../persistent-session-L4YIJJML.js");
3745
+ const { collectDiagnostics } = await import("../persistent-session-JUJY46HW.js");
3647
3746
  const diagCodeNames = [...persistentSessionAgents];
3648
3747
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
3649
3748
  let tailscaleHostname;
@@ -3694,7 +3793,7 @@ async function pollCycle() {
3694
3793
  const {
3695
3794
  collectResponsivenessProbes,
3696
3795
  getResponsivenessIntervalMs
3697
- } = await import("../responsiveness-probe-YRLESO54.js");
3796
+ } = await import("../responsiveness-probe-XOEC7J5D.js");
3698
3797
  const probeIntervalMs = getResponsivenessIntervalMs();
3699
3798
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
3700
3799
  const probeCodeNames = [...persistentSessionAgents];
@@ -3754,7 +3853,7 @@ async function pollCycle() {
3754
3853
  for (const agent of agents) {
3755
3854
  const requested = agent.restart_requested_at ?? null;
3756
3855
  if (!requested) continue;
3757
- const prev = state3.agents.find((a) => a.agentId === agent.agent_id);
3856
+ const prev = state4.agents.find((a) => a.agentId === agent.agent_id);
3758
3857
  const lastProcessed = prev?.lastRestartProcessedAt ?? null;
3759
3858
  if (lastProcessed && Date.parse(lastProcessed) >= Date.parse(requested)) continue;
3760
3859
  log(`[restart] Dashboard requested restart for '${agent.code_name}' at ${requested}`);
@@ -3777,7 +3876,7 @@ async function pollCycle() {
3777
3876
  await processAgent(agent, agentStates);
3778
3877
  } catch (err) {
3779
3878
  log(`Error processing agent '${agent.code_name}': ${err.message}`);
3780
- const existing = state3.agents.find((a) => a.agentId === agent.agent_id);
3879
+ const existing = state4.agents.find((a) => a.agentId === agent.agent_id);
3781
3880
  if (existing) {
3782
3881
  agentStates.push(existing);
3783
3882
  } else {
@@ -3803,12 +3902,12 @@ async function pollCycle() {
3803
3902
  void maybeReportActivityCache({ api, log });
3804
3903
  const restartAckStateChanged = applyRestartAcks({
3805
3904
  agentStates,
3806
- priorAgents: state3.agents,
3905
+ priorAgents: state4.agents,
3807
3906
  restartAcks
3808
3907
  });
3809
3908
  if (restartAckStateChanged) {
3810
3909
  try {
3811
- const ackedState = { ...state3, agents: agentStates };
3910
+ const ackedState = { ...state4, agents: agentStates };
3812
3911
  writeFileSync3(getStateFile(), JSON.stringify(ackedState, null, 2));
3813
3912
  } catch (err) {
3814
3913
  log(`[restart] failed to persist ack immediately: ${err.message}`);
@@ -3826,7 +3925,7 @@ async function pollCycle() {
3826
3925
  } catch {
3827
3926
  }
3828
3927
  const currentIds = new Set(agents.map((a) => a.agent_id));
3829
- for (const prev of state3.agents) {
3928
+ for (const prev of state4.agents) {
3830
3929
  if (!currentIds.has(prev.agentId)) {
3831
3930
  log(`Agent '${prev.codeName}' removed from host (deleted or unassigned)`);
3832
3931
  const adapter = resolveAgentFramework(prev.codeName);
@@ -3839,7 +3938,7 @@ async function pollCycle() {
3839
3938
  }
3840
3939
  killAgentChannelProcesses(prev.codeName, { log });
3841
3940
  freePort(prev.codeName);
3842
- const agentDir = join5(adapter.getAgentDir(prev.codeName), "provision");
3941
+ const agentDir = join6(adapter.getAgentDir(prev.codeName), "provision");
3843
3942
  await cleanupAgentFiles(prev.codeName, agentDir);
3844
3943
  clearAgentCaches(prev.agentId, prev.codeName);
3845
3944
  }
@@ -3926,10 +4025,10 @@ async function pollCycle() {
3926
4025
  }
3927
4026
  } catch {
3928
4027
  }
3929
- state3 = {
3930
- ...state3,
4028
+ state4 = {
4029
+ ...state4,
3931
4030
  lastPollAt: (/* @__PURE__ */ new Date()).toISOString(),
3932
- pollCount: state3.pollCount + 1,
4031
+ pollCount: state4.pollCount + 1,
3933
4032
  agents: agentStates,
3934
4033
  // ENG-5441: serialise trip state on every poll so manager restarts
3935
4034
  // never silently clear a tripped breaker. Cheap — only tripped
@@ -3940,9 +4039,9 @@ async function pollCycle() {
3940
4039
  log(`[poll-backoff] recovered after ${consecutivePollFailures} failure(s), resuming normal interval`);
3941
4040
  consecutivePollFailures = 0;
3942
4041
  }
3943
- send({ type: "state-update", state: state3 });
4042
+ send({ type: "state-update", state: state4 });
3944
4043
  } catch (err) {
3945
- state3.errorCount++;
4044
+ state4.errorCount++;
3946
4045
  const message = err.message;
3947
4046
  log(`Poll error: ${message}`);
3948
4047
  send({ type: "error", message });
@@ -3980,10 +4079,16 @@ async function processAgent(agent, agentStates) {
3980
4079
  agentId: agent.agent_id,
3981
4080
  log
3982
4081
  });
4082
+ void maybeReportTokenUsage({
4083
+ api,
4084
+ codeName: agent.code_name,
4085
+ agentId: agent.agent_id,
4086
+ log
4087
+ });
3983
4088
  }
3984
4089
  const now = (/* @__PURE__ */ new Date()).toISOString();
3985
4090
  const adapter = resolveAgentFramework(agent.code_name);
3986
- let agentDir = join5(adapter.getAgentDir(agent.code_name), "provision");
4091
+ let agentDir = join6(adapter.getAgentDir(agent.code_name), "provision");
3987
4092
  if (agent.status === "draft" || agent.status === "paused") {
3988
4093
  if (previousKnownStatus !== agent.status) {
3989
4094
  log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
@@ -4104,7 +4209,7 @@ async function processAgent(agent, agentStates) {
4104
4209
  });
4105
4210
  } catch (err) {
4106
4211
  log(`Refresh failed for '${agent.code_name}': ${err.message}`);
4107
- const existing = state3.agents.find((a) => a.agentId === agent.agent_id);
4212
+ const existing = state4.agents.find((a) => a.agentId === agent.agent_id);
4108
4213
  agentStates.push(existing ?? {
4109
4214
  agentId: agent.agent_id,
4110
4215
  codeName: agent.code_name,
@@ -4152,7 +4257,7 @@ async function processAgent(agent, agentStates) {
4152
4257
  const frameworkId = refreshData.agent.framework ?? "openclaw";
4153
4258
  agentFrameworkCache.set(agent.code_name, frameworkId);
4154
4259
  const frameworkAdapter = getFramework(frameworkId);
4155
- agentDir = join5(frameworkAdapter.getAgentDir(agent.code_name), "provision");
4260
+ agentDir = join6(frameworkAdapter.getAgentDir(agent.code_name), "provision");
4156
4261
  cacheAgentDeliveryMetadata(agent.code_name, refreshData);
4157
4262
  if (frameworkAdapter.seedProfileConfig) {
4158
4263
  frameworkAdapter.seedProfileConfig(agent.code_name);
@@ -4160,7 +4265,7 @@ async function processAgent(agent, agentStates) {
4160
4265
  const charterVersion = refreshData.charter.version;
4161
4266
  const toolsVersion = refreshData.tools.version;
4162
4267
  const known = knownVersions.get(agent.agent_id);
4163
- let lastProvisionAt = state3.agents.find((a) => a.agentId === agent.agent_id)?.lastProvisionAt ?? null;
4268
+ let lastProvisionAt = state4.agents.find((a) => a.agentId === agent.agent_id)?.lastProvisionAt ?? null;
4164
4269
  const currentChannelIds = launchableChannelIds(refreshData.channel_configs);
4165
4270
  const previousChannelIds = knownChannels.get(agent.agent_id);
4166
4271
  const channelsChanged = !previousChannelIds || currentChannelIds.size !== previousChannelIds.size || [...currentChannelIds].some((ch) => !previousChannelIds.has(ch)) || [...previousChannelIds].some((ch) => !currentChannelIds.has(ch));
@@ -4183,7 +4288,7 @@ async function processAgent(agent, agentStates) {
4183
4288
  const changedFiles = [];
4184
4289
  mkdirSync2(agentDir, { recursive: true });
4185
4290
  for (const artifact of artifacts) {
4186
- const filePath = join5(agentDir, artifact.relativePath);
4291
+ const filePath = join6(agentDir, artifact.relativePath);
4187
4292
  let existingHash;
4188
4293
  let newHash;
4189
4294
  let writeContent = artifact.content;
@@ -4195,8 +4300,8 @@ async function processAgent(agent, agentStates) {
4195
4300
  };
4196
4301
  newHash = sha256(stripDynamicSections(artifact.content));
4197
4302
  try {
4198
- const projectClaudeMd = join5(config.configDir, agent.code_name, "project", "CLAUDE.md");
4199
- const existing = readFileSync4(projectClaudeMd, "utf-8");
4303
+ const projectClaudeMd = join6(config.configDir, agent.code_name, "project", "CLAUDE.md");
4304
+ const existing = readFileSync5(projectClaudeMd, "utf-8");
4200
4305
  existingHash = sha256(stripDynamicSections(existing));
4201
4306
  } catch {
4202
4307
  existingHash = null;
@@ -4214,7 +4319,7 @@ async function processAgent(agent, agentStates) {
4214
4319
  const generatorKeys = Object.keys(generatorServers);
4215
4320
  let existingRaw = "";
4216
4321
  try {
4217
- existingRaw = readFileSync4(filePath, "utf-8");
4322
+ existingRaw = readFileSync5(filePath, "utf-8");
4218
4323
  } catch {
4219
4324
  }
4220
4325
  const existingServers = parseMcp(existingRaw);
@@ -4236,22 +4341,22 @@ async function processAgent(agent, agentStates) {
4236
4341
  }
4237
4342
  }
4238
4343
  if (changedFiles.length > 0) {
4239
- const isFirst = !existsSync4(join5(agentDir, "CHARTER.md"));
4344
+ const isFirst = !existsSync4(join6(agentDir, "CHARTER.md"));
4240
4345
  const verb = isFirst ? "Provisioning" : "Updating";
4241
4346
  const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
4242
4347
  log(`${verb} '${agent.code_name}': ${fileNames}`);
4243
4348
  for (const file of changedFiles) {
4244
- const filePath = join5(agentDir, file.relativePath);
4349
+ const filePath = join6(agentDir, file.relativePath);
4245
4350
  mkdirSync2(dirname(filePath), { recursive: true });
4246
4351
  writeFileSync3(filePath, file.content);
4247
4352
  }
4248
4353
  try {
4249
- const provSkillsDir = join5(agentDir, ".claude", "skills");
4354
+ const provSkillsDir = join6(agentDir, ".claude", "skills");
4250
4355
  if (existsSync4(provSkillsDir)) {
4251
- for (const folder of readdirSync2(provSkillsDir)) {
4356
+ for (const folder of readdirSync3(provSkillsDir)) {
4252
4357
  if (folder.startsWith("knowledge-")) {
4253
4358
  try {
4254
- rmSync2(join5(provSkillsDir, folder), { recursive: true });
4359
+ rmSync2(join6(provSkillsDir, folder), { recursive: true });
4255
4360
  } catch {
4256
4361
  }
4257
4362
  }
@@ -4264,7 +4369,7 @@ async function processAgent(agent, agentStates) {
4264
4369
  const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
4265
4370
  const hashes = /* @__PURE__ */ new Map();
4266
4371
  for (const file of trackedFiles2) {
4267
- const h = hashFile(join5(agentDir, file));
4372
+ const h = hashFile(join6(agentDir, file));
4268
4373
  if (h) hashes.set(file, h);
4269
4374
  }
4270
4375
  writtenHashes.set(agent.agent_id, hashes);
@@ -4311,7 +4416,7 @@ async function processAgent(agent, agentStates) {
4311
4416
  if (written && existsSync4(agentDir)) {
4312
4417
  const driftedFiles = [];
4313
4418
  for (const [file, expectedHash] of written) {
4314
- const localHash = hashFile(join5(agentDir, file));
4419
+ const localHash = hashFile(join6(agentDir, file));
4315
4420
  if (localHash && localHash !== expectedHash) {
4316
4421
  driftedFiles.push(file);
4317
4422
  }
@@ -4322,7 +4427,7 @@ async function processAgent(agent, agentStates) {
4322
4427
  try {
4323
4428
  const localHashes = {};
4324
4429
  for (const file of driftedFiles) {
4325
- localHashes[file] = hashFile(join5(agentDir, file));
4430
+ localHashes[file] = hashFile(join6(agentDir, file));
4326
4431
  }
4327
4432
  await api.post("/host/drift", {
4328
4433
  agent_id: agent.agent_id,
@@ -4480,18 +4585,18 @@ async function processAgent(agent, agentStates) {
4480
4585
  if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? "openclaw") === "claude-code") {
4481
4586
  try {
4482
4587
  const agentProvisionDir = agentDir;
4483
- const projectDir = join5(homedir4(), ".augmented", agent.code_name, "project");
4588
+ const projectDir = join6(homedir4(), ".augmented", agent.code_name, "project");
4484
4589
  mkdirSync2(agentProvisionDir, { recursive: true });
4485
4590
  mkdirSync2(projectDir, { recursive: true });
4486
- const provisionMcpPath = join5(agentProvisionDir, ".mcp.json");
4487
- const projectMcpPath = join5(projectDir, ".mcp.json");
4591
+ const provisionMcpPath = join6(agentProvisionDir, ".mcp.json");
4592
+ const projectMcpPath = join6(projectDir, ".mcp.json");
4488
4593
  let mcpConfig = { mcpServers: {} };
4489
4594
  try {
4490
- mcpConfig = JSON.parse(readFileSync4(provisionMcpPath, "utf-8"));
4595
+ mcpConfig = JSON.parse(readFileSync5(provisionMcpPath, "utf-8"));
4491
4596
  if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
4492
4597
  } catch {
4493
4598
  }
4494
- const localDirectChatChannel = join5(homedir4(), ".augmented", "_mcp", "direct-chat-channel.js");
4599
+ const localDirectChatChannel = join6(homedir4(), ".augmented", "_mcp", "direct-chat-channel.js");
4495
4600
  const directChatTeamSettings = refreshData.team?.settings;
4496
4601
  const directChatTz = (() => {
4497
4602
  const tz = directChatTeamSettings?.["timezone"];
@@ -4513,7 +4618,7 @@ async function processAgent(agent, agentStates) {
4513
4618
  writeFileSync3(projectMcpPath, serialized);
4514
4619
  log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
4515
4620
  }
4516
- const staleChannelsPath = join5(projectDir, ".mcp-channels.json");
4621
+ const staleChannelsPath = join6(projectDir, ".mcp-channels.json");
4517
4622
  if (existsSync4(staleChannelsPath)) {
4518
4623
  try {
4519
4624
  rmSync2(staleChannelsPath, { force: true });
@@ -4524,7 +4629,7 @@ async function processAgent(agent, agentStates) {
4524
4629
  log(`Failed to provision direct-chat channel for '${agent.code_name}': ${err.message}`);
4525
4630
  }
4526
4631
  }
4527
- let lastSecretsProvisionAt = state3.agents.find((a) => a.agentId === agent.agent_id)?.lastSecretsProvisionAt ?? null;
4632
+ let lastSecretsProvisionAt = state4.agents.find((a) => a.agentId === agent.agent_id)?.lastSecretsProvisionAt ?? null;
4528
4633
  let secretsHash = knownSecretsHashes.get(agent.agent_id) ?? null;
4529
4634
  try {
4530
4635
  const secretsData = await api.post("/host/secrets", { agent_id: agent.agent_id });
@@ -4580,11 +4685,11 @@ async function processAgent(agent, agentStates) {
4580
4685
  const intHash = computeIntegrationsHash(integrations);
4581
4686
  const prevIntHash = knownIntegrationHashes.get(agent.agent_id);
4582
4687
  if (intHash !== prevIntHash) {
4583
- const projectDir = join5(homedir4(), ".augmented", agent.code_name, "project");
4584
- const envIntPath = join5(projectDir, ".env.integrations");
4688
+ const projectDir = join6(homedir4(), ".augmented", agent.code_name, "project");
4689
+ const envIntPath = join6(projectDir, ".env.integrations");
4585
4690
  let preWriteEnv;
4586
4691
  try {
4587
- preWriteEnv = readFileSync4(envIntPath, "utf-8");
4692
+ preWriteEnv = readFileSync5(envIntPath, "utf-8");
4588
4693
  } catch {
4589
4694
  preWriteEnv = void 0;
4590
4695
  }
@@ -4596,9 +4701,9 @@ async function processAgent(agent, agentStates) {
4596
4701
  let rotationHandled = true;
4597
4702
  if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
4598
4703
  try {
4599
- const projectMcpPath = join5(projectDir, ".mcp.json");
4600
- const postWriteEnv = readFileSync4(envIntPath, "utf-8");
4601
- const mcpContent = readFileSync4(projectMcpPath, "utf-8");
4704
+ const projectMcpPath = join6(projectDir, ".mcp.json");
4705
+ const postWriteEnv = readFileSync5(envIntPath, "utf-8");
4706
+ const mcpContent = readFileSync5(projectMcpPath, "utf-8");
4602
4707
  const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
4603
4708
  const mcpJsonForReap = JSON.parse(mcpContent);
4604
4709
  const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
@@ -4664,8 +4769,8 @@ async function processAgent(agent, agentStates) {
4664
4769
  const mcpPath = frameworkAdapter.getMcpPath(agent.code_name);
4665
4770
  if (mcpPath) {
4666
4771
  try {
4667
- const { readFileSync: readFileSync5 } = await import("fs");
4668
- const mcpConfig = JSON.parse(readFileSync5(mcpPath, "utf-8"));
4772
+ const { readFileSync: readFileSync6 } = await import("fs");
4773
+ const mcpConfig = JSON.parse(readFileSync6(mcpPath, "utf-8"));
4669
4774
  if (mcpConfig.mcpServers) {
4670
4775
  const managedPrefixes = [
4671
4776
  "composio_",
@@ -4754,7 +4859,7 @@ async function processAgent(agent, agentStates) {
4754
4859
  if (agent.status === "active") {
4755
4860
  if (frameworkAdapter.installPlugin) {
4756
4861
  try {
4757
- const pluginPath = join5(process.cwd(), "packages", "openclaw-plugin-augmented", "src", "index.ts");
4862
+ const pluginPath = join6(process.cwd(), "packages", "openclaw-plugin-augmented", "src", "index.ts");
4758
4863
  if (existsSync4(pluginPath)) {
4759
4864
  frameworkAdapter.installPlugin(agent.code_name, "augmented", pluginPath, {
4760
4865
  agtHost: requireHost(),
@@ -4820,25 +4925,25 @@ async function processAgent(agent, agentStates) {
4820
4925
  }
4821
4926
  }
4822
4927
  try {
4823
- const { readdirSync: readdirSync3, rmSync: rmSync3 } = await import("fs");
4928
+ const { readdirSync: readdirSync4, rmSync: rmSync3 } = await import("fs");
4824
4929
  const { homedir: homedir5 } = await import("os");
4825
4930
  const frameworkId2 = frameworkAdapter.id;
4826
4931
  const candidateSkillDirs = [
4827
4932
  // Claude Code — framework runtime tree
4828
- join5(homedir5(), ".augmented", agent.code_name, "skills"),
4933
+ join6(homedir5(), ".augmented", agent.code_name, "skills"),
4829
4934
  // Claude Code — project tree
4830
- join5(homedir5(), ".augmented", agent.code_name, "project", ".claude", "skills"),
4935
+ join6(homedir5(), ".augmented", agent.code_name, "project", ".claude", "skills"),
4831
4936
  // OpenClaw — framework runtime tree
4832
- join5(homedir5(), `.openclaw-${agent.code_name}`, "skills"),
4937
+ join6(homedir5(), `.openclaw-${agent.code_name}`, "skills"),
4833
4938
  // Defensive: legacy provision-side path, not currently an
4834
4939
  // install target but cheap to sweep.
4835
- join5(agentDir, ".claude", "skills")
4940
+ join6(agentDir, ".claude", "skills")
4836
4941
  ];
4837
4942
  const existingDirs = candidateSkillDirs.filter((d) => existsSync4(d));
4838
4943
  const discoveredEntries = /* @__PURE__ */ new Set();
4839
4944
  for (const dir of existingDirs) {
4840
4945
  try {
4841
- for (const entry of readdirSync3(dir)) {
4946
+ for (const entry of readdirSync4(dir)) {
4842
4947
  if (entry.startsWith("plugin-") || entry.startsWith("integration-")) {
4843
4948
  discoveredEntries.add(entry);
4844
4949
  }
@@ -4848,7 +4953,7 @@ async function processAgent(agent, agentStates) {
4848
4953
  }
4849
4954
  const removeSkillFolder = (entry, reason) => {
4850
4955
  for (const dir of existingDirs) {
4851
- const p = join5(dir, entry);
4956
+ const p = join6(dir, entry);
4852
4957
  if (existsSync4(p)) {
4853
4958
  rmSync3(p, { recursive: true, force: true });
4854
4959
  }
@@ -5009,8 +5114,8 @@ async function processAgent(agent, agentStates) {
5009
5114
  const sess = getSessionState(agent.code_name);
5010
5115
  let mcpJsonParsed = null;
5011
5116
  try {
5012
- const mcpPath = join5(getProjectDir(agent.code_name), ".mcp.json");
5013
- mcpJsonParsed = JSON.parse(readFileSync4(mcpPath, "utf-8"));
5117
+ const mcpPath = join6(getProjectDir(agent.code_name), ".mcp.json");
5118
+ mcpJsonParsed = JSON.parse(readFileSync5(mcpPath, "utf-8"));
5014
5119
  } catch {
5015
5120
  }
5016
5121
  reapMissingMcpSessions({
@@ -5159,10 +5264,10 @@ async function processAgent(agent, agentStates) {
5159
5264
  lastWorkTriggerAt.set(agent.code_name, triggerTs);
5160
5265
  if (agentFw === "openclaw" && gatewayRunning && gatewayPort) {
5161
5266
  const homeDir = process.env["HOME"] ?? "/tmp";
5162
- const jobsPath = join5(homeDir, `.openclaw-${agent.code_name}`, "cron", "jobs.json");
5267
+ const jobsPath = join6(homeDir, `.openclaw-${agent.code_name}`, "cron", "jobs.json");
5163
5268
  if (existsSync4(jobsPath)) {
5164
5269
  try {
5165
- const jobsData = JSON.parse(readFileSync4(jobsPath, "utf-8"));
5270
+ const jobsData = JSON.parse(readFileSync5(jobsPath, "utf-8"));
5166
5271
  const kanbanJob = (jobsData.jobs ?? []).find(
5167
5272
  (j) => typeof j.name === "string" && j.name.includes("kanban-work")
5168
5273
  );
@@ -5306,7 +5411,7 @@ In progress for ${age} minutes \u2014 auto-failed`).catch(() => {
5306
5411
  if (trackedFiles.length > 0 && existsSync4(agentDir)) {
5307
5412
  const hashes = /* @__PURE__ */ new Map();
5308
5413
  for (const file of trackedFiles) {
5309
- const h = hashFile(join5(agentDir, file));
5414
+ const h = hashFile(join6(agentDir, file));
5310
5415
  if (h) hashes.set(file, h);
5311
5416
  }
5312
5417
  writtenHashes.set(agent.agent_id, hashes);
@@ -5340,19 +5445,19 @@ function cleanupStaleSessions(codeName) {
5340
5445
  lastCleanupAt.set(codeName, Date.now());
5341
5446
  const homeDir = process.env["HOME"] ?? "/tmp";
5342
5447
  for (const agentDir of ["main", codeName]) {
5343
- const sessionsDir = join5(homeDir, `.openclaw-${codeName}`, "agents", agentDir, "sessions");
5448
+ const sessionsDir = join6(homeDir, `.openclaw-${codeName}`, "agents", agentDir, "sessions");
5344
5449
  cleanupCronSessions(sessionsDir, CRON_SESSION_KEEP_COUNT);
5345
5450
  }
5346
- const cronRunsDir = join5(homeDir, `.openclaw-${codeName}`, "cron", "runs");
5451
+ const cronRunsDir = join6(homeDir, `.openclaw-${codeName}`, "cron", "runs");
5347
5452
  cleanupOldFiles(cronRunsDir, CRON_RUN_RETENTION_DAYS, ".jsonl");
5348
- const cronJobsPath = join5(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
5453
+ const cronJobsPath = join6(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
5349
5454
  clearStaleCronRunState(cronJobsPath);
5350
5455
  }
5351
5456
  function cleanupCronSessions(sessionsDir, keepCount) {
5352
- const indexPath = join5(sessionsDir, "sessions.json");
5457
+ const indexPath = join6(sessionsDir, "sessions.json");
5353
5458
  if (!existsSync4(indexPath)) return;
5354
5459
  try {
5355
- const raw = readFileSync4(indexPath, "utf-8");
5460
+ const raw = readFileSync5(indexPath, "utf-8");
5356
5461
  const index = JSON.parse(raw);
5357
5462
  const cronRunKeys = Object.keys(index).filter((k) => k.includes(":cron:") && k.includes(":run:")).map((k) => ({
5358
5463
  key: k,
@@ -5365,7 +5470,7 @@ function cleanupCronSessions(sessionsDir, keepCount) {
5365
5470
  for (const entry of toDelete) {
5366
5471
  delete index[entry.key];
5367
5472
  if (entry.sessionId) {
5368
- const sessionFile = join5(sessionsDir, `${entry.sessionId}.jsonl`);
5473
+ const sessionFile = join6(sessionsDir, `${entry.sessionId}.jsonl`);
5369
5474
  try {
5370
5475
  if (existsSync4(sessionFile)) {
5371
5476
  unlinkSync(sessionFile);
@@ -5387,7 +5492,7 @@ function cleanupCronSessions(sessionsDir, keepCount) {
5387
5492
  delete index[parentKey];
5388
5493
  if (parentSessionId) {
5389
5494
  try {
5390
- const f = join5(sessionsDir, `${parentSessionId}.jsonl`);
5495
+ const f = join6(sessionsDir, `${parentSessionId}.jsonl`);
5391
5496
  if (existsSync4(f)) {
5392
5497
  unlinkSync(f);
5393
5498
  deletedFiles++;
@@ -5408,26 +5513,26 @@ var STALE_RUN_TIMEOUT_MS = 5 * 6e4;
5408
5513
  function clearStaleCronRunState(jobsPath) {
5409
5514
  if (!existsSync4(jobsPath)) return;
5410
5515
  try {
5411
- const raw = readFileSync4(jobsPath, "utf-8");
5516
+ const raw = readFileSync5(jobsPath, "utf-8");
5412
5517
  const data = JSON.parse(raw);
5413
5518
  const jobs = data.jobs ?? data;
5414
5519
  if (!Array.isArray(jobs)) return;
5415
5520
  let changed = false;
5416
5521
  const now = Date.now();
5417
5522
  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";
5523
+ const state5 = job.state;
5524
+ if (!state5) continue;
5525
+ const runStartedAt = state5.runningAtMs ?? state5.runStartedAtMs;
5526
+ const isRunning = state5.running === true || state5.status === "running";
5422
5527
  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;
5528
+ state5.running = false;
5529
+ delete state5.status;
5530
+ delete state5.runStartedAtMs;
5531
+ delete state5.currentRunId;
5427
5532
  changed = true;
5428
5533
  log(`Cleared stale running state for cron job '${job.name}' (stuck for ${Math.round((now - runStartedAt) / 6e4)}min)`);
5429
5534
  } else if (isRunning && !runStartedAt) {
5430
- state4.running = false;
5535
+ state5.running = false;
5431
5536
  changed = true;
5432
5537
  log(`Cleared stale running state for cron job '${job.name}' (no start timestamp)`);
5433
5538
  }
@@ -5443,11 +5548,11 @@ function cleanupOldFiles(dir, maxAgeDays, ext) {
5443
5548
  const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3;
5444
5549
  let removed = 0;
5445
5550
  try {
5446
- for (const f of readdirSync2(dir)) {
5551
+ for (const f of readdirSync3(dir)) {
5447
5552
  if (!f.endsWith(ext)) continue;
5448
- const fullPath = join5(dir, f);
5553
+ const fullPath = join6(dir, f);
5449
5554
  try {
5450
- const st = statSync(fullPath);
5555
+ const st = statSync2(fullPath);
5451
5556
  if (st.mtimeMs < cutoff) {
5452
5557
  unlinkSync(fullPath);
5453
5558
  removed++;
@@ -5491,16 +5596,16 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
5491
5596
  enabled: t.enabled ?? true,
5492
5597
  triggered_at: t.triggered_at ?? null
5493
5598
  }));
5494
- const state5 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
5495
- claudeSchedulerStates.set(codeName, state5);
5599
+ const state6 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
5600
+ claudeSchedulerStates.set(codeName, state6);
5496
5601
  knownTasksHashes.set(agent.agent_id, combinedHash);
5497
5602
  log(`[claude-scheduler] Tasks synced for '${codeName}' (${taskInputs.length} task(s))`);
5498
5603
  }
5499
5604
  if (!claudeSchedulerStates.has(codeName)) {
5500
5605
  claudeSchedulerStates.set(codeName, loadSchedulerState(codeName));
5501
5606
  }
5502
- const state4 = claudeSchedulerStates.get(codeName);
5503
- const ready = getReadyTasks(state4, inFlightClaudeTasks);
5607
+ const state5 = claudeSchedulerStates.get(codeName);
5608
+ const ready = getReadyTasks(state5, inFlightClaudeTasks);
5504
5609
  if (ready.length === 0) return;
5505
5610
  for (const task of ready) {
5506
5611
  if ((claudeTaskConcurrency.get(codeName) ?? 0) >= MAX_CLAUDE_CONCURRENCY) break;
@@ -5589,7 +5694,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
5589
5694
  }
5590
5695
  async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
5591
5696
  const projectDir = getProjectDir2(codeName);
5592
- const mcpConfigPath = join5(projectDir, ".mcp.json");
5697
+ const mcpConfigPath = join6(projectDir, ".mcp.json");
5593
5698
  let runId = null;
5594
5699
  let kanbanItemId = null;
5595
5700
  let taskResult;
@@ -5597,11 +5702,11 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
5597
5702
  const priorRuns = await fetchPriorScheduledRuns(agentId, task.taskId);
5598
5703
  prompt = wrapScheduledTaskPrompt(prompt, { priorRuns });
5599
5704
  try {
5600
- const claudeMdPath = join5(projectDir, "CLAUDE.md");
5705
+ const claudeMdPath = join6(projectDir, "CLAUDE.md");
5601
5706
  const serverNames = [];
5602
5707
  if (existsSync4(mcpConfigPath)) {
5603
5708
  try {
5604
- const d = JSON.parse(readFileSync4(mcpConfigPath, "utf-8"));
5709
+ const d = JSON.parse(readFileSync5(mcpConfigPath, "utf-8"));
5605
5710
  if (d.mcpServers) serverNames.push(...Object.keys(d.mcpServers));
5606
5711
  } catch {
5607
5712
  }
@@ -5624,10 +5729,10 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
5624
5729
  claudeArgs.push("--system-prompt-file", claudeMdPath);
5625
5730
  }
5626
5731
  const childEnv = { ...process.env };
5627
- const envIntPath = join5(projectDir, ".env.integrations");
5732
+ const envIntPath = join6(projectDir, ".env.integrations");
5628
5733
  if (existsSync4(envIntPath)) {
5629
5734
  try {
5630
- for (const line of readFileSync4(envIntPath, "utf-8").split("\n")) {
5735
+ for (const line of readFileSync5(envIntPath, "utf-8").split("\n")) {
5631
5736
  if (!line || line.startsWith("#") || !line.includes("=")) continue;
5632
5737
  const eqIdx = line.indexOf("=");
5633
5738
  childEnv[line.slice(0, eqIdx)] = line.slice(eqIdx + 1);
@@ -5781,8 +5886,8 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
5781
5886
  }
5782
5887
  }
5783
5888
  function fireClaudeWorkTrigger(codeName, agentId, boardItems) {
5784
- const state4 = claudeSchedulerStates.get(codeName) ?? loadSchedulerState(codeName);
5785
- const kanbanTask = findTaskByTemplate(state4, "kanban-work");
5889
+ const state5 = claudeSchedulerStates.get(codeName) ?? loadSchedulerState(codeName);
5890
+ const kanbanTask = findTaskByTemplate(state5, "kanban-work");
5786
5891
  if (!kanbanTask) {
5787
5892
  log(`[claude-scheduler] Work trigger: no kanban-work task found for '${codeName}'`);
5788
5893
  return;
@@ -5811,8 +5916,8 @@ var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
5811
5916
  async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
5812
5917
  const codeName = agent.code_name;
5813
5918
  const projectDir = getProjectDir(codeName);
5814
- const mcpConfigPath = join5(projectDir, ".mcp.json");
5815
- const claudeMdPath = join5(projectDir, "CLAUDE.md");
5919
+ const mcpConfigPath = join6(projectDir, ".mcp.json");
5920
+ const claudeMdPath = join6(projectDir, "CLAUDE.md");
5816
5921
  if (restartBreaker.isTripped(codeName)) {
5817
5922
  const trip = restartBreaker.getTrip(codeName);
5818
5923
  return {
@@ -6049,9 +6154,9 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash2("sha256").
6049
6154
  } else if (!claudeSchedulerStates.has(codeName)) {
6050
6155
  claudeSchedulerStates.set(codeName, loadSchedulerState(codeName));
6051
6156
  }
6052
- const state4 = claudeSchedulerStates.get(codeName);
6053
- if (state4) {
6054
- const ready = getReadyTasks(state4, inFlightClaudeTasks);
6157
+ const state5 = claudeSchedulerStates.get(codeName);
6158
+ if (state5) {
6159
+ const ready = getReadyTasks(state5, inFlightClaudeTasks);
6055
6160
  if (ready.length > 0) {
6056
6161
  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
6162
  }
@@ -6430,11 +6535,11 @@ ${escapeXml(msg.content)}
6430
6535
  if (fw === "claude-code") {
6431
6536
  const { getProjectDir: ccProjectDir } = await import("../claude-scheduler-XHJS2MZV.js");
6432
6537
  const projDir = ccProjectDir(agent.codeName);
6433
- const mcpConfigPath = join5(projDir, ".mcp.json");
6538
+ const mcpConfigPath = join6(projDir, ".mcp.json");
6434
6539
  const serverNames = [];
6435
6540
  if (existsSync4(mcpConfigPath)) {
6436
6541
  try {
6437
- const d = JSON.parse(readFileSync4(mcpConfigPath, "utf-8"));
6542
+ const d = JSON.parse(readFileSync5(mcpConfigPath, "utf-8"));
6438
6543
  if (d.mcpServers) serverNames.push(...Object.keys(d.mcpServers));
6439
6544
  } catch {
6440
6545
  }
@@ -6453,15 +6558,15 @@ ${escapeXml(msg.content)}
6453
6558
  "--allowedTools",
6454
6559
  allowedTools
6455
6560
  ];
6456
- const chatClaudeMd = join5(projDir, "CLAUDE.md");
6561
+ const chatClaudeMd = join6(projDir, "CLAUDE.md");
6457
6562
  if (existsSync4(chatClaudeMd)) {
6458
6563
  chatArgs.push("--system-prompt-file", chatClaudeMd);
6459
6564
  }
6460
- const envIntPath = join5(projDir, ".env.integrations");
6565
+ const envIntPath = join6(projDir, ".env.integrations");
6461
6566
  const childEnv = { ...process.env };
6462
6567
  if (existsSync4(envIntPath)) {
6463
6568
  try {
6464
- for (const line of readFileSync4(envIntPath, "utf-8").split("\n")) {
6569
+ for (const line of readFileSync5(envIntPath, "utf-8").split("\n")) {
6465
6570
  if (!line || line.startsWith("#") || !line.includes("=")) continue;
6466
6571
  const eqIdx = line.indexOf("=");
6467
6572
  childEnv[line.slice(0, eqIdx)] = line.slice(eqIdx + 1);
@@ -6804,12 +6909,12 @@ function getBuiltInSkillContent(skillId) {
6804
6909
  if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
6805
6910
  try {
6806
6911
  const candidates = [
6807
- join5(process.cwd(), "skills", skillId, "SKILL.md"),
6808
- join5(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "skills", skillId, "SKILL.md")
6912
+ join6(process.cwd(), "skills", skillId, "SKILL.md"),
6913
+ join6(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "skills", skillId, "SKILL.md")
6809
6914
  ];
6810
6915
  for (const candidate of candidates) {
6811
6916
  if (existsSync4(candidate)) {
6812
- const content = readFileSync4(candidate, "utf-8");
6917
+ const content = readFileSync5(candidate, "utf-8");
6813
6918
  const files = [{ relativePath: "SKILL.md", content }];
6814
6919
  builtInSkillCache.set(skillId, files);
6815
6920
  return files;
@@ -7422,7 +7527,7 @@ async function processClaudePairSessions(agents) {
7422
7527
  killPairSession,
7423
7528
  pairTmuxSession,
7424
7529
  finalizeClaudePairOnboarding
7425
- } = await import("../claude-pair-runtime-XCFWTH6T.js");
7530
+ } = await import("../claude-pair-runtime-ZQAJOQPN.js");
7426
7531
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
7427
7532
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
7428
7533
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -7717,8 +7822,8 @@ function parseMemoryFile(raw, fallbackName) {
7717
7822
  };
7718
7823
  }
7719
7824
  async function syncMemories(agent, configDir, log2) {
7720
- const projectDir = join5(configDir, agent.code_name, "project");
7721
- const memoryDir = join5(projectDir, "memory");
7825
+ const projectDir = join6(configDir, agent.code_name, "project");
7826
+ const memoryDir = join6(projectDir, "memory");
7722
7827
  const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
7723
7828
  if (isFreshSync) {
7724
7829
  log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
@@ -7733,10 +7838,10 @@ async function syncMemories(agent, configDir, log2) {
7733
7838
  const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
7734
7839
  const currentHashes = /* @__PURE__ */ new Map();
7735
7840
  const changedMemories = [];
7736
- for (const file of readdirSync2(memoryDir)) {
7841
+ for (const file of readdirSync3(memoryDir)) {
7737
7842
  if (!file.endsWith(".md")) continue;
7738
7843
  try {
7739
- const raw = readFileSync4(join5(memoryDir, file), "utf-8");
7844
+ const raw = readFileSync5(join6(memoryDir, file), "utf-8");
7740
7845
  const fileHash = createHash2("sha256").update(raw).digest("hex").slice(0, 16);
7741
7846
  currentHashes.set(file, fileHash);
7742
7847
  if (prevHashes.get(file) === fileHash) continue;
@@ -7761,7 +7866,7 @@ async function syncMemories(agent, configDir, log2) {
7761
7866
  } catch (err) {
7762
7867
  for (const mem of changedMemories) {
7763
7868
  for (const [file] of currentHashes) {
7764
- const parsed = parseMemoryFile(readFileSync4(join5(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
7869
+ const parsed = parseMemoryFile(readFileSync5(join6(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
7765
7870
  if (parsed?.name === mem.name) currentHashes.delete(file);
7766
7871
  }
7767
7872
  }
@@ -7774,7 +7879,7 @@ async function syncMemories(agent, configDir, log2) {
7774
7879
  }
7775
7880
  }
7776
7881
  async function downloadMemories(agent, memoryDir, log2, { force }) {
7777
- const localFiles = existsSync4(memoryDir) ? readdirSync2(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
7882
+ const localFiles = existsSync4(memoryDir) ? readdirSync3(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
7778
7883
  const localListHash = createHash2("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
7779
7884
  const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
7780
7885
  const prevDownload = lastDownloadHash.get(agent.agent_id);
@@ -7796,7 +7901,7 @@ async function downloadMemories(agent, memoryDir, log2, { force }) {
7796
7901
  const mem = dbMemories.memories[i];
7797
7902
  const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
7798
7903
  const slug = rawSlug || `memory-${i}`;
7799
- const filePath = join5(memoryDir, `${slug}.md`);
7904
+ const filePath = join6(memoryDir, `${slug}.md`);
7800
7905
  const desired = `---
7801
7906
  name: ${JSON.stringify(mem.name)}
7802
7907
  type: ${mem.type}
@@ -7808,7 +7913,7 @@ ${mem.content}
7808
7913
  if (existsSync4(filePath)) {
7809
7914
  let existing = "";
7810
7915
  try {
7811
- existing = readFileSync4(filePath, "utf-8");
7916
+ existing = readFileSync5(filePath, "utf-8");
7812
7917
  } catch {
7813
7918
  }
7814
7919
  if (existing === desired) continue;
@@ -7820,7 +7925,7 @@ ${mem.content}
7820
7925
  }
7821
7926
  }
7822
7927
  if (written > 0 || overwritten > 0) {
7823
- const updatedFiles = readdirSync2(memoryDir).filter((f) => f.endsWith(".md")).sort();
7928
+ const updatedFiles = readdirSync3(memoryDir).filter((f) => f.endsWith(".md")).sort();
7824
7929
  lastLocalFileHash.set(agent.agent_id, createHash2("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
7825
7930
  log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
7826
7931
  }
@@ -8004,11 +8109,11 @@ function startManager(opts) {
8004
8109
  try {
8005
8110
  const stateFile = getStateFile();
8006
8111
  if (existsSync4(stateFile)) {
8007
- const raw = readFileSync4(stateFile, "utf-8");
8112
+ const raw = readFileSync5(stateFile, "utf-8");
8008
8113
  const parsed = JSON.parse(raw);
8009
8114
  if (Array.isArray(parsed.agents)) {
8010
- state3.agents = parsed.agents;
8011
- log(`[startup] rehydrated ${state3.agents.length} agent state(s) from ${stateFile}`);
8115
+ state4.agents = parsed.agents;
8116
+ log(`[startup] rehydrated ${state4.agents.length} agent state(s) from ${stateFile}`);
8012
8117
  }
8013
8118
  if (parsed.circuitBreakerTrips && typeof parsed.circuitBreakerTrips === "object") {
8014
8119
  restartBreaker.hydrate(parsed.circuitBreakerTrips);
@@ -8020,7 +8125,7 @@ function startManager(opts) {
8020
8125
  log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
8021
8126
  }
8022
8127
  log(
8023
- `[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join5(homedir4(), ".augmented", "manager.log")}`
8128
+ `[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join6(homedir4(), ".augmented", "manager.log")}`
8024
8129
  );
8025
8130
  warnOnConflictingKanbanModes();
8026
8131
  deployMcpAssets();
@@ -8083,14 +8188,14 @@ function restartRunningChannelMcps(basenames) {
8083
8188
  }
8084
8189
  }
8085
8190
  function deployMcpAssets() {
8086
- const targetDir = join5(homedir4(), ".augmented", "_mcp");
8191
+ const targetDir = join6(homedir4(), ".augmented", "_mcp");
8087
8192
  mkdirSync2(targetDir, { recursive: true });
8088
8193
  const moduleDir = dirname(fileURLToPath(import.meta.url));
8089
8194
  let mcpSourceDir = "";
8090
8195
  let dir = moduleDir;
8091
8196
  for (let i = 0; i < 6; i++) {
8092
- const candidate = join5(dir, "dist", "mcp");
8093
- if (existsSync4(join5(candidate, "index.js"))) {
8197
+ const candidate = join6(dir, "dist", "mcp");
8198
+ if (existsSync4(join6(candidate, "index.js"))) {
8094
8199
  mcpSourceDir = candidate;
8095
8200
  break;
8096
8201
  }
@@ -8106,7 +8211,7 @@ function deployMcpAssets() {
8106
8211
  const fileHash = (p) => {
8107
8212
  try {
8108
8213
  if (!existsSync4(p)) return null;
8109
- return createHash2("sha256").update(readFileSync4(p)).digest("hex");
8214
+ return createHash2("sha256").update(readFileSync5(p)).digest("hex");
8110
8215
  } catch {
8111
8216
  return null;
8112
8217
  }
@@ -8117,8 +8222,8 @@ function deployMcpAssets() {
8117
8222
  "telegram-channel.js"
8118
8223
  ]);
8119
8224
  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);
8225
+ const src = join6(mcpSourceDir, file);
8226
+ const dst = join6(targetDir, file);
8122
8227
  if (!existsSync4(src)) continue;
8123
8228
  const before = fileHash(dst);
8124
8229
  try {
@@ -8136,16 +8241,16 @@ function deployMcpAssets() {
8136
8241
  log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
8137
8242
  restartRunningChannelMcps(changedBasenames);
8138
8243
  }
8139
- const localMcpPath = join5(targetDir, "index.js");
8244
+ const localMcpPath = join6(targetDir, "index.js");
8140
8245
  try {
8141
- const agentsDir = join5(homedir4(), ".augmented", "agents");
8246
+ const agentsDir = join6(homedir4(), ".augmented", "agents");
8142
8247
  if (existsSync4(agentsDir)) {
8143
- for (const entry of readdirSync2(agentsDir, { withFileTypes: true })) {
8248
+ for (const entry of readdirSync3(agentsDir, { withFileTypes: true })) {
8144
8249
  if (!entry.isDirectory()) continue;
8145
8250
  for (const subdir of ["provision", "project"]) {
8146
- const mcpJsonPath = join5(agentsDir, entry.name, subdir, ".mcp.json");
8251
+ const mcpJsonPath = join6(agentsDir, entry.name, subdir, ".mcp.json");
8147
8252
  try {
8148
- const raw = readFileSync4(mcpJsonPath, "utf-8");
8253
+ const raw = readFileSync5(mcpJsonPath, "utf-8");
8149
8254
  if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
8150
8255
  const mcpConfig = JSON.parse(raw);
8151
8256
  const augServer = mcpConfig.mcpServers?.["augmented"];