@askexenow/exe-os 0.8.65 → 0.8.69

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.
Files changed (54) hide show
  1. package/dist/bin/cleanup-stale-review-tasks.js +8 -7
  2. package/dist/bin/cli.js +204 -120
  3. package/dist/bin/exe-assign.js +11 -10
  4. package/dist/bin/exe-boot.js +83 -78
  5. package/dist/bin/exe-call.js +33 -1
  6. package/dist/bin/exe-cloud.js +3 -2
  7. package/dist/bin/exe-dispatch.js +31 -30
  8. package/dist/bin/exe-gateway.js +33 -32
  9. package/dist/bin/exe-heartbeat.js +21 -20
  10. package/dist/bin/exe-launch-agent.js +84 -19
  11. package/dist/bin/exe-link.js +16 -11
  12. package/dist/bin/exe-new-employee.js +20 -19
  13. package/dist/bin/exe-pending-messages.js +7 -6
  14. package/dist/bin/exe-pending-reviews.js +16 -15
  15. package/dist/bin/exe-rename.js +12 -11
  16. package/dist/bin/exe-review.js +4 -3
  17. package/dist/bin/exe-session-cleanup.js +20 -19
  18. package/dist/bin/exe-settings.js +3 -2
  19. package/dist/bin/exe-status.js +16 -15
  20. package/dist/bin/exe-team.js +4 -3
  21. package/dist/bin/git-sweep.js +31 -30
  22. package/dist/bin/install.js +284 -113
  23. package/dist/bin/scan-tasks.js +33 -32
  24. package/dist/bin/setup.js +114 -30
  25. package/dist/gateway/index.js +32 -31
  26. package/dist/hooks/bug-report-worker.js +58 -26
  27. package/dist/hooks/commit-complete.js +31 -30
  28. package/dist/hooks/ingest-worker.js +58 -57
  29. package/dist/hooks/post-compact.js +10 -9
  30. package/dist/hooks/pre-compact.js +31 -30
  31. package/dist/hooks/pre-tool-use.js +46 -14
  32. package/dist/hooks/prompt-ingest-worker.js +15 -14
  33. package/dist/hooks/prompt-submit.js +15 -14
  34. package/dist/hooks/response-ingest-worker.js +8 -7
  35. package/dist/hooks/session-end.js +14 -13
  36. package/dist/hooks/session-start.js +10 -9
  37. package/dist/hooks/stop.js +10 -9
  38. package/dist/hooks/subagent-stop.js +10 -9
  39. package/dist/hooks/summary-worker.js +41 -36
  40. package/dist/index.js +43 -42
  41. package/dist/lib/cloud-sync.js +16 -11
  42. package/dist/lib/employees.js +33 -1
  43. package/dist/lib/exe-daemon.js +56 -55
  44. package/dist/lib/messaging.js +9 -8
  45. package/dist/lib/tasks.js +27 -26
  46. package/dist/lib/tmux-routing.js +29 -28
  47. package/dist/mcp/server.js +94 -62
  48. package/dist/mcp/tools/create-task.js +60 -28
  49. package/dist/mcp/tools/list-tasks.js +10 -9
  50. package/dist/mcp/tools/send-message.js +11 -10
  51. package/dist/mcp/tools/update-task.js +21 -20
  52. package/dist/runtime/index.js +31 -30
  53. package/dist/tui/App.js +67 -35
  54. package/package.json +1 -1
@@ -118,14 +118,16 @@ __export(employees_exports, {
118
118
  isMultiInstance: () => isMultiInstance,
119
119
  loadEmployees: () => loadEmployees,
120
120
  loadEmployeesSync: () => loadEmployeesSync,
121
+ normalizeRosterCase: () => normalizeRosterCase,
121
122
  registerBinSymlinks: () => registerBinSymlinks,
122
123
  saveEmployees: () => saveEmployees,
123
124
  validateEmployeeName: () => validateEmployeeName
124
125
  });
125
126
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
126
- import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2 } from "fs";
127
+ import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
127
128
  import { execSync } from "child_process";
128
129
  import path2 from "path";
