@askexenow/exe-os 0.8.83 → 0.8.86

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 (103) hide show
  1. package/dist/bin/backfill-conversations.js +746 -595
  2. package/dist/bin/backfill-responses.js +745 -594
  3. package/dist/bin/backfill-vectors.js +312 -226
  4. package/dist/bin/cleanup-stale-review-tasks.js +154 -21
  5. package/dist/bin/cli.js +14678 -12676
  6. package/dist/bin/exe-agent-config.js +242 -0
  7. package/dist/bin/exe-agent.js +100 -91
  8. package/dist/bin/exe-assign.js +1003 -854
  9. package/dist/bin/exe-boot.js +1420 -485
  10. package/dist/bin/exe-call.js +10 -0
  11. package/dist/bin/exe-cloud.js +29 -6
  12. package/dist/bin/exe-dispatch.js +572 -271
  13. package/dist/bin/exe-doctor.js +403 -6
  14. package/dist/bin/exe-export-behaviors.js +175 -72
  15. package/dist/bin/exe-forget.js +102 -3
  16. package/dist/bin/exe-gateway.js +796 -292
  17. package/dist/bin/exe-healthcheck.js +134 -1
  18. package/dist/bin/exe-heartbeat.js +172 -36
  19. package/dist/bin/exe-kill.js +175 -72
  20. package/dist/bin/exe-launch-agent.js +189 -76
  21. package/dist/bin/exe-link.js +927 -82
  22. package/dist/bin/exe-new-employee.js +60 -8
  23. package/dist/bin/exe-pending-messages.js +151 -19
  24. package/dist/bin/exe-pending-notifications.js +97 -2
  25. package/dist/bin/exe-pending-reviews.js +155 -22
  26. package/dist/bin/exe-rename.js +564 -23
  27. package/dist/bin/exe-review.js +231 -73
  28. package/dist/bin/exe-search.js +995 -228
  29. package/dist/bin/exe-session-cleanup.js +4930 -1664
  30. package/dist/bin/exe-settings.js +20 -5
  31. package/dist/bin/exe-start-codex.js +2598 -0
  32. package/dist/bin/exe-start.sh +15 -3
  33. package/dist/bin/exe-status.js +154 -21
  34. package/dist/bin/exe-team.js +97 -2
  35. package/dist/bin/git-sweep.js +1180 -363
  36. package/dist/bin/graph-backfill.js +175 -72
  37. package/dist/bin/graph-export.js +175 -72
  38. package/dist/bin/install.js +60 -7
  39. package/dist/bin/list-providers.js +1 -0
  40. package/dist/bin/scan-tasks.js +1185 -367
  41. package/dist/bin/setup.js +914 -270
  42. package/dist/bin/shard-migrate.js +175 -72
  43. package/dist/bin/update.js +1 -0
  44. package/dist/bin/wiki-sync.js +175 -72
  45. package/dist/gateway/index.js +792 -285
  46. package/dist/hooks/bug-report-worker.js +445 -135
  47. package/dist/hooks/commit-complete.js +1178 -361
  48. package/dist/hooks/error-recall.js +994 -228
  49. package/dist/hooks/ingest-worker.js +1799 -1234
  50. package/dist/hooks/ingest.js +3 -0
  51. package/dist/hooks/instructions-loaded.js +707 -97
  52. package/dist/hooks/notification.js +699 -89
  53. package/dist/hooks/post-compact.js +757 -109
  54. package/dist/hooks/pre-compact.js +1061 -244
  55. package/dist/hooks/pre-tool-use.js +787 -130
  56. package/dist/hooks/prompt-ingest-worker.js +242 -101
  57. package/dist/hooks/prompt-submit.js +1121 -299
  58. package/dist/hooks/response-ingest-worker.js +242 -101
  59. package/dist/hooks/session-end.js +4063 -397
  60. package/dist/hooks/session-start.js +1071 -254
  61. package/dist/hooks/stop.js +768 -120
  62. package/dist/hooks/subagent-stop.js +757 -109
  63. package/dist/hooks/summary-worker.js +1706 -1011
  64. package/dist/index.js +1821 -1098
  65. package/dist/lib/agent-config.js +167 -0
  66. package/dist/lib/cloud-sync.js +932 -88
  67. package/dist/lib/consolidation.js +2 -1
  68. package/dist/lib/database.js +642 -87
  69. package/dist/lib/db-daemon-client.js +503 -0
  70. package/dist/lib/device-registry.js +547 -7
  71. package/dist/lib/embedder.js +14 -28
  72. package/dist/lib/employee-templates.js +84 -74
  73. package/dist/lib/employees.js +9 -0
  74. package/dist/lib/exe-daemon-client.js +16 -29
  75. package/dist/lib/exe-daemon.js +2733 -1575
  76. package/dist/lib/hybrid-search.js +995 -228
  77. package/dist/lib/identity.js +87 -67
  78. package/dist/lib/keychain.js +9 -1
  79. package/dist/lib/messaging.js +103 -40
  80. package/dist/lib/reminders.js +91 -74
  81. package/dist/lib/runtime-table.js +16 -0
  82. package/dist/lib/schedules.js +96 -2
  83. package/dist/lib/session-wrappers.js +22 -0
  84. package/dist/lib/skill-learning.js +103 -85
  85. package/dist/lib/store.js +234 -73
  86. package/dist/lib/tasks.js +348 -134
  87. package/dist/lib/tmux-routing.js +422 -208
  88. package/dist/lib/token-spend.js +273 -0
  89. package/dist/lib/ws-client.js +11 -0
  90. package/dist/mcp/server.js +5742 -696
  91. package/dist/mcp/tools/complete-reminder.js +94 -77
  92. package/dist/mcp/tools/create-reminder.js +94 -77
  93. package/dist/mcp/tools/create-task.js +375 -152
  94. package/dist/mcp/tools/deactivate-behavior.js +95 -77
  95. package/dist/mcp/tools/list-reminders.js +94 -77
  96. package/dist/mcp/tools/list-tasks.js +99 -31
  97. package/dist/mcp/tools/send-message.js +108 -45
  98. package/dist/mcp/tools/update-task.js +162 -77
  99. package/dist/runtime/index.js +1075 -258
  100. package/dist/tui/App.js +1333 -506
  101. package/package.json +6 -1
  102. package/src/commands/exe/agent-config.md +27 -0
  103. package/src/commands/exe/cc-doctor.md +10 -0
