@askexenow/exe-os 0.9.7 → 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 +657 -35
  5. package/dist/bin/cli.js +1388 -605
  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 +784 -153
  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 +692 -70
  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 +1053 -271
  17. package/dist/bin/exe-heartbeat.js +665 -43
  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 +834 -150
  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 +657 -35
  33. package/dist/bin/exe-team.js +635 -13
  34. package/dist/bin/git-sweep.js +720 -89
  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 +724 -93
  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 +1027 -245
  43. package/dist/hooks/bug-report-worker.js +891 -170
  44. package/dist/hooks/commit-complete.js +718 -87
  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 +840 -156
  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 +674 -43
  52. package/dist/hooks/pre-compact.js +718 -87
  53. package/dist/hooks/pre-tool-use.js +872 -125
  54. package/dist/hooks/prompt-ingest-worker.js +758 -83
  55. package/dist/hooks/prompt-submit.js +1060 -319
  56. package/dist/hooks/response-ingest-worker.js +758 -83
  57. package/dist/hooks/session-end.js +721 -90
  58. package/dist/hooks/session-start.js +1031 -207
  59. package/dist/hooks/stop.js +680 -49
  60. package/dist/hooks/subagent-stop.js +674 -43
  61. package/dist/hooks/summary-worker.js +816 -132
  62. package/dist/index.js +1015 -232
  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 +894 -162
  73. package/dist/lib/hybrid-search.js +771 -88
  74. package/dist/lib/identity.js +27 -7
  75. package/dist/lib/messaging.js +55 -28
  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 +98 -71
  82. package/dist/lib/tmux-routing.js +87 -60
  83. package/dist/lib/token-spend.js +26 -6
  84. package/dist/mcp/server.js +1784 -458
  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 +290 -164
  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 +195 -38
  91. package/dist/mcp/tools/send-message.js +58 -31
  92. package/dist/mcp/tools/update-task.js +75 -48
  93. package/dist/runtime/index.js +720 -89
  94. package/dist/tui/App.js +853 -123
  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;
@@ -593,10 +642,10 @@ var init_tmux_routing = __esm({
593
642
  init_intercom_queue();
594
643
  init_plan_limits();
595
644
  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");
599
- 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");
600
649
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
601
650
  }
602
651
  });
@@ -627,8 +676,8 @@ var init_task_scope = __esm({
627
676
 
628
677
  // src/lib/tasks-crud.ts
629
678
  import crypto2 from "crypto";
630
- import path10 from "path";
631
- import os7 from "os";
679
+ import path11 from "path";
680
+ import os8 from "os";
632
681
  import { execSync as execSync4 } from "child_process";
633
682
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
634
683
  import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
@@ -713,7 +762,7 @@ var init_tasks_crud = __esm({
713
762
  });
714
763
 
715
764
  // src/lib/tasks-review.ts
716
- import path11 from "path";
765
+ import path12 from "path";
717
766
  import { existsSync as existsSync10, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
718
767
  var init_tasks_review = __esm({
719
768
  "src/lib/tasks-review.ts"() {
@@ -729,7 +778,7 @@ var init_tasks_review = __esm({
729
778
  });
730
779
 
731
780
  // src/lib/tasks-chain.ts
732
- import path12 from "path";
781
+ import path13 from "path";
733
782
  import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
734
783
  var init_tasks_chain = __esm({
735
784
  "src/lib/tasks-chain.ts"() {
@@ -753,7 +802,7 @@ var init_tasks_notify = __esm({
753
802
  });
754
803
 
755
804
  // src/lib/tasks.ts
756
- import path13 from "path";
805
+ import path14 from "path";
757
806
  import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, unlinkSync as unlinkSync4 } from "fs";
758
807
  var init_tasks = __esm({
759
808
  "src/lib/tasks.ts"() {
@@ -774,7 +823,7 @@ var init_tasks = __esm({
774
823
 
775
824
  // src/lib/project-name.ts
776
825
  import { execSync as execSync5 } from "child_process";
777
- import path14 from "path";
826
+ import path15 from "path";
778
827
  function getProjectName(cwd) {
779
828
  const dir = cwd ?? process.cwd();
780
829
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -787,7 +836,7 @@ function getProjectName(cwd) {
787
836
  timeout: 2e3,
788
837
  stdio: ["pipe", "pipe", "pipe"]
789
838
  }).trim();
790
- repoRoot = path14.dirname(gitCommonDir);
839
+ repoRoot = path15.dirname(gitCommonDir);
791
840
  } catch {
792
841
  repoRoot = execSync5("git rev-parse --show-toplevel", {
793
842
  cwd: dir,
@@ -796,11 +845,11 @@ function getProjectName(cwd) {
796
845
  stdio: ["pipe", "pipe", "pipe"]
797
846
  }).trim();
798
847
  }
799
- _cached2 = path14.basename(repoRoot);
848
+ _cached2 = path15.basename(repoRoot);
800
849
  _cachedCwd = dir;
801
850
  return _cached2;
802
851
  } catch {
803
- _cached2 = path14.basename(dir);
852
+ _cached2 = path15.basename(dir);
804
853
  _cachedCwd = dir;
805
854
  return _cached2;
806
855
  }
@@ -818,12 +867,111 @@ var init_project_name = __esm({
818
867
  init_tasks();
819
868
  init_project_name();
820
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
821
969
  function registerListTasks(server) {
822
970
  server.registerTool(
823
971
  "list_tasks",
824
972
  {
825
973
  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.",
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.",
827
975
  inputSchema: {
828
976
  assigned_to: z.string().optional().describe("Filter by employee name"),
829
977
  status: z.enum(["open", "in_progress", "done", "blocked", "cancelled"]).optional().describe("Filter by status"),
@@ -833,7 +981,16 @@ function registerListTasks(server) {
833
981
  },
834
982
  async ({ assigned_to, status, project_name, priority }) => {
835
983
  try {
836
- 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
+ }
837
994
  const tasks = await listTasks({
838
995
  assignedTo: assigned_to,
839
996
  status,