@askexenow/exe-os 0.8.32 → 0.8.36

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 (87) hide show
  1. package/dist/bin/backfill-conversations.js +332 -348
  2. package/dist/bin/backfill-responses.js +72 -12
  3. package/dist/bin/backfill-vectors.js +72 -12
  4. package/dist/bin/cleanup-stale-review-tasks.js +63 -3
  5. package/dist/bin/cli.js +1518 -1122
  6. package/dist/bin/exe-agent.js +4 -4
  7. package/dist/bin/exe-assign.js +80 -18
  8. package/dist/bin/exe-boot.js +408 -89
  9. package/dist/bin/exe-call.js +83 -24
  10. package/dist/bin/exe-dispatch.js +18 -10
  11. package/dist/bin/exe-doctor.js +63 -3
  12. package/dist/bin/exe-export-behaviors.js +64 -3
  13. package/dist/bin/exe-forget.js +69 -4
  14. package/dist/bin/exe-gateway.js +121 -36
  15. package/dist/bin/exe-heartbeat.js +77 -13
  16. package/dist/bin/exe-kill.js +64 -3
  17. package/dist/bin/exe-launch-agent.js +162 -35
  18. package/dist/bin/exe-link.js +946 -0
  19. package/dist/bin/exe-new-employee.js +121 -36
  20. package/dist/bin/exe-pending-messages.js +72 -7
  21. package/dist/bin/exe-pending-notifications.js +63 -3
  22. package/dist/bin/exe-pending-reviews.js +75 -10
  23. package/dist/bin/exe-rename.js +1287 -0
  24. package/dist/bin/exe-review.js +64 -4
  25. package/dist/bin/exe-search.js +79 -13
  26. package/dist/bin/exe-session-cleanup.js +91 -26
  27. package/dist/bin/exe-status.js +64 -4
  28. package/dist/bin/exe-team.js +64 -4
  29. package/dist/bin/git-sweep.js +71 -4
  30. package/dist/bin/graph-backfill.js +64 -3
  31. package/dist/bin/graph-export.js +64 -3
  32. package/dist/bin/install.js +3 -3
  33. package/dist/bin/scan-tasks.js +71 -4
  34. package/dist/bin/setup.js +156 -38
  35. package/dist/bin/shard-migrate.js +64 -3
  36. package/dist/bin/wiki-sync.js +64 -3
  37. package/dist/gateway/index.js +122 -37
  38. package/dist/hooks/bug-report-worker.js +209 -23
  39. package/dist/hooks/commit-complete.js +71 -4
  40. package/dist/hooks/error-recall.js +79 -13
  41. package/dist/hooks/ingest-worker.js +129 -43
  42. package/dist/hooks/instructions-loaded.js +71 -4
  43. package/dist/hooks/notification.js +71 -4
  44. package/dist/hooks/post-compact.js +71 -4
  45. package/dist/hooks/pre-compact.js +71 -4
  46. package/dist/hooks/pre-tool-use.js +413 -194
  47. package/dist/hooks/prompt-ingest-worker.js +82 -22
  48. package/dist/hooks/prompt-submit.js +103 -37
  49. package/dist/hooks/response-ingest-worker.js +87 -22
  50. package/dist/hooks/session-end.js +71 -4
  51. package/dist/hooks/session-start.js +79 -13
  52. package/dist/hooks/stop.js +71 -4
  53. package/dist/hooks/subagent-stop.js +71 -4
  54. package/dist/hooks/summary-worker.js +303 -50
  55. package/dist/index.js +134 -46
  56. package/dist/lib/cloud-sync.js +209 -15
  57. package/dist/lib/consolidation.js +4 -4
  58. package/dist/lib/database.js +64 -2
  59. package/dist/lib/device-registry.js +70 -3
  60. package/dist/lib/employee-templates.js +48 -22
  61. package/dist/lib/employees.js +34 -1
  62. package/dist/lib/exe-daemon.js +136 -53
  63. package/dist/lib/hybrid-search.js +79 -13
  64. package/dist/lib/identity-templates.js +57 -6
  65. package/dist/lib/identity.js +3 -3
  66. package/dist/lib/messaging.js +22 -14
  67. package/dist/lib/reminders.js +3 -3
  68. package/dist/lib/schedules.js +63 -3
  69. package/dist/lib/skill-learning.js +3 -3
  70. package/dist/lib/status-brief.js +63 -5
  71. package/dist/lib/store.js +64 -3
  72. package/dist/lib/task-router.js +4 -2
  73. package/dist/lib/tasks.js +48 -21
  74. package/dist/lib/tmux-routing.js +47 -20
  75. package/dist/mcp/server.js +727 -58
  76. package/dist/mcp/tools/complete-reminder.js +3 -3
  77. package/dist/mcp/tools/create-reminder.js +3 -3
  78. package/dist/mcp/tools/create-task.js +151 -24
  79. package/dist/mcp/tools/deactivate-behavior.js +3 -3
  80. package/dist/mcp/tools/list-reminders.js +3 -3
  81. package/dist/mcp/tools/list-tasks.js +17 -8
  82. package/dist/mcp/tools/send-message.js +24 -16
  83. package/dist/mcp/tools/update-task.js +25 -16
  84. package/dist/runtime/index.js +112 -24
  85. package/dist/tui/App.js +139 -36
  86. package/package.json +6 -2
  87. package/src/commands/exe/rename.md +12 -0
