@askexenow/exe-os 0.8.37 → 0.8.39

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 (93) hide show
  1. package/README.md +17 -8
  2. package/dist/bin/backfill-conversations.js +112 -70
  3. package/dist/bin/backfill-responses.js +53 -18
  4. package/dist/bin/backfill-vectors.js +43 -16
  5. package/dist/bin/cleanup-stale-review-tasks.js +38 -16
  6. package/dist/bin/cli.js +790 -468
  7. package/dist/bin/exe-agent.js +19 -4
  8. package/dist/bin/exe-assign.js +46 -13
  9. package/dist/bin/exe-boot.js +288 -129
  10. package/dist/bin/exe-call.js +20 -10
  11. package/dist/bin/exe-cloud.js +135 -30
  12. package/dist/bin/exe-dispatch.js +1 -1
  13. package/dist/bin/exe-doctor.js +38 -16
  14. package/dist/bin/exe-export-behaviors.js +43 -21
  15. package/dist/bin/exe-forget.js +39 -17
  16. package/dist/bin/exe-gateway.js +159 -50
  17. package/dist/bin/exe-heartbeat.js +53 -31
  18. package/dist/bin/exe-kill.js +40 -18
  19. package/dist/bin/exe-launch-agent.js +109 -36
  20. package/dist/bin/exe-link.js +196 -87
  21. package/dist/bin/exe-new-employee.js +56 -17
  22. package/dist/bin/exe-pending-messages.js +47 -25
  23. package/dist/bin/exe-pending-notifications.js +38 -16
  24. package/dist/bin/exe-pending-reviews.js +51 -29
  25. package/dist/bin/exe-rename.js +21 -7
  26. package/dist/bin/exe-review.js +41 -13
  27. package/dist/bin/exe-search.js +57 -21
  28. package/dist/bin/exe-session-cleanup.js +67 -31
  29. package/dist/bin/exe-settings.js +63 -2
  30. package/dist/bin/exe-status.js +35 -13
  31. package/dist/bin/exe-team.js +35 -13
  32. package/dist/bin/git-sweep.js +45 -17
  33. package/dist/bin/graph-backfill.js +38 -16
  34. package/dist/bin/graph-export.js +38 -16
  35. package/dist/bin/install.js +10 -1
  36. package/dist/bin/scan-tasks.js +47 -19
  37. package/dist/bin/setup.js +444 -259
  38. package/dist/bin/shard-migrate.js +38 -16
  39. package/dist/bin/wiki-sync.js +40 -17
  40. package/dist/gateway/index.js +113 -48
  41. package/dist/hooks/bug-report-worker.js +66 -39
  42. package/dist/hooks/commit-complete.js +45 -17
  43. package/dist/hooks/error-recall.js +60 -20
  44. package/dist/hooks/exe-heartbeat-hook.js +3 -2
  45. package/dist/hooks/ingest-worker.js +174 -45
  46. package/dist/hooks/ingest.js +74 -28
  47. package/dist/hooks/instructions-loaded.js +46 -17
  48. package/dist/hooks/notification.js +44 -15
  49. package/dist/hooks/post-compact.js +44 -15
  50. package/dist/hooks/pre-compact.js +42 -14
  51. package/dist/hooks/pre-tool-use.js +59 -22
  52. package/dist/hooks/prompt-ingest-worker.js +75 -14
  53. package/dist/hooks/prompt-submit.js +75 -32
  54. package/dist/hooks/response-ingest-worker.js +76 -15
  55. package/dist/hooks/session-end.js +54 -22
  56. package/dist/hooks/session-start.js +57 -20
  57. package/dist/hooks/stop.js +44 -15
  58. package/dist/hooks/subagent-stop.js +44 -15
  59. package/dist/hooks/summary-worker.js +339 -106
  60. package/dist/index.js +94 -23
  61. package/dist/lib/cloud-sync.js +191 -80
  62. package/dist/lib/config.js +4 -1
  63. package/dist/lib/consolidation.js +5 -4
  64. package/dist/lib/database.js +1 -0
  65. package/dist/lib/device-registry.js +2 -1
  66. package/dist/lib/embedder.js +9 -1
  67. package/dist/lib/employee-templates.js +5 -0
  68. package/dist/lib/employees.js +11 -6
  69. package/dist/lib/exe-daemon-client.js +6 -1
  70. package/dist/lib/exe-daemon.js +95 -36
  71. package/dist/lib/hybrid-search.js +57 -21
  72. package/dist/lib/identity-templates.js +16 -7
  73. package/dist/lib/identity.js +1 -1
  74. package/dist/lib/keychain.js +2 -1
  75. package/dist/lib/license.js +56 -6
  76. package/dist/lib/messaging.js +1 -1
  77. package/dist/lib/reminders.js +2 -2
  78. package/dist/lib/schedules.js +38 -16
  79. package/dist/lib/skill-learning.js +1 -1
  80. package/dist/lib/store.js +44 -16
  81. package/dist/lib/tasks.js +1 -1
  82. package/dist/lib/tmux-routing.js +1 -1
  83. package/dist/mcp/server.js +280 -155
  84. package/dist/mcp/tools/complete-reminder.js +1 -1
  85. package/dist/mcp/tools/create-task.js +14 -6
  86. package/dist/mcp/tools/deactivate-behavior.js +2 -2
  87. package/dist/mcp/tools/list-reminders.js +1 -1
  88. package/dist/mcp/tools/list-tasks.js +36 -28
  89. package/dist/mcp/tools/send-message.js +1 -1
  90. package/dist/mcp/tools/update-task.js +1 -1
  91. package/dist/runtime/index.js +42 -8
  92. package/dist/tui/App.js +220 -99
  93. package/package.json +5 -3
