@askexenow/exe-os 0.8.33 → 0.8.37

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 (89) hide show
  1. package/dist/bin/backfill-conversations.js +341 -349
  2. package/dist/bin/backfill-responses.js +81 -13
  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 +1737 -1117
  6. package/dist/bin/exe-assign.js +89 -19
  7. package/dist/bin/exe-boot.js +951 -101
  8. package/dist/bin/exe-call.js +61 -2
  9. package/dist/bin/exe-dispatch.js +61 -13
  10. package/dist/bin/exe-doctor.js +63 -3
  11. package/dist/bin/exe-export-behaviors.js +71 -3
  12. package/dist/bin/exe-forget.js +69 -4
  13. package/dist/bin/exe-gateway.js +178 -45
  14. package/dist/bin/exe-heartbeat.js +79 -14
  15. package/dist/bin/exe-kill.js +71 -3
  16. package/dist/bin/exe-launch-agent.js +148 -14
  17. package/dist/bin/exe-link.js +1437 -0
  18. package/dist/bin/exe-new-employee.js +98 -13
  19. package/dist/bin/exe-pending-messages.js +74 -8
  20. package/dist/bin/exe-pending-notifications.js +63 -3
  21. package/dist/bin/exe-pending-reviews.js +77 -11
  22. package/dist/bin/exe-rename.js +1287 -0
  23. package/dist/bin/exe-review.js +73 -5
  24. package/dist/bin/exe-search.js +88 -14
  25. package/dist/bin/exe-session-cleanup.js +102 -28
  26. package/dist/bin/exe-status.js +64 -4
  27. package/dist/bin/exe-team.js +64 -4
  28. package/dist/bin/git-sweep.js +80 -5
  29. package/dist/bin/graph-backfill.js +71 -3
  30. package/dist/bin/graph-export.js +71 -3
  31. package/dist/bin/install.js +38 -8
  32. package/dist/bin/scan-tasks.js +80 -5
  33. package/dist/bin/setup.js +128 -10
  34. package/dist/bin/shard-migrate.js +71 -3
  35. package/dist/bin/wiki-sync.js +71 -3
  36. package/dist/gateway/index.js +179 -46
  37. package/dist/hooks/bug-report-worker.js +254 -28
  38. package/dist/hooks/commit-complete.js +80 -5
  39. package/dist/hooks/error-recall.js +89 -15
  40. package/dist/hooks/exe-heartbeat-hook.js +1 -1
  41. package/dist/hooks/ingest-worker.js +185 -51
  42. package/dist/hooks/ingest.js +1 -1
  43. package/dist/hooks/instructions-loaded.js +81 -6
  44. package/dist/hooks/notification.js +81 -6
  45. package/dist/hooks/post-compact.js +81 -6
  46. package/dist/hooks/pre-compact.js +81 -6
  47. package/dist/hooks/pre-tool-use.js +423 -196
  48. package/dist/hooks/prompt-ingest-worker.js +91 -23
  49. package/dist/hooks/prompt-submit.js +159 -45
  50. package/dist/hooks/response-ingest-worker.js +96 -23
  51. package/dist/hooks/session-end.js +81 -6
  52. package/dist/hooks/session-start.js +89 -15
  53. package/dist/hooks/stop.js +81 -6
  54. package/dist/hooks/subagent-stop.js +81 -6
  55. package/dist/hooks/summary-worker.js +807 -55
  56. package/dist/index.js +198 -60
  57. package/dist/lib/cloud-sync.js +703 -18
  58. package/dist/lib/consolidation.js +4 -4
  59. package/dist/lib/database.js +64 -2
  60. package/dist/lib/device-registry.js +70 -3
  61. package/dist/lib/employee-templates.js +26 -0
  62. package/dist/lib/employees.js +34 -1
  63. package/dist/lib/exe-daemon.js +207 -74
  64. package/dist/lib/hybrid-search.js +88 -14
  65. package/dist/lib/identity-templates.js +51 -0
  66. package/dist/lib/identity.js +3 -3
  67. package/dist/lib/messaging.js +65 -17
  68. package/dist/lib/reminders.js +3 -3
  69. package/dist/lib/schedules.js +63 -3
  70. package/dist/lib/skill-learning.js +3 -3
  71. package/dist/lib/status-brief.js +63 -5
  72. package/dist/lib/store.js +73 -4
  73. package/dist/lib/task-router.js +4 -2
  74. package/dist/lib/tasks.js +95 -28
  75. package/dist/lib/tmux-routing.js +92 -23
  76. package/dist/mcp/server.js +800 -74
  77. package/dist/mcp/tools/complete-reminder.js +3 -3
  78. package/dist/mcp/tools/create-reminder.js +3 -3
  79. package/dist/mcp/tools/create-task.js +198 -31
  80. package/dist/mcp/tools/deactivate-behavior.js +4 -4
  81. package/dist/mcp/tools/list-reminders.js +3 -3
  82. package/dist/mcp/tools/list-tasks.js +19 -9
  83. package/dist/mcp/tools/send-message.js +69 -21
  84. package/dist/mcp/tools/update-task.js +28 -18
  85. package/dist/runtime/index.js +166 -28
  86. package/dist/tui/App.js +193 -40
  87. package/package.json +7 -3
  88. package/src/commands/exe/afk.md +116 -0
  89. package/src/commands/exe/rename.md +12 -0
