@askexenow/exe-os 0.9.6 → 0.9.8

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 (95) hide show
  1. package/dist/bin/backfill-conversations.js +754 -79
  2. package/dist/bin/backfill-responses.js +752 -77
  3. package/dist/bin/backfill-vectors.js +752 -77
  4. package/dist/bin/cleanup-stale-review-tasks.js +668 -37
  5. package/dist/bin/cli.js +1399 -607
  6. package/dist/bin/exe-agent-config.js +123 -95
  7. package/dist/bin/exe-agent.js +41 -25
  8. package/dist/bin/exe-assign.js +732 -57
  9. package/dist/bin/exe-boot.js +795 -155
  10. package/dist/bin/exe-call.js +209 -138
  11. package/dist/bin/exe-cloud.js +35 -12
  12. package/dist/bin/exe-dispatch.js +703 -72
  13. package/dist/bin/exe-doctor.js +648 -26
  14. package/dist/bin/exe-export-behaviors.js +650 -20
  15. package/dist/bin/exe-forget.js +635 -13
  16. package/dist/bin/exe-gateway.js +1064 -273
  17. package/dist/bin/exe-heartbeat.js +676 -45
  18. package/dist/bin/exe-kill.js +646 -16
  19. package/dist/bin/exe-launch-agent.js +887 -97
  20. package/dist/bin/exe-link.js +658 -43
  21. package/dist/bin/exe-new-employee.js +378 -177
  22. package/dist/bin/exe-pending-messages.js +656 -34
  23. package/dist/bin/exe-pending-notifications.js +635 -13
  24. package/dist/bin/exe-pending-reviews.js +659 -37
  25. package/dist/bin/exe-rename.js +645 -30
  26. package/dist/bin/exe-review.js +635 -13
  27. package/dist/bin/exe-search.js +771 -88
  28. package/dist/bin/exe-session-cleanup.js +845 -152
  29. package/dist/bin/exe-settings.js +127 -91
  30. package/dist/bin/exe-start-codex.js +729 -94
  31. package/dist/bin/exe-start-opencode.js +717 -82
  32. package/dist/bin/exe-status.js +668 -37
  33. package/dist/bin/exe-team.js +635 -13
  34. package/dist/bin/git-sweep.js +731 -91
  35. package/dist/bin/graph-backfill.js +643 -13
  36. package/dist/bin/graph-export.js +646 -16
  37. package/dist/bin/install.js +596 -193
  38. package/dist/bin/scan-tasks.js +735 -95
  39. package/dist/bin/setup.js +1038 -210
  40. package/dist/bin/shard-migrate.js +645 -15
  41. package/dist/bin/wiki-sync.js +646 -16
  42. package/dist/gateway/index.js +1038 -247
  43. package/dist/hooks/bug-report-worker.js +902 -172
  44. package/dist/hooks/commit-complete.js +729 -89
  45. package/dist/hooks/error-recall.js +776 -93
  46. package/dist/hooks/exe-heartbeat-hook.js +85 -71
  47. package/dist/hooks/ingest-worker.js +851 -158
  48. package/dist/hooks/ingest.js +90 -73
  49. package/dist/hooks/instructions-loaded.js +669 -38
  50. package/dist/hooks/notification.js +661 -30
  51. package/dist/hooks/post-compact.js +685 -45
  52. package/dist/hooks/pre-compact.js +729 -89
  53. package/dist/hooks/pre-tool-use.js +883 -127
  54. package/dist/hooks/prompt-ingest-worker.js +758 -83
  55. package/dist/hooks/prompt-submit.js +1071 -321
  56. package/dist/hooks/response-ingest-worker.js +758 -83
  57. package/dist/hooks/session-end.js +732 -92
  58. package/dist/hooks/session-start.js +1042 -209
  59. package/dist/hooks/stop.js +691 -51
  60. package/dist/hooks/subagent-stop.js +685 -45
  61. package/dist/hooks/summary-worker.js +827 -134
  62. package/dist/index.js +1026 -234
  63. package/dist/lib/cloud-sync.js +663 -48
  64. package/dist/lib/consolidation.js +26 -3
  65. package/dist/lib/database.js +626 -18
  66. package/dist/lib/db.js +2261 -0
  67. package/dist/lib/device-registry.js +640 -25
  68. package/dist/lib/embedder.js +96 -43
  69. package/dist/lib/employee-templates.js +16 -0
  70. package/dist/lib/employees.js +259 -83
  71. package/dist/lib/exe-daemon-client.js +101 -63
  72. package/dist/lib/exe-daemon.js +905 -164
  73. package/dist/lib/hybrid-search.js +771 -88
  74. package/dist/lib/identity.js +27 -7
  75. package/dist/lib/messaging.js +66 -30
  76. package/dist/lib/reminders.js +21 -1
  77. package/dist/lib/schedules.js +636 -14
  78. package/dist/lib/skill-learning.js +21 -1
  79. package/dist/lib/store.js +643 -13
  80. package/dist/lib/task-router.js +82 -71
  81. package/dist/lib/tasks.js +109 -73
  82. package/dist/lib/tmux-routing.js +98 -62
  83. package/dist/lib/token-spend.js +26 -6
  84. package/dist/mcp/server.js +1807 -472
  85. package/dist/mcp/tools/complete-reminder.js +21 -1
  86. package/dist/mcp/tools/create-reminder.js +21 -1
  87. package/dist/mcp/tools/create-task.js +301 -166
  88. package/dist/mcp/tools/deactivate-behavior.js +24 -4
  89. package/dist/mcp/tools/list-reminders.js +21 -1
  90. package/dist/mcp/tools/list-tasks.js +206 -40
  91. package/dist/mcp/tools/send-message.js +69 -33
  92. package/dist/mcp/tools/update-task.js +86 -50
  93. package/dist/runtime/index.js +731 -91
  94. package/dist/tui/App.js +864 -125
  95. package/package.json +3 -2