130
+ import os2 from "os";
129
131
  function validateEmployeeName(name) {
130
132
  if (!name) {
131
133
  return { valid: false, error: "Name is required" };
@@ -193,6 +195,36 @@ function addEmployee(employees, employee) {
193
195
  }
194
196
  return [...employees, normalized];
195
197
  }
198
+ async function normalizeRosterCase(rosterPath) {
199
+ const employees = await loadEmployees(rosterPath);
200
+ let changed = false;
201
+ for (const emp of employees) {
202
+ if (emp.name !== emp.name.toLowerCase()) {
203
+ const oldName = emp.name;
204
+ emp.name = emp.name.toLowerCase();
205
+ changed = true;
206
+ try {
207
+ const identityDir = path2.join(os2.homedir(), ".exe-os", "identity");
208
+ const oldPath = path2.join(identityDir, `${oldName}.md`);
209
+ const newPath = path2.join(identityDir, `${emp.name}.md`);
210
+ if (existsSync2(oldPath) && !existsSync2(newPath)) {
211
+ renameSync2(oldPath, newPath);
212
+ } else if (existsSync2(oldPath) && oldPath !== newPath) {
213
+ const content = readFileSync2(oldPath, "utf-8");
214
+ writeFileSync(newPath, content, "utf-8");
215
+ if (oldPath.toLowerCase() !== newPath.toLowerCase()) {
216
+ unlinkSync(oldPath);
217
+ }
218
+ }
219
+ } catch {
220
+ }
221
+ }
222
+ }
223
+ if (changed) {
224
+ await saveEmployees(employees, rosterPath);
225
+ }
226
+ return changed;
227
+ }
196
228
  function findExeBin() {
197
229
  try {
198
230
  return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
@@ -724,7 +724,7 @@ function isMainModule(importMetaUrl) {
724
724
  }
725
725
 
726
726
  // src/lib/cloud-sync.ts
727
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync5, readdirSync, mkdirSync as mkdirSync2, appendFileSync, unlinkSync, openSync, closeSync } from "fs";
727
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, readdirSync, mkdirSync as mkdirSync2, appendFileSync, unlinkSync as unlinkSync2, openSync, closeSync } from "fs";
728
728
  import crypto3 from "crypto";
729
729
  import path5 from "path";
730
730
  import { homedir } from "os";
@@ -745,9 +745,10 @@ init_config();
745
745
  // src/lib/employees.ts
746
746
  init_config();
747
747
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
748
- import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync3 } from "fs";
748
+ import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
749
749
  import { execSync } from "child_process";
750
750
  import path4 from "path";
751
+ import os3 from "os";
751
752
  var EMPLOYEES_PATH = path4.join(EXE_AI_DIR, "exe-employees.json");
752
753
 
753
754
  // src/lib/cloud-sync.ts
