@askexenow/exe-os 0.8.40 → 0.8.42

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 (78) 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 +1376 -659
  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 +2549 -1784
  9. package/dist/bin/exe-call.js +39 -1
  10. package/dist/bin/exe-cloud.js +12 -2
  11. package/dist/bin/exe-dispatch.js +39 -2
  12. package/dist/bin/exe-doctor.js +791 -634
  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 +2501 -1846
  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 +44 -12
  20. package/dist/bin/exe-new-employee.js +6 -2
  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 +176 -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 +157 -4
  27. package/dist/bin/exe-session-cleanup.js +2487 -403
  28. package/dist/bin/exe-settings.js +2 -1
  29. package/dist/bin/exe-status.js +474 -317
  30. package/dist/bin/exe-team.js +474 -317
  31. package/dist/bin/git-sweep.js +2691 -151
  32. package/dist/bin/graph-backfill.js +794 -637
  33. package/dist/bin/graph-export.js +798 -641
  34. package/dist/bin/scan-tasks.js +2951 -44
  35. package/dist/bin/setup.js +50 -26
  36. package/dist/bin/shard-migrate.js +792 -637
  37. package/dist/bin/wiki-sync.js +794 -637
  38. package/dist/gateway/index.js +2542 -1887
  39. package/dist/hooks/bug-report-worker.js +2118 -576
  40. package/dist/hooks/commit-complete.js +2690 -150
  41. package/dist/hooks/error-recall.js +157 -4
  42. package/dist/hooks/ingest-worker.js +1455 -803
  43. package/dist/hooks/instructions-loaded.js +151 -0
  44. package/dist/hooks/notification.js +153 -2
  45. package/dist/hooks/post-compact.js +164 -0
  46. package/dist/hooks/pre-compact.js +3073 -101
  47. package/dist/hooks/pre-tool-use.js +151 -0
  48. package/dist/hooks/prompt-ingest-worker.js +1670 -1509
  49. package/dist/hooks/prompt-submit.js +2650 -1074
  50. package/dist/hooks/response-ingest-worker.js +154 -6
  51. package/dist/hooks/session-end.js +153 -2
  52. package/dist/hooks/session-start.js +157 -4
  53. package/dist/hooks/stop.js +151 -0
  54. package/dist/hooks/subagent-stop.js +155 -2
  55. package/dist/hooks/summary-worker.js +190 -21
  56. package/dist/index.js +326 -102
  57. package/dist/lib/cloud-sync.js +31 -10
  58. package/dist/lib/config.js +2 -0
  59. package/dist/lib/consolidation.js +69 -2
  60. package/dist/lib/database.js +19 -0
  61. package/dist/lib/device-registry.js +19 -0
  62. package/dist/lib/embedder.js +3 -1
  63. package/dist/lib/employee-templates.js +20 -1
  64. package/dist/lib/exe-daemon.js +285 -18
  65. package/dist/lib/hybrid-search.js +157 -4
  66. package/dist/lib/messaging.js +39 -2
  67. package/dist/lib/schedules.js +792 -637
  68. package/dist/lib/store.js +796 -636
  69. package/dist/lib/tasks.js +1485 -918
  70. package/dist/lib/tmux-routing.js +194 -10
  71. package/dist/mcp/server.js +1643 -924
  72. package/dist/mcp/tools/create-task.js +2283 -829
  73. package/dist/mcp/tools/list-tasks.js +2788 -159
  74. package/dist/mcp/tools/send-message.js +39 -2
  75. package/dist/mcp/tools/update-task.js +79 -0
  76. package/dist/runtime/index.js +280 -68
  77. package/dist/tui/App.js +1485 -645
  78. package/package.json +3 -2
@@ -631,8 +631,28 @@ function getMySession() {
631
631
  return getTransport().getMySession();
632
632
  }
633
633
  function employeeSessionName(employee, exeSession, instance) {
634
+ if (!/^exe\d+$/.test(exeSession)) {
635
+ const root = extractRootExe(exeSession);
636
+ if (root) {
637
+ process.stderr.write(
638
+ `[tmux-routing] WARN: exeSession="${exeSession}" is not a root exe session, using "${root}" instead
639
+ `
640
+ );
641
+ exeSession = root;
642
+ } else {
643
+ throw new Error(
644
+ `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1"), not an agent session`
645
+ );
646
+ }
647
+ }
634
648
  const suffix = instance != null && instance > 0 ? String(instance) : "";
635
- return `${employee}${suffix}-${exeSession}`;
649
+ const name = `${employee}${suffix}-${exeSession}`;
650
+ if (!VALID_SESSION_NAME.test(name)) {
651
+ throw new Error(
652
+ `Invalid session name "${name}" \u2014 must match {agent}-exe{N} or {agent}{instance}-exe{N}`
653
+ );
654
+ }
655
+ return name;
636
656
  }
637
657
  function extractRootExe(name) {
638
658
  const match = name.match(/(exe\d+)$/);
@@ -791,6 +811,22 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
791
811
  error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
792
812
  };
793
813
  }
814
+ if (!/^exe\d+$/.test(exeSession)) {
815
+ const root = extractRootExe(exeSession);
816
+ if (root) {
817
+ process.stderr.write(
818
+ `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root exe). Auto-correcting to "${root}".
819
+ `
820
+ );
821
+ exeSession = root;
822
+ } else {
823
+ return {
824
+ status: "failed",
825
+ sessionName: "",
826
+ error: `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1")`
827
+ };
828
+ }
829
+ }
794
830
  let effectiveInstance = opts?.instance;
