@askexenow/exe-os 0.8.89 → 0.8.91

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 +10 -0
  2. package/dist/bin/backfill-responses.js +10 -0
  3. package/dist/bin/backfill-vectors.js +10 -0
  4. package/dist/bin/cli.js +75 -30
  5. package/dist/bin/exe-assign.js +13 -3
  6. package/dist/bin/exe-boot.js +34 -24
  7. package/dist/bin/exe-gateway.js +36 -26
  8. package/dist/bin/exe-link.js +10 -0
  9. package/dist/bin/exe-rename.js +10 -0
  10. package/dist/bin/exe-search.js +10 -0
  11. package/dist/bin/exe-session-cleanup.js +30 -20
  12. package/dist/bin/git-sweep.js +25 -15
  13. package/dist/bin/scan-tasks.js +27 -17
  14. package/dist/bin/setup.js +52 -7
  15. package/dist/gateway/index.js +34 -24
  16. package/dist/hooks/commit-complete.js +25 -15
  17. package/dist/hooks/error-recall.js +10 -0
  18. package/dist/hooks/ingest-worker.js +30 -20
  19. package/dist/hooks/instructions-loaded.js +15 -5
  20. package/dist/hooks/notification.js +13 -3
  21. package/dist/hooks/post-compact.js +17 -7
  22. package/dist/hooks/pre-compact.js +25 -15
  23. package/dist/hooks/pre-tool-use.js +20 -10
  24. package/dist/hooks/prompt-ingest-worker.js +10 -0
  25. package/dist/hooks/prompt-submit.js +20 -10
  26. package/dist/hooks/response-ingest-worker.js +10 -0
  27. package/dist/hooks/session-end.js +26 -16
  28. package/dist/hooks/session-start.js +19 -9
  29. package/dist/hooks/stop.js +17 -7
  30. package/dist/hooks/subagent-stop.js +17 -7
  31. package/dist/hooks/summary-worker.js +23 -13
  32. package/dist/index.js +29 -19
  33. package/dist/lib/cloud-sync.js +13 -3
  34. package/dist/lib/database.js +10 -0
  35. package/dist/lib/db-daemon-client.js +10 -0
  36. package/dist/lib/device-registry.js +12 -2
  37. package/dist/lib/embedder.js +10 -0
  38. package/dist/lib/exe-daemon-client.js +10 -0
  39. package/dist/lib/exe-daemon.js +31 -21
  40. package/dist/lib/hybrid-search.js +10 -0
  41. package/dist/mcp/server.js +38 -28
  42. package/dist/runtime/index.js +25 -15
  43. package/dist/tui/App.js +27 -17
  44. package/package.json +1 -1