@@ -262,7 +262,7 @@ function listShards() {
262
262
  }
263
263
  async function ensureShardSchema(client) {
264
264
  await client.execute("PRAGMA journal_mode = WAL");
265
- await client.execute("PRAGMA busy_timeout = 5000");
265
+ await client.execute("PRAGMA busy_timeout = 30000");
266
266
  try {
267
267
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
268
268
  } catch {
@@ -459,12 +459,65 @@ var EMBEDDING_DIM = 1024;
459
459
 
460
460
  // src/lib/database.ts
461
461
  import { createClient } from "@libsql/client";
462
+
463
+ // src/lib/db-retry.ts
464
+ var MAX_RETRIES = 3;
465
+ var BASE_DELAY_MS = 200;
466
+ var MAX_JITTER_MS = 300;
467
+ function isBusyError(err) {
468
+ if (err instanceof Error) {
469
+ const msg = err.message.toLowerCase();
470
+ return msg.includes("sqlite_busy") || msg.includes("database is locked");
471
+ }
472
+ return false;
473
+ }
474
+ function delay(ms) {
475
+ return new Promise((resolve) => setTimeout(resolve, ms));
476
+ }
477
+ async function retryOnBusy(fn, label) {
478
+ let lastError;
479
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
480
+ try {
481
+ return await fn();
482
+ } catch (err) {
483
+ lastError = err;
484
+ if (!isBusyError(err) || attempt === MAX_RETRIES) {
485
+ throw err;
486
+ }
487
+ const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
488
+ const jitter = Math.floor(Math.random() * MAX_JITTER_MS);
489
+ process.stderr.write(
490
+ `[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${MAX_RETRIES} \u2014 waiting ${backoff + jitter}ms
491
+ `
492
+ );
493
+ await delay(backoff + jitter);
494
+ }
495
+ }
496
+ throw lastError;
497
+ }
498
+ function wrapWithRetry(client) {
499
+ return new Proxy(client, {
500
+ get(target, prop, receiver) {
501
+ if (prop === "execute") {
502
+ return (sql) => retryOnBusy(() => target.execute(sql), "execute");
503
+ }
504
+ if (prop === "batch") {
505
+ return (stmts) => retryOnBusy(() => target.batch(stmts), "batch");
506
+ }
507
+ return Reflect.get(target, prop, receiver);
508
+ }
509
+ });
510
+ }
511
+
512
+ // src/lib/database.ts
462
513
  var _client = null;
514
+ var _resilientClient = null;
463
515
  var initTurso = initDatabase;
464
516
  async function initDatabase(config) {
465
517
  if (_client) {
466
518
  _client.close();
467
519
  _client = null;
520
+ _resilientClient = null;
468
521
  }
469
522
  const opts = {
470
523
  url: `file:${config.dbPath}`
@@ -473,17 +526,24 @@ async function initDatabase(config) {
473
526
  opts.encryptionKey = config.encryptionKey;
474
527
  }
475
528
  _client = createClient(opts);
529
+ _resilientClient = wrapWithRetry(_client);
476
530
  }
477
531
  function getClient() {
532
+ if (!_resilientClient) {
533
+ throw new Error("Database client not initialized. Call initDatabase() first.");
534
+ }
535
+ return _resilientClient;
536
+ }
537
+ function getRawClient() {
478
538
  if (!_client) {
479
539
  throw new Error("Database client not initialized. Call initDatabase() first.");
480
540
  }
481
541
  return _client;
482
542
  }
483
543
  async function ensureSchema() {
484
- const client = getClient();
544
+ const client = getRawClient();
485
545
  await client.execute("PRAGMA journal_mode = WAL");
486
- await client.execute("PRAGMA busy_timeout = 5000");
546
+ await client.execute("PRAGMA busy_timeout = 30000");
487
547
  try {
488
548
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
489
549
  } catch {
@@ -1732,11 +1792,11 @@ async function connectEmbedDaemon() {
1732
1792
  }
1733
1793
  }
1734
1794
  const start = Date.now();
1735
- let delay = 100;
1795
+ let delay2 = 100;
1736
1796
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
1737
- await new Promise((r) => setTimeout(r, delay));
1797
+ await new Promise((r) => setTimeout(r, delay2));
1738
1798
  if (await connectToSocket()) return true;
1739
- delay = Math.min(delay * 2, 3e3);
1799
+ delay2 = Math.min(delay2 * 2, 3e3);
1740
1800
  }
1741
1801
  return false;
1742
1802
  }
@@ -1828,11 +1888,11 @@ async function embedViaClient(text, priority = "high") {
1828
1888
  `);
1829
1889
  killAndRespawnDaemon();
1830
1890
  const start = Date.now();
1831
- let delay = 200;
1891
+ let delay2 = 200;
1832
1892
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
1833
- await new Promise((r) => setTimeout(r, delay));
1893
+ await new Promise((r) => setTimeout(r, delay2));
1834
1894
  if (await connectToSocket()) break;
1835
- delay = Math.min(delay * 2, 3e3);
1895
+ delay2 = Math.min(delay2 * 2, 3e3);
1836
1896
  }
1837
1897
  if (!_connected) return null;
1838
1898
  }
@@ -1844,11 +1904,11 @@ async function embedViaClient(text, priority = "high") {
1844
1904
  `);
1845
1905
  killAndRespawnDaemon();
1846
1906
  const start = Date.now();
1847
- let delay = 200;
1907
+ let delay2 = 200;
1848
1908
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
1849
- await new Promise((r) => setTimeout(r, delay));
1909
+ await new Promise((r) => setTimeout(r, delay2));
1850
1910
  if (await connectToSocket()) break;
1851
- delay = Math.min(delay * 2, 3e3);
1911
+ delay2 = Math.min(delay2 * 2, 3e3);
1852
1912
  }
