@askexenow/exe-os 0.9.7 → 0.9.9

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 (101) hide show
  1. package/dist/bin/backfill-conversations.js +953 -105
  2. package/dist/bin/backfill-responses.js +952 -104
  3. package/dist/bin/backfill-vectors.js +956 -108
  4. package/dist/bin/cleanup-stale-review-tasks.js +802 -58
  5. package/dist/bin/cli.js +2292 -1070
  6. package/dist/bin/exe-agent-config.js +157 -101
  7. package/dist/bin/exe-agent.js +55 -29
  8. package/dist/bin/exe-assign.js +940 -92
  9. package/dist/bin/exe-boot.js +1424 -442
  10. package/dist/bin/exe-call.js +240 -141
  11. package/dist/bin/exe-cloud.js +198 -70
  12. package/dist/bin/exe-dispatch.js +951 -192
  13. package/dist/bin/exe-doctor.js +791 -51
  14. package/dist/bin/exe-export-behaviors.js +790 -42
  15. package/dist/bin/exe-forget.js +771 -31
  16. package/dist/bin/exe-gateway.js +1592 -521
  17. package/dist/bin/exe-heartbeat.js +850 -109
  18. package/dist/bin/exe-kill.js +783 -35
  19. package/dist/bin/exe-launch-agent.js +1030 -107
  20. package/dist/bin/exe-link.js +916 -110
  21. package/dist/bin/exe-new-employee.js +526 -217
  22. package/dist/bin/exe-pending-messages.js +1046 -62
  23. package/dist/bin/exe-pending-notifications.js +1318 -111
  24. package/dist/bin/exe-pending-reviews.js +1040 -72
  25. package/dist/bin/exe-rename.js +772 -59
  26. package/dist/bin/exe-review.js +772 -32
  27. package/dist/bin/exe-search.js +982 -128
  28. package/dist/bin/exe-session-cleanup.js +1180 -306
  29. package/dist/bin/exe-settings.js +185 -105
  30. package/dist/bin/exe-start-codex.js +886 -132
  31. package/dist/bin/exe-start-opencode.js +873 -119
  32. package/dist/bin/exe-status.js +803 -59
  33. package/dist/bin/exe-team.js +772 -32
  34. package/dist/bin/git-sweep.js +1046 -223
  35. package/dist/bin/graph-backfill.js +779 -31
  36. package/dist/bin/graph-export.js +785 -37
  37. package/dist/bin/install.js +632 -200
  38. package/dist/bin/scan-tasks.js +1055 -232
  39. package/dist/bin/setup.js +1419 -320
  40. package/dist/bin/shard-migrate.js +783 -35
  41. package/dist/bin/update.js +138 -49
  42. package/dist/bin/wiki-sync.js +782 -34
  43. package/dist/gateway/index.js +1444 -449
  44. package/dist/hooks/bug-report-worker.js +1141 -269
  45. package/dist/hooks/codex-stop-task-finalizer.js +4678 -0
  46. package/dist/hooks/commit-complete.js +1044 -221
  47. package/dist/hooks/error-recall.js +989 -135
  48. package/dist/hooks/exe-heartbeat-hook.js +99 -75
  49. package/dist/hooks/ingest-worker.js +4176 -3226
  50. package/dist/hooks/ingest.js +920 -168
  51. package/dist/hooks/instructions-loaded.js +874 -70
  52. package/dist/hooks/notification.js +860 -56
  53. package/dist/hooks/post-compact.js +881 -73
  54. package/dist/hooks/pre-compact.js +1050 -227
  55. package/dist/hooks/pre-tool-use.js +1084 -159
  56. package/dist/hooks/prompt-ingest-worker.js +1089 -164
  57. package/dist/hooks/prompt-submit.js +1469 -515
  58. package/dist/hooks/response-ingest-worker.js +1104 -179
  59. package/dist/hooks/session-end.js +1085 -251
  60. package/dist/hooks/session-start.js +1241 -231
  61. package/dist/hooks/stop.js +935 -109
  62. package/dist/hooks/subagent-stop.js +881 -73
  63. package/dist/hooks/summary-worker.js +1323 -307
  64. package/dist/index.js +1449 -452
  65. package/dist/lib/agent-config.js +28 -6
  66. package/dist/lib/cloud-sync.js +909 -115
  67. package/dist/lib/config.js +30 -10
  68. package/dist/lib/consolidation.js +42 -9
  69. package/dist/lib/database.js +739 -33
  70. package/dist/lib/db-daemon-client.js +73 -19
  71. package/dist/lib/db.js +2359 -0
  72. package/dist/lib/device-registry.js +760 -47
  73. package/dist/lib/embedder.js +201 -73
  74. package/dist/lib/employee-templates.js +30 -4
  75. package/dist/lib/employees.js +290 -86
  76. package/dist/lib/exe-daemon-client.js +187 -83
  77. package/dist/lib/exe-daemon.js +1696 -616
  78. package/dist/lib/hybrid-search.js +982 -128
  79. package/dist/lib/identity.js +43 -13
  80. package/dist/lib/license.js +133 -48
  81. package/dist/lib/messaging.js +167 -80
  82. package/dist/lib/reminders.js +35 -5
  83. package/dist/lib/schedules.js +772 -32
  84. package/dist/lib/skill-learning.js +54 -7
  85. package/dist/lib/store.js +779 -31
  86. package/dist/lib/task-router.js +94 -73
  87. package/dist/lib/tasks.js +298 -225
  88. package/dist/lib/tmux-routing.js +246 -172
  89. package/dist/lib/token-spend.js +52 -14
  90. package/dist/mcp/server.js +2893 -850
  91. package/dist/mcp/tools/complete-reminder.js +35 -5
  92. package/dist/mcp/tools/create-reminder.js +35 -5
  93. package/dist/mcp/tools/create-task.js +507 -323
  94. package/dist/mcp/tools/deactivate-behavior.js +40 -10
  95. package/dist/mcp/tools/list-reminders.js +35 -5
  96. package/dist/mcp/tools/list-tasks.js +277 -104
  97. package/dist/mcp/tools/send-message.js +129 -56
  98. package/dist/mcp/tools/update-task.js +1864 -188
  99. package/dist/runtime/index.js +1083 -259
  100. package/dist/tui/App.js +1501 -434
  101. package/package.json +3 -2
