@askexenow/exe-os 0.8.41 → 0.8.43

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 (76) hide show
  1. package/dist/bin/backfill-conversations.js +805 -642
  2. package/dist/bin/backfill-responses.js +804 -641
  3. package/dist/bin/backfill-vectors.js +791 -634
  4. package/dist/bin/cleanup-stale-review-tasks.js +788 -631
  5. package/dist/bin/cli.js +1345 -660
  6. package/dist/bin/exe-agent.js +20 -1
  7. package/dist/bin/exe-assign.js +1503 -1343
  8. package/dist/bin/exe-boot.js +2518 -1798
  9. package/dist/bin/exe-call.js +39 -1
  10. package/dist/bin/exe-cloud.js +15 -1
  11. package/dist/bin/exe-dispatch.js +39 -2
  12. package/dist/bin/exe-doctor.js +790 -633
  13. package/dist/bin/exe-export-behaviors.js +792 -637
  14. package/dist/bin/exe-forget.js +145 -0
  15. package/dist/bin/exe-gateway.js +2500 -1877
  16. package/dist/bin/exe-heartbeat.js +147 -1
  17. package/dist/bin/exe-kill.js +795 -640
  18. package/dist/bin/exe-launch-agent.js +2168 -2008
  19. package/dist/bin/exe-link.js +28 -2
  20. package/dist/bin/exe-new-employee.js +25 -3
  21. package/dist/bin/exe-pending-messages.js +146 -1
  22. package/dist/bin/exe-pending-notifications.js +788 -631
  23. package/dist/bin/exe-pending-reviews.js +147 -1
  24. package/dist/bin/exe-rename.js +23 -0
  25. package/dist/bin/exe-review.js +490 -327
  26. package/dist/bin/exe-search.js +154 -3
  27. package/dist/bin/exe-session-cleanup.js +2466 -413
  28. package/dist/bin/exe-status.js +474 -317
  29. package/dist/bin/exe-team.js +474 -317
  30. package/dist/bin/git-sweep.js +2690 -150
  31. package/dist/bin/graph-backfill.js +794 -637
  32. package/dist/bin/graph-export.js +798 -641
  33. package/dist/bin/scan-tasks.js +2951 -44
  34. package/dist/bin/setup.js +62 -26
  35. package/dist/bin/shard-migrate.js +792 -637
  36. package/dist/bin/wiki-sync.js +794 -637
  37. package/dist/gateway/index.js +2504 -1895
  38. package/dist/hooks/bug-report-worker.js +2118 -576
  39. package/dist/hooks/commit-complete.js +2689 -149
  40. package/dist/hooks/error-recall.js +154 -3
  41. package/dist/hooks/ingest-worker.js +1439 -815
  42. package/dist/hooks/instructions-loaded.js +151 -0
  43. package/dist/hooks/notification.js +153 -2
  44. package/dist/hooks/post-compact.js +164 -0
  45. package/dist/hooks/pre-compact.js +3073 -101
  46. package/dist/hooks/pre-tool-use.js +151 -0
  47. package/dist/hooks/prompt-ingest-worker.js +1714 -1537
  48. package/dist/hooks/prompt-submit.js +2658 -1113
  49. package/dist/hooks/response-ingest-worker.js +170 -6
  50. package/dist/hooks/session-end.js +153 -2
  51. package/dist/hooks/session-start.js +154 -3
  52. package/dist/hooks/stop.js +151 -0
  53. package/dist/hooks/subagent-stop.js +151 -0
  54. package/dist/hooks/summary-worker.js +179 -7
  55. package/dist/index.js +278 -100
  56. package/dist/lib/cloud-sync.js +28 -2
  57. package/dist/lib/consolidation.js +69 -2
  58. package/dist/lib/database.js +19 -0
  59. package/dist/lib/device-registry.js +19 -0
  60. package/dist/lib/employee-templates.js +20 -1
  61. package/dist/lib/exe-daemon.js +236 -16
  62. package/dist/lib/hybrid-search.js +154 -3
  63. package/dist/lib/license.js +15 -1
  64. package/dist/lib/messaging.js +39 -2
  65. package/dist/lib/schedules.js +792 -637
  66. package/dist/lib/store.js +796 -636
  67. package/dist/lib/tasks.js +1614 -1091
  68. package/dist/lib/tmux-routing.js +149 -9
  69. package/dist/mcp/server.js +1825 -1138
  70. package/dist/mcp/tools/create-task.js +2280 -828
  71. package/dist/mcp/tools/list-tasks.js +2788 -159
  72. package/dist/mcp/tools/send-message.js +39 -2
  73. package/dist/mcp/tools/update-task.js +64 -0
  74. package/dist/runtime/index.js +235 -67
  75. package/dist/tui/App.js +1452 -644
  76. package/package.json +3 -2