@@ -1,12 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
- }) : x)(function(x) {
7
- if (typeof require !== "undefined") return require.apply(this, arguments);
8
- throw Error('Dynamic require of "' + x + '" is not supported');
9
- });
10
4
  var __esm = (fn, res) => function __init() {
11
5
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
6
  };
@@ -16,15 +10,15 @@ var __export = (target, all) => {
16
10
  };
17
11
 
18
12
  // src/lib/config.ts
19
- import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
13
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, chmod as chmod2 } from "fs/promises";
20
14
  import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
21
15
  import path2 from "path";
22
- import os from "os";
16
+ import os2 from "os";
23
17
  function resolveDataDir() {
24
18
  if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
25
19
  if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
26
- const newDir = path2.join(os.homedir(), ".exe-os");
27
- const legacyDir = path2.join(os.homedir(), ".exe-mem");
20
+ const newDir = path2.join(os2.homedir(), ".exe-os");
21
+ const legacyDir = path2.join(os2.homedir(), ".exe-mem");
28
22
  if (!existsSync2(newDir) && existsSync2(legacyDir)) {
29
23
  try {
30
24
  renameSync(legacyDir, newDir);
@@ -111,7 +105,7 @@ async function loadConfig() {
111
105
  normalizeAutoUpdate(migratedCfg);
112
106
  const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
113
107
  if (config.dbPath.startsWith("~")) {
114
- config.dbPath = config.dbPath.replace(/^~/, os.homedir());
108
+ config.dbPath = config.dbPath.replace(/^~/, os2.homedir());
115
109
  }
116
110
  return config;
117
111
  } catch {
@@ -218,7 +212,7 @@ __export(shard_manager_exports, {
218
212
  shardExists: () => shardExists
219
213
  });
220
214
  import path3 from "path";
221
- import { existsSync as existsSync3, mkdirSync } from "fs";
215
+ import { existsSync as existsSync3, mkdirSync, readdirSync } from "fs";
222
216
  import { createClient as createClient2 } from "@libsql/client";
223
217
  function initShardManager(encryptionKey) {
224
218
  _encryptionKey = encryptionKey;
@@ -257,8 +251,7 @@ function shardExists(projectName2) {
257
251
  }
258
252
  function listShards() {
259
253
  if (!existsSync3(SHARDS_DIR)) return [];
260
- const { readdirSync: readdirSync2 } = __require("fs");
261
- return readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
254
+ return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
262
255
  }
263
256
  async function ensureShardSchema(client) {
264
257
  await client.execute("PRAGMA journal_mode = WAL");
@@ -533,6 +526,7 @@ async function ensureSchema() {
533
526
  const client = getRawClient();
534
527
  await client.execute("PRAGMA journal_mode = WAL");
535
528
  await client.execute("PRAGMA busy_timeout = 30000");
529
+ await client.execute("PRAGMA wal_autocheckpoint = 1000");
536
530
  try {
537
531
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
538
532
  } catch {
@@ -1334,11 +1328,12 @@ async function disposeDatabase() {
1334
1328
  import { readFile, writeFile, unlink, mkdir, chmod } from "fs/promises";
1335
1329
  import { existsSync } from "fs";
1336
1330
  import path from "path";
1331
+ import os from "os";
1337
1332
  import crypto from "crypto";
1338
1333
  var SERVICE = "exe-mem";
1339
1334
  var ACCOUNT = "master-key";
1340
1335
  function getKeyDir() {
1341
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(process.env.HOME ?? "/tmp", ".exe-os");
1336
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(os.homedir(), ".exe-os");
1342
1337
  }
1343
1338
  function getKeyPath() {
1344
1339
  return path.join(getKeyDir(), "master.key");
@@ -1375,6 +1370,30 @@ async function getMasterKey() {
1375
1370
 
1376
1371
  // src/lib/store.ts
1377
1372
  init_config();
1373
+ var INIT_MAX_RETRIES = 3;
1374
+ var INIT_RETRY_DELAY_MS = 1e3;
1375
+ function isBusyError2(err) {
1376
+ if (err instanceof Error) {
1377
+ const msg = err.message.toLowerCase();
1378
+ return msg.includes("sqlite_busy") || msg.includes("database is locked");
1379
+ }
1380
+ return false;
1381
+ }
1382
+ async function retryOnBusy2(fn, label) {
1383
+ for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
1384
+ try {
1385
+ return await fn();
1386
+ } catch (err) {
1387
+ if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
1388
+ process.stderr.write(
1389
+ `[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
1390
+ `
1391
+ );
1392
+ await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
1393
+ }
1394
+ }
1395
+ throw new Error("unreachable");
1396
+ }
1378
1397
  var _pendingRecords = [];
1379
1398
  var _batchSize = 20;
1380
1399
  var _flushIntervalMs = 1e4;
@@ -1409,14 +1428,17 @@ async function initStore(options) {
1409
1428
  dbPath,
1410
1429
  encryptionKey: hexKey
1411
1430
  });
1412
- await ensureSchema();
1431
+ await retryOnBusy2(() => ensureSchema(), "ensureSchema");
1413
1432
  try {
1414
1433
  const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
1415
1434
  initShardManager2(hexKey);
1416
1435
  } catch {
1417
1436
  }
1418
1437
  const client = getClient();
1419
- const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
1438
+ const vResult = await retryOnBusy2(
1439
+ () => client.execute("SELECT MAX(version) as max_v FROM memories"),
1440
+ "version-query"
1441
+ );
1420
1442
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
1421
1443
  }
1422
1444
  async function flushBatch() {
@@ -1568,12 +1590,12 @@ function vectorToBlob(vector) {
1568
1590
  }
1569
1591
 
1570
1592
  // src/lib/behaviors-export.ts
1571
- import os2 from "os";
1593
+ import os3 from "os";
1572
1594
  import path4 from "path";
1573
1595
  import {
1574
1596
  existsSync as existsSync4,
1575
1597
  mkdirSync as mkdirSync2,
1576
- readdirSync,
1598
+ readdirSync as readdirSync2,
1577
1599
  statSync,
1578
1600
  unlinkSync,
1579
1601
  writeFileSync
@@ -1611,7 +1633,7 @@ async function listBehaviors(agentId2, projectName2, limit = 30) {
1611
1633
 
1612
1634
  // src/lib/behaviors-export.ts
1613
1635
  var BEHAVIORS_EXPORT_DIR = path4.join(
1614
- os2.homedir(),
1636
+ os3.homedir(),
1615
1637
  ".exe-os",
1616
1638
  "behaviors-export"
1617
1639
  );
@@ -1621,7 +1643,7 @@ function sweepStaleBehaviorExports(now = Date.now()) {
1621
1643
  if (!existsSync4(BEHAVIORS_EXPORT_DIR)) return;
1622
1644
  let entries;
1623
1645
  try {
1624
- entries = readdirSync(BEHAVIORS_EXPORT_DIR);
1646
+ entries = readdirSync2(BEHAVIORS_EXPORT_DIR);
1625
1647
  } catch {
1626
1648
  return;
1627
1649
  }
@@ -1,12 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
- }) : x)(function(x) {
7
- if (typeof require !== "undefined") return require.apply(this, arguments);
8
- throw Error('Dynamic require of "' + x + '" is not supported');
9
- });
10
4
  var __esm = (fn, res) => function __init() {
11
5
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
6
  };
@@ -110,6 +104,7 @@ async function ensureSchema() {
110
104
  const client = getRawClient();
111
105
  await client.execute("PRAGMA journal_mode = WAL");
112
106
  await client.execute("PRAGMA busy_timeout = 30000");
107
+ await client.execute("PRAGMA wal_autocheckpoint = 1000");
113
108
  try {
114
109
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
115
110
  } catch {
@@ -913,9 +908,10 @@ var init_database = __esm({
913
908
  import { readFile, writeFile, unlink, mkdir, chmod } from "fs/promises";
914
909
  import { existsSync } from "fs";
915
910
  import path from "path";
911
+ import os from "os";
916
912
  import crypto from "crypto";
917
913
  function getKeyDir() {
918
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(process.env.HOME ?? "/tmp", ".exe-os");
914
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(os.homedir(), ".exe-os");
919
915
  }
920
916
  function getKeyPath() {
921
917
  return path.join(getKeyDir(), "master.key");
@@ -959,15 +955,15 @@ var init_keychain = __esm({
959
955
  });
960
956
 
961
957
  // src/lib/config.ts
962
- import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
958
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, chmod as chmod2 } from "fs/promises";
963
959
  import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
964
960
  import path2 from "path";
965
- import os from "os";
961
+ import os2 from "os";
966
962
  function resolveDataDir() {
967
963
  if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
968
964
  if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
969
- const newDir = path2.join(os.homedir(), ".exe-os");
970
- const legacyDir = path2.join(os.homedir(), ".exe-mem");
965
+ const newDir = path2.join(os2.homedir(), ".exe-os");
966
+ const legacyDir = path2.join(os2.homedir(), ".exe-mem");
971
967
  if (!existsSync2(newDir) && existsSync2(legacyDir)) {
972
968
  try {
973
969
  renameSync(legacyDir, newDir);
@@ -1054,7 +1050,7 @@ async function loadConfig() {
1054
1050
  normalizeAutoUpdate(migratedCfg);
1055
1051
  const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
1056
1052
  if (config.dbPath.startsWith("~")) {
1057
- config.dbPath = config.dbPath.replace(/^~/, os.homedir());
1053
+ config.dbPath = config.dbPath.replace(/^~/, os2.homedir());
1058
1054
  }
1059
1055
  return config;
1060
1056
  } catch {
@@ -1161,7 +1157,7 @@ __export(shard_manager_exports, {
1161
1157
  shardExists: () => shardExists
1162
1158
  });
1163
1159
  import path3 from "path";
1164
- import { existsSync as existsSync3, mkdirSync } from "fs";
1160
+ import { existsSync as existsSync3, mkdirSync, readdirSync } from "fs";
1165
1161
  import { createClient as createClient2 } from "@libsql/client";
1166
1162
  function initShardManager(encryptionKey) {
1167
1163
  _encryptionKey = encryptionKey;
@@ -1200,7 +1196,6 @@ function shardExists(projectName) {
1200
1196
  }
1201
1197
  function listShards() {
1202
1198
  if (!existsSync3(SHARDS_DIR)) return [];
1203
- const { readdirSync } = __require("fs");
1204
1199
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
1205
1200
  }
1206
1201
  async function ensureShardSchema(client) {
@@ -1390,6 +1385,28 @@ var init_shard_manager = __esm({
1390
1385
  });
1391
1386
 
1392
1387
  // src/lib/store.ts
1388
+ function isBusyError2(err) {
1389
+ if (err instanceof Error) {
1390
+ const msg = err.message.toLowerCase();
1391
+ return msg.includes("sqlite_busy") || msg.includes("database is locked");
1392
+ }
1393
+ return false;
1394
+ }
1395
+ async function retryOnBusy2(fn, label) {
1396
+ for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
1397
+ try {
1398
+ return await fn();
1399
+ } catch (err) {
1400
+ if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
1401
+ process.stderr.write(
1402
+ `[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
1403
+ `
1404
+ );
1405
+ await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
1406
+ }
1407
+ }
1408
+ throw new Error("unreachable");
1409
+ }
1393
1410
  async function initStore(options) {
1394
1411
  if (_flushTimer !== null) {
1395
1412
  clearInterval(_flushTimer);
@@ -1418,14 +1435,17 @@ async function initStore(options) {
1418
1435
  dbPath,
1419
1436
  encryptionKey: hexKey
1420
1437
  });
1421
- await ensureSchema();
1438
+ await retryOnBusy2(() => ensureSchema(), "ensureSchema");
1422
1439
  try {
1423
1440
  const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
1424
1441
  initShardManager2(hexKey);
1425
1442
  } catch {
1426
1443
  }
1427
1444
  const client = getClient();
1428
- const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
1445
+ const vResult = await retryOnBusy2(
1446
+ () => client.execute("SELECT MAX(version) as max_v FROM memories"),
1447
+ "version-query"
1448
+ );
1429
1449
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
1430
1450
  }
1431
1451
  function buildWikiScopeFilter(options, columnPrefix) {
@@ -1480,7 +1500,7 @@ async function attachDocumentMetadata(records) {
1480
1500
  }
1481
1501
  return records;
1482
1502
  }
1483
- var _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
1503
+ var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
1484
1504
  var init_store = __esm({
1485
1505
  "src/lib/store.ts"() {
1486
1506
  "use strict";
@@ -1488,6 +1508,8 @@ var init_store = __esm({
1488
1508
  init_database();
1489
1509
  init_keychain();
1490
1510
  init_config();
1511
+ INIT_MAX_RETRIES = 3;
1512
+ INIT_RETRY_DELAY_MS = 1e3;
1491
1513
  _pendingRecords = [];
1492
1514
  _batchSize = 20;
1493
1515
  _flushIntervalMs = 1e4;