@askexenow/exe-os 0.8.90 → 0.8.92

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 (44) hide show
  1. package/dist/bin/backfill-conversations.js +13 -1
  2. package/dist/bin/backfill-responses.js +13 -1
  3. package/dist/bin/backfill-vectors.js +13 -1
  4. package/dist/bin/cli.js +45 -33
  5. package/dist/bin/exe-assign.js +16 -4
  6. package/dist/bin/exe-boot.js +37 -25
  7. package/dist/bin/exe-gateway.js +39 -27
  8. package/dist/bin/exe-link.js +13 -1
  9. package/dist/bin/exe-rename.js +13 -1
  10. package/dist/bin/exe-search.js +13 -1
  11. package/dist/bin/exe-session-cleanup.js +33 -21
  12. package/dist/bin/git-sweep.js +28 -16
  13. package/dist/bin/scan-tasks.js +30 -18
  14. package/dist/bin/setup.js +22 -10
  15. package/dist/gateway/index.js +37 -25
  16. package/dist/hooks/commit-complete.js +28 -16
  17. package/dist/hooks/error-recall.js +13 -1
  18. package/dist/hooks/ingest-worker.js +33 -21
  19. package/dist/hooks/instructions-loaded.js +18 -6
  20. package/dist/hooks/notification.js +16 -4
  21. package/dist/hooks/post-compact.js +20 -8
  22. package/dist/hooks/pre-compact.js +28 -16
  23. package/dist/hooks/pre-tool-use.js +23 -11
  24. package/dist/hooks/prompt-ingest-worker.js +13 -1
  25. package/dist/hooks/prompt-submit.js +23 -11
  26. package/dist/hooks/response-ingest-worker.js +13 -1
  27. package/dist/hooks/session-end.js +29 -17
  28. package/dist/hooks/session-start.js +22 -10
  29. package/dist/hooks/stop.js +20 -8
  30. package/dist/hooks/subagent-stop.js +20 -8
  31. package/dist/hooks/summary-worker.js +26 -14
  32. package/dist/index.js +32 -20
  33. package/dist/lib/cloud-sync.js +16 -4
  34. package/dist/lib/database.js +13 -1
  35. package/dist/lib/db-daemon-client.js +13 -1
  36. package/dist/lib/device-registry.js +15 -3
  37. package/dist/lib/embedder.js +13 -1
  38. package/dist/lib/exe-daemon-client.js +13 -1
  39. package/dist/lib/exe-daemon.js +34 -22
  40. package/dist/lib/hybrid-search.js +13 -1
  41. package/dist/mcp/server.js +41 -29
  42. package/dist/runtime/index.js +28 -16
  43. package/dist/tui/App.js +30 -18
  44. package/package.json +1 -1
@@ -1689,6 +1689,7 @@ ${p.content}`).join("\n\n");
1689
1689
 
1690
1690
  // src/lib/exe-daemon-client.ts
1691
1691
  import net from "net";
1692
+ import os4 from "os";
1692
1693
  import { spawn } from "child_process";
1693
1694
  import { randomUUID as randomUUID2 } from "crypto";
1694
1695
  import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -1752,6 +1753,15 @@ function findPackageRoot() {
1752
1753
  return null;
1753
1754
  }
1754
1755
  function spawnDaemon() {
1756
+ const freeGB = os4.freemem() / (1024 * 1024 * 1024);
1757
+ const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
1758
+ if (freeGB < 1.5 && totalGB <= 8) {
1759
+ process.stderr.write(
1760
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
1761
+ `
1762
+ );
1763
+ return;
1764
+ }
1755
1765
  const pkgRoot = findPackageRoot();
