@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,7 +251,6 @@ function shardExists(projectName) {
257
251
  }
258
252
  function listShards() {
259
253
  if (!existsSync3(SHARDS_DIR)) return [];
260
- const { readdirSync } = __require("fs");
261
254
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
262
255
  }
263
256
  async function ensureShardSchema(client) {
@@ -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() {
@@ -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,7 +251,6 @@ function shardExists(projectName) {
257
251
  }
258
252
  function listShards() {
259
253
  if (!existsSync3(SHARDS_DIR)) return [];
260
- const { readdirSync } = __require("fs");
261
254
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
262
255
  }
263
256
  async function ensureShardSchema(client) {
@@ -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() {
@@ -1577,7 +1599,8 @@ async function wikiRequest(config, path4, method = "GET", body) {
1577
1599
  const response = await fetch(url, {
1578
1600
  method,
1579
1601
  headers,
1580
- body: body ? JSON.stringify(body) : void 0
1602
+ body: body ? JSON.stringify(body) : void 0,
1603
+ signal: AbortSignal.timeout(3e4)
1581
1604
  });
1582
1605
  if (!response.ok) {
1583
1606
  throw new Error(`Wiki API ${method} ${path4}: ${response.status} ${response.statusText}`);