@@ -11,6 +11,7 @@ import { realpathSync } from "fs";
11
11
  import { fileURLToPath } from "url";
12
12
  function isMainModule(importMetaUrl) {
13
13
  if (process.argv[1] == null) return false;
14
+ if (process.argv[1].includes("mcp/server")) return false;
14
15
  try {
15
16
  const scriptPath = realpathSync(process.argv[1]);
16
17
  const modulePath = realpathSync(fileURLToPath(importMetaUrl));
@@ -177,13 +178,144 @@ function checkWorkerSpawning(pkgRoot) {
177
178
  }
178
179
  return results;
179
180
  }
181
+ function checkClaudeCodeInstall() {
182
+ const results = [];
183
+ const execPath = process.env.CLAUDE_CODE_EXECPATH ?? "";
184
+ if (execPath.length > 0 && (execPath.includes("claude/versions/") || execPath.includes("claude.exe") || execPath.includes("claude-native"))) {
185
+ results.push({
186
+ name: "cc/execpath-clean",
187
+ pass: false,
188
+ detail: `CLAUDE_CODE_EXECPATH points to native binary: "${execPath}" \u2014 20K phantom billing risk. Unset it: unset CLAUDE_CODE_EXECPATH`
189
+ });
190
+ } else {
191
+ results.push({
192
+ name: "cc/execpath-clean",
193
+ pass: true,
194
+ detail: execPath ? `CLAUDE_CODE_EXECPATH=${execPath} (node runtime, OK)` : "CLAUDE_CODE_EXECPATH is unset"
195
+ });
196
+ }
197
+ try {
198
+ const claudePath = execSync("which claude 2>/dev/null || true", { encoding: "utf8", timeout: 5e3 }).trim();
199
+ if (!claudePath) {
200
+ results.push({
201
+ name: "cc/cli-binary",
202
+ pass: false,
203
+ detail: "claude not found in PATH"
204
+ });
205
+ } else {
206
+ let resolved = claudePath;
207
+ try {
208
+ resolved = execSync(`readlink -f "${claudePath}" 2>/dev/null || readlink "${claudePath}" 2>/dev/null || echo "${claudePath}"`, {
209
+ encoding: "utf8",
210
+ timeout: 5e3
211
+ }).trim();
212
+ } catch {
213
+ }
214
+ if (resolved.includes("bin/claude.exe") || resolved.includes("bin/claude-native")) {
215
+ results.push({
216
+ name: "cc/cli-binary",
217
+ pass: false,
218
+ detail: `claude resolves to native binary: ${resolved}. Should be cli.js. Run: npm install -g @anthropic-ai/claude-code@2.1.98`
219
+ });
220
+ } else {
221
+ results.push({
222
+ name: "cc/cli-binary",
223
+ pass: true,
224
+ detail: `claude resolves to: ${resolved}`
225
+ });
226
+ }
227
+ }
228
+ } catch {
229
+ results.push({
230
+ name: "cc/cli-binary",
231
+ pass: false,
232
+ detail: "Failed to check claude binary path"
233
+ });
234
+ }
235
+ const versionsDir = path.join(
236
+ process.env.HOME ?? process.env.USERPROFILE ?? "",
237
+ ".local",
238
+ "share",
239
+ "claude",
240
+ "versions"
241
+ );
242
+ if (existsSync(versionsDir)) {
243
+ try {
244
+ const entries = readdirSync(versionsDir);
245
+ if (entries.length > 0) {
246
+ results.push({
247
+ name: "cc/native-cache-clean",
248
+ pass: false,
249
+ detail: `${entries.length} cached native version(s) found in ${versionsDir}: ${entries.slice(0, 3).join(", ")}${entries.length > 3 ? "..." : ""}. Remove: rm -rf "${versionsDir}"`
250
+ });
251
+ } else {
252
+ results.push({
253
+ name: "cc/native-cache-clean",
254
+ pass: true,
255
+ detail: `${versionsDir} is empty`
256
+ });
257
+ }
258
+ } catch {
259
+ results.push({
260
+ name: "cc/native-cache-clean",
261
+ pass: true,
262
+ detail: `${versionsDir} not readable (OK)`
263
+ });
264
+ }
265
+ } else {
266
+ results.push({
267
+ name: "cc/native-cache-clean",
268
+ pass: true,
269
+ detail: `${versionsDir} does not exist`
270
+ });
271
+ }
272
+ const disableOld = process.env.DISABLE_AUTOUPDATER === "1";
273
+ const disableNew = process.env.CLAUDE_CODE_AUTOUPDATER_DISABLED === "1";
274
+ if (!disableOld && !disableNew) {
275
+ results.push({
276
+ name: "cc/autoupdater-disabled",
277
+ pass: false,
278
+ detail: "Neither DISABLE_AUTOUPDATER=1 nor CLAUDE_CODE_AUTOUPDATER_DISABLED=1 is set. Auto-updater may install infected native binary. Export both in your shell profile."
279
+ });
280
+ } else {
281
+ const which = [
282
+ disableOld ? "DISABLE_AUTOUPDATER=1" : null,
283
+ disableNew ? "CLAUDE_CODE_AUTOUPDATER_DISABLED=1" : null
284
+ ].filter(Boolean).join(" + ");
285
+ results.push({
286
+ name: "cc/autoupdater-disabled",
287
+ pass: true,
288
+ detail: `Auto-updater disabled via ${which}`
289
+ });
290
+ }
291
+ try {
292
+ const ccVersion = execSync("claude --version 2>/dev/null || echo unknown", {
293
+ encoding: "utf8",
294
+ timeout: 5e3
295
+ }).trim();
296
+ const versionMatch = ccVersion.match(/(\d+\.\d+\.\d+)/);
297
+ if (versionMatch) {
298
+ const ver = versionMatch[1];
299
+ const [, minor] = ver.split(".").map(Number);
300
+ const isRisky = minor !== void 0 && minor >= 1 && parseInt(ver.split(".")[2] ?? "0") >= 119;
301
+ results.push({
302
+ name: "cc/version",
303
+ pass: !isRisky,
304
+ detail: isRisky ? `CC version ${ver} \u2014 \u22652.1.119 ships native binary only. Pin: npm install -g @anthropic-ai/claude-code@2.1.98` : `CC version ${ver}`
305
+ });
306
+ }
307
+ } catch {
308
+ }
309
+ return results;
310
+ }
180
311
  function runHealthCheck() {
181
312
  const pkgRoot = findPackageRoot();
182
313
  const results = [
183
314
  ...checkBuildIntegrity(pkgRoot),
184
315
  ...checkEmbedPipeline(pkgRoot),
185
316
  ...checkTaskSystem(pkgRoot),
186
- ...checkWorkerSpawning(pkgRoot)
317
+ ...checkWorkerSpawning(pkgRoot),
318
+ ...checkClaudeCodeInstall()
187
319
  ];
188
320
  const passed = results.filter((r) => r.pass).length;
189
321
  const failed = results.filter((r) => !r.pass).length;
@@ -203,5 +335,6 @@ if (isMainModule(import.meta.url)) {
203
335
  process.exit(failed > 0 ? 1 : 0);
204
336
  }
205
337
  export {
338
+ checkClaudeCodeInstall,
206
339
  runHealthCheck
207
340
  };
@@ -335,6 +335,12 @@ function getClient() {
335
335
  if (!_resilientClient) {
336
336
  throw new Error("Database client not initialized. Call initDatabase() first.");
337
337
  }
338
+ if (process.env.EXE_IS_DAEMON === "1") {
339
+ return _resilientClient;
340
+ }
341
+ if (_daemonClient && _daemonClient._isDaemonActive()) {
342
+ return _daemonClient;
343
+ }
338
344
  return _resilientClient;
339
345
  }
340
346
  function getRawClient() {
@@ -823,6 +829,12 @@ async function ensureSchema() {
823
829
  } catch {
824
830
  }
825
831
  }
832
+ try {
833
+ await client.execute(
834
+ `CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
835
+ );
836
+ } catch {
837
+ }
826
838
  await client.executeMultiple(`
827
839
  CREATE TABLE IF NOT EXISTS entities (
828
840
  id TEXT PRIMARY KEY,
@@ -875,7 +887,30 @@ async function ensureSchema() {
875
887
  entity_id TEXT NOT NULL,
876
888
  PRIMARY KEY (hyperedge_id, entity_id)
877
889
  );
890
+
891
+ CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
892
+ name,
893
+ content=entities,
894
+ content_rowid=rowid
895
+ );
896
+
897
+ CREATE TRIGGER IF NOT EXISTS entities_fts_ai AFTER INSERT ON entities BEGIN
898
+ INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
899
+ END;
900
+
901
+ CREATE TRIGGER IF NOT EXISTS entities_fts_ad AFTER DELETE ON entities BEGIN
902
+ INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
903
+ END;
904
+
905
+ CREATE TRIGGER IF NOT EXISTS entities_fts_au AFTER UPDATE ON entities BEGIN
906
+ INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
907
+ INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
908
+ END;
878
909
  `);
910
+ try {
911
+ await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
912
+ } catch {
913
+ }
879
914
  await client.executeMultiple(`
880
915
  CREATE TABLE IF NOT EXISTS entity_aliases (
881
916
  alias TEXT NOT NULL PRIMARY KEY,
@@ -1056,6 +1091,33 @@ async function ensureSchema() {
1056
1091
  CREATE INDEX IF NOT EXISTS idx_conversations_channel
1057
1092
  ON conversations(channel_id);
1058
1093
  `);
1094
+ await client.executeMultiple(`
1095
+ CREATE TABLE IF NOT EXISTS session_agent_map (
1096
+ session_uuid TEXT PRIMARY KEY,
1097
+ agent_id TEXT NOT NULL,
1098
+ session_name TEXT,
1099
+ task_id TEXT,
1100
+ project_name TEXT,
1101
+ started_at TEXT NOT NULL
1102
+ );
1103
+
1104
+ CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
1105
+ ON session_agent_map(agent_id);
1106
+ `);
1107
+ try {
1108
+ const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
1109
+ if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
1110
+ await client.execute({
1111
+ sql: `INSERT OR IGNORE INTO session_agent_map (session_uuid, agent_id, session_name, started_at)
1112
+ SELECT session_id, agent_id, '', MIN(timestamp)
1113
+ FROM memories
1114
+ WHERE session_id IS NOT NULL AND session_id != '' AND agent_id IS NOT NULL AND agent_id != ''
1115
+ GROUP BY session_id, agent_id`,
1116
+ args: []
1117
+ });
1118
+ }
1119
+ } catch {
1120
+ }
1059
1121
  try {
1060
1122
  await client.execute({
1061
1123
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -1189,8 +1251,30 @@ async function ensureSchema() {
1189
1251
  });
1190
1252
  } catch {
1191
1253
  }
1254
+ for (const col of [
1255
+ "ALTER TABLE memories ADD COLUMN intent TEXT",
1256
+ "ALTER TABLE memories ADD COLUMN outcome TEXT",
1257
+ "ALTER TABLE memories ADD COLUMN domain TEXT",
1258
+ "ALTER TABLE memories ADD COLUMN referenced_entities TEXT",
1259
+ "ALTER TABLE memories ADD COLUMN retrieval_count INTEGER DEFAULT 0",
1260
+ "ALTER TABLE memories ADD COLUMN chain_position TEXT",
1261
+ "ALTER TABLE memories ADD COLUMN review_status TEXT",
1262
+ "ALTER TABLE memories ADD COLUMN context_window_pct INTEGER",
1263
+ "ALTER TABLE memories ADD COLUMN file_paths TEXT",
1264
+ "ALTER TABLE memories ADD COLUMN commit_hash TEXT",
1265
+ "ALTER TABLE memories ADD COLUMN duration_ms INTEGER",
1266
+ "ALTER TABLE memories ADD COLUMN token_cost REAL",
1267
+ "ALTER TABLE memories ADD COLUMN audience TEXT",
1268
+ "ALTER TABLE memories ADD COLUMN language_type TEXT",
1269
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
1270
+ ]) {
1271
+ try {
1272
+ await client.execute(col);
1273
+ } catch {
1274
+ }
1275
+ }
1192
1276
  }
1193
- var _client, _resilientClient, initTurso;
1277
+ var _client, _resilientClient, _daemonClient, initTurso;
1194
1278
  var init_database = __esm({
1195
1279
  "src/lib/database.ts"() {
1196
1280
  "use strict";
@@ -1198,6 +1282,7 @@ var init_database = __esm({
1198
1282
  init_employees();
1199
1283
  _client = null;
1200
1284
  _resilientClient = null;
1285
+ _daemonClient = null;
1201
1286
  initTurso = initDatabase;
1202
1287
  }
1203
1288
  });
@@ -1883,39 +1968,75 @@ var init_provider_table = __esm({
1883
1968
  }
1884
1969
  });
1885
1970
 
1886
- // src/lib/intercom-queue.ts
1887
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync as renameSync3, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
1971
+ // src/lib/runtime-table.ts
1972
+ var RUNTIME_TABLE;
1973
+ var init_runtime_table = __esm({
1974
+ "src/lib/runtime-table.ts"() {
1975
+ "use strict";
1976
+ RUNTIME_TABLE = {
1977
+ codex: {
1978
+ binary: "codex",
1979
+ launchMode: "exec",
1980
+ autoApproveFlag: "--full-auto",
1981
+ inlineFlag: "--no-alt-screen",
1982
+ apiKeyEnv: "OPENAI_API_KEY",
1983
+ defaultModel: "gpt-5.4"
1984
+ }
1985
+ };
1986
+ }
1987
+ });
1988
+
1989
+ // src/lib/agent-config.ts
1990
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
1888
1991
  import path7 from "path";
1992
+ var AGENT_CONFIG_PATH, DEFAULT_MODELS;
1993
+ var init_agent_config = __esm({
1994
+ "src/lib/agent-config.ts"() {
1995
+ "use strict";
1996
+ init_config();
1997
+ init_runtime_table();
1998
+ AGENT_CONFIG_PATH = path7.join(EXE_AI_DIR, "agent-config.json");
1999
+ DEFAULT_MODELS = {
2000
+ claude: "claude-opus-4",
2001
+ codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
2002
+ opencode: "minimax-m2.7"
2003
+ };
2004
+ }
2005
+ });
2006
+
2007
+ // src/lib/intercom-queue.ts
2008
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
2009
+ import path8 from "path";
1889
2010
  import os6 from "os";
1890
2011
  var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
1891
2012
  var init_intercom_queue = __esm({
1892
2013
  "src/lib/intercom-queue.ts"() {
1893
2014
  "use strict";
1894
- QUEUE_PATH = path7.join(os6.homedir(), ".exe-os", "intercom-queue.json");
2015
+ QUEUE_PATH = path8.join(os6.homedir(), ".exe-os", "intercom-queue.json");
1895
2016
  TTL_MS = 60 * 60 * 1e3;
1896
- INTERCOM_LOG = path7.join(os6.homedir(), ".exe-os", "intercom.log");
2017
+ INTERCOM_LOG = path8.join(os6.homedir(), ".exe-os", "intercom.log");
1897
2018
  }
1898
2019
  });
1899
2020
 
1900
2021
  // src/lib/license.ts
1901
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
2022
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
1902
2023
  import { randomUUID as randomUUID2 } from "crypto";
1903
- import path8 from "path";
2024
+ import path9 from "path";
1904
2025
  import { jwtVerify, importSPKI } from "jose";
1905
2026
  var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
1906
2027
  var init_license = __esm({
1907
2028
  "src/lib/license.ts"() {
1908
2029
  "use strict";
1909
2030
  init_config();
1910
- LICENSE_PATH = path8.join(EXE_AI_DIR, "license.key");
1911
- CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
1912
- DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
2031
+ LICENSE_PATH = path9.join(EXE_AI_DIR, "license.key");
2032
+ CACHE_PATH = path9.join(EXE_AI_DIR, "license-cache.json");
2033
+ DEVICE_ID_PATH = path9.join(EXE_AI_DIR, "device-id");
1913
2034
  }
1914
2035
  });
1915
2036
 
1916
2037
  // src/lib/plan-limits.ts
1917
- import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
1918
- import path9 from "path";
2038
+ import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
2039
+ import path10 from "path";
1919
2040
  var CACHE_PATH2;
1920
2041
  var init_plan_limits = __esm({
1921
2042
  "src/lib/plan-limits.ts"() {
@@ -1924,13 +2045,13 @@ var init_plan_limits = __esm({
1924
2045
  init_employees();
1925
2046
  init_license();
1926
2047
  init_config();
1927
- CACHE_PATH2 = path9.join(EXE_AI_DIR, "license-cache.json");
2048
+ CACHE_PATH2 = path10.join(EXE_AI_DIR, "license-cache.json");
1928
2049
  }
1929
2050
  });
1930
2051
 
1931
2052
  // src/lib/tmux-routing.ts
1932
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync9, appendFileSync } from "fs";
1933
- import path10 from "path";
2053
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync10, appendFileSync } from "fs";
2054
+ import path11 from "path";
1934
2055
  import os7 from "os";
1935
2056
  import { fileURLToPath as fileURLToPath2 } from "url";
1936
2057
  function getMySession() {
@@ -1944,7 +2065,7 @@ function extractRootExe(name) {
1944
2065
  }
1945
2066
  function getParentExe(sessionKey) {
1946
2067
  try {
1947
- const data = JSON.parse(readFileSync7(path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
2068
+ const data = JSON.parse(readFileSync8(path11.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
1948
2069
  return data.parentExe || null;
1949
2070
  } catch {
1950
2071
  return null;
@@ -1978,27 +2099,29 @@ var init_tmux_routing = __esm({
1978
2099
  init_cc_agent_support();
1979
2100
  init_mcp_prefix();
1980
2101
  init_provider_table();
2102
+ init_agent_config();
2103
+ init_runtime_table();
1981
2104
  init_intercom_queue();
1982
2105
  init_plan_limits();
1983
2106
  init_employees();
1984
- SPAWN_LOCK_DIR = path10.join(os7.homedir(), ".exe-os", "spawn-locks");
1985
- SESSION_CACHE = path10.join(os7.homedir(), ".exe-os", "session-cache");
1986
- INTERCOM_LOG2 = path10.join(os7.homedir(), ".exe-os", "intercom.log");
1987
- DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
2107
+ SPAWN_LOCK_DIR = path11.join(os7.homedir(), ".exe-os", "spawn-locks");
2108
+ SESSION_CACHE = path11.join(os7.homedir(), ".exe-os", "session-cache");
2109
+ INTERCOM_LOG2 = path11.join(os7.homedir(), ".exe-os", "intercom.log");
2110
+ DEBOUNCE_FILE = path11.join(SESSION_CACHE, "intercom-debounce.json");
1988
2111
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
1989
2112
  }
1990
2113
  });
1991
2114
 
1992
2115
  // src/lib/tasks-review.ts
1993
- import path11 from "path";
1994
- import { existsSync as existsSync10, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
2116
+ import path12 from "path";
2117
+ import { existsSync as existsSync11, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
1995
2118
  async function listPendingReviews(limit, sessionScope) {
1996
2119
  const client = getClient();
1997
2120
  if (sessionScope) {
1998
2121
  const result2 = await client.execute({
1999
2122
  sql: `SELECT title, assigned_to, project_name FROM tasks
2000
2123
  WHERE status = 'needs_review'
2001
- AND (session_scope = ? OR session_scope IS NULL)
2124
+ AND session_scope = ?
2002
2125
  ORDER BY priority ASC, created_at DESC LIMIT ?`,
2003
2126
  args: [sessionScope, limit]
2004
2127
  });
@@ -2050,12 +2173,13 @@ var init_task_scope = __esm({
2050
2173
  });
2051
2174
 
2052
2175
  // src/bin/exe-heartbeat.ts
2053
- import { createHash } from "crypto";
2054
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
2176
+ import { createHash as createHash2 } from "crypto";
2177
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6 } from "fs";
2055
2178
  import os8 from "os";
2056
- import path12 from "path";
2179
+ import path13 from "path";
2057
2180
 
2058
2181
  // src/lib/store.ts
2182
+ import { createHash } from "crypto";
2059
2183
  init_database();
2060
2184
 
2061
2185
  // src/lib/keychain.ts
@@ -2091,12 +2215,20 @@ async function getMasterKey() {
2091
2215
  }
2092
2216
  const keyPath = getKeyPath();
2093
2217
  if (!existsSync3(keyPath)) {
2218
+ process.stderr.write(
2219
+ `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2220
+ `
2221
+ );
2094
2222
  return null;
2095
2223
  }
2096
2224
  try {
2097
2225
  const content = await readFile3(keyPath, "utf-8");
2098
2226
  return Buffer.from(content.trim(), "base64");
2099
- } catch {
2227
+ } catch (err) {
2228
+ process.stderr.write(
2229
+ `[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
2230
+ `
2231
+ );
2100
2232
  return null;
2101
2233
  }
2102
2234
  }
@@ -2189,6 +2321,7 @@ import { realpathSync } from "fs";
2189
2321
  import { fileURLToPath } from "url";
2190
2322
  function isMainModule(importMetaUrl) {
2191
2323
  if (process.argv[1] == null) return false;
2324
+ if (process.argv[1].includes("mcp/server")) return false;
2192
2325
  try {
2193
2326
  const scriptPath = realpathSync(process.argv[1]);
2194
2327
  const modulePath = realpathSync(fileURLToPath(importMetaUrl));
@@ -2214,18 +2347,18 @@ var MESSAGE_PREVIEW_CHARS = 80;
2214
2347
  var MARKER_FILENAME = "exe-heartbeat-marker.json";
2215
2348
  var SESSION_CACHE_SUBDIR = "session-cache";
2216
2349
  function resolveExeOsDir() {
2217
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path12.join(os8.homedir(), ".exe-os");
2350
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path13.join(os8.homedir(), ".exe-os");
2218
2351
  }
2219
2352
  function getMarkerDir() {
2220
- return path12.join(resolveExeOsDir(), SESSION_CACHE_SUBDIR);
2353
+ return path13.join(resolveExeOsDir(), SESSION_CACHE_SUBDIR);
2221
2354
  }
2222
2355
  function getMarkerPath() {
2223
- return path12.join(getMarkerDir(), MARKER_FILENAME);
2356
+ return path13.join(getMarkerDir(), MARKER_FILENAME);
2224
2357
  }
2225
2358
  var UNREAD_MESSAGE_STATUSES = ["pending", "delivered"];
2226
2359
  function readMarker() {
2227
2360
  try {
2228
- const raw = readFileSync8(getMarkerPath(), "utf8");
2361
+ const raw = readFileSync9(getMarkerPath(), "utf8");
2229
2362
  const parsed = JSON.parse(raw);
2230
2363
  if (typeof parsed.lastFiredAt !== "string" || typeof parsed.lastSurfaceHash !== "string") {
2231
2364
  return null;
@@ -2237,13 +2370,13 @@ function readMarker() {
2237
2370
  }
2238
2371
  function writeMarker(marker) {
2239
2372
  try {
2240
- mkdirSync5(getMarkerDir(), { recursive: true });
2241
- writeFileSync5(getMarkerPath(), JSON.stringify(marker));
2373
+ mkdirSync6(getMarkerDir(), { recursive: true });
2374
+ writeFileSync6(getMarkerPath(), JSON.stringify(marker));
2242
2375
  } catch {
2243
2376
  }
2244
2377
  }
2245
2378
  function hashOutput(text) {
2246
- return createHash("sha256").update(text).digest("hex");
2379
+ return createHash2("sha256").update(text).digest("hex");
2247
2380
  }
2248
2381
  async function queryPendingReviews() {
2249
2382
  let sessionScope;
@@ -2309,10 +2442,13 @@ async function queryStaleInProgress(thresholdHours) {
2309
2442
  }
2310
2443
  async function queryNewErrors(sinceIso) {
2311
2444
  const client = getClient();
2445
+ const erScope = sessionScopeFilter();
2312
2446
  const result = await client.execute({
2313
- sql: `SELECT COUNT(*) as cnt FROM memories
2447
+ sql: erScope.args.length > 0 ? `SELECT COUNT(*) as cnt FROM memories
2448
+ WHERE has_error = 1 AND timestamp > ?
2449
+ AND agent_id IN (SELECT DISTINCT assigned_to FROM tasks WHERE 1=1${erScope.sql})` : `SELECT COUNT(*) as cnt FROM memories
2314
2450
  WHERE has_error = 1 AND timestamp > ?`,
2315
- args: [sinceIso]
2451
+ args: erScope.args.length > 0 ? [sinceIso, ...erScope.args] : [sinceIso]
2316
2452
  });
2317
2453
  const count = Number(result.rows[0]?.cnt ?? 0);
2318
2454
  if (count === 0) return "";