@askexenow/exe-os 0.9.16 → 0.9.18

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 (97) hide show
  1. package/dist/bin/backfill-conversations.js +1242 -909
  2. package/dist/bin/backfill-responses.js +1245 -912
  3. package/dist/bin/backfill-vectors.js +1244 -906
  4. package/dist/bin/cleanup-stale-review-tasks.js +1870 -417
  5. package/dist/bin/cli.js +217 -107
  6. package/dist/bin/exe-agent-config.js +2 -2
  7. package/dist/bin/exe-agent.js +62 -0
  8. package/dist/bin/exe-assign.js +346 -10
  9. package/dist/bin/exe-boot.js +387 -32
  10. package/dist/bin/exe-call.js +72 -2
  11. package/dist/bin/exe-cloud.js +8 -0
  12. package/dist/bin/exe-dispatch.js +1821 -225
  13. package/dist/bin/exe-doctor.js +720 -52
  14. package/dist/bin/exe-export-behaviors.js +1429 -148
  15. package/dist/bin/exe-forget.js +1408 -34
  16. package/dist/bin/exe-gateway.js +1629 -1295
  17. package/dist/bin/exe-heartbeat.js +1899 -448
  18. package/dist/bin/exe-kill.js +1624 -346
  19. package/dist/bin/exe-launch-agent.js +726 -90
  20. package/dist/bin/exe-link.js +27 -8
  21. package/dist/bin/exe-new-employee.js +75 -9
  22. package/dist/bin/exe-pending-messages.js +2769 -1316
  23. package/dist/bin/exe-pending-notifications.js +2829 -1376
  24. package/dist/bin/exe-pending-reviews.js +2847 -1392
  25. package/dist/bin/exe-rename.js +89 -8
  26. package/dist/bin/exe-review.js +1494 -312
  27. package/dist/bin/exe-search.js +1608 -1300
  28. package/dist/bin/exe-session-cleanup.js +194 -91
  29. package/dist/bin/exe-settings.js +10 -2
  30. package/dist/bin/exe-start-codex.js +769 -120
  31. package/dist/bin/exe-start-opencode.js +763 -108
  32. package/dist/bin/exe-status.js +1887 -434
  33. package/dist/bin/exe-team.js +1782 -324
  34. package/dist/bin/git-sweep.js +408 -33
  35. package/dist/bin/graph-backfill.js +681 -27
  36. package/dist/bin/graph-export.js +1419 -141
  37. package/dist/bin/install.js +4 -8
  38. package/dist/bin/intercom-check.js +8641 -0
  39. package/dist/bin/scan-tasks.js +553 -38
  40. package/dist/bin/setup.js +82 -10
  41. package/dist/bin/shard-migrate.js +682 -28
  42. package/dist/gateway/index.js +1629 -1295
  43. package/dist/hooks/bug-report-worker.js +1136 -183
  44. package/dist/hooks/codex-stop-task-finalizer.js +1060 -107
  45. package/dist/hooks/commit-complete.js +408 -33
  46. package/dist/hooks/error-recall.js +1608 -1300
  47. package/dist/hooks/ingest-worker.js +250 -7966
  48. package/dist/hooks/ingest.js +707 -119
  49. package/dist/hooks/instructions-loaded.js +383 -20
  50. package/dist/hooks/notification.js +383 -20
  51. package/dist/hooks/post-compact.js +384 -21
  52. package/dist/hooks/{response-ingest-worker.js → post-tool-combined.js} +4157 -1716
  53. package/dist/hooks/pre-compact.js +486 -45
  54. package/dist/hooks/pre-tool-use.js +385 -22
  55. package/dist/hooks/prompt-submit.js +291 -96
  56. package/dist/hooks/session-end.js +490 -48
  57. package/dist/hooks/session-start.js +236 -22
  58. package/dist/hooks/stop.js +192 -50
  59. package/dist/hooks/subagent-stop.js +95 -18
  60. package/dist/hooks/summary-worker.js +205 -361
  61. package/dist/index.js +221 -105
  62. package/dist/lib/agent-config.js +2 -2
  63. package/dist/lib/cloud-sync.js +27 -8
  64. package/dist/lib/consolidation.js +437 -41
  65. package/dist/lib/database.js +20 -8
  66. package/dist/lib/db-daemon-client.js +2 -2
  67. package/dist/lib/db.js +20 -8
  68. package/dist/lib/device-registry.js +27 -8
  69. package/dist/lib/employee-templates.js +62 -0
  70. package/dist/lib/employees.js +2 -2
  71. package/dist/lib/exe-daemon.js +6703 -6259
  72. package/dist/lib/hybrid-search.js +1608 -1300
  73. package/dist/lib/identity.js +1 -1
  74. package/dist/lib/messaging.js +11 -3
  75. package/dist/lib/reminders.js +1 -1
  76. package/dist/lib/schedules.js +718 -26
  77. package/dist/lib/session-registry.js +11 -0
  78. package/dist/lib/skill-learning.js +639 -9
  79. package/dist/lib/store.js +676 -27
  80. package/dist/lib/tasks.js +665 -27
  81. package/dist/lib/tmux-routing.js +732 -94
  82. package/dist/lib/token-spend.js +1 -1
  83. package/dist/mcp/server.js +856 -383
  84. package/dist/mcp/tools/complete-reminder.js +1 -1
  85. package/dist/mcp/tools/create-reminder.js +1 -1
  86. package/dist/mcp/tools/create-task.js +616 -46
  87. package/dist/mcp/tools/deactivate-behavior.js +9 -1
  88. package/dist/mcp/tools/list-reminders.js +1 -1
  89. package/dist/mcp/tools/list-tasks.js +10 -2
  90. package/dist/mcp/tools/send-message.js +11 -3
  91. package/dist/mcp/tools/update-task.js +677 -39
  92. package/dist/runtime/index.js +425 -37
  93. package/dist/tui/App.js +365 -34
  94. package/package.json +5 -2
  95. package/src/commands/exe/intercom.md +6 -17
  96. package/dist/bin/wiki-sync.js +0 -2991
  97. package/dist/hooks/prompt-ingest-worker.js +0 -3979