@@ -19,19 +19,27 @@ var __copyProps = (to, from, except, desc) => {
19
19
  };
20
20
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
21
 
22
+ // src/lib/db-retry.ts
23
+ var init_db_retry = __esm({
24
+ "src/lib/db-retry.ts"() {
25
+ "use strict";
26
+ }
27
+ });
28
+
22
29
  // src/lib/database.ts
23
30
  import { createClient } from "@libsql/client";
24
31
  function getClient() {
25
- if (!_client) {
32
+ if (!_resilientClient) {
26
33
  throw new Error("Database client not initialized. Call initDatabase() first.");
27
34
  }
28
- return _client;
35
+ return _resilientClient;
29
36
  }
30
- var _client;
37
+ var _resilientClient;
31
38
  var init_database = __esm({
32
39
  "src/lib/database.ts"() {
33
40
  "use strict";
34
- _client = null;
41
+ init_db_retry();
42
+ _resilientClient = null;
35
43
  }
36
44
  });
37
45
 
@@ -432,7 +440,7 @@ var init_config = __esm({
432
440
 
433
441
  // src/lib/employees.ts
434
442
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
435
- import { existsSync as existsSync4, symlinkSync, readlinkSync } from "fs";
443
+ import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync4 } from "fs";
436
444
  import { execSync as execSync3 } from "child_process";
437
445
  import path4 from "path";
438
446
  var EMPLOYEES_PATH;
@@ -445,7 +453,7 @@ var init_employees = __esm({
445
453
  });
446
454
 
447
455
  // src/lib/license.ts
448
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
456
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
449
457
  import { randomUUID } from "crypto";
450
458
  import path5 from "path";
451
459
  import { jwtVerify, importSPKI } from "jose";
@@ -468,12 +476,12 @@ var init_license = __esm({
468
476
  });
469
477
 
470
478
  // src/lib/plan-limits.ts
471
- import { readFileSync as readFileSync5, existsSync as existsSync6 } from "fs";
479
+ import { readFileSync as readFileSync6, existsSync as existsSync6 } from "fs";
472
480
  import path6 from "path";
473
481
  function getLicenseSync() {
474
482
  try {
475
483
  if (!existsSync6(CACHE_PATH2)) return freeLicense();
476
- const raw = JSON.parse(readFileSync5(CACHE_PATH2, "utf8"));
484
+ const raw = JSON.parse(readFileSync6(CACHE_PATH2, "utf8"));
477
485
  if (!raw.token || typeof raw.token !== "string") return freeLicense();
478
486
  const parts = raw.token.split(".");
479
487
  if (parts.length !== 3) return freeLicense();
@@ -512,7 +520,7 @@ function assertEmployeeLimitSync(rosterPath) {
512
520
  let count = 0;
513
521
  try {
514
522
  if (existsSync6(filePath)) {
515
- const raw = readFileSync5(filePath, "utf8");
523
+ const raw = readFileSync6(filePath, "utf8");
516
524
  const employees = JSON.parse(raw);
517
525
  count = Array.isArray(employees) ? employees.length : 0;
518
526
  }
@@ -547,10 +555,46 @@ var init_plan_limits = __esm({
547
555
 
548
556
  // src/lib/tmux-routing.ts
549
557
  import { execFileSync as execFileSync2, execSync as execSync4 } from "child_process";
550
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync7, appendFileSync } from "fs";
558
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync7, appendFileSync } from "fs";
551
559
  import path7 from "path";
552
560
  import os4 from "os";
553
561
  import { fileURLToPath } from "url";
562
+ import { unlinkSync } from "fs";
563
+ function spawnLockPath(sessionName) {
564
+ return path7.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
565
+ }
566
+ function isProcessAlive(pid) {
567
+ try {
568
+ process.kill(pid, 0);
569
+ return true;
570
+ } catch {
571
+ return false;
572
+ }
573
+ }
574
+ function acquireSpawnLock(sessionName) {
575
+ if (!existsSync7(SPAWN_LOCK_DIR)) {
576
+ mkdirSync4(SPAWN_LOCK_DIR, { recursive: true });
577
+ }
578
+ const lockFile = spawnLockPath(sessionName);
579
+ if (existsSync7(lockFile)) {
580
+ try {
581
+ const lock = JSON.parse(readFileSync7(lockFile, "utf8"));
582
+ const age = Date.now() - lock.timestamp;
583
+ if (isProcessAlive(lock.pid) && age < 6e4) {
584
+ return false;
585
+ }
586
+ } catch {
587
+ }
588
+ }
589
+ writeFileSync4(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
590
+ return true;
591
+ }
592
+ function releaseSpawnLock(sessionName) {
593
+ try {
594
+ unlinkSync(spawnLockPath(sessionName));
595
+ } catch {
596
+ }
597
+ }
554
598
  function resolveBehaviorsExporterScript() {
555
599
  try {
556
600
  const thisFile = fileURLToPath(import.meta.url);
@@ -596,7 +640,7 @@ function extractRootExe(name) {
596
640
  }
597
641
  function getParentExe(sessionKey) {
598
642
  try {
599
- const data = JSON.parse(readFileSync6(path7.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
643
+ const data = JSON.parse(readFileSync7(path7.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
600
644
  return data.parentExe || null;
601
645
  } catch {
602
646
  return null;
@@ -620,17 +664,17 @@ function isEmployeeAlive(sessionName) {
620
664
  }
621
665
  function findFreeInstance(employeeName, exeSession, maxInstances = 10, isAlive = isEmployeeAlive) {
622
666
  const base = employeeSessionName(employeeName, exeSession);
623
- if (!isAlive(base)) return 0;
667
+ if (!isAlive(base) && acquireSpawnLock(base)) return 0;
624
668
  for (let i = 2; i <= maxInstances; i++) {
625
669
  const candidate = employeeSessionName(employeeName, exeSession, i);
626
- if (!isAlive(candidate)) return i;
670
+ if (!isAlive(candidate) && acquireSpawnLock(candidate)) return i;
627
671
  }
628
672
  return null;
629
673
  }
630
674
  function readDebounceState() {
631
675
  try {
632
676
  if (!existsSync7(DEBOUNCE_FILE)) return {};
633
- return JSON.parse(readFileSync6(DEBOUNCE_FILE, "utf8"));
677
+ return JSON.parse(readFileSync7(DEBOUNCE_FILE, "utf8"));
634
678
  } catch {
635
679
  return {};
636
680
  }
@@ -804,7 +848,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
804
848
  const claudeJsonPath = path7.join(os4.homedir(), ".claude.json");
805
849
  let claudeJson = {};
806
850
  try {
807
- claudeJson = JSON.parse(readFileSync6(claudeJsonPath, "utf8"));
851
+ claudeJson = JSON.parse(readFileSync7(claudeJsonPath, "utf8"));
808
852
  } catch {
809
853
  }
810
854
  if (!claudeJson.projects) claudeJson.projects = {};
@@ -822,7 +866,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
822
866
  const settingsPath = path7.join(projSettingsDir, "settings.json");
823
867
  let settings = {};
824
868
  try {
825
- settings = JSON.parse(readFileSync6(settingsPath, "utf8"));
869
+ settings = JSON.parse(readFileSync7(settingsPath, "utf8"));
826
870
  } catch {
827
871
  }
828
872
  const perms = settings.permissions ?? {};
@@ -935,6 +979,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
935
979
  command: spawnCommand
936
980
  });
937
981
  if (spawnResult.error) {
982
+ releaseSpawnLock(sessionName);
938
983
  return { sessionName, error: `tmux new-session failed: ${spawnResult.error}` };
939
984
  }
940
985
  transport.pipeLog(sessionName, logFile);
@@ -972,6 +1017,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
972
1017
  }
973
1018
  }
974
1019
  if (!booted) {
1020
+ releaseSpawnLock(sessionName);
975
1021
  return { sessionName, error: `${useExeAgent ? "exe-agent" : "claude"} did not boot within 15s` };
976
1022
  }
977
1023
  if (!useExeAgent) {
@@ -988,9 +1034,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
988
1034
  pid: 0,
989
1035
  registeredAt: (/* @__PURE__ */ new Date()).toISOString()
990
1036
  });
1037
+ releaseSpawnLock(sessionName);
991
1038
  return { sessionName };
992
1039
  }
993
- var SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
1040
+ var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
994
1041
  var init_tmux_routing = __esm({
995
1042
  "src/lib/tmux-routing.ts"() {
996
1043
  "use strict";
@@ -1002,6 +1049,7 @@ var init_tmux_routing = __esm({
1002
1049
  init_provider_table();
1003
1050
  init_intercom_queue();
1004
1051
  init_plan_limits();
1052
+ SPAWN_LOCK_DIR = path7.join(os4.homedir(), ".exe-os", "spawn-locks");
1005
1053
  SESSION_CACHE = path7.join(os4.homedir(), ".exe-os", "session-cache");
1006
1054
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
1007
1055
  INTERCOM_DEBOUNCE_MS = 3e4;
@@ -1158,7 +1206,7 @@ async function markFailed(messageId, reason) {
1158
1206
 
1159
1207
  // src/adapters/claude/active-agent.ts
1160
1208
  init_config();
1161
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, unlinkSync, readdirSync } from "fs";
1209
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, unlinkSync as unlinkSync2, readdirSync } from "fs";
1162
1210
  import { execSync as execSync5 } from "child_process";
1163
1211
  import path8 from "path";
1164
1212
 
@@ -1174,14 +1222,14 @@ function getMarkerPath() {
1174
1222
  function getActiveAgent() {
1175
1223
  try {
1176
1224
  const markerPath = getMarkerPath();
1177
- const raw = readFileSync7(markerPath, "utf8");
1225
+ const raw = readFileSync8(markerPath, "utf8");
1178
1226
  const data = JSON.parse(raw);
1179
1227
  if (data.agentId) {
1180
1228
  if (data.startedAt) {
1181
1229
  const age = Date.now() - new Date(data.startedAt).getTime();
1182
1230
  if (age > STALE_MS) {
1183
1231
  try {
1184
- unlinkSync(markerPath);
1232
+ unlinkSync2(markerPath);
1185
1233
  } catch {
1186
1234
  }
1187
1235
  } else {
@@ -1204,7 +1252,7 @@ function getActiveAgent() {
1204
1252
  "tmux display-message -p '#{session_name}' 2>/dev/null",
1205
1253
  { encoding: "utf8", timeout: 2e3 }
1206
1254
  ).trim();
1207
- const empMatch = sessionName.match(/^(\w+)-exe\d+$/);
1255
+ const empMatch = sessionName.match(/^([a-zA-Z]+)\d*-exe\d+$/);
1208
1256
  if (empMatch && empMatch[1] !== "exe") {
1209
1257
  return { agentId: empMatch[1], agentRole: "employee" };
1210
1258
  }
@@ -19,19 +19,27 @@ var __copyProps = (to, from, except, desc) => {
19
19
  };
20
20
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
21
 
22
+ // src/lib/db-retry.ts
23
+ var init_db_retry = __esm({
24
+ "src/lib/db-retry.ts"() {
25
+ "use strict";
26
+ }
27
+ });
28
+
22
29
  // src/lib/database.ts
23
30
  import { createClient } from "@libsql/client";
24
31
  function getClient() {
25
- if (!_client) {
32
+ if (!_resilientClient) {
26
33
  throw new Error("Database client not initialized. Call initDatabase() first.");
27
34
  }
28
- return _client;
35
+ return _resilientClient;
29
36
  }
30
- var _client;
37
+ var _resilientClient;
31
38
  var init_database = __esm({
32
39
  "src/lib/database.ts"() {
33
40
  "use strict";
34
- _client = null;
41
+ init_db_retry();
42
+ _resilientClient = null;
35
43
  }
36
44
  });
37
45
 
@@ -468,7 +476,7 @@ var init_tasks_crud = __esm({
468
476
 
469
477
  // src/lib/employees.ts
470
478
  import { readFile as readFile2, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
471
- import { existsSync as existsSync4, symlinkSync, readlinkSync } from "fs";
479
+ import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync4 } from "fs";
472
480
  import { execSync as execSync2 } from "child_process";
473
481
  import path4 from "path";
474
482
  var EMPLOYEES_PATH;
@@ -663,7 +671,7 @@ var init_provider_table = __esm({
663
671
  });
664
672
 
665
673
  // src/lib/intercom-queue.ts
666
- import { readFileSync as readFileSync4, writeFileSync, renameSync as renameSync2, existsSync as existsSync5, mkdirSync } from "fs";
674
+ import { readFileSync as readFileSync5, writeFileSync, renameSync as renameSync2, existsSync as existsSync5, mkdirSync } from "fs";
667
675
  import path6 from "path";
668
676
  import os4 from "os";
669
677
  function ensureDir() {
@@ -673,7 +681,7 @@ function ensureDir() {
673
681
  function readQueue() {
674
682
  try {
675
683
  if (!existsSync5(QUEUE_PATH)) return [];
676
- return JSON.parse(readFileSync4(QUEUE_PATH, "utf8"));
684
+ return JSON.parse(readFileSync5(QUEUE_PATH, "utf8"));
677
685
  } catch {
678
686
  return [];
679
687
  }
@@ -712,7 +720,7 @@ var init_intercom_queue = __esm({
712
720
  });
713
721
 
714
722
  // src/lib/license.ts
715
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
723
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
716
724
  import { randomUUID } from "crypto";
717
725
  import path7 from "path";
718
726
  import { jwtVerify, importSPKI } from "jose";
@@ -728,7 +736,7 @@ var init_license = __esm({
728
736
  });
729
737
 
730
738
  // src/lib/plan-limits.ts
731
- import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
739
+ import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
732
740
  import path8 from "path";
733
741
  var CACHE_PATH2;
734
742
  var init_plan_limits = __esm({
@@ -743,7 +751,7 @@ var init_plan_limits = __esm({
743
751
  });
744
752
 
745
753
  // src/lib/tmux-routing.ts
746
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync8, appendFileSync } from "fs";
754
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync8, appendFileSync } from "fs";
747
755
  import path9 from "path";
748
756
  import os5 from "os";
749
757
  import { fileURLToPath } from "url";
@@ -756,7 +764,7 @@ function extractRootExe(name) {
756
764
  }
757
765
  function getParentExe(sessionKey) {
758
766
  try {
759
- const data = JSON.parse(readFileSync7(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
767
+ const data = JSON.parse(readFileSync8(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
760
768
  return data.parentExe || null;
761
769
  } catch {
762
770
  return null;
@@ -764,7 +772,7 @@ function getParentExe(sessionKey) {
764
772
  }
765
773
  function getDispatchedBy(sessionKey) {
766
774
  try {
767
- const data = JSON.parse(readFileSync7(
775
+ const data = JSON.parse(readFileSync8(
768
776
  path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
769
777
  "utf8"
770
778
  ));
@@ -789,7 +797,7 @@ function resolveExeSession() {
789
797
  function readDebounceState() {
790
798
  try {
791
799
  if (!existsSync8(DEBOUNCE_FILE)) return {};
792
- return JSON.parse(readFileSync7(DEBOUNCE_FILE, "utf8"));
800
+ return JSON.parse(readFileSync8(DEBOUNCE_FILE, "utf8"));
793
801
  } catch {
794
802
  return {};
795
803
  }
@@ -909,7 +917,7 @@ function notifyParentExe(sessionKey) {
909
917
  }
910
918
  return true;
911
919
  }
912
- var SESSION_CACHE, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
920
+ var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
913
921
  var init_tmux_routing = __esm({
914
922
  "src/lib/tmux-routing.ts"() {
915
923
  "use strict";
@@ -921,6 +929,7 @@ var init_tmux_routing = __esm({
921
929
  init_provider_table();
922
930
  init_intercom_queue();
923
931
  init_plan_limits();
932
+ SPAWN_LOCK_DIR = path9.join(os5.homedir(), ".exe-os", "spawn-locks");
924
933
  SESSION_CACHE = path9.join(os5.homedir(), ".exe-os", "session-cache");
925
934
  INTERCOM_DEBOUNCE_MS = 3e4;
926
935
  INTERCOM_LOG2 = path9.join(os5.homedir(), ".exe-os", "intercom.log");
@@ -1103,6 +1112,7 @@ var init_tasks_notify = __esm({
1103
1112
  init_session_key();
1104
1113
  init_notifications();
1105
1114
  init_transport();
1115
+ init_employees();
1106
1116
  }
1107
1117
  });
1108
1118
 
@@ -1544,7 +1554,7 @@ __export(active_agent_exports, {
1544
1554
  getAllActiveAgents: () => getAllActiveAgents,
1545
1555
  writeActiveAgent: () => writeActiveAgent
1546
1556
  });
1547
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
1557
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
1548
1558
  import { execSync as execSync5 } from "child_process";
1549
1559
  import path13 from "path";
1550
1560
  function getMarkerPath() {
@@ -1569,7 +1579,7 @@ function clearActiveAgent() {
1569
1579
  function getActiveAgent() {
1570
1580
  try {
1571
1581
  const markerPath = getMarkerPath();
1572
- const raw = readFileSync8(markerPath, "utf8");
1582
+ const raw = readFileSync9(markerPath, "utf8");
1573
1583
  const data = JSON.parse(raw);
1574
1584
  if (data.agentId) {
1575
1585
  if (data.startedAt) {
@@ -1599,7 +1609,7 @@ function getActiveAgent() {
1599
1609
  "tmux display-message -p '#{session_name}' 2>/dev/null",
1600
1610
  { encoding: "utf8", timeout: 2e3 }
1601
1611
  ).trim();
1602
- const empMatch = sessionName.match(/^(\w+)-exe\d+$/);
1612
+ const empMatch = sessionName.match(/^([a-zA-Z]+)\d*-exe\d+$/);
1603
1613
  if (empMatch && empMatch[1] !== "exe") {
1604
1614
  return { agentId: empMatch[1], agentRole: "employee" };
1605
1615
  }
@@ -1622,7 +1632,7 @@ function getAllActiveAgents() {
1622
1632
  const key = file.slice("active-agent-".length, -".json".length);
1623
1633
  if (key === "undefined") continue;
1624
1634
  try {
1625
- const raw = readFileSync8(path13.join(CACHE_DIR, file), "utf8");
1635
+ const raw = readFileSync9(path13.join(CACHE_DIR, file), "utf8");
1626
1636
  const data = JSON.parse(raw);
1627
1637
  if (!data.agentId) continue;
1628
1638
  if (data.startedAt) {