1853
1913
  if (!_connected) return null;
1854
1914
  const retry = await sendRequest([text], priority);
@@ -262,7 +262,7 @@ function listShards() {
262
262
  }
263
263
  async function ensureShardSchema(client) {
264
264
  await client.execute("PRAGMA journal_mode = WAL");
265
- await client.execute("PRAGMA busy_timeout = 5000");
265
+ await client.execute("PRAGMA busy_timeout = 30000");
266
266
  try {
267
267
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
268
268
  } catch {
@@ -448,12 +448,65 @@ var init_shard_manager = __esm({
448
448
 
449
449
  // src/lib/database.ts
450
450
  import { createClient } from "@libsql/client";
451
+
452
+ // src/lib/db-retry.ts
453
+ var MAX_RETRIES = 3;
454
+ var BASE_DELAY_MS = 200;
455
+ var MAX_JITTER_MS = 300;
456
+ function isBusyError(err) {
457
+ if (err instanceof Error) {
458
+ const msg = err.message.toLowerCase();
459
+ return msg.includes("sqlite_busy") || msg.includes("database is locked");
460
+ }
461
+ return false;
462
+ }
463
+ function delay(ms) {
464
+ return new Promise((resolve) => setTimeout(resolve, ms));
465
+ }
466
+ async function retryOnBusy(fn, label) {
467
+ let lastError;
468
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
469
+ try {
470
+ return await fn();
471
+ } catch (err) {
472
+ lastError = err;
473
+ if (!isBusyError(err) || attempt === MAX_RETRIES) {
474
+ throw err;
475
+ }
476
+ const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
477
+ const jitter = Math.floor(Math.random() * MAX_JITTER_MS);
478
+ process.stderr.write(
479
+ `[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${MAX_RETRIES} \u2014 waiting ${backoff + jitter}ms
480
+ `
481
+ );
482
+ await delay(backoff + jitter);
483
+ }
484
+ }
485
+ throw lastError;
486
+ }
487
+ function wrapWithRetry(client) {
488
+ return new Proxy(client, {
489
+ get(target, prop, receiver) {
490
+ if (prop === "execute") {
491
+ return (sql) => retryOnBusy(() => target.execute(sql), "execute");
492
+ }
493
+ if (prop === "batch") {
494
+ return (stmts) => retryOnBusy(() => target.batch(stmts), "batch");
495
+ }
496
+ return Reflect.get(target, prop, receiver);
497
+ }
498
+ });
499
+ }
500
+
501
+ // src/lib/database.ts
451
502
  var _client = null;
503
+ var _resilientClient = null;
452
504
  var initTurso = initDatabase;
453
505
  async function initDatabase(config) {
454
506
  if (_client) {
455
507
  _client.close();
456
508
  _client = null;
509
+ _resilientClient = null;
457
510
  }
458
511
  const opts = {
459
512
  url: `file:${config.dbPath}`
@@ -462,17 +515,24 @@ async function initDatabase(config) {
462
515
  opts.encryptionKey = config.encryptionKey;
463
516
  }
464
517
  _client = createClient(opts);
518
+ _resilientClient = wrapWithRetry(_client);
465
519
  }
466
520
  function getClient() {
521
+ if (!_resilientClient) {
522
+ throw new Error("Database client not initialized. Call initDatabase() first.");
523
+ }
524
+ return _resilientClient;
525
+ }
526
+ function getRawClient() {
467
527
  if (!_client) {
468
528
  throw new Error("Database client not initialized. Call initDatabase() first.");
469
529
  }
470
530
  return _client;
471
531
  }
472
532
  async function ensureSchema() {
473
- const client = getClient();
533
+ const client = getRawClient();
474
534
  await client.execute("PRAGMA journal_mode = WAL");
475
- await client.execute("PRAGMA busy_timeout = 5000");
535
+ await client.execute("PRAGMA busy_timeout = 30000");
476
536
  try {
477
537
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
478
538
  } catch {
@@ -1546,11 +1606,11 @@ async function connectEmbedDaemon() {
1546
1606
  }
1547
1607
  }
1548
1608
  const start = Date.now();
1549
- let delay = 100;
1609
+ let delay2 = 100;
1550
1610
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
1551
- await new Promise((r) => setTimeout(r, delay));
1611
+ await new Promise((r) => setTimeout(r, delay2));
1552
1612
  if (await connectToSocket()) return true;
1553
- delay = Math.min(delay * 2, 3e3);
1613
+ delay2 = Math.min(delay2 * 2, 3e3);
1554
1614
  }
1555
1615
  return false;
1556
1616
  }
@@ -1642,11 +1702,11 @@ async function embedViaClient(text, priority = "high") {
1642
1702
  `);
1643
1703
  killAndRespawnDaemon();
1644
1704
  const start = Date.now();
1645
- let delay = 200;
1705
+ let delay2 = 200;
1646
1706
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
1647
- await new Promise((r) => setTimeout(r, delay));
1707
+ await new Promise((r) => setTimeout(r, delay2));
1648
1708
  if (await connectToSocket()) break;
1649
- delay = Math.min(delay * 2, 3e3);
1709
+ delay2 = Math.min(delay2 * 2, 3e3);
1650
1710
  }
1651
1711
  if (!_connected) return null;
1652
1712
  }
@@ -1658,11 +1718,11 @@ async function embedViaClient(text, priority = "high") {
1658
1718
  `);
1659
1719
  killAndRespawnDaemon();
1660
1720
  const start = Date.now();
1661
- let delay = 200;
1721
+ let delay2 = 200;
1662
1722
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
1663
- await new Promise((r) => setTimeout(r, delay));
1723
+ await new Promise((r) => setTimeout(r, delay2));
1664
1724
  if (await connectToSocket()) break;
1665
- delay = Math.min(delay * 2, 3e3);
1725
+ delay2 = Math.min(delay2 * 2, 3e3);
1666
1726
  }
1667
1727
  if (!_connected) return null;
1668
1728
  const retry = await sendRequest([text], priority);
@@ -262,7 +262,7 @@ function listShards() {
262
262
  }
263
263
  async function ensureShardSchema(client) {
264
264
  await client.execute("PRAGMA journal_mode = WAL");
265
- await client.execute("PRAGMA busy_timeout = 5000");
265
+ await client.execute("PRAGMA busy_timeout = 30000");
266
266
  try {
267
267
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
268
268
  } catch {
@@ -448,12 +448,65 @@ var init_shard_manager = __esm({
448
448
 
449
449
  // src/lib/database.ts
450
450
  import { createClient } from "@libsql/client";
451
+
452
+ // src/lib/db-retry.ts
453
+ var MAX_RETRIES = 3;
454
+ var BASE_DELAY_MS = 200;
455
+ var MAX_JITTER_MS = 300;
456
+ function isBusyError(err) {
457
+ if (err instanceof Error) {
458
+ const msg = err.message.toLowerCase();
459
+ return msg.includes("sqlite_busy") || msg.includes("database is locked");
460
+ }
461
+ return false;
462
+ }
463
+ function delay(ms) {
464
+ return new Promise((resolve) => setTimeout(resolve, ms));
465
+ }
466
+ async function retryOnBusy(fn, label) {
467
+ let lastError;
468
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
469
+ try {
470
+ return await fn();
471
+ } catch (err) {
472
+ lastError = err;
473
+ if (!isBusyError(err) || attempt === MAX_RETRIES) {
474
+ throw err;
475
+ }
476
+ const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
477
+ const jitter = Math.floor(Math.random() * MAX_JITTER_MS);
478
+ process.stderr.write(
479
+ `[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${MAX_RETRIES} \u2014 waiting ${backoff + jitter}ms
480
+ `
481
+ );
482
+ await delay(backoff + jitter);
483
+ }
484
+ }
485
+ throw lastError;
486
+ }
487
+ function wrapWithRetry(client) {
488
+ return new Proxy(client, {
489
+ get(target, prop, receiver) {
490
+ if (prop === "execute") {
491
+ return (sql) => retryOnBusy(() => target.execute(sql), "execute");
492
+ }
493
+ if (prop === "batch") {
494
+ return (stmts) => retryOnBusy(() => target.batch(stmts), "batch");
495
+ }
496
+ return Reflect.get(target, prop, receiver);
497
+ }
498
+ });
499
+ }
500
+
501
+ // src/lib/database.ts
451
502
  var _client = null;
503
+ var _resilientClient = null;
452
504
  var initTurso = initDatabase;
453
505
  async function initDatabase(config) {
454
506
  if (_client) {
455
507
  _client.close();
456
508
  _client = null;
509
+ _resilientClient = null;
457
510
  }
458
511
  const opts = {
459
512
  url: `file:${config.dbPath}`
@@ -462,17 +515,24 @@ async function initDatabase(config) {
462
515
  opts.encryptionKey = config.encryptionKey;
463
516
  }
464
517
  _client = createClient(opts);
518
+ _resilientClient = wrapWithRetry(_client);
465
519
  }
466
520
  function getClient() {
521
+ if (!_resilientClient) {
522
+ throw new Error("Database client not initialized. Call initDatabase() first.");
523
+ }
524
+ return _resilientClient;
525
+ }
526
+ function getRawClient() {
467
527
  if (!_client) {
468
528
  throw new Error("Database client not initialized. Call initDatabase() first.");
469
529
  }
470
530
  return _client;
471
531
  }
472
532
  async function ensureSchema() {
473
- const client = getClient();
533
+ const client = getRawClient();
474
534
  await client.execute("PRAGMA journal_mode = WAL");
475
- await client.execute("PRAGMA busy_timeout = 5000");
535
+ await client.execute("PRAGMA busy_timeout = 30000");
476
536
  try {
477
537
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
478
538
  } catch {