@@ -355,7 +355,7 @@ var init_agent_config = __esm({
355
355
  init_secure_files();
356
356
  AGENT_CONFIG_PATH = path2.join(EXE_AI_DIR, "agent-config.json");
357
357
  KNOWN_RUNTIMES = {
358
- claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
358
+ claude: ["claude-opus-4.6", "claude-opus-4", "claude-sonnet-4.6", "claude-sonnet-4", "claude-haiku-4.5"],
359
359
  codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
360
360
  opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
361
361
  };
@@ -365,7 +365,7 @@ var init_agent_config = __esm({
365
365
  opencode: "OpenCode (open source)"
366
366
  };
367
367
  DEFAULT_MODELS = {
368
- claude: "claude-opus-4",
368
+ claude: "claude-opus-4.6",
369
369
  codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
370
370
  opencode: RUNTIME_TABLE.opencode?.defaultModel ?? "anthropic/claude-sonnet-4-6"
371
371
  };
@@ -710,9 +710,9 @@ var MAX_RETRIES, BASE_DELAY_MS, MAX_JITTER_MS;
710
710
  var init_db_retry = __esm({
711
711
  "src/lib/db-retry.ts"() {
712
712
  "use strict";
713
- MAX_RETRIES = 3;
714
- BASE_DELAY_MS = 200;
715
- MAX_JITTER_MS = 300;
713
+ MAX_RETRIES = 5;
714
+ BASE_DELAY_MS = 250;
715
+ MAX_JITTER_MS = 400;
716
716
  }
717
717
  });
718
718
 
@@ -1300,7 +1300,544 @@ var init_database_adapter = __esm({
1300
1300
  }
1301
1301
  });
1302
1302
 
1303
+ // src/lib/daemon-auth.ts
1304
+ var daemon_auth_exports = {};
1305
+ __export(daemon_auth_exports, {
1306
+ DAEMON_TOKEN_PATH: () => DAEMON_TOKEN_PATH,
1307
+ ensureDaemonToken: () => ensureDaemonToken,
1308
+ readDaemonToken: () => readDaemonToken
1309
+ });
1310
+ import crypto2 from "crypto";
1311
+ import path8 from "path";
1312
+ import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
1313
+ function normalizeToken(token) {
1314
+ if (!token) return null;
1315
+ const trimmed = token.trim();
1316
+ return trimmed.length > 0 ? trimmed : null;
1317
+ }
1318
+ function readDaemonToken() {
1319
+ try {
1320
+ if (!existsSync7(DAEMON_TOKEN_PATH)) return null;
1321
+ return normalizeToken(readFileSync6(DAEMON_TOKEN_PATH, "utf8"));
1322
+ } catch {
1323
+ return null;
1324
+ }
1325
+ }
1326
+ function ensureDaemonToken(seed) {
1327
+ const existing = readDaemonToken();
1328
+ if (existing) return existing;
1329
+ const token = normalizeToken(seed) ?? crypto2.randomBytes(32).toString("hex");
1330
+ ensurePrivateDirSync(EXE_AI_DIR);
1331
+ writeFileSync6(DAEMON_TOKEN_PATH, `${token}
1332
+ `, "utf8");
1333
+ enforcePrivateFileSync(DAEMON_TOKEN_PATH);
1334
+ return token;
1335
+ }
1336
+ var DAEMON_TOKEN_PATH;
1337
+ var init_daemon_auth = __esm({
1338
+ "src/lib/daemon-auth.ts"() {
1339
+ "use strict";
1340
+ init_config();
1341
+ init_secure_files();
1342
+ DAEMON_TOKEN_PATH = path8.join(EXE_AI_DIR, "exed.token");
1343
+ }
1344
+ });
1345
+
1346
+ // src/lib/exe-daemon-client.ts
1347
+ import net from "net";
1348
+ import os5 from "os";
1349
+ import { spawn } from "child_process";
1350
+ import { randomUUID } from "crypto";
1351
+ import { existsSync as existsSync8, unlinkSync as unlinkSync5, readFileSync as readFileSync7, openSync, closeSync, statSync } from "fs";
1352
+ import path9 from "path";
1353
+ import { fileURLToPath } from "url";
1354
+ function handleData(chunk) {
1355
+ _buffer += chunk.toString();
1356
+ if (_buffer.length > MAX_BUFFER) {
1357
+ _buffer = "";
1358
+ return;
1359
+ }
1360
+ let newlineIdx;
1361
+ while ((newlineIdx = _buffer.indexOf("\n")) !== -1) {
1362
+ const line = _buffer.slice(0, newlineIdx).trim();
1363
+ _buffer = _buffer.slice(newlineIdx + 1);
1364
+ if (!line) continue;
1365
+ try {
1366
+ const response = JSON.parse(line);
1367
+ const id = response.id;
1368
+ if (!id) continue;
1369
+ const entry = _pending.get(id);
1370
+ if (entry) {
1371
+ clearTimeout(entry.timer);
1372
+ _pending.delete(id);
1373
+ entry.resolve(response);
1374
+ }
1375
+ } catch {
1376
+ }
1377
+ }
1378
+ }
1379
+ function cleanupStaleFiles() {
1380
+ if (existsSync8(PID_PATH)) {
1381
+ try {
1382
+ const pid = parseInt(readFileSync7(PID_PATH, "utf8").trim(), 10);
1383
+ if (pid > 0) {
1384
+ try {
1385
+ process.kill(pid, 0);
1386
+ return;
1387
+ } catch {
1388
+ }
1389
+ }
1390
+ } catch {
1391
+ }
1392
+ try {
1393
+ unlinkSync5(PID_PATH);
1394
+ } catch {
1395
+ }
1396
+ try {
1397
+ unlinkSync5(SOCKET_PATH);
1398
+ } catch {
1399
+ }
1400
+ }
1401
+ }
1402
+ function findPackageRoot() {
1403
+ let dir = path9.dirname(fileURLToPath(import.meta.url));
1404
+ const { root } = path9.parse(dir);
1405
+ while (dir !== root) {
1406
+ if (existsSync8(path9.join(dir, "package.json"))) return dir;
1407
+ dir = path9.dirname(dir);
1408
+ }
1409
+ return null;
1410
+ }
1411
+ function getAvailableMemoryGB() {
1412
+ if (process.platform === "darwin") {
1413
+ try {
1414
+ const { execSync: execSync6 } = __require("child_process");
1415
+ const vmstat = execSync6("vm_stat", { encoding: "utf8" });
1416
+ const pageSize = 16384;
1417
+ const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1418
+ const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
1419
+ const free = vmstat.match(/Pages free:\s+(\d+)/);
1420
+ const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
1421
+ const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
1422
+ const freePages = free ? parseInt(free[1], 10) : 0;
1423
+ const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
1424
+ const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
1425
+ return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
1426
+ } catch {
1427
+ return os5.freemem() / (1024 * 1024 * 1024);
1428
+ }
1429
+ }
1430
+ return os5.freemem() / (1024 * 1024 * 1024);
1431
+ }
1432
+ function spawnDaemon() {
1433
+ const freeGB = getAvailableMemoryGB();
1434
+ const totalGB = os5.totalmem() / (1024 * 1024 * 1024);
1435
+ if (totalGB <= 8) {
1436
+ process.stderr.write(
1437
+ `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
1438
+ `
1439
+ );
1440
+ return;
1441
+ }
1442
+ if (totalGB <= 16 && freeGB < 2) {
1443
+ process.stderr.write(
1444
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1445
+ `
1446
+ );
1447
+ return;
1448
+ }
1449
+ const pkgRoot = findPackageRoot();
1450
+ if (!pkgRoot) {
1451
+ process.stderr.write("[exed-client] WARN: cannot find package root\n");
1452
+ return;
1453
+ }
1454
+ const daemonPath = path9.join(pkgRoot, "dist", "lib", "exe-daemon.js");
1455
+ if (!existsSync8(daemonPath)) {
1456
+ process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
1457
+ `);
1458
+ return;
1459
+ }
1460
+ const resolvedPath = daemonPath;
1461
+ const daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV] ?? null);
1462
+ process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
1463
+ `);
1464
+ const logPath = path9.join(path9.dirname(SOCKET_PATH), "exed.log");
1465
+ let stderrFd = "ignore";
1466
+ try {
1467
+ stderrFd = openSync(logPath, "a");
1468
+ } catch {
1469
+ }
1470
+ const heapCapMB = totalGB <= 8 ? 256 : 512;
1471
+ const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
1472
+ const child = spawn(process.execPath, nodeArgs, {
1473
+ detached: true,
1474
+ stdio: ["ignore", "ignore", stderrFd],
1475
+ env: {
1476
+ ...process.env,
1477
+ TMUX: void 0,
1478
+ // Daemon is global — must not inherit session scope
1479
+ TMUX_PANE: void 0,
1480
+ // Prevents resolveExeSession() from scoping to one session
1481
+ EXE_DAEMON_SOCK: SOCKET_PATH,
1482
+ EXE_DAEMON_PID: PID_PATH,
1483
+ [DAEMON_TOKEN_ENV]: daemonToken
1484
+ }
1485
+ });
1486
+ child.unref();
1487
+ if (typeof stderrFd === "number") {
1488
+ try {
1489
+ closeSync(stderrFd);
1490
+ } catch {
1491
+ }
1492
+ }
1493
+ }
1494
+ function acquireSpawnLock() {
1495
+ try {
1496
+ const fd = openSync(SPAWN_LOCK_PATH, "wx");
1497
+ closeSync(fd);
1498
+ return true;
1499
+ } catch {
1500
+ try {
1501
+ const stat = statSync(SPAWN_LOCK_PATH);
1502
+ if (Date.now() - stat.mtimeMs > SPAWN_LOCK_STALE_MS) {
1503
+ try {
1504
+ unlinkSync5(SPAWN_LOCK_PATH);
1505
+ } catch {
1506
+ }
1507
+ try {
1508
+ const fd = openSync(SPAWN_LOCK_PATH, "wx");
1509
+ closeSync(fd);
1510
+ return true;
1511
+ } catch {
1512
+ }
1513
+ }
1514
+ } catch {
1515
+ }
1516
+ return false;
1517
+ }
1518
+ }
1519
+ function releaseSpawnLock() {
1520
+ try {
1521
+ unlinkSync5(SPAWN_LOCK_PATH);
1522
+ } catch {
1523
+ }
1524
+ }
1525
+ function connectToSocket() {
1526
+ return new Promise((resolve) => {
1527
+ if (_socket && _connected) {
1528
+ resolve(true);
1529
+ return;
1530
+ }
1531
+ const socket = net.createConnection({ path: SOCKET_PATH });
1532
+ const connectTimeout = setTimeout(() => {
1533
+ socket.destroy();
1534
+ resolve(false);
1535
+ }, 2e3);
1536
+ socket.on("connect", () => {
1537
+ clearTimeout(connectTimeout);
1538
+ _socket = socket;
1539
+ _connected = true;
1540
+ _buffer = "";
1541
+ socket.on("data", handleData);
1542
+ socket.on("close", () => {
1543
+ _connected = false;
1544
+ _socket = null;
1545
+ for (const [id, entry] of _pending) {
1546
+ clearTimeout(entry.timer);
1547
+ _pending.delete(id);
1548
+ entry.resolve({ error: "Connection closed" });
1549
+ }
1550
+ });
1551
+ socket.on("error", () => {
1552
+ _connected = false;
1553
+ _socket = null;
1554
+ });
1555
+ resolve(true);
1556
+ });
1557
+ socket.on("error", () => {
1558
+ clearTimeout(connectTimeout);
1559
+ resolve(false);
1560
+ });
1561
+ });
1562
+ }
1563
+ async function connectEmbedDaemon() {
1564
+ if (_socket && _connected) return true;
1565
+ if (await connectToSocket()) return true;
1566
+ if (acquireSpawnLock()) {
1567
+ try {
1568
+ cleanupStaleFiles();
1569
+ spawnDaemon();
1570
+ } finally {
1571
+ releaseSpawnLock();
1572
+ }
1573
+ }
1574
+ const start = Date.now();
1575
+ let delay2 = 100;
1576
+ while (Date.now() - start < CONNECT_TIMEOUT_MS) {
1577
+ await new Promise((r) => setTimeout(r, delay2));
1578
+ if (await connectToSocket()) return true;
1579
+ delay2 = Math.min(delay2 * 2, 3e3);
1580
+ }
1581
+ return false;
1582
+ }
1583
+ function sendDaemonRequest(payload, timeoutMs = REQUEST_TIMEOUT_MS) {
1584
+ return new Promise((resolve) => {
1585
+ if (!_socket || !_connected) {
1586
+ resolve({ error: "Not connected" });
1587
+ return;
1588
+ }
1589
+ const id = randomUUID();
1590
+ const token = process.env[DAEMON_TOKEN_ENV] ?? readDaemonToken();
1591
+ const timer = setTimeout(() => {
1592
+ _pending.delete(id);
1593
+ resolve({ error: "Request timeout" });
1594
+ }, timeoutMs);
1595
+ _pending.set(id, { resolve, timer });
1596
+ try {
1597
+ _socket.write(JSON.stringify({ id, token, ...payload }) + "\n");
1598
+ } catch {
1599
+ clearTimeout(timer);
1600
+ _pending.delete(id);
1601
+ resolve({ error: "Write failed" });
1602
+ }
1603
+ });
1604
+ }
1605
+ function isClientConnected() {
1606
+ return _connected;
1607
+ }
1608
+ var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, DAEMON_TOKEN_ENV, _socket, _connected, _buffer, _pending, MAX_BUFFER;
1609
+ var init_exe_daemon_client = __esm({
1610
+ "src/lib/exe-daemon-client.ts"() {
1611
+ "use strict";
1612
+ init_config();
1613
+ init_daemon_auth();
1614
+ SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path9.join(EXE_AI_DIR, "exed.sock");
1615
+ PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path9.join(EXE_AI_DIR, "exed.pid");
1616
+ SPAWN_LOCK_PATH = path9.join(EXE_AI_DIR, "exed-spawn.lock");
1617
+ SPAWN_LOCK_STALE_MS = 3e4;
1618
+ CONNECT_TIMEOUT_MS = 15e3;
1619
+ REQUEST_TIMEOUT_MS = 3e4;
1620
+ DAEMON_TOKEN_ENV = "EXE_DAEMON_TOKEN";
1621
+ _socket = null;
1622
+ _connected = false;
1623
+ _buffer = "";
1624
+ _pending = /* @__PURE__ */ new Map();
1625
+ MAX_BUFFER = 1e7;
1626
+ }
1627
+ });
1628
+
1629
+ // src/lib/daemon-protocol.ts
1630
+ function serializeValue(v) {
1631
+ if (v === null || v === void 0) return null;
1632
+ if (typeof v === "bigint") return Number(v);
1633
+ if (typeof v === "boolean") return v ? 1 : 0;
1634
+ if (v instanceof Uint8Array) {
1635
+ return { __blob: Buffer.from(v).toString("base64") };
1636
+ }
1637
+ if (ArrayBuffer.isView(v)) {
1638
+ return { __blob: Buffer.from(v.buffer, v.byteOffset, v.byteLength).toString("base64") };
1639
+ }
1640
+ if (v instanceof ArrayBuffer) {
1641
+ return { __blob: Buffer.from(v).toString("base64") };
1642
+ }
1643
+ if (typeof v === "string" || typeof v === "number") return v;
1644
+ return String(v);
1645
+ }
1646
+ function deserializeValue(v) {
1647
+ if (v === null) return null;
1648
+ if (typeof v === "object" && v !== null && "__blob" in v) {
1649
+ const buf = Buffer.from(v.__blob, "base64");
1650
+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
1651
+ }
1652
+ return v;
1653
+ }
1654
+ function deserializeResultSet(srs) {
1655
+ const rows = srs.rows.map((obj) => {
1656
+ const values = srs.columns.map(
1657
+ (col) => deserializeValue(obj[col] ?? null)
1658
+ );
1659
+ const row = values;
1660
+ for (let i = 0; i < srs.columns.length; i++) {
1661
+ const col = srs.columns[i];
1662
+ if (col !== void 0) {
1663
+ row[col] = values[i] ?? null;
1664
+ }
1665
+ }
1666
+ Object.defineProperty(row, "length", {
1667
+ value: values.length,
1668
+ enumerable: false
1669
+ });
1670
+ return row;
1671
+ });
1672
+ return {
1673
+ columns: srs.columns,
1674
+ columnTypes: srs.columnTypes ?? [],
1675
+ rows,
1676
+ rowsAffected: srs.rowsAffected,
1677
+ lastInsertRowid: srs.lastInsertRowid != null ? BigInt(srs.lastInsertRowid) : void 0,
1678
+ toJSON: () => ({
1679
+ columns: srs.columns,
1680
+ columnTypes: srs.columnTypes ?? [],
1681
+ rows: srs.rows,
1682
+ rowsAffected: srs.rowsAffected,
1683
+ lastInsertRowid: srs.lastInsertRowid
1684
+ })
1685
+ };
1686
+ }
1687
+ var init_daemon_protocol = __esm({
1688
+ "src/lib/daemon-protocol.ts"() {
1689
+ "use strict";
1690
+ }
1691
+ });
1692
+
1693
+ // src/lib/db-daemon-client.ts
1694
+ var db_daemon_client_exports = {};
1695
+ __export(db_daemon_client_exports, {
1696
+ createDaemonDbClient: () => createDaemonDbClient,
1697
+ initDaemonDbClient: () => initDaemonDbClient
1698
+ });
1699
+ function normalizeStatement2(stmt) {
1700
+ if (typeof stmt === "string") {
1701
+ return { sql: stmt, args: [] };
1702
+ }
1703
+ const sql = stmt.sql;
1704
+ let args = [];
1705
+ if (Array.isArray(stmt.args)) {
1706
+ args = stmt.args.map((v) => serializeValue(v));
1707
+ } else if (stmt.args && typeof stmt.args === "object") {
1708
+ const named = {};
1709
+ for (const [key, val] of Object.entries(stmt.args)) {
1710
+ named[key] = serializeValue(val);
1711
+ }
1712
+ return { sql, args: named };
1713
+ }
1714
+ return { sql, args };
1715
+ }
1716
+ function createDaemonDbClient(fallbackClient) {
1717
+ let _useDaemon = false;
1718
+ const client = {
1719
+ async execute(stmt) {
1720
+ if (!_useDaemon || !isClientConnected()) {
1721
+ return fallbackClient.execute(stmt);
1722
+ }
1723
+ const { sql, args } = normalizeStatement2(stmt);
1724
+ const response = await sendDaemonRequest({
1725
+ type: "db-execute",
1726
+ sql,
1727
+ args
1728
+ });
1729
+ if (response.error) {
1730
+ const errMsg = String(response.error);
1731
+ if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed" || errMsg === "DB not initialized") {
1732
+ process.stderr.write(`[db-daemon] Transport error (${errMsg}), falling back to direct
1733
+ `);
1734
+ return fallbackClient.execute(stmt);
1735
+ }
1736
+ throw new Error(errMsg);
1737
+ }
1738
+ if (response.db) {
1739
+ return deserializeResultSet(response.db);
1740
+ }
1741
+ process.stderr.write("[db-daemon] Unexpected response shape, falling back to direct\n");
1742
+ return fallbackClient.execute(stmt);
1743
+ },
1744
+ async batch(stmts, mode) {
1745
+ if (!_useDaemon || !isClientConnected()) {
1746
+ return fallbackClient.batch(stmts, mode);
1747
+ }
1748
+ const statements = stmts.map(normalizeStatement2);
1749
+ const response = await sendDaemonRequest({
1750
+ type: "db-batch",
1751
+ statements,
1752
+ mode: mode ?? "deferred"
1753
+ });
1754
+ if (response.error) {
1755
+ const errMsg = String(response.error);
1756
+ if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed" || errMsg === "DB not initialized") {
1757
+ process.stderr.write(`[db-daemon] Batch transport error (${errMsg}), falling back to direct
1758
+ `);
1759
+ return fallbackClient.batch(stmts, mode);
1760
+ }
1761
+ throw new Error(errMsg);
1762
+ }
1763
+ const batchResults = response["db-batch"];
1764
+ if (batchResults) {
1765
+ return batchResults.map(deserializeResultSet);
1766
+ }
1767
+ process.stderr.write("[db-daemon] Unexpected batch response shape, falling back to direct\n");
1768
+ return fallbackClient.batch(stmts, mode);
1769
+ },
1770
+ // Transaction support — delegate to fallback (transactions need direct connection)
1771
+ async transaction(mode) {
1772
+ return fallbackClient.transaction(mode);
1773
+ },
1774
+ // executeMultiple — delegate to fallback (used only for schema migrations)
1775
+ async executeMultiple(sql) {
1776
+ return fallbackClient.executeMultiple(sql);
1777
+ },
1778
+ // migrate — delegate to fallback
1779
+ async migrate(stmts) {
1780
+ return fallbackClient.migrate(stmts);
1781
+ },
1782
+ // Sync mode — delegate to fallback
1783
+ sync() {
1784
+ return fallbackClient.sync();
1785
+ },
1786
+ close() {
1787
+ _useDaemon = false;
1788
+ },
1789
+ get closed() {
1790
+ return fallbackClient.closed;
1791
+ },
1792
+ get protocol() {
1793
+ return fallbackClient.protocol;
1794
+ }
1795
+ };
1796
+ return {
1797
+ ...client,
1798
+ /** Enable daemon routing (call after confirming daemon is connected) */
1799
+ _enableDaemon() {
1800
+ _useDaemon = true;
1801
+ },
1802
+ /** Check if daemon routing is active */
1803
+ _isDaemonActive() {
1804
+ return _useDaemon && isClientConnected();
1805
+ }
1806
+ };
1807
+ }
1808
+ async function initDaemonDbClient(fallbackClient) {
1809
+ if (process.env.EXE_IS_DAEMON === "1") return null;
1810
+ const connected = await connectEmbedDaemon();
1811
+ if (!connected) {
1812
+ process.stderr.write("[db-daemon] Daemon unavailable \u2014 using direct SQLite\n");
1813
+ return null;
1814
+ }
1815
+ const client = createDaemonDbClient(fallbackClient);
1816
+ client._enableDaemon();
1817
+ process.stderr.write("[db-daemon] DB routing through daemon (single-writer)\n");
1818
+ return client;
1819
+ }
1820
+ var init_db_daemon_client = __esm({
1821
+ "src/lib/db-daemon-client.ts"() {
1822
+ "use strict";
1823
+ init_exe_daemon_client();
1824
+ init_daemon_protocol();
1825
+ }
1826
+ });
1827
+
1303
1828
  // src/lib/database.ts
1829
+ var database_exports = {};
1830
+ __export(database_exports, {
1831
+ disposeDatabase: () => disposeDatabase,
1832
+ disposeTurso: () => disposeTurso,
1833
+ ensureSchema: () => ensureSchema,
1834
+ getClient: () => getClient,
1835
+ getRawClient: () => getRawClient,
1836
+ initDaemonClient: () => initDaemonClient,
1837
+ initDatabase: () => initDatabase,
1838
+ initTurso: () => initTurso,
1839
+ isInitialized: () => isInitialized
1840
+ });
1304
1841
  import { createClient } from "@libsql/client";
1305
1842
  async function initDatabase(config) {
1306
1843
  if (_walCheckpointTimer) {
@@ -1339,15 +1876,18 @@ async function initDatabase(config) {
1339
1876
  });
1340
1877
  }, 3e4);
1341
1878
  _walCheckpointTimer.unref();
1342
- if (process.env.DATABASE_URL) {
1879
+ if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
1343
1880
  _adapterClient = await createPrismaDbAdapter(_resilientClient);
1344
1881
  }
1345
1882
  }
1883
+ function isInitialized() {
1884
+ return _adapterClient !== null || _client !== null;
1885
+ }
1346
1886
  function getClient() {
1347
1887
  if (!_adapterClient) {
1348
1888
  throw new Error("Database client not initialized. Call initDatabase() first.");
1349
1889
  }
1350
- if (process.env.DATABASE_URL) {
1890
+ if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
1351
1891
  return _adapterClient;
1352
1892
  }
1353
1893
  if (process.env.EXE_IS_DAEMON === "1") {
@@ -1358,6 +1898,22 @@ function getClient() {
1358
1898
  }
1359
1899
  return _resilientClient;
1360
1900
  }
1901
+ async function initDaemonClient() {
1902
+ if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
1903
+ if (process.env.EXE_IS_DAEMON === "1") return;
1904
+ if (process.env.VITEST) return;
1905
+ if (!_resilientClient) return;
1906
+ if (_daemonClient) return;
1907
+ try {
1908
+ const { initDaemonDbClient: initDaemonDbClient2 } = await Promise.resolve().then(() => (init_db_daemon_client(), db_daemon_client_exports));
1909
+ _daemonClient = await initDaemonDbClient2(_resilientClient);
1910
+ } catch (err) {
1911
+ process.stderr.write(
1912
+ `[database] Daemon client init failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
1913
+ `
1914
+ );
1915
+ }
1916
+ }
1361
1917
  function getRawClient() {
1362
1918
  if (!_client) {
1363
1919
  throw new Error("Database client not initialized. Call initDatabase() first.");
@@ -1496,6 +2052,13 @@ async function ensureSchema() {
1496
2052
  });
1497
2053
  } catch {
1498
2054
  }
2055
+ try {
2056
+ await client.execute({
2057
+ sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
2058
+ args: []
2059
+ });
2060
+ } catch {
2061
+ }
1499
2062
  try {
1500
2063
  await client.execute({
1501
2064
  sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
@@ -2366,6 +2929,7 @@ var init_database = __esm({
2366
2929
  init_db_retry();
2367
2930
  init_employees();
2368
2931
  init_database_adapter();
2932
+ init_memory();
2369
2933
  _client = null;
2370
2934
  _resilientClient = null;
2371
2935
  _walCheckpointTimer = null;
@@ -2378,14 +2942,14 @@ var init_database = __esm({
2378
2942
 
2379
2943
  // src/lib/keychain.ts
2380
2944
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2381
- import { existsSync as existsSync7 } from "fs";
2382
- import path8 from "path";
2383
- import os5 from "os";
2945
+ import { existsSync as existsSync9 } from "fs";
2946
+ import path10 from "path";
2947
+ import os6 from "os";
2384
2948
  function getKeyDir() {
2385
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path8.join(os5.homedir(), ".exe-os");
2949
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path10.join(os6.homedir(), ".exe-os");
2386
2950
  }
2387
2951
  function getKeyPath() {
2388
- return path8.join(getKeyDir(), "master.key");
2952
+ return path10.join(getKeyDir(), "master.key");
2389
2953
  }
2390
2954
  async function tryKeytar() {
2391
2955
  try {
@@ -2406,9 +2970,9 @@ async function getMasterKey() {
2406
2970
  }
2407
2971
  }
2408
2972
  const keyPath = getKeyPath();
2409
- if (!existsSync7(keyPath)) {
2973
+ if (!existsSync9(keyPath)) {
2410
2974
  process.stderr.write(
2411
- `[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2975
+ `[keychain] Key not found at ${keyPath} (HOME=${os6.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2412
2976
  `
2413
2977
  );
2414
2978
  return null;
@@ -2502,12 +3066,12 @@ __export(shard_manager_exports, {
2502
3066
  listShards: () => listShards,
2503
3067
  shardExists: () => shardExists
2504
3068
  });
2505
- import path9 from "path";
2506
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
3069
+ import path11 from "path";
3070
+ import { existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
2507
3071
  import { createClient as createClient2 } from "@libsql/client";
2508
3072
  function initShardManager(encryptionKey) {
2509
3073
  _encryptionKey = encryptionKey;
2510
- if (!existsSync8(SHARDS_DIR)) {
3074
+ if (!existsSync10(SHARDS_DIR)) {
2511
3075
  mkdirSync5(SHARDS_DIR, { recursive: true });
2512
3076
  }
2513
3077
  _shardingEnabled = true;
@@ -2537,7 +3101,7 @@ function getShardClient(projectName) {
2537
3101
  while (_shards.size >= MAX_OPEN_SHARDS) {
2538
3102
  evictLRU();
2539
3103
  }
2540
- const dbPath = path9.join(SHARDS_DIR, `${safeName}.db`);
3104
+ const dbPath = path11.join(SHARDS_DIR, `${safeName}.db`);
2541
3105
  const client = createClient2({
2542
3106
  url: `file:${dbPath}`,
2543
3107
  encryptionKey: _encryptionKey
@@ -2548,10 +3112,10 @@ function getShardClient(projectName) {
2548
3112
  }
2549
3113
  function shardExists(projectName) {
2550
3114
  const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2551
- return existsSync8(path9.join(SHARDS_DIR, `${safeName}.db`));
3115
+ return existsSync10(path11.join(SHARDS_DIR, `${safeName}.db`));
2552
3116
  }
2553
3117
  function listShards() {
2554
- if (!existsSync8(SHARDS_DIR)) return [];
3118
+ if (!existsSync10(SHARDS_DIR)) return [];
2555
3119
  return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
2556
3120
  }
2557
3121
  async function ensureShardSchema(client) {
@@ -2798,7 +3362,7 @@ var init_shard_manager = __esm({
2798
3362
  "src/lib/shard-manager.ts"() {
2799
3363
  "use strict";
2800
3364
  init_config();
2801
- SHARDS_DIR = path9.join(EXE_AI_DIR, "shards");
3365
+ SHARDS_DIR = path11.join(EXE_AI_DIR, "shards");
2802
3366
  SHARD_IDLE_MS = 5 * 60 * 1e3;
2803
3367
  MAX_OPEN_SHARDS = 10;
2804
3368
  EVICTION_INTERVAL_MS = 60 * 1e3;
@@ -2918,6 +3482,68 @@ var init_platform_procedures = __esm({
2918
3482
  domain: "architecture",
2919
3483
  priority: "p0",
2920
3484
  content: "Tasks live in the DB. Intercom (tmux send-keys) is fire-and-forget \u2014 it may fail, get garbled, or arrive mid-work. Never rely on intercom for task delivery. The UserPromptSubmit hook checks the DB for new tasks on every prompt. Your operating procedures step 7 says check for next work. The daemon nudges idle agents as a speedup. If you have no tasks, you found them all."
3485
+ },
3486
+ // --- MCP is the ONLY data interface ---
3487
+ {
3488
+ title: "MCP disconnect \u2014 ask the user, never work around it",
3489
+ domain: "workflow",
3490
+ priority: "p0",
3491
+ content: "If MCP tools are unavailable, disconnected, or returning connection errors: STOP. Tell the user clearly: 'MCP server is disconnected. Please run /mcp to reconnect.' Do NOT attempt workarounds \u2014 no raw Node imports, no direct DB access, no CLI hacks, no daemon socket calls. MCP is the ONLY data interface. Working around it wastes time, hits bundling issues, and bypasses the contract boundary. Ask once, wait, proceed when reconnected."
3492
+ },
3493
+ // --- MCP Tool Catalog (Layer 0 — every agent knows what tools exist) ---
3494
+ {
3495
+ title: "MCP tools \u2014 memory and search",
3496
+ domain: "tool-use",
3497
+ priority: "p1",
3498
+ content: "recall_my_memory: search your own memories (semantic + FTS). ask_team_memory: search a colleague's memories by agent name. store_memory: persist a memory (decisions, summaries, context). commit_memory: high-importance memory that survives consolidation. search_everything: unified search across memories, tasks, entities, conversations. get_session_context: temporal window of memories around a timestamp. consolidate_memories: merge duplicate/related memories into insights. get_memory_cardinality: count memories per agent (health check)."
3499
+ },
3500
+ {
3501
+ title: "MCP tools \u2014 task orchestration",
3502
+ domain: "tool-use",
3503
+ priority: "p1",
3504
+ content: "create_task: dispatch work to an employee (auto-spawns session). The ONLY dispatch path. list_tasks: query tasks by status, assignee, project. get_task: fetch full task details by ID. update_task: change status (in_progress, done, blocked, cancelled) + add result summary. close_task: finalize a reviewed task (COO only). checkpoint_task: save progress state for crash recovery. resume_employee: re-spawn an employee session for an existing task."
3505
+ },
3506
+ {
3507
+ title: "MCP tools \u2014 knowledge graph (GraphRAG)",
3508
+ domain: "tool-use",
3509
+ priority: "p1",
3510
+ content: "query_relationships: find connections between entities in the knowledge graph. get_entity_neighbors: explore an entity's direct connections. get_hot_entities: find most-referenced entities (trending topics). get_graph_stats: graph health \u2014 entity/relationship counts, density. export_graph: export graph data for visualization. merge_entities: deduplicate entities (alias resolution). find_similar_trajectories: match tool-call patterns to past task solutions."
3511
+ },
3512
+ {
3513
+ title: "MCP tools \u2014 identity, behavior, and decisions",
3514
+ domain: "tool-use",
3515
+ priority: "p1",
3516
+ content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query."
3517
+ },
3518
+ {
3519
+ title: "MCP tools \u2014 communication and messaging",
3520
+ domain: "tool-use",
3521
+ priority: "p1",
3522
+ content: "send_message: send supplementary context to another agent (NOT for actionable work \u2014 use create_task). acknowledge_messages: mark messages as read. send_whatsapp: send WhatsApp message via gateway (customer-facing alerts). query_conversations: search ingested conversations across all channels (WhatsApp, email, etc.)."
3523
+ },
3524
+ {
3525
+ title: "MCP tools \u2014 wiki, documents, and content",
3526
+ domain: "tool-use",
3527
+ priority: "p1",
3528
+ content: "create_wiki_page: create a wiki page in exe-wiki. list_wiki_pages: browse wiki pages. get_wiki_page: read a wiki page. update_wiki_page: edit a wiki page. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
3529
+ },
3530
+ {
3531
+ title: "MCP tools \u2014 system, operations, and admin",
3532
+ domain: "tool-use",
3533
+ priority: "p1",
3534
+ content: "get_agent_spend: token usage per agent/session (cost tracking). list_agent_sessions: view agent session history. get_session_kills: audit log of killed sessions. get_daemon_health: check exed daemon status. get_auto_wake_status: daemon auto-wake configuration. get_worker_gate: check worker deployment gates. run_memory_audit: health check \u2014 duplicates, null vectors, orphaned rows. run_consolidation: trigger sleep-time memory consolidation. cloud_sync: force a cloud sync cycle. backup_vps: trigger VPS backup."
3535
+ },
3536
+ {
3537
+ title: "MCP tools \u2014 config, licensing, and team",
3538
+ domain: "tool-use",
3539
+ priority: "p1",
3540
+ content: "set_agent_config: view/change per-agent runtime and model settings. list_employees: view the employee roster. add_person: add a person to the CRM contacts roster. list_people: browse CRM contacts. get_person: fetch contact details. get_license_status: check license validity. create_license: generate a new license key (admin). list_licenses: view all issued licenses. activate_license: activate a license on a device."
3541
+ },
3542
+ {
3543
+ title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
3544
+ domain: "tool-use",
3545
+ priority: "p1",
3546
+ content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage Layer 0 procedures (actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
2921
3547
  }
2922
3548
  ];
2923
3549
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -2934,7 +3560,7 @@ __export(global_procedures_exports, {
2934
3560
  loadGlobalProcedures: () => loadGlobalProcedures,
2935
3561
  storeGlobalProcedure: () => storeGlobalProcedure
2936
3562
  });
2937
- import { randomUUID } from "crypto";
3563
+ import { randomUUID as randomUUID2 } from "crypto";
2938
3564
  async function loadGlobalProcedures() {
2939
3565
  const client = getClient();
2940
3566
  const result = await client.execute({
@@ -2963,7 +3589,7 @@ ${sections.join("\n\n")}
2963
3589
  `;
2964
3590
  }
2965
3591
  async function storeGlobalProcedure(input2) {
2966
- const id = randomUUID();
3592
+ const id = randomUUID2();
2967
3593
  const now = (/* @__PURE__ */ new Date()).toISOString();
2968
3594
  const client = getClient();
2969
3595
  await client.execute({
@@ -3067,6 +3693,11 @@ async function initStore(options) {
3067
3693
  encryptionKey: hexKey
3068
3694
  });
3069
3695
  await retryOnBusy2(() => ensureSchema(), "ensureSchema");
3696
+ try {
3697
+ const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
3698
+ await initDaemonClient2();
3699
+ } catch {
3700
+ }
3070
3701
  if (!options?.lightweight) {
3071
3702
  try {
3072
3703
  const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
@@ -3588,7 +4219,7 @@ __export(git_staleness_exports, {
3588
4219
  recordFileRead: () => recordFileRead
3589
4220
  });
3590
4221
  import { execSync as execSync4 } from "child_process";
3591
- import path10 from "path";
4222
+ import path12 from "path";
3592
4223
  function getHeadCommit(cwd) {
3593
4224
  try {
3594
4225
  return execSync4("git rev-parse --short HEAD", {
@@ -3601,9 +4232,9 @@ function getHeadCommit(cwd) {
3601
4232
  }
3602
4233
  }
3603
4234
  function normalizeTrackedPath(cwd, filePath) {
3604
- const resolved = path10.resolve(cwd, filePath);
3605
- const relative = path10.relative(cwd, resolved);
3606
- if (!relative || relative.startsWith("..") || path10.isAbsolute(relative)) {
4235
+ const resolved = path12.resolve(cwd, filePath);
4236
+ const relative = path12.relative(cwd, resolved);
4237
+ if (!relative || relative.startsWith("..") || path12.isAbsolute(relative)) {
3607
4238
  return null;
3608
4239
  }
3609
4240
  return relative;
@@ -3722,8 +4353,8 @@ function findContainingChunk(filePath, snippet) {
3722
4353
  try {
3723
4354
  const ext = filePath.split(".").pop()?.toLowerCase();
3724
4355
  if (ext !== "ts" && ext !== "tsx" && ext !== "js" && ext !== "jsx") return "";
3725
- const { readFileSync: readFileSync8 } = __require("fs");
3726
- const source = readFileSync8(filePath, "utf8");
4356
+ const { readFileSync: readFileSync9 } = __require("fs");
4357
+ const source = readFileSync9(filePath, "utf8");
3727
4358
  const lines = source.split("\n");
3728
4359
  const lowerSnippet = snippet.toLowerCase().slice(0, 80);
3729
4360
  let matchLine = -1;
@@ -3789,9 +4420,9 @@ function extractBash(input2, response) {
3789
4420
  }
3790
4421
  function extractGrep(input2, response) {
3791
4422
  const pattern = String(input2.pattern ?? "");
3792
- const path14 = input2.path ? String(input2.path) : "";
4423
+ const path15 = input2.path ? String(input2.path) : "";
3793
4424
  const output = String(response.text ?? response.content ?? JSON.stringify(response).slice(0, MAX_OUTPUT));
3794
- return `Searched for "${pattern}"${path14 ? ` in ${path14}` : ""}
4425
+ return `Searched for "${pattern}"${path15 ? ` in ${path15}` : ""}
3795
4426
  ${output.slice(0, MAX_OUTPUT)}`;
3796
4427
  }
3797
4428
  function extractGlob(input2, response) {
@@ -3892,7 +4523,7 @@ __export(project_name_exports, {
3892
4523
  getProjectName: () => getProjectName
3893
4524
  });
3894
4525
  import { execSync as execSync5 } from "child_process";
3895
- import path11 from "path";
4526
+ import path13 from "path";
3896
4527
  function getProjectName(cwd) {
3897
4528
  const dir = cwd ?? process.cwd();
3898
4529
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -3905,7 +4536,7 @@ function getProjectName(cwd) {
3905
4536
  timeout: 2e3,
3906
4537
  stdio: ["pipe", "pipe", "pipe"]
3907
4538
  }).trim();
3908
- repoRoot = path11.dirname(gitCommonDir);
4539
+ repoRoot = path13.dirname(gitCommonDir);
3909
4540
  } catch {
3910
4541
  repoRoot = execSync5("git rev-parse --show-toplevel", {
3911
4542
  cwd: dir,
@@ -3914,11 +4545,11 @@ function getProjectName(cwd) {
3914
4545
  stdio: ["pipe", "pipe", "pipe"]
3915
4546
  }).trim();
3916
4547
  }
3917
- _cached2 = path11.basename(repoRoot);
4548
+ _cached2 = path13.basename(repoRoot);
3918
4549
  _cachedCwd = dir;
3919
4550
  return _cached2;
3920
4551
  } catch {
3921
- _cached2 = path11.basename(dir);
4552
+ _cached2 = path13.basename(dir);
3922
4553
  _cachedCwd = dir;
3923
4554
  return _cached2;
3924
4555
  }
@@ -3936,56 +4567,13 @@ var init_project_name = __esm({
3936
4567
  }
3937
4568
  });
3938
4569
 
3939
- // src/lib/daemon-auth.ts
3940
- var daemon_auth_exports = {};
3941
- __export(daemon_auth_exports, {
3942
- DAEMON_TOKEN_PATH: () => DAEMON_TOKEN_PATH,
3943
- ensureDaemonToken: () => ensureDaemonToken,
3944
- readDaemonToken: () => readDaemonToken
3945
- });
3946
- import crypto2 from "crypto";
3947
- import path12 from "path";
3948
- import { existsSync as existsSync9, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
3949
- function normalizeToken(token) {
3950
- if (!token) return null;
3951
- const trimmed = token.trim();
3952
- return trimmed.length > 0 ? trimmed : null;
3953
- }
3954
- function readDaemonToken() {
3955
- try {
3956
- if (!existsSync9(DAEMON_TOKEN_PATH)) return null;
3957
- return normalizeToken(readFileSync6(DAEMON_TOKEN_PATH, "utf8"));
3958
- } catch {
3959
- return null;
3960
- }
3961
- }
3962
- function ensureDaemonToken(seed) {
3963
- const existing = readDaemonToken();
3964
- if (existing) return existing;
3965
- const token = normalizeToken(seed) ?? crypto2.randomBytes(32).toString("hex");
3966
- ensurePrivateDirSync(EXE_AI_DIR);
3967
- writeFileSync6(DAEMON_TOKEN_PATH, `${token}
3968
- `, "utf8");
3969
- enforcePrivateFileSync(DAEMON_TOKEN_PATH);
3970
- return token;
3971
- }
3972
- var DAEMON_TOKEN_PATH;
3973
- var init_daemon_auth = __esm({
3974
- "src/lib/daemon-auth.ts"() {
3975
- "use strict";
3976
- init_config();
3977
- init_secure_files();
3978
- DAEMON_TOKEN_PATH = path12.join(EXE_AI_DIR, "exed.token");
3979
- }
3980
- });
3981
-
3982
4570
  // src/adapters/claude/hooks/ingest.ts
3983
4571
  init_config();
3984
4572
  init_config();
3985
- import { spawn } from "child_process";
3986
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, existsSync as existsSync10, openSync, closeSync } from "fs";
3987
- import path13 from "path";
3988
- import { fileURLToPath } from "url";
4573
+ import { spawn as spawn2 } from "child_process";
4574
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, existsSync as existsSync11, openSync as openSync2, closeSync as closeSync2 } from "fs";
4575
+ import path14 from "path";
4576
+ import { fileURLToPath as fileURLToPath2 } from "url";
3989
4577
 
3990
4578
  // src/lib/active-agent.ts
3991
4579
  init_config();
@@ -4379,10 +4967,10 @@ if (!loadConfigSync().autoIngestion) {
4379
4967
  if (!process.env.EXE_OS_DIR) {
4380
4968
  process.env.EXE_OS_DIR = EXE_AI_DIR;
4381
4969
  }
4382
- var WORKER_LOG_PATH = path13.join(EXE_AI_DIR, "workers.log");
4970
+ var WORKER_LOG_PATH = path14.join(EXE_AI_DIR, "workers.log");
4383
4971
  function openWorkerLog() {
4384
4972
  try {
4385
- return openSync(WORKER_LOG_PATH, "a");
4973
+ return openSync2(WORKER_LOG_PATH, "a");
4386
4974
  } catch {
4387
4975
  return "ignore";
4388
4976
  }
@@ -4391,13 +4979,13 @@ var ALLOWED_TOOL_RE = /^(Bash|Edit|Write|Read|Glob|Grep|Agent|apply_patch|mcp__.
4391
4979
  var WRITE_TOOL_RE = /^(Bash|Edit|Write|apply_patch)$/;
4392
4980
  var SUMMARY_INTERVAL = 25;
4393
4981
  var MIN_WRITES_FOR_SUMMARY = 3;
4394
- var COUNTER_DIR = path13.join(EXE_AI_DIR, "session-cache");
4982
+ var COUNTER_DIR = path14.join(EXE_AI_DIR, "session-cache");
4395
4983
  function getCounterPath(sessionId) {
4396
- return path13.join(COUNTER_DIR, `counter-${sessionId}.json`);
4984
+ return path14.join(COUNTER_DIR, `counter-${sessionId}.json`);
4397
4985
  }
4398
4986
  function loadCounter(sessionId) {
4399
4987
  try {
4400
- const raw = readFileSync7(getCounterPath(sessionId), "utf8");
4988
+ const raw = readFileSync8(getCounterPath(sessionId), "utf8");
4401
4989
  return JSON.parse(raw);
4402
4990
  } catch {
4403
4991
  return { total: 0, writes: 0, pipelineWrites: 0, lastSummaryAt: 0, pipelineDetected: false };
@@ -4422,8 +5010,8 @@ process.stdin.on("end", async () => {
4422
5010
  try {
4423
5011
  if (process.env.EXE_DEBUG_HOOKS) {
4424
5012
  try {
4425
- const debugPath = path13.join(EXE_AI_DIR, "logs", "hook-stdin-ingest.log");
4426
- mkdirSync6(path13.dirname(debugPath), { recursive: true });
5013
+ const debugPath = path14.join(EXE_AI_DIR, "logs", "hook-stdin-ingest.log");
5014
+ mkdirSync6(path14.dirname(debugPath), { recursive: true });
4427
5015
  const ts = (/* @__PURE__ */ new Date()).toISOString();
4428
5016
  const snippet = input.length > 2e3 ? input.slice(0, 2e3) + "...[truncated]" : input;
4429
5017
  writeFileSync7(debugPath, `[${ts}] ${snippet}
@@ -4511,14 +5099,14 @@ Your output files must start with: exe/output/${agent.agentId}-`
4511
5099
  const classification = classifyError(errorText);
4512
5100
  if (classification === "system" && data.session_id) {
4513
5101
  const fp = errorFingerprint(data.tool_name, errorText);
4514
- const fpFilePath = path13.join(COUNTER_DIR, `bug-fingerprints-${data.session_id}.json`);
5102
+ const fpFilePath = path14.join(COUNTER_DIR, `bug-fingerprints-${data.session_id}.json`);
4515
5103
  let fpData = {
4516
5104
  seen: {},
4517
5105
  taskCount: 0,
4518
5106
  lastTaskAt: ""
4519
5107
  };
4520
5108
  try {
4521
- fpData = JSON.parse(readFileSync7(fpFilePath, "utf8"));
5109
+ fpData = JSON.parse(readFileSync8(fpFilePath, "utf8"));
4522
5110
  } catch {
4523
5111
  }
4524
5112
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -4536,15 +5124,15 @@ Your output files must start with: exe/output/${agent.agentId}-`
4536
5124
  fpData.seen[fp] = { count: 1, firstAt: now, lastAt: now };
4537
5125
  fpData.taskCount++;
4538
5126
  fpData.lastTaskAt = now;
4539
- const bugWorkerPath = path13.resolve(
4540
- path13.dirname(fileURLToPath(import.meta.url)),
5127
+ const bugWorkerPath = path14.resolve(
5128
+ path14.dirname(fileURLToPath2(import.meta.url)),
4541
5129
  "bug-report-worker.js"
4542
5130
  );
4543
- if (existsSync10(bugWorkerPath) && tryAcquireWorkerSlot()) {
5131
+ if (existsSync11(bugWorkerPath) && tryAcquireWorkerSlot()) {
4544
5132
  const stderrFd2 = openWorkerLog();
4545
- const projectName = process.cwd().split(path13.sep).pop() ?? "unknown";
5133
+ const projectName = process.cwd().split(path14.sep).pop() ?? "unknown";
4546
5134
  const bugToolInput = data.tool_input ?? {};
4547
- const bugWorker = spawn(process.execPath, [bugWorkerPath], {
5135
+ const bugWorker = spawn2(process.execPath, [bugWorkerPath], {
4548
5136
  detached: true,
4549
5137
  stdio: ["ignore", "ignore", stderrFd2],
4550
5138
  env: {
@@ -4561,7 +5149,7 @@ Your output files must start with: exe/output/${agent.agentId}-`
4561
5149
  if (bugWorker.pid) registerWorkerPid(bugWorker.pid);
4562
5150
  bugWorker.unref();
4563
5151
  if (typeof stderrFd2 === "number") try {
4564
- closeSync(stderrFd2);
5152
+ closeSync2(stderrFd2);
4565
5153
  } catch {
4566
5154
  }
4567
5155
  } else {
@@ -4588,13 +5176,13 @@ Your output files must start with: exe/output/${agent.agentId}-`
4588
5176
  }
4589
5177
  const callsSinceLastSummary = counter.total - counter.lastSummaryAt;
4590
5178
  if (callsSinceLastSummary >= SUMMARY_INTERVAL && counter.writes >= MIN_WRITES_FOR_SUMMARY) {
4591
- const summaryWorkerPath = path13.resolve(
4592
- path13.dirname(fileURLToPath(import.meta.url)),
5179
+ const summaryWorkerPath = path14.resolve(
5180
+ path14.dirname(fileURLToPath2(import.meta.url)),
4593
5181
  "summary-worker.js"
4594
5182
  );
4595
- if (existsSync10(summaryWorkerPath) && tryAcquireWorkerSlot()) {
5183
+ if (existsSync11(summaryWorkerPath) && tryAcquireWorkerSlot()) {
4596
5184
  const stderrFd2 = openWorkerLog();
4597
- const summaryWorker = spawn(process.execPath, [summaryWorkerPath], {
5185
+ const summaryWorker = spawn2(process.execPath, [summaryWorkerPath], {
4598
5186
  detached: true,
4599
5187
  stdio: ["ignore", "ignore", stderrFd2],
4600
5188
  env: {
@@ -4609,7 +5197,7 @@ Your output files must start with: exe/output/${agent.agentId}-`
4609
5197
  if (summaryWorker.pid) registerWorkerPid(summaryWorker.pid);
4610
5198
  summaryWorker.unref();
4611
5199
  if (typeof stderrFd2 === "number") try {
4612
- closeSync(stderrFd2);
5200
+ closeSync2(stderrFd2);
4613
5201
  } catch {
4614
5202
  }
4615
5203
  } else {
@@ -4638,14 +5226,14 @@ WARNING: You are writing code without running the build pipeline. If this task a
4638
5226
  const bashOutput = typeof data.tool_response === "string" ? data.tool_response : JSON.stringify(data.tool_response ?? "");
4639
5227
  const commitMatch = bashOutput.match(/\[(\S+)\s+([a-f0-9]{7,40})\]\s+(.+)/);
4640
5228
  if (commitMatch) {
4641
- const commitWorkerPath = path13.resolve(
4642
- path13.dirname(fileURLToPath(import.meta.url)),
5229
+ const commitWorkerPath = path14.resolve(
5230
+ path14.dirname(fileURLToPath2(import.meta.url)),
4643
5231
  "commit-complete.js"
4644
5232
  );
4645
- if (existsSync10(commitWorkerPath) && tryAcquireWorkerSlot()) {
5233
+ if (existsSync11(commitWorkerPath) && tryAcquireWorkerSlot()) {
4646
5234
  const stderrFd2 = openWorkerLog();
4647
- const projectName = process.cwd().split(path13.sep).pop() ?? "unknown";
4648
- const commitWorker = spawn(process.execPath, [commitWorkerPath], {
5235
+ const projectName = process.cwd().split(path14.sep).pop() ?? "unknown";
5236
+ const commitWorker = spawn2(process.execPath, [commitWorkerPath], {
4649
5237
  detached: true,
4650
5238
  stdio: ["ignore", "ignore", stderrFd2],
4651
5239
  env: {
@@ -4659,7 +5247,7 @@ WARNING: You are writing code without running the build pipeline. If this task a
4659
5247
  if (commitWorker.pid) registerWorkerPid(commitWorker.pid);
4660
5248
  commitWorker.unref();
4661
5249
  if (typeof stderrFd2 === "number") try {
4662
- closeSync(stderrFd2);
5250
+ closeSync2(stderrFd2);
4663
5251
  } catch {
4664
5252
  }
4665
5253
  }
@@ -4670,8 +5258,8 @@ WARNING: You are writing code without running the build pipeline. If this task a
4670
5258
  }
4671
5259
  let sentViaDaemon = false;
4672
5260
  try {
4673
- const socketPath = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path13.join(EXE_AI_DIR, "exed.sock");
4674
- if (existsSync10(socketPath)) {
5261
+ const socketPath = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path14.join(EXE_AI_DIR, "exed.sock");
5262
+ if (existsSync11(socketPath)) {
4675
5263
  const { extractSemanticText: extractSemanticText2 } = await Promise.resolve().then(() => (init_content_extractor(), content_extractor_exports));
4676
5264
  const { getProjectName: getProjectName2 } = await Promise.resolve().then(() => (init_project_name(), project_name_exports));
4677
5265
  const { canCoordinate: canCoordinate2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
@@ -4680,9 +5268,9 @@ WARNING: You are writing code without running the build pipeline. If this task a
4680
5268
  if (rawText.length >= 50) {
4681
5269
  let taskId = null;
4682
5270
  try {
4683
- const cachePath = path13.join(EXE_AI_DIR, "session-cache", `current-task-${agent.agentId}.json`);
4684
- if (existsSync10(cachePath)) {
4685
- const cached = JSON.parse(readFileSync7(cachePath, "utf8"));
5271
+ const cachePath = path14.join(EXE_AI_DIR, "session-cache", `current-task-${agent.agentId}.json`);
5272
+ if (existsSync11(cachePath)) {
5273
+ const cached = JSON.parse(readFileSync8(cachePath, "utf8"));
4686
5274
  taskId = cached.taskId ?? null;
4687
5275
  }
4688
5276
  } catch {
@@ -4710,8 +5298,8 @@ WARNING: You are writing code without running the build pipeline. If this task a
4710
5298
  draft: isDraft,
4711
5299
  trajectory: { input: toolInputStr, tool: data.tool_name, output: toolOutputStr, result_type: hasError ? "error" : "success" }
4712
5300
  }) + "\n";
4713
- const net = await import("net");
4714
- const sock = net.connect(socketPath);
5301
+ const net2 = await import("net");
5302
+ const sock = net2.connect(socketPath);
4715
5303
  sock.on("error", () => {
4716
5304
  });
4717
5305
  sock.write(payload, () => {
@@ -4728,8 +5316,8 @@ WARNING: You are writing code without running the build pipeline. If this task a
4728
5316
  setTimeout(() => process.exit(0), 10);
4729
5317
  return;
4730
5318
  }
4731
- const workerPath = path13.resolve(
4732
- path13.dirname(fileURLToPath(import.meta.url)),
5319
+ const workerPath = path14.resolve(
5320
+ path14.dirname(fileURLToPath2(import.meta.url)),
4733
5321
  "ingest-worker.js"
4734
5322
  );
4735
5323
  if (!tryAcquireWorkerSlot()) {
@@ -4737,7 +5325,7 @@ WARNING: You are writing code without running the build pipeline. If this task a
4737
5325
  process.exit(0);
4738
5326
  }
4739
5327
  const stderrFd = openWorkerLog();
4740
- const worker = spawn(process.execPath, [workerPath], {
5328
+ const worker = spawn2(process.execPath, [workerPath], {
4741
5329
  detached: true,
4742
5330
  stdio: ["pipe", "ignore", stderrFd],
4743
5331
  env: { ...process.env, AGENT_ID: agent.agentId, AGENT_ROLE: agent.agentRole }
@@ -4747,7 +5335,7 @@ WARNING: You are writing code without running the build pipeline. If this task a
4747
5335
  worker.stdin.end();
4748
5336
  worker.unref();
4749
5337
  if (typeof stderrFd === "number") try {
4750
- closeSync(stderrFd);
5338
+ closeSync2(stderrFd);
4751
5339
  } catch {
4752
5340
  }
4753
5341
  } catch {