@@ -477,6 +477,10 @@ function loadLicense() {
477
477
  return null;
478
478
  }
479
479
  }
480
+ function saveLicense(apiKey) {
481
+ mkdirSync(EXE_AI_DIR, { recursive: true });
482
+ writeFileSync(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
483
+ }
480
484
  async function verifyLicenseJwt(token) {
481
485
  try {
482
486
  const key = await importSPKI(LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG);
@@ -566,7 +570,21 @@ function getCacheAgeMs() {
566
570
  }
567
571
  }
568
572
  async function checkLicense() {
569
- const key = loadLicense();
573
+ let key = loadLicense();
574
+ if (!key) {
575
+ try {
576
+ const configPath = path4.join(EXE_AI_DIR, "config.json");
577
+ if (existsSync4(configPath)) {
578
+ const raw = JSON.parse(readFileSync3(configPath, "utf8"));
579
+ const cloud = raw.cloud;
580
+ if (cloud?.apiKey) {
581
+ key = cloud.apiKey;
582
+ saveLicense(key);
583
+ }
584
+ }
585
+ } catch {
586
+ }
587
+ }
570
588
  if (!key) return FREE_LICENSE;
571
589
  const cached = await getCachedLicense();
572
590
  if (cached && getCacheAgeMs() < CACHE_MAX_AGE_MS) return cached;
@@ -726,7 +744,7 @@ async function fetchWithRetry(url, init) {
726
744
  try {
727
745
  const signal = AbortSignal.timeout(FETCH_TIMEOUT_MS);
728
746
  const resp = await fetch(url, { ...init, signal });
729
- if (resp.status >= 500 && attempt < MAX_RETRIES) {
747
+ if (resp && resp.status >= 500 && attempt < MAX_RETRIES) {
730
748
  await new Promise((r) => setTimeout(r, BASE_DELAY_MS * Math.pow(2, attempt)));
731
749
  continue;
732
750
  }
@@ -770,6 +788,10 @@ async function cloudPush(records, maxVersion, config) {
770
788
  },
771
789
  body: JSON.stringify({ version: maxVersion, blob })
772
790
  });
791
+ if (resp == null) {
792
+ logError("[cloud-sync] PUSH FAILED: no response from server");
793
+ return false;
794
+ }
773
795
  if (resp.status === 409) {
774
796
  logError("[cloud-sync] PUSH VERSION CONFLICT \u2014 re-pull required before next push");
775
797
  return false;
@@ -792,6 +814,10 @@ async function cloudPull(sinceVersion, config) {
792
814
  },
793
815
  body: JSON.stringify({ since_version: sinceVersion })
794
816
  });
817
+ if (response == null) {
818
+ logError("[cloud-sync] PULL FAILED: no response from server");
819
+ return { records: [], maxVersion: sinceVersion };
820
+ }
795
821
  if (!response.ok) return { records: [], maxVersion: sinceVersion };
796
822
  const data = await response.json();
797
823
  const allRecords = [];
@@ -890,6 +890,10 @@ function registerBinSymlinks(name) {
890
890
  return { created, skipped, errors };
891
891
  }
892
892
 
893
+ // src/lib/global-procedures.ts
894
+ init_database();
895
+ import { randomUUID } from "crypto";
896
+
893
897
  // src/lib/employee-templates.ts
894
898
  var TEMPLATE_VERSION = 1;
895
899
  var TEMPLATES = {
@@ -1236,7 +1240,7 @@ import path4 from "path";
1236
1240
  // src/lib/license.ts
1237
1241
  init_config();
1238
1242
  import { readFileSync as readFileSync3, writeFileSync, existsSync as existsSync3, mkdirSync } from "fs";
1239
- import { randomUUID } from "crypto";
1243
+ import { randomUUID as randomUUID2 } from "crypto";
1240
1244
  import path3 from "path";
1241
1245
  import { jwtVerify, importSPKI } from "jose";
1242
1246
  var LICENSE_PATH = path3.join(EXE_AI_DIR, "license.key");
@@ -1289,7 +1293,7 @@ function loadDeviceId() {
1289
1293
  }
1290
1294
  } catch {
1291
1295
  }
1292
- const id = randomUUID();
1296
+ const id = randomUUID2();
1293
1297
  mkdirSync(EXE_AI_DIR, { recursive: true });
1294
1298
  writeFileSync(DEVICE_ID_PATH, id, "utf8");
1295
1299
  return id;
@@ -1302,6 +1306,10 @@ function loadLicense() {
1302
1306
  return null;
1303
1307
  }
1304
1308
  }
1309
+ function saveLicense(apiKey) {
1310
+ mkdirSync(EXE_AI_DIR, { recursive: true });
1311
+ writeFileSync(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
1312
+ }
1305
1313
  async function verifyLicenseJwt(token) {
1306
1314
  try {
1307
1315
  const key = await importSPKI(LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG);
@@ -1392,7 +1400,21 @@ function getCacheAgeMs() {
1392
1400
  }
1393
1401
  }
1394
1402
  async function checkLicense() {
1395
- const key = loadLicense();
1403
+ let key = loadLicense();
1404
+ if (!key) {
1405
+ try {
1406
+ const configPath = path3.join(EXE_AI_DIR, "config.json");
1407
+ if (existsSync3(configPath)) {
1408
+ const raw = JSON.parse(readFileSync3(configPath, "utf8"));
1409
+ const cloud = raw.cloud;
1410
+ if (cloud?.apiKey) {
1411
+ key = cloud.apiKey;
1412
+ saveLicense(key);
1413
+ }
1414
+ }
1415
+ } catch {
1416
+ }
1417
+ }
1396
1418
  if (!key) return FREE_LICENSE;
1397
1419
  const cached = await getCachedLicense();
1398
1420
  if (cached && getCacheAgeMs() < CACHE_MAX_AGE_MS) return cached;
@@ -301,6 +301,13 @@ async function ensureSchema() {
301
301
  });
302
302
  } catch {
303
303
  }
304
+ try {
305
+ await client.execute({
306
+ sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
307
+ args: []
308
+ });
309
+ } catch {
310
+ }
304
311
  try {
305
312
  await client.execute({
306
313
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -747,6 +754,18 @@ async function ensureSchema() {
747
754
  CREATE INDEX IF NOT EXISTS idx_session_kills_agent
748
755
  ON session_kills(agent_id);
749
756
  `);
757
+ await client.execute(`
758
+ CREATE TABLE IF NOT EXISTS global_procedures (
759
+ id TEXT PRIMARY KEY,
760
+ title TEXT NOT NULL,
761
+ content TEXT NOT NULL,
762
+ priority TEXT NOT NULL DEFAULT 'p0',
763
+ domain TEXT,
764
+ active INTEGER NOT NULL DEFAULT 1,
765
+ created_at TEXT NOT NULL,
766
+ updated_at TEXT NOT NULL
767
+ )
768
+ `);
750
769
  await client.executeMultiple(`
751
770
  CREATE TABLE IF NOT EXISTS conversations (
752
771
  id TEXT PRIMARY KEY,
@@ -1085,6 +1104,61 @@ var init_config = __esm({
1085
1104
  }
1086
1105
  });
1087
1106
 
1107
+ // src/lib/state-bus.ts
1108
+ var StateBus, orgBus;
1109
+ var init_state_bus = __esm({
1110
+ "src/lib/state-bus.ts"() {
1111
+ "use strict";
1112
+ StateBus = class {
1113
+ handlers = /* @__PURE__ */ new Map();
1114
+ globalHandlers = /* @__PURE__ */ new Set();
1115
+ /** Emit an event to all subscribers */
1116
+ emit(event) {
1117
+ const typeHandlers = this.handlers.get(event.type);
1118
+ if (typeHandlers) {
1119
+ for (const handler of typeHandlers) {
1120
+ try {
1121
+ handler(event);
1122
+ } catch {
1123
+ }
1124
+ }
1125
+ }
1126
+ for (const handler of this.globalHandlers) {
1127
+ try {
1128
+ handler(event);
1129
+ } catch {
1130
+ }
1131
+ }
1132
+ }
1133
+ /** Subscribe to a specific event type */
1134
+ on(type, handler) {
1135
+ if (!this.handlers.has(type)) {
1136
+ this.handlers.set(type, /* @__PURE__ */ new Set());
1137
+ }
1138
+ this.handlers.get(type).add(handler);
1139
+ }
1140
+ /** Subscribe to ALL events */
1141
+ onAny(handler) {
1142
+ this.globalHandlers.add(handler);
1143
+ }
1144
+ /** Unsubscribe from a specific event type */
1145
+ off(type, handler) {
1146
+ this.handlers.get(type)?.delete(handler);
1147
+ }
1148
+ /** Unsubscribe from ALL events */
1149
+ offAny(handler) {
1150
+ this.globalHandlers.delete(handler);
1151
+ }
1152
+ /** Remove all listeners */
1153
+ clear() {
1154
+ this.handlers.clear();
1155
+ this.globalHandlers.clear();
1156
+ }
1157
+ };
1158
+ orgBus = new StateBus();
1159
+ }
1160
+ });
1161
+
1088
1162
  // src/lib/shard-manager.ts
1089
1163
  var shard_manager_exports = {};
1090
1164
  __export(shard_manager_exports, {
@@ -1326,6 +1400,71 @@ var init_shard_manager = __esm({
1326
1400
  }
1327
1401
  });
1328
1402
 
1403
+ // src/lib/global-procedures.ts
1404
+ var global_procedures_exports = {};
1405
+ __export(global_procedures_exports, {
1406
+ deactivateGlobalProcedure: () => deactivateGlobalProcedure,
1407
+ getGlobalProceduresBlock: () => getGlobalProceduresBlock,
1408
+ loadGlobalProcedures: () => loadGlobalProcedures,
1409
+ storeGlobalProcedure: () => storeGlobalProcedure
1410
+ });
1411
+ import { randomUUID } from "crypto";
1412
+ async function loadGlobalProcedures() {
1413
+ const client = getClient();
1414
+ const result = await client.execute({
1415
+ sql: "SELECT * FROM global_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
1416
+ args: []
1417
+ });
1418
+ const procedures = result.rows;
1419
+ if (procedures.length > 0) {
1420
+ _cache = procedures.map((p) => `### ${p.title}
1421
+ ${p.content}`).join("\n\n");
1422
+ } else {
1423
+ _cache = "";
1424
+ }
1425
+ _cacheLoaded = true;
1426
+ return procedures;
1427
+ }
1428
+ function getGlobalProceduresBlock() {
1429
+ if (!_cacheLoaded) return "";
1430
+ if (!_cache) return "";
1431
+ return `## Organization-Wide Procedures (MANDATORY \u2014 supersedes all other rules)
1432
+
1433
+ ${_cache}
1434
+ `;
1435
+ }
1436
+ async function storeGlobalProcedure(input) {
1437
+ const id = randomUUID();
1438
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1439
+ const client = getClient();
1440
+ await client.execute({
1441
+ sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
1442
+ VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
1443
+ args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now, now]
1444
+ });
1445
+ await loadGlobalProcedures();
1446
+ return id;
1447
+ }
1448
+ async function deactivateGlobalProcedure(id) {
1449
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1450
+ const client = getClient();
1451
+ const result = await client.execute({
1452
+ sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE id = ?",
1453
+ args: [now, id]
1454
+ });
1455
+ await loadGlobalProcedures();
1456
+ return result.rowsAffected > 0;
1457
+ }
1458
+ var _cache, _cacheLoaded;
1459
+ var init_global_procedures = __esm({
1460
+ "src/lib/global-procedures.ts"() {
1461
+ "use strict";
1462
+ init_database();
1463
+ _cache = "";
1464
+ _cacheLoaded = false;
1465
+ }
1466
+ });
1467
+
1329
1468
  // src/lib/session-registry.ts
1330
1469
  import path4 from "path";
1331
1470
  import os3 from "os";
@@ -1411,7 +1550,7 @@ var init_employees = __esm({
1411
1550
 
1412
1551
  // src/lib/license.ts
1413
1552
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
1414
- import { randomUUID } from "crypto";
1553
+ import { randomUUID as randomUUID2 } from "crypto";
1415
1554
  import path7 from "path";
1416
1555
  import { jwtVerify, importSPKI } from "jose";
1417
1556
  var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
@@ -1513,6 +1652,7 @@ async function getMasterKey() {
1513
1652
 
1514
1653
  // src/lib/store.ts
1515
1654
  init_config();
1655
+ init_state_bus();
1516
1656
  var INIT_MAX_RETRIES = 3;
1517
1657
  var INIT_RETRY_DELAY_MS = 1e3;
1518
1658
  function isBusyError2(err) {
@@ -1583,6 +1723,11 @@ async function initStore(options) {
1583
1723
  "version-query"
1584
1724
  );
1585
1725
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
1726
+ try {
1727
+ const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
1728
+ await loadGlobalProcedures2();
1729
+ } catch {
1730
+ }
1586
1731
  }
1587
1732
 
1588
1733
  // src/lib/messaging.ts