@askexenow/exe-os 0.8.49 → 0.8.51

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
@@ -6096,6 +6096,159 @@ var init_setup_wizard = __esm({
6096
6096
  }
6097
6097
  });
6098
6098
 
6099
+ // src/lib/update-check.ts
6100
+ import { execSync as execSync3 } from "child_process";
6101
+ import { readFileSync as readFileSync9 } from "fs";
6102
+ import path14 from "path";
6103
+ function getLocalVersion(packageRoot) {
6104
+ const pkgPath = path14.join(packageRoot, "package.json");
6105
+ const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
6106
+ return pkg.version;
6107
+ }
6108
+ function getRemoteVersion() {
6109
+ try {
6110
+ const output = execSync3("npm view @askexenow/exe-os version", {
6111
+ encoding: "utf-8",
6112
+ timeout: 15e3,
6113
+ stdio: ["pipe", "pipe", "pipe"]
6114
+ });
6115
+ return output.trim();
6116
+ } catch {
6117
+ return null;
6118
+ }
6119
+ }
6120
+ function checkForUpdate(packageRoot) {
6121
+ const localVersion = getLocalVersion(packageRoot);
6122
+ const remoteVersion = getRemoteVersion();
6123
+ if (!remoteVersion) {
6124
+ return {
6125
+ updateAvailable: false,
6126
+ localVersion,
6127
+ error: "Could not reach npm registry or package not published yet"
6128
+ };
6129
+ }
6130
+ if (remoteVersion === localVersion) {
6131
+ return { updateAvailable: false, localVersion, remoteVersion };
6132
+ }
6133
+ return { updateAvailable: true, localVersion, remoteVersion };
6134
+ }
6135
+ var init_update_check = __esm({
6136
+ "src/lib/update-check.ts"() {
6137
+ "use strict";
6138
+ }
6139
+ });
6140
+
6141
+ // src/bin/update.ts
6142
+ var update_exports = {};
6143
+ __export(update_exports, {
6144
+ checkForUpdate: () => checkForUpdate,
6145
+ getLocalVersion: () => getLocalVersion,
6146
+ getRemoteVersion: () => getRemoteVersion,
6147
+ runUpdate: () => runUpdate
6148
+ });
6149
+ import { execSync as execSync4 } from "child_process";
6150
+ import { createInterface as createInterface3 } from "readline";
6151
+ async function runUpdate(cliArgs) {
6152
+ const args2 = cliArgs ?? process.argv.slice(2);
6153
+ const autoMode = args2.includes("--auto") || args2.includes("-y");
6154
+ const checkOnly = args2.includes("--check");
6155
+ const packageRoot = new URL("../..", import.meta.url).pathname;
6156
+ const result = checkForUpdate(packageRoot);
6157
+ if (result.error) {
6158
+ console.error(`\u26A0\uFE0F ${result.error}`);
6159
+ process.exit(0);
6160
+ }
6161
+ if (checkOnly) {
6162
+ if (result.updateAvailable) {
6163
+ console.log(`Update available: v${result.localVersion} \u2192 v${result.remoteVersion}`);
6164
+ } else {
6165
+ console.log(`\u2705 exe-os is up to date (v${result.localVersion})`);
6166
+ }
6167
+ process.exit(0);
6168
+ }
6169
+ if (!result.updateAvailable) {
6170
+ console.log(`\u2705 exe-os is up to date (v${result.localVersion})`);
6171
+ process.exit(0);
6172
+ }
6173
+ console.log(`
6174
+ \u{1F4E6} Update available: v${result.localVersion} \u2192 v${result.remoteVersion}
6175
+ `);
6176
+ let proceed = autoMode;
6177
+ if (!proceed) {
6178
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
6179
+ const answer = await new Promise((resolve) => {
6180
+ rl.question("Install update? (Y/n) ", resolve);
6181
+ });
6182
+ rl.close();
6183
+ proceed = answer.toLowerCase() !== "n";
6184
+ }
6185
+ if (!proceed) {
6186
+ console.log("Update skipped.");
6187
+ process.exit(0);
6188
+ }
6189
+ console.log("\n\u{1F9F9} Clearing npm cache...");
6190
+ try {
6191
+ execSync4("npm cache clean --force", { stdio: "pipe" });
6192
+ console.log(" Done");
6193
+ } catch {
6194
+ console.log(" Skipped (non-critical)");
6195
+ }
6196
+ console.log("\u{1F4E5} Installing @askexenow/exe-os@latest...");
6197
+ try {
6198
+ execSync4("npm install -g @askexenow/exe-os@latest", {
6199
+ stdio: ["pipe", "pipe", "pipe"],
6200
+ timeout: 12e4
6201
+ });
6202
+ } catch (err) {
6203
+ console.error("\n\u274C Update failed.");
6204
+ console.error(" Try manually: npm install -g @askexenow/exe-os@latest");
6205
+ if (err instanceof Error && err.message) {
6206
+ console.error(` Error: ${err.message.split("\n")[0]}`);
6207
+ }
6208
+ process.exit(1);
6209
+ }
6210
+ let newVersion;
6211
+ try {
6212
+ newVersion = getLocalVersion(packageRoot);
6213
+ } catch {
6214
+ try {
6215
+ const out = execSync4("npm list -g @askexenow/exe-os --depth=0 2>/dev/null", { encoding: "utf8" });
6216
+ const match = out.match(/@askexenow\/exe-os@(\S+)/);
6217
+ newVersion = match?.[1] ?? "unknown";
6218
+ } catch {
6219
+ newVersion = "unknown";
6220
+ }
6221
+ }
6222
+ const remoteVersion = result.remoteVersion;
6223
+ if (newVersion === remoteVersion) {
6224
+ console.log(`
6225
+ \u2705 Updated to v${newVersion}`);
6226
+ } else if (newVersion !== result.localVersion) {
6227
+ console.log(`
6228
+ \u2705 Updated to v${newVersion} (latest: v${remoteVersion})`);
6229
+ } else {
6230
+ console.log(`
6231
+ \u26A0\uFE0F Version unchanged (v${newVersion}). npm cache may be stale.`);
6232
+ console.log(" Try: npm cache clean --force && npm install -g @askexenow/exe-os@latest");
6233
+ }
6234
+ console.log(" Hooks re-wired, daemon restarted automatically.");
6235
+ console.log("\n\u{1F680} Ready. Start your COO session to use the new version.\n");
6236
+ }
6237
+ var init_update = __esm({
6238
+ "src/bin/update.ts"() {
6239
+ "use strict";
6240
+ init_is_main();
6241
+ init_update_check();
6242
+ init_update_check();
6243
+ if (isMainModule(import.meta.url)) {
6244
+ runUpdate().catch((err) => {
6245
+ console.error(err instanceof Error ? err.message : String(err));
6246
+ process.exit(1);
6247
+ });
6248
+ }
6249
+ }
6250
+ });
6251
+
6099
6252
  // node_modules/es-toolkit/dist/function/debounce.mjs