@@ -26,9 +26,18 @@ var init_db_retry = __esm({
26
26
  }
27
27
  });
28
28
 
29
+ // src/lib/secure-files.ts
30
+ import { chmodSync, existsSync, mkdirSync } from "fs";
31
+ import { chmod, mkdir } from "fs/promises";
32
+ var init_secure_files = __esm({
33
+ "src/lib/secure-files.ts"() {
34
+ "use strict";
35
+ }
36
+ });
37
+
29
38
  // src/lib/config.ts
30
- import { readFile, writeFile, mkdir, chmod } from "fs/promises";
31
- import { readFileSync, existsSync, renameSync } from "fs";
39
+ import { readFile, writeFile } from "fs/promises";
40
+ import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
32
41
  import path from "path";
33
42
  import os from "os";
34
43
  function resolveDataDir() {
@@ -36,7 +45,7 @@ function resolveDataDir() {
36
45
  if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
37
46
  const newDir = path.join(os.homedir(), ".exe-os");
38
47
  const legacyDir = path.join(os.homedir(), ".exe-mem");
39
- if (!existsSync(newDir) && existsSync(legacyDir)) {
48
+ if (!existsSync2(newDir) && existsSync2(legacyDir)) {
40
49
  try {
41
50
  renameSync(legacyDir, newDir);
42
51
  process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
@@ -51,6 +60,7 @@ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CON
51
60
  var init_config = __esm({
52
61
  "src/lib/config.ts"() {
53
62
  "use strict";
63
+ init_secure_files();
54
64
  EXE_AI_DIR = resolveDataDir();
55
65
  DB_PATH = path.join(EXE_AI_DIR, "memories.db");
56
66
  MODELS_DIR = path.join(EXE_AI_DIR, "models");
@@ -119,25 +129,72 @@ var init_config = __esm({
119
129
 
120
130
  // src/lib/employees.ts
121
131
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
122
- import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
132
+ import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
123
133
  import { execSync } from "child_process";
124
134
  import path2 from "path";
125
135
  import os2 from "os";
126
- var EMPLOYEES_PATH;
136
+ function normalizeRole(role) {
137
+ return (role ?? "").trim().toLowerCase();
138
+ }
139
+ function isCoordinatorRole(role) {
140
+ return normalizeRole(role) === normalizeRole(COORDINATOR_ROLE);
141
+ }
142
+ function getCoordinatorEmployee(employees) {
143
+ return employees.find((e) => isCoordinatorRole(e.role));
144
+ }
145
+ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
146
+ if (!existsSync3(employeesPath)) return [];
147
+ try {
148
+ return JSON.parse(readFileSync2(employeesPath, "utf-8"));
149
+ } catch {
150
+ return [];
151
+ }
152
+ }
153
+ function getEmployee(employees, name) {
154
+ return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
155
+ }
156
+ var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, IDENTITY_DIR;
127
157
  var init_employees = __esm({
128
158
  "src/lib/employees.ts"() {
129
159
  "use strict";
130
160
  init_config();
131
161
  EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
162
+ DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
163
+ COORDINATOR_ROLE = "COO";
164
+ IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
165
+ }
166
+ });
167
+
168
+ // src/lib/database-adapter.ts
169
+ import os3 from "os";
170
+ import path3 from "path";
171
+ import { createRequire } from "module";
172
+ import { pathToFileURL } from "url";
173
+ var BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES;
174
+ var init_database_adapter = __esm({
175
+ "src/lib/database-adapter.ts"() {
176
+ "use strict";
177
+ BOOLEAN_COLUMNS_BY_TABLE = {
178
+ memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
179
+ behaviors: /* @__PURE__ */ new Set(["active"]),
180
+ notifications: /* @__PURE__ */ new Set(["read"]),
181
+ users: /* @__PURE__ */ new Set(["has_personal_memory"])
182
+ };
183
+ BOOLEAN_COLUMN_NAMES = new Set(
184
+ Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
185
+ );
132
186
  }
133
187
  });
134
188
 
135
189
  // src/lib/database.ts
136
190
  import { createClient } from "@libsql/client";
137
191
  function getClient() {
138
- if (!_resilientClient) {
192
+ if (!_adapterClient) {
139
193
  throw new Error("Database client not initialized. Call initDatabase() first.");
140
194
  }
195
+ if (process.env.DATABASE_URL) {
196
+ return _adapterClient;
197
+ }
141
198
  if (process.env.EXE_IS_DAEMON === "1") {
142
199
  return _resilientClient;
143
200
  }
@@ -146,87 +203,16 @@ function getClient() {
146
203
  }
147
204
  return _resilientClient;
148
205
  }
149
- var _resilientClient, _daemonClient;
206
+ var _resilientClient, _daemonClient, _adapterClient;
150
207
  var init_database = __esm({
151
208
  "src/lib/database.ts"() {
152
209
  "use strict";
153
210
  init_db_retry();
154
211
  init_employees();
212
+ init_database_adapter();
155
213
  _resilientClient = null;
156
214
  _daemonClient = null;
157
- }
158
- });
159
-
160
- // src/lib/notifications.ts
161
- import crypto from "crypto";
162
- import path3 from "path";
163
- import os3 from "os";
164
- import {
165
- readFileSync as readFileSync3,
166
- readdirSync,
167
- unlinkSync as unlinkSync2,
168
- existsSync as existsSync3,
169
- rmdirSync
170
- } from "fs";
171
- var init_notifications = __esm({
172
- "src/lib/notifications.ts"() {
173
- "use strict";
174
- init_database();
175
- }
176
- });
177
-
178
- // src/lib/state-bus.ts
179
- var StateBus, orgBus;
180
- var init_state_bus = __esm({
181
- "src/lib/state-bus.ts"() {
182
- "use strict";
183
- StateBus = class {
184
- handlers = /* @__PURE__ */ new Map();
185
- globalHandlers = /* @__PURE__ */ new Set();
186
- /** Emit an event to all subscribers */
187
- emit(event) {
188
- const typeHandlers = this.handlers.get(event.type);
189
- if (typeHandlers) {
190
- for (const handler of typeHandlers) {
191
- try {
192
- handler(event);
193
- } catch {
194
- }
195
- }
196
- }
197
- for (const handler of this.globalHandlers) {
198
- try {
199
- handler(event);
200
- } catch {
201
- }
202
- }
203
- }
204
- /** Subscribe to a specific event type */
205
- on(type, handler) {
206
- if (!this.handlers.has(type)) {
207
- this.handlers.set(type, /* @__PURE__ */ new Set());
208
- }
209
- this.handlers.get(type).add(handler);
210
- }
211
- /** Subscribe to ALL events */
212
- onAny(handler) {
213
- this.globalHandlers.add(handler);
214
- }
215
- /** Unsubscribe from a specific event type */
216
- off(type, handler) {
217
- this.handlers.get(type)?.delete(handler);
218
- }
219
- /** Unsubscribe from ALL events */
220
- offAny(handler) {
221
- this.globalHandlers.delete(handler);
222
- }
223
- /** Remove all listeners */
224
- clear() {
225
- this.handlers.clear();
226
- this.globalHandlers.clear();
227
- }
228
- };
229
- orgBus = new StateBus();
215
+ _adapterClient = null;
230
216
  }
231
217
  });
232
218
 
@@ -472,7 +458,7 @@ var init_runtime_table = __esm({
472
458
  });
473
459
 
474
460
  // src/lib/agent-config.ts
475
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync4, mkdirSync } from "fs";
461
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync4 } from "fs";
476
462
  import path5 from "path";
477
463
  var AGENT_CONFIG_PATH, DEFAULT_MODELS;
478
464
  var init_agent_config = __esm({
@@ -480,6 +466,7 @@ var init_agent_config = __esm({
480
466
  "use strict";
481
467
  init_config();
482
468
  init_runtime_table();
469
+ init_secure_files();
483
470
  AGENT_CONFIG_PATH = path5.join(EXE_AI_DIR, "agent-config.json");
484
471
  DEFAULT_MODELS = {
485
472
  claude: "claude-opus-4",
@@ -490,7 +477,7 @@ var init_agent_config = __esm({
490
477
  });
491
478
 
492
479
  // src/lib/intercom-queue.ts
493
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
480
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
494
481
  import path6 from "path";
495
482
  import os5 from "os";
496
483
  var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
@@ -504,8 +491,11 @@ var init_intercom_queue = __esm({
504
491
  });
505
492
 
506
493
  // src/lib/license.ts
507
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
494
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
508
495
  import { randomUUID } from "crypto";
496
+ import { createRequire as createRequire2 } from "module";
497
+ import { pathToFileURL as pathToFileURL2 } from "url";
498
+ import os6 from "os";
509
499
  import path7 from "path";
510
500
  import { jwtVerify, importSPKI } from "jose";
511
501
  var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
@@ -520,7 +510,7 @@ var init_license = __esm({
520
510
  });
521
511
 
522
512
  // src/lib/plan-limits.ts
523
- import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
513
+ import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
524
514
  import path8 from "path";
525
515
  var CACHE_PATH2;
526
516
  var init_plan_limits = __esm({
@@ -535,9 +525,9 @@ var init_plan_limits = __esm({
535
525
  });
536
526
 
537
527
  // src/lib/tmux-routing.ts
538
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync8, appendFileSync, readdirSync as readdirSync2 } from "fs";
528
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync8, appendFileSync, readdirSync } from "fs";
539
529
  import path9 from "path";
540
- import os6 from "os";
530
+ import os7 from "os";
541
531
  import { fileURLToPath } from "url";
542
532
  function getMySession() {
543
533
  return getTransport().getMySession();
@@ -550,7 +540,7 @@ function extractRootExe(name) {
550
540
  }
551
541
  function getParentExe(sessionKey) {
552
542
  try {
553
- const data = JSON.parse(readFileSync8(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
543
+ const data = JSON.parse(readFileSync7(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
554
544
  return data.parentExe || null;
555
545
  } catch {
556
546
  return null;
@@ -593,9 +583,9 @@ var init_tmux_routing = __esm({
593
583
  init_intercom_queue();
594
584
  init_plan_limits();
595
585
  init_employees();
596
- SPAWN_LOCK_DIR = path9.join(os6.homedir(), ".exe-os", "spawn-locks");
597
- SESSION_CACHE = path9.join(os6.homedir(), ".exe-os", "session-cache");
598
- INTERCOM_LOG2 = path9.join(os6.homedir(), ".exe-os", "intercom.log");
586
+ SPAWN_LOCK_DIR = path9.join(os7.homedir(), ".exe-os", "spawn-locks");
587
+ SESSION_CACHE = path9.join(os7.homedir(), ".exe-os", "session-cache");
588
+ INTERCOM_LOG2 = path9.join(os7.homedir(), ".exe-os", "intercom.log");
599
589
  DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
600
590
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
601
591
  }
@@ -625,13 +615,87 @@ var init_task_scope = __esm({
625
615
  }
626
616
  });
627
617
 
618
+ // src/lib/notifications.ts
619
+ import crypto from "crypto";
620
+ import path10 from "path";
621
+ import os8 from "os";
622
+ import {
623
+ readFileSync as readFileSync8,
624
+ readdirSync as readdirSync2,
625
+ unlinkSync as unlinkSync2,
626
+ existsSync as existsSync9,
627
+ rmdirSync
628
+ } from "fs";
629
+ var init_notifications = __esm({
630
+ "src/lib/notifications.ts"() {
631
+ "use strict";
632
+ init_database();
633
+ init_task_scope();
634
+ }
635
+ });
636
+
637
+ // src/lib/state-bus.ts
638
+ var StateBus, orgBus;
639
+ var init_state_bus = __esm({
640
+ "src/lib/state-bus.ts"() {
641
+ "use strict";
642
+ StateBus = class {
643
+ handlers = /* @__PURE__ */ new Map();
644
+ globalHandlers = /* @__PURE__ */ new Set();
645
+ /** Emit an event to all subscribers */
646
+ emit(event) {
647
+ const typeHandlers = this.handlers.get(event.type);
648
+ if (typeHandlers) {
649
+ for (const handler of typeHandlers) {
650
+ try {
651
+ handler(event);
652
+ } catch {
653
+ }
654
+ }
655
+ }
656
+ for (const handler of this.globalHandlers) {
657
+ try {
658
+ handler(event);
659
+ } catch {
660
+ }
661
+ }
662
+ }
663
+ /** Subscribe to a specific event type */
664
+ on(type, handler) {
665
+ if (!this.handlers.has(type)) {
666
+ this.handlers.set(type, /* @__PURE__ */ new Set());
667
+ }
668
+ this.handlers.get(type).add(handler);
669
+ }
670
+ /** Subscribe to ALL events */
671
+ onAny(handler) {
672
+ this.globalHandlers.add(handler);
673
+ }
674
+ /** Unsubscribe from a specific event type */
675
+ off(type, handler) {
676
+ this.handlers.get(type)?.delete(handler);
677
+ }
678
+ /** Unsubscribe from ALL events */
679
+ offAny(handler) {
680
+ this.globalHandlers.delete(handler);
681
+ }
682
+ /** Remove all listeners */
683
+ clear() {
684
+ this.handlers.clear();
685
+ this.globalHandlers.clear();
686
+ }
687
+ };
688
+ orgBus = new StateBus();
689
+ }
690
+ });
691
+
628
692
  // src/lib/tasks-crud.ts
629
693
  import crypto2 from "crypto";
630
- import path10 from "path";
631
- import os7 from "os";
694
+ import path11 from "path";
695
+ import os9 from "os";
632
696
  import { execSync as execSync4 } from "child_process";
633
697
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
634
- import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
698
+ import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
635
699
  function buildKeywordIndex() {
636
700
  const idx = /* @__PURE__ */ new Map();
637
701
  for (const [role, keywords] of Object.entries(LANE_KEYWORDS)) {
@@ -713,8 +777,8 @@ var init_tasks_crud = __esm({
713
777
  });
714
778
 
715
779
  // src/lib/tasks-review.ts
716
- import path11 from "path";
717
- import { existsSync as existsSync10, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
780
+ import path12 from "path";
781
+ import { existsSync as existsSync11, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
718
782
  var init_tasks_review = __esm({
719
783
  "src/lib/tasks-review.ts"() {
720
784
  "use strict";
@@ -725,11 +789,12 @@ var init_tasks_review = __esm({
725
789
  init_tmux_routing();
726
790
  init_session_key();
727
791
  init_state_bus();
792
+ init_task_scope();
728
793
  }
729
794
  });
730
795
 
731
796
  // src/lib/tasks-chain.ts
732
- import path12 from "path";
797
+ import path13 from "path";
733
798
  import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
734
799
  var init_tasks_chain = __esm({
735
800
  "src/lib/tasks-chain.ts"() {
@@ -753,7 +818,7 @@ var init_tasks_notify = __esm({
753
818
  });
754
819
 
755
820
  // src/lib/tasks.ts
756
- import path13 from "path";
821
+ import path14 from "path";
757
822
  import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, unlinkSync as unlinkSync4 } from "fs";
758
823
  var init_tasks = __esm({
759
824
  "src/lib/tasks.ts"() {
@@ -774,7 +839,7 @@ var init_tasks = __esm({
774
839
 
775
840
  // src/lib/project-name.ts
776
841
  import { execSync as execSync5 } from "child_process";
777
- import path14 from "path";
842
+ import path15 from "path";
778
843
  function getProjectName(cwd) {
779
844
  const dir = cwd ?? process.cwd();
780
845
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -787,7 +852,7 @@ function getProjectName(cwd) {
787
852
  timeout: 2e3,
788
853
  stdio: ["pipe", "pipe", "pipe"]
789
854
  }).trim();
790
- repoRoot = path14.dirname(gitCommonDir);
855
+ repoRoot = path15.dirname(gitCommonDir);
791
856
  } catch {
792
857
  repoRoot = execSync5("git rev-parse --show-toplevel", {
793
858
  cwd: dir,
@@ -796,11 +861,11 @@ function getProjectName(cwd) {
796
861
  stdio: ["pipe", "pipe", "pipe"]
797
862
  }).trim();
798
863
  }
799
- _cached2 = path14.basename(repoRoot);
864
+ _cached2 = path15.basename(repoRoot);
800
865
  _cachedCwd = dir;
801
866
  return _cached2;
802
867
  } catch {
803
- _cached2 = path14.basename(dir);
868
+ _cached2 = path15.basename(dir);
804
869
  _cachedCwd = dir;
805
870
  return _cached2;
806
871
  }
@@ -818,22 +883,130 @@ var init_project_name = __esm({
818
883
  init_tasks();
819
884
  init_project_name();
820
885
  import { z } from "zod";
886
+
887
+ // src/lib/active-agent.ts
888
+ init_config();
889
+ init_session_key();
890
+ init_employees();
891
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, unlinkSync as unlinkSync5, readdirSync as readdirSync4 } from "fs";
892
+ import { execSync as execSync6 } from "child_process";
893
+ import path16 from "path";
894
+ var CACHE_DIR = path16.join(EXE_AI_DIR, "session-cache");
895
+ var STALE_MS = 24 * 60 * 60 * 1e3;
896
+ function isNameWithOptionalInstance(candidate, baseName) {
897
+ if (candidate === baseName) return true;
898
+ if (!candidate.startsWith(baseName)) return false;
899
+ return /^\d+$/.test(candidate.slice(baseName.length));
900
+ }
901
+ function resolveEmployeeFromSessionPrefix(prefix, employees) {
902
+ const sorted = [...employees].sort((a, b) => b.name.length - a.name.length);
903
+ for (const employee of sorted) {
904
+ if (isNameWithOptionalInstance(prefix, employee.name)) {
905
+ return { agentId: employee.name, agentRole: employee.role };
906
+ }
907
+ }
908
+ return null;
909
+ }
910
+ function resolveActiveAgentFromTmuxSession(sessionName) {
911
+ const employees = loadEmployeesSync();
912
+ const coordinator = getCoordinatorEmployee(employees);
913
+ const coordinatorName = coordinator?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
914
+ if (isNameWithOptionalInstance(sessionName, coordinatorName)) {
915
+ return {
916
+ agentId: coordinatorName,
917
+ agentRole: coordinator?.role ?? "COO"
918
+ };
919
+ }
920
+ if (isNameWithOptionalInstance(sessionName, DEFAULT_COORDINATOR_TEMPLATE_NAME)) {
921
+ return {
922
+ agentId: coordinator?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME,
923
+ agentRole: coordinator?.role ?? "COO"
924
+ };
925
+ }
926
+ if (sessionName.includes("-")) {
927
+ const prefix = sessionName.split("-")[0] ?? "";
928
+ const employee = resolveEmployeeFromSessionPrefix(prefix, employees);
929
+ if (employee) return employee;
930
+ const legacy = prefix.match(/^([a-zA-Z]+)\d*$/);
931
+ if (legacy?.[1] && legacy[1] !== DEFAULT_COORDINATOR_TEMPLATE_NAME) {
932
+ const emp = getEmployee(employees, legacy[1]);
933
+ return { agentId: emp?.name ?? legacy[1], agentRole: emp?.role ?? "employee" };
934
+ }
935
+ }
936
+ return null;
937
+ }
938
+ function getMarkerPath() {
939
+ return path16.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
940
+ }
941
+ function getActiveAgent() {
942
+ try {
943
+ const markerPath = getMarkerPath();
944
+ const raw = readFileSync10(markerPath, "utf8");
945
+ const data = JSON.parse(raw);
946
+ if (data.agentId) {
947
+ if (data.startedAt) {
948
+ const age = Date.now() - new Date(data.startedAt).getTime();
949
+ if (age > STALE_MS) {
950
+ try {
951
+ unlinkSync5(markerPath);
952
+ } catch {
953
+ }
954
+ } else {
955
+ return {
956
+ agentId: data.agentId,
957
+ agentRole: data.agentRole || "employee"
958
+ };
959
+ }
960
+ } else {
961
+ return {
962
+ agentId: data.agentId,
963
+ agentRole: data.agentRole || "employee"
964
+ };
965
+ }
966
+ }
967
+ } catch {
968
+ }
969
+ try {
970
+ const sessionName = execSync6(
971
+ "tmux display-message -p '#{session_name}' 2>/dev/null",
972
+ { encoding: "utf8", timeout: 2e3 }
973
+ ).trim();
974
+ const resolved = resolveActiveAgentFromTmuxSession(sessionName);
975
+ if (resolved) return resolved;
976
+ } catch {
977
+ }
978
+ return {
979
+ agentId: process.env.AGENT_ID || "default",
980
+ agentRole: process.env.AGENT_ROLE || "employee"
981
+ };
982
+ }
983
+
984
+ // src/mcp/tools/list-tasks.ts
821
985
  function registerListTasks(server) {
822
986
  server.registerTool(
823
987
  "list_tasks",
824
988
  {
825
989
  title: "List Tasks",
826
- description: "Query tasks by assignee, status, project, or priority. Defaults to current project. Pass project_name='all' to see all projects.",
990
+ description: "Query tasks by assignee, status, project, or priority. Defaults to current project. Pass project_name='all' for all projects. When querying your own tasks, project filter is skipped automatically.",
827
991
  inputSchema: {
828
992
  assigned_to: z.string().optional().describe("Filter by employee name"),
829
- status: z.enum(["open", "in_progress", "done", "blocked", "cancelled"]).optional().describe("Filter by status"),
993
+ status: z.enum(["open", "in_progress", "done", "needs_review", "blocked", "cancelled", "closed"]).optional().describe("Filter by status. Default: active tasks only (excludes closed/cancelled)"),
830
994
  project_name: z.string().optional().describe("Project name. Defaults to current project. Pass 'all' for all projects."),
831
995
  priority: z.enum(["p0", "p1", "p2"]).optional().describe("Filter by priority")
832
996
  }
833
997
  },
834
998
  async ({ assigned_to, status, project_name, priority }) => {
835
999
  try {
836
- const resolvedProject = project_name === "all" ? void 0 : project_name ?? getProjectName();
1000
+ let resolvedProject;
1001
+ if (project_name === "all") {
1002
+ resolvedProject = void 0;
1003
+ } else if (project_name) {
1004
+ resolvedProject = project_name;
1005
+ } else {
1006
+ const { agentId } = getActiveAgent();
1007
+ const queryingSelf = !assigned_to || assigned_to === agentId;
1008
+ resolvedProject = queryingSelf ? void 0 : getProjectName();
1009
+ }
837
1010
  const tasks = await listTasks({
838
1011
  assignedTo: assigned_to,
839
1012
  status,