@askexenow/exe-os 0.9.19 → 0.9.20

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.
package/dist/bin/cli.js CHANGED
@@ -12333,11 +12333,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
12333
12333
  if (pending instanceof Promise) {
12334
12334
  pending.then((count) => {
12335
12335
  if (count > 0) {
12336
- execSync8(
12337
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
12338
- { timeout: 3e3 }
12339
- );
12340
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
12336
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
12341
12337
  }
12342
12338
  }).catch(() => {
12343
12339
  });
@@ -15623,6 +15619,9 @@ async function runUpdate(cliArgs) {
15623
15619
  console.log(" Try: npm cache clean --force && npm install -g @askexenow/exe-os@latest");
15624
15620
  }
15625
15621
  console.log(" Hooks re-wired, daemon restarted automatically.");
15622
+ console.log("");
15623
+ console.log(" \x1B[33m\u26A1 Run /mcp in each active Claude Code session to pick up new tools.\x1B[0m");
15624
+ console.log(" \x1B[2m(MCP servers can't hot-reload \u2014 Claude Code needs to reconnect them.)\x1B[0m");
15626
15625
  try {
15627
15626
  const { existsSync: exists, readFileSync: readFile8 } = await import("fs");
15628
15627
  const p = await import("path");
@@ -7551,11 +7551,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
7551
7551
  if (pending instanceof Promise) {
7552
7552
  pending.then((count) => {
7553
7553
  if (count > 0) {
7554
- execSync7(
7555
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
7556
- { timeout: 3e3 }
7557
- );
7558
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
7554
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
7559
7555
  }
7560
7556
  }).catch(() => {
7561
7557
  });
@@ -6131,11 +6131,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
6131
6131
  if (pending instanceof Promise) {
6132
6132
  pending.then((count) => {
6133
6133
  if (count > 0) {
6134
- execSync6(
6135
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
6136
- { timeout: 3e3 }
6137
- );
6138
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
6134
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
6139
6135
  }
6140
6136
  }).catch(() => {
6141
6137
  });
@@ -10968,11 +10968,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
10968
10968
  if (pending instanceof Promise) {
10969
10969
  pending.then((count) => {
10970
10970
  if (count > 0) {
10971
- execSync6(
10972
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
10973
- { timeout: 3e3 }
10974
- );
10975
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
10971
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
10976
10972
  }
10977
10973
  }).catch(() => {
10978
10974
  });
@@ -12265,7 +12261,7 @@ var WebhookServer = class {
12265
12261
  sendJson(res, 200, {
12266
12262
  status: "ok",
12267
12263
  uptime,
12268
- handlers: [...this.handlers.keys()]
12264
+ adapterCount: this.handlers.size
12269
12265
  });
12270
12266
  }
12271
12267
  async handleQuery(req, res) {
@@ -12418,13 +12414,24 @@ function matchesChannel(msgChannel, matchChannel) {
12418
12414
  const channels = Array.isArray(matchChannel) ? matchChannel : [matchChannel];
12419
12415
  return channels.includes(msgChannel);
12420
12416
  }
12417
+ var MAX_REGEX_LENGTH = 200;
12418
+ function safeRegExp(pattern, flags) {
12419
+ if (pattern.length > MAX_REGEX_LENGTH) return null;
12420
+ try {
12421
+ return new RegExp(pattern, flags);
12422
+ } catch {
12423
+ return null;
12424
+ }
12425
+ }
12421
12426
  function matchesSender(msgSender, matchSender) {
12422
12427
  if (!matchSender) return true;
12423
- return new RegExp(matchSender).test(msgSender);
12428
+ const re = safeRegExp(matchSender);
12429
+ return re ? re.test(msgSender) : false;
12424
12430
  }
12425
12431
  function matchesTextPattern(msgText, matchPattern) {
12426
12432
  if (!matchPattern) return true;
12427
- return new RegExp(matchPattern, "i").test(msgText);
12433
+ const re = safeRegExp(matchPattern, "i");
12434
+ return re ? re.test(msgText) : false;
12428
12435
  }
12429
12436
  function matchesRoute(msg, match) {
12430
12437
  return matchesPlatform(msg.platform, match.platform) && matchesChannel(msg.channelId, match.channelId) && matchesSender(msg.senderId, match.senderId) && matchesTextPattern(msg.text, match.textPattern);
@@ -7264,11 +7264,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName2, taskTit
7264
7264
  if (pending instanceof Promise) {
7265
7265
  pending.then((count) => {
7266
7266
  if (count > 0) {
7267
- execSync6(
7268
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
7269
- { timeout: 3e3 }
7270
- );
7271
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName2} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
7267
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName2} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
7272
7268
  }
7273
7269
  }).catch(() => {
7274
7270
  });
@@ -6048,11 +6048,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
6048
6048
  if (pending instanceof Promise) {
6049
6049
  pending.then((count) => {
6050
6050
  if (count > 0) {
6051
- execSync6(
6052
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
6053
- { timeout: 3e3 }
6054
- );
6055
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
6051
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
6056
6052
  }
6057
6053
  }).catch(() => {
6058
6054
  });
@@ -1597,7 +1597,7 @@ var init_installer2 = __esm({
1597
1597
 
1598
1598
  // src/bin/install.ts
1599
1599
  init_installer();
1600
- import { existsSync as existsSync10, readFileSync as readFileSync7, unlinkSync as unlinkSync3, readdirSync as readdirSync2, openSync, closeSync } from "fs";
1600
+ import { existsSync as existsSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync6, unlinkSync as unlinkSync3, readdirSync as readdirSync2, openSync, closeSync } from "fs";
1601
1601
  import { spawn, execSync as execSync3 } from "child_process";
1602
1602
  import path9 from "path";
1603
1603
  import os7 from "os";
@@ -1777,6 +1777,13 @@ function restartDaemon() {
1777
1777
  }
1778
1778
  } catch {
1779
1779
  }
1780
+ try {
1781
+ const versionPath = path9.join(EXE_DIR, "mcp-version");
1782
+ writeFileSync6(versionPath, `deploy-${Date.now()}`);
1783
+ process.stderr.write(`exe-os: MCP version marker updated \u2014 servers will hot-reload within 10s
1784
+ `);
1785
+ } catch {
1786
+ }
1780
1787
  try {
1781
1788
  const wpDir = path9.join(EXE_DIR, "worker-pids");
1782
1789
  if (existsSync10(wpDir)) {
@@ -7041,11 +7041,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
7041
7041
  if (pending instanceof Promise) {
7042
7042
  pending.then((count) => {
7043
7043
  if (count > 0) {
7044
- execSync6(
7045
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
7046
- { timeout: 3e3 }
7047
- );
7048
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
7044
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
7049
7045
  }
7050
7046
  }).catch(() => {
7051
7047
  });
@@ -6119,11 +6119,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
6119
6119
  if (pending instanceof Promise) {
6120
6120
  pending.then((count) => {
6121
6121
  if (count > 0) {
6122
- execSync6(
6123
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
6124
- { timeout: 3e3 }
6125
- );
6126
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
6122
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
6127
6123
  }
6128
6124
  }).catch(() => {
6129
6125
  });
@@ -724,6 +724,9 @@ async function runUpdate(cliArgs) {
724
724
  console.log(" Try: npm cache clean --force && npm install -g @askexenow/exe-os@latest");
725
725
  }
726
726
  console.log(" Hooks re-wired, daemon restarted automatically.");
727
+ console.log("");
728
+ console.log(" \x1B[33m\u26A1 Run /mcp in each active Claude Code session to pick up new tools.\x1B[0m");
729
+ console.log(" \x1B[2m(MCP servers can't hot-reload \u2014 Claude Code needs to reconnect them.)\x1B[0m");
727
730
  try {
728
731
  const { existsSync: exists, readFileSync: readFile2 } = await import("fs");
729
732
  const p = await import("path");
@@ -8884,11 +8884,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
8884
8884
  if (pending instanceof Promise) {
8885
8885
  pending.then((count) => {
8886
8886
  if (count > 0) {
8887
- execSync6(
8888
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
8889
- { timeout: 3e3 }
8890
- );
8891
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
8887
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
8892
8888
  }
8893
8889
  }).catch(() => {
8894
8890
  });
@@ -9552,13 +9548,24 @@ function matchesChannel(msgChannel, matchChannel) {
9552
9548
  const channels = Array.isArray(matchChannel) ? matchChannel : [matchChannel];
9553
9549
  return channels.includes(msgChannel);
9554
9550
  }
9551
+ var MAX_REGEX_LENGTH = 200;
9552
+ function safeRegExp(pattern, flags) {
9553
+ if (pattern.length > MAX_REGEX_LENGTH) return null;
9554
+ try {
9555
+ return new RegExp(pattern, flags);
9556
+ } catch {
9557
+ return null;
9558
+ }
9559
+ }
9555
9560
  function matchesSender(msgSender, matchSender) {
9556
9561
  if (!matchSender) return true;
9557
- return new RegExp(matchSender).test(msgSender);
9562
+ const re = safeRegExp(matchSender);
9563
+ return re ? re.test(msgSender) : false;
9558
9564
  }
9559
9565
  function matchesTextPattern(msgText, matchPattern) {
9560
9566
  if (!matchPattern) return true;
9561
- return new RegExp(matchPattern, "i").test(msgText);
9567
+ const re = safeRegExp(matchPattern, "i");
9568
+ return re ? re.test(msgText) : false;
9562
9569
  }
9563
9570
  function matchesRoute(msg, match) {
9564
9571
  return matchesPlatform(msg.platform, match.platform) && matchesChannel(msg.channelId, match.channelId) && matchesSender(msg.senderId, match.senderId) && matchesTextPattern(msg.text, match.textPattern);
@@ -9598,6 +9605,12 @@ function validateGatewayConfig(config2) {
9598
9605
  if (!route.target) {
9599
9606
  warnings.push(`Route "${route.name}" has no target employee`);
9600
9607
  }
9608
+ if (route.match.senderId && !safeRegExp(route.match.senderId)) {
9609
+ warnings.push(`Route "${route.name}" has invalid senderId regex: ${route.match.senderId}`);
9610
+ }
9611
+ if (route.match.textPattern && !safeRegExp(route.match.textPattern, "i")) {
9612
+ warnings.push(`Route "${route.name}" has invalid textPattern regex: ${route.match.textPattern}`);
9613
+ }
9601
9614
  const isEmptyMatch = !route.match.platform && !route.match.channelId && !route.match.senderId && !route.match.textPattern;
9602
9615
  if (isEmptyMatch && config2.routes.indexOf(route) !== config2.routes.length - 1) {
9603
9616
  warnings.push(
@@ -5315,11 +5315,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
5315
5315
  if (pending instanceof Promise) {
5316
5316
  pending.then((count) => {
5317
5317
  if (count > 0) {
5318
- execSync4(
5319
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
5320
- { timeout: 3e3 }
5321
- );
5322
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
5318
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
5323
5319
  }
5324
5320
  }).catch(() => {
5325
5321
  });
@@ -6047,11 +6047,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
6047
6047
  if (pending instanceof Promise) {
6048
6048
  pending.then((count) => {
6049
6049
  if (count > 0) {
6050
- execSync6(
6051
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
6052
- { timeout: 3e3 }
6053
- );
6054
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
6050
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
6055
6051
  }
6056
6052
  }).catch(() => {
6057
6053
  });
@@ -6031,11 +6031,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
6031
6031
  if (pending instanceof Promise) {
6032
6032
  pending.then((count) => {
6033
6033
  if (count > 0) {
6034
- execSync7(
6035
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
6036
- { timeout: 3e3 }
6037
- );
6038
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
6034
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
6039
6035
  }
6040
6036
  }).catch(() => {
6041
6037
  });
@@ -8585,11 +8585,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
8585
8585
  if (pending instanceof Promise) {
8586
8586
  pending.then((count) => {
8587
8587
  if (count > 0) {
8588
- execSync9(
8589
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
8590
- { timeout: 3e3 }
8591
- );
8592
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
8588
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
8593
8589
  }
8594
8590
  }).catch(() => {
8595
8591
  });
@@ -10152,7 +10148,8 @@ process.stdin.on("end", async () => {
10152
10148
  transport.sendKeys(session, nudgeMsg);
10153
10149
  if (rtConfig.runtime === "codex" || rtConfig.runtime === "opencode") {
10154
10150
  try {
10155
- execSync10(`tmux send-keys -t ${session} Tab`, { encoding: "utf8", timeout: 2e3 });
10151
+ const { execFileSync: efs } = __require("child_process");
10152
+ efs("tmux", ["send-keys", "-t", session, "Tab"], { encoding: "utf8", timeout: 2e3 });
10156
10153
  } catch {
10157
10154
  }
10158
10155
  }
@@ -6240,11 +6240,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
6240
6240
  if (pending instanceof Promise) {
6241
6241
  pending.then((count) => {
6242
6242
  if (count > 0) {
6243
- execSync7(
6244
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
6245
- { timeout: 3e3 }
6246
- );
6247
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
6243
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
6248
6244
  }
6249
6245
  }).catch(() => {
6250
6246
  });
package/dist/index.js CHANGED
@@ -6420,11 +6420,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
6420
6420
  if (pending instanceof Promise) {
6421
6421
  pending.then((count) => {
6422
6422
  if (count > 0) {
6423
- execSync7(
6424
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
6425
- { timeout: 3e3 }
6426
- );
6427
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
6423
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
6428
6424
  }
6429
6425
  }).catch(() => {
6430
6426
  });
@@ -12299,13 +12295,24 @@ function matchesChannel(msgChannel, matchChannel) {
12299
12295
  const channels = Array.isArray(matchChannel) ? matchChannel : [matchChannel];
12300
12296
  return channels.includes(msgChannel);
12301
12297
  }
12298
+ var MAX_REGEX_LENGTH = 200;
12299
+ function safeRegExp(pattern, flags) {
12300
+ if (pattern.length > MAX_REGEX_LENGTH) return null;
12301
+ try {
12302
+ return new RegExp(pattern, flags);
12303
+ } catch {
12304
+ return null;
12305
+ }
12306
+ }
12302
12307
  function matchesSender(msgSender, matchSender) {
12303
12308
  if (!matchSender) return true;
12304
- return new RegExp(matchSender).test(msgSender);
12309
+ const re = safeRegExp(matchSender);
12310
+ return re ? re.test(msgSender) : false;
12305
12311
  }
12306
12312
  function matchesTextPattern(msgText, matchPattern) {
12307
12313
  if (!matchPattern) return true;
12308
- return new RegExp(matchPattern, "i").test(msgText);
12314
+ const re = safeRegExp(matchPattern, "i");
12315
+ return re ? re.test(msgText) : false;
12309
12316
  }
12310
12317
  function matchesRoute(msg, match) {
12311
12318
  return matchesPlatform(msg.platform, match.platform) && matchesChannel(msg.channelId, match.channelId) && matchesSender(msg.senderId, match.senderId) && matchesTextPattern(msg.text, match.textPattern);
@@ -12345,6 +12352,12 @@ function validateGatewayConfig(config2) {
12345
12352
  if (!route.target) {
12346
12353
  warnings.push(`Route "${route.name}" has no target employee`);
12347
12354
  }
12355
+ if (route.match.senderId && !safeRegExp(route.match.senderId)) {
12356
+ warnings.push(`Route "${route.name}" has invalid senderId regex: ${route.match.senderId}`);
12357
+ }
12358
+ if (route.match.textPattern && !safeRegExp(route.match.textPattern, "i")) {
12359
+ warnings.push(`Route "${route.name}" has invalid textPattern regex: ${route.match.textPattern}`);
12360
+ }
12348
12361
  const isEmptyMatch = !route.match.platform && !route.match.channelId && !route.match.senderId && !route.match.textPattern;
12349
12362
  if (isEmptyMatch && config2.routes.indexOf(route) !== config2.routes.length - 1) {
12350
12363
  warnings.push(
@@ -8046,11 +8046,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
8046
8046
  if (pending instanceof Promise) {
8047
8047
  pending.then((count) => {
8048
8048
  if (count > 0) {
8049
- execSync7(
8050
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
8051
- { timeout: 3e3 }
8052
- );
8053
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
8049
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
8054
8050
  }
8055
8051
  }).catch(() => {
8056
8052
  });
package/dist/lib/tasks.js CHANGED
@@ -2142,11 +2142,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
2142
2142
  if (pending instanceof Promise) {
2143
2143
  pending.then((count) => {
2144
2144
  if (count > 0) {
2145
- execSync4(
2146
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
2147
- { timeout: 3e3 }
2148
- );
2149
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
2145
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
2150
2146
  }
2151
2147
  }).catch(() => {
2152
2148
  });
@@ -4167,11 +4167,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
4167
4167
  if (pending instanceof Promise) {
4168
4168
  pending.then((count) => {
4169
4169
  if (count > 0) {
4170
- execSync6(
4171
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
4172
- { timeout: 3e3 }
4173
- );
4174
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
4170
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
4175
4171
  }
4176
4172
  }).catch(() => {
4177
4173
  });
@@ -5792,8 +5792,8 @@ async function hybridSearch(queryText, agentId, options) {
5792
5792
  try {
5793
5793
  const fs = await import("fs");
5794
5794
  const path44 = await import("path");
5795
- const os18 = await import("os");
5796
- const logPath = path44.join(os18.homedir(), ".exe-os", "search-quality.jsonl");
5795
+ const os19 = await import("os");
5796
+ const logPath = path44.join(os19.homedir(), ".exe-os", "search-quality.jsonl");
5797
5797
  fs.mkdirSync(path44.dirname(logPath), { recursive: true });
5798
5798
  fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
5799
5799
  } catch {
@@ -8491,11 +8491,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
8491
8491
  if (pending instanceof Promise) {
8492
8492
  pending.then((count) => {
8493
8493
  if (count > 0) {
8494
- execSync7(
8495
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
8496
- { timeout: 3e3 }
8497
- );
8498
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
8494
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
8499
8495
  }
8500
8496
  }).catch(() => {
8501
8497
  });
@@ -12130,8 +12126,9 @@ init_database();
12130
12126
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12131
12127
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12132
12128
  import { spawn as spawn4 } from "child_process";
12133
- import { existsSync as existsSync33, openSync as openSync3, mkdirSync as mkdirSync17, closeSync as closeSync3 } from "fs";
12129
+ import { existsSync as existsSync33, openSync as openSync3, mkdirSync as mkdirSync17, closeSync as closeSync3, readFileSync as readFileSync28 } from "fs";
12134
12130
  import path43 from "path";
12131
+ import os18 from "os";
12135
12132
  import { fileURLToPath as fileURLToPath5 } from "url";
12136
12133
 
12137
12134
  // src/mcp/tools/recall-my-memory.ts
@@ -18920,8 +18917,8 @@ function registerExportGraph(server2) {
18920
18917
  const html = await exportGraphHTML(client);
18921
18918
  const fs = await import("fs");
18922
18919
  const path44 = await import("path");
18923
- const os18 = await import("os");
18924
- const outDir = path44.join(os18.homedir(), ".exe-os", "exports");
18920
+ const os19 = await import("os");
18921
+ const outDir = path44.join(os19.homedir(), ".exe-os", "exports");
18925
18922
  fs.mkdirSync(outDir, { recursive: true });
18926
18923
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
18927
18924
  const filePath = path44.join(outDir, `graph-${timestamp}.html`);
@@ -23072,6 +23069,28 @@ try {
23072
23069
  }
23073
23070
  }, 3e4);
23074
23071
  _ppidWatchdog.unref();
23072
+ const MCP_VERSION_PATH = path43.join(os18.homedir(), ".exe-os", "mcp-version");
23073
+ let _currentMcpVersion = null;
23074
+ try {
23075
+ _currentMcpVersion = existsSync33(MCP_VERSION_PATH) ? readFileSync28(MCP_VERSION_PATH, "utf8").trim() : null;
23076
+ } catch {
23077
+ }
23078
+ const _versionWatchdog = setInterval(() => {
23079
+ try {
23080
+ if (!existsSync33(MCP_VERSION_PATH)) return;
23081
+ const diskVersion = readFileSync28(MCP_VERSION_PATH, "utf8").trim();
23082
+ if (_currentMcpVersion && diskVersion !== _currentMcpVersion) {
23083
+ process.stderr.write(
23084
+ `[exe-os] MCP version changed (${_currentMcpVersion} \u2192 ${diskVersion}). Hot-reloading...
23085
+ `
23086
+ );
23087
+ void shutdown("hot_reload");
23088
+ }
23089
+ if (!_currentMcpVersion) _currentMcpVersion = diskVersion;
23090
+ } catch {
23091
+ }
23092
+ }, 1e4);
23093
+ _versionWatchdog.unref();
23075
23094
  const BACKFILL_CHECK_MS = 5 * 60 * 1e3;
23076
23095
  _backfillTimer = setInterval(async () => {
23077
23096
  try {
@@ -2381,11 +2381,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
2381
2381
  if (pending instanceof Promise) {
2382
2382
  pending.then((count) => {
2383
2383
  if (count > 0) {
2384
- execSync4(
2385
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
2386
- { timeout: 3e3 }
2387
- );
2388
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
2384
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
2389
2385
  }
2390
2386
  }).catch(() => {
2391
2387
  });
@@ -2145,11 +2145,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
2145
2145
  if (pending instanceof Promise) {
2146
2146
  pending.then((count) => {
2147
2147
  if (count > 0) {
2148
- execSync4(
2149
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
2150
- { timeout: 3e3 }
2151
- );
2152
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
2148
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
2153
2149
  }
2154
2150
  }).catch(() => {
2155
2151
  });
@@ -6181,11 +6181,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
6181
6181
  if (pending instanceof Promise) {
6182
6182
  pending.then((count) => {
6183
6183
  if (count > 0) {
6184
- execSync7(
6185
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
6186
- { timeout: 3e3 }
6187
- );
6188
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
6184
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
6189
6185
  }
6190
6186
  }).catch(() => {
6191
6187
  });
package/dist/tui/App.js CHANGED
@@ -6785,11 +6785,7 @@ function notifyCoordinatorTaskCompletion(coordinatorSession, agentName, taskTitl
6785
6785
  if (pending instanceof Promise) {
6786
6786
  pending.then((count) => {
6787
6787
  if (count > 0) {
6788
- execSync7(
6789
- `tmux send-keys -t ${JSON.stringify(coordinatorSession)} '/exe-intercom' Enter`,
6790
- { timeout: 3e3 }
6791
- );
6792
- logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending)`);
6788
+ logIntercom(`COMPLETION \u2192 ${coordinatorSession} (${agentName} completed "${taskTitle.slice(0, 50)}", ${count} reviews pending \u2014 hook will surface)`);
6793
6789
  }
6794
6790
  }).catch(() => {
6795
6791
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.19",
3
+ "version": "0.9.20",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "CC-BY-NC-4.0",
6
6
  "type": "module",
@@ -67,14 +67,14 @@
67
67
  "test:watch": "vitest",
68
68
  "typecheck": "tsc --noEmit",
69
69
  "build": "tsup && mkdir -p dist/assets && cp src/assets/tmux.conf dist/assets/ && cp src/assets/ghostty.conf dist/assets/ && cp src/assets/statusline-command.sh dist/assets/ && cp src/bin/exe-start.sh dist/bin/exe-start.sh",
70
- "deploy": "node dist/bin/pre-build-guard.js 2>/dev/null; (kill $(cat ~/.exe-os/exed.pid 2>/dev/null) 2>/dev/null; pgrep -f exe-daemon.js | xargs kill 2>/dev/null; true) && tsup && mkdir -p dist/assets && cp src/assets/tmux.conf dist/assets/ && cp src/assets/ghostty.conf dist/assets/ && cp src/assets/statusline-command.sh dist/assets/ && cp src/bin/exe-start.sh dist/bin/exe-start.sh && npm install -g . && node dist/bin/install.js --global && echo '[exe-os] Deploy complete. MCP servers will auto-reconnect on next tool call.'",
70
+ "deploy": "node dist/bin/pre-build-guard.js 2>/dev/null; (kill $(cat ~/.exe-os/exed.pid 2>/dev/null) 2>/dev/null; pgrep -f exe-daemon.js | xargs kill 2>/dev/null; true) && tsup && mkdir -p dist/assets && cp src/assets/tmux.conf dist/assets/ && cp src/assets/ghostty.conf dist/assets/ && cp src/assets/statusline-command.sh dist/assets/ && cp src/bin/exe-start.sh dist/bin/exe-start.sh && npm install -g . && node dist/bin/install.js --global && echo '[exe-os] Deploy complete. Run /mcp in active sessions to reconnect.'",
71
71
  "postinstall": "node dist/bin/install.js --global 2>/dev/null || true",
72
72
  "prepublishOnly": "npm run typecheck && npm run build && node dist/bin/customer-readiness.js",
73
73
  "test:publish": "npx vitest run --maxWorkers=4 --exclude 'tests/tui/**' --exclude 'tests/lib/tmux-routing.test.ts' --exclude 'tests/lib/intercom-routing.test.ts' --exclude 'tests/gateway/**' --exclude 'tests/installer/setup-wizard.test.ts' --exclude 'tests/mcp/ingest-document.test.ts' --exclude 'tests/lib/hybrid-search.test.ts' --exclude 'tests/lib/worker-gate.test.ts'",
74
74
  "benchmark:longmemeval": "npx tsx tests/benchmarks/longmemeval.ts"
75
75
  },
76
76
  "dependencies": {
77
- "@anthropic-ai/sdk": "^0.80.0",
77
+ "@anthropic-ai/sdk": "^0.95.1",
78
78
  "@discordjs/voice": "^0.19.2",
79
79
  "@libsql/client": "^0.14.0",
80
80
  "@modelcontextprotocol/sdk": "^1.27.1",