@@ -1416,9 +1416,10 @@ var init_config = __esm({
1416
1416
 
1417
1417
  // src/lib/employees.ts
1418
1418
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
1419
- import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync4 } from "fs";
1419
+ import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync4, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
1420
1420
  import { execSync as execSync3 } from "child_process";
1421
1421
  import path4 from "path";
1422
+ import os4 from "os";
1422
1423
  function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
1423
1424
  if (!existsSync4(employeesPath)) return [];
1424
1425
  try {
@@ -1447,7 +1448,7 @@ var init_employees = __esm({
1447
1448
  });
1448
1449
 
1449
1450
  // src/lib/license.ts
1450
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
1451
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
1451
1452
  import { randomUUID } from "crypto";
1452
1453
  import path5 from "path";
1453
1454
  import { jwtVerify, importSPKI } from "jose";
@@ -1550,11 +1551,11 @@ var init_plan_limits = __esm({
1550
1551
  // src/lib/notifications.ts
1551
1552
  import crypto from "crypto";
1552
1553
  import path7 from "path";
1553
- import os4 from "os";
1554
+ import os5 from "os";
1554
1555
  import {
1555
1556
  readFileSync as readFileSync7,
1556
1557
  readdirSync,
1557
- unlinkSync,
1558
+ unlinkSync as unlinkSync2,
1558
1559
  existsSync as existsSync7,
1559
1560
  rmdirSync
1560
1561
  } from "fs";
@@ -2130,7 +2131,7 @@ var init_tasks_crud = __esm({
2130
2131
 
2131
2132
  // src/lib/tasks-review.ts
2132
2133
  import path9 from "path";
2133
- import { existsSync as existsSync9, readdirSync as readdirSync2, unlinkSync as unlinkSync2 } from "fs";
2134
+ import { existsSync as existsSync9, readdirSync as readdirSync2, unlinkSync as unlinkSync3 } from "fs";
2134
2135
  async function countPendingReviews(sessionScope) {
2135
2136
  const client = getClient();
2136
2137
  if (sessionScope) {
@@ -2315,7 +2316,7 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
2315
2316
  if (existsSync9(cacheDir)) {
2316
2317
  for (const f of readdirSync2(cacheDir)) {
2317
2318
  if (f.startsWith("review-notified-")) {
2318
- unlinkSync2(path9.join(cacheDir, f));
2319
+ unlinkSync3(path9.join(cacheDir, f));
2319
2320
  }
2320
2321
  }
2321
2322
  }
@@ -2921,7 +2922,7 @@ __export(tasks_exports, {
2921
2922
  writeCheckpoint: () => writeCheckpoint
2922
2923
  });
2923
2924
  import path12 from "path";
2924
- import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, unlinkSync as unlinkSync3 } from "fs";
2925
+ import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, unlinkSync as unlinkSync4 } from "fs";
2925
2926
  async function createTask(input) {
2926
2927
  const result2 = await createTaskCore(input);
2927
2928
  if (!input.skipDispatch && result2.status !== "blocked" && !process.env.VITEST) {
@@ -2944,10 +2945,10 @@ async function updateTask(input) {
2944
2945
  const cachePath = path12.join(cacheDir, `current-task-${agent}.json`);
2945
2946
  if (input.status === "in_progress") {
2946
2947
  mkdirSync4(cacheDir, { recursive: true });
2947
- writeFileSync4(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
2948
+ writeFileSync5(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
2948
2949
  } else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled") {
2949
2950
  try {
2950
- unlinkSync3(cachePath);
2951
+ unlinkSync4(cachePath);
2951
2952
  } catch {
2952
2953
  }
2953
2954
  }
@@ -3389,11 +3390,11 @@ __export(tmux_routing_exports, {
3389
3390
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
3390
3391
  });
3391
3392
  import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
3392
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync10, appendFileSync } from "fs";
3393
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync10, appendFileSync } from "fs";
3393
3394
  import path13 from "path";
3394
- import os5 from "os";
3395
+ import os6 from "os";
3395
3396
  import { fileURLToPath } from "url";
3396
- import { unlinkSync as unlinkSync4 } from "fs";
3397
+ import { unlinkSync as unlinkSync5 } from "fs";
3397
3398
  function spawnLockPath(sessionName) {
3398
3399
  return path13.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
3399
3400
  }
@@ -3420,12 +3421,12 @@ function acquireSpawnLock(sessionName) {
3420
3421
  } catch {
3421
3422
  }
3422
3423
  }
3423
- writeFileSync5(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
3424
+ writeFileSync6(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
3424
3425
  return true;
3425
3426
  }
3426
3427
  function releaseSpawnLock(sessionName) {
3427
3428
  try {
3428
- unlinkSync4(spawnLockPath(sessionName));
3429
+ unlinkSync5(spawnLockPath(sessionName));
3429
3430
  } catch {
3430
3431
  }
3431
3432
  }
@@ -3507,7 +3508,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
3507
3508
  }
3508
3509
  const rootExe = extractRootExe(parentExe) ?? parentExe;
3509
3510
  const filePath = path13.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
3510
- writeFileSync5(filePath, JSON.stringify({
3511
+ writeFileSync6(filePath, JSON.stringify({
3511
3512
  parentExe: rootExe,
3512
3513
  dispatchedBy: dispatchedBy || rootExe,
3513
3514
  registeredAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -3594,7 +3595,7 @@ function readDebounceState() {
3594
3595
  function writeDebounceState(state) {
3595
3596
  try {
3596
3597
  if (!existsSync10(SESSION_CACHE)) mkdirSync5(SESSION_CACHE, { recursive: true });
3597
- writeFileSync5(DEBOUNCE_FILE, JSON.stringify(state));
3598
+ writeFileSync6(DEBOUNCE_FILE, JSON.stringify(state));
3598
3599
  } catch {
3599
3600
  }
3600
3601
  }
@@ -3783,7 +3784,7 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
3783
3784
  const transport = getTransport();
3784
3785
  const sessionName = employeeSessionName(employeeName2, exeSession2, opts?.instance);
3785
3786
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName2}${opts.instance}` : employeeName2;
3786
- const logDir = path13.join(os5.homedir(), ".exe-os", "session-logs");
3787
+ const logDir = path13.join(os6.homedir(), ".exe-os", "session-logs");
3787
3788
  const logFile = path13.join(logDir, `${instanceLabel}-${Date.now()}.log`);
3788
3789
  if (!existsSync10(logDir)) {
3789
3790
  mkdirSync5(logDir, { recursive: true });
@@ -3799,7 +3800,7 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
3799
3800
  } catch {
3800
3801
  }
3801
3802
  try {
3802
- const claudeJsonPath = path13.join(os5.homedir(), ".claude.json");
3803
+ const claudeJsonPath = path13.join(os6.homedir(), ".claude.json");
3803
3804
  let claudeJson = {};
3804
3805
  try {
3805
3806
  claudeJson = JSON.parse(readFileSync9(claudeJsonPath, "utf8"));
@@ -3810,11 +3811,11 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
3810
3811
  const trustDir = opts?.cwd ?? projectDir2;
3811
3812
  if (!projects[trustDir]) projects[trustDir] = {};
3812
3813
  projects[trustDir].hasTrustDialogAccepted = true;
3813
- writeFileSync5(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
3814
+ writeFileSync6(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
3814
3815
  } catch {
3815
3816
  }
3816
3817
  try {
3817
- const settingsDir = path13.join(os5.homedir(), ".claude", "projects");
3818
+ const settingsDir = path13.join(os6.homedir(), ".claude", "projects");
3818
3819
  const normalizedKey = (opts?.cwd ?? projectDir2).replace(/\//g, "-").replace(/^-/, "");
3819
3820
  const projSettingsDir = path13.join(settingsDir, normalizedKey);
3820
3821
  const settingsPath = path13.join(projSettingsDir, "settings.json");
@@ -3849,7 +3850,7 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
3849
3850
  perms.allow = allow;
3850
3851
  settings.permissions = perms;
3851
3852
  mkdirSync5(projSettingsDir, { recursive: true });
3852
- writeFileSync5(settingsPath, JSON.stringify(settings, null, 2) + "\n");
3853
+ writeFileSync6(settingsPath, JSON.stringify(settings, null, 2) + "\n");
3853
3854
  }
3854
3855
  } catch {
3855
3856
  }
@@ -3862,7 +3863,7 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
3862
3863
  let legacyFallbackWarned = false;
3863
3864
  if (!useExeAgent && !useBinSymlink) {
3864
3865
  const identityPath = path13.join(
3865
- os5.homedir(),
3866
+ os6.homedir(),
3866
3867
  ".exe-os",
3867
3868
  "identity",
3868
3869
  `${employeeName2}.md`
@@ -3892,7 +3893,7 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
3892
3893
  }
3893
3894
  let sessionContextFlag = "";
3894
3895
  try {
3895
- const ctxDir = path13.join(os5.homedir(), ".exe-os", "session-cache");
3896
+ const ctxDir = path13.join(os6.homedir(), ".exe-os", "session-cache");
3896
3897
  mkdirSync5(ctxDir, { recursive: true });
3897
3898
  const ctxFile = path13.join(ctxDir, `session-context-${sessionName}.md`);
3898
3899
  const ctxContent = [
@@ -3901,7 +3902,7 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
3901
3902
  `Your parent exe session is ${exeSession2}.`,
3902
3903
  `Your employees (if any) use the -${exeSession2} suffix (e.g., tom-${exeSession2}).`
3903
3904
  ].join("\n");
3904
- writeFileSync5(ctxFile, ctxContent);
3905
+ writeFileSync6(ctxFile, ctxContent);
3905
3906
  sessionContextFlag = ` --append-system-prompt-file ${ctxFile}`;
3906
3907
  } catch {
3907
3908
  }
@@ -3940,7 +3941,7 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
3940
3941
  try {
3941
3942
  const mySession = getMySession();
3942
3943
  const dispatchInfo = path13.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
3943
- writeFileSync5(dispatchInfo, JSON.stringify({
3944
+ writeFileSync6(dispatchInfo, JSON.stringify({
3944
3945
  dispatchedBy: mySession,
3945
3946
  rootExe: exeSession2,
3946
3947
  provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : "anthropic",
@@ -4003,13 +4004,13 @@ var init_tmux_routing = __esm({
4003
4004
  init_provider_table();
4004
4005
  init_intercom_queue();
4005
4006
  init_plan_limits();
4006
- SPAWN_LOCK_DIR = path13.join(os5.homedir(), ".exe-os", "spawn-locks");
4007
- SESSION_CACHE = path13.join(os5.homedir(), ".exe-os", "session-cache");
4007
+ SPAWN_LOCK_DIR = path13.join(os6.homedir(), ".exe-os", "spawn-locks");
4008
+ SESSION_CACHE = path13.join(os6.homedir(), ".exe-os", "session-cache");
4008
4009
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
4009
4010
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
4010
4011
  VERIFY_PANE_LINES = 200;
4011
4012
  INTERCOM_DEBOUNCE_MS = 3e4;
4012
- INTERCOM_LOG2 = path13.join(os5.homedir(), ".exe-os", "intercom.log");
4013
+ INTERCOM_LOG2 = path13.join(os6.homedir(), ".exe-os", "intercom.log");
4013
4014
  DEBOUNCE_FILE = path13.join(SESSION_CACHE, "intercom-debounce.json");
4014
4015
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
4015
4016
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -4449,11 +4450,11 @@ init_database();
4449
4450
  import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
4450
4451
  import { existsSync as existsSync11 } from "fs";
4451
4452
  import path14 from "path";
4452
- import os6 from "os";
4453
+ import os7 from "os";
4453
4454
  var SERVICE = "exe-mem";
4454
4455
  var ACCOUNT = "master-key";
4455
4456
  function getKeyDir() {
4456
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path14.join(os6.homedir(), ".exe-os");
4457
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path14.join(os7.homedir(), ".exe-os");
4457
4458
  }
4458
4459
  function getKeyPath() {
4459
4460
  return path14.join(getKeyDir(), "master.key");
@@ -5003,9 +5003,10 @@ var init_intercom_queue = __esm({
5003
5003
 
5004
5004
  // src/lib/employees.ts
5005
5005
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
5006
- import { existsSync as existsSync8, symlinkSync, readlinkSync, readFileSync as readFileSync7 } from "fs";
5006
+ import { existsSync as existsSync8, symlinkSync, readlinkSync, readFileSync as readFileSync7, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "fs";
5007
5007
  import { execSync as execSync3 } from "child_process";
5008
5008
  import path9 from "path";
5009
+ import os6 from "os";
5009
5010
  function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
5010
5011
  if (!existsSync8(employeesPath)) return [];
5011
5012
  try {
@@ -5114,11 +5115,11 @@ var init_plan_limits = __esm({
5114
5115
  // src/lib/notifications.ts
5115
5116
  import crypto2 from "crypto";
5116
5117
  import path11 from "path";
5117
- import os6 from "os";
5118
+ import os7 from "os";
5118
5119
  import {
5119
5120
  readFileSync as readFileSync9,
5120
5121
  readdirSync as readdirSync2,
5121
- unlinkSync as unlinkSync2,
5122
+ unlinkSync as unlinkSync3,
5122
5123
  existsSync as existsSync10,
5123
5124
  rmdirSync
5124
5125
  } from "fs";
@@ -5639,7 +5640,7 @@ var init_tasks_crud = __esm({
5639
5640
 
5640
5641
  // src/lib/tasks-review.ts
5641
5642
  import path13 from "path";
5642
- import { existsSync as existsSync12, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
5643
+ import { existsSync as existsSync12, readdirSync as readdirSync3, unlinkSync as unlinkSync4 } from "fs";
5643
5644
  async function countPendingReviews(sessionScope) {
5644
5645
  const client = getClient();
5645
5646
  if (sessionScope) {
@@ -5824,7 +5825,7 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
5824
5825
  if (existsSync12(cacheDir)) {
5825
5826
  for (const f of readdirSync3(cacheDir)) {
5826
5827
  if (f.startsWith("review-notified-")) {
5827
- unlinkSync3(path13.join(cacheDir, f));
5828
+ unlinkSync4(path13.join(cacheDir, f));
5828
5829
  }
5829
5830
  }
5830
5831
  }
@@ -6430,7 +6431,7 @@ __export(tasks_exports, {
6430
6431
  writeCheckpoint: () => writeCheckpoint
6431
6432
  });
6432
6433
  import path16 from "path";
6433
- import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync6, unlinkSync as unlinkSync4 } from "fs";
6434
+ import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, unlinkSync as unlinkSync5 } from "fs";
6434
6435
  async function createTask(input) {
6435
6436
  const result = await createTaskCore(input);
6436
6437
  if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
@@ -6453,10 +6454,10 @@ async function updateTask(input) {
6453
6454
  const cachePath = path16.join(cacheDir, `current-task-${agent}.json`);
6454
6455
  if (input.status === "in_progress") {
6455
6456
  mkdirSync6(cacheDir, { recursive: true });
6456
- writeFileSync4(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
6457
+ writeFileSync5(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
6457
6458
  } else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled") {
6458
6459
  try {
6459
- unlinkSync4(cachePath);
6460
+ unlinkSync5(cachePath);
6460
6461
  } catch {
6461
6462
  }
6462
6463
  }
@@ -6898,11 +6899,11 @@ __export(tmux_routing_exports, {
6898
6899
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
6899
6900
  });
6900
6901
  import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
6901
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync5, mkdirSync as mkdirSync7, existsSync as existsSync13, appendFileSync } from "fs";
6902
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, existsSync as existsSync13, appendFileSync } from "fs";
6902
6903
  import path17 from "path";
6903
- import os7 from "os";
6904
+ import os8 from "os";
6904
6905
  import { fileURLToPath as fileURLToPath2 } from "url";
6905
- import { unlinkSync as unlinkSync5 } from "fs";
6906
+ import { unlinkSync as unlinkSync6 } from "fs";
6906
6907
  function spawnLockPath(sessionName) {
6907
6908
  return path17.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
6908
6909
  }
@@ -6929,12 +6930,12 @@ function acquireSpawnLock2(sessionName) {
6929
6930
  } catch {
6930
6931
  }
6931
6932
  }
6932
- writeFileSync5(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
6933
+ writeFileSync6(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
6933
6934
  return true;
6934
6935
  }
6935
6936
  function releaseSpawnLock2(sessionName) {
6936
6937
  try {
6937
- unlinkSync5(spawnLockPath(sessionName));
6938
+ unlinkSync6(spawnLockPath(sessionName));
6938
6939
  } catch {
6939
6940
  }
6940
6941
  }
@@ -7016,7 +7017,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
7016
7017
  }
7017
7018
  const rootExe = extractRootExe(parentExe) ?? parentExe;
7018
7019
  const filePath = path17.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
7019
- writeFileSync5(filePath, JSON.stringify({
7020
+ writeFileSync6(filePath, JSON.stringify({
7020
7021
  parentExe: rootExe,
7021
7022
  dispatchedBy: dispatchedBy || rootExe,
7022
7023
  registeredAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -7103,7 +7104,7 @@ function readDebounceState() {
7103
7104
  function writeDebounceState(state) {
7104
7105
  try {
7105
7106
  if (!existsSync13(SESSION_CACHE)) mkdirSync7(SESSION_CACHE, { recursive: true });
7106
- writeFileSync5(DEBOUNCE_FILE, JSON.stringify(state));
7107
+ writeFileSync6(DEBOUNCE_FILE, JSON.stringify(state));
7107
7108
  } catch {
7108
7109
  }
7109
7110
  }
@@ -7292,7 +7293,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7292
7293
  const transport = getTransport();
7293
7294
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
7294
7295
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
7295
- const logDir = path17.join(os7.homedir(), ".exe-os", "session-logs");
7296
+ const logDir = path17.join(os8.homedir(), ".exe-os", "session-logs");
7296
7297
  const logFile = path17.join(logDir, `${instanceLabel}-${Date.now()}.log`);
7297
7298
  if (!existsSync13(logDir)) {
7298
7299
  mkdirSync7(logDir, { recursive: true });
@@ -7308,7 +7309,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7308
7309
  } catch {
7309
7310
  }
7310
7311
  try {
7311
- const claudeJsonPath = path17.join(os7.homedir(), ".claude.json");
7312
+ const claudeJsonPath = path17.join(os8.homedir(), ".claude.json");
7312
7313
  let claudeJson = {};
7313
7314
  try {
7314
7315
  claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
@@ -7319,11 +7320,11 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7319
7320
  const trustDir = opts?.cwd ?? projectDir;
7320
7321
  if (!projects[trustDir]) projects[trustDir] = {};
7321
7322
  projects[trustDir].hasTrustDialogAccepted = true;
7322
- writeFileSync5(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
7323
+ writeFileSync6(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
7323
7324
  } catch {
7324
7325
  }
7325
7326
  try {
7326
- const settingsDir = path17.join(os7.homedir(), ".claude", "projects");
7327
+ const settingsDir = path17.join(os8.homedir(), ".claude", "projects");
7327
7328
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
7328
7329
  const projSettingsDir = path17.join(settingsDir, normalizedKey);
7329
7330
  const settingsPath = path17.join(projSettingsDir, "settings.json");
@@ -7358,7 +7359,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7358
7359
  perms.allow = allow;
7359
7360
  settings.permissions = perms;
7360
7361
  mkdirSync7(projSettingsDir, { recursive: true });
7361
- writeFileSync5(settingsPath, JSON.stringify(settings, null, 2) + "\n");
7362
+ writeFileSync6(settingsPath, JSON.stringify(settings, null, 2) + "\n");
7362
7363
  }
7363
7364
  } catch {
7364
7365
  }
@@ -7371,7 +7372,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7371
7372
  let legacyFallbackWarned = false;
7372
7373
  if (!useExeAgent && !useBinSymlink) {
7373
7374
  const identityPath = path17.join(
7374
- os7.homedir(),
7375
+ os8.homedir(),
7375
7376
  ".exe-os",
7376
7377
  "identity",
7377
7378
  `${employeeName}.md`
@@ -7401,7 +7402,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7401
7402
  }
7402
7403
  let sessionContextFlag = "";
7403
7404
  try {
7404
- const ctxDir = path17.join(os7.homedir(), ".exe-os", "session-cache");
7405
+ const ctxDir = path17.join(os8.homedir(), ".exe-os", "session-cache");
7405
7406
  mkdirSync7(ctxDir, { recursive: true });
7406
7407
  const ctxFile = path17.join(ctxDir, `session-context-${sessionName}.md`);
7407
7408
  const ctxContent = [
@@ -7410,7 +7411,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7410
7411
  `Your parent exe session is ${exeSession}.`,
7411
7412
  `Your employees (if any) use the -${exeSession} suffix (e.g., tom-${exeSession}).`
7412
7413
  ].join("\n");
7413
- writeFileSync5(ctxFile, ctxContent);
7414
+ writeFileSync6(ctxFile, ctxContent);
7414
7415
  sessionContextFlag = ` --append-system-prompt-file ${ctxFile}`;
7415
7416
  } catch {
7416
7417
  }
@@ -7449,7 +7450,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7449
7450
  try {
7450
7451
  const mySession = getMySession();
7451
7452
  const dispatchInfo = path17.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
7452
- writeFileSync5(dispatchInfo, JSON.stringify({
7453
+ writeFileSync6(dispatchInfo, JSON.stringify({
7453
7454
  dispatchedBy: mySession,
7454
7455
  rootExe: exeSession,
7455
7456
  provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : "anthropic",
@@ -7512,13 +7513,13 @@ var init_tmux_routing = __esm({
7512
7513
  init_provider_table();
7513
7514
  init_intercom_queue();
7514
7515
  init_plan_limits();
7515
- SPAWN_LOCK_DIR = path17.join(os7.homedir(), ".exe-os", "spawn-locks");
7516
- SESSION_CACHE = path17.join(os7.homedir(), ".exe-os", "session-cache");
7516
+ SPAWN_LOCK_DIR = path17.join(os8.homedir(), ".exe-os", "spawn-locks");
7517
+ SESSION_CACHE = path17.join(os8.homedir(), ".exe-os", "session-cache");
7517
7518
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
7518
7519
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
7519
7520
  VERIFY_PANE_LINES = 200;
7520
7521
  INTERCOM_DEBOUNCE_MS = 3e4;
7521
- INTERCOM_LOG2 = path17.join(os7.homedir(), ".exe-os", "intercom.log");
7522
+ INTERCOM_LOG2 = path17.join(os8.homedir(), ".exe-os", "intercom.log");
7522
7523
  DEBOUNCE_FILE = path17.join(SESSION_CACHE, "intercom-debounce.json");
7523
7524
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
7524
7525
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -7777,10 +7778,10 @@ var init_messaging = __esm({
7777
7778
  });
7778
7779
 
7779
7780
  // src/automation/trigger-engine.ts
7780
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync6, existsSync as existsSync14, mkdirSync as mkdirSync8 } from "fs";
7781
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync7, existsSync as existsSync14, mkdirSync as mkdirSync8 } from "fs";
7781
7782
  import { randomUUID as randomUUID8 } from "crypto";
7782
7783
  import path18 from "path";
7783
- import os8 from "os";
7784
+ import os9 from "os";
7784
7785
  function substituteTemplate(template, record) {
7785
7786
  return template.replace(
7786
7787
  /\{\{(\w+(?:\.\w+)*)\}\}/g,
@@ -8070,7 +8071,7 @@ var TRIGGERS_PATH, GRAPH_API_VERSION;
8070
8071
  var init_trigger_engine = __esm({
8071
8072
  "src/automation/trigger-engine.ts"() {
8072
8073
  "use strict";
8073
- TRIGGERS_PATH = path18.join(os8.homedir(), ".exe-os", "triggers.json");
8074
+ TRIGGERS_PATH = path18.join(os9.homedir(), ".exe-os", "triggers.json");
8074
8075
  GRAPH_API_VERSION = "v21.0";
8075
8076
  }
8076
8077
  });
@@ -8135,7 +8136,7 @@ var init_crm_webhook = __esm({
8135
8136
  // src/bin/exe-gateway.ts
8136
8137
  import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
8137
8138
  import path19 from "path";
8138
- import os9 from "os";
8139
+ import os10 from "os";
8139
8140
 
8140
8141
  // src/gateway/webhook-server.ts
8141
8142
  import {
@@ -8969,7 +8970,7 @@ var BotRegistry = class {
8969
8970
  };
8970
8971
 
8971
8972
  // src/bin/exe-gateway.ts
8972
- var CONFIG_DIR = path19.join(os9.homedir(), ".exe-os");
8973
+ var CONFIG_DIR = path19.join(os10.homedir(), ".exe-os");
8973
8974
  var CONFIG_PATH3 = path19.join(CONFIG_DIR, "gateway.json");
8974
8975
  var DEFAULT_PORT = 3100;
8975
8976
  function loadConfig2() {