@@ -660,6 +660,7 @@ var init_employees = __esm({
660
660
 
661
661
  // src/lib/exe-daemon-client.ts
662
662
  import net from "net";
663
+ import os5 from "os";
663
664
  import { spawn } from "child_process";
664
665
  import { randomUUID } from "crypto";
665
666
  import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync6, openSync, closeSync, statSync } from "fs";
@@ -723,6 +724,15 @@ function findPackageRoot() {
723
724
  return null;
724
725
  }
725
726
  function spawnDaemon() {
727
+ const freeGB = os5.freemem() / (1024 * 1024 * 1024);
728
+ const totalGB = os5.totalmem() / (1024 * 1024 * 1024);
729
+ if (freeGB < 1.5 && totalGB <= 8) {
730
+ process.stderr.write(
731
+ `[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.
732
+ `
733
+ );
734
+ return;
735
+ }
726
736
  const pkgRoot = findPackageRoot();
727
737
  if (!pkgRoot) {
728
738
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -2212,7 +2222,7 @@ var init_plan_limits = __esm({
2212
2222
  // src/lib/notifications.ts
2213
2223
  import crypto from "crypto";
2214
2224
  import path9 from "path";
2215
- import os5 from "os";
2225
+ import os6 from "os";
2216
2226
  import {
2217
2227
  readFileSync as readFileSync9,
2218
2228
  readdirSync,
@@ -2353,7 +2363,7 @@ var init_state_bus = __esm({
2353
2363
  // src/lib/tasks-crud.ts
2354
2364
  import crypto3 from "crypto";
2355
2365
  import path10 from "path";
2356
- import os6 from "os";
2366
+ import os7 from "os";
2357
2367
  import { execSync as execSync4 } from "child_process";
2358
2368
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
2359
2369
  import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
@@ -2568,7 +2578,7 @@ ${laneWarning}` : laneWarning;
2568
2578
  });
2569
2579
  if (input.baseDir) {
2570
2580
  try {
2571
- const EXE_OS_DIR = path10.join(os6.homedir(), ".exe-os");
2581
+ const EXE_OS_DIR = path10.join(os7.homedir(), ".exe-os");
2572
2582
  const mdPath = path10.join(EXE_OS_DIR, taskFile);
2573
2583
  const mdDir = path10.dirname(mdPath);
2574
2584
  if (!existsSync10(mdDir)) await mkdir3(mdDir, { recursive: true });
@@ -4223,7 +4233,7 @@ __export(tmux_routing_exports, {
4223
4233
  import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
4224
4234
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, existsSync as existsSync12, appendFileSync } from "fs";
4225
4235
  import path15 from "path";
4226
- import os7 from "os";
4236
+ import os8 from "os";
4227
4237
  import { fileURLToPath as fileURLToPath3 } from "url";
4228
4238
  import { unlinkSync as unlinkSync6 } from "fs";
4229
4239
  function spawnLockPath(sessionName) {
@@ -4637,7 +4647,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4637
4647
  const transport = getTransport();
4638
4648
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
4639
4649
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
4640
- const logDir = path15.join(os7.homedir(), ".exe-os", "session-logs");
4650
+ const logDir = path15.join(os8.homedir(), ".exe-os", "session-logs");
4641
4651
  const logFile = path15.join(logDir, `${instanceLabel}-${Date.now()}.log`);
4642
4652
  if (!existsSync12(logDir)) {
4643
4653
  mkdirSync6(logDir, { recursive: true });
@@ -4653,7 +4663,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4653
4663
  } catch {
4654
4664
  }
4655
4665
  try {
4656
- const claudeJsonPath = path15.join(os7.homedir(), ".claude.json");
4666
+ const claudeJsonPath = path15.join(os8.homedir(), ".claude.json");
4657
4667
  let claudeJson = {};
4658
4668
  try {
4659
4669
  claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
@@ -4668,7 +4678,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4668
4678
  } catch {
4669
4679
  }
4670
4680
  try {
4671
- const settingsDir = path15.join(os7.homedir(), ".claude", "projects");
4681
+ const settingsDir = path15.join(os8.homedir(), ".claude", "projects");
4672
4682
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
4673
4683
  const projSettingsDir = path15.join(settingsDir, normalizedKey);
4674
4684
  const settingsPath = path15.join(projSettingsDir, "settings.json");
@@ -4719,7 +4729,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4719
4729
  let legacyFallbackWarned = false;
4720
4730
  if (!useExeAgent && !useBinSymlink) {
4721
4731
  const identityPath = path15.join(
4722
- os7.homedir(),
4732
+ os8.homedir(),
4723
4733
  ".exe-os",
4724
4734
  "identity",
4725
4735
  `${employeeName}.md`
@@ -4749,7 +4759,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4749
4759
  }
4750
4760
  let sessionContextFlag = "";
4751
4761
  try {
4752
- const ctxDir = path15.join(os7.homedir(), ".exe-os", "session-cache");
4762
+ const ctxDir = path15.join(os8.homedir(), ".exe-os", "session-cache");
4753
4763
  mkdirSync6(ctxDir, { recursive: true });
4754
4764
  const ctxFile = path15.join(ctxDir, `session-context-${sessionName}.md`);
4755
4765
  const ctxContent = [
@@ -4910,13 +4920,13 @@ var init_tmux_routing = __esm({
4910
4920
  init_intercom_queue();
4911
4921
  init_plan_limits();
4912
4922
  init_employees();
4913
- SPAWN_LOCK_DIR = path15.join(os7.homedir(), ".exe-os", "spawn-locks");
4914
- SESSION_CACHE = path15.join(os7.homedir(), ".exe-os", "session-cache");
4923
+ SPAWN_LOCK_DIR = path15.join(os8.homedir(), ".exe-os", "spawn-locks");
4924
+ SESSION_CACHE = path15.join(os8.homedir(), ".exe-os", "session-cache");
4915
4925
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
4916
4926
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
4917
4927
  VERIFY_PANE_LINES = 200;
4918
4928
  INTERCOM_DEBOUNCE_MS = 3e4;
4919
- INTERCOM_LOG2 = path15.join(os7.homedir(), ".exe-os", "intercom.log");
4929
+ INTERCOM_LOG2 = path15.join(os8.homedir(), ".exe-os", "intercom.log");
4920
4930
  DEBOUNCE_FILE = path15.join(SESSION_CACHE, "intercom-debounce.json");
4921
4931
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
4922
4932
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -4960,9 +4970,9 @@ var init_memory = __esm({
4960
4970
  import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
4961
4971
  import { existsSync as existsSync13 } from "fs";
4962
4972
  import path16 from "path";
4963
- import os8 from "os";
4973
+ import os9 from "os";
4964
4974
  function getKeyDir() {
4965
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path16.join(os8.homedir(), ".exe-os");
4975
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path16.join(os9.homedir(), ".exe-os");
4966
4976
  }
4967
4977
  function getKeyPath() {
4968
4978
  return path16.join(getKeyDir(), "master.key");
@@ -4988,7 +4998,7 @@ async function getMasterKey() {
4988
4998
  const keyPath = getKeyPath();
4989
4999
  if (!existsSync13(keyPath)) {
4990
5000
  process.stderr.write(
4991
- `[keychain] Key not found at ${keyPath} (HOME=${os8.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
5001
+ `[keychain] Key not found at ${keyPath} (HOME=${os9.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
4992
5002
  `
4993
5003
  );
4994
5004
  return null;
@@ -6010,7 +6020,7 @@ var init_store = __esm({
6010
6020
  // src/bin/scan-tasks.ts
6011
6021
  import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
6012
6022
  import path18 from "path";
6013
- import os9 from "os";
6023
+ import os10 from "os";
6014
6024
 
6015
6025
  // src/lib/is-main.ts
6016
6026
  import { realpathSync } from "fs";
@@ -6031,7 +6041,7 @@ function isMainModule(importMetaUrl) {
6031
6041
  init_task_scope();
6032
6042
  function checkMcpHealth() {
6033
6043
  try {
6034
- const claudeJson = path18.join(os9.homedir(), ".claude.json");
6044
+ const claudeJson = path18.join(os10.homedir(), ".claude.json");
6035
6045
  if (!existsSync15(claudeJson)) {
6036
6046
  process.stderr.write(
6037
6047
  "\u26A0\uFE0F MCP config missing (~/.claude.json not found) \u2014 close_task won't work. Run /exe-setup\n"
package/dist/bin/setup.js CHANGED
@@ -389,6 +389,7 @@ var init_memory = __esm({
389
389
 
390
390
  // src/lib/exe-daemon-client.ts
391
391
  import net from "net";
392
+ import os3 from "os";
392
393
  import { spawn } from "child_process";
393
394
  import { randomUUID } from "crypto";
394
395
  import { existsSync as existsSync4, unlinkSync as unlinkSync2, readFileSync as readFileSync2, openSync, closeSync, statSync } from "fs";
@@ -452,6 +453,15 @@ function findPackageRoot() {
452
453
  return null;
453
454
  }
454
455
  function spawnDaemon() {
456
+ const freeGB = os3.freemem() / (1024 * 1024 * 1024);
457
+ const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
458
+ if (freeGB < 1.5 && totalGB <= 8) {
459
+ process.stderr.write(
460
+ `[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.
461
+ `
462
+ );
463
+ return;
464
+ }
455
465
  const pkgRoot = findPackageRoot();
456
466
  if (!pkgRoot) {
457
467
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -1320,7 +1330,7 @@ import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir4 } from
1320
1330
  import { existsSync as existsSync6, symlinkSync, readlinkSync, readFileSync as readFileSync4, renameSync as renameSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "fs";
1321
1331
  import { execSync } from "child_process";
1322
1332
  import path6 from "path";
1323
- import os3 from "os";
1333
+ import os4 from "os";
1324
1334
  function normalizeRole(role) {
1325
1335
  return (role ?? "").trim().toLowerCase();
1326
1336
  }
@@ -1424,7 +1434,7 @@ async function normalizeRosterCase(rosterPath) {
1424
1434
  emp.name = emp.name.toLowerCase();
1425
1435
  changed = true;
1426
1436
  try {
1427
- const identityDir = path6.join(os3.homedir(), ".exe-os", "identity");
1437
+ const identityDir = path6.join(os4.homedir(), ".exe-os", "identity");
1428
1438
  const oldPath = path6.join(identityDir, `${oldName}.md`);
1429
1439
  const newPath = path6.join(identityDir, `${emp.name}.md`);
1430
1440
  if (existsSync6(oldPath) && !existsSync6(newPath)) {
@@ -5617,7 +5627,7 @@ init_config();
5617
5627
  init_keychain();
5618
5628
  import crypto3 from "crypto";
5619
5629
  import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync7, unlinkSync as unlinkSync7 } from "fs";
5620
- import os4 from "os";
5630
+ import os5 from "os";
5621
5631
  import path11 from "path";
5622
5632
  import { createInterface } from "readline";
5623
5633
 
@@ -5725,7 +5735,7 @@ function findPackageRoot2() {
5725
5735
  }
5726
5736
  return null;
5727
5737
  }
5728
- var SETUP_STATE_PATH = path11.join(os4.homedir(), ".exe-os", "setup-state.json");
5738
+ var SETUP_STATE_PATH = path11.join(os5.homedir(), ".exe-os", "setup-state.json");
5729
5739
  function loadSetupState() {
5730
5740
  try {
5731
5741
  return JSON.parse(readFileSync9(SETUP_STATE_PATH, "utf8"));
@@ -5753,7 +5763,33 @@ function ask(rl, prompt) {
5753
5763
  doAsk();
5754
5764
  });
5755
5765
  }
5766
+ function getAvailableMemoryGB() {
5767
+ return os5.freemem() / (1024 * 1024 * 1024);
5768
+ }
5769
+ function getTotalMemoryGB() {
5770
+ return os5.totalmem() / (1024 * 1024 * 1024);
5771
+ }
5772
+ function isLowMemory() {
5773
+ return getAvailableMemoryGB() < 2;
5774
+ }
5756
5775
  async function validateModel(log) {
5776
+ const totalGB = getTotalMemoryGB();
5777
+ const freeGB = getAvailableMemoryGB();
5778
+ if (totalGB <= 8 || isLowMemory()) {
5779
+ log(`System memory: ${totalGB.toFixed(0)}GB total, ${freeGB.toFixed(1)}GB free`);
5780
+ log("Skipping in-memory model validation (low memory \u2014 will validate on first use).");
5781
+ const modelPath = path11.join(MODELS_DIR, LOCAL_FILENAME);
5782
+ if (existsSync11(modelPath)) {
5783
+ const { statSync: statSync2 } = await import("fs");
5784
+ const size = statSync2(modelPath).size;
5785
+ if (size > 300 * 1e6) {
5786
+ log(`Model file verified (${(size / 1e6).toFixed(0)} MB).`);
5787
+ return;
5788
+ }
5789
+ throw new Error(`Model file too small (${(size / 1e6).toFixed(0)} MB) \u2014 may be corrupted. Delete and re-run setup.`);
5790
+ }
5791
+ throw new Error("Model file not found after download.");
5792
+ }
5757
5793
  log("Validating model...");
5758
5794
  const { embedDirect: embedDirect2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
5759
5795
  const result = await embedDirect2("test embedding");
@@ -5945,6 +5981,15 @@ async function runSetupWizard(opts = {}) {
5945
5981
  log("");
5946
5982
  if (!state.completedSteps.includes(3)) {
5947
5983
  if (!skipModel2) {
5984
+ const freeGB = getAvailableMemoryGB();
5985
+ const totalGB = getTotalMemoryGB();
5986
+ if (freeGB < 2) {
5987
+ log(`\u26A0 Low memory detected: ${freeGB.toFixed(1)}GB free of ${totalGB.toFixed(0)}GB total`);
5988
+ log(" Close other applications (browser, Slack, etc.) before continuing.");
5989
+ log(" The embedding model needs ~500MB to download and load.");
5990
+ log("");
5991
+ await ask(rl, "Press Enter when ready, or Ctrl+C to abort and free memory first: ");
5992
+ }
5948
5993
  log("Note: jina-embeddings-v5-text-small is licensed CC-BY-NC-4.0 (non-commercial)");
5949
5994
  log("");
5950
5995
  await downloadModel({
@@ -5981,7 +6026,7 @@ async function runSetupWizard(opts = {}) {
5981
6026
  await saveConfig(config);
5982
6027
  log("");
5983
6028
  try {
5984
- const claudeJsonPath = path11.join(os4.homedir(), ".claude.json");
6029
+ const claudeJsonPath = path11.join(os5.homedir(), ".claude.json");
5985
6030
  let claudeJson = {};
5986
6031
  try {
5987
6032
  claudeJson = JSON.parse(readFileSync9(claudeJsonPath, "utf8"));
@@ -5989,7 +6034,7 @@ async function runSetupWizard(opts = {}) {
5989
6034
  }
5990
6035
  if (!claudeJson.projects) claudeJson.projects = {};
5991
6036
  const projects = claudeJson.projects;
5992
- for (const dir of [process.cwd(), os4.homedir()]) {
6037
+ for (const dir of [process.cwd(), os5.homedir()]) {
5993
6038
  if (!projects[dir]) projects[dir] = {};
5994
6039
  projects[dir].hasTrustDialogAccepted = true;
5995
6040
  }
@@ -6264,7 +6309,7 @@ async function runSetupWizard(opts = {}) {
6264
6309
  log(`Session shortcuts generated (${cooName}1, ${cooName}2, ...)`);
6265
6310
  }
6266
6311
  if (wrapResult.pathConfigured) {
6267
- const binDir = path11.join(os4.homedir(), ".exe-os", "bin");
6312
+ const binDir = path11.join(os5.homedir(), ".exe-os", "bin");
6268
6313
  process.env.PATH = `${binDir}:${process.env.PATH ?? ""}`;
6269
6314
  pathJustConfigured = true;
6270
6315
  }
@@ -1828,6 +1828,7 @@ var init_memory = __esm({
1828
1828
 
1829
1829
  // src/lib/exe-daemon-client.ts
1830
1830
  import net from "net";
1831
+ import os3 from "os";
1831
1832
  import { spawn } from "child_process";
1832
1833
  import { randomUUID } from "crypto";
1833
1834
  import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -1891,6 +1892,15 @@ function findPackageRoot() {
1891
1892
  return null;
1892
1893
  }
1893
1894
  function spawnDaemon() {
1895
+ const freeGB = os3.freemem() / (1024 * 1024 * 1024);
1896
+ const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
1897
+ if (freeGB < 1.5 && totalGB <= 8) {
1898
+ process.stderr.write(
1899
+ `[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.
1900
+ `
1901
+ );
1902
+ return;
1903
+ }
1894
1904
  const pkgRoot = findPackageRoot();
1895
1905
  if (!pkgRoot) {
1896
1906
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -2229,9 +2239,9 @@ var init_embedder = __esm({
2229
2239
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2230
2240
  import { existsSync as existsSync4 } from "fs";
2231
2241
  import path4 from "path";
2232
- import os3 from "os";
2242
+ import os4 from "os";
2233
2243
  function getKeyDir() {
2234
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os3.homedir(), ".exe-os");
2244
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os4.homedir(), ".exe-os");
2235
2245
  }
2236
2246
  function getKeyPath() {
2237
2247
  return path4.join(getKeyDir(), "master.key");
@@ -2257,7 +2267,7 @@ async function getMasterKey() {
2257
2267
  const keyPath = getKeyPath();
2258
2268
  if (!existsSync4(keyPath)) {
2259
2269
  process.stderr.write(
2260
- `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2270
+ `[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2261
2271
  `
2262
2272
  );
2263
2273
  return null;
@@ -4388,7 +4398,7 @@ var init_whatsapp_accounts = __esm({
4388
4398
  // src/lib/session-registry.ts
4389
4399
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, existsSync as existsSync6 } from "fs";
4390
4400
  import path7 from "path";
4391
- import os5 from "os";
4401
+ import os6 from "os";
4392
4402
  function registerSession(entry) {
4393
4403
  const dir = path7.dirname(REGISTRY_PATH);
4394
4404
  if (!existsSync6(dir)) {
@@ -4415,7 +4425,7 @@ var REGISTRY_PATH;
4415
4425
  var init_session_registry = __esm({
4416
4426
  "src/lib/session-registry.ts"() {
4417
4427
  "use strict";
4418
- REGISTRY_PATH = path7.join(os5.homedir(), ".exe-os", "session-registry.json");
4428
+ REGISTRY_PATH = path7.join(os6.homedir(), ".exe-os", "session-registry.json");
4419
4429
  }
4420
4430
  });
4421
4431
 
@@ -4688,7 +4698,7 @@ var init_agent_config = __esm({
4688
4698
  // src/lib/intercom-queue.ts
4689
4699
  import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync8, mkdirSync as mkdirSync5 } from "fs";
4690
4700
  import path9 from "path";
4691
- import os6 from "os";
4701
+ import os7 from "os";
4692
4702
  function ensureDir() {
4693
4703
  const dir = path9.dirname(QUEUE_PATH);
4694
4704
  if (!existsSync8(dir)) mkdirSync5(dir, { recursive: true });
@@ -4728,9 +4738,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
4728
4738
  var init_intercom_queue = __esm({
4729
4739
  "src/lib/intercom-queue.ts"() {
4730
4740
  "use strict";
4731
- QUEUE_PATH = path9.join(os6.homedir(), ".exe-os", "intercom-queue.json");
4741
+ QUEUE_PATH = path9.join(os7.homedir(), ".exe-os", "intercom-queue.json");
4732
4742
  TTL_MS = 60 * 60 * 1e3;
4733
- INTERCOM_LOG = path9.join(os6.homedir(), ".exe-os", "intercom.log");
4743
+ INTERCOM_LOG = path9.join(os7.homedir(), ".exe-os", "intercom.log");
4734
4744
  }
4735
4745
  });
4736
4746
 
@@ -4838,7 +4848,7 @@ var init_plan_limits = __esm({
4838
4848
  // src/lib/notifications.ts
4839
4849
  import crypto3 from "crypto";
4840
4850
  import path12 from "path";
4841
- import os7 from "os";
4851
+ import os8 from "os";
4842
4852
  import {
4843
4853
  readFileSync as readFileSync10,
4844
4854
  readdirSync as readdirSync2,
@@ -4948,7 +4958,7 @@ var init_task_scope = __esm({
4948
4958
  // src/lib/tasks-crud.ts
4949
4959
  import crypto5 from "crypto";
4950
4960
  import path13 from "path";
4951
- import os8 from "os";
4961
+ import os9 from "os";
4952
4962
  import { execSync as execSync4 } from "child_process";
4953
4963
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
4954
4964
  import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
@@ -5163,7 +5173,7 @@ ${laneWarning}` : laneWarning;
5163
5173
  });
5164
5174
  if (input.baseDir) {
5165
5175
  try {
5166
- const EXE_OS_DIR = path13.join(os8.homedir(), ".exe-os");
5176
+ const EXE_OS_DIR = path13.join(os9.homedir(), ".exe-os");
5167
5177
  const mdPath = path13.join(EXE_OS_DIR, taskFile);
5168
5178
  const mdDir = path13.dirname(mdPath);
5169
5179
  if (!existsSync12(mdDir)) await mkdir4(mdDir, { recursive: true });
@@ -6809,7 +6819,7 @@ __export(tmux_routing_exports, {
6809
6819
  import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
6810
6820
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, existsSync as existsSync14, appendFileSync } from "fs";
6811
6821
  import path18 from "path";
6812
- import os9 from "os";
6822
+ import os10 from "os";
6813
6823
  import { fileURLToPath as fileURLToPath2 } from "url";
6814
6824
  import { unlinkSync as unlinkSync6 } from "fs";
6815
6825
  function spawnLockPath(sessionName) {
@@ -7223,7 +7233,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7223
7233
  const transport = getTransport();
7224
7234
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
7225
7235
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
7226
- const logDir = path18.join(os9.homedir(), ".exe-os", "session-logs");
7236
+ const logDir = path18.join(os10.homedir(), ".exe-os", "session-logs");
7227
7237
  const logFile = path18.join(logDir, `${instanceLabel}-${Date.now()}.log`);
7228
7238
  if (!existsSync14(logDir)) {
7229
7239
  mkdirSync8(logDir, { recursive: true });
@@ -7239,7 +7249,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7239
7249
  } catch {
7240
7250
  }
7241
7251
  try {
7242
- const claudeJsonPath = path18.join(os9.homedir(), ".claude.json");
7252
+ const claudeJsonPath = path18.join(os10.homedir(), ".claude.json");
7243
7253
  let claudeJson = {};
7244
7254
  try {
7245
7255
  claudeJson = JSON.parse(readFileSync12(claudeJsonPath, "utf8"));
@@ -7254,7 +7264,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7254
7264
  } catch {
7255
7265
  }
7256
7266
  try {
7257
- const settingsDir = path18.join(os9.homedir(), ".claude", "projects");
7267
+ const settingsDir = path18.join(os10.homedir(), ".claude", "projects");
7258
7268
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
7259
7269
  const projSettingsDir = path18.join(settingsDir, normalizedKey);
7260
7270
  const settingsPath = path18.join(projSettingsDir, "settings.json");
@@ -7305,7 +7315,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7305
7315
  let legacyFallbackWarned = false;
7306
7316
  if (!useExeAgent && !useBinSymlink) {
7307
7317
  const identityPath = path18.join(
7308
- os9.homedir(),
7318
+ os10.homedir(),
7309
7319
  ".exe-os",
7310
7320
  "identity",
7311
7321
  `${employeeName}.md`
@@ -7335,7 +7345,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7335
7345
  }
7336
7346
  let sessionContextFlag = "";
7337
7347
  try {
7338
- const ctxDir = path18.join(os9.homedir(), ".exe-os", "session-cache");
7348
+ const ctxDir = path18.join(os10.homedir(), ".exe-os", "session-cache");
7339
7349
  mkdirSync8(ctxDir, { recursive: true });
7340
7350
  const ctxFile = path18.join(ctxDir, `session-context-${sessionName}.md`);
7341
7351
  const ctxContent = [
@@ -7496,13 +7506,13 @@ var init_tmux_routing = __esm({
7496
7506
  init_intercom_queue();
7497
7507
  init_plan_limits();
7498
7508
  init_employees();
7499
- SPAWN_LOCK_DIR = path18.join(os9.homedir(), ".exe-os", "spawn-locks");
7500
- SESSION_CACHE = path18.join(os9.homedir(), ".exe-os", "session-cache");
7509
+ SPAWN_LOCK_DIR = path18.join(os10.homedir(), ".exe-os", "spawn-locks");
7510
+ SESSION_CACHE = path18.join(os10.homedir(), ".exe-os", "session-cache");
7501
7511
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
7502
7512
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
7503
7513
  VERIFY_PANE_LINES = 200;
7504
7514
  INTERCOM_DEBOUNCE_MS = 3e4;
7505
- INTERCOM_LOG2 = path18.join(os9.homedir(), ".exe-os", "intercom.log");
7515
+ INTERCOM_LOG2 = path18.join(os10.homedir(), ".exe-os", "intercom.log");
7506
7516
  DEBOUNCE_FILE = path18.join(SESSION_CACHE, "intercom-debounce.json");
7507
7517
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
7508
7518
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -10687,12 +10697,12 @@ var SlackAdapter = class {
10687
10697
  // src/gateway/adapters/imessage.ts
10688
10698
  import { execFile } from "child_process";
10689
10699
  import { promisify } from "util";
10690
- import os4 from "os";
10700
+ import os5 from "os";
10691
10701
  import path6 from "path";
10692
10702
  var execFileAsync = promisify(execFile);
10693
10703
  var POLL_INTERVAL_MS = 5e3;
10694
10704
  var MESSAGES_DB_PATH = path6.join(
10695
- process.env.HOME ?? os4.homedir(),
10705
+ process.env.HOME ?? os5.homedir(),
10696
10706
  "Library/Messages/chat.db"
10697
10707
  );
10698
10708
  var IMessageAdapter = class {
@@ -11538,8 +11548,8 @@ async function ensureCRMContact(info) {
11538
11548
  import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, existsSync as existsSync15, mkdirSync as mkdirSync9 } from "fs";
11539
11549
  import { randomUUID as randomUUID12 } from "crypto";
11540
11550
  import path19 from "path";
11541
- import os10 from "os";
11542
- var TRIGGERS_PATH = path19.join(os10.homedir(), ".exe-os", "triggers.json");
11551
+ import os11 from "os";
11552
+ var TRIGGERS_PATH = path19.join(os11.homedir(), ".exe-os", "triggers.json");
11543
11553
  var GRAPH_API_VERSION = "v21.0";
11544
11554
  function substituteTemplate(template, record) {
11545
11555
  return template.replace(
@@ -659,6 +659,7 @@ var init_employees = __esm({
659
659
 
660
660
  // src/lib/exe-daemon-client.ts
661
661
  import net from "net";
662
+ import os5 from "os";
662
663
  import { spawn } from "child_process";
663
664
  import { randomUUID } from "crypto";
664
665
  import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync6, openSync, closeSync, statSync } from "fs";
@@ -722,6 +723,15 @@ function findPackageRoot() {
722
723
  return null;
723
724
  }
724
725
  function spawnDaemon() {
726
+ const freeGB = os5.freemem() / (1024 * 1024 * 1024);
727
+ const totalGB = os5.totalmem() / (1024 * 1024 * 1024);
728
+ if (freeGB < 1.5 && totalGB <= 8) {
729
+ process.stderr.write(
730
+ `[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.
731
+ `
732
+ );
733
+ return;
734
+ }
725
735
  const pkgRoot = findPackageRoot();
726
736
  if (!pkgRoot) {
727
737
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -2211,7 +2221,7 @@ var init_plan_limits = __esm({
2211
2221
  // src/lib/notifications.ts
2212
2222
  import crypto from "crypto";
2213
2223
  import path9 from "path";
2214
- import os5 from "os";
2224
+ import os6 from "os";
2215
2225
  import {
2216
2226
  readFileSync as readFileSync9,
2217
2227
  readdirSync,
@@ -2368,7 +2378,7 @@ __export(tasks_crud_exports, {
2368
2378
  });
2369
2379
  import crypto3 from "crypto";
2370
2380
  import path10 from "path";
2371
- import os6 from "os";
2381
+ import os7 from "os";
2372
2382
  import { execSync as execSync4 } from "child_process";
2373
2383
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
2374
2384
  import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
@@ -2583,7 +2593,7 @@ ${laneWarning}` : laneWarning;
2583
2593
  });
2584
2594
  if (input.baseDir) {
2585
2595
  try {
2586
- const EXE_OS_DIR = path10.join(os6.homedir(), ".exe-os");
2596
+ const EXE_OS_DIR = path10.join(os7.homedir(), ".exe-os");
2587
2597
  const mdPath = path10.join(EXE_OS_DIR, taskFile);
2588
2598
  const mdDir = path10.dirname(mdPath);
2589
2599
  if (!existsSync10(mdDir)) await mkdir3(mdDir, { recursive: true });
@@ -4229,7 +4239,7 @@ __export(tmux_routing_exports, {
4229
4239
  import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
4230
4240
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, existsSync as existsSync12, appendFileSync } from "fs";
4231
4241
  import path15 from "path";
4232
- import os7 from "os";
4242
+ import os8 from "os";
4233
4243
  import { fileURLToPath as fileURLToPath2 } from "url";
4234
4244
  import { unlinkSync as unlinkSync6 } from "fs";
4235
4245
  function spawnLockPath(sessionName) {
@@ -4643,7 +4653,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4643
4653
  const transport = getTransport();
4644
4654
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
4645
4655
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
4646
- const logDir = path15.join(os7.homedir(), ".exe-os", "session-logs");
4656
+ const logDir = path15.join(os8.homedir(), ".exe-os", "session-logs");
4647
4657
  const logFile = path15.join(logDir, `${instanceLabel}-${Date.now()}.log`);
4648
4658
  if (!existsSync12(logDir)) {
4649
4659
  mkdirSync6(logDir, { recursive: true });
@@ -4659,7 +4669,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4659
4669
  } catch {
4660
4670
  }
4661
4671
  try {
4662
- const claudeJsonPath = path15.join(os7.homedir(), ".claude.json");
4672
+ const claudeJsonPath = path15.join(os8.homedir(), ".claude.json");
4663
4673
  let claudeJson = {};
4664
4674
  try {
4665
4675
  claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
@@ -4674,7 +4684,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4674
4684
  } catch {
4675
4685
  }
4676
4686
  try {
4677
- const settingsDir = path15.join(os7.homedir(), ".claude", "projects");
4687
+ const settingsDir = path15.join(os8.homedir(), ".claude", "projects");
4678
4688
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
4679
4689
  const projSettingsDir = path15.join(settingsDir, normalizedKey);
4680
4690
  const settingsPath = path15.join(projSettingsDir, "settings.json");
@@ -4725,7 +4735,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4725
4735
  let legacyFallbackWarned = false;
4726
4736
  if (!useExeAgent && !useBinSymlink) {
4727
4737
  const identityPath = path15.join(
4728
- os7.homedir(),
4738
+ os8.homedir(),
4729
4739
  ".exe-os",
4730
4740
  "identity",
4731
4741
  `${employeeName}.md`
@@ -4755,7 +4765,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4755
4765
  }
4756
4766
  let sessionContextFlag = "";
4757
4767
  try {
4758
- const ctxDir = path15.join(os7.homedir(), ".exe-os", "session-cache");
4768
+ const ctxDir = path15.join(os8.homedir(), ".exe-os", "session-cache");
4759
4769
  mkdirSync6(ctxDir, { recursive: true });
4760
4770
  const ctxFile = path15.join(ctxDir, `session-context-${sessionName}.md`);
4761
4771
  const ctxContent = [
@@ -4916,13 +4926,13 @@ var init_tmux_routing = __esm({
4916
4926
  init_intercom_queue();
4917
4927
  init_plan_limits();
4918
4928
  init_employees();
4919
- SPAWN_LOCK_DIR = path15.join(os7.homedir(), ".exe-os", "spawn-locks");
4920
- SESSION_CACHE = path15.join(os7.homedir(), ".exe-os", "session-cache");
4929
+ SPAWN_LOCK_DIR = path15.join(os8.homedir(), ".exe-os", "spawn-locks");
4930
+ SESSION_CACHE = path15.join(os8.homedir(), ".exe-os", "session-cache");
4921
4931
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
4922
4932
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
4923
4933
  VERIFY_PANE_LINES = 200;
4924
4934
  INTERCOM_DEBOUNCE_MS = 3e4;
4925
- INTERCOM_LOG2 = path15.join(os7.homedir(), ".exe-os", "intercom.log");
4935
+ INTERCOM_LOG2 = path15.join(os8.homedir(), ".exe-os", "intercom.log");
4926
4936
  DEBOUNCE_FILE = path15.join(SESSION_CACHE, "intercom-debounce.json");
4927
4937
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
4928
4938
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -4966,9 +4976,9 @@ var init_memory = __esm({
4966
4976
  import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
4967
4977
  import { existsSync as existsSync13 } from "fs";
4968
4978
  import path16 from "path";
4969
- import os8 from "os";
4979
+ import os9 from "os";
4970
4980
  function getKeyDir() {
4971
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path16.join(os8.homedir(), ".exe-os");
4981
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path16.join(os9.homedir(), ".exe-os");
4972
4982
  }
4973
4983
  function getKeyPath() {
4974
4984
  return path16.join(getKeyDir(), "master.key");
@@ -4994,7 +5004,7 @@ async function getMasterKey() {
4994
5004
  const keyPath = getKeyPath();
4995
5005
  if (!existsSync13(keyPath)) {
4996
5006
  process.stderr.write(
4997
- `[keychain] Key not found at ${keyPath} (HOME=${os8.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
5007
+ `[keychain] Key not found at ${keyPath} (HOME=${os9.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
4998
5008
  `
4999
5009
  );
5000
5010
  return null;
@@ -2663,6 +2663,7 @@ var init_reranker = __esm({
2663
2663
 
2664
2664
  // src/lib/exe-daemon-client.ts
2665
2665
  import net from "net";
2666
+ import os4 from "os";
2666
2667
  import { spawn } from "child_process";
2667
2668
  import { randomUUID as randomUUID2 } from "crypto";
2668
2669
  import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -2726,6 +2727,15 @@ function findPackageRoot() {
2726
2727
  return null;
2727
2728
  }
2728
2729
  function spawnDaemon() {
2730
+ const freeGB = os4.freemem() / (1024 * 1024 * 1024);
2731
+ const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
2732
+ if (freeGB < 1.5 && totalGB <= 8) {
2733
+ process.stderr.write(
2734
+ `[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.
2735
+ `
2736
+ );
2737
+ return;
2738
+ }
2729
2739
  const pkgRoot = findPackageRoot();
2730
2740
  if (!pkgRoot) {
2731
2741
  process.stderr.write("[exed-client] WARN: cannot find package root\n");