@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
@@ -1835,6 +1835,7 @@ var init_memory = __esm({
1835
1835
 
1836
1836
  // src/lib/exe-daemon-client.ts
1837
1837
  import net from "net";
1838
+ import os3 from "os";
1838
1839
  import { spawn } from "child_process";
1839
1840
  import { randomUUID } from "crypto";
1840
1841
  import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -1898,6 +1899,15 @@ function findPackageRoot() {
1898
1899
  return null;
1899
1900
  }
1900
1901
  function spawnDaemon() {
1902
+ const freeGB = os3.freemem() / (1024 * 1024 * 1024);
1903
+ const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
1904
+ if (freeGB < 1.5 && totalGB <= 8) {
1905
+ process.stderr.write(
1906
+ `[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.
1907
+ `
1908
+ );
1909
+ return;
1910
+ }
1901
1911
  const pkgRoot = findPackageRoot();
1902
1912
  if (!pkgRoot) {
1903
1913
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -1918,7 +1928,9 @@ function spawnDaemon() {
1918
1928
  stderrFd = openSync(logPath, "a");
1919
1929
  } catch {
1920
1930
  }
1921
- const child = spawn(process.execPath, [resolvedPath], {
1931
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
1932
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
1933
+ const child = spawn(process.execPath, nodeArgs, {
1922
1934
  detached: true,
1923
1935
  stdio: ["ignore", "ignore", stderrFd],
1924
1936
  env: {
@@ -2236,9 +2248,9 @@ var init_embedder = __esm({
2236
2248
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2237
2249
  import { existsSync as existsSync4 } from "fs";
2238
2250
  import path4 from "path";
2239
- import os3 from "os";
2251
+ import os4 from "os";
2240
2252
  function getKeyDir() {
2241
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os3.homedir(), ".exe-os");
2253
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os4.homedir(), ".exe-os");
2242
2254
  }
2243
2255
  function getKeyPath() {
2244
2256
  return path4.join(getKeyDir(), "master.key");
@@ -2264,7 +2276,7 @@ async function getMasterKey() {
2264
2276
  const keyPath = getKeyPath();
2265
2277
  if (!existsSync4(keyPath)) {
2266
2278
  process.stderr.write(
2267
- `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2279
+ `[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2268
2280
  `
2269
2281
  );
2270
2282
  return null;
@@ -5594,7 +5606,7 @@ __export(imessage_exports, {
5594
5606
  });
5595
5607
  import { execFile } from "child_process";
5596
5608
  import { promisify } from "util";
5597
- import os4 from "os";
5609
+ import os5 from "os";
5598
5610
  import path7 from "path";
5599
5611
  var execFileAsync, POLL_INTERVAL_MS, MESSAGES_DB_PATH, IMessageAdapter;
5600
5612
  var init_imessage = __esm({
@@ -5603,7 +5615,7 @@ var init_imessage = __esm({
5603
5615
  execFileAsync = promisify(execFile);
5604
5616
  POLL_INTERVAL_MS = 5e3;
5605
5617
  MESSAGES_DB_PATH = path7.join(
5606
- process.env.HOME ?? os4.homedir(),
5618
+ process.env.HOME ?? os5.homedir(),
5607
5619
  "Library/Messages/chat.db"
5608
5620
  );
5609
5621
  IMessageAdapter = class {
@@ -6069,7 +6081,7 @@ var init_whatsapp_accounts = __esm({
6069
6081
  // src/lib/session-registry.ts
6070
6082
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, existsSync as existsSync7 } from "fs";
6071
6083
  import path8 from "path";
6072
- import os5 from "os";
6084
+ import os6 from "os";
6073
6085
  function registerSession(entry) {
6074
6086
  const dir = path8.dirname(REGISTRY_PATH);
6075
6087
  if (!existsSync7(dir)) {
@@ -6096,7 +6108,7 @@ var REGISTRY_PATH;
6096
6108
  var init_session_registry = __esm({
6097
6109
  "src/lib/session-registry.ts"() {
6098
6110
  "use strict";
6099
- REGISTRY_PATH = path8.join(os5.homedir(), ".exe-os", "session-registry.json");
6111
+ REGISTRY_PATH = path8.join(os6.homedir(), ".exe-os", "session-registry.json");
6100
6112
  }
6101
6113
  });
6102
6114
 
@@ -6369,7 +6381,7 @@ var init_agent_config = __esm({
6369
6381
  // src/lib/intercom-queue.ts
6370
6382
  import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, renameSync as renameSync3, existsSync as existsSync9, mkdirSync as mkdirSync6 } from "fs";
6371
6383
  import path10 from "path";
6372
- import os6 from "os";
6384
+ import os7 from "os";
6373
6385
  function ensureDir() {
6374
6386
  const dir = path10.dirname(QUEUE_PATH);
6375
6387
  if (!existsSync9(dir)) mkdirSync6(dir, { recursive: true });
@@ -6409,9 +6421,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
6409
6421
  var init_intercom_queue = __esm({
6410
6422
  "src/lib/intercom-queue.ts"() {
6411
6423
  "use strict";
6412
- QUEUE_PATH = path10.join(os6.homedir(), ".exe-os", "intercom-queue.json");
6424
+ QUEUE_PATH = path10.join(os7.homedir(), ".exe-os", "intercom-queue.json");
6413
6425
  TTL_MS = 60 * 60 * 1e3;
6414
- INTERCOM_LOG = path10.join(os6.homedir(), ".exe-os", "intercom.log");
6426
+ INTERCOM_LOG = path10.join(os7.homedir(), ".exe-os", "intercom.log");
6415
6427
  }
6416
6428
  });
6417
6429
 
@@ -6496,7 +6508,7 @@ var init_plan_limits = __esm({
6496
6508
  // src/lib/notifications.ts
6497
6509
  import crypto3 from "crypto";
6498
6510
  import path12 from "path";
6499
- import os7 from "os";
6511
+ import os8 from "os";
6500
6512
  import {
6501
6513
  readFileSync as readFileSync10,
6502
6514
  readdirSync as readdirSync2,
@@ -6606,7 +6618,7 @@ var init_task_scope = __esm({
6606
6618
  // src/lib/tasks-crud.ts
6607
6619
  import crypto5 from "crypto";
6608
6620
  import path13 from "path";
6609
- import os8 from "os";
6621
+ import os9 from "os";
6610
6622
  import { execSync as execSync4 } from "child_process";
6611
6623
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
6612
6624
  import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
@@ -6821,7 +6833,7 @@ ${laneWarning}` : laneWarning;
6821
6833
  });
6822
6834
  if (input.baseDir) {
6823
6835
  try {
6824
- const EXE_OS_DIR = path13.join(os8.homedir(), ".exe-os");
6836
+ const EXE_OS_DIR = path13.join(os9.homedir(), ".exe-os");
6825
6837
  const mdPath = path13.join(EXE_OS_DIR, taskFile);
6826
6838
  const mdDir = path13.dirname(mdPath);
6827
6839
  if (!existsSync12(mdDir)) await mkdir4(mdDir, { recursive: true });
@@ -8467,7 +8479,7 @@ __export(tmux_routing_exports, {
8467
8479
  import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
8468
8480
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, existsSync as existsSync14, appendFileSync } from "fs";
8469
8481
  import path18 from "path";
8470
- import os9 from "os";
8482
+ import os10 from "os";
8471
8483
  import { fileURLToPath as fileURLToPath2 } from "url";
8472
8484
  import { unlinkSync as unlinkSync6 } from "fs";
8473
8485
  function spawnLockPath(sessionName) {
@@ -8881,7 +8893,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8881
8893
  const transport = getTransport();
8882
8894
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
8883
8895
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
8884
- const logDir = path18.join(os9.homedir(), ".exe-os", "session-logs");
8896
+ const logDir = path18.join(os10.homedir(), ".exe-os", "session-logs");
8885
8897
  const logFile = path18.join(logDir, `${instanceLabel}-${Date.now()}.log`);
8886
8898
  if (!existsSync14(logDir)) {
8887
8899
  mkdirSync8(logDir, { recursive: true });
@@ -8897,7 +8909,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8897
8909
  } catch {
8898
8910
  }
8899
8911
  try {
8900
- const claudeJsonPath = path18.join(os9.homedir(), ".claude.json");
8912
+ const claudeJsonPath = path18.join(os10.homedir(), ".claude.json");
8901
8913
  let claudeJson = {};
8902
8914
  try {
8903
8915
  claudeJson = JSON.parse(readFileSync12(claudeJsonPath, "utf8"));
@@ -8912,7 +8924,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8912
8924
  } catch {
8913
8925
  }
8914
8926
  try {
8915
- const settingsDir = path18.join(os9.homedir(), ".claude", "projects");
8927
+ const settingsDir = path18.join(os10.homedir(), ".claude", "projects");
8916
8928
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
8917
8929
  const projSettingsDir = path18.join(settingsDir, normalizedKey);
8918
8930
  const settingsPath = path18.join(projSettingsDir, "settings.json");
@@ -8963,7 +8975,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8963
8975
  let legacyFallbackWarned = false;
8964
8976
  if (!useExeAgent && !useBinSymlink) {
8965
8977
  const identityPath = path18.join(
8966
- os9.homedir(),
8978
+ os10.homedir(),
8967
8979
  ".exe-os",
8968
8980
  "identity",
8969
8981
  `${employeeName}.md`
@@ -8993,7 +9005,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8993
9005
  }
8994
9006
  let sessionContextFlag = "";
8995
9007
  try {
8996
- const ctxDir = path18.join(os9.homedir(), ".exe-os", "session-cache");
9008
+ const ctxDir = path18.join(os10.homedir(), ".exe-os", "session-cache");
8997
9009
  mkdirSync8(ctxDir, { recursive: true });
8998
9010
  const ctxFile = path18.join(ctxDir, `session-context-${sessionName}.md`);
8999
9011
  const ctxContent = [
@@ -9154,13 +9166,13 @@ var init_tmux_routing = __esm({
9154
9166
  init_intercom_queue();
9155
9167
  init_plan_limits();
9156
9168
  init_employees();
9157
- SPAWN_LOCK_DIR = path18.join(os9.homedir(), ".exe-os", "spawn-locks");
9158
- SESSION_CACHE = path18.join(os9.homedir(), ".exe-os", "session-cache");
9169
+ SPAWN_LOCK_DIR = path18.join(os10.homedir(), ".exe-os", "spawn-locks");
9170
+ SESSION_CACHE = path18.join(os10.homedir(), ".exe-os", "session-cache");
9159
9171
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
9160
9172
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
9161
9173
  VERIFY_PANE_LINES = 200;
9162
9174
  INTERCOM_DEBOUNCE_MS = 3e4;
9163
- INTERCOM_LOG2 = path18.join(os9.homedir(), ".exe-os", "intercom.log");
9175
+ INTERCOM_LOG2 = path18.join(os10.homedir(), ".exe-os", "intercom.log");
9164
9176
  DEBOUNCE_FILE = path18.join(SESSION_CACHE, "intercom-debounce.json");
9165
9177
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
9166
9178
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -9422,7 +9434,7 @@ var init_messaging = __esm({
9422
9434
  import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, existsSync as existsSync15, mkdirSync as mkdirSync9 } from "fs";
9423
9435
  import { randomUUID as randomUUID8 } from "crypto";
9424
9436
  import path19 from "path";
9425
- import os10 from "os";
9437
+ import os11 from "os";
9426
9438
  function substituteTemplate(template, record) {
9427
9439
  return template.replace(
9428
9440
  /\{\{(\w+(?:\.\w+)*)\}\}/g,
@@ -9717,7 +9729,7 @@ var TRIGGERS_PATH, GRAPH_API_VERSION;
9717
9729
  var init_trigger_engine = __esm({
9718
9730
  "src/automation/trigger-engine.ts"() {
9719
9731
  "use strict";
9720
- TRIGGERS_PATH = path19.join(os10.homedir(), ".exe-os", "triggers.json");
9732
+ TRIGGERS_PATH = path19.join(os11.homedir(), ".exe-os", "triggers.json");
9721
9733
  GRAPH_API_VERSION = "v21.0";
9722
9734
  }
9723
9735
  });
@@ -9782,7 +9794,7 @@ var init_crm_webhook = __esm({
9782
9794
  // src/bin/exe-gateway.ts
9783
9795
  import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
9784
9796
  import path20 from "path";
9785
- import os11 from "os";
9797
+ import os12 from "os";
9786
9798
 
9787
9799
  // src/gateway/webhook-server.ts
9788
9800
  import {
@@ -10748,7 +10760,7 @@ var BotRegistry = class {
10748
10760
 
10749
10761
  // src/bin/exe-gateway.ts
10750
10762
  init_employees();
10751
- var CONFIG_DIR = path20.join(os11.homedir(), ".exe-os");
10763
+ var CONFIG_DIR = path20.join(os12.homedir(), ".exe-os");
10752
10764
  var CONFIG_PATH3 = path20.join(CONFIG_DIR, "gateway.json");
10753
10765
  var DEFAULT_PORT = 3100;
10754
10766
  function loadConfig2() {
@@ -580,6 +580,7 @@ var init_employees = __esm({
580
580
 
581
581
  // src/lib/exe-daemon-client.ts
582
582
  import net from "net";
583
+ import os4 from "os";
583
584
  import { spawn } from "child_process";
584
585
  import { randomUUID } from "crypto";
585
586
  import { existsSync as existsSync4, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -643,6 +644,15 @@ function findPackageRoot() {
643
644
  return null;
644
645
  }
645
646
  function spawnDaemon() {
647
+ const freeGB = os4.freemem() / (1024 * 1024 * 1024);
648
+ const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
649
+ if (freeGB < 1.5 && totalGB <= 8) {
650
+ process.stderr.write(
651
+ `[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.
652
+ `
653
+ );
654
+ return;
655
+ }
646
656
  const pkgRoot = findPackageRoot();
647
657
  if (!pkgRoot) {
648
658
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -663,7 +673,9 @@ function spawnDaemon() {
663
673
  stderrFd = openSync(logPath, "a");
664
674
  } catch {
665
675
  }
666
- const child = spawn(process.execPath, [resolvedPath], {
676
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
677
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
678
+ const child = spawn(process.execPath, nodeArgs, {
667
679
  detached: true,
668
680
  stdio: ["ignore", "ignore", stderrFd],
669
681
  env: {
@@ -264,6 +264,7 @@ var init_db_retry = __esm({
264
264
 
265
265
  // src/lib/exe-daemon-client.ts
266
266
  import net from "net";
267
+ import os3 from "os";
267
268
  import { spawn } from "child_process";
268
269
  import { randomUUID } from "crypto";
269
270
  import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -327,6 +328,15 @@ function findPackageRoot() {
327
328
  return null;
328
329
  }
329
330
  function spawnDaemon() {
331
+ const freeGB = os3.freemem() / (1024 * 1024 * 1024);
332
+ const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
333
+ if (freeGB < 1.5 && totalGB <= 8) {
334
+ process.stderr.write(
335
+ `[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.
336
+ `
337
+ );
338
+ return;
339
+ }
330
340
  const pkgRoot = findPackageRoot();
331
341
  if (!pkgRoot) {
332
342
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -347,7 +357,9 @@ function spawnDaemon() {
347
357
  stderrFd = openSync(logPath, "a");
348
358
  } catch {
349
359
  }
350
- const child = spawn(process.execPath, [resolvedPath], {
360
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
361
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
362
+ const child = spawn(process.execPath, nodeArgs, {
351
363
  detached: true,
352
364
  stdio: ["ignore", "ignore", stderrFd],
353
365
  env: {
@@ -2661,6 +2661,7 @@ var init_reranker = __esm({
2661
2661
 
2662
2662
  // src/lib/exe-daemon-client.ts
2663
2663
  import net from "net";
2664
+ import os4 from "os";
2664
2665
  import { spawn } from "child_process";
2665
2666
  import { randomUUID as randomUUID2 } from "crypto";
2666
2667
  import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -2724,6 +2725,15 @@ function findPackageRoot() {
2724
2725
  return null;
2725
2726
  }
2726
2727
  function spawnDaemon() {
2728
+ const freeGB = os4.freemem() / (1024 * 1024 * 1024);
2729
+ const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
2730
+ if (freeGB < 1.5 && totalGB <= 8) {
2731
+ process.stderr.write(
2732
+ `[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.
2733
+ `
2734
+ );
2735
+ return;
2736
+ }
2727
2737
  const pkgRoot = findPackageRoot();
2728
2738
  if (!pkgRoot) {
2729
2739
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -2744,7 +2754,9 @@ function spawnDaemon() {
2744
2754
  stderrFd = openSync(logPath, "a");
2745
2755
  } catch {
2746
2756
  }
2747
- const child = spawn(process.execPath, [resolvedPath], {
2757
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
2758
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
2759
+ const child = spawn(process.execPath, nodeArgs, {
2748
2760
  detached: true,
2749
2761
  stdio: ["ignore", "ignore", stderrFd],
2750
2762
  env: {
@@ -388,6 +388,7 @@ var init_employees = __esm({
388
388
 
389
389
  // src/lib/exe-daemon-client.ts
390
390
  import net from "net";
391
+ import os3 from "os";
391
392
  import { spawn } from "child_process";
392
393
  import { randomUUID } from "crypto";
393
394
  import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -451,6 +452,15 @@ function findPackageRoot() {
451
452
  return null;
452
453
  }
453
454
  function spawnDaemon() {
455
+ const freeGB = os3.freemem() / (1024 * 1024 * 1024);
456
+ const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
457
+ if (freeGB < 1.5 && totalGB <= 8) {
458
+ process.stderr.write(
459
+ `[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.
460
+ `
461
+ );
462
+ return;
463
+ }
454
464
  const pkgRoot = findPackageRoot();
455
465
  if (!pkgRoot) {
456
466
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -471,7 +481,9 @@ function spawnDaemon() {
471
481
  stderrFd = openSync(logPath, "a");
472
482
  } catch {
473
483
  }
474
- const child = spawn(process.execPath, [resolvedPath], {
484
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
485
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
486
+ const child = spawn(process.execPath, nodeArgs, {
475
487
  detached: true,
476
488
  stdio: ["ignore", "ignore", stderrFd],
477
489
  env: {
@@ -1936,9 +1948,9 @@ var init_database = __esm({
1936
1948
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
1937
1949
  import { existsSync as existsSync4 } from "fs";
1938
1950
  import path4 from "path";
1939
- import os3 from "os";
1951
+ import os4 from "os";
1940
1952
  function getKeyDir() {
1941
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os3.homedir(), ".exe-os");
1953
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os4.homedir(), ".exe-os");
1942
1954
  }
1943
1955
  function getKeyPath() {
1944
1956
  return path4.join(getKeyDir(), "master.key");
@@ -1964,7 +1976,7 @@ async function getMasterKey() {
1964
1976
  const keyPath = getKeyPath();
1965
1977
  if (!existsSync4(keyPath)) {
1966
1978
  process.stderr.write(
1967
- `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
1979
+ `[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
1968
1980
  `
1969
1981
  );
1970
1982
  return null;
@@ -3041,7 +3053,7 @@ var init_store = __esm({
3041
3053
  // src/lib/session-registry.ts
3042
3054
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync6 } from "fs";
3043
3055
  import path6 from "path";
3044
- import os4 from "os";
3056
+ import os5 from "os";
3045
3057
  function registerSession(entry) {
3046
3058
  const dir = path6.dirname(REGISTRY_PATH);
3047
3059
  if (!existsSync6(dir)) {
@@ -3068,7 +3080,7 @@ var REGISTRY_PATH;
3068
3080
  var init_session_registry = __esm({
3069
3081
  "src/lib/session-registry.ts"() {
3070
3082
  "use strict";
3071
- REGISTRY_PATH = path6.join(os4.homedir(), ".exe-os", "session-registry.json");
3083
+ REGISTRY_PATH = path6.join(os5.homedir(), ".exe-os", "session-registry.json");
3072
3084
  }
3073
3085
  });
3074
3086
 
@@ -3341,7 +3353,7 @@ var init_agent_config = __esm({
3341
3353
  // src/lib/intercom-queue.ts
3342
3354
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
3343
3355
  import path8 from "path";
3344
- import os5 from "os";
3356
+ import os6 from "os";
3345
3357
  function ensureDir() {
3346
3358
  const dir = path8.dirname(QUEUE_PATH);
3347
3359
  if (!existsSync8(dir)) mkdirSync4(dir, { recursive: true });
@@ -3381,9 +3393,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
3381
3393
  var init_intercom_queue = __esm({
3382
3394
  "src/lib/intercom-queue.ts"() {
3383
3395
  "use strict";
3384
- QUEUE_PATH = path8.join(os5.homedir(), ".exe-os", "intercom-queue.json");
3396
+ QUEUE_PATH = path8.join(os6.homedir(), ".exe-os", "intercom-queue.json");
3385
3397
  TTL_MS = 60 * 60 * 1e3;
3386
- INTERCOM_LOG = path8.join(os5.homedir(), ".exe-os", "intercom.log");
3398
+ INTERCOM_LOG = path8.join(os6.homedir(), ".exe-os", "intercom.log");
3387
3399
  }
3388
3400
  });
3389
3401
 
@@ -3491,7 +3503,7 @@ var init_plan_limits = __esm({
3491
3503
  // src/lib/notifications.ts
3492
3504
  import crypto from "crypto";
3493
3505
  import path11 from "path";
3494
- import os6 from "os";
3506
+ import os7 from "os";
3495
3507
  import {
3496
3508
  readFileSync as readFileSync9,
3497
3509
  readdirSync as readdirSync2,
@@ -3593,7 +3605,7 @@ __export(tasks_crud_exports, {
3593
3605
  });
3594
3606
  import crypto3 from "crypto";
3595
3607
  import path12 from "path";
3596
- import os7 from "os";
3608
+ import os8 from "os";
3597
3609
  import { execSync as execSync4 } from "child_process";
3598
3610
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
3599
3611
  import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
@@ -3808,7 +3820,7 @@ ${laneWarning}` : laneWarning;
3808
3820
  });
3809
3821
  if (input.baseDir) {
3810
3822
  try {
3811
- const EXE_OS_DIR = path12.join(os7.homedir(), ".exe-os");
3823
+ const EXE_OS_DIR = path12.join(os8.homedir(), ".exe-os");
3812
3824
  const mdPath = path12.join(EXE_OS_DIR, taskFile);
3813
3825
  const mdDir = path12.dirname(mdPath);
3814
3826
  if (!existsSync12(mdDir)) await mkdir4(mdDir, { recursive: true });
@@ -5553,7 +5565,7 @@ __export(tmux_routing_exports, {
5553
5565
  import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
5554
5566
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, existsSync as existsSync14, appendFileSync } from "fs";
5555
5567
  import path17 from "path";
5556
- import os8 from "os";
5568
+ import os9 from "os";
5557
5569
  import { fileURLToPath as fileURLToPath2 } from "url";
5558
5570
  import { unlinkSync as unlinkSync6 } from "fs";
5559
5571
  function spawnLockPath(sessionName) {
@@ -5967,7 +5979,7 @@ function spawnEmployee(employeeName, exeSession2, projectDir, opts) {
5967
5979
  const transport = getTransport();
5968
5980
  const sessionName = employeeSessionName(employeeName, exeSession2, opts?.instance);
5969
5981
  const instanceLabel2 = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
5970
- const logDir = path17.join(os8.homedir(), ".exe-os", "session-logs");
5982
+ const logDir = path17.join(os9.homedir(), ".exe-os", "session-logs");
5971
5983
  const logFile = path17.join(logDir, `${instanceLabel2}-${Date.now()}.log`);
5972
5984
  if (!existsSync14(logDir)) {
5973
5985
  mkdirSync7(logDir, { recursive: true });
@@ -5983,7 +5995,7 @@ function spawnEmployee(employeeName, exeSession2, projectDir, opts) {
5983
5995
  } catch {
5984
5996
  }
5985
5997
  try {
5986
- const claudeJsonPath = path17.join(os8.homedir(), ".claude.json");
5998
+ const claudeJsonPath = path17.join(os9.homedir(), ".claude.json");
5987
5999
  let claudeJson = {};
5988
6000
  try {
5989
6001
  claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
@@ -5998,7 +6010,7 @@ function spawnEmployee(employeeName, exeSession2, projectDir, opts) {
5998
6010
  } catch {
5999
6011
  }
6000
6012
  try {
6001
- const settingsDir = path17.join(os8.homedir(), ".claude", "projects");
6013
+ const settingsDir = path17.join(os9.homedir(), ".claude", "projects");
6002
6014
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
6003
6015
  const projSettingsDir = path17.join(settingsDir, normalizedKey);
6004
6016
  const settingsPath = path17.join(projSettingsDir, "settings.json");
@@ -6049,7 +6061,7 @@ function spawnEmployee(employeeName, exeSession2, projectDir, opts) {
6049
6061
  let legacyFallbackWarned = false;
6050
6062
  if (!useExeAgent && !useBinSymlink) {
6051
6063
  const identityPath = path17.join(
6052
- os8.homedir(),
6064
+ os9.homedir(),
6053
6065
  ".exe-os",
6054
6066
  "identity",
6055
6067
  `${employeeName}.md`
@@ -6079,7 +6091,7 @@ function spawnEmployee(employeeName, exeSession2, projectDir, opts) {
6079
6091
  }
6080
6092
  let sessionContextFlag = "";
6081
6093
  try {
6082
- const ctxDir = path17.join(os8.homedir(), ".exe-os", "session-cache");
6094
+ const ctxDir = path17.join(os9.homedir(), ".exe-os", "session-cache");
6083
6095
  mkdirSync7(ctxDir, { recursive: true });
6084
6096
  const ctxFile = path17.join(ctxDir, `session-context-${sessionName}.md`);
6085
6097
  const ctxContent = [
@@ -6240,13 +6252,13 @@ var init_tmux_routing = __esm({
6240
6252
  init_intercom_queue();
6241
6253
  init_plan_limits();
6242
6254
  init_employees();
6243
- SPAWN_LOCK_DIR = path17.join(os8.homedir(), ".exe-os", "spawn-locks");
6244
- SESSION_CACHE = path17.join(os8.homedir(), ".exe-os", "session-cache");
6255
+ SPAWN_LOCK_DIR = path17.join(os9.homedir(), ".exe-os", "spawn-locks");
6256
+ SESSION_CACHE = path17.join(os9.homedir(), ".exe-os", "session-cache");
6245
6257
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
6246
6258
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
6247
6259
  VERIFY_PANE_LINES = 200;
6248
6260
  INTERCOM_DEBOUNCE_MS = 3e4;
6249
- INTERCOM_LOG2 = path17.join(os8.homedir(), ".exe-os", "intercom.log");
6261
+ INTERCOM_LOG2 = path17.join(os9.homedir(), ".exe-os", "intercom.log");
6250
6262
  DEBOUNCE_FILE = path17.join(SESSION_CACHE, "intercom-debounce.json");
6251
6263
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
6252
6264
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;