795
831
  if (effectiveInstance === void 0 && opts?.autoInstance) {
796
832
  const free = findFreeInstance(
@@ -1037,7 +1073,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
1037
1073
  releaseSpawnLock(sessionName);
1038
1074
  return { sessionName };
1039
1075
  }
1040
- var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
1076
+ var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, VALID_SESSION_NAME, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
1041
1077
  var init_tmux_routing = __esm({
1042
1078
  "src/lib/tmux-routing.ts"() {
1043
1079
  "use strict";
@@ -1052,6 +1088,7 @@ var init_tmux_routing = __esm({
1052
1088
  SPAWN_LOCK_DIR = path7.join(os4.homedir(), ".exe-os", "spawn-locks");
1053
1089
  SESSION_CACHE = path7.join(os4.homedir(), ".exe-os", "session-cache");
1054
1090
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
1091
+ VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
1055
1092
  INTERCOM_DEBOUNCE_MS = 3e4;
1056
1093
  INTERCOM_LOG2 = path7.join(os4.homedir(), ".exe-os", "intercom.log");
1057
1094
  DEBOUNCE_FILE = path7.join(SESSION_CACHE, "intercom-debounce.json");
@@ -284,6 +284,61 @@ var init_notifications = __esm({
284
284
  }
285
285
  });
286
286
 
287
+ // src/lib/state-bus.ts
288
+ var StateBus, orgBus;
289
+ var init_state_bus = __esm({
290
+ "src/lib/state-bus.ts"() {
291
+ "use strict";
292
+ StateBus = class {
293
+ handlers = /* @__PURE__ */ new Map();
294
+ globalHandlers = /* @__PURE__ */ new Set();
295
+ /** Emit an event to all subscribers */
296
+ emit(event) {
297
+ const typeHandlers = this.handlers.get(event.type);
298
+ if (typeHandlers) {
299
+ for (const handler of typeHandlers) {
300
+ try {
301
+ handler(event);
302
+ } catch {
303
+ }
304
+ }
305
+ }
306
+ for (const handler of this.globalHandlers) {
307
+ try {
308
+ handler(event);
309
+ } catch {
310
+ }
311
+ }
312
+ }
313
+ /** Subscribe to a specific event type */
314
+ on(type, handler) {
315
+ if (!this.handlers.has(type)) {
316
+ this.handlers.set(type, /* @__PURE__ */ new Set());
317
+ }
318
+ this.handlers.get(type).add(handler);
319
+ }
320
+ /** Subscribe to ALL events */
321
+ onAny(handler) {
322
+ this.globalHandlers.add(handler);
323
+ }
324
+ /** Unsubscribe from a specific event type */
325
+ off(type, handler) {
326
+ this.handlers.get(type)?.delete(handler);
327
+ }
328
+ /** Unsubscribe from ALL events */
329
+ offAny(handler) {
330
+ this.globalHandlers.delete(handler);
331
+ }
332
+ /** Remove all listeners */
333
+ clear() {
334
+ this.handlers.clear();
335
+ this.globalHandlers.clear();
336
+ }
337
+ };
338
+ orgBus = new StateBus();
339
+ }
340
+ });
341
+
287
342
  // src/lib/tasks-crud.ts
288
343
  import crypto2 from "crypto";
289
344
  import path3 from "path";
@@ -1007,6 +1062,7 @@ var init_tasks_review = __esm({
1007
1062
  init_tasks_crud();
1008
1063
  init_tmux_routing();
1009
1064
  init_session_key();
1065
+ init_state_bus();
1010
1066
  }
1011
1067
  });
1012
1068
 
@@ -1461,6 +1517,21 @@ async function updateTask(input) {
1461
1517
  });
1462
1518
  } catch {
1463
1519
  }
1520
+ try {
1521
+ const client = getClient();
1522
+ const cascaded = await client.execute({
1523
+ sql: `UPDATE tasks SET status = 'done', updated_at = ?
1524
+ WHERE parent_task_id = ? AND status = 'needs_review'`,
1525
+ args: [now, taskId]
1526
+ });
1527
+ if (cascaded.rowsAffected > 0) {
1528
+ process.stderr.write(
1529
+ `[cascade] Closed ${cascaded.rowsAffected} orphaned review task(s) for parent ${taskId}
1530
+ `
1531
+ );
1532
+ }
1533
+ } catch {
1534
+ }
1464
1535
  }
1465
1536
  const isTerminal = input.status === "done" || input.status === "needs_review";
1466
1537
  if (isTerminal) {
@@ -1474,6 +1545,13 @@ async function updateTask(input) {
1474
1545
  await cascadeUnblock(taskId, input.baseDir, now);
1475
1546
  } catch {
1476
1547
  }
1548
+ orgBus.emit({
1549
+ type: "task_completed",
1550
+ taskId,
1551
+ employee: String(row.assigned_to),
1552
+ result: input.result ?? "",
1553
+ timestamp: now
1554
+ });
1477
1555
  if (row.parent_task_id) {
1478
1556
  try {
1479
1557
  await checkSubtaskCompletion(String(row.parent_task_id), String(row.project_name));
@@ -1528,6 +1606,7 @@ var init_tasks = __esm({
1528
1606
  init_database();
1529
1607
  init_config();
1530
1608
  init_notifications();
1609
+ init_state_bus();
1531
1610
  init_tasks_crud();
1532
1611
  init_tasks_review();
1533
1612
  init_tasks_crud();