@askexenow/exe-os 0.9.73 → 0.9.75

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
@@ -3698,8 +3698,8 @@ function findPackageRoot() {
3698
3698
  function getAvailableMemoryGB() {
3699
3699
  if (process.platform === "darwin") {
3700
3700
  try {
3701
- const { execSync: execSync17 } = __require("child_process");
3702
- const vmstat = execSync17("vm_stat", { encoding: "utf8" });
3701
+ const { execSync: execSync18 } = __require("child_process");
3702
+ const vmstat = execSync18("vm_stat", { encoding: "utf8" });
3703
3703
  const pageSize = 16384;
3704
3704
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
3705
3705
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -5825,6 +5825,7 @@ __export(license_exports, {
5825
5825
  loadDeviceId: () => loadDeviceId,
5826
5826
  loadLicense: () => loadLicense,
5827
5827
  mirrorLicenseKey: () => mirrorLicenseKey,
5828
+ readCachedLicenseToken: () => readCachedLicenseToken,
5828
5829
  saveLicense: () => saveLicense,
5829
5830
  startLicenseRevalidation: () => startLicenseRevalidation,
5830
5831
  stopLicenseRevalidation: () => stopLicenseRevalidation,
@@ -5910,7 +5911,7 @@ async function getCachedLicense() {
5910
5911
  return null;
5911
5912
  }
5912
5913
  }
5913
- function readCachedToken() {
5914
+ function readCachedLicenseToken() {
5914
5915
  try {
5915
5916
  if (!existsSync13(CACHE_PATH)) return null;
5916
5917
  const raw = JSON.parse(readFileSync10(CACHE_PATH, "utf8"));
@@ -5921,7 +5922,7 @@ function readCachedToken() {
5921
5922
  }
5922
5923
  function getRawCachedPlan() {
5923
5924
  try {
5924
- const token = readCachedToken();
5925
+ const token = readCachedLicenseToken();
5925
5926
  if (!token) return null;
5926
5927
  const parts = token.split(".");
5927
5928
  if (parts.length !== 3) return null;
@@ -6188,7 +6189,7 @@ async function assertVpsLicense(opts) {
6188
6189
  const graceDays = opts?.offlineGraceDays ?? 7;
6189
6190
  const graceMs = graceDays * 24 * 60 * 60 * 1e3;
6190
6191
  try {
6191
- const token = readCachedToken();
6192
+ const token = readCachedLicenseToken();
6192
6193
  if (token) {
6193
6194
  const payloadB64 = token.split(".")[1];
6194
6195
  if (payloadB64) {
@@ -18119,12 +18120,14 @@ import {
18119
18120
  readdirSync as readdirSync9,
18120
18121
  unlinkSync as unlinkSync14
18121
18122
  } from "fs";
18123
+ import { execSync as execSync13 } from "child_process";
18122
18124
  import path37 from "path";
18123
18125
  import { homedir as homedir5 } from "os";
18124
18126
  function generateSessionWrappers(packageRoot, homeDir) {
18125
18127
  const home = homeDir ?? homedir5();
18126
18128
  const binDir = path37.join(home, ".exe-os", "bin");
18127
18129
  const rosterPath = path37.join(home, ".exe-os", "exe-employees.json");
18130
+ const shouldMirrorToGlobalBin = homeDir === void 0;
18128
18131
  mkdirSync21(binDir, { recursive: true });
18129
18132
  const exeStartDst = path37.join(binDir, "exe-start");
18130
18133
  const candidates = [
@@ -18165,15 +18168,18 @@ function generateSessionWrappers(packageRoot, homeDir) {
18165
18168
  const wrapperContent = `#!/bin/bash
18166
18169
  exec "${exeStartDst}" "$0" "$@"
18167
18170
  `;
18171
+ const globalBinDir = shouldMirrorToGlobalBin ? resolveGlobalBinDir() : null;
18168
18172
  for (const emp of employees) {
18169
18173
  for (let n = 1; n <= MAX_N; n++) {
18170
- const wrapperPath = path37.join(binDir, `${emp.name}${n}`);
18171
- writeFileSync22(wrapperPath, wrapperContent);
18172
- chmodSync3(wrapperPath, 493);
18174
+ writeWrapper(path37.join(binDir, `${emp.name}${n}`), wrapperContent);
18175
+ if (globalBinDir) {
18176
+ writeWrapper(path37.join(globalBinDir, `${emp.name}${n}`), wrapperContent);
18177
+ }
18173
18178
  created++;
18174
- const codexPath = path37.join(binDir, `${emp.name}${n}-codex`);
18175
- writeFileSync22(codexPath, wrapperContent);
18176
- chmodSync3(codexPath, 493);
18179
+ writeWrapper(path37.join(binDir, `${emp.name}${n}-codex`), wrapperContent);
18180
+ if (globalBinDir) {
18181
+ writeWrapper(path37.join(globalBinDir, `${emp.name}${n}-codex`), wrapperContent);
18182
+ }
18177
18183
  created++;
18178
18184
  }
18179
18185
  }
@@ -18202,6 +18208,26 @@ exec node "${codexLauncher}" --agent ${emp.name} "$@"
18202
18208
  const pathConfigured = ensurePath(home, binDir);
18203
18209
  return { created, pathConfigured };
18204
18210
  }
18211
+ function writeWrapper(wrapperPath, content) {
18212
+ try {
18213
+ writeFileSync22(wrapperPath, content);
18214
+ chmodSync3(wrapperPath, 493);
18215
+ } catch {
18216
+ }
18217
+ }
18218
+ function resolveGlobalBinDir() {
18219
+ try {
18220
+ const exeOsPath = execSync13("command -v exe-os", { encoding: "utf8", timeout: 3e3 }).trim().split("\n")[0];
18221
+ if (exeOsPath) return path37.dirname(exeOsPath);
18222
+ } catch {
18223
+ }
18224
+ try {
18225
+ const prefix = execSync13("npm prefix -g", { encoding: "utf8", timeout: 3e3 }).trim();
18226
+ if (prefix) return path37.join(prefix, "bin");
18227
+ } catch {
18228
+ }
18229
+ return null;
18230
+ }
18205
18231
  function ensurePath(home, binDir) {
18206
18232
  if (process.env.PATH?.split(":").includes(binDir)) {
18207
18233
  return false;
@@ -18303,8 +18329,8 @@ function ask3(rl, prompt) {
18303
18329
  function getAvailableMemoryGB2() {
18304
18330
  if (process.platform === "darwin") {
18305
18331
  try {
18306
- const { execSync: execSync17 } = __require("child_process");
18307
- const vmstat = execSync17("vm_stat", { encoding: "utf8" });
18332
+ const { execSync: execSync18 } = __require("child_process");
18333
+ const vmstat = execSync18("vm_stat", { encoding: "utf8" });
18308
18334
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
18309
18335
  const pageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : 16384;
18310
18336
  const free = vmstat.match(/Pages free:\s+(\d+)/);
@@ -19164,7 +19190,7 @@ var init_update_backup = __esm({
19164
19190
  });
19165
19191
 
19166
19192
  // src/lib/update-check.ts
19167
- import { execSync as execSync13 } from "child_process";
19193
+ import { execSync as execSync14 } from "child_process";
19168
19194
  import { readFileSync as readFileSync27 } from "fs";
19169
19195
  import path40 from "path";
19170
19196
  function getLocalVersion(packageRoot) {
@@ -19174,7 +19200,7 @@ function getLocalVersion(packageRoot) {
19174
19200
  }
19175
19201
  function getRemoteVersion() {
19176
19202
  try {
19177
- const output = execSync13("npm view @askexenow/exe-os version", {
19203
+ const output = execSync14("npm view @askexenow/exe-os version", {
19178
19204
  encoding: "utf-8",
19179
19205
  timeout: 15e3,
19180
19206
  stdio: ["pipe", "pipe", "pipe"]
@@ -19213,7 +19239,7 @@ __export(update_exports, {
19213
19239
  getRemoteVersion: () => getRemoteVersion,
19214
19240
  runUpdate: () => runUpdate
19215
19241
  });
19216
- import { execSync as execSync14 } from "child_process";
19242
+ import { execSync as execSync15 } from "child_process";
19217
19243
  import { createInterface as createInterface5 } from "readline";
19218
19244
  async function runRestore() {
19219
19245
  console.log("\n\u{1F504} Restoring from update backup...");
@@ -19224,7 +19250,7 @@ async function runRestore() {
19224
19250
  console.log(`
19225
19251
  \u{1F4E5} Reinstalling @askexenow/exe-os@${manifest.version}...`);
19226
19252
  try {
19227
- execSync14(`npm install -g @askexenow/exe-os@${manifest.version}`, {
19253
+ execSync15(`npm install -g @askexenow/exe-os@${manifest.version}`, {
19228
19254
  stdio: ["pipe", "pipe", "inherit"],
19229
19255
  timeout: 3e5
19230
19256
  });
@@ -19301,7 +19327,7 @@ async function runUpdate(cliArgs) {
19301
19327
  }
19302
19328
  console.log("\u{1F9F9} Clearing npm cache...");
19303
19329
  try {
19304
- execSync14("npm cache clean --force", { stdio: "pipe" });
19330
+ execSync15("npm cache clean --force", { stdio: "pipe" });
19305
19331
  console.log(" Done");
19306
19332
  } catch {
19307
19333
  console.log(" Skipped (non-critical)");
@@ -19309,7 +19335,7 @@ async function runUpdate(cliArgs) {
19309
19335
  console.log("\u{1F4E5} Installing @askexenow/exe-os@latest...");
19310
19336
  console.log(" This may take a minute...\n");
19311
19337
  try {
19312
- execSync14("npm install -g @askexenow/exe-os@latest", {
19338
+ execSync15("npm install -g @askexenow/exe-os@latest", {
19313
19339
  stdio: ["pipe", "pipe", "inherit"],
19314
19340
  timeout: 3e5
19315
19341
  });
@@ -19327,7 +19353,7 @@ async function runUpdate(cliArgs) {
19327
19353
  newVersion = getLocalVersion(packageRoot);
19328
19354
  } catch {
19329
19355
  try {
19330
- const out = execSync14("npm list -g @askexenow/exe-os --depth=0 2>/dev/null", { encoding: "utf8" });
19356
+ const out = execSync15("npm list -g @askexenow/exe-os --depth=0 2>/dev/null", { encoding: "utf8" });
19331
19357
  const match = out.match(/@askexenow\/exe-os@(\S+)/);
19332
19358
  newVersion = match?.[1] ?? "unknown";
19333
19359
  } catch {
@@ -19356,7 +19382,7 @@ async function runUpdate(cliArgs) {
19356
19382
  }
19357
19383
  console.log("\u{1F527} Re-registering MCP, hooks, wrappers, and daemon...");
19358
19384
  try {
19359
- execSync14("exe-os-install --global", {
19385
+ execSync15("exe-os-install --global", {
19360
19386
  stdio: ["pipe", "inherit", "inherit"],
19361
19387
  timeout: 3e5
19362
19388
  });
@@ -26693,13 +26719,13 @@ __export(tmux_status_exports, {
26693
26719
  parseActivity: () => parseActivity,
26694
26720
  parseContextPercentage: () => parseContextPercentage
26695
26721
  });
26696
- import { execSync as execSync15 } from "child_process";
26722
+ import { execSync as execSync16 } from "child_process";
26697
26723
  function inTmux() {
26698
26724
  if (process.env.TMUX || process.env.TMUX_PANE) return true;
26699
26725
  const term = process.env.TERM ?? "";
26700
26726
  if (term.startsWith("tmux") || term.startsWith("screen")) return true;
26701
26727
  try {
26702
- execSync15("tmux display-message -p '#{session_name}' 2>/dev/null", {
26728
+ execSync16("tmux display-message -p '#{session_name}' 2>/dev/null", {
26703
26729
  encoding: "utf8",
26704
26730
  timeout: 2e3
26705
26731
  });
@@ -26709,12 +26735,12 @@ function inTmux() {
26709
26735
  try {
26710
26736
  let pid = process.ppid;
26711
26737
  for (let depth = 0; depth < 8 && pid > 1; depth++) {
26712
- const comm = execSync15(`ps -p ${pid} -o comm= 2>/dev/null`, {
26738
+ const comm = execSync16(`ps -p ${pid} -o comm= 2>/dev/null`, {
26713
26739
  encoding: "utf8",
26714
26740
  timeout: 1e3
26715
26741
  }).trim();
26716
26742
  if (/tmux/.test(comm)) return true;
26717
- const ppid = execSync15(`ps -p ${pid} -o ppid= 2>/dev/null`, {
26743
+ const ppid = execSync16(`ps -p ${pid} -o ppid= 2>/dev/null`, {
26718
26744
  encoding: "utf8",
26719
26745
  timeout: 1e3
26720
26746
  }).trim();
@@ -26727,7 +26753,7 @@ function inTmux() {
26727
26753
  }
26728
26754
  function listTmuxSessions() {
26729
26755
  try {
26730
- const out = execSync15("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
26756
+ const out = execSync16("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
26731
26757
  encoding: "utf8",
26732
26758
  timeout: 3e3
26733
26759
  });
@@ -26738,7 +26764,7 @@ function listTmuxSessions() {
26738
26764
  }
26739
26765
  function capturePaneLines(windowName, lines = 10) {
26740
26766
  try {
26741
- const out = execSync15(
26767
+ const out = execSync16(
26742
26768
  `tmux capture-pane -t ${JSON.stringify(windowName)} -p 2>/dev/null | tail -${lines}`,
26743
26769
  { encoding: "utf8", timeout: 3e3 }
26744
26770
  );
@@ -26749,7 +26775,7 @@ function capturePaneLines(windowName, lines = 10) {
26749
26775
  }
26750
26776
  function getPaneCwd(windowName) {
26751
26777
  try {
26752
- const out = execSync15(
26778
+ const out = execSync16(
26753
26779
  `tmux display-message -t ${JSON.stringify(windowName)} -p '#{pane_current_path}' 2>/dev/null`,
26754
26780
  { encoding: "utf8", timeout: 3e3 }
26755
26781
  );
@@ -26760,7 +26786,7 @@ function getPaneCwd(windowName) {
26760
26786
  }
26761
26787
  function projectFromPath(dir) {
26762
26788
  try {
26763
- const root = execSync15("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
26789
+ const root = execSync16("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
26764
26790
  encoding: "utf8",
26765
26791
  timeout: 3e3
26766
26792
  }).trim();
@@ -26829,7 +26855,7 @@ function getEmployeeStatuses(employeeNames) {
26829
26855
  }
26830
26856
  let paneAlive = true;
26831
26857
  try {
26832
- const paneStatus = execSync15(
26858
+ const paneStatus = execSync16(
26833
26859
  `tmux list-panes -t ${JSON.stringify(sessionName)} -F '#{pane_dead}' 2>/dev/null`,
26834
26860
  { encoding: "utf8", timeout: 3e3 }
26835
26861
  ).trim();
@@ -27019,8 +27045,8 @@ function Footer() {
27019
27045
  setSessions(allSessions.length);
27020
27046
  if (!currentSession) {
27021
27047
  try {
27022
- const { execSync: execSync17 } = await import("child_process");
27023
- const name = execSync17("tmux display-message -p '#{session_name}' 2>/dev/null", {
27048
+ const { execSync: execSync18 } = await import("child_process");
27049
+ const name = execSync18("tmux display-message -p '#{session_name}' 2>/dev/null", {
27024
27050
  encoding: "utf8",
27025
27051
  timeout: 2e3
27026
27052
  }).trim();
@@ -30374,8 +30400,8 @@ function TmuxPane({ sessionName, employeeName, employeeRole, projectName, onDeta
30374
30400
  }
30375
30401
  const capture = () => {
30376
30402
  try {
30377
- const { execSync: execSync17 } = __require("child_process");
30378
- const output = execSync17(
30403
+ const { execSync: execSync18 } = __require("child_process");
30404
+ const output = execSync18(
30379
30405
  `tmux capture-pane -t ${JSON.stringify(sessionName)} -p -e 2>/dev/null | tail -${CAPTURE_LINES}`,
30380
30406
  { encoding: "utf8", timeout: 3e3 }
30381
30407
  );
@@ -30399,8 +30425,8 @@ function TmuxPane({ sessionName, employeeName, employeeRole, projectName, onDeta
30399
30425
  if (key.return) {
30400
30426
  if (!demo && inputBuffer.trim()) {
30401
30427
  try {
30402
- const { execSync: execSync17 } = __require("child_process");
30403
- execSync17(
30428
+ const { execSync: execSync18 } = __require("child_process");
30429
+ execSync18(
30404
30430
  `tmux send-keys -t ${JSON.stringify(sessionName)} ${JSON.stringify(inputBuffer)} Enter`,
30405
30431
  { timeout: 2e3 }
30406
30432
  );
@@ -30408,8 +30434,8 @@ function TmuxPane({ sessionName, employeeName, employeeRole, projectName, onDeta
30408
30434
  }
30409
30435
  } else if (!demo) {
30410
30436
  try {
30411
- const { execSync: execSync17 } = __require("child_process");
30412
- execSync17(`tmux send-keys -t ${JSON.stringify(sessionName)} Enter`, { timeout: 2e3 });
30437
+ const { execSync: execSync18 } = __require("child_process");
30438
+ execSync18(`tmux send-keys -t ${JSON.stringify(sessionName)} Enter`, { timeout: 2e3 });
30413
30439
  } catch {
30414
30440
  }
30415
30441
  }
@@ -31096,12 +31122,12 @@ function SessionsView({
31096
31122
  return;
31097
31123
  }
31098
31124
  } else {
31099
- const { execSync: execSync17 } = await import("child_process");
31125
+ const { execSync: execSync18 } = await import("child_process");
31100
31126
  const dir = projectDir || process.cwd();
31101
- execSync17(`tmux new-session -d -s ${JSON.stringify(entry.sessionName)} -c ${JSON.stringify(dir)}`, { timeout: 5e3 });
31102
- execSync17(`tmux send-keys -t ${JSON.stringify(entry.sessionName)} "claude --dangerously-skip-permissions" Enter`, { timeout: 3e3 });
31127
+ execSync18(`tmux new-session -d -s ${JSON.stringify(entry.sessionName)} -c ${JSON.stringify(dir)}`, { timeout: 5e3 });
31128
+ execSync18(`tmux send-keys -t ${JSON.stringify(entry.sessionName)} "claude --dangerously-skip-permissions" Enter`, { timeout: 3e3 });
31103
31129
  await new Promise((r) => setTimeout(r, 3e3));
31104
- execSync17(`tmux send-keys -t ${JSON.stringify(entry.sessionName)} "/exe" Enter`, { timeout: 3e3 });
31130
+ execSync18(`tmux send-keys -t ${JSON.stringify(entry.sessionName)} "/exe" Enter`, { timeout: 3e3 });
31105
31131
  }
31106
31132
  const updated = { ...entry, status: "active", activity: "Starting...", attached: false };
31107
31133
  setViewingEmployee(updated);
@@ -31204,7 +31230,7 @@ function SessionsView({
31204
31230
  const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2, capturePaneLines: capturePaneLines2, parseActivity: parseActivity2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
31205
31231
  const { getCoordinatorName: getCoordinatorName2, isCoordinatorRole: isCoordinatorRole2, loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
31206
31232
  const { isExeSession: isExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
31207
- const { execSync: execSync17 } = await import("child_process");
31233
+ const { execSync: execSync18 } = await import("child_process");
31208
31234
  if (!inTmux2()) {
31209
31235
  setTmuxAvailable(false);
31210
31236
  setProjects([]);
@@ -31213,7 +31239,7 @@ function SessionsView({
31213
31239
  setTmuxAvailable(true);
31214
31240
  const attachedMap = /* @__PURE__ */ new Map();
31215
31241
  try {
31216
- const out = execSync17("tmux list-sessions -F '#{session_name}:#{session_attached}' 2>/dev/null", {
31242
+ const out = execSync18("tmux list-sessions -F '#{session_name}:#{session_attached}' 2>/dev/null", {
31217
31243
  encoding: "utf8",
31218
31244
  timeout: 3e3
31219
31245
  });
@@ -32249,8 +32275,8 @@ function upsertConversation(conversations, platform, senderId, message) {
32249
32275
  async function loadGatewayConfig() {
32250
32276
  const state = { running: false, port: 3100, adapters: [], agents: [], gatewayUrl: "" };
32251
32277
  try {
32252
- const { execSync: execSync17 } = await import("child_process");
32253
- const ps = execSync17("pgrep -f exe-gateway 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
32278
+ const { execSync: execSync18 } = await import("child_process");
32279
+ const ps = execSync18("pgrep -f exe-gateway 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
32254
32280
  state.running = ps.trim().length > 0;
32255
32281
  } catch {
32256
32282
  state.running = false;
@@ -32727,10 +32753,10 @@ var init_Gateway = __esm({
32727
32753
  });
32728
32754
 
32729
32755
  // src/tui/utils/agent-status.ts
32730
- import { execSync as execSync16 } from "child_process";
32756
+ import { execSync as execSync17 } from "child_process";
32731
32757
  function getAgentStatus(agentId) {
32732
32758
  try {
32733
- const sessions = execSync16("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
32759
+ const sessions = execSync17("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
32734
32760
  encoding: "utf8",
32735
32761
  timeout: 2e3
32736
32762
  }).trim().split("\n");
@@ -32741,7 +32767,7 @@ function getAgentStatus(agentId) {
32741
32767
  return /^\d?-/.test(suffix) || /^\d+$/.test(suffix);
32742
32768
  });
32743
32769
  if (!agentSession) return { label: "offline", color: "gray" };
32744
- const pane = execSync16(`tmux capture-pane -t "${agentSession}" -p 2>/dev/null | tail -3`, {
32770
+ const pane = execSync17(`tmux capture-pane -t "${agentSession}" -p 2>/dev/null | tail -3`, {
32745
32771
  encoding: "utf8",
32746
32772
  timeout: 2e3
32747
32773
  });
@@ -33664,8 +33690,8 @@ function SettingsView({ onBack }) {
33664
33690
  };
33665
33691
  });
33666
33692
  try {
33667
- const { execSync: execSync17 } = await import("child_process");
33668
- execSync17("curl -s --max-time 1 http://localhost:11434/api/tags", { timeout: 2e3 });
33693
+ const { execSync: execSync18 } = await import("child_process");
33694
+ execSync18("curl -s --max-time 1 http://localhost:11434/api/tags", { timeout: 2e3 });
33669
33695
  providerList.push({ name: "Ollama", configured: true, detail: "localhost:11434" });
33670
33696
  } catch {
33671
33697
  providerList.push({ name: "Ollama", configured: false, detail: "not running" });
@@ -36461,10 +36487,10 @@ async function runClaudeUninstall(flags = []) {
36461
36487
  }
36462
36488
  }
36463
36489
  try {
36464
- const { execSync: execSync17 } = await import("child_process");
36490
+ const { execSync: execSync18 } = await import("child_process");
36465
36491
  const findExeBin3 = () => {
36466
36492
  try {
36467
- return execSync17(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
36493
+ return execSync18(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
36468
36494
  } catch {
36469
36495
  return null;
36470
36496
  }
@@ -5022,6 +5022,7 @@ __export(license_exports, {
5022
5022
  loadDeviceId: () => loadDeviceId,
5023
5023
  loadLicense: () => loadLicense,
5024
5024
  mirrorLicenseKey: () => mirrorLicenseKey,
5025
+ readCachedLicenseToken: () => readCachedLicenseToken,
5025
5026
  saveLicense: () => saveLicense,
5026
5027
  startLicenseRevalidation: () => startLicenseRevalidation,
5027
5028
  stopLicenseRevalidation: () => stopLicenseRevalidation,
@@ -5107,7 +5108,7 @@ async function getCachedLicense() {
5107
5108
  return null;
5108
5109
  }
5109
5110
  }
5110
- function readCachedToken() {
5111
+ function readCachedLicenseToken() {
5111
5112
  try {
5112
5113
  if (!existsSync11(CACHE_PATH)) return null;
5113
5114
  const raw = JSON.parse(readFileSync8(CACHE_PATH, "utf8"));
@@ -5118,7 +5119,7 @@ function readCachedToken() {
5118
5119
  }
5119
5120
  function getRawCachedPlan() {
5120
5121
  try {
5121
- const token = readCachedToken();
5122
+ const token = readCachedLicenseToken();
5122
5123
  if (!token) return null;
5123
5124
  const parts = token.split(".");
5124
5125
  if (parts.length !== 3) return null;
@@ -5385,7 +5386,7 @@ async function assertVpsLicense(opts) {
5385
5386
  const graceDays = opts?.offlineGraceDays ?? 7;
5386
5387
  const graceMs = graceDays * 24 * 60 * 60 * 1e3;
5387
5388
  try {
5388
- const token = readCachedToken();
5389
+ const token = readCachedLicenseToken();
5389
5390
  if (token) {
5390
5391
  const payloadB64 = token.split(".")[1];
5391
5392
  if (payloadB64) {
@@ -3676,6 +3676,7 @@ __export(license_exports, {
3676
3676
  loadDeviceId: () => loadDeviceId,
3677
3677
  loadLicense: () => loadLicense,
3678
3678
  mirrorLicenseKey: () => mirrorLicenseKey,
3679
+ readCachedLicenseToken: () => readCachedLicenseToken,
3679
3680
  saveLicense: () => saveLicense,
3680
3681
  startLicenseRevalidation: () => startLicenseRevalidation,
3681
3682
  stopLicenseRevalidation: () => stopLicenseRevalidation,
@@ -3761,7 +3762,7 @@ async function getCachedLicense() {
3761
3762
  return null;
3762
3763
  }
3763
3764
  }
3764
- function readCachedToken() {
3765
+ function readCachedLicenseToken() {
3765
3766
  try {
3766
3767
  if (!existsSync7(CACHE_PATH)) return null;
3767
3768
  const raw = JSON.parse(readFileSync5(CACHE_PATH, "utf8"));
@@ -3772,7 +3773,7 @@ function readCachedToken() {
3772
3773
  }
3773
3774
  function getRawCachedPlan() {
3774
3775
  try {
3775
- const token = readCachedToken();
3776
+ const token = readCachedLicenseToken();
3776
3777
  if (!token) return null;
3777
3778
  const parts = token.split(".");
3778
3779
  if (parts.length !== 3) return null;
@@ -4039,7 +4040,7 @@ async function assertVpsLicense(opts) {
4039
4040
  const graceDays = opts?.offlineGraceDays ?? 7;
4040
4041
  const graceMs = graceDays * 24 * 60 * 60 * 1e3;
4041
4042
  try {
4042
- const token = readCachedToken();
4043
+ const token = readCachedLicenseToken();
4043
4044
  if (token) {
4044
4045
  const payloadB64 = token.split(".")[1];
4045
4046
  if (payloadB64) {
@@ -7198,6 +7198,7 @@ __export(license_exports, {
7198
7198
  loadDeviceId: () => loadDeviceId,
7199
7199
  loadLicense: () => loadLicense,
7200
7200
  mirrorLicenseKey: () => mirrorLicenseKey,
7201
+ readCachedLicenseToken: () => readCachedLicenseToken,
7201
7202
  saveLicense: () => saveLicense,
7202
7203
  startLicenseRevalidation: () => startLicenseRevalidation,
7203
7204
  stopLicenseRevalidation: () => stopLicenseRevalidation,
@@ -7283,7 +7284,7 @@ async function getCachedLicense() {
7283
7284
  return null;
7284
7285
  }
7285
7286
  }
7286
- function readCachedToken() {
7287
+ function readCachedLicenseToken() {
7287
7288
  try {
7288
7289
  if (!existsSync9(CACHE_PATH)) return null;
7289
7290
  const raw = JSON.parse(readFileSync6(CACHE_PATH, "utf8"));
@@ -7294,7 +7295,7 @@ function readCachedToken() {
7294
7295
  }
7295
7296
  function getRawCachedPlan() {
7296
7297
  try {
7297
- const token = readCachedToken();
7298
+ const token = readCachedLicenseToken();
7298
7299
  if (!token) return null;
7299
7300
  const parts = token.split(".");
7300
7301
  if (parts.length !== 3) return null;
@@ -7561,7 +7562,7 @@ async function assertVpsLicense(opts) {
7561
7562
  const graceDays = opts?.offlineGraceDays ?? 7;
7562
7563
  const graceMs = graceDays * 24 * 60 * 60 * 1e3;
7563
7564
  try {
7564
- const token = readCachedToken();
7565
+ const token = readCachedLicenseToken();
7565
7566
  if (token) {
7566
7567
  const payloadB64 = token.split(".")[1];
7567
7568
  if (payloadB64) {
@@ -258,7 +258,7 @@ var init_agent_config = __esm({
258
258
  // src/lib/employees.ts
259
259
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
260
260
  import { existsSync as existsSync5, symlinkSync, readlinkSync, readFileSync as readFileSync4, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "fs";
261
- import { execSync } from "child_process";
261
+ import { execSync as execSync2 } from "child_process";
262
262
  import path4 from "path";
263
263
  import os2 from "os";
264
264
  function normalizeRole(role) {
@@ -364,7 +364,7 @@ async function hireEmployee(employee) {
364
364
  }
365
365
  function findExeBin() {
366
366
  try {
367
- return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
367
+ return execSync2(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
368
368
  } catch {
369
369
  return null;
370
370
  }
@@ -1486,7 +1486,7 @@ import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSy
1486
1486
  import { createHash as createHash2 } from "crypto";
1487
1487
  import path12 from "path";
1488
1488
  import os8 from "os";
1489
- import { execSync as execSync2 } from "child_process";
1489
+ import { execSync as execSync3 } from "child_process";
1490
1490
  import { fileURLToPath as fileURLToPath2 } from "url";
1491
1491
  function resolvePackageRoot() {
1492
1492
  const thisFile = fileURLToPath2(import.meta.url);
@@ -2297,7 +2297,7 @@ ${sourceLine}
2297
2297
  `);
2298
2298
  }
2299
2299
  try {
2300
- execSync2(`tmux source-file ${exeTmuxConf} 2>/dev/null`);
2300
+ execSync3(`tmux source-file ${exeTmuxConf} 2>/dev/null`);
2301
2301
  } catch {
2302
2302
  }
2303
2303
  process.stderr.write("exe-os: tmux config installed\n");
@@ -2308,7 +2308,7 @@ function setupGhostty(home) {
2308
2308
  const macConfig = path12.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
2309
2309
  const ghosttyInstalled = existsSync12(xdgConfig) || existsSync12(macConfig) || (() => {
2310
2310
  try {
2311
- execSync2("which ghostty 2>/dev/null");
2311
+ execSync3("which ghostty 2>/dev/null");
2312
2312
  return true;
2313
2313
  } catch {
2314
2314
  return false;
@@ -2415,6 +2415,7 @@ import {
2415
2415
  readdirSync,
2416
2416
  unlinkSync
2417
2417
  } from "fs";
2418
+ import { execSync } from "child_process";
2418
2419
  import path from "path";
2419
2420
  import { homedir } from "os";
2420
2421
  var MAX_N = 9;
@@ -2422,6 +2423,7 @@ function generateSessionWrappers(packageRoot, homeDir) {
2422
2423
  const home = homeDir ?? homedir();
2423
2424
  const binDir = path.join(home, ".exe-os", "bin");
2424
2425
  const rosterPath = path.join(home, ".exe-os", "exe-employees.json");
2426
+ const shouldMirrorToGlobalBin = homeDir === void 0;
2425
2427
  mkdirSync(binDir, { recursive: true });
2426
2428
  const exeStartDst = path.join(binDir, "exe-start");
2427
2429
  const candidates = [
@@ -2462,15 +2464,18 @@ function generateSessionWrappers(packageRoot, homeDir) {
2462
2464
  const wrapperContent = `#!/bin/bash
2463
2465
  exec "${exeStartDst}" "$0" "$@"
2464
2466
  `;
2467
+ const globalBinDir = shouldMirrorToGlobalBin ? resolveGlobalBinDir() : null;
2465
2468
  for (const emp of employees) {
2466
2469
  for (let n = 1; n <= MAX_N; n++) {
2467
- const wrapperPath = path.join(binDir, `${emp.name}${n}`);
2468
- writeFileSync(wrapperPath, wrapperContent);
2469
- chmodSync(wrapperPath, 493);
2470
+ writeWrapper(path.join(binDir, `${emp.name}${n}`), wrapperContent);
2471
+ if (globalBinDir) {
2472
+ writeWrapper(path.join(globalBinDir, `${emp.name}${n}`), wrapperContent);
2473
+ }
2470
2474
  created++;
2471
- const codexPath = path.join(binDir, `${emp.name}${n}-codex`);
2472
- writeFileSync(codexPath, wrapperContent);
2473
- chmodSync(codexPath, 493);
2475
+ writeWrapper(path.join(binDir, `${emp.name}${n}-codex`), wrapperContent);
2476
+ if (globalBinDir) {
2477
+ writeWrapper(path.join(globalBinDir, `${emp.name}${n}-codex`), wrapperContent);
2478
+ }
2474
2479
  created++;
2475
2480
  }
2476
2481
  }
@@ -2499,6 +2504,26 @@ exec node "${codexLauncher}" --agent ${emp.name} "$@"
2499
2504
  const pathConfigured = ensurePath(home, binDir);
2500
2505
  return { created, pathConfigured };
2501
2506
  }
2507
+ function writeWrapper(wrapperPath, content) {
2508
+ try {
2509
+ writeFileSync(wrapperPath, content);
2510
+ chmodSync(wrapperPath, 493);
2511
+ } catch {
2512
+ }
2513
+ }
2514
+ function resolveGlobalBinDir() {
2515
+ try {
2516
+ const exeOsPath = execSync("command -v exe-os", { encoding: "utf8", timeout: 3e3 }).trim().split("\n")[0];
2517
+ if (exeOsPath) return path.dirname(exeOsPath);
2518
+ } catch {
2519
+ }
2520
+ try {
2521
+ const prefix = execSync("npm prefix -g", { encoding: "utf8", timeout: 3e3 }).trim();
2522
+ if (prefix) return path.join(prefix, "bin");
2523
+ } catch {
2524
+ }
2525
+ return null;
2526
+ }
2502
2527
  function ensurePath(home, binDir) {
2503
2528
  if (process.env.PATH?.split(":").includes(binDir)) {
2504
2529
  return false;
@@ -3221,7 +3246,7 @@ async function getCachedLicense() {
3221
3246
  return null;
3222
3247
  }
3223
3248
  }
3224
- function readCachedToken() {
3249
+ function readCachedLicenseToken() {
3225
3250
  try {
3226
3251
  if (!existsSync6(CACHE_PATH)) return null;
3227
3252
  const raw = JSON.parse(readFileSync5(CACHE_PATH, "utf8"));
@@ -3232,7 +3257,7 @@ function readCachedToken() {
3232
3257
  }
3233
3258
  function getRawCachedPlan() {
3234
3259
  try {
3235
- const token = readCachedToken();
3260
+ const token = readCachedLicenseToken();
3236
3261
  if (!token) return null;
3237
3262
  const parts = token.split(".");
3238
3263
  if (parts.length !== 3) return null;
@@ -2057,7 +2057,7 @@ var init_installer2 = __esm({
2057
2057
  // src/bin/install.ts
2058
2058
  init_installer();
2059
2059
  import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync7, unlinkSync as unlinkSync3, readdirSync as readdirSync2, openSync, closeSync } from "fs";
2060
- import { spawn, execSync as execSync3 } from "child_process";
2060
+ import { spawn, execSync as execSync4 } from "child_process";
2061
2061
  import path10 from "path";
2062
2062
  import os8 from "os";
2063
2063
 
@@ -2071,6 +2071,7 @@ import {
2071
2071
  readdirSync,
2072
2072
  unlinkSync as unlinkSync2
2073
2073
  } from "fs";
2074
+ import { execSync as execSync3 } from "child_process";
2074
2075
  import path8 from "path";
2075
2076
  import { homedir } from "os";
2076
2077
  var MAX_N = 9;
@@ -2078,6 +2079,7 @@ function generateSessionWrappers(packageRoot, homeDir) {
2078
2079
  const home = homeDir ?? homedir();
2079
2080
  const binDir = path8.join(home, ".exe-os", "bin");
2080
2081
  const rosterPath = path8.join(home, ".exe-os", "exe-employees.json");
2082
+ const shouldMirrorToGlobalBin = homeDir === void 0;
2081
2083
  mkdirSync5(binDir, { recursive: true });
2082
2084
  const exeStartDst = path8.join(binDir, "exe-start");
2083
2085
  const candidates = [
@@ -2118,15 +2120,18 @@ function generateSessionWrappers(packageRoot, homeDir) {
2118
2120
  const wrapperContent = `#!/bin/bash
2119
2121
  exec "${exeStartDst}" "$0" "$@"
2120
2122
  `;
2123
+ const globalBinDir = shouldMirrorToGlobalBin ? resolveGlobalBinDir() : null;
2121
2124
  for (const emp of employees) {
2122
2125
  for (let n = 1; n <= MAX_N; n++) {
2123
- const wrapperPath = path8.join(binDir, `${emp.name}${n}`);
2124
- writeFileSync6(wrapperPath, wrapperContent);
2125
- chmodSync3(wrapperPath, 493);
2126
+ writeWrapper(path8.join(binDir, `${emp.name}${n}`), wrapperContent);
2127
+ if (globalBinDir) {
2128
+ writeWrapper(path8.join(globalBinDir, `${emp.name}${n}`), wrapperContent);
2129
+ }
2126
2130
  created++;
2127
- const codexPath = path8.join(binDir, `${emp.name}${n}-codex`);
2128
- writeFileSync6(codexPath, wrapperContent);
2129
- chmodSync3(codexPath, 493);
2131
+ writeWrapper(path8.join(binDir, `${emp.name}${n}-codex`), wrapperContent);
2132
+ if (globalBinDir) {
2133
+ writeWrapper(path8.join(globalBinDir, `${emp.name}${n}-codex`), wrapperContent);
2134
+ }
2130
2135
  created++;
2131
2136
  }
2132
2137
  }
@@ -2155,6 +2160,26 @@ exec node "${codexLauncher}" --agent ${emp.name} "$@"
2155
2160
  const pathConfigured = ensurePath(home, binDir);
2156
2161
  return { created, pathConfigured };
2157
2162
  }
2163
+ function writeWrapper(wrapperPath, content) {
2164
+ try {
2165
+ writeFileSync6(wrapperPath, content);
2166
+ chmodSync3(wrapperPath, 493);
2167
+ } catch {
2168
+ }
2169
+ }
2170
+ function resolveGlobalBinDir() {
2171
+ try {
2172
+ const exeOsPath = execSync3("command -v exe-os", { encoding: "utf8", timeout: 3e3 }).trim().split("\n")[0];
2173
+ if (exeOsPath) return path8.dirname(exeOsPath);
2174
+ } catch {
2175
+ }
2176
+ try {
2177
+ const prefix = execSync3("npm prefix -g", { encoding: "utf8", timeout: 3e3 }).trim();
2178
+ if (prefix) return path8.join(prefix, "bin");
2179
+ } catch {
2180
+ }
2181
+ return null;
2182
+ }
2158
2183
  function ensurePath(home, binDir) {
2159
2184
  if (process.env.PATH?.split(":").includes(binDir)) {
2160
2185
  return false;
@@ -2213,7 +2238,7 @@ function restartDaemon() {
2213
2238
  }
2214
2239
  }
2215
2240
  try {
2216
- const pids = execSync3("pgrep -f 'exe-daemon.js' 2>/dev/null || true", { encoding: "utf8" }).trim().split("\n").filter(Boolean).map(Number).filter((n) => !isNaN(n) && n !== process.pid);
2241
+ const pids = execSync4("pgrep -f 'exe-daemon.js' 2>/dev/null || true", { encoding: "utf8" }).trim().split("\n").filter(Boolean).map(Number).filter((n) => !isNaN(n) && n !== process.pid);
2217
2242
  for (const pid of pids) {
2218
2243
  try {
2219
2244
  process.kill(pid, "SIGKILL");
@@ -2227,7 +2252,7 @@ function restartDaemon() {
2227
2252
  } catch {
2228
2253
  }
2229
2254
  try {
2230
- const pids = execSync3("pgrep -f 'backfill-vectors.js' 2>/dev/null || true", { encoding: "utf8" }).trim().split("\n").filter(Boolean).map(Number).filter((n) => !isNaN(n) && n !== process.pid);
2255
+ const pids = execSync4("pgrep -f 'backfill-vectors.js' 2>/dev/null || true", { encoding: "utf8" }).trim().split("\n").filter(Boolean).map(Number).filter((n) => !isNaN(n) && n !== process.pid);
2231
2256
  for (const pid of pids) {
2232
2257
  try {
2233
2258
  process.kill(pid, "SIGKILL");
@@ -2264,7 +2289,7 @@ function restartDaemon() {
2264
2289
  } catch {
2265
2290
  }
2266
2291
  try {
2267
- execSync3("sleep 0.5");
2292
+ execSync4("sleep 0.5");
2268
2293
  } catch {
2269
2294
  }
2270
2295
  } catch {
@@ -2357,7 +2382,7 @@ if (args.includes("--commands-only")) {
2357
2382
  `);
2358
2383
  }
2359
2384
  try {
2360
- execSync3("which codex", { encoding: "utf8", timeout: 5e3 });
2385
+ execSync4("which codex", { encoding: "utf8", timeout: 5e3 });
2361
2386
  const { runCodexInstaller: runCodexInstaller2 } = await Promise.resolve().then(() => (init_installer2(), installer_exports));
2362
2387
  await runCodexInstaller2();
2363
2388
  } catch {
package/dist/bin/setup.js CHANGED
@@ -911,8 +911,8 @@ function findPackageRoot() {
911
911
  function getAvailableMemoryGB() {
912
912
  if (process.platform === "darwin") {
913
913
  try {
914
- const { execSync: execSync3 } = __require("child_process");
915
- const vmstat = execSync3("vm_stat", { encoding: "utf8" });
914
+ const { execSync: execSync4 } = __require("child_process");
915
+ const vmstat = execSync4("vm_stat", { encoding: "utf8" });
916
916
  const pageSize = 16384;
917
917
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
918
918
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -1355,6 +1355,7 @@ __export(license_exports, {
1355
1355
  loadDeviceId: () => loadDeviceId,
1356
1356
  loadLicense: () => loadLicense,
1357
1357
  mirrorLicenseKey: () => mirrorLicenseKey,
1358
+ readCachedLicenseToken: () => readCachedLicenseToken,
1358
1359
  saveLicense: () => saveLicense,
1359
1360
  startLicenseRevalidation: () => startLicenseRevalidation,
1360
1361
  stopLicenseRevalidation: () => stopLicenseRevalidation,
@@ -1440,7 +1441,7 @@ async function getCachedLicense() {
1440
1441
  return null;
1441
1442
  }
1442
1443
  }
1443
- function readCachedToken() {
1444
+ function readCachedLicenseToken() {
1444
1445
  try {
1445
1446
  if (!existsSync7(CACHE_PATH)) return null;
1446
1447
  const raw = JSON.parse(readFileSync4(CACHE_PATH, "utf8"));
@@ -1451,7 +1452,7 @@ function readCachedToken() {
1451
1452
  }
1452
1453
  function getRawCachedPlan() {
1453
1454
  try {
1454
- const token = readCachedToken();
1455
+ const token = readCachedLicenseToken();
1455
1456
  if (!token) return null;
1456
1457
  const parts = token.split(".");
1457
1458
  if (parts.length !== 3) return null;
@@ -1718,7 +1719,7 @@ async function assertVpsLicense(opts) {
1718
1719
  const graceDays = opts?.offlineGraceDays ?? 7;
1719
1720
  const graceMs = graceDays * 24 * 60 * 60 * 1e3;
1720
1721
  try {
1721
- const token = readCachedToken();
1722
+ const token = readCachedLicenseToken();
1722
1723
  if (token) {
1723
1724
  const payloadB64 = token.split(".")[1];
1724
1725
  if (payloadB64) {
@@ -7906,12 +7907,14 @@ import {
7906
7907
  readdirSync as readdirSync4,
7907
7908
  unlinkSync as unlinkSync7
7908
7909
  } from "fs";
7910
+ import { execSync as execSync3 } from "child_process";
7909
7911
  import path16 from "path";
7910
7912
  import { homedir as homedir3 } from "os";
7911
7913
  function generateSessionWrappers(packageRoot, homeDir) {
7912
7914
  const home = homeDir ?? homedir3();
7913
7915
  const binDir = path16.join(home, ".exe-os", "bin");
7914
7916
  const rosterPath = path16.join(home, ".exe-os", "exe-employees.json");
7917
+ const shouldMirrorToGlobalBin = homeDir === void 0;
7915
7918
  mkdirSync8(binDir, { recursive: true });
7916
7919
  const exeStartDst = path16.join(binDir, "exe-start");
7917
7920
  const candidates = [
@@ -7952,15 +7955,18 @@ function generateSessionWrappers(packageRoot, homeDir) {
7952
7955
  const wrapperContent = `#!/bin/bash
7953
7956
  exec "${exeStartDst}" "$0" "$@"
7954
7957
  `;
7958
+ const globalBinDir = shouldMirrorToGlobalBin ? resolveGlobalBinDir() : null;
7955
7959
  for (const emp of employees) {
7956
7960
  for (let n = 1; n <= MAX_N; n++) {
7957
- const wrapperPath = path16.join(binDir, `${emp.name}${n}`);
7958
- writeFileSync10(wrapperPath, wrapperContent);
7959
- chmodSync2(wrapperPath, 493);
7961
+ writeWrapper(path16.join(binDir, `${emp.name}${n}`), wrapperContent);
7962
+ if (globalBinDir) {
7963
+ writeWrapper(path16.join(globalBinDir, `${emp.name}${n}`), wrapperContent);
7964
+ }
7960
7965
  created++;
7961
- const codexPath = path16.join(binDir, `${emp.name}${n}-codex`);
7962
- writeFileSync10(codexPath, wrapperContent);
7963
- chmodSync2(codexPath, 493);
7966
+ writeWrapper(path16.join(binDir, `${emp.name}${n}-codex`), wrapperContent);
7967
+ if (globalBinDir) {
7968
+ writeWrapper(path16.join(globalBinDir, `${emp.name}${n}-codex`), wrapperContent);
7969
+ }
7964
7970
  created++;
7965
7971
  }
7966
7972
  }
@@ -7989,6 +7995,26 @@ exec node "${codexLauncher}" --agent ${emp.name} "$@"
7989
7995
  const pathConfigured = ensurePath(home, binDir);
7990
7996
  return { created, pathConfigured };
7991
7997
  }
7998
+ function writeWrapper(wrapperPath, content) {
7999
+ try {
8000
+ writeFileSync10(wrapperPath, content);
8001
+ chmodSync2(wrapperPath, 493);
8002
+ } catch {
8003
+ }
8004
+ }
8005
+ function resolveGlobalBinDir() {
8006
+ try {
8007
+ const exeOsPath = execSync3("command -v exe-os", { encoding: "utf8", timeout: 3e3 }).trim().split("\n")[0];
8008
+ if (exeOsPath) return path16.dirname(exeOsPath);
8009
+ } catch {
8010
+ }
8011
+ try {
8012
+ const prefix = execSync3("npm prefix -g", { encoding: "utf8", timeout: 3e3 }).trim();
8013
+ if (prefix) return path16.join(prefix, "bin");
8014
+ } catch {
8015
+ }
8016
+ return null;
8017
+ }
7992
8018
  function ensurePath(home, binDir) {
7993
8019
  if (process.env.PATH?.split(":").includes(binDir)) {
7994
8020
  return false;
@@ -8177,8 +8203,8 @@ function ask(rl, prompt) {
8177
8203
  function getAvailableMemoryGB2() {
8178
8204
  if (process.platform === "darwin") {
8179
8205
  try {
8180
- const { execSync: execSync3 } = __require("child_process");
8181
- const vmstat = execSync3("vm_stat", { encoding: "utf8" });
8206
+ const { execSync: execSync4 } = __require("child_process");
8207
+ const vmstat = execSync4("vm_stat", { encoding: "utf8" });
8182
8208
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
8183
8209
  const pageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : 16384;
8184
8210
  const free = vmstat.match(/Pages free:\s+(\d+)/);
@@ -135,6 +135,7 @@ __export(license_exports, {
135
135
  loadDeviceId: () => loadDeviceId,
136
136
  loadLicense: () => loadLicense,
137
137
  mirrorLicenseKey: () => mirrorLicenseKey,
138
+ readCachedLicenseToken: () => readCachedLicenseToken,
138
139
  saveLicense: () => saveLicense,
139
140
  startLicenseRevalidation: () => startLicenseRevalidation,
140
141
  stopLicenseRevalidation: () => stopLicenseRevalidation,
@@ -220,7 +221,7 @@ async function getCachedLicense() {
220
221
  return null;
221
222
  }
222
223
  }
223
- function readCachedToken() {
224
+ function readCachedLicenseToken() {
224
225
  try {
225
226
  if (!existsSync4(CACHE_PATH)) return null;
226
227
  const raw = JSON.parse(readFileSync3(CACHE_PATH, "utf8"));
@@ -231,7 +232,7 @@ function readCachedToken() {
231
232
  }
232
233
  function getRawCachedPlan() {
233
234
  try {
234
- const token = readCachedToken();
235
+ const token = readCachedLicenseToken();
235
236
  if (!token) return null;
236
237
  const parts = token.split(".");
237
238
  if (parts.length !== 3) return null;
@@ -498,7 +499,7 @@ async function assertVpsLicense(opts) {
498
499
  const graceDays = opts?.offlineGraceDays ?? 7;
499
500
  const graceMs = graceDays * 24 * 60 * 60 * 1e3;
500
501
  try {
501
- const token = readCachedToken();
502
+ const token = readCachedLicenseToken();
502
503
  if (token) {
503
504
  const payloadB64 = token.split(".")[1];
504
505
  if (payloadB64) {
@@ -4668,6 +4668,7 @@ __export(license_exports, {
4668
4668
  loadDeviceId: () => loadDeviceId,
4669
4669
  loadLicense: () => loadLicense,
4670
4670
  mirrorLicenseKey: () => mirrorLicenseKey,
4671
+ readCachedLicenseToken: () => readCachedLicenseToken,
4671
4672
  saveLicense: () => saveLicense,
4672
4673
  startLicenseRevalidation: () => startLicenseRevalidation,
4673
4674
  stopLicenseRevalidation: () => stopLicenseRevalidation,
@@ -4753,7 +4754,7 @@ async function getCachedLicense() {
4753
4754
  return null;
4754
4755
  }
4755
4756
  }
4756
- function readCachedToken() {
4757
+ function readCachedLicenseToken() {
4757
4758
  try {
4758
4759
  if (!existsSync10(CACHE_PATH)) return null;
4759
4760
  const raw = JSON.parse(readFileSync7(CACHE_PATH, "utf8"));
@@ -4764,7 +4765,7 @@ function readCachedToken() {
4764
4765
  }
4765
4766
  function getRawCachedPlan() {
4766
4767
  try {
4767
- const token = readCachedToken();
4768
+ const token = readCachedLicenseToken();
4768
4769
  if (!token) return null;
4769
4770
  const parts = token.split(".");
4770
4771
  if (parts.length !== 3) return null;
@@ -5031,7 +5032,7 @@ async function assertVpsLicense(opts) {
5031
5032
  const graceDays = opts?.offlineGraceDays ?? 7;
5032
5033
  const graceMs = graceDays * 24 * 60 * 60 * 1e3;
5033
5034
  try {
5034
- const token = readCachedToken();
5035
+ const token = readCachedLicenseToken();
5035
5036
  if (token) {
5036
5037
  const payloadB64 = token.split(".")[1];
5037
5038
  if (payloadB64) {
@@ -9311,7 +9311,7 @@ async function getCachedLicense() {
9311
9311
  return null;
9312
9312
  }
9313
9313
  }
9314
- function readCachedToken() {
9314
+ function readCachedLicenseToken() {
9315
9315
  try {
9316
9316
  if (!existsSync15(CACHE_PATH)) return null;
9317
9317
  const raw = JSON.parse(readFileSync11(CACHE_PATH, "utf8"));
@@ -9322,7 +9322,7 @@ function readCachedToken() {
9322
9322
  }
9323
9323
  function getRawCachedPlan() {
9324
9324
  try {
9325
- const token = readCachedToken();
9325
+ const token = readCachedLicenseToken();
9326
9326
  if (!token) return null;
9327
9327
  const parts = token.split(".");
9328
9328
  if (parts.length !== 3) return null;
@@ -29887,6 +29887,7 @@ async function maybeSendUpstream(payload) {
29887
29887
  const endpoint2 = config2.support?.bugReportEndpoint || process.env.EXE_BUG_REPORT_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/bug-reports` : "https://askexe.com/v1/support/bug-reports");
29888
29888
  const token = config2.support?.bugReportToken || process.env.EXE_BUG_REPORT_TOKEN;
29889
29889
  const licenseKey = loadLicense() || process.env.EXE_LICENSE_KEY || config2.cloud?.apiKey;
29890
+ const licenseToken = readCachedLicenseToken();
29890
29891
  if (!endpoint2) {
29891
29892
  return "not_configured";
29892
29893
  }
@@ -29900,7 +29901,8 @@ async function maybeSendUpstream(payload) {
29900
29901
  headers: {
29901
29902
  "content-type": "application/json",
29902
29903
  ...token ? { authorization: `Bearer ${token}` } : {},
29903
- ...licenseKey ? { "x-exe-license-key": licenseKey } : {}
29904
+ ...licenseKey ? { "x-exe-license-key": licenseKey } : {},
29905
+ ...licenseToken ? { "x-exe-license-token": licenseToken } : {}
29904
29906
  },
29905
29907
  body: JSON.stringify(payload),
29906
29908
  signal: AbortSignal.timeout(1e4)
@@ -212,7 +212,7 @@ async function getCachedLicense() {
212
212
  return null;
213
213
  }
214
214
  }
215
- function readCachedToken() {
215
+ function readCachedLicenseToken() {
216
216
  try {
217
217
  if (!existsSync3(CACHE_PATH)) return null;
218
218
  const raw = JSON.parse(readFileSync2(CACHE_PATH, "utf8"));
@@ -223,7 +223,7 @@ function readCachedToken() {
223
223
  }
224
224
  function getRawCachedPlan() {
225
225
  try {
226
- const token = readCachedToken();
226
+ const token = readCachedLicenseToken();
227
227
  if (!token) return null;
228
228
  const parts = token.split(".");
229
229
  if (parts.length !== 3) return null;
@@ -493,7 +493,7 @@ async function assertVpsLicense(opts) {
493
493
  const graceDays = opts?.offlineGraceDays ?? 7;
494
494
  const graceMs = graceDays * 24 * 60 * 60 * 1e3;
495
495
  try {
496
- const token = readCachedToken();
496
+ const token = readCachedLicenseToken();
497
497
  if (token) {
498
498
  const payloadB64 = token.split(".")[1];
499
499
  if (payloadB64) {
@@ -557,6 +557,7 @@ export {
557
557
  loadDeviceId,
558
558
  loadLicense,
559
559
  mirrorLicenseKey,
560
+ readCachedLicenseToken,
560
561
  saveLicense,
561
562
  startLicenseRevalidation,
562
563
  stopLicenseRevalidation,
@@ -8,6 +8,7 @@ import {
8
8
  readdirSync,
9
9
  unlinkSync
10
10
  } from "fs";
11
+ import { execSync } from "child_process";
11
12
  import path from "path";
12
13
  import { homedir } from "os";
13
14
  var MAX_N = 9;
@@ -15,6 +16,7 @@ function generateSessionWrappers(packageRoot, homeDir) {
15
16
  const home = homeDir ?? homedir();
16
17
  const binDir = path.join(home, ".exe-os", "bin");
17
18
  const rosterPath = path.join(home, ".exe-os", "exe-employees.json");
19
+ const shouldMirrorToGlobalBin = homeDir === void 0;
18
20
  mkdirSync(binDir, { recursive: true });
19
21
  const exeStartDst = path.join(binDir, "exe-start");
20
22
  const candidates = [
@@ -55,15 +57,18 @@ function generateSessionWrappers(packageRoot, homeDir) {
55
57
  const wrapperContent = `#!/bin/bash
56
58
  exec "${exeStartDst}" "$0" "$@"
57
59
  `;
60
+ const globalBinDir = shouldMirrorToGlobalBin ? resolveGlobalBinDir() : null;
58
61
  for (const emp of employees) {
59
62
  for (let n = 1; n <= MAX_N; n++) {
60
- const wrapperPath = path.join(binDir, `${emp.name}${n}`);
61
- writeFileSync(wrapperPath, wrapperContent);
62
- chmodSync(wrapperPath, 493);
63
+ writeWrapper(path.join(binDir, `${emp.name}${n}`), wrapperContent);
64
+ if (globalBinDir) {
65
+ writeWrapper(path.join(globalBinDir, `${emp.name}${n}`), wrapperContent);
66
+ }
63
67
  created++;
64
- const codexPath = path.join(binDir, `${emp.name}${n}-codex`);
65
- writeFileSync(codexPath, wrapperContent);
66
- chmodSync(codexPath, 493);
68
+ writeWrapper(path.join(binDir, `${emp.name}${n}-codex`), wrapperContent);
69
+ if (globalBinDir) {
70
+ writeWrapper(path.join(globalBinDir, `${emp.name}${n}-codex`), wrapperContent);
71
+ }
67
72
  created++;
68
73
  }
69
74
  }
@@ -92,6 +97,26 @@ exec node "${codexLauncher}" --agent ${emp.name} "$@"
92
97
  const pathConfigured = ensurePath(home, binDir);
93
98
  return { created, pathConfigured };
94
99
  }
100
+ function writeWrapper(wrapperPath, content) {
101
+ try {
102
+ writeFileSync(wrapperPath, content);
103
+ chmodSync(wrapperPath, 493);
104
+ } catch {
105
+ }
106
+ }
107
+ function resolveGlobalBinDir() {
108
+ try {
109
+ const exeOsPath = execSync("command -v exe-os", { encoding: "utf8", timeout: 3e3 }).trim().split("\n")[0];
110
+ if (exeOsPath) return path.dirname(exeOsPath);
111
+ } catch {
112
+ }
113
+ try {
114
+ const prefix = execSync("npm prefix -g", { encoding: "utf8", timeout: 3e3 }).trim();
115
+ if (prefix) return path.join(prefix, "bin");
116
+ } catch {
117
+ }
118
+ return null;
119
+ }
95
120
  function ensurePath(home, binDir) {
96
121
  if (process.env.PATH?.split(":").includes(binDir)) {
97
122
  return false;
@@ -8010,6 +8010,7 @@ __export(license_exports, {
8010
8010
  loadDeviceId: () => loadDeviceId,
8011
8011
  loadLicense: () => loadLicense,
8012
8012
  mirrorLicenseKey: () => mirrorLicenseKey,
8013
+ readCachedLicenseToken: () => readCachedLicenseToken,
8013
8014
  saveLicense: () => saveLicense,
8014
8015
  startLicenseRevalidation: () => startLicenseRevalidation,
8015
8016
  stopLicenseRevalidation: () => stopLicenseRevalidation,
@@ -8095,7 +8096,7 @@ async function getCachedLicense() {
8095
8096
  return null;
8096
8097
  }
8097
8098
  }
8098
- function readCachedToken() {
8099
+ function readCachedLicenseToken() {
8099
8100
  try {
8100
8101
  if (!existsSync11(CACHE_PATH)) return null;
8101
8102
  const raw = JSON.parse(readFileSync8(CACHE_PATH, "utf8"));
@@ -8106,7 +8107,7 @@ function readCachedToken() {
8106
8107
  }
8107
8108
  function getRawCachedPlan() {
8108
8109
  try {
8109
- const token = readCachedToken();
8110
+ const token = readCachedLicenseToken();
8110
8111
  if (!token) return null;
8111
8112
  const parts = token.split(".");
8112
8113
  if (parts.length !== 3) return null;
@@ -8373,7 +8374,7 @@ async function assertVpsLicense(opts) {
8373
8374
  const graceDays = opts?.offlineGraceDays ?? 7;
8374
8375
  const graceMs = graceDays * 24 * 60 * 60 * 1e3;
8375
8376
  try {
8376
- const token = readCachedToken();
8377
+ const token = readCachedLicenseToken();
8377
8378
  if (token) {
8378
8379
  const payloadB64 = token.split(".")[1];
8379
8380
  if (payloadB64) {
@@ -26873,6 +26874,7 @@ async function maybeSendUpstream(payload) {
26873
26874
  const endpoint2 = config2.support?.bugReportEndpoint || process.env.EXE_BUG_REPORT_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/bug-reports` : "https://askexe.com/v1/support/bug-reports");
26874
26875
  const token = config2.support?.bugReportToken || process.env.EXE_BUG_REPORT_TOKEN;
26875
26876
  const licenseKey = loadLicense() || process.env.EXE_LICENSE_KEY || config2.cloud?.apiKey;
26877
+ const licenseToken = readCachedLicenseToken();
26876
26878
  if (!endpoint2) {
26877
26879
  return "not_configured";
26878
26880
  }
@@ -26886,7 +26888,8 @@ async function maybeSendUpstream(payload) {
26886
26888
  headers: {
26887
26889
  "content-type": "application/json",
26888
26890
  ...token ? { authorization: `Bearer ${token}` } : {},
26889
- ...licenseKey ? { "x-exe-license-key": licenseKey } : {}
26891
+ ...licenseKey ? { "x-exe-license-key": licenseKey } : {},
26892
+ ...licenseToken ? { "x-exe-license-token": licenseToken } : {}
26890
26893
  },
26891
26894
  body: JSON.stringify(payload),
26892
26895
  signal: AbortSignal.timeout(1e4)
package/dist/tui/App.js CHANGED
@@ -3914,6 +3914,7 @@ __export(license_exports, {
3914
3914
  loadDeviceId: () => loadDeviceId,
3915
3915
  loadLicense: () => loadLicense,
3916
3916
  mirrorLicenseKey: () => mirrorLicenseKey,
3917
+ readCachedLicenseToken: () => readCachedLicenseToken,
3917
3918
  saveLicense: () => saveLicense,
3918
3919
  startLicenseRevalidation: () => startLicenseRevalidation,
3919
3920
  stopLicenseRevalidation: () => stopLicenseRevalidation,
@@ -3999,7 +4000,7 @@ async function getCachedLicense() {
3999
4000
  return null;
4000
4001
  }
4001
4002
  }
4002
- function readCachedToken() {
4003
+ function readCachedLicenseToken() {
4003
4004
  try {
4004
4005
  if (!existsSync10(CACHE_PATH)) return null;
4005
4006
  const raw = JSON.parse(readFileSync9(CACHE_PATH, "utf8"));
@@ -4010,7 +4011,7 @@ function readCachedToken() {
4010
4011
  }
4011
4012
  function getRawCachedPlan() {
4012
4013
  try {
4013
- const token = readCachedToken();
4014
+ const token = readCachedLicenseToken();
4014
4015
  if (!token) return null;
4015
4016
  const parts = token.split(".");
4016
4017
  if (parts.length !== 3) return null;
@@ -4277,7 +4278,7 @@ async function assertVpsLicense(opts) {
4277
4278
  const graceDays = opts?.offlineGraceDays ?? 7;
4278
4279
  const graceMs = graceDays * 24 * 60 * 60 * 1e3;
4279
4280
  try {
4280
- const token = readCachedToken();
4281
+ const token = readCachedLicenseToken();
4281
4282
  if (token) {
4282
4283
  const payloadB64 = token.split(".")[1];
4283
4284
  if (payloadB64) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.73",
3
+ "version": "0.9.75",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",