@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,7 +129,7 @@ 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";
@@ -136,7 +146,7 @@ function getCoordinatorName(employees = loadEmployeesSync()) {
136
146
  return getCoordinatorEmployee(employees)?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
137
147
  }
138
148
  function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
139
- if (!existsSync2(employeesPath)) return [];
149
+ if (!existsSync3(employeesPath)) return [];
140
150
  try {
141
151
  return JSON.parse(readFileSync2(employeesPath, "utf-8"));
142
152
  } catch {
@@ -154,7 +164,7 @@ function baseAgentName(name, employees) {
154
164
  if (getEmployee(roster, base)) return base;
155
165
  return name;
156
166
  }
157
- var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE;
167
+ var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, IDENTITY_DIR;
158
168
  var init_employees = __esm({
159
169
  "src/lib/employees.ts"() {
160
170
  "use strict";
@@ -162,15 +172,40 @@ var init_employees = __esm({
162
172
  EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
163
173
  DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
164
174
  COORDINATOR_ROLE = "COO";
175
+ IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
176
+ }
177
+ });
178
+
179
+ // src/lib/database-adapter.ts
180
+ import os3 from "os";
181
+ import path3 from "path";
182
+ import { createRequire } from "module";
183
+ import { pathToFileURL } from "url";
184
+ var BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES;
185
+ var init_database_adapter = __esm({
186
+ "src/lib/database-adapter.ts"() {
187
+ "use strict";
188
+ BOOLEAN_COLUMNS_BY_TABLE = {
189
+ memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
190
+ behaviors: /* @__PURE__ */ new Set(["active"]),
191
+ notifications: /* @__PURE__ */ new Set(["read"]),
192
+ users: /* @__PURE__ */ new Set(["has_personal_memory"])
193
+ };
194
+ BOOLEAN_COLUMN_NAMES = new Set(
195
+ Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
196
+ );
165
197
  }
166
198
  });
167
199
 
168
200
  // src/lib/database.ts
169
201
  import { createClient } from "@libsql/client";
170
202
  function getClient() {
171
- if (!_resilientClient) {
203
+ if (!_adapterClient) {
172
204
  throw new Error("Database client not initialized. Call initDatabase() first.");
173
205
  }
206
+ if (process.env.DATABASE_URL) {
207
+ return _adapterClient;
208
+ }
174
209
  if (process.env.EXE_IS_DAEMON === "1") {
175
210
  return _resilientClient;
176
211
  }
@@ -179,25 +214,27 @@ function getClient() {
179
214
  }
180
215
  return _resilientClient;
181
216
  }
182
- var _resilientClient, _daemonClient;
217
+ var _resilientClient, _daemonClient, _adapterClient;
183
218
  var init_database = __esm({
184
219
  "src/lib/database.ts"() {
185
220
  "use strict";
186
221
  init_db_retry();
187
222
  init_employees();
223
+ init_database_adapter();
188
224
  _resilientClient = null;
189
225
  _daemonClient = null;
226
+ _adapterClient = null;
190
227
  }
191
228
  });
192
229
 
193
230
  // src/lib/session-registry.ts
194
- import path3 from "path";
195
- import os3 from "os";
231
+ import path4 from "path";
232
+ import os4 from "os";
196
233
  var REGISTRY_PATH;
197
234
  var init_session_registry = __esm({
198
235
  "src/lib/session-registry.ts"() {
199
236
  "use strict";
200
- REGISTRY_PATH = path3.join(os3.homedir(), ".exe-os", "session-registry.json");
237
+ REGISTRY_PATH = path4.join(os4.homedir(), ".exe-os", "session-registry.json");
201
238
  }
202
239
  });
203
240
 
@@ -433,10 +470,10 @@ var init_runtime_table = __esm({
433
470
  });
434
471
 
435
472
  // src/lib/agent-config.ts
436
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync } from "fs";
437
- import path4 from "path";
473
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync4 } from "fs";
474
+ import path5 from "path";
438
475
  function loadAgentConfig() {
439
- if (!existsSync3(AGENT_CONFIG_PATH)) return {};
476
+ if (!existsSync4(AGENT_CONFIG_PATH)) return {};
440
477
  try {
441
478
  return JSON.parse(readFileSync3(AGENT_CONFIG_PATH, "utf-8"));
442
479
  } catch {
@@ -457,7 +494,8 @@ var init_agent_config = __esm({
457
494
  "use strict";
458
495
  init_config();
459
496
  init_runtime_table();
460
- AGENT_CONFIG_PATH = path4.join(EXE_AI_DIR, "agent-config.json");
497
+ init_secure_files();
498
+ AGENT_CONFIG_PATH = path5.join(EXE_AI_DIR, "agent-config.json");
461
499
  DEFAULT_MODELS = {
462
500
  claude: "claude-opus-4",
463
501
  codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
@@ -467,16 +505,16 @@ var init_agent_config = __esm({
467
505
  });
468
506
 
469
507
  // src/lib/intercom-queue.ts
470
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
471
- import path5 from "path";
472
- import os4 from "os";
508
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
509
+ import path6 from "path";
510
+ import os5 from "os";
473
511
  function ensureDir() {
474
- const dir = path5.dirname(QUEUE_PATH);
475
- if (!existsSync4(dir)) mkdirSync2(dir, { recursive: true });
512
+ const dir = path6.dirname(QUEUE_PATH);
513
+ if (!existsSync5(dir)) mkdirSync2(dir, { recursive: true });
476
514
  }
477
515
  function readQueue() {
478
516
  try {
479
- if (!existsSync4(QUEUE_PATH)) return [];
517
+ if (!existsSync5(QUEUE_PATH)) return [];
480
518
  return JSON.parse(readFileSync4(QUEUE_PATH, "utf8"));
481
519
  } catch {
482
520
  return [];
@@ -509,31 +547,34 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
509
547
  var init_intercom_queue = __esm({
510
548
  "src/lib/intercom-queue.ts"() {
511
549
  "use strict";
512
- QUEUE_PATH = path5.join(os4.homedir(), ".exe-os", "intercom-queue.json");
550
+ QUEUE_PATH = path6.join(os5.homedir(), ".exe-os", "intercom-queue.json");
513
551
  TTL_MS = 60 * 60 * 1e3;
514
- INTERCOM_LOG = path5.join(os4.homedir(), ".exe-os", "intercom.log");
552
+ INTERCOM_LOG = path6.join(os5.homedir(), ".exe-os", "intercom.log");
515
553
  }
516
554
  });
517
555
 
518
556
  // src/lib/license.ts
519
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
557
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
520
558
  import { randomUUID } from "crypto";
521
- import path6 from "path";
559
+ import { createRequire as createRequire2 } from "module";
560
+ import { pathToFileURL as pathToFileURL2 } from "url";
561
+ import os6 from "os";
562
+ import path7 from "path";
522
563
  import { jwtVerify, importSPKI } from "jose";
523
564
  var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
524
565
  var init_license = __esm({
525
566
  "src/lib/license.ts"() {
526
567
  "use strict";
527
568
  init_config();
528
- LICENSE_PATH = path6.join(EXE_AI_DIR, "license.key");
529
- CACHE_PATH = path6.join(EXE_AI_DIR, "license-cache.json");
530
- DEVICE_ID_PATH = path6.join(EXE_AI_DIR, "device-id");
569
+ LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
570
+ CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
571
+ DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
531
572
  }
532
573
  });
533
574
 
534
575
  // src/lib/plan-limits.ts
535
- import { readFileSync as readFileSync6, existsSync as existsSync6 } from "fs";
536
- import path7 from "path";
576
+ import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
577
+ import path8 from "path";
537
578
  var CACHE_PATH2;
538
579
  var init_plan_limits = __esm({
539
580
  "src/lib/plan-limits.ts"() {
@@ -542,15 +583,15 @@ var init_plan_limits = __esm({
542
583
  init_employees();
543
584
  init_license();
544
585
  init_config();
545
- CACHE_PATH2 = path7.join(EXE_AI_DIR, "license-cache.json");
586
+ CACHE_PATH2 = path8.join(EXE_AI_DIR, "license-cache.json");
546
587
  }
547
588
  });
548
589
 
549
590
  // src/lib/tmux-routing.ts
550
591
  import { execFileSync as execFileSync2, execSync as execSync4 } from "child_process";
551
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync7, appendFileSync, readdirSync } from "fs";
552
- import path8 from "path";
553
- import os5 from "os";
592
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync8, appendFileSync, readdirSync } from "fs";
593
+ import path9 from "path";
594
+ import os7 from "os";
554
595
  import { fileURLToPath } from "url";
555
596
  function getMySession() {
556
597
  return getTransport().getMySession();
@@ -590,7 +631,7 @@ function extractRootExe(name) {
590
631
  }
591
632
  function getParentExe(sessionKey) {
592
633
  try {
593
- const data = JSON.parse(readFileSync7(path8.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
634
+ const data = JSON.parse(readFileSync7(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
594
635
  return data.parentExe || null;
595
636
  } catch {
596
637
  return null;
@@ -623,7 +664,7 @@ function isEmployeeAlive(sessionName) {
623
664
  }
624
665
  function readDebounceState() {
625
666
  try {
626
- if (!existsSync7(DEBOUNCE_FILE)) return {};
667
+ if (!existsSync8(DEBOUNCE_FILE)) return {};
627
668
  const raw = JSON.parse(readFileSync7(DEBOUNCE_FILE, "utf8"));
628
669
  const state = {};
629
670
  for (const [key, val] of Object.entries(raw)) {
@@ -640,7 +681,7 @@ function readDebounceState() {
640
681
  }
641
682
  function writeDebounceState(state) {
642
683
  try {
643
- if (!existsSync7(SESSION_CACHE)) mkdirSync4(SESSION_CACHE, { recursive: true });
684
+ if (!existsSync8(SESSION_CACHE)) mkdirSync4(SESSION_CACHE, { recursive: true });
644
685
  writeFileSync5(DEBOUNCE_FILE, JSON.stringify(state));
645
686
  } catch {
646
687
  }
@@ -735,8 +776,8 @@ function sendIntercom(targetSession) {
735
776
  try {
736
777
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
737
778
  const agent = baseAgentName(rawAgent);
738
- const markerPath = path8.join(SESSION_CACHE, `current-task-${agent}.json`);
739
- if (existsSync7(markerPath)) {
779
+ const markerPath = path9.join(SESSION_CACHE, `current-task-${agent}.json`);
780
+ if (existsSync8(markerPath)) {
740
781
  logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker \u2014 will auto-chain)`);
741
782
  return "debounced";
742
783
  }
@@ -745,8 +786,8 @@ function sendIntercom(targetSession) {
745
786
  try {
746
787
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
747
788
  const agent = baseAgentName(rawAgent);
748
- const taskDir = path8.join(process.cwd(), "exe", agent);
749
- if (existsSync7(taskDir)) {
789
+ const taskDir = path9.join(process.cwd(), "exe", agent);
790
+ if (existsSync8(taskDir)) {
750
791
  const files = readdirSync(taskDir).filter(
751
792
  (f) => f.endsWith(".md") && f !== "DONE.txt"
752
793
  );
@@ -799,24 +840,49 @@ var init_tmux_routing = __esm({
799
840
  init_intercom_queue();
800
841
  init_plan_limits();
801
842
  init_employees();
802
- SPAWN_LOCK_DIR = path8.join(os5.homedir(), ".exe-os", "spawn-locks");
803
- SESSION_CACHE = path8.join(os5.homedir(), ".exe-os", "session-cache");
843
+ SPAWN_LOCK_DIR = path9.join(os7.homedir(), ".exe-os", "spawn-locks");
844
+ SESSION_CACHE = path9.join(os7.homedir(), ".exe-os", "session-cache");
804
845
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
805
846
  INTERCOM_DEBOUNCE_MS = 3e4;
806
847
  CODEX_DEBOUNCE_MS = 12e4;
807
- INTERCOM_LOG2 = path8.join(os5.homedir(), ".exe-os", "intercom.log");
808
- DEBOUNCE_FILE = path8.join(SESSION_CACHE, "intercom-debounce.json");
848
+ INTERCOM_LOG2 = path9.join(os7.homedir(), ".exe-os", "intercom.log");
849
+ DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
809
850
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
810
851
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
811
852
  }
812
853
  });
813
854
 
855
+ // src/lib/task-scope.ts
856
+ function getCurrentSessionScope() {
857
+ try {
858
+ return resolveExeSession();
859
+ } catch {
860
+ return null;
861
+ }
862
+ }
863
+ function strictSessionScopeFilter(sessionScope, tableAlias) {
864
+ const scope = sessionScope !== void 0 ? sessionScope : getCurrentSessionScope();
865
+ if (!scope) return { sql: "", args: [] };
866
+ const col = tableAlias ? `${tableAlias}.session_scope` : "session_scope";
867
+ return {
868
+ sql: ` AND ${col} = ?`,
869
+ args: [scope]
870
+ };
871
+ }
872
+ var init_task_scope = __esm({
873
+ "src/lib/task-scope.ts"() {
874
+ "use strict";
875
+ init_tmux_routing();
876
+ }
877
+ });
878
+
814
879
  // src/mcp/tools/send-message.ts
815
880
  import { z } from "zod";
816
881
 
817
882
  // src/lib/messaging.ts
818
883
  init_database();
819
884
  init_tmux_routing();
885
+ init_task_scope();
820
886
  import crypto from "crypto";
821
887
  function generateUlid() {
822
888
  const timestamp = Date.now().toString(36).padStart(10, "0");
@@ -831,6 +897,7 @@ function rowToMessage(row) {
831
897
  targetAgent: row.target_agent,
832
898
  targetProject: row.target_project ?? null,
833
899
  targetDevice: row.target_device,
900
+ sessionScope: row.session_scope ?? null,
834
901
  content: row.content,
835
902
  priority: row.priority ?? "normal",
836
903
  status: row.status ?? "pending",
@@ -849,15 +916,17 @@ async function sendMessage(input) {
849
916
  const id = generateUlid();
850
917
  const now = (/* @__PURE__ */ new Date()).toISOString();
851
918
  const targetDevice = input.targetDevice ?? "local";
919
+ const sessionScope = input.sessionScope === void 0 ? resolveExeSession() : input.sessionScope;
852
920
  await client.execute({
853
- sql: `INSERT INTO messages (id, from_agent, from_device, target_agent, target_project, target_device, content, priority, status, created_at)
854
- VALUES (?, ?, 'local', ?, ?, ?, ?, ?, 'pending', ?)`,
921
+ sql: `INSERT INTO messages (id, from_agent, from_device, target_agent, target_project, target_device, session_scope, content, priority, status, created_at)
922
+ VALUES (?, ?, 'local', ?, ?, ?, ?, ?, ?, 'pending', ?)`,
855
923
  args: [
856
924
  id,
857
925
  input.fromAgent,
858
926
  input.targetAgent,
859
927
  input.targetProject ?? null,
860
928
  targetDevice,
929
+ sessionScope,
861
930
  input.content,
862
931
  input.priority ?? "normal",
863
932
  now
@@ -871,9 +940,10 @@ async function sendMessage(input) {
871
940
  }
872
941
  } catch {
873
942
  }
943
+ const sentScope = strictSessionScopeFilter(sessionScope);
874
944
  const result = await client.execute({
875
- sql: "SELECT * FROM messages WHERE id = ?",
876
- args: [id]
945
+ sql: `SELECT * FROM messages WHERE id = ?${sentScope.sql}`,
946
+ args: [id, ...sentScope.args]
877
947
  });
878
948
  return rowToMessage(result.rows[0]);
879
949
  }
@@ -895,6 +965,7 @@ async function deliverCrossMachineMessage(messageId, targetDevice) {
895
965
  fromAgent: msg.fromAgent,
896
966
  targetAgent: msg.targetAgent,
897
967
  targetProject: msg.targetProject,
968
+ sessionScope: msg.sessionScope,
898
969
  content: msg.content,
899
970
  priority: msg.priority,
900
971
  createdAt: msg.createdAt
@@ -938,7 +1009,7 @@ async function deliverLocalMessage(messageId) {
938
1009
  } catch {
939
1010
  const newRetryCount = msg.retryCount + 1;
940
1011
  if (newRetryCount >= MAX_RETRIES) {
941
- await markFailed(messageId, "session unavailable after 10 retries");
1012
+ await markFailed(messageId, "session unavailable after 10 retries", msg.sessionScope);
942
1013
  } else {
943
1014
  await client.execute({
944
1015
  sql: "UPDATE messages SET retry_count = ? WHERE id = ?",
@@ -948,11 +1019,13 @@ async function deliverLocalMessage(messageId) {
948
1019
  return false;
949
1020
  }
950
1021
  }
951
- async function markFailed(messageId, reason) {
1022
+ async function markFailed(messageId, reason, sessionScope) {
952
1023
  const client = getClient();
1024
+ const scope = strictSessionScopeFilter(sessionScope);
953
1025
  await client.execute({
954
- sql: "UPDATE messages SET status = 'failed', failed_at = ?, failure_reason = ? WHERE id = ?",
955
- args: [(/* @__PURE__ */ new Date()).toISOString(), reason, messageId]
1026
+ sql: `UPDATE messages SET status = 'failed', failed_at = ?, failure_reason = ?
1027
+ WHERE id = ?${scope.sql}`,
1028
+ args: [(/* @__PURE__ */ new Date()).toISOString(), reason, messageId, ...scope.args]
956
1029
  });
957
1030
  }
958
1031
 
@@ -962,8 +1035,8 @@ init_session_key();
962
1035
  init_employees();
963
1036
  import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, unlinkSync as unlinkSync2, readdirSync as readdirSync2 } from "fs";
964
1037
  import { execSync as execSync5 } from "child_process";
965
- import path9 from "path";
966
- var CACHE_DIR = path9.join(EXE_AI_DIR, "session-cache");
1038
+ import path10 from "path";
1039
+ var CACHE_DIR = path10.join(EXE_AI_DIR, "session-cache");
967
1040
  var STALE_MS = 24 * 60 * 60 * 1e3;
968
1041
  function isNameWithOptionalInstance(candidate, baseName) {
969
1042
  if (candidate === baseName) return true;
@@ -1008,7 +1081,7 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
1008
1081
  return null;
1009
1082
  }
1010
1083
  function getMarkerPath() {
1011
- return path9.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
1084
+ return path10.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
1012
1085
  }
1013
1086
  function getActiveAgent() {
1014
1087
  try {