@@ -143,14 +143,34 @@ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
143
143
  function getEmployee(employees, name) {
144
144
  return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
145
145
  }
146
+ var IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
147
+
148
+ // src/lib/database-adapter.ts
149
+ import os3 from "os";
150
+ import path3 from "path";
151
+ import { createRequire } from "module";
152
+ import { pathToFileURL } from "url";
153
+ var BOOLEAN_COLUMNS_BY_TABLE = {
154
+ memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
155
+ behaviors: /* @__PURE__ */ new Set(["active"]),
156
+ notifications: /* @__PURE__ */ new Set(["read"]),
157
+ users: /* @__PURE__ */ new Set(["has_personal_memory"])
158
+ };
159
+ var BOOLEAN_COLUMN_NAMES = new Set(
160
+ Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
161
+ );
146
162
 
147
163
  // src/lib/database.ts
148
164
  var _resilientClient = null;
149
165
  var _daemonClient = null;
166
+ var _adapterClient = null;
150
167
  function getClient() {
151
- if (!_resilientClient) {
168
+ if (!_adapterClient) {
152
169
  throw new Error("Database client not initialized. Call initDatabase() first.");
153
170
  }
171
+ if (process.env.DATABASE_URL) {
172
+ return _adapterClient;
173
+ }
154
174
  if (process.env.EXE_IS_DAEMON === "1") {
155
175
  return _resilientClient;
156
176
  }
@@ -174,7 +194,7 @@ async function deactivateBehavior(id) {
174
194
  init_config();
175
195
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync, unlinkSync as unlinkSync2, readdirSync } from "fs";
176
196
  import { execSync as execSync3 } from "child_process";
177
- import path3 from "path";
197
+ import path4 from "path";
178
198
 
179
199
  // src/lib/session-key.ts
180
200
  import { execSync as execSync2 } from "child_process";
@@ -239,7 +259,7 @@ function getSessionKey() {
239
259
  }
240
260
 
241
261
  // src/lib/active-agent.ts
242
- var CACHE_DIR = path3.join(EXE_AI_DIR, "session-cache");
262
+ var CACHE_DIR = path4.join(EXE_AI_DIR, "session-cache");
243
263
  var STALE_MS = 24 * 60 * 60 * 1e3;
244
264
  function isNameWithOptionalInstance(candidate, baseName) {
245
265
  if (candidate === baseName) return true;
@@ -284,7 +304,7 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
284
304
  return null;
285
305
  }
286
306
  function getMarkerPath() {
287
- return path3.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
307
+ return path4.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
288
308
  }
289
309
  function getActiveAgent() {
290
310
  try {
@@ -111,14 +111,34 @@ import { execSync } from "child_process";
111
111
  import path2 from "path";
112
112
  import os2 from "os";
113
113
  var EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
114
+ var IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
115
+
116
+ // src/lib/database-adapter.ts
117
+ import os3 from "os";
118
+ import path3 from "path";
119
+ import { createRequire } from "module";
120
+ import { pathToFileURL } from "url";
121
+ var BOOLEAN_COLUMNS_BY_TABLE = {
122
+ memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
123
+ behaviors: /* @__PURE__ */ new Set(["active"]),
124
+ notifications: /* @__PURE__ */ new Set(["read"]),
125
+ users: /* @__PURE__ */ new Set(["has_personal_memory"])
126
+ };
127
+ var BOOLEAN_COLUMN_NAMES = new Set(
128
+ Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
129
+ );
114
130
 
115
131
  // src/lib/database.ts
116
132
  var _resilientClient = null;
117
133
  var _daemonClient = null;
134
+ var _adapterClient = null;
118
135
  function getClient() {
119
- if (!_resilientClient) {
136
+ if (!_adapterClient) {
120
137
  throw new Error("Database client not initialized. Call initDatabase() first.");
121
138
  }
139
+ if (process.env.DATABASE_URL) {
140
+ return _adapterClient;
141
+ }
122
142
  if (process.env.EXE_IS_DAEMON === "1") {
123
143
  return _resilientClient;
124
144
  }
@@ -123,21 +123,68 @@ import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as r
123
123
  import { execSync } from "child_process";
124
124
  import path2 from "path";
125
125
  import os2 from "os";
126
- var EMPLOYEES_PATH;
126
+ function normalizeRole(role) {
127
+ return (role ?? "").trim().toLowerCase();
128
+ }
129
+ function isCoordinatorRole(role) {
130
+ return normalizeRole(role) === normalizeRole(COORDINATOR_ROLE);
131
+ }
132
+ function getCoordinatorEmployee(employees) {
133
+ return employees.find((e) => isCoordinatorRole(e.role));
134
+ }
135
+ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
136
+ if (!existsSync2(employeesPath)) return [];
137
+ try {
138
+ return JSON.parse(readFileSync2(employeesPath, "utf-8"));
139
+ } catch {
140
+ return [];
141
+ }
142
+ }
143
+ function getEmployee(employees, name) {
144
+ return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
145
+ }
146
+ var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, IDENTITY_DIR;
127
147
  var init_employees = __esm({
128
148
  "src/lib/employees.ts"() {
129
149
  "use strict";
130
150
  init_config();
131
151
  EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
152
+ DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
153
+ COORDINATOR_ROLE = "COO";
154
+ IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
155
+ }
156
+ });
157
+
158
+ // src/lib/database-adapter.ts
159
+ import os3 from "os";
160
+ import path3 from "path";
161
+ import { createRequire } from "module";
162
+ import { pathToFileURL } from "url";
163
+ var BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES;
164
+ var init_database_adapter = __esm({
165
+ "src/lib/database-adapter.ts"() {
166
+ "use strict";
167
+ BOOLEAN_COLUMNS_BY_TABLE = {
168
+ memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
169
+ behaviors: /* @__PURE__ */ new Set(["active"]),
170
+ notifications: /* @__PURE__ */ new Set(["read"]),
171
+ users: /* @__PURE__ */ new Set(["has_personal_memory"])
172
+ };
173
+ BOOLEAN_COLUMN_NAMES = new Set(
174
+ Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
175
+ );
132
176
  }
133
177
  });
134
178
 
135
179
  // src/lib/database.ts
136
180
  import { createClient } from "@libsql/client";
137
181
  function getClient() {
138
- if (!_resilientClient) {
182
+ if (!_adapterClient) {
139
183
  throw new Error("Database client not initialized. Call initDatabase() first.");
140
184
  }
185
+ if (process.env.DATABASE_URL) {
186
+ return _adapterClient;
187
+ }
141
188
  if (process.env.EXE_IS_DAEMON === "1") {
142
189
  return _resilientClient;
143
190
  }
@@ -146,21 +193,23 @@ function getClient() {
146
193
  }
147
194
  return _resilientClient;
148
195
  }
149
- var _resilientClient, _daemonClient;
196
+ var _resilientClient, _daemonClient, _adapterClient;
150
197
  var init_database = __esm({
151
198
  "src/lib/database.ts"() {
152
199
  "use strict";
153
200
  init_db_retry();
154
201
  init_employees();
202
+ init_database_adapter();
155
203
  _resilientClient = null;
156
204
  _daemonClient = null;
205
+ _adapterClient = null;
157
206
  }
158
207
  });
159
208
 
160
209
  // src/lib/notifications.ts
161
210
  import crypto from "crypto";
162
- import path3 from "path";
163
- import os3 from "os";
211
+ import path4 from "path";
212
+ import os4 from "os";
164
213
  import {
165
214
  readFileSync as readFileSync3,
166
215
  readdirSync,
@@ -231,13 +280,13 @@ var init_state_bus = __esm({
231
280
  });
232
281
 
233
282
  // src/lib/session-registry.ts
234
- import path4 from "path";
235
- import os4 from "os";
283
+ import path5 from "path";
284
+ import os5 from "os";
236
285
  var REGISTRY_PATH;
237
286
  var init_session_registry = __esm({
238
287
  "src/lib/session-registry.ts"() {
239
288
  "use strict";
240
- REGISTRY_PATH = path4.join(os4.homedir(), ".exe-os", "session-registry.json");
289
+ REGISTRY_PATH = path5.join(os5.homedir(), ".exe-os", "session-registry.json");
241
290
  }
242
291
  });
243
292
 
@@ -473,14 +522,14 @@ var init_runtime_table = __esm({
473
522
 
474
523
  // src/lib/agent-config.ts
475
524
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync4, mkdirSync } from "fs";
476
- import path5 from "path";
525
+ import path6 from "path";
477
526
  var AGENT_CONFIG_PATH, DEFAULT_MODELS;
478
527
  var init_agent_config = __esm({
479
528
  "src/lib/agent-config.ts"() {
480
529
  "use strict";
481
530
  init_config();
482
531
  init_runtime_table();
483
- AGENT_CONFIG_PATH = path5.join(EXE_AI_DIR, "agent-config.json");
532
+ AGENT_CONFIG_PATH = path6.join(EXE_AI_DIR, "agent-config.json");
484
533
  DEFAULT_MODELS = {
485
534
  claude: "claude-opus-4",
486
535
  codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
@@ -491,37 +540,37 @@ var init_agent_config = __esm({
491
540
 
492
541
  // src/lib/intercom-queue.ts
493
542
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
494
- import path6 from "path";
495
- import os5 from "os";
543
+ import path7 from "path";
544
+ import os6 from "os";
496
545
  var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
497
546
  var init_intercom_queue = __esm({
498
547
  "src/lib/intercom-queue.ts"() {
499
548
  "use strict";
500
- QUEUE_PATH = path6.join(os5.homedir(), ".exe-os", "intercom-queue.json");
549
+ QUEUE_PATH = path7.join(os6.homedir(), ".exe-os", "intercom-queue.json");
501
550
  TTL_MS = 60 * 60 * 1e3;
502
- INTERCOM_LOG = path6.join(os5.homedir(), ".exe-os", "intercom.log");
551
+ INTERCOM_LOG = path7.join(os6.homedir(), ".exe-os", "intercom.log");
503
552
  }
504
553
  });
505
554
 
506
555
  // src/lib/license.ts
507
556
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
508
557
  import { randomUUID } from "crypto";
509
- import path7 from "path";
558
+ import path8 from "path";
510
559
  import { jwtVerify, importSPKI } from "jose";
511
560
  var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
512
561
  var init_license = __esm({
513
562
  "src/lib/license.ts"() {
514
563
  "use strict";
515
564
  init_config();
516
- LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
517
- CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
518
- DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
565
+ LICENSE_PATH = path8.join(EXE_AI_DIR, "license.key");
566
+ CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
567
+ DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
519
568
  }
520
569
  });
521
570
 
522
571
  // src/lib/plan-limits.ts
523
572
  import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
524
- import path8 from "path";
573
+ import path9 from "path";
525
574
  var CACHE_PATH2;
526
575
  var init_plan_limits = __esm({
527
576
  "src/lib/plan-limits.ts"() {
@@ -530,14 +579,14 @@ var init_plan_limits = __esm({
530
579
  init_employees();
531
580
  init_license();
532
581
  init_config();
533
- CACHE_PATH2 = path8.join(EXE_AI_DIR, "license-cache.json");
582
+ CACHE_PATH2 = path9.join(EXE_AI_DIR, "license-cache.json");
534
583
  }
535
584
  });
536
585
 
537
586
  // src/lib/tmux-routing.ts
538
587
  import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync8, appendFileSync, readdirSync as readdirSync2 } from "fs";
539
- import path9 from "path";
540
- import os6 from "os";
588
+ import path10 from "path";
589
+ import os7 from "os";
541
590
  import { fileURLToPath } from "url";
542
591
  function getMySession() {
543
592
  return getTransport().getMySession();
@@ -550,7 +599,7 @@ function extractRootExe(name) {
550
599
  }
551
600
  function getParentExe(sessionKey) {
552
601
  try {
553
- const data = JSON.parse(readFileSync8(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
602
+ const data = JSON.parse(readFileSync8(path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
554
603
  return data.parentExe || null;
555
604
  } catch {
556
605
  return null;
@@ -559,15 +608,24 @@ function getParentExe(sessionKey) {
559
608
  function resolveExeSession() {
560
609
  const mySession = getMySession();
561
610
  if (!mySession) return null;
611
+ const fromSessionName = extractRootExe(mySession);
562
612
  try {
563
613
  const key = getSessionKey();
564
614
  const parentExe = getParentExe(key);
565
615
  if (parentExe) {
566
- return extractRootExe(parentExe) ?? parentExe;
616
+ const fromCache = extractRootExe(parentExe) ?? parentExe;
617
+ if (fromSessionName && fromCache !== fromSessionName) {
618
+ process.stderr.write(
619
+ `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
620
+ `
621
+ );
622
+ return fromSessionName;
623
+ }
624
+ return fromCache;
567
625
  }
568
626
  } catch {
569
627
  }
570
- return extractRootExe(mySession) ?? mySession;
628
+ return fromSessionName ?? mySession;
571
629
  }
572
630
  var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
573
631
  var init_tmux_routing = __esm({
@@ -584,10 +642,10 @@ var init_tmux_routing = __esm({
584
642
  init_intercom_queue();
585
643
  init_plan_limits();
586
644
  init_employees();
587
- SPAWN_LOCK_DIR = path9.join(os6.homedir(), ".exe-os", "spawn-locks");
588
- SESSION_CACHE = path9.join(os6.homedir(), ".exe-os", "session-cache");
589
- INTERCOM_LOG2 = path9.join(os6.homedir(), ".exe-os", "intercom.log");
590
- DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
645
+ SPAWN_LOCK_DIR = path10.join(os7.homedir(), ".exe-os", "spawn-locks");
646
+ SESSION_CACHE = path10.join(os7.homedir(), ".exe-os", "session-cache");
647
+ INTERCOM_LOG2 = path10.join(os7.homedir(), ".exe-os", "intercom.log");
648
+ DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
591
649
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
592
650
  }
593
651
  });
@@ -618,8 +676,8 @@ var init_task_scope = __esm({
618
676
 
619
677
  // src/lib/tasks-crud.ts
620
678
  import crypto2 from "crypto";
621
- import path10 from "path";
622
- import os7 from "os";
679
+ import path11 from "path";
680
+ import os8 from "os";
623
681
  import { execSync as execSync4 } from "child_process";
624
682
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
625
683
  import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
@@ -704,7 +762,7 @@ var init_tasks_crud = __esm({
704
762
  });
705
763
 
706
764
  // src/lib/tasks-review.ts
707
- import path11 from "path";
765
+ import path12 from "path";
708
766
  import { existsSync as existsSync10, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
709
767
  var init_tasks_review = __esm({
710
768
  "src/lib/tasks-review.ts"() {
@@ -720,7 +778,7 @@ var init_tasks_review = __esm({
720
778
  });
721
779
 
722
780
  // src/lib/tasks-chain.ts
723
- import path12 from "path";
781
+ import path13 from "path";
724
782
  import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
725
783
  var init_tasks_chain = __esm({
726
784
  "src/lib/tasks-chain.ts"() {
@@ -744,7 +802,7 @@ var init_tasks_notify = __esm({
744
802
  });
745
803
 
746
804
  // src/lib/tasks.ts
747
- import path13 from "path";
805
+ import path14 from "path";
748
806
  import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, unlinkSync as unlinkSync4 } from "fs";
749
807
  var init_tasks = __esm({
750
808
  "src/lib/tasks.ts"() {
@@ -765,7 +823,7 @@ var init_tasks = __esm({
765
823
 
766
824
  // src/lib/project-name.ts
767
825
  import { execSync as execSync5 } from "child_process";
768
- import path14 from "path";
826
+ import path15 from "path";
769
827
  function getProjectName(cwd) {
770
828
  const dir = cwd ?? process.cwd();
771
829
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -778,7 +836,7 @@ function getProjectName(cwd) {
778
836
  timeout: 2e3,
779
837
  stdio: ["pipe", "pipe", "pipe"]
780
838
  }).trim();
781
- repoRoot = path14.dirname(gitCommonDir);
839
+ repoRoot = path15.dirname(gitCommonDir);
782
840
  } catch {
783
841
  repoRoot = execSync5("git rev-parse --show-toplevel", {
784
842
  cwd: dir,
@@ -787,11 +845,11 @@ function getProjectName(cwd) {
787
845
  stdio: ["pipe", "pipe", "pipe"]
788
846
  }).trim();
789
847
  }
790
- _cached2 = path14.basename(repoRoot);
848
+ _cached2 = path15.basename(repoRoot);
791
849
  _cachedCwd = dir;
792
850
  return _cached2;
793
851
  } catch {
794
- _cached2 = path14.basename(dir);
852
+ _cached2 = path15.basename(dir);
795
853
  _cachedCwd = dir;
796
854
  return _cached2;
797
855
  }
@@ -809,12 +867,111 @@ var init_project_name = __esm({
809
867
  init_tasks();
810
868
  init_project_name();
811
869
  import { z } from "zod";
870
+
871
+ // src/lib/active-agent.ts
872
+ init_config();
873
+ init_session_key();
874
+ init_employees();
875
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, unlinkSync as unlinkSync5, readdirSync as readdirSync4 } from "fs";
876
+ import { execSync as execSync6 } from "child_process";
877
+ import path16 from "path";
878
+ var CACHE_DIR = path16.join(EXE_AI_DIR, "session-cache");
879
+ var STALE_MS = 24 * 60 * 60 * 1e3;
880
+ function isNameWithOptionalInstance(candidate, baseName) {
881
+ if (candidate === baseName) return true;
882
+ if (!candidate.startsWith(baseName)) return false;
883
+ return /^\d+$/.test(candidate.slice(baseName.length));
884
+ }
885
+ function resolveEmployeeFromSessionPrefix(prefix, employees) {
886
+ const sorted = [...employees].sort((a, b) => b.name.length - a.name.length);
887
+ for (const employee of sorted) {
888
+ if (isNameWithOptionalInstance(prefix, employee.name)) {
889
+ return { agentId: employee.name, agentRole: employee.role };
890
+ }
891
+ }
892
+ return null;
893
+ }
894
+ function resolveActiveAgentFromTmuxSession(sessionName) {
895
+ const employees = loadEmployeesSync();
896
+ const coordinator = getCoordinatorEmployee(employees);
897
+ const coordinatorName = coordinator?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
898
+ if (isNameWithOptionalInstance(sessionName, coordinatorName)) {
899
+ return {
900
+ agentId: coordinatorName,
901
+ agentRole: coordinator?.role ?? "COO"
902
+ };
903
+ }
904
+ if (isNameWithOptionalInstance(sessionName, DEFAULT_COORDINATOR_TEMPLATE_NAME)) {
905
+ return {
906
+ agentId: coordinator?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME,
907
+ agentRole: coordinator?.role ?? "COO"
908
+ };
909
+ }
910
+ if (sessionName.includes("-")) {
911
+ const prefix = sessionName.split("-")[0] ?? "";
912
+ const employee = resolveEmployeeFromSessionPrefix(prefix, employees);
913
+ if (employee) return employee;
914
+ const legacy = prefix.match(/^([a-zA-Z]+)\d*$/);
915
+ if (legacy?.[1] && legacy[1] !== DEFAULT_COORDINATOR_TEMPLATE_NAME) {
916
+ const emp = getEmployee(employees, legacy[1]);
917
+ return { agentId: emp?.name ?? legacy[1], agentRole: emp?.role ?? "employee" };
918
+ }
919
+ }
920
+ return null;
921
+ }
922
+ function getMarkerPath() {
923
+ return path16.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
924
+ }
925
+ function getActiveAgent() {
926
+ try {
927
+ const markerPath = getMarkerPath();
928
+ const raw = readFileSync10(markerPath, "utf8");
929
+ const data = JSON.parse(raw);
930
+ if (data.agentId) {
931
+ if (data.startedAt) {
932
+ const age = Date.now() - new Date(data.startedAt).getTime();
933
+ if (age > STALE_MS) {
934
+ try {
935
+ unlinkSync5(markerPath);
936
+ } catch {
937
+ }
938
+ } else {
939
+ return {
940
+ agentId: data.agentId,
941
+ agentRole: data.agentRole || "employee"
942
+ };
943
+ }
944
+ } else {
945
+ return {
946
+ agentId: data.agentId,
947
+ agentRole: data.agentRole || "employee"
948
+ };
949
+ }
950
+ }
951
+ } catch {
952
+ }
953
+ try {
954
+ const sessionName = execSync6(
955
+ "tmux display-message -p '#{session_name}' 2>/dev/null",
956
+ { encoding: "utf8", timeout: 2e3 }
957
+ ).trim();
958
+ const resolved = resolveActiveAgentFromTmuxSession(sessionName);
959
+ if (resolved) return resolved;
960
+ } catch {
961
+ }
962
+ return {
963
+ agentId: process.env.AGENT_ID || "default",
964
+ agentRole: process.env.AGENT_ROLE || "employee"
965
+ };
966
+ }
967
+
968
+ // src/mcp/tools/list-tasks.ts
812
969
  function registerListTasks(server) {
813
970
  server.registerTool(
814
971
  "list_tasks",
815
972
  {
816
973
  title: "List Tasks",
817
- description: "Query tasks by assignee, status, project, or priority. Defaults to current project. Pass project_name='all' to see all projects.",
974
+ 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.",
818
975
  inputSchema: {
819
976
  assigned_to: z.string().optional().describe("Filter by employee name"),
820
977
  status: z.enum(["open", "in_progress", "done", "blocked", "cancelled"]).optional().describe("Filter by status"),
@@ -824,7 +981,16 @@ function registerListTasks(server) {
824
981
  },
825
982
  async ({ assigned_to, status, project_name, priority }) => {
826
983
  try {
827
- const resolvedProject = project_name === "all" ? void 0 : project_name ?? getProjectName();
984
+ let resolvedProject;
985
+ if (project_name === "all") {
986
+ resolvedProject = void 0;
987
+ } else if (project_name) {
988
+ resolvedProject = project_name;
989
+ } else {
990
+ const { agentId } = getActiveAgent();
991
+ const queryingSelf = !assigned_to || assigned_to === agentId;
992
+ resolvedProject = queryingSelf ? void 0 : getProjectName();
993
+ }
828
994
  const tasks = await listTasks({
829
995
  assignedTo: assigned_to,
830
996
  status,