@askexenow/exe-os 0.8.49 → 0.8.50

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();
@@ -17442,11 +17595,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
17442
17595
  );
17443
17596
  }
17444
17597
  try {
17445
- const cacheDir = path26.join(EXE_AI_DIR, "session-cache");
17598
+ const cacheDir = path27.join(EXE_AI_DIR, "session-cache");
17446
17599
  if (existsSync19(cacheDir)) {
17447
17600
  for (const f of readdirSync4(cacheDir)) {
17448
17601
  if (f.startsWith("review-notified-")) {
17449
- unlinkSync6(path26.join(cacheDir, f));
17602
+ unlinkSync6(path27.join(cacheDir, f));
17450
17603
  }
17451
17604
  }
17452
17605
  }
@@ -17468,7 +17621,7 @@ var init_tasks_review = __esm({
17468
17621
  });
17469
17622
 
17470
17623
  // src/lib/tasks-chain.ts
17471
- import path27 from "path";
17624
+ import path28 from "path";
17472
17625
  import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
17473
17626
  async function cascadeUnblock(taskId, baseDir, now) {
17474
17627
  const client = getClient();
@@ -17484,7 +17637,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
17484
17637
  });
17485
17638
  for (const ur of unblockedRows.rows) {
17486
17639
  try {
17487
- const ubFile = path27.join(baseDir, String(ur.task_file));
17640
+ const ubFile = path28.join(baseDir, String(ur.task_file));
17488
17641
  let ubContent = await readFile5(ubFile, "utf-8");
17489
17642
  ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
17490
17643
  ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
@@ -17549,34 +17702,34 @@ var init_tasks_chain = __esm({
17549
17702
  });
17550
17703
 
17551
17704
  // src/lib/project-name.ts
17552
- import { execSync as execSync8 } from "child_process";
17553
- import path28 from "path";
17705
+ import { execSync as execSync10 } from "child_process";
17706
+ import path29 from "path";
17554
17707
  function getProjectName(cwd2) {
17555
17708
  const dir = cwd2 ?? process.cwd();
17556
17709
  if (_cached2 && _cachedCwd === dir) return _cached2;
17557
17710
  try {
17558
17711
  let repoRoot;
17559
17712
  try {
17560
- const gitCommonDir = execSync8("git rev-parse --path-format=absolute --git-common-dir", {
17713
+ const gitCommonDir = execSync10("git rev-parse --path-format=absolute --git-common-dir", {
17561
17714
  cwd: dir,
17562
17715
  encoding: "utf8",
17563
17716
  timeout: 2e3,
17564
17717
  stdio: ["pipe", "pipe", "pipe"]
17565
17718
  }).trim();
17566
- repoRoot = path28.dirname(gitCommonDir);
17719
+ repoRoot = path29.dirname(gitCommonDir);
17567
17720
  } catch {
17568
- repoRoot = execSync8("git rev-parse --show-toplevel", {
17721
+ repoRoot = execSync10("git rev-parse --show-toplevel", {
17569
17722
  cwd: dir,
17570
17723
  encoding: "utf8",
17571
17724
  timeout: 2e3,
17572
17725
  stdio: ["pipe", "pipe", "pipe"]
17573
17726
  }).trim();
17574
17727
  }
17575
- _cached2 = path28.basename(repoRoot);
17728
+ _cached2 = path29.basename(repoRoot);
17576
17729
  _cachedCwd = dir;
17577
17730
  return _cached2;
17578
17731
  } catch {
17579
- _cached2 = path28.basename(dir);
17732
+ _cached2 = path29.basename(dir);
17580
17733
  _cachedCwd = dir;
17581
17734
  return _cached2;
17582
17735
  }
@@ -18048,7 +18201,7 @@ __export(tasks_exports, {
18048
18201
  updateTaskStatus: () => updateTaskStatus,
18049
18202
  writeCheckpoint: () => writeCheckpoint
18050
18203
  });
18051
- import path29 from "path";
18204
+ import path30 from "path";
18052
18205
  import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7 } from "fs";
18053
18206
  async function createTask(input) {
18054
18207
  const result = await createTaskCore(input);
@@ -18068,8 +18221,8 @@ async function updateTask(input) {
18068
18221
  const { row, taskFile, now, taskId } = await updateTaskStatus(input);
18069
18222
  try {
18070
18223
  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`);
18224
+ const cacheDir = path30.join(EXE_AI_DIR, "session-cache");
18225
+ const cachePath = path30.join(cacheDir, `current-task-${agent}.json`);
18073
18226
  if (input.status === "in_progress") {
18074
18227
  mkdirSync8(cacheDir, { recursive: true });
18075
18228
  writeFileSync7(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
@@ -18512,14 +18665,14 @@ __export(tmux_routing_exports, {
18512
18665
  spawnEmployee: () => spawnEmployee,
18513
18666
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
18514
18667
  });
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";
18668
+ import { execFileSync as execFileSync3, execSync as execSync11 } from "child_process";
18669
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync8, mkdirSync as mkdirSync9, existsSync as existsSync20, appendFileSync } from "fs";
18670
+ import path31 from "path";
18518
18671
  import os10 from "os";
18519
18672
  import { fileURLToPath as fileURLToPath4 } from "url";
18520
18673
  import { unlinkSync as unlinkSync8 } from "fs";
18521
18674
  function spawnLockPath(sessionName) {
18522
- return path30.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
18675
+ return path31.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
18523
18676
  }
18524
18677
  function isProcessAlive(pid) {
18525
18678
  try {
@@ -18536,7 +18689,7 @@ function acquireSpawnLock2(sessionName) {
18536
18689
  const lockFile = spawnLockPath(sessionName);
18537
18690
  if (existsSync20(lockFile)) {
18538
18691
  try {
18539
- const lock = JSON.parse(readFileSync15(lockFile, "utf8"));
18692
+ const lock = JSON.parse(readFileSync16(lockFile, "utf8"));
18540
18693
  const age = Date.now() - lock.timestamp;
18541
18694
  if (isProcessAlive(lock.pid) && age < 6e4) {
18542
18695
  return false;
@@ -18556,8 +18709,8 @@ function releaseSpawnLock2(sessionName) {
18556
18709
  function resolveBehaviorsExporterScript() {
18557
18710
  try {
18558
18711
  const thisFile = fileURLToPath4(import.meta.url);
18559
- const scriptPath = path30.join(
18560
- path30.dirname(thisFile),
18712
+ const scriptPath = path31.join(
18713
+ path31.dirname(thisFile),
18561
18714
  "..",
18562
18715
  "bin",
18563
18716
  "exe-export-behaviors.js"
@@ -18627,7 +18780,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
18627
18780
  mkdirSync9(SESSION_CACHE, { recursive: true });
18628
18781
  }
18629
18782
  const rootExe = extractRootExe(parentExe) ?? parentExe;
18630
- const filePath = path30.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
18783
+ const filePath = path31.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
18631
18784
  writeFileSync8(filePath, JSON.stringify({
18632
18785
  parentExe: rootExe,
18633
18786
  dispatchedBy: dispatchedBy || rootExe,
@@ -18636,7 +18789,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
18636
18789
  }
18637
18790
  function getParentExe(sessionKey) {
18638
18791
  try {
18639
- const data = JSON.parse(readFileSync15(path30.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
18792
+ const data = JSON.parse(readFileSync16(path31.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
18640
18793
  return data.parentExe || null;
18641
18794
  } catch {
18642
18795
  return null;
@@ -18644,8 +18797,8 @@ function getParentExe(sessionKey) {
18644
18797
  }
18645
18798
  function getDispatchedBy(sessionKey) {
18646
18799
  try {
18647
- const data = JSON.parse(readFileSync15(
18648
- path30.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
18800
+ const data = JSON.parse(readFileSync16(
18801
+ path31.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
18649
18802
  "utf8"
18650
18803
  ));
18651
18804
  return data.dispatchedBy ?? data.parentExe ?? null;
@@ -18707,7 +18860,7 @@ async function verifyPaneAtCapacity(sessionName) {
18707
18860
  function readDebounceState() {
18708
18861
  try {
18709
18862
  if (!existsSync20(DEBOUNCE_FILE)) return {};
18710
- return JSON.parse(readFileSync15(DEBOUNCE_FILE, "utf8"));
18863
+ return JSON.parse(readFileSync16(DEBOUNCE_FILE, "utf8"));
18711
18864
  } catch {
18712
18865
  return {};
18713
18866
  }
@@ -18904,8 +19057,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18904
19057
  const transport = getTransport();
18905
19058
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
18906
19059
  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`);
19060
+ const logDir = path31.join(os10.homedir(), ".exe-os", "session-logs");
19061
+ const logFile = path31.join(logDir, `${instanceLabel}-${Date.now()}.log`);
18909
19062
  if (!existsSync20(logDir)) {
18910
19063
  mkdirSync9(logDir, { recursive: true });
18911
19064
  }
@@ -18913,17 +19066,17 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18913
19066
  let cleanupSuffix = "";
18914
19067
  try {
18915
19068
  const thisFile = fileURLToPath4(import.meta.url);
18916
- const cleanupScript = path30.join(path30.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
19069
+ const cleanupScript = path31.join(path31.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
18917
19070
  if (existsSync20(cleanupScript)) {
18918
19071
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
18919
19072
  }
18920
19073
  } catch {
18921
19074
  }
18922
19075
  try {
18923
- const claudeJsonPath = path30.join(os10.homedir(), ".claude.json");
19076
+ const claudeJsonPath = path31.join(os10.homedir(), ".claude.json");
18924
19077
  let claudeJson = {};
18925
19078
  try {
18926
- claudeJson = JSON.parse(readFileSync15(claudeJsonPath, "utf8"));
19079
+ claudeJson = JSON.parse(readFileSync16(claudeJsonPath, "utf8"));
18927
19080
  } catch {
18928
19081
  }
18929
19082
  if (!claudeJson.projects) claudeJson.projects = {};
@@ -18935,13 +19088,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18935
19088
  } catch {
18936
19089
  }
18937
19090
  try {
18938
- const settingsDir = path30.join(os10.homedir(), ".claude", "projects");
19091
+ const settingsDir = path31.join(os10.homedir(), ".claude", "projects");
18939
19092
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
18940
- const projSettingsDir = path30.join(settingsDir, normalizedKey);
18941
- const settingsPath = path30.join(projSettingsDir, "settings.json");
19093
+ const projSettingsDir = path31.join(settingsDir, normalizedKey);
19094
+ const settingsPath = path31.join(projSettingsDir, "settings.json");
18942
19095
  let settings = {};
18943
19096
  try {
18944
- settings = JSON.parse(readFileSync15(settingsPath, "utf8"));
19097
+ settings = JSON.parse(readFileSync16(settingsPath, "utf8"));
18945
19098
  } catch {
18946
19099
  }
18947
19100
  const perms = settings.permissions ?? {};
@@ -18982,7 +19135,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18982
19135
  let behaviorsFlag = "";
18983
19136
  let legacyFallbackWarned = false;
18984
19137
  if (!useExeAgent && !useBinSymlink) {
18985
- const identityPath2 = path30.join(
19138
+ const identityPath2 = path31.join(
18986
19139
  os10.homedir(),
18987
19140
  ".exe-os",
18988
19141
  "identity",
@@ -18998,7 +19151,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18998
19151
  }
18999
19152
  const behaviorsFile = exportBehaviorsSync(
19000
19153
  employeeName,
19001
- path30.basename(spawnCwd),
19154
+ path31.basename(spawnCwd),
19002
19155
  sessionName
19003
19156
  );
19004
19157
  if (behaviorsFile) {
@@ -19013,9 +19166,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
19013
19166
  }
19014
19167
  let sessionContextFlag = "";
19015
19168
  try {
19016
- const ctxDir = path30.join(os10.homedir(), ".exe-os", "session-cache");
19169
+ const ctxDir = path31.join(os10.homedir(), ".exe-os", "session-cache");
19017
19170
  mkdirSync9(ctxDir, { recursive: true });
19018
- const ctxFile = path30.join(ctxDir, `session-context-${sessionName}.md`);
19171
+ const ctxFile = path31.join(ctxDir, `session-context-${sessionName}.md`);
19019
19172
  const ctxContent = [
19020
19173
  `## Session Context`,
19021
19174
  `You are running in tmux session: ${sessionName}.`,
@@ -19060,7 +19213,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
19060
19213
  transport.pipeLog(sessionName, logFile);
19061
19214
  try {
19062
19215
  const mySession = getMySession();
19063
- const dispatchInfo = path30.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
19216
+ const dispatchInfo = path31.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
19064
19217
  writeFileSync8(dispatchInfo, JSON.stringify({
19065
19218
  dispatchedBy: mySession,
19066
19219
  rootExe: exeSession,
@@ -19072,7 +19225,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
19072
19225
  let booted = false;
19073
19226
  for (let i = 0; i < 30; i++) {
19074
19227
  try {
19075
- execSync9("sleep 0.5");
19228
+ execSync11("sleep 0.5");
19076
19229
  } catch {
19077
19230
  }
19078
19231
  try {
@@ -19124,14 +19277,14 @@ var init_tmux_routing = __esm({
19124
19277
  init_provider_table();
19125
19278
  init_intercom_queue();
19126
19279
  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");
19280
+ SPAWN_LOCK_DIR = path31.join(os10.homedir(), ".exe-os", "spawn-locks");
19281
+ SESSION_CACHE = path31.join(os10.homedir(), ".exe-os", "session-cache");
19129
19282
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
19130
19283
  VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
19131
19284
  VERIFY_PANE_LINES = 200;
19132
19285
  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");
19286
+ INTERCOM_LOG2 = path31.join(os10.homedir(), ".exe-os", "intercom.log");
19287
+ DEBOUNCE_FILE = path31.join(SESSION_CACHE, "intercom-debounce.json");
19135
19288
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
19136
19289
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
19137
19290
  }
@@ -19519,7 +19672,7 @@ var init_useOrchestrator = __esm({
19519
19672
 
19520
19673
  // src/tui/views/Sessions.tsx
19521
19674
  import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
19522
- import path31 from "path";
19675
+ import path32 from "path";
19523
19676
  import { homedir as homedir4 } from "os";
19524
19677
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
19525
19678
  function SessionsView({
@@ -19554,7 +19707,7 @@ function SessionsView({
19554
19707
  if (demo) {
19555
19708
  setProjects(DEMO_PROJECTS.map((p) => ({
19556
19709
  ...p,
19557
- projectDir: path31.join(homedir4(), p.projectName),
19710
+ projectDir: path32.join(homedir4(), p.projectName),
19558
19711
  employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
19559
19712
  })));
19560
19713
  return;
@@ -21147,10 +21300,10 @@ var init_Gateway = __esm({
21147
21300
  });
21148
21301
 
21149
21302
  // src/tui/utils/agent-status.ts
21150
- import { execSync as execSync10 } from "child_process";
21303
+ import { execSync as execSync12 } from "child_process";
21151
21304
  function getAgentStatus(agentId) {
21152
21305
  try {
21153
- const sessions = execSync10("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
21306
+ const sessions = execSync12("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
21154
21307
  encoding: "utf8",
21155
21308
  timeout: 2e3
21156
21309
  }).trim().split("\n");
@@ -21161,7 +21314,7 @@ function getAgentStatus(agentId) {
21161
21314
  return /^\d?-/.test(suffix) || /^\d+$/.test(suffix);
21162
21315
  });
21163
21316
  if (!agentSession) return { label: "offline", color: "gray" };
21164
- const pane = execSync10(`tmux capture-pane -t "${agentSession}" -p 2>/dev/null | tail -3`, {
21317
+ const pane = execSync12(`tmux capture-pane -t "${agentSession}" -p 2>/dev/null | tail -3`, {
21165
21318
  encoding: "utf8",
21166
21319
  timeout: 2e3
21167
21320
  });
@@ -22739,101 +22892,6 @@ var init_App2 = __esm({
22739
22892
  }
22740
22893
  });
22741
22894
 
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...");
22821
- try {
22822
- execSync12("npm install -g @askexenow/exe-os@latest", { stdio: "inherit" });
22823
- console.log("Update complete!");
22824
- } catch {
22825
- console.error(
22826
- "Update failed. Try running manually: npx exe-os --global"
22827
- );
22828
- process.exit(1);
22829
- }
22830
- } else {
22831
- console.log("Update skipped.");
22832
- }
22833
- }
22834
- }
22835
- });
22836
-
22837
22895
  // src/bin/cli.ts
22838
22896
  import { existsSync as existsSync21, readFileSync as readFileSync17, writeFileSync as writeFileSync9, readdirSync as readdirSync5, rmSync } from "fs";
22839
22897
  import path33 from "path";
@@ -22892,6 +22950,9 @@ if (args.includes("--global")) {
22892
22950
  } else if (args[0] === "setup" || args[0] === "-setup" || args[0] === "--setup") {
22893
22951
  const { runSetupWizard: runSetupWizard2 } = await Promise.resolve().then(() => (init_setup_wizard(), setup_wizard_exports));
22894
22952
  await runSetupWizard2({ skipModel: args.includes("--skip-model") });
22953
+ } else if (args[0] === "update") {
22954
+ const { runUpdate: runUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
22955
+ await runUpdate2(args.slice(1));
22895
22956
  } else {
22896
22957
  checkForUpdateOnBoot().catch(() => {
22897
22958
  });
@@ -23217,7 +23278,7 @@ async function checkForUpdateOnBoot() {
23217
23278
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
23218
23279
  const config = await loadConfig2();
23219
23280
  if (!config.autoUpdate.checkOnBoot) return;
23220
- const { checkForUpdate: checkForUpdate2 } = await init_update().then(() => update_exports);
23281
+ const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
23221
23282
  const packageRoot = path33.resolve(
23222
23283
  new URL("../..", import.meta.url).pathname
23223
23284
  );
@@ -56,43 +56,101 @@ function checkForUpdate(packageRoot) {
56
56
  }
57
57
 
58
58
  // src/bin/update.ts
59
- if (isMainModule(import.meta.url)) {
59
+ async function runUpdate(cliArgs) {
60
+ const args = cliArgs ?? process.argv.slice(2);
61
+ const autoMode = args.includes("--auto") || args.includes("-y");
62
+ const checkOnly = args.includes("--check");
60
63
  const packageRoot = new URL("../..", import.meta.url).pathname;
61
64
  const result = checkForUpdate(packageRoot);
62
65
  if (result.error) {
63
- console.error(result.error);
66
+ console.error(`\u26A0\uFE0F ${result.error}`);
67
+ process.exit(0);
68
+ }
69
+ if (checkOnly) {
70
+ if (result.updateAvailable) {
71
+ console.log(`Update available: v${result.localVersion} \u2192 v${result.remoteVersion}`);
72
+ } else {
73
+ console.log(`\u2705 exe-os is up to date (v${result.localVersion})`);
74
+ }
64
75
  process.exit(0);
65
76
  }
66
77
  if (!result.updateAvailable) {
67
- console.log(`exe-os is up to date (v${result.localVersion})`);
78
+ console.log(`\u2705 exe-os is up to date (v${result.localVersion})`);
68
79
  process.exit(0);
69
80
  }
70
- console.log(
71
- `Update available: v${result.localVersion} -> v${result.remoteVersion}`
72
- );
73
- console.log("");
74
- const rl = createInterface({ input: process.stdin, output: process.stdout });
75
- const answer = await new Promise((resolve) => {
76
- rl.question("Install update? (y/N) ", resolve);
77
- });
78
- rl.close();
79
- if (answer.toLowerCase() === "y") {
80
- console.log("Updating...");
81
+ console.log(`
82
+ \u{1F4E6} Update available: v${result.localVersion} \u2192 v${result.remoteVersion}
83
+ `);
84
+ let proceed = autoMode;
85
+ if (!proceed) {
86
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
87
+ const answer = await new Promise((resolve) => {
88
+ rl.question("Install update? (Y/n) ", resolve);
89
+ });
90
+ rl.close();
91
+ proceed = answer.toLowerCase() !== "n";
92
+ }
93
+ if (!proceed) {
94
+ console.log("Update skipped.");
95
+ process.exit(0);
96
+ }
97
+ console.log("\n\u{1F9F9} Clearing npm cache...");
98
+ try {
99
+ execSync2("npm cache clean --force", { stdio: "pipe" });
100
+ console.log(" Done");
101
+ } catch {
102
+ console.log(" Skipped (non-critical)");
103
+ }
104
+ console.log("\u{1F4E5} Installing @askexenow/exe-os@latest...");
105
+ try {
106
+ execSync2("npm install -g @askexenow/exe-os@latest", {
107
+ stdio: ["pipe", "pipe", "pipe"],
108
+ timeout: 12e4
109
+ });
110
+ } catch (err) {
111
+ console.error("\n\u274C Update failed.");
112
+ console.error(" Try manually: npm install -g @askexenow/exe-os@latest");
113
+ if (err instanceof Error && err.message) {
114
+ console.error(` Error: ${err.message.split("\n")[0]}`);
115
+ }
116
+ process.exit(1);
117
+ }
118
+ let newVersion;
119
+ try {
120
+ newVersion = getLocalVersion(packageRoot);
121
+ } catch {
81
122
  try {
82
- execSync2("npm install -g @askexenow/exe-os@latest", { stdio: "inherit" });
83
- console.log("Update complete!");
123
+ const out = execSync2("npm list -g @askexenow/exe-os --depth=0 2>/dev/null", { encoding: "utf8" });
124
+ const match = out.match(/@askexenow\/exe-os@(\S+)/);
125
+ newVersion = match?.[1] ?? "unknown";
84
126
  } catch {
85
- console.error(
86
- "Update failed. Try running manually: npx exe-os --global"
87
- );
88
- process.exit(1);
127
+ newVersion = "unknown";
89
128
  }
129
+ }
130
+ const remoteVersion = result.remoteVersion;
131
+ if (newVersion === remoteVersion) {
132
+ console.log(`
133
+ \u2705 Updated to v${newVersion}`);
134
+ } else if (newVersion !== result.localVersion) {
135
+ console.log(`
136
+ \u2705 Updated to v${newVersion} (latest: v${remoteVersion})`);
90
137
  } else {
91
- console.log("Update skipped.");
138
+ console.log(`
139
+ \u26A0\uFE0F Version unchanged (v${newVersion}). npm cache may be stale.`);
140
+ console.log(" Try: npm cache clean --force && npm install -g @askexenow/exe-os@latest");
92
141
  }
142
+ console.log(" Hooks re-wired, daemon restarted automatically.");
143
+ console.log("\n\u{1F680} Ready. Start your COO session to use the new version.\n");
144
+ }
145
+ if (isMainModule(import.meta.url)) {
146
+ runUpdate().catch((err) => {
147
+ console.error(err instanceof Error ? err.message : String(err));
148
+ process.exit(1);
149
+ });
93
150
  }
94
151
  export {
95
152
  checkForUpdate,
96
153
  getLocalVersion,
97
- getRemoteVersion
154
+ getRemoteVersion,
155
+ runUpdate
98
156
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.8.49",
3
+ "version": "0.8.50",
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",