6100
6253
  function debounce(func, debounceMs, { signal, edges } = {}) {
6101
6254
  let pendingThis = void 0;
@@ -12558,13 +12711,13 @@ __export(tmux_status_exports, {
12558
12711
  parseActivity: () => parseActivity,
12559
12712
  parseContextPercentage: () => parseContextPercentage
12560
12713
  });
12561
- import { execSync as execSync3 } from "child_process";
12714
+ import { execSync as execSync5 } from "child_process";
12562
12715
  function inTmux() {
12563
12716
  if (process.env.TMUX || process.env.TMUX_PANE) return true;
12564
12717
  const term = process.env.TERM ?? "";
12565
12718
  if (term.startsWith("tmux") || term.startsWith("screen")) return true;
12566
12719
  try {
12567
- execSync3("tmux display-message -p '#{session_name}' 2>/dev/null", {
12720
+ execSync5("tmux display-message -p '#{session_name}' 2>/dev/null", {
12568
12721
  encoding: "utf8",
12569
12722
  timeout: 2e3
12570
12723
  });
@@ -12574,12 +12727,12 @@ function inTmux() {
12574
12727
  try {
12575
12728
  let pid = process.ppid;
12576
12729
  for (let depth = 0; depth < 8 && pid > 1; depth++) {
12577
- const comm = execSync3(`ps -p ${pid} -o comm= 2>/dev/null`, {
12730
+ const comm = execSync5(`ps -p ${pid} -o comm= 2>/dev/null`, {
12578
12731
  encoding: "utf8",
12579
12732
  timeout: 1e3
12580
12733
  }).trim();
12581
12734
  if (/tmux/.test(comm)) return true;
12582
- const ppid = execSync3(`ps -p ${pid} -o ppid= 2>/dev/null`, {
12735
+ const ppid = execSync5(`ps -p ${pid} -o ppid= 2>/dev/null`, {
12583
12736
  encoding: "utf8",
12584
12737
  timeout: 1e3
12585
12738
  }).trim();
@@ -12592,7 +12745,7 @@ function inTmux() {
12592
12745
  }
12593
12746
  function listTmuxSessions() {
12594
12747
  try {
12595
- const out = execSync3("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
12748
+ const out = execSync5("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
12596
12749
  encoding: "utf8",
12597
12750
  timeout: 3e3
12598
12751
  });
@@ -12603,7 +12756,7 @@ function listTmuxSessions() {
12603
12756
  }
12604
12757
  function capturePaneLines(windowName, lines = 10) {
12605
12758
  try {
12606
- const out = execSync3(
12759
+ const out = execSync5(
12607
12760
  `tmux capture-pane -t ${JSON.stringify(windowName)} -p 2>/dev/null | tail -${lines}`,
12608
12761
  { encoding: "utf8", timeout: 3e3 }
12609
12762
  );
@@ -12614,7 +12767,7 @@ function capturePaneLines(windowName, lines = 10) {
12614
12767
  }
12615
12768
  function getPaneCwd(windowName) {
12616
12769
  try {
12617
- const out = execSync3(
12770
+ const out = execSync5(
12618
12771
  `tmux display-message -t ${JSON.stringify(windowName)} -p '#{pane_current_path}' 2>/dev/null`,
12619
12772
  { encoding: "utf8", timeout: 3e3 }
12620
12773
  );
@@ -12625,7 +12778,7 @@ function getPaneCwd(windowName) {
12625
12778
  }
12626
12779
  function projectFromPath(dir) {
12627
12780
  try {
12628
- const root = execSync3("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
12781
+ const root = execSync5("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
12629
12782
  encoding: "utf8",
12630
12783
  timeout: 3e3
12631
12784
  }).trim();
@@ -12694,7 +12847,7 @@ function getEmployeeStatuses(employeeNames) {
12694
12847
  }
12695
12848
  let paneAlive = true;
12696
12849
  try {
12697
- const paneStatus = execSync3(
12850
+ const paneStatus = execSync5(
12698
12851
  `tmux list-panes -t ${JSON.stringify(sessionName)} -F '#{pane_dead}' 2>/dev/null`,
12699
12852
  { encoding: "utf8", timeout: 3e3 }
12700
12853
  ).trim();
@@ -14894,10 +15047,10 @@ var init_hooks = __esm({
14894
15047
  });
14895
15048
 
14896
15049
  // src/runtime/safety-checks.ts
14897
- import path14 from "path";
15050
+ import path15 from "path";
14898
15051
  import os6 from "os";
14899
15052
  function checkPathSafety(filePath) {
14900
- const resolved = path14.resolve(filePath);
15053
+ const resolved = path15.resolve(filePath);
14901
15054
  for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
14902
15055
  const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
14903
15056
  if (matches) {
@@ -14907,7 +15060,7 @@ function checkPathSafety(filePath) {
14907
15060
  return { safe: true, bypassImmune: true };
14908
15061
  }
14909
15062
  function checkReadPathSafety(filePath) {
14910
- const resolved = path14.resolve(filePath);
15063
+ const resolved = path15.resolve(filePath);
14911
15064
  const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
14912
15065
  (p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
14913
15066
  );
@@ -14933,11 +15086,11 @@ var init_safety_checks = __esm({
14933
15086
  reason: "Git config can set hooks and command execution"
14934
15087
  },
14935
15088
  {
14936
- pattern: (p) => p.startsWith(path14.join(HOME, ".claude")),
15089
+ pattern: (p) => p.startsWith(path15.join(HOME, ".claude")),
14937
15090
  reason: "Claude configuration files are protected"
14938
15091
  },
14939
15092
  {
14940
- pattern: (p) => p.startsWith(path14.join(HOME, ".exe-os")),
15093
+ pattern: (p) => p.startsWith(path15.join(HOME, ".exe-os")),
14941
15094
  reason: "exe-os configuration files are protected"
14942
15095
  },
14943
15096
  {
@@ -14954,7 +15107,7 @@ var init_safety_checks = __esm({
14954
15107
  },
14955
15108
  {
14956
15109
  pattern: (p) => {
14957
- const name = path14.basename(p);
15110
+ const name = path15.basename(p);
14958
15111
  return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
14959
15112
  },
14960
15113
  reason: "Shell configuration files can execute arbitrary code on login"
@@ -14981,7 +15134,7 @@ __export(file_read_exports, {
14981
15134
  FileReadTool: () => FileReadTool
14982
15135
  });
14983
15136
  import fs3 from "fs/promises";
14984
- import path15 from "path";
15137
+ import path16 from "path";
14985
15138
  import { z } from "zod";
14986
15139
  function isBinary(buf) {
14987
15140
  for (let i = 0; i < buf.length; i++) {
@@ -15017,7 +15170,7 @@ var init_file_read = __esm({
15017
15170
  return { behavior: "allow" };
15018
15171
  },
15019
15172
  async call(input, context) {
15020
- const filePath = path15.isAbsolute(input.file_path) ? input.file_path : path15.resolve(context.cwd, input.file_path);
15173
+ const filePath = path16.isAbsolute(input.file_path) ? input.file_path : path16.resolve(context.cwd, input.file_path);
15021
15174
  let stat2;
15022
15175
  try {
15023
15176
  stat2 = await fs3.stat(filePath);
@@ -15057,7 +15210,7 @@ __export(glob_exports, {
15057
15210
  GlobTool: () => GlobTool
15058
15211
  });
15059
15212
  import fs4 from "fs/promises";
15060
- import path16 from "path";
15213
+ import path17 from "path";
15061
15214
  import { z as z2 } from "zod";
15062
15215
  async function walkDir(dir, maxDepth = 10) {
15063
15216
  const results = [];
@@ -15073,7 +15226,7 @@ async function walkDir(dir, maxDepth = 10) {
15073
15226
  if (entry.isDirectory() && (entry.name === "node_modules" || entry.name === ".git")) {
15074
15227
  continue;
15075
15228
  }
15076
- const fullPath = path16.join(current, entry.name);
15229
+ const fullPath = path17.join(current, entry.name);
15077
15230
  if (entry.isDirectory()) {
15078
15231
  await walk(fullPath, depth + 1);
15079
15232
  } else {
@@ -15107,11 +15260,11 @@ var init_glob = __esm({
15107
15260
  inputSchema: inputSchema2,
15108
15261
  isReadOnly: true,
15109
15262
  async call(input, context) {
15110
- const baseDir = input.path ? path16.isAbsolute(input.path) ? input.path : path16.resolve(context.cwd, input.path) : context.cwd;
15263
+ const baseDir = input.path ? path17.isAbsolute(input.path) ? input.path : path17.resolve(context.cwd, input.path) : context.cwd;
15111
15264
  try {
15112
15265
  const entries = await walkDir(baseDir);
15113
15266
  const matched = entries.filter(
15114
- (e) => simpleGlobMatch(path16.relative(baseDir, e.path), input.pattern)
15267
+ (e) => simpleGlobMatch(path17.relative(baseDir, e.path), input.pattern)
15115
15268
  );
15116
15269
  matched.sort((a, b) => b.mtime - a.mtime);
15117
15270
  if (matched.length === 0) {
@@ -15137,7 +15290,7 @@ __export(grep_exports, {
15137
15290
  });
15138
15291
  import { spawn as spawn2 } from "child_process";
15139
15292
  import fs5 from "fs/promises";
15140
- import path17 from "path";
15293
+ import path18 from "path";
15141
15294
  import { z as z3 } from "zod";
15142
15295
  function runRipgrep(input, searchPath, context) {
15143
15296
  return new Promise((resolve, reject) => {
@@ -15191,7 +15344,7 @@ async function nodeGrep(input, searchPath) {
15191
15344
  }
15192
15345
  for (const entry of entries) {
15193
15346
  if (entry.name === "node_modules" || entry.name === ".git") continue;
15194
- const fullPath = path17.join(dir, entry.name);
15347
+ const fullPath = path18.join(dir, entry.name);
15195
15348
  if (entry.isDirectory()) {
15196
15349
  await walk(fullPath);
15197
15350
  } else {
@@ -15237,7 +15390,7 @@ var init_grep = __esm({
15237
15390
  inputSchema: inputSchema3,
15238
15391
  isReadOnly: true,
15239
15392
  async call(input, context) {
15240
- const searchPath = input.path ? path17.isAbsolute(input.path) ? input.path : path17.resolve(context.cwd, input.path) : context.cwd;
15393
+ const searchPath = input.path ? path18.isAbsolute(input.path) ? input.path : path18.resolve(context.cwd, input.path) : context.cwd;
15241
15394
  try {
15242
15395
  const result = await runRipgrep(input, searchPath, context);
15243
15396
  return result;
@@ -15262,7 +15415,7 @@ __export(file_write_exports, {
15262
15415
  FileWriteTool: () => FileWriteTool
15263
15416
  });
15264
15417
  import fs6 from "fs/promises";
15265
- import path18 from "path";
15418
+ import path19 from "path";
15266
15419
  import { z as z4 } from "zod";
15267
15420
  var inputSchema4, FileWriteTool;
15268
15421
  var init_file_write = __esm({
@@ -15290,8 +15443,8 @@ var init_file_write = __esm({
15290
15443
  return { behavior: "allow" };
15291
15444
  },
15292
15445
  async call(input, context) {
15293
- const filePath = path18.isAbsolute(input.file_path) ? input.file_path : path18.resolve(context.cwd, input.file_path);
15294
- const dir = path18.dirname(filePath);
15446
+ const filePath = path19.isAbsolute(input.file_path) ? input.file_path : path19.resolve(context.cwd, input.file_path);
15447
+ const dir = path19.dirname(filePath);
15295
15448
  await fs6.mkdir(dir, { recursive: true });
15296
15449
  await fs6.writeFile(filePath, input.content, "utf-8");
15297
15450
  return {
@@ -15309,7 +15462,7 @@ __export(file_edit_exports, {
15309
15462
  FileEditTool: () => FileEditTool
15310
15463
  });
15311
15464
  import fs7 from "fs/promises";
15312
- import path19 from "path";
15465
+ import path20 from "path";
15313
15466
  import { z as z5 } from "zod";
15314
15467
  function countOccurrences(haystack, needle) {
15315
15468
  let count = 0;
@@ -15350,7 +15503,7 @@ var init_file_edit = __esm({
15350
15503
  return { behavior: "allow" };
15351
15504
  },
15352
15505
  async call(input, context) {
15353
- const filePath = path19.isAbsolute(input.file_path) ? input.file_path : path19.resolve(context.cwd, input.file_path);
15506
+ const filePath = path20.isAbsolute(input.file_path) ? input.file_path : path20.resolve(context.cwd, input.file_path);
15354
15507
  let content;
15355
15508
  try {
15356
15509
  content = await fs7.readFile(filePath, "utf-8");
@@ -15596,12 +15749,12 @@ __export(session_registry_exports, {
15596
15749
  pruneStaleSessions: () => pruneStaleSessions,
15597
15750
  registerSession: () => registerSession
15598
15751
  });
15599
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, existsSync as existsSync14 } from "fs";
15600
- import { execSync as execSync4 } from "child_process";
15601
- import path20 from "path";
15752
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, existsSync as existsSync14 } from "fs";
15753
+ import { execSync as execSync6 } from "child_process";
15754
+ import path21 from "path";
15602
15755
  import os7 from "os";
15603
15756
  function registerSession(entry) {
15604
- const dir = path20.dirname(REGISTRY_PATH);
15757
+ const dir = path21.dirname(REGISTRY_PATH);
15605
15758
  if (!existsSync14(dir)) {
15606
15759
  mkdirSync6(dir, { recursive: true });
15607
15760
  }
@@ -15616,7 +15769,7 @@ function registerSession(entry) {
15616
15769
  }
15617
15770
  function listSessions() {
15618
15771
  try {
15619
- const raw = readFileSync10(REGISTRY_PATH, "utf8");
15772
+ const raw = readFileSync11(REGISTRY_PATH, "utf8");
15620
15773
  return JSON.parse(raw);
15621
15774
  } catch {
15622
15775
  return [];
@@ -15627,7 +15780,7 @@ function pruneStaleSessions() {
15627
15780
  if (sessions.length === 0) return 0;
15628
15781
  let liveSessions = [];
15629
15782
  try {
15630
- liveSessions = execSync4("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
15783
+ liveSessions = execSync6("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
15631
15784
  encoding: "utf8"
15632
15785
  }).trim().split("\n").filter(Boolean);
15633
15786
  } catch {
@@ -15645,14 +15798,14 @@ var REGISTRY_PATH;
15645
15798
  var init_session_registry = __esm({
15646
15799
  "src/lib/session-registry.ts"() {
15647
15800
  "use strict";
15648
- REGISTRY_PATH = path20.join(os7.homedir(), ".exe-os", "session-registry.json");
15801
+ REGISTRY_PATH = path21.join(os7.homedir(), ".exe-os", "session-registry.json");
15649
15802
  }
15650
15803
  });
15651
15804
 
15652
15805
  // src/tui/views/CommandCenter.tsx
15653
15806
  import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
15654
15807
  import TextInput from "ink-text-input";
15655
- import path21 from "path";
15808
+ import path22 from "path";
15656
15809
  import { homedir as homedir3 } from "os";
15657
15810
  import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
15658
15811
  function CommandCenterView({
@@ -15893,7 +16046,7 @@ function CommandCenterView({
15893
16046
  const demoEntries = DEMO_PROJECTS.map((p) => ({
15894
16047
  projectName: p.projectName,
15895
16048
  exeSession: p.exeSession,
15896
- projectDir: path21.join(homedir3(), p.projectName),
16049
+ projectDir: path22.join(homedir3(), p.projectName),
15897
16050
  employeeCount: p.employees.length,
15898
16051
  activeCount: p.employees.filter((e) => e.status === "active").length,
15899
16052
  memoryCount: p.employees.length * 4e3,
@@ -16463,13 +16616,13 @@ var init_task_router = __esm({
16463
16616
  });
16464
16617
 
16465
16618
  // src/lib/session-key.ts
16466
- import { execSync as execSync5 } from "child_process";
16619
+ import { execSync as execSync7 } from "child_process";
16467
16620
  function getSessionKey() {
16468
16621
  if (_cached) return _cached;
16469
16622
  let pid = process.ppid;
16470
16623
  for (let i = 0; i < 10; i++) {
16471
16624
  try {
16472
- const info = execSync5(`ps -p ${pid} -o ppid=,comm=`, {
16625
+ const info = execSync7(`ps -p ${pid} -o ppid=,comm=`, {
16473
16626
  encoding: "utf8",
16474
16627
  timeout: 2e3
16475
16628
  }).trim();
@@ -16613,14 +16766,14 @@ var init_transport = __esm({
16613
16766
  });
16614
16767
 
16615
16768
  // src/lib/cc-agent-support.ts
16616
- import { execSync as execSync6 } from "child_process";
16769
+ import { execSync as execSync8 } from "child_process";
16617
16770
  function _resetCcAgentSupportCache() {
16618
16771
  _cachedSupport = null;
16619
16772
  }
16620
16773
  function claudeSupportsAgentFlag() {
16621
16774
  if (_cachedSupport !== null) return _cachedSupport;
16622
16775
  try {
16623
- const helpOutput = execSync6("claude --help 2>&1", {
16776
+ const helpOutput = execSync8("claude --help 2>&1", {
16624
16777
  encoding: "utf-8",
16625
16778
  timeout: 5e3
16626
16779
  });
@@ -16663,17 +16816,17 @@ var init_provider_table = __esm({
16663
16816
  });
16664
16817
 
16665
16818
  // src/lib/intercom-queue.ts
16666
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync6, renameSync as renameSync4, existsSync as existsSync15, mkdirSync as mkdirSync7 } from "fs";
16667
- import path22 from "path";
16819
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync6, renameSync as renameSync4, existsSync as existsSync15, mkdirSync as mkdirSync7 } from "fs";
16820
+ import path23 from "path";
16668
16821
  import os8 from "os";
16669
16822
  function ensureDir2() {
16670
- const dir = path22.dirname(QUEUE_PATH);
16823
+ const dir = path23.dirname(QUEUE_PATH);
16671
16824
  if (!existsSync15(dir)) mkdirSync7(dir, { recursive: true });
16672
16825
  }
16673
16826
  function readQueue() {
16674
16827
  try {
16675
16828
  if (!existsSync15(QUEUE_PATH)) return [];
16676
- return JSON.parse(readFileSync11(QUEUE_PATH, "utf8"));
16829
+ return JSON.parse(readFileSync12(QUEUE_PATH, "utf8"));
16677
16830
  } catch {
16678
16831
  return [];
16679
16832
  }
@@ -16705,19 +16858,19 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
16705
16858
  var init_intercom_queue = __esm({
16706
16859
  "src/lib/intercom-queue.ts"() {
16707
16860
  "use strict";
16708
- QUEUE_PATH = path22.join(os8.homedir(), ".exe-os", "intercom-queue.json");
16861
+ QUEUE_PATH = path23.join(os8.homedir(), ".exe-os", "intercom-queue.json");
16709
16862
  TTL_MS = 60 * 60 * 1e3;
16710
- INTERCOM_LOG = path22.join(os8.homedir(), ".exe-os", "intercom.log");
16863
+ INTERCOM_LOG = path23.join(os8.homedir(), ".exe-os", "intercom.log");
16711
16864
  }
16712
16865
  });
16713
16866
 
16714
16867
  // src/lib/plan-limits.ts
16715
- import { readFileSync as readFileSync12, existsSync as existsSync16 } from "fs";
16716
- import path23 from "path";
16868
+ import { readFileSync as readFileSync13, existsSync as existsSync16 } from "fs";
16869
+ import path24 from "path";
16717
16870
  function getLicenseSync() {
16718
16871
  try {
16719
16872
  if (!existsSync16(CACHE_PATH2)) return freeLicense();
16720
- const raw = JSON.parse(readFileSync12(CACHE_PATH2, "utf8"));
16873
+ const raw = JSON.parse(readFileSync13(CACHE_PATH2, "utf8"));
16721
16874
  if (!raw.token || typeof raw.token !== "string") return freeLicense();
16722
16875
  const parts = raw.token.split(".");
16723
16876
  if (parts.length !== 3) return freeLicense();
@@ -16756,7 +16909,7 @@ function assertEmployeeLimitSync(rosterPath) {
16756
16909
  let count = 0;
16757
16910
  try {
16758
16911
  if (existsSync16(filePath)) {
16759
- const raw = readFileSync12(filePath, "utf8");
16912
+ const raw = readFileSync13(filePath, "utf8");
16760
16913
  const employees = JSON.parse(raw);
16761
16914
  count = Array.isArray(employees) ? employees.length : 0;
16762
16915
  }
@@ -16785,16 +16938,16 @@ var init_plan_limits = __esm({
16785
16938
  this.name = "PlanLimitError";
16786
16939
  }
16787
16940
  };
16788
- CACHE_PATH2 = path23.join(EXE_AI_DIR, "license-cache.json");
16941
+ CACHE_PATH2 = path24.join(EXE_AI_DIR, "license-cache.json");
16789
16942
  }
16790
16943
  });
16791
16944
 
16792
16945
  // src/lib/notifications.ts
16793
16946
  import crypto4 from "crypto";
16794
- import path24 from "path";
16947
+ import path25 from "path";
16795
16948
  import os9 from "os";
16796
16949
  import {
16797
- readFileSync as readFileSync13,
16950
+ readFileSync as readFileSync14,
16798
16951
  readdirSync as readdirSync3,
16799
16952
  unlinkSync as unlinkSync5,
16800
16953
  existsSync as existsSync17,
@@ -16877,10 +17030,10 @@ var init_session_kill_telemetry = __esm({
16877
17030
 
16878
17031
  // src/lib/tasks-crud.ts
16879
17032
  import crypto6 from "crypto";
16880
- import path25 from "path";
16881
- import { execSync as execSync7 } from "child_process";
17033
+ import path26 from "path";
17034
+ import { execSync as execSync9 } from "child_process";
16882
17035
  import { mkdir as mkdir6, writeFile as writeFile5, appendFile } from "fs/promises";
16883
- import { existsSync as existsSync18, readFileSync as readFileSync14 } from "fs";
17036
+ import { existsSync as existsSync18, readFileSync as readFileSync15 } from "fs";
16884
17037
  async function writeCheckpoint(input) {
16885
17038
  const client = getClient();
16886
17039
  const row = await resolveTask(client, input.taskId);
@@ -17010,8 +17163,8 @@ async function createTaskCore(input) {
17010
17163
  }
17011
17164
  if (input.baseDir) {
17012
17165
  try {
17013
- await mkdir6(path25.join(input.baseDir, "exe", "output"), { recursive: true });
17014
- await mkdir6(path25.join(input.baseDir, "exe", "research"), { recursive: true });
17166
+ await mkdir6(path26.join(input.baseDir, "exe", "output"), { recursive: true });
17167
+ await mkdir6(path26.join(input.baseDir, "exe", "research"), { recursive: true });
17015
17168
  await ensureArchitectureDoc(input.baseDir, input.projectName);
17016
17169
  await ensureGitignoreExe(input.baseDir);
17017
17170
  } catch {
@@ -17127,12 +17280,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
17127
17280
  if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
17128
17281
  try {
17129
17282
  const since = new Date(taskCreatedAt).toISOString();
17130
- const branch = execSync7(
17283
+ const branch = execSync9(
17131
17284
  "git rev-parse --abbrev-ref HEAD 2>/dev/null",
17132
17285
  { encoding: "utf8", timeout: 3e3 }
17133
17286
  ).trim();
17134
17287
  const branchArg = branch && branch !== "HEAD" ? branch : "";
17135
- const commitCount = execSync7(
17288
+ const commitCount = execSync9(
17136
17289
  `git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
17137
17290
  { encoding: "utf8", timeout: 5e3 }
17138
17291
  ).trim();
@@ -17235,7 +17388,7 @@ async function deleteTaskCore(taskId, _baseDir) {
17235
17388
  return { taskFile, assignedTo, assignedBy, taskSlug };
17236
17389
  }
17237
17390
  async function ensureArchitectureDoc(baseDir, projectName) {
17238
- const archPath = path25.join(baseDir, "exe", "ARCHITECTURE.md");
17391
+ const archPath = path26.join(baseDir, "exe", "ARCHITECTURE.md");
17239
17392
  try {
17240
17393
  if (existsSync18(archPath)) return;
17241
17394
  const template = [
@@ -17270,10 +17423,10 @@ async function ensureArchitectureDoc(baseDir, projectName) {
17270
17423
  }
17271
17424
  }
17272
17425
  async function ensureGitignoreExe(baseDir) {
17273
- const gitignorePath = path25.join(baseDir, ".gitignore");
17426
+ const gitignorePath = path26.join(baseDir, ".gitignore");
17274
17427
  try {
17275
17428
  if (existsSync18(gitignorePath)) {
17276
- const content = readFileSync14(gitignorePath, "utf-8");
17429
+ const content = readFileSync15(gitignorePath, "utf-8");
17277
17430
  if (/^\/?exe\/?$/m.test(content)) return;
17278
17431
  await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
17279
17432
  } else {
@@ -17293,7 +17446,7 @@ var init_tasks_crud = __esm({
17293
17446
  });
17294
17447
 
17295
17448
  // src/lib/tasks-review.ts
17296
- import path26 from "path";
17449
+ import path27 from "path";
17297
17450
  import { existsSync as existsSync19, readdirSync as readdirSync4, unlinkSync as unlinkSync6 } from "fs";
17298
17451
  async function countPendingReviews() {
17299
17452
  const client = getClient();
@@ -17312,8 +17465,18 @@ async function countNewPendingReviewsSince(sinceIso) {
17312
17465
  });
17313
17466
  return Number(result.rows[0]?.cnt) || 0;
17314
17467
  }
17315
- async function listPendingReviews(limit) {
17468
+ async function listPendingReviews(limit, sessionScope) {
17316
17469
  const client = getClient();
17470
+ if (sessionScope) {
17471
+ const result2 = await client.execute({
17472
+ sql: `SELECT title, assigned_to, project_name FROM tasks
17473
+ WHERE status = 'needs_review'
17474
+ AND (session_scope = ? OR session_scope IS NULL)
17475
+ ORDER BY priority ASC, created_at DESC LIMIT ?`,
17476
+ args: [sessionScope, limit]
17477
+ });
17478
+ return result2.rows;
17479
+ }
17317
17480
  const result = await client.execute({
17318
17481
  sql: `SELECT title, assigned_to, project_name FROM tasks
17319
17482
  WHERE status = 'needs_review'
@@ -17442,11 +17605,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
17442
17605
  );
17443
17606
  }
17444
17607
  try {
17445
- const cacheDir = path26.join(EXE_AI_DIR, "session-cache");
17608
+ const cacheDir = path27.join(EXE_AI_DIR, "session-cache");
17446
17609
  if (existsSync19(cacheDir)) {
17447
17610
  for (const f of readdirSync4(cacheDir)) {
17448
17611
  if (f.startsWith("review-notified-")) {
17449
- unlinkSync6(path26.join(cacheDir, f));
17612
+ unlinkSync6(path27.join(cacheDir, f));
17450
17613
  }
17451
17614
  }
17452
17615
  }
@@ -17468,7 +17631,7 @@ var init_tasks_review = __esm({
17468
17631
  });
17469
17632
 
17470
17633
  // src/lib/tasks-chain.ts
17471
- import path27 from "path";
17634
+ import path28 from "path";
17472
17635
  import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
17473
17636
  async function cascadeUnblock(taskId, baseDir, now) {
17474
17637
  const client = getClient();
@@ -17484,7 +17647,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
17484
17647
  });
17485
17648
  for (const ur of unblockedRows.rows) {
17486
17649
  try {
17487
- const ubFile = path27.join(baseDir, String(ur.task_file));
17650
+ const ubFile = path28.join(baseDir, String(ur.task_file));
17488
17651
  let ubContent = await readFile5(ubFile, "utf-8");
17489
17652
  ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
17490
17653
  ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
@@ -17549,34 +17712,34 @@ var init_tasks_chain = __esm({
17549
17712
  });
17550
17713
 
17551
17714
  // src/lib/project-name.ts
17552
- import { execSync as execSync8 } from "child_process";
17553
- import path28 from "path";
17715
+ import { execSync as execSync10 } from "child_process";
17716
+ import path29 from "path";
17554
17717
  function getProjectName(cwd2) {
17555
17718
  const dir = cwd2 ?? process.cwd();
17556
17719
  if (_cached2 && _cachedCwd === dir) return _cached2;
17557
17720
  try {
17558
17721
  let repoRoot;
17559
17722
  try {
17560
- const gitCommonDir = execSync8("git rev-parse --path-format=absolute --git-common-dir", {
17723
+ const gitCommonDir = execSync10("git rev-parse --path-format=absolute --git-common-dir", {
17561
17724
  cwd: dir,
17562
17725
  encoding: "utf8",
17563
17726
  timeout: 2e3,
17564
17727
  stdio: ["pipe", "pipe", "pipe"]
17565
17728
  }).trim();
17566
- repoRoot = path28.dirname(gitCommonDir);
17729
+ repoRoot = path29.dirname(gitCommonDir);
17567
17730
  } catch {
17568
- repoRoot = execSync8("git rev-parse --show-toplevel", {
17731
+ repoRoot = execSync10("git rev-parse --show-toplevel", {
17569
17732
  cwd: dir,
17570
17733
  encoding: "utf8",
17571
17734
  timeout: 2e3,
17572
17735
  stdio: ["pipe", "pipe", "pipe"]
17573
17736
  }).trim();
17574
17737
  }
17575
- _cached2 = path28.basename(repoRoot);
17738
+ _cached2 = path29.basename(repoRoot);
17576
17739
  _cachedCwd = dir;
17577
17740
  return _cached2;
17578
17741
  } catch {
17579
- _cached2 = path28.basename(dir);
17742
+ _cached2 = path29.basename(dir);
17580
17743
  _cachedCwd = dir;
17581
17744
  return _cached2;
17582
17745
  }
@@ -18048,7 +18211,7 @@ __export(tasks_exports, {
18048
18211
  updateTaskStatus: () => updateTaskStatus,
18049
18212
  writeCheckpoint: () => writeCheckpoint
18050
18213
  });
18051
- import path29 from "path";
18214
+ import path30 from "path";
18052
18215
  import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7 } from "fs";
18053
18216
  async function createTask(input) {
18054
18217
  const result = await createTaskCore(input);
@@ -18068,8 +18231,8 @@ async function updateTask(input) {
18068
18231
  const { row, taskFile, now, taskId } = await updateTaskStatus(input);
18069
18232
  try {
18070
18233
  const agent = String(row.assigned_to);
18071
- const cacheDir = path29.join(EXE_AI_DIR, "session-cache");
18072
- const cachePath = path29.join(cacheDir, `current-task-${agent}.json`);
18234
+ const cacheDir = path30.join(EXE_AI_DIR, "session-cache");
18235
+ const cachePath = path30.join(cacheDir, `current-task-${agent}.json`);
18073
18236
  if (input.status === "in_progress") {
18074
18237
  mkdirSync8(cacheDir, { recursive: true });
18075
18238
  writeFileSync7(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
@@ -18512,14 +18675,14 @@ __export(tmux_routing_exports, {
18512
18675
  spawnEmployee: () => spawnEmployee,
18513
18676
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
18514
18677
  });
18515
- import { execFileSync as execFileSync3, execSync as execSync9 } from "child_process";
18516
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync8, mkdirSync as mkdirSync9, existsSync as existsSync20, appendFileSync } from "fs";
18517
- import path30 from "path";
18678
+ import { execFileSync as execFileSync3, execSync as execSync11 } from "child_process";
18679
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync8, mkdirSync as mkdirSync9, existsSync as existsSync20, appendFileSync } from "fs";
18680
+ import path31 from "path";
18518
18681
  import os10 from "os";
18519
18682
  import { fileURLToPath as fileURLToPath4 } from "url";
18520
18683
  import { unlinkSync as unlinkSync8 } from "fs";
18521
18684
  function spawnLockPath(sessionName) {
18522
- return path30.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
18685
+ return path31.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
18523
18686
  }
18524
18687
  function isProcessAlive(pid) {
18525
18688
  try {
@@ -18536,7 +18699,7 @@ function acquireSpawnLock2(sessionName) {
18536
18699
  const lockFile = spawnLockPath(sessionName);
18537
18700
  if (existsSync20(lockFile)) {
18538
18701
  try {
18539
- const lock = JSON.parse(readFileSync15(lockFile, "utf8"));
18702
+ const lock = JSON.parse(readFileSync16(lockFile, "utf8"));
18540
18703
  const age = Date.now() - lock.timestamp;
18541
18704
  if (isProcessAlive(lock.pid) && age < 6e4) {
18542
18705
  return false;
@@ -18556,8 +18719,8 @@ function releaseSpawnLock2(sessionName) {
18556
18719
  function resolveBehaviorsExporterScript() {
18557
18720
  try {
18558
18721
  const thisFile = fileURLToPath4(import.meta.url);
18559
- const scriptPath = path30.join(
18560
- path30.dirname(thisFile),
18722
+ const scriptPath = path31.join(
18723
+ path31.dirname(thisFile),
18561
18724
  "..",
18562
18725
  "bin",
18563
18726
  "exe-export-behaviors.js"
@@ -18627,7 +18790,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
18627
18790
  mkdirSync9(SESSION_CACHE, { recursive: true });
18628
18791
  }
18629
18792
  const rootExe = extractRootExe(parentExe) ?? parentExe;
18630
- const filePath = path30.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
18793
+ const filePath = path31.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
18631
18794
  writeFileSync8(filePath, JSON.stringify({
18632
18795
  parentExe: rootExe,
18633
18796
  dispatchedBy: dispatchedBy || rootExe,
@@ -18636,7 +18799,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
18636
18799
  }
18637
18800
  function getParentExe(sessionKey) {
18638
18801
  try {
18639
- const data = JSON.parse(readFileSync15(path30.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
18802
+ const data = JSON.parse(readFileSync16(path31.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
18640
18803
  return data.parentExe || null;
18641
18804
  } catch {
18642
18805
  return null;
@@ -18644,8 +18807,8 @@ function getParentExe(sessionKey) {
18644
18807
  }
18645
18808
  function getDispatchedBy(sessionKey) {
18646
18809
  try {
18647
- const data = JSON.parse(readFileSync15(
18648
- path30.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
18810
+ const data = JSON.parse(readFileSync16(
18811
+ path31.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
18649
18812
  "utf8"
18650
18813
  ));
18651
18814
  return data.dispatchedBy ?? data.parentExe ?? null;
@@ -18707,7 +18870,7 @@ async function verifyPaneAtCapacity(sessionName) {
18707
18870
  function readDebounceState() {
18708
18871
  try {
18709
18872
  if (!existsSync20(DEBOUNCE_FILE)) return {};
18710
- return JSON.parse(readFileSync15(DEBOUNCE_FILE, "utf8"));
18873
+ return JSON.parse(readFileSync16(DEBOUNCE_FILE, "utf8"));
18711
18874
  } catch {
18712
18875
  return {};
18713
18876
  }
@@ -18904,8 +19067,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18904
19067
  const transport = getTransport();
18905
19068
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
18906
19069
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
18907
- const logDir = path30.join(os10.homedir(), ".exe-os", "session-logs");
18908
- const logFile = path30.join(logDir, `${instanceLabel}-${Date.now()}.log`);
19070
+ const logDir = path31.join(os10.homedir(), ".exe-os", "session-logs");
19071
+ const logFile = path31.join(logDir, `${instanceLabel}-${Date.now()}.log`);
18909
19072
  if (!existsSync20(logDir)) {
18910
19073
  mkdirSync9(logDir, { recursive: true });
18911
19074
  }
@@ -18913,17 +19076,17 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18913
19076
  let cleanupSuffix = "";
18914
19077
  try {
18915
19078
  const thisFile = fileURLToPath4(import.meta.url);
18916
- const cleanupScript = path30.join(path30.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
19079
+ const cleanupScript = path31.join(path31.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
18917
19080
  if (existsSync20(cleanupScript)) {
18918
19081
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
18919
19082
  }
18920
19083
  } catch {
18921
19084
  }
18922
19085
  try {
18923
- const claudeJsonPath = path30.join(os10.homedir(), ".claude.json");
19086
+ const claudeJsonPath = path31.join(os10.homedir(), ".claude.json");
18924
19087
  let claudeJson = {};
18925
19088
  try {
18926
- claudeJson = JSON.parse(readFileSync15(claudeJsonPath, "utf8"));
19089
+ claudeJson = JSON.parse(readFileSync16(claudeJsonPath, "utf8"));
18927
19090
  } catch {
18928
19091
  }
18929
19092
  if (!claudeJson.projects) claudeJson.projects = {};
@@ -18935,13 +19098,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18935
19098
  } catch {
18936
19099
  }
18937
19100
  try {
18938
- const settingsDir = path30.join(os10.homedir(), ".claude", "projects");
19101
+ const settingsDir = path31.join(os10.homedir(), ".claude", "projects");
18939
19102
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
18940
- const projSettingsDir = path30.join(settingsDir, normalizedKey);
18941
- const settingsPath = path30.join(projSettingsDir, "settings.json");
19103
+ const projSettingsDir = path31.join(settingsDir, normalizedKey);
19104
+ const settingsPath = path31.join(projSettingsDir, "settings.json");
18942
19105
  let settings = {};
18943
19106
  try {
18944
- settings = JSON.parse(readFileSync15(settingsPath, "utf8"));
19107
+ settings = JSON.parse(readFileSync16(settingsPath, "utf8"));
18945
19108
  } catch {
18946
19109
  }
18947
19110
  const perms = settings.permissions ?? {};
@@ -18982,7 +19145,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18982
19145
  let behaviorsFlag = "";
18983
19146
  let legacyFallbackWarned = false;
18984
19147
  if (!useExeAgent && !useBinSymlink) {
18985
- const identityPath2 = path30.join(
19148
+ const identityPath2 = path31.join(
18986
19149
  os10.homedir(),
18987
19150
  ".exe-os",
18988
19151
  "identity",
@@ -18998,7 +19161,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18998
19161
  }
18999
19162
  const behaviorsFile = exportBehaviorsSync(
19000
19163
  employeeName,
19001
- path30.basename(spawnCwd),
19164
+ path31.basename(spawnCwd),
19002
19165
  sessionName
19003
19166
  );
19004
19167
  if (behaviorsFile) {
@@ -19013,9 +19176,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
19013
19176
  }
19014
19177
  let sessionContextFlag = "";
19015
19178
  try {
19016
- const ctxDir = path30.join(os10.homedir(), ".exe-os", "session-cache");
19179
+ const ctxDir = path31.join(os10.homedir(), ".exe-os", "session-cache");
19017
19180
  mkdirSync9(ctxDir, { recursive: true });
19018
- const ctxFile = path30.join(ctxDir, `session-context-${sessionName}.md`);
19181
+ const ctxFile = path31.join(ctxDir, `session-context-${sessionName}.md`);
19019
19182
  const ctxContent = [
19020
19183
  `## Session Context`,
19021
19184
  `You are running in tmux session: ${sessionName}.`,
@@ -19060,7 +19223,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
19060
19223
  transport.pipeLog(sessionName, logFile);
19061
19224
  try {
19062
19225
  const mySession = getMySession();
19063
- const dispatchInfo = path30.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
19226
+ const dispatchInfo = path31.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
19064
19227
  writeFileSync8(dispatchInfo, JSON.stringify({
19065
19228
  dispatchedBy: mySession,
19066
19229
  rootExe: exeSession,
@@ -19072,7 +19235,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
19072
19235
  let booted = false;
19073
19236
  for (let i = 0; i < 30; i++) {
19074
19237
  try {
19075
- execSync9("sleep 0.5");
19238
+ execSync11("sleep 0.5");
19076
19239
  } catch {
19077
19240
  }
19078
19241
  try {
@@ -19124,14 +19287,14 @@ var init_tmux_routing = __esm({
19124
19287
  init_provider_table();
19125
19288
  init_intercom_queue();
19126
19289
  init_plan_limits();
19127
- SPAWN_LOCK_DIR = path30.join(os10.homedir(), ".exe-os", "spawn-locks");
19128
- SESSION_CACHE = path30.join(os10.homedir(), ".exe-os", "session-cache");
19290
+ SPAWN_LOCK_DIR = path31.join(os10.homedir(), ".exe-os", "spawn-locks");
19291
+ SESSION_CACHE = path31.join(os10.homedir(), ".exe-os", "session-cache");
19129
19292
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
19130
19293
  VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
19131
19294
  VERIFY_PANE_LINES = 200;
19132
19295
  INTERCOM_DEBOUNCE_MS = 3e4;
19133
- INTERCOM_LOG2 = path30.join(os10.homedir(), ".exe-os", "intercom.log");
19134
- DEBOUNCE_FILE = path30.join(SESSION_CACHE, "intercom-debounce.json");
19296
+ INTERCOM_LOG2 = path31.join(os10.homedir(), ".exe-os", "intercom.log");
19297
+ DEBOUNCE_FILE = path31.join(SESSION_CACHE, "intercom-debounce.json");
19135
19298
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
19136
19299
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
19137
19300
  }
@@ -19519,7 +19682,7 @@ var init_useOrchestrator = __esm({
19519
19682
 
19520
19683
  // src/tui/views/Sessions.tsx
19521
19684
  import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
19522
- import path31 from "path";
19685
+ import path32 from "path";
19523
19686
  import { homedir as homedir4 } from "os";
19524
19687
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
19525
19688
  function SessionsView({
@@ -19554,7 +19717,7 @@ function SessionsView({
19554
19717
  if (demo) {
19555
19718
  setProjects(DEMO_PROJECTS.map((p) => ({
19556
19719
  ...p,
19557
- projectDir: path31.join(homedir4(), p.projectName),
19720
+ projectDir: path32.join(homedir4(), p.projectName),
19558
19721
  employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
19559
19722
  })));
19560
19723
  return;
@@ -21147,10 +21310,10 @@ var init_Gateway = __esm({
21147
21310
  });
21148
21311
 
21149
21312
  // src/tui/utils/agent-status.ts
21150
- import { execSync as execSync10 } from "child_process";
21313
+ import { execSync as execSync12 } from "child_process";
21151
21314
  function getAgentStatus(agentId) {
21152
21315
  try {
21153
- const sessions = execSync10("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
21316
+ const sessions = execSync12("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
21154
21317
  encoding: "utf8",
21155
21318
  timeout: 2e3
21156
21319
  }).trim().split("\n");
@@ -21161,7 +21324,7 @@ function getAgentStatus(agentId) {
21161
21324
  return /^\d?-/.test(suffix) || /^\d+$/.test(suffix);
21162
21325
  });
21163
21326
  if (!agentSession) return { label: "offline", color: "gray" };
21164
- const pane = execSync10(`tmux capture-pane -t "${agentSession}" -p 2>/dev/null | tail -3`, {
21327
+ const pane = execSync12(`tmux capture-pane -t "${agentSession}" -p 2>/dev/null | tail -3`, {
21165
21328
  encoding: "utf8",
21166
21329
  timeout: 2e3
21167
21330
  });
@@ -22522,8 +22685,6 @@ function App2() {
22522
22685
  setSection(SECTIONS[tabIdx].key);
22523
22686
  setFocus("sidebar");
22524
22687
  }
22525
- } else {
22526
- setFocus("content");
22527
22688
  }
22528
22689
  }, []));
22529
22690
  const [focus, setFocus] = useState16("sidebar");
@@ -22736,100 +22897,36 @@ var init_App2 = __esm({
22736
22897
  }
22737
22898
  }
22738
22899
  render_default(/* @__PURE__ */ jsx17(App2, {}));
22739
- }
22740
- });
22741
-
22742
- // src/lib/update-check.ts
22743
- import { execSync as execSync11 } from "child_process";
22744
- import { readFileSync as readFileSync16 } from "fs";
22745
- import path32 from "path";
22746
- function getLocalVersion(packageRoot) {
22747
- const pkgPath = path32.join(packageRoot, "package.json");
22748
- const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
22749
- return pkg.version;
22750
- }
22751
- function getRemoteVersion() {
22752
- try {
22753
- const output = execSync11("npm view @askexenow/exe-os version", {
22754
- encoding: "utf-8",
22755
- timeout: 15e3,
22756
- stdio: ["pipe", "pipe", "pipe"]
22757
- });
22758
- return output.trim();
22759
- } catch {
22760
- return null;
22761
- }
22762
- }
22763
- function checkForUpdate(packageRoot) {
22764
- const localVersion = getLocalVersion(packageRoot);
22765
- const remoteVersion = getRemoteVersion();
22766
- if (!remoteVersion) {
22767
- return {
22768
- updateAvailable: false,
22769
- localVersion,
22770
- error: "Could not reach npm registry or package not published yet"
22771
- };
22772
- }
22773
- if (remoteVersion === localVersion) {
22774
- return { updateAvailable: false, localVersion, remoteVersion };
22775
- }
22776
- return { updateAvailable: true, localVersion, remoteVersion };
22777
- }
22778
- var init_update_check = __esm({
22779
- "src/lib/update-check.ts"() {
22780
- "use strict";
22781
- }
22782
- });
22783
-
22784
- // src/bin/update.ts
22785
- var update_exports = {};
22786
- __export(update_exports, {
22787
- checkForUpdate: () => checkForUpdate,
22788
- getLocalVersion: () => getLocalVersion,
22789
- getRemoteVersion: () => getRemoteVersion
22790
- });
22791
- import { execSync as execSync12 } from "child_process";
22792
- import { createInterface as createInterface3 } from "readline";
22793
- var init_update = __esm({
22794
- async "src/bin/update.ts"() {
22795
- "use strict";
22796
- init_is_main();
22797
- init_update_check();
22798
- init_update_check();
22799
- if (isMainModule(import.meta.url)) {
22800
- const packageRoot = new URL("../..", import.meta.url).pathname;
22801
- const result = checkForUpdate(packageRoot);
22802
- if (result.error) {
22803
- console.error(result.error);
22804
- process.exit(0);
22805
- }
22806
- if (!result.updateAvailable) {
22807
- console.log(`exe-os is up to date (v${result.localVersion})`);
22808
- process.exit(0);
22809
- }
22810
- console.log(
22811
- `Update available: v${result.localVersion} -> v${result.remoteVersion}`
22812
- );
22813
- console.log("");
22814
- const rl = createInterface3({ input: process.stdin, output: process.stdout });
22815
- const answer = await new Promise((resolve) => {
22816
- rl.question("Install update? (y/N) ", resolve);
22817
- });
22818
- rl.close();
22819
- if (answer.toLowerCase() === "y") {
22820
- console.log("Updating...");
22900
+ {
22901
+ const CLEANUP_SEQ = "\x1B[?1006l\x1B[?1002l\x1B[?1000l\x1B[?25h\x1B[?1049l";
22902
+ const terminalCleanup = () => {
22821
22903
  try {
22822
- execSync12("npm install -g @askexenow/exe-os@latest", { stdio: "inherit" });
22823
- console.log("Update complete!");
22904
+ process.stdout.write(CLEANUP_SEQ);
22824
22905
  } catch {
22825
- console.error(
22826
- "Update failed. Try running manually: npx exe-os --global"
22827
- );
22828
- process.exit(1);
22829
22906
  }
22830
- } else {
22831
- console.log("Update skipped.");
22907
+ };
22908
+ process.on("exit", terminalCleanup);
22909
+ for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) {
22910
+ process.on(sig, () => {
22911
+ terminalCleanup();
22912
+ process.removeAllListeners(sig);
22913
+ process.kill(process.pid, sig);
22914
+ });
22832
22915
  }
22916
+ process.on("uncaughtException", (err) => {
22917
+ terminalCleanup();
22918
+ process.stderr.write(`
22919
+ ${err.stack || err.message}
22920
+ `);
22921
+ process.exit(1);
22922
+ });
22923
+ process.on("unhandledRejection", (reason) => {
22924
+ terminalCleanup();
22925
+ process.stderr.write(`
22926
+ Unhandled rejection: ${reason}
22927
+ `);
22928
+ process.exit(1);
22929
+ });
22833
22930
  }
22834
22931
  }
22835
22932
  });
@@ -22892,6 +22989,9 @@ if (args.includes("--global")) {
22892
22989
  } else if (args[0] === "setup" || args[0] === "-setup" || args[0] === "--setup") {
22893
22990
  const { runSetupWizard: runSetupWizard2 } = await Promise.resolve().then(() => (init_setup_wizard(), setup_wizard_exports));
22894
22991
  await runSetupWizard2({ skipModel: args.includes("--skip-model") });
22992
+ } else if (args[0] === "update") {
22993
+ const { runUpdate: runUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
22994
+ await runUpdate2(args.slice(1));
22895
22995
  } else {
22896
22996
  checkForUpdateOnBoot().catch(() => {
22897
22997
  });
@@ -23217,7 +23317,7 @@ async function checkForUpdateOnBoot() {
23217
23317
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
23218
23318
  const config = await loadConfig2();
23219
23319
  if (!config.autoUpdate.checkOnBoot) return;
23220
- const { checkForUpdate: checkForUpdate2 } = await init_update().then(() => update_exports);
23320
+ const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
23221
23321
  const packageRoot = path33.resolve(
23222
23322
  new URL("../..", import.meta.url).pathname
23223
23323
  );