1756
1766
  if (!pkgRoot) {
1757
1767
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -1772,7 +1782,9 @@ function spawnDaemon() {
1772
1782
  stderrFd = openSync(logPath, "a");
1773
1783
  } catch {
1774
1784
  }
1775
- const child = spawn(process.execPath, [resolvedPath], {
1785
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
1786
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
1787
+ const child = spawn(process.execPath, nodeArgs, {
1776
1788
  detached: true,
1777
1789
  stdio: ["ignore", "ignore", stderrFd],
1778
1790
  env: {
@@ -1689,6 +1689,7 @@ ${p.content}`).join("\n\n");
1689
1689
 
1690
1690
  // src/lib/exe-daemon-client.ts
1691
1691
  import net from "net";
1692
+ import os4 from "os";
1692
1693
  import { spawn } from "child_process";
1693
1694
  import { randomUUID as randomUUID2 } from "crypto";
1694
1695
  import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -1752,6 +1753,15 @@ function findPackageRoot() {
1752
1753
  return null;
1753
1754
  }
1754
1755
  function spawnDaemon() {
1756
+ const freeGB = os4.freemem() / (1024 * 1024 * 1024);
1757
+ const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
1758
+ if (freeGB < 1.5 && totalGB <= 8) {
1759
+ process.stderr.write(
1760
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
1761
+ `
1762
+ );
1763
+ return;
1764
+ }
1755
1765
  const pkgRoot = findPackageRoot();
1756
1766
  if (!pkgRoot) {
1757
1767
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -1772,7 +1782,9 @@ function spawnDaemon() {
1772
1782
  stderrFd = openSync(logPath, "a");
1773
1783
  } catch {
1774
1784
  }
1775
- const child = spawn(process.execPath, [resolvedPath], {
1785
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
1786
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
1787
+ const child = spawn(process.execPath, nodeArgs, {
1776
1788
  detached: true,
1777
1789
  stdio: ["ignore", "ignore", stderrFd],
1778
1790
  env: {
@@ -1691,6 +1691,7 @@ ${p.content}`).join("\n\n");
1691
1691
 
1692
1692
  // src/lib/exe-daemon-client.ts
1693
1693
  import net from "net";
1694
+ import os4 from "os";
1694
1695
  import { spawn } from "child_process";
1695
1696
  import { randomUUID as randomUUID2 } from "crypto";
1696
1697
  import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -1754,6 +1755,15 @@ function findPackageRoot() {
1754
1755
  return null;
1755
1756
  }
1756
1757
  function spawnDaemon() {
1758
+ const freeGB = os4.freemem() / (1024 * 1024 * 1024);
1759
+ const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
1760
+ if (freeGB < 1.5 && totalGB <= 8) {
1761
+ process.stderr.write(
1762
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
1763
+ `
1764
+ );
1765
+ return;
1766
+ }
1757
1767
  const pkgRoot = findPackageRoot();
1758
1768
  if (!pkgRoot) {
1759
1769
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -1774,7 +1784,9 @@ function spawnDaemon() {
1774
1784
  stderrFd = openSync(logPath, "a");
1775
1785
  } catch {
1776
1786
  }
1777
- const child = spawn(process.execPath, [resolvedPath], {
1787
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
1788
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
1789
+ const child = spawn(process.execPath, nodeArgs, {
1778
1790
  detached: true,
1779
1791
  stdio: ["ignore", "ignore", stderrFd],
1780
1792
  env: {
package/dist/bin/cli.js CHANGED
@@ -1389,6 +1389,7 @@ var init_db_retry = __esm({
1389
1389
 
1390
1390
  // src/lib/exe-daemon-client.ts
1391
1391
  import net from "net";
1392
+ import os6 from "os";
1392
1393
  import { spawn } from "child_process";
1393
1394
  import { randomUUID } from "crypto";
1394
1395
  import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
@@ -1452,6 +1453,15 @@ function findPackageRoot() {
1452
1453
  return null;
1453
1454
  }
1454
1455
  function spawnDaemon() {
1456
+ const freeGB = os6.freemem() / (1024 * 1024 * 1024);
1457
+ const totalGB = os6.totalmem() / (1024 * 1024 * 1024);
1458
+ if (freeGB < 1.5 && totalGB <= 8) {
1459
+ process.stderr.write(
1460
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
1461
+ `
1462
+ );
1463
+ return;
1464
+ }
1455
1465
  const pkgRoot = findPackageRoot();
1456
1466
  if (!pkgRoot) {
1457
1467
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -1472,7 +1482,9 @@ function spawnDaemon() {
1472
1482
  stderrFd = openSync(logPath, "a");
1473
1483
  } catch {
1474
1484
  }
1475
- const child = spawn(process.execPath, [resolvedPath], {
1485
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
1486
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
1487
+ const child = spawn(process.execPath, nodeArgs, {
1476
1488
  detached: true,
1477
1489
  stdio: ["ignore", "ignore", stderrFd],
1478
1490
  env: {
@@ -6972,7 +6984,7 @@ __export(session_registry_exports, {
6972
6984
  import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, existsSync as existsSync11 } from "fs";
6973
6985
  import { execSync as execSync3 } from "child_process";
6974
6986
  import path12 from "path";
6975
- import os6 from "os";
6987
+ import os7 from "os";
6976
6988
  function registerSession(entry) {
6977
6989
  const dir = path12.dirname(REGISTRY_PATH);
6978
6990
  if (!existsSync11(dir)) {
@@ -7018,7 +7030,7 @@ var REGISTRY_PATH;
7018
7030
  var init_session_registry = __esm({
7019
7031
  "src/lib/session-registry.ts"() {
7020
7032
  "use strict";
7021
- REGISTRY_PATH = path12.join(os6.homedir(), ".exe-os", "session-registry.json");
7033
+ REGISTRY_PATH = path12.join(os7.homedir(), ".exe-os", "session-registry.json");
7022
7034
  }
7023
7035
  });
7024
7036
 
@@ -7276,7 +7288,7 @@ var init_agent_config = __esm({
7276
7288
  // src/lib/intercom-queue.ts
7277
7289
  import { readFileSync as readFileSync10, writeFileSync as writeFileSync8, renameSync as renameSync3, existsSync as existsSync13, mkdirSync as mkdirSync9 } from "fs";
7278
7290
  import path14 from "path";
7279
- import os7 from "os";
7291
+ import os8 from "os";
7280
7292
  function ensureDir() {
7281
7293
  const dir = path14.dirname(QUEUE_PATH);
7282
7294
  if (!existsSync13(dir)) mkdirSync9(dir, { recursive: true });
@@ -7316,9 +7328,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
7316
7328
  var init_intercom_queue = __esm({
7317
7329
  "src/lib/intercom-queue.ts"() {
7318
7330
  "use strict";
7319
- QUEUE_PATH = path14.join(os7.homedir(), ".exe-os", "intercom-queue.json");
7331
+ QUEUE_PATH = path14.join(os8.homedir(), ".exe-os", "intercom-queue.json");
7320
7332
  TTL_MS = 60 * 60 * 1e3;
7321
- INTERCOM_LOG = path14.join(os7.homedir(), ".exe-os", "intercom.log");
7333
+ INTERCOM_LOG = path14.join(os8.homedir(), ".exe-os", "intercom.log");
7322
7334
  }
7323
7335
  });
7324
7336
 
@@ -7403,7 +7415,7 @@ var init_plan_limits = __esm({
7403
7415
  // src/lib/notifications.ts
7404
7416
  import crypto5 from "crypto";
7405
7417
  import path16 from "path";
7406
- import os8 from "os";
7418
+ import os9 from "os";
7407
7419
  import {
7408
7420
  readFileSync as readFileSync12,
7409
7421
  readdirSync as readdirSync3,
@@ -7534,7 +7546,7 @@ __export(tasks_crud_exports, {
7534
7546
  });
7535
7547
  import crypto7 from "crypto";
7536
7548
  import path17 from "path";
7537
- import os9 from "os";
7549
+ import os10 from "os";
7538
7550
  import { execSync as execSync6 } from "child_process";
7539
7551
  import { mkdir as mkdir5, writeFile as writeFile5, appendFile } from "fs/promises";
7540
7552
  import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
@@ -7749,7 +7761,7 @@ ${laneWarning}` : laneWarning;
7749
7761
  });
7750
7762
  if (input.baseDir) {
7751
7763
  try {
7752
- const EXE_OS_DIR = path17.join(os9.homedir(), ".exe-os");
7764
+ const EXE_OS_DIR = path17.join(os10.homedir(), ".exe-os");
7753
7765
  const mdPath = path17.join(EXE_OS_DIR, taskFile);
7754
7766
  const mdDir = path17.dirname(mdPath);
7755
7767
  if (!existsSync16(mdDir)) await mkdir5(mdDir, { recursive: true });
@@ -9395,7 +9407,7 @@ __export(tmux_routing_exports, {
9395
9407
  import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
9396
9408
  import { readFileSync as readFileSync14, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11, existsSync as existsSync18, appendFileSync as appendFileSync2 } from "fs";
9397
9409
  import path22 from "path";
9398
- import os10 from "os";
9410
+ import os11 from "os";
9399
9411
  import { fileURLToPath as fileURLToPath4 } from "url";
9400
9412
  import { unlinkSync as unlinkSync8 } from "fs";
9401
9413
  function spawnLockPath(sessionName) {
@@ -9809,7 +9821,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9809
9821
  const transport = getTransport();
9810
9822
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
9811
9823
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
9812
- const logDir = path22.join(os10.homedir(), ".exe-os", "session-logs");
9824
+ const logDir = path22.join(os11.homedir(), ".exe-os", "session-logs");
9813
9825
  const logFile = path22.join(logDir, `${instanceLabel}-${Date.now()}.log`);
9814
9826
  if (!existsSync18(logDir)) {
9815
9827
  mkdirSync11(logDir, { recursive: true });
@@ -9825,7 +9837,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9825
9837
  } catch {
9826
9838
  }
9827
9839
  try {
9828
- const claudeJsonPath = path22.join(os10.homedir(), ".claude.json");
9840
+ const claudeJsonPath = path22.join(os11.homedir(), ".claude.json");
9829
9841
  let claudeJson = {};
9830
9842
  try {
9831
9843
  claudeJson = JSON.parse(readFileSync14(claudeJsonPath, "utf8"));
@@ -9840,7 +9852,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9840
9852
  } catch {
9841
9853
  }
9842
9854
  try {
9843
- const settingsDir = path22.join(os10.homedir(), ".claude", "projects");
9855
+ const settingsDir = path22.join(os11.homedir(), ".claude", "projects");
9844
9856
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
9845
9857
  const projSettingsDir = path22.join(settingsDir, normalizedKey);
9846
9858
  const settingsPath = path22.join(projSettingsDir, "settings.json");
@@ -9891,7 +9903,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9891
9903
  let legacyFallbackWarned = false;
9892
9904
  if (!useExeAgent && !useBinSymlink) {
9893
9905
  const identityPath2 = path22.join(
9894
- os10.homedir(),
9906
+ os11.homedir(),
9895
9907
  ".exe-os",
9896
9908
  "identity",
9897
9909
  `${employeeName}.md`
@@ -9921,7 +9933,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9921
9933
  }
9922
9934
  let sessionContextFlag = "";
9923
9935
  try {
9924
- const ctxDir = path22.join(os10.homedir(), ".exe-os", "session-cache");
9936
+ const ctxDir = path22.join(os11.homedir(), ".exe-os", "session-cache");
9925
9937
  mkdirSync11(ctxDir, { recursive: true });
9926
9938
  const ctxFile = path22.join(ctxDir, `session-context-${sessionName}.md`);
9927
9939
  const ctxContent = [
@@ -10082,13 +10094,13 @@ var init_tmux_routing = __esm({
10082
10094
  init_intercom_queue();
10083
10095
  init_plan_limits();
10084
10096
  init_employees();
10085
- SPAWN_LOCK_DIR = path22.join(os10.homedir(), ".exe-os", "spawn-locks");
10086
- SESSION_CACHE = path22.join(os10.homedir(), ".exe-os", "session-cache");
10097
+ SPAWN_LOCK_DIR = path22.join(os11.homedir(), ".exe-os", "spawn-locks");
10098
+ SESSION_CACHE = path22.join(os11.homedir(), ".exe-os", "session-cache");
10087
10099
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
10088
10100
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
10089
10101
  VERIFY_PANE_LINES = 200;
10090
10102
  INTERCOM_DEBOUNCE_MS = 3e4;
10091
- INTERCOM_LOG2 = path22.join(os10.homedir(), ".exe-os", "intercom.log");
10103
+ INTERCOM_LOG2 = path22.join(os11.homedir(), ".exe-os", "intercom.log");
10092
10104
  DEBOUNCE_FILE = path22.join(SESSION_CACHE, "intercom-debounce.json");
10093
10105
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
10094
10106
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -12317,7 +12329,7 @@ __export(setup_wizard_exports, {
12317
12329
  });
12318
12330
  import crypto11 from "crypto";
12319
12331
  import { existsSync as existsSync23, mkdirSync as mkdirSync15, readFileSync as readFileSync19, writeFileSync as writeFileSync15, unlinkSync as unlinkSync13 } from "fs";
12320
- import os11 from "os";
12332
+ import os12 from "os";
12321
12333
  import path28 from "path";
12322
12334
  import { createInterface as createInterface3 } from "readline";
12323
12335
  function findPackageRoot2() {
@@ -12364,10 +12376,10 @@ function ask2(rl, prompt) {
12364
12376
  });
12365
12377
  }
12366
12378
  function getAvailableMemoryGB() {
12367
- return os11.freemem() / (1024 * 1024 * 1024);
12379
+ return os12.freemem() / (1024 * 1024 * 1024);
12368
12380
  }
12369
12381
  function getTotalMemoryGB() {
12370
- return os11.totalmem() / (1024 * 1024 * 1024);
12382
+ return os12.totalmem() / (1024 * 1024 * 1024);
12371
12383
  }
12372
12384
  function isLowMemory() {
12373
12385
  return getAvailableMemoryGB() < 2;
@@ -12626,7 +12638,7 @@ async function runSetupWizard(opts = {}) {
12626
12638
  await saveConfig(config);
12627
12639
  log("");
12628
12640
  try {
12629
- const claudeJsonPath = path28.join(os11.homedir(), ".claude.json");
12641
+ const claudeJsonPath = path28.join(os12.homedir(), ".claude.json");
12630
12642
  let claudeJson = {};
12631
12643
  try {
12632
12644
  claudeJson = JSON.parse(readFileSync19(claudeJsonPath, "utf8"));
@@ -12634,7 +12646,7 @@ async function runSetupWizard(opts = {}) {
12634
12646
  }
12635
12647
  if (!claudeJson.projects) claudeJson.projects = {};
12636
12648
  const projects = claudeJson.projects;
12637
- for (const dir of [process.cwd(), os11.homedir()]) {
12649
+ for (const dir of [process.cwd(), os12.homedir()]) {
12638
12650
  if (!projects[dir]) projects[dir] = {};
12639
12651
  projects[dir].hasTrustDialogAccepted = true;
12640
12652
  }
@@ -12909,7 +12921,7 @@ async function runSetupWizard(opts = {}) {
12909
12921
  log(`Session shortcuts generated (${cooName}1, ${cooName}2, ...)`);
12910
12922
  }
12911
12923
  if (wrapResult.pathConfigured) {
12912
- const binDir = path28.join(os11.homedir(), ".exe-os", "bin");
12924
+ const binDir = path28.join(os12.homedir(), ".exe-os", "bin");
12913
12925
  process.env.PATH = `${binDir}:${process.env.PATH ?? ""}`;
12914
12926
  pathJustConfigured = true;
12915
12927
  }
@@ -12986,7 +12998,7 @@ var init_setup_wizard = __esm({
12986
12998
  init_config();
12987
12999
  init_keychain();
12988
13000
  init_model_downloader();
12989
- SETUP_STATE_PATH = path28.join(os11.homedir(), ".exe-os", "setup-state.json");
13001
+ SETUP_STATE_PATH = path28.join(os12.homedir(), ".exe-os", "setup-state.json");
12990
13002
  }
12991
13003
  });
12992
13004
 
@@ -21964,7 +21976,7 @@ var init_hooks = __esm({
21964
21976
 
21965
21977
  // src/runtime/safety-checks.ts
21966
21978
  import path30 from "path";
21967
- import os12 from "os";
21979
+ import os13 from "os";
21968
21980
  function checkPathSafety(filePath) {
21969
21981
  const resolved = path30.resolve(filePath);
21970
21982
  for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
@@ -21991,7 +22003,7 @@ var HOME, BYPASS_IMMUNE_PATTERNS;
21991
22003
  var init_safety_checks = __esm({
21992
22004
  "src/runtime/safety-checks.ts"() {
21993
22005
  "use strict";
21994
- HOME = os12.homedir();
22006
+ HOME = os13.homedir();
21995
22007
  BYPASS_IMMUNE_PATTERNS = [
21996
22008
  {
21997
22009
  pattern: /\/\.git\/hooks\//,
@@ -27157,7 +27169,7 @@ Unhandled rejection: ${reason}
27157
27169
  // src/bin/cli.ts
27158
27170
  import { existsSync as existsSync25, readFileSync as readFileSync22, writeFileSync as writeFileSync16, readdirSync as readdirSync8, rmSync } from "fs";
27159
27171
  import path38 from "path";
27160
- import os13 from "os";
27172
+ import os14 from "os";
27161
27173
  var args = process.argv.slice(2);
27162
27174
  if (args.includes("--version") || args.includes("-v")) {
27163
27175
  try {
@@ -27300,7 +27312,7 @@ ID: ${result.id}`);
27300
27312
  });
27301
27313
  await init_App2().then(() => App_exports);
27302
27314
  } else {
27303
- const claudeDir = path38.join(os13.homedir(), ".claude");
27315
+ const claudeDir = path38.join(os14.homedir(), ".claude");
27304
27316
  const settingsPath = path38.join(claudeDir, "settings.json");
27305
27317
  const hasClaudeCode = existsSync25(settingsPath) && (() => {
27306
27318
  try {
@@ -27313,7 +27325,7 @@ ID: ${result.id}`);
27313
27325
  if (hasClaudeCode) {
27314
27326
  let cooName = "exe";
27315
27327
  try {
27316
- const rosterPath = path38.join(os13.homedir(), ".exe-os", "exe-employees.json");
27328
+ const rosterPath = path38.join(os14.homedir(), ".exe-os", "exe-employees.json");
27317
27329
  if (existsSync25(rosterPath)) {
27318
27330
  const roster = JSON.parse(readFileSync22(rosterPath, "utf8"));
27319
27331
  const coo = roster.find((e) => e.role === "COO");
@@ -27355,9 +27367,9 @@ async function runClaudeInstall() {
27355
27367
  }
27356
27368
  }
27357
27369
  async function runClaudeCheck() {
27358
- const claudeDir = path38.join(os13.homedir(), ".claude");
27370
+ const claudeDir = path38.join(os14.homedir(), ".claude");
27359
27371
  const settingsPath = path38.join(claudeDir, "settings.json");
27360
- const claudeJsonPath = path38.join(os13.homedir(), ".claude.json");
27372
+ const claudeJsonPath = path38.join(os14.homedir(), ".claude.json");
27361
27373
  let ok = true;
27362
27374
  if (existsSync25(settingsPath)) {
27363
27375
  let settings;
@@ -27427,7 +27439,7 @@ async function runClaudeCheck() {
27427
27439
  async function runClaudeUninstall(flags = []) {
27428
27440
  const dryRun = flags.includes("--dry-run");
27429
27441
  const purge = flags.includes("--purge");
27430
- const homeDir = os13.homedir();
27442
+ const homeDir = os14.homedir();
27431
27443
  const claudeDir = path38.join(homeDir, ".claude");
27432
27444
  const settingsPath = path38.join(claudeDir, "settings.json");
27433
27445
  const claudeJsonPath = path38.join(homeDir, ".claude.json");
@@ -245,6 +245,7 @@ var init_employees = __esm({
245
245
 
246
246
  // src/lib/exe-daemon-client.ts
247
247
  import net from "net";
248
+ import os3 from "os";
248
249
  import { spawn } from "child_process";
249
250
  import { randomUUID as randomUUID2 } from "crypto";
250
251
  import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -308,6 +309,15 @@ function findPackageRoot() {
308
309
  return null;
309
310
  }
310
311
  function spawnDaemon() {
312
+ const freeGB = os3.freemem() / (1024 * 1024 * 1024);
313
+ const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
314
+ if (freeGB < 1.5 && totalGB <= 8) {
315
+ process.stderr.write(
316
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
317
+ `
318
+ );
319
+ return;
320
+ }
311
321
  const pkgRoot = findPackageRoot();
312
322
  if (!pkgRoot) {
313
323
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -328,7 +338,9 @@ function spawnDaemon() {
328
338
  stderrFd = openSync(logPath, "a");
329
339
  } catch {
330
340
  }
331
- const child = spawn(process.execPath, [resolvedPath], {
341
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
342
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
343
+ const child = spawn(process.execPath, nodeArgs, {
332
344
  detached: true,
333
345
  stdio: ["ignore", "ignore", stderrFd],
334
346
  env: {
@@ -2171,11 +2183,11 @@ init_database();
2171
2183
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2172
2184
  import { existsSync as existsSync4 } from "fs";
2173
2185
  import path4 from "path";
2174
- import os3 from "os";
2186
+ import os4 from "os";
2175
2187
  var SERVICE = "exe-mem";
2176
2188
  var ACCOUNT = "master-key";
2177
2189
  function getKeyDir() {
2178
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os3.homedir(), ".exe-os");
2190
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os4.homedir(), ".exe-os");
2179
2191
  }
2180
2192
  function getKeyPath() {
2181
2193
  return path4.join(getKeyDir(), "master.key");
@@ -2201,7 +2213,7 @@ async function getMasterKey() {
2201
2213
  const keyPath = getKeyPath();
2202
2214
  if (!existsSync4(keyPath)) {
2203
2215
  process.stderr.write(
2204
- `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2216
+ `[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2205
2217
  `
2206
2218
  );
2207
2219
  return null;
@@ -429,6 +429,7 @@ var init_db_retry = __esm({
429
429
 
430
430
  // src/lib/exe-daemon-client.ts
431
431
  import net from "net";
432
+ import os3 from "os";
432
433
  import { spawn } from "child_process";
433
434
  import { randomUUID } from "crypto";
434
435
  import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -492,6 +493,15 @@ function findPackageRoot() {
492
493
  return null;
493
494
  }
494
495
  function spawnDaemon() {
496
+ const freeGB = os3.freemem() / (1024 * 1024 * 1024);
497
+ const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
498
+ if (freeGB < 1.5 && totalGB <= 8) {
499
+ process.stderr.write(
500
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
501
+ `
502
+ );
503
+ return;
504
+ }
495
505
  const pkgRoot = findPackageRoot();
496
506
  if (!pkgRoot) {
497
507
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -512,7 +522,9 @@ function spawnDaemon() {
512
522
  stderrFd = openSync(logPath, "a");
513
523
  } catch {
514
524
  }
515
- const child = spawn(process.execPath, [resolvedPath], {
525
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
526
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
527
+ const child = spawn(process.execPath, nodeArgs, {
516
528
  detached: true,
517
529
  stdio: ["ignore", "ignore", stderrFd],
518
530
  env: {
@@ -2077,9 +2089,9 @@ __export(keychain_exports, {
2077
2089
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2078
2090
  import { existsSync as existsSync4 } from "fs";
2079
2091
  import path4 from "path";
2080
- import os3 from "os";
2092
+ import os4 from "os";
2081
2093
  function getKeyDir() {
2082
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os3.homedir(), ".exe-os");
2094
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os4.homedir(), ".exe-os");
2083
2095
  }
2084
2096
  function getKeyPath() {
2085
2097
  return path4.join(getKeyDir(), "master.key");
@@ -2105,7 +2117,7 @@ async function getMasterKey() {
2105
2117
  const keyPath = getKeyPath();
2106
2118
  if (!existsSync4(keyPath)) {
2107
2119
  process.stderr.write(
2108
- `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2120
+ `[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2109
2121
  `
2110
2122
  );
2111
2123
  return null;
@@ -2588,7 +2600,7 @@ __export(session_registry_exports, {
2588
2600
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync6 } from "fs";
2589
2601
  import { execSync as execSync2 } from "child_process";
2590
2602
  import path6 from "path";
2591
- import os4 from "os";
2603
+ import os5 from "os";
2592
2604
  function registerSession(entry) {
2593
2605
  const dir = path6.dirname(REGISTRY_PATH);
2594
2606
  if (!existsSync6(dir)) {
@@ -2634,7 +2646,7 @@ var REGISTRY_PATH;
2634
2646
  var init_session_registry = __esm({
2635
2647
  "src/lib/session-registry.ts"() {
2636
2648
  "use strict";
2637
- REGISTRY_PATH = path6.join(os4.homedir(), ".exe-os", "session-registry.json");
2649
+ REGISTRY_PATH = path6.join(os5.homedir(), ".exe-os", "session-registry.json");
2638
2650
  }
2639
2651
  });
2640
2652
 
@@ -2907,7 +2919,7 @@ var init_agent_config = __esm({
2907
2919
  // src/lib/intercom-queue.ts
2908
2920
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
2909
2921
  import path8 from "path";
2910
- import os5 from "os";
2922
+ import os6 from "os";
2911
2923
  function ensureDir() {
2912
2924
  const dir = path8.dirname(QUEUE_PATH);
2913
2925
  if (!existsSync8(dir)) mkdirSync4(dir, { recursive: true });
@@ -2947,9 +2959,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
2947
2959
  var init_intercom_queue = __esm({
2948
2960
  "src/lib/intercom-queue.ts"() {
2949
2961
  "use strict";
2950
- QUEUE_PATH = path8.join(os5.homedir(), ".exe-os", "intercom-queue.json");
2962
+ QUEUE_PATH = path8.join(os6.homedir(), ".exe-os", "intercom-queue.json");
2951
2963
  TTL_MS = 60 * 60 * 1e3;
2952
- INTERCOM_LOG = path8.join(os5.homedir(), ".exe-os", "intercom.log");
2964
+ INTERCOM_LOG = path8.join(os6.homedir(), ".exe-os", "intercom.log");
2953
2965
  }
2954
2966
  });
2955
2967
 
@@ -3421,7 +3433,7 @@ var init_plan_limits = __esm({
3421
3433
  // src/lib/notifications.ts
3422
3434
  import crypto from "crypto";
3423
3435
  import path11 from "path";
3424
- import os6 from "os";
3436
+ import os7 from "os";
3425
3437
  import {
3426
3438
  readFileSync as readFileSync9,
3427
3439
  readdirSync as readdirSync2,
@@ -3539,7 +3551,7 @@ async function markDoneTaskNotificationsAsRead() {
3539
3551
  }
3540
3552
  }
3541
3553
  async function migrateJsonNotifications() {
3542
- const base = process.env.EXE_OS_DIR || process.env.EXE_MEM_DIR || path11.join(os6.homedir(), ".exe-os");
3554
+ const base = process.env.EXE_OS_DIR || process.env.EXE_MEM_DIR || path11.join(os7.homedir(), ".exe-os");
3543
3555
  const notifDir = path11.join(base, "notifications");
3544
3556
  if (!existsSync11(notifDir)) return 0;
3545
3557
  let migrated = 0;
@@ -3698,7 +3710,7 @@ var init_session_kill_telemetry = __esm({
3698
3710
  // src/lib/tasks-crud.ts
3699
3711
  import crypto3 from "crypto";
3700
3712
  import path12 from "path";
3701
- import os7 from "os";
3713
+ import os8 from "os";
3702
3714
  import { execSync as execSync5 } from "child_process";
3703
3715
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
3704
3716
  import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
@@ -3913,7 +3925,7 @@ ${laneWarning}` : laneWarning;
3913
3925
  });
3914
3926
  if (input.baseDir) {
3915
3927
  try {
3916
- const EXE_OS_DIR = path12.join(os7.homedir(), ".exe-os");
3928
+ const EXE_OS_DIR = path12.join(os8.homedir(), ".exe-os");
3917
3929
  const mdPath = path12.join(EXE_OS_DIR, taskFile);
3918
3930
  const mdDir = path12.dirname(mdPath);
3919
3931
  if (!existsSync12(mdDir)) await mkdir4(mdDir, { recursive: true });
@@ -5568,7 +5580,7 @@ __export(tmux_routing_exports, {
5568
5580
  import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
5569
5581
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, existsSync as existsSync14, appendFileSync } from "fs";
5570
5582
  import path17 from "path";
5571
- import os8 from "os";
5583
+ import os9 from "os";
5572
5584
  import { fileURLToPath as fileURLToPath2 } from "url";
5573
5585
  import { unlinkSync as unlinkSync6 } from "fs";
5574
5586
  function spawnLockPath(sessionName) {
@@ -5982,7 +5994,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5982
5994
  const transport = getTransport();
5983
5995
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
5984
5996
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
5985
- const logDir = path17.join(os8.homedir(), ".exe-os", "session-logs");
5997
+ const logDir = path17.join(os9.homedir(), ".exe-os", "session-logs");
5986
5998
  const logFile = path17.join(logDir, `${instanceLabel}-${Date.now()}.log`);
5987
5999
  if (!existsSync14(logDir)) {
5988
6000
  mkdirSync7(logDir, { recursive: true });
@@ -5998,7 +6010,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5998
6010
  } catch {
5999
6011
  }
6000
6012
  try {
6001
- const claudeJsonPath = path17.join(os8.homedir(), ".claude.json");
6013
+ const claudeJsonPath = path17.join(os9.homedir(), ".claude.json");
6002
6014
  let claudeJson = {};
6003
6015
  try {
6004
6016
  claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
@@ -6013,7 +6025,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6013
6025
  } catch {
6014
6026
  }
6015
6027
  try {
6016
- const settingsDir = path17.join(os8.homedir(), ".claude", "projects");
6028
+ const settingsDir = path17.join(os9.homedir(), ".claude", "projects");
6017
6029
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
6018
6030
  const projSettingsDir = path17.join(settingsDir, normalizedKey);
6019
6031
  const settingsPath = path17.join(projSettingsDir, "settings.json");
@@ -6064,7 +6076,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6064
6076
  let legacyFallbackWarned = false;
6065
6077
  if (!useExeAgent && !useBinSymlink) {
6066
6078
  const identityPath = path17.join(
6067
- os8.homedir(),
6079
+ os9.homedir(),
6068
6080
  ".exe-os",
6069
6081
  "identity",
6070
6082
  `${employeeName}.md`
@@ -6094,7 +6106,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6094
6106
  }
6095
6107
  let sessionContextFlag = "";
6096
6108
  try {
6097
- const ctxDir = path17.join(os8.homedir(), ".exe-os", "session-cache");
6109
+ const ctxDir = path17.join(os9.homedir(), ".exe-os", "session-cache");
6098
6110
  mkdirSync7(ctxDir, { recursive: true });
6099
6111
  const ctxFile = path17.join(ctxDir, `session-context-${sessionName}.md`);
6100
6112
  const ctxContent = [
@@ -6255,13 +6267,13 @@ var init_tmux_routing = __esm({
6255
6267
  init_intercom_queue();
6256
6268
  init_plan_limits();
6257
6269
  init_employees();
6258
- SPAWN_LOCK_DIR = path17.join(os8.homedir(), ".exe-os", "spawn-locks");
6259
- SESSION_CACHE = path17.join(os8.homedir(), ".exe-os", "session-cache");
6270
+ SPAWN_LOCK_DIR = path17.join(os9.homedir(), ".exe-os", "spawn-locks");
6271
+ SESSION_CACHE = path17.join(os9.homedir(), ".exe-os", "session-cache");
6260
6272
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
6261
6273
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
6262
6274
  VERIFY_PANE_LINES = 200;
6263
6275
  INTERCOM_DEBOUNCE_MS = 3e4;
6264
- INTERCOM_LOG2 = path17.join(os8.homedir(), ".exe-os", "intercom.log");
6276
+ INTERCOM_LOG2 = path17.join(os9.homedir(), ".exe-os", "intercom.log");
6265
6277
  DEBOUNCE_FILE = path17.join(SESSION_CACHE, "intercom-debounce.json");
6266
6278
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
6267
6279
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -8008,7 +8020,7 @@ init_employees();
8008
8020
  import path22 from "path";
8009
8021
  import { mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
8010
8022
  import { existsSync as existsSync18, readFileSync as readFileSync15, readdirSync as readdirSync7, unlinkSync as unlinkSync11 } from "fs";
8011
- import os9 from "os";
8023
+ import os10 from "os";
8012
8024
 
8013
8025
  // src/lib/employee-templates.ts
8014
8026
  init_global_procedures();
@@ -9228,7 +9240,7 @@ async function boot(options) {
9228
9240
  ]);
9229
9241
  try {
9230
9242
  const configPath = path22.join(
9231
- process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os9.homedir(), ".exe-os"),
9243
+ process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os10.homedir(), ".exe-os"),
9232
9244
  "config.json"
9233
9245
  );
9234
9246
  if (existsSync18(configPath)) {
@@ -9427,7 +9439,7 @@ ${brief}`;
9427
9439
  console.log(brief);
9428
9440
  try {
9429
9441
  const configPath2 = path22.join(
9430
- process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os9.homedir(), ".exe-os"),
9442
+ process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os10.homedir(), ".exe-os"),
9431
9443
  "config.json"
9432
9444
  );
9433
9445
  if (existsSync18(configPath2)) {