@askexenow/exe-os 0.9.84 → 0.9.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +32 -14
  2. package/dist/bin/agentic-reflection-backfill.js +32 -14
  3. package/dist/bin/agentic-semantic-label.js +32 -14
  4. package/dist/bin/backfill-conversations.js +32 -14
  5. package/dist/bin/backfill-responses.js +32 -14
  6. package/dist/bin/backfill-vectors.js +32 -14
  7. package/dist/bin/bulk-sync-postgres.js +32 -14
  8. package/dist/bin/cleanup-stale-review-tasks.js +35 -17
  9. package/dist/bin/cli.js +224 -86
  10. package/dist/bin/exe-assign.js +32 -14
  11. package/dist/bin/exe-boot.js +57 -39
  12. package/dist/bin/exe-cloud.js +22 -4
  13. package/dist/bin/exe-dispatch.js +43 -25
  14. package/dist/bin/exe-doctor.js +22 -4
  15. package/dist/bin/exe-export-behaviors.js +32 -14
  16. package/dist/bin/exe-forget.js +32 -14
  17. package/dist/bin/exe-gateway.js +47 -29
  18. package/dist/bin/exe-heartbeat.js +37 -19
  19. package/dist/bin/exe-kill.js +36 -18
  20. package/dist/bin/exe-launch-agent.js +170 -79
  21. package/dist/bin/exe-new-employee.js +32 -0
  22. package/dist/bin/exe-pending-messages.js +35 -17
  23. package/dist/bin/exe-pending-notifications.js +35 -17
  24. package/dist/bin/exe-pending-reviews.js +37 -19
  25. package/dist/bin/exe-rename.js +34 -16
  26. package/dist/bin/exe-review.js +32 -14
  27. package/dist/bin/exe-search.js +40 -22
  28. package/dist/bin/exe-session-cleanup.js +67 -44
  29. package/dist/bin/exe-start-codex.js +39 -21
  30. package/dist/bin/exe-start-opencode.js +37 -19
  31. package/dist/bin/exe-status.js +44 -26
  32. package/dist/bin/exe-team.js +32 -14
  33. package/dist/bin/git-sweep.js +45 -27
  34. package/dist/bin/graph-backfill.js +32 -14
  35. package/dist/bin/graph-export.js +32 -14
  36. package/dist/bin/install.js +32 -0
  37. package/dist/bin/intercom-check.js +49 -31
  38. package/dist/bin/scan-tasks.js +45 -27
  39. package/dist/bin/setup.js +29 -11
  40. package/dist/bin/shard-migrate.js +32 -14
  41. package/dist/bin/stack-update.js +95 -7
  42. package/dist/bin/update.js +1 -1
  43. package/dist/gateway/index.js +47 -29
  44. package/dist/hooks/bug-report-worker.js +47 -29
  45. package/dist/hooks/codex-stop-task-finalizer.js +41 -23
  46. package/dist/hooks/commit-complete.js +46 -28
  47. package/dist/hooks/error-recall.js +44 -26
  48. package/dist/hooks/ingest-worker.js +4 -4
  49. package/dist/hooks/ingest.js +38 -20
  50. package/dist/hooks/instructions-loaded.js +32 -14
  51. package/dist/hooks/notification.js +32 -14
  52. package/dist/hooks/post-compact.js +32 -14
  53. package/dist/hooks/post-tool-combined.js +45 -27
  54. package/dist/hooks/pre-compact.js +43 -25
  55. package/dist/hooks/pre-tool-use.js +40 -22
  56. package/dist/hooks/prompt-submit.js +60 -42
  57. package/dist/hooks/session-end.js +48 -30
  58. package/dist/hooks/session-start.js +50 -32
  59. package/dist/hooks/stop.js +35 -17
  60. package/dist/hooks/subagent-stop.js +32 -14
  61. package/dist/hooks/summary-worker.js +37 -19
  62. package/dist/index.js +43 -25
  63. package/dist/lib/cloud-sync.js +32 -14
  64. package/dist/lib/database.js +22 -4
  65. package/dist/lib/db-daemon-client.js +16 -4
  66. package/dist/lib/db.js +22 -4
  67. package/dist/lib/device-registry.js +22 -4
  68. package/dist/lib/embedder.js +16 -4
  69. package/dist/lib/exe-daemon-client.js +16 -4
  70. package/dist/lib/exe-daemon.js +165 -66
  71. package/dist/lib/hybrid-search.js +40 -22
  72. package/dist/lib/schedules.js +35 -17
  73. package/dist/lib/skill-learning.js +16 -4
  74. package/dist/lib/store.js +32 -14
  75. package/dist/lib/tasks.js +16 -4
  76. package/dist/lib/tmux-routing.js +18 -6
  77. package/dist/mcp/server.js +142 -60
  78. package/dist/mcp/tools/create-task.js +18 -6
  79. package/dist/mcp/tools/update-task.js +18 -6
  80. package/dist/runtime/index.js +43 -25
  81. package/dist/tui/App.js +73 -55
  82. package/package.json +1 -1
@@ -1501,7 +1501,7 @@ __export(exe_daemon_client_exports, {
1501
1501
  });
1502
1502
  import net from "net";
1503
1503
  import os4 from "os";
1504
- import { spawn } from "child_process";
1504
+ import { spawn, execSync as execSync2 } from "child_process";
1505
1505
  import { randomUUID } from "crypto";
1506
1506
  import { existsSync as existsSync7, unlinkSync as unlinkSync2, readFileSync as readFileSync6, openSync, closeSync, statSync } from "fs";
1507
1507
  import path7 from "path";
@@ -1531,6 +1531,14 @@ function handleData(chunk) {
1531
1531
  }
1532
1532
  }
1533
1533
  }
1534
+ function isZombie(pid) {
1535
+ try {
1536
+ const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
1537
+ return state.startsWith("Z");
1538
+ } catch {
1539
+ return false;
1540
+ }
1541
+ }
1534
1542
  function cleanupStaleFiles() {
1535
1543
  if (existsSync7(PID_PATH)) {
1536
1544
  try {
@@ -1538,7 +1546,11 @@ function cleanupStaleFiles() {
1538
1546
  if (pid > 0) {
1539
1547
  try {
1540
1548
  process.kill(pid, 0);
1541
- return;
1549
+ if (!isZombie(pid)) {
1550
+ return;
1551
+ }
1552
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
1553
+ `);
1542
1554
  } catch {
1543
1555
  }
1544
1556
  }
@@ -1566,8 +1578,8 @@ function findPackageRoot() {
1566
1578
  function getAvailableMemoryGB() {
1567
1579
  if (process.platform === "darwin") {
1568
1580
  try {
1569
- const { execSync: execSync17 } = __require("child_process");
1570
- const vmstat = execSync17("vm_stat", { encoding: "utf8" });
1581
+ const { execSync: execSync18 } = __require("child_process");
1582
+ const vmstat = execSync18("vm_stat", { encoding: "utf8" });
1571
1583
  const pageSize = 16384;
1572
1584
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1573
1585
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -3458,6 +3470,12 @@ async function disposeDatabase() {
3458
3470
  clearInterval(_walCheckpointTimer);
3459
3471
  _walCheckpointTimer = null;
3460
3472
  }
3473
+ if (_client) {
3474
+ try {
3475
+ await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
3476
+ } catch {
3477
+ }
3478
+ }
3461
3479
  if (_daemonClient) {
3462
3480
  _daemonClient.close();
3463
3481
  _daemonClient = null;
@@ -5198,7 +5216,7 @@ __export(keychain_exports, {
5198
5216
  });
5199
5217
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
5200
5218
  import { existsSync as existsSync11, statSync as statSync4 } from "fs";
5201
- import { execSync as execSync2 } from "child_process";
5219
+ import { execSync as execSync3 } from "child_process";
5202
5220
  import path11 from "path";
5203
5221
  import os6 from "os";
5204
5222
  function getKeyDir() {
@@ -5215,13 +5233,13 @@ function linuxSecretAvailable() {
5215
5233
  if (process.platform !== "linux") return false;
5216
5234
  if (linuxSecretAvailability !== null) return linuxSecretAvailability;
5217
5235
  try {
5218
- execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
5236
+ execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
5219
5237
  } catch {
5220
5238
  linuxSecretAvailability = false;
5221
5239
  return false;
5222
5240
  }
5223
5241
  try {
5224
- execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
5242
+ execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
5225
5243
  linuxSecretAvailability = true;
5226
5244
  } catch {
5227
5245
  linuxSecretAvailability = false;
@@ -5245,7 +5263,7 @@ function macKeychainGet(service = SERVICE) {
5245
5263
  if (!nativeKeychainAllowed()) return null;
5246
5264
  if (process.platform !== "darwin") return null;
5247
5265
  try {
5248
- return execSync2(
5266
+ return execSync3(
5249
5267
  `security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
5250
5268
  { encoding: "utf-8", timeout: 5e3 }
5251
5269
  ).trim();
@@ -5258,13 +5276,13 @@ function macKeychainSet(value, service = SERVICE) {
5258
5276
  if (process.platform !== "darwin") return false;
5259
5277
  try {
5260
5278
  try {
5261
- execSync2(
5279
+ execSync3(
5262
5280
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
5263
5281
  { timeout: 5e3 }
5264
5282
  );
5265
5283
  } catch {
5266
5284
  }
5267
- execSync2(
5285
+ execSync3(
5268
5286
  `security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
5269
5287
  { timeout: 5e3 }
5270
5288
  );
@@ -5277,7 +5295,7 @@ function macKeychainDelete(service = SERVICE) {
5277
5295
  if (!nativeKeychainAllowed()) return false;
5278
5296
  if (process.platform !== "darwin") return false;
5279
5297
  try {
5280
- execSync2(
5298
+ execSync3(
5281
5299
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
5282
5300
  { timeout: 5e3 }
5283
5301
  );
@@ -5289,7 +5307,7 @@ function macKeychainDelete(service = SERVICE) {
5289
5307
  function linuxSecretGet(service = SERVICE) {
5290
5308
  if (!linuxSecretAvailable()) return null;
5291
5309
  try {
5292
- return execSync2(
5310
+ return execSync3(
5293
5311
  `secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
5294
5312
  { encoding: "utf-8", timeout: 5e3 }
5295
5313
  ).trim();
@@ -5300,7 +5318,7 @@ function linuxSecretGet(service = SERVICE) {
5300
5318
  function linuxSecretSet(value, service = SERVICE) {
5301
5319
  if (!linuxSecretAvailable()) return false;
5302
5320
  try {
5303
- execSync2(
5321
+ execSync3(
5304
5322
  `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
5305
5323
  { timeout: 5e3 }
5306
5324
  );
@@ -5313,7 +5331,7 @@ function linuxSecretDelete(service = SERVICE) {
5313
5331
  if (!nativeKeychainAllowed()) return false;
5314
5332
  if (process.platform !== "linux") return false;
5315
5333
  try {
5316
- execSync2(
5334
+ execSync3(
5317
5335
  `secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
5318
5336
  { timeout: 5e3 }
5319
5337
  );
@@ -7211,7 +7229,7 @@ __export(project_name_exports, {
7211
7229
  _resetCache: () => _resetCache,
7212
7230
  getProjectName: () => getProjectName
7213
7231
  });
7214
- import { execSync as execSync3 } from "child_process";
7232
+ import { execSync as execSync4 } from "child_process";
7215
7233
  import path14 from "path";
7216
7234
  function getProjectName(cwd) {
7217
7235
  const dir = cwd ?? process.cwd();
@@ -7219,7 +7237,7 @@ function getProjectName(cwd) {
7219
7237
  try {
7220
7238
  let repoRoot;
7221
7239
  try {
7222
- const gitCommonDir = execSync3("git rev-parse --path-format=absolute --git-common-dir", {
7240
+ const gitCommonDir = execSync4("git rev-parse --path-format=absolute --git-common-dir", {
7223
7241
  cwd: dir,
7224
7242
  encoding: "utf8",
7225
7243
  timeout: 2e3,
@@ -7227,7 +7245,7 @@ function getProjectName(cwd) {
7227
7245
  }).trim();
7228
7246
  repoRoot = path14.dirname(gitCommonDir);
7229
7247
  } catch {
7230
- repoRoot = execSync3("git rev-parse --show-toplevel", {
7248
+ repoRoot = execSync4("git rev-parse --show-toplevel", {
7231
7249
  cwd: dir,
7232
7250
  encoding: "utf8",
7233
7251
  timeout: 2e3,
@@ -7261,14 +7279,14 @@ var file_grep_exports = {};
7261
7279
  __export(file_grep_exports, {
7262
7280
  grepProjectFiles: () => grepProjectFiles
7263
7281
  });
7264
- import { execSync as execSync4 } from "child_process";
7282
+ import { execSync as execSync5 } from "child_process";
7265
7283
  import { readFileSync as readFileSync9, readdirSync as readdirSync2, statSync as statSync6, existsSync as existsSync14 } from "fs";
7266
7284
  import path15 from "path";
7267
7285
  import crypto3 from "crypto";
7268
7286
  function hasRipgrep() {
7269
7287
  if (_hasRg === null) {
7270
7288
  try {
7271
- execSync4("rg --version", { stdio: "ignore", timeout: 2e3 });
7289
+ execSync5("rg --version", { stdio: "ignore", timeout: 2e3 });
7272
7290
  _hasRg = true;
7273
7291
  } catch {
7274
7292
  _hasRg = false;
@@ -7334,7 +7352,7 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
7334
7352
  const globs = (patterns ?? DEFAULT_PATTERNS).map((p) => `--glob '${p}'`).join(" ");
7335
7353
  const excludes = EXCLUDE_DIRS.map((d) => `--glob '!${d}'`).join(" ");
7336
7354
  const cmd = `rg -i -c --hidden --no-config --no-ignore '${pattern.replace(/'/g, "\\'")}' . ${globs} ${excludes} --max-filesize ${MAX_FILE_SIZE} 2>/dev/null || true`;
7337
- const output = execSync4(cmd, {
7355
+ const output = execSync5(cmd, {
7338
7356
  cwd: projectRoot,
7339
7357
  encoding: "utf8",
7340
7358
  timeout: 3e3,
@@ -7349,12 +7367,12 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
7349
7367
  const matchCount = parseInt(line.slice(colonIdx + 1));
7350
7368
  if (isNaN(matchCount) || matchCount === 0) continue;
7351
7369
  try {
7352
- const firstMatch = execSync4(
7370
+ const firstMatch = execSync5(
7353
7371
  `rg -i -n --hidden '${pattern.replace(/'/g, "\\'")}' '${filePath}' --max-count 1 2>/dev/null | head -1`,
7354
7372
  { cwd: projectRoot, encoding: "utf8", timeout: 1e3 }
7355
7373
  ).trim();
7356
7374
  const lineNum = parseInt(firstMatch.split(":")[0] ?? "1");
7357
- const totalLines = execSync4(`wc -l < '${filePath}'`, {
7375
+ const totalLines = execSync5(`wc -l < '${filePath}'`, {
7358
7376
  cwd: projectRoot,
7359
7377
  encoding: "utf8",
7360
7378
  timeout: 1e3
@@ -8705,7 +8723,7 @@ var init_hybrid_search = __esm({
8705
8723
  });
8706
8724
 
8707
8725
  // src/lib/session-key.ts
8708
- import { execSync as execSync5 } from "child_process";
8726
+ import { execSync as execSync6 } from "child_process";
8709
8727
  function normalizeCommand(command) {
8710
8728
  const trimmed = command.trim().toLowerCase();
8711
8729
  const parts = trimmed.split(/[\\/]/);
@@ -8724,7 +8742,7 @@ function resolveRuntimeProcess() {
8724
8742
  let pid = process.ppid;
8725
8743
  for (let i = 0; i < 10; i++) {
8726
8744
  try {
8727
- const info = execSync5(`ps -p ${pid} -o ppid=,comm=`, {
8745
+ const info = execSync6(`ps -p ${pid} -o ppid=,comm=`, {
8728
8746
  encoding: "utf8",
8729
8747
  timeout: 2e3
8730
8748
  }).trim();
@@ -8804,7 +8822,7 @@ __export(active_agent_exports, {
8804
8822
  writeActiveAgent: () => writeActiveAgent
8805
8823
  });
8806
8824
  import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, mkdirSync as mkdirSync4, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
8807
- import { execSync as execSync6 } from "child_process";
8825
+ import { execSync as execSync7 } from "child_process";
8808
8826
  import path16 from "path";
8809
8827
  function isNameWithOptionalInstance(candidate, baseName) {
8810
8828
  if (candidate === baseName) return true;
@@ -8898,7 +8916,7 @@ function getActiveAgent() {
8898
8916
  } catch {
8899
8917
  }
8900
8918
  try {
8901
- const sessionName = execSync6(
8919
+ const sessionName = execSync7(
8902
8920
  "tmux display-message -p '#{session_name}' 2>/dev/null",
8903
8921
  { encoding: "utf8", timeout: 2e3 }
8904
8922
  ).trim();
@@ -11308,7 +11326,7 @@ __export(session_registry_exports, {
11308
11326
  registerSession: () => registerSession
11309
11327
  });
11310
11328
  import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, mkdirSync as mkdirSync6, existsSync as existsSync17 } from "fs";
11311
- import { execSync as execSync7 } from "child_process";
11329
+ import { execSync as execSync8 } from "child_process";
11312
11330
  import path21 from "path";
11313
11331
  import os8 from "os";
11314
11332
  function registerSession(entry) {
@@ -11348,7 +11366,7 @@ function pruneStaleSessions() {
11348
11366
  if (sessions.length === 0) return 0;
11349
11367
  let liveSessions = [];
11350
11368
  try {
11351
- liveSessions = execSync7("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
11369
+ liveSessions = execSync8("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
11352
11370
  encoding: "utf8"
11353
11371
  }).trim().split("\n").filter(Boolean);
11354
11372
  } catch {
@@ -11496,14 +11514,14 @@ var init_transport = __esm({
11496
11514
  });
11497
11515
 
11498
11516
  // src/lib/cc-agent-support.ts
11499
- import { execSync as execSync8 } from "child_process";
11517
+ import { execSync as execSync9 } from "child_process";
11500
11518
  function _resetCcAgentSupportCache() {
11501
11519
  _cachedSupport = null;
11502
11520
  }
11503
11521
  function claudeSupportsAgentFlag() {
11504
11522
  if (_cachedSupport !== null) return _cachedSupport;
11505
11523
  try {
11506
- const helpOutput = execSync8("claude --help 2>&1", {
11524
+ const helpOutput = execSync9("claude --help 2>&1", {
11507
11525
  encoding: "utf-8",
11508
11526
  timeout: 5e3
11509
11527
  });
@@ -12480,7 +12498,7 @@ __export(tmux_routing_exports, {
12480
12498
  spawnEmployee: () => spawnEmployee,
12481
12499
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
12482
12500
  });
12483
- import { execFileSync as execFileSync2, execSync as execSync9 } from "child_process";
12501
+ import { execFileSync as execFileSync2, execSync as execSync10 } from "child_process";
12484
12502
  import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, mkdirSync as mkdirSync9, existsSync as existsSync21, appendFileSync as appendFileSync3, readdirSync as readdirSync5 } from "fs";
12485
12503
  import path25 from "path";
12486
12504
  import os11 from "os";
@@ -13201,7 +13219,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
13201
13219
  let booted = false;
13202
13220
  for (let i = 0; i < 30; i++) {
13203
13221
  try {
13204
- execSync9("sleep 0.5");
13222
+ execSync10("sleep 0.5");
13205
13223
  } catch {
13206
13224
  }
13207
13225
  try {
@@ -13455,7 +13473,7 @@ __export(tasks_crud_exports, {
13455
13473
  import crypto8 from "crypto";
13456
13474
  import path27 from "path";
13457
13475
  import os13 from "os";
13458
- import { execSync as execSync10 } from "child_process";
13476
+ import { execSync as execSync11 } from "child_process";
13459
13477
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
13460
13478
  import { existsSync as existsSync23, readFileSync as readFileSync17 } from "fs";
13461
13479
  async function writeCheckpoint(input) {
@@ -13800,14 +13818,14 @@ function isTmuxSessionAlive(identifier) {
13800
13818
  if (!identifier || identifier === "unknown") return true;
13801
13819
  try {
13802
13820
  if (identifier.startsWith("%")) {
13803
- const output = execSync10("tmux list-panes -a -F '#{pane_id}'", {
13821
+ const output = execSync11("tmux list-panes -a -F '#{pane_id}'", {
13804
13822
  timeout: 2e3,
13805
13823
  encoding: "utf8",
13806
13824
  stdio: ["pipe", "pipe", "pipe"]
13807
13825
  });
13808
13826
  return output.split("\n").some((l) => l.trim() === identifier);
13809
13827
  } else {
13810
- execSync10(`tmux has-session -t ${JSON.stringify(identifier)}`, {
13828
+ execSync11(`tmux has-session -t ${JSON.stringify(identifier)}`, {
13811
13829
  timeout: 2e3,
13812
13830
  stdio: ["pipe", "pipe", "pipe"]
13813
13831
  });
@@ -13816,7 +13834,7 @@ function isTmuxSessionAlive(identifier) {
13816
13834
  } catch {
13817
13835
  if (identifier.startsWith("%")) return true;
13818
13836
  try {
13819
- execSync10("tmux list-sessions", {
13837
+ execSync11("tmux list-sessions", {
13820
13838
  timeout: 2e3,
13821
13839
  stdio: ["pipe", "pipe", "pipe"]
13822
13840
  });
@@ -13831,12 +13849,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
13831
13849
  if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
13832
13850
  try {
13833
13851
  const since = new Date(taskCreatedAt).toISOString();
13834
- const branch = execSync10(
13852
+ const branch = execSync11(
13835
13853
  "git rev-parse --abbrev-ref HEAD 2>/dev/null",
13836
13854
  { encoding: "utf8", timeout: 3e3 }
13837
13855
  ).trim();
13838
13856
  const branchArg = branch && branch !== "HEAD" ? branch : "";
13839
- const commitCount = execSync10(
13857
+ const commitCount = execSync11(
13840
13858
  `git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
13841
13859
  { encoding: "utf8", timeout: 5e3 }
13842
13860
  ).trim();
@@ -20863,13 +20881,13 @@ __export(tmux_status_exports, {
20863
20881
  parseActivity: () => parseActivity,
20864
20882
  parseContextPercentage: () => parseContextPercentage
20865
20883
  });
20866
- import { execSync as execSync11 } from "child_process";
20884
+ import { execSync as execSync12 } from "child_process";
20867
20885
  function inTmux() {
20868
20886
  if (process.env.TMUX || process.env.TMUX_PANE) return true;
20869
20887
  const term = process.env.TERM ?? "";
20870
20888
  if (term.startsWith("tmux") || term.startsWith("screen")) return true;
20871
20889
  try {
20872
- execSync11("tmux display-message -p '#{session_name}' 2>/dev/null", {
20890
+ execSync12("tmux display-message -p '#{session_name}' 2>/dev/null", {
20873
20891
  encoding: "utf8",
20874
20892
  timeout: 2e3
20875
20893
  });
@@ -20879,12 +20897,12 @@ function inTmux() {
20879
20897
  try {
20880
20898
  let pid = process.ppid;
20881
20899
  for (let depth = 0; depth < 8 && pid > 1; depth++) {
20882
- const comm = execSync11(`ps -p ${pid} -o comm= 2>/dev/null`, {
20900
+ const comm = execSync12(`ps -p ${pid} -o comm= 2>/dev/null`, {
20883
20901
  encoding: "utf8",
20884
20902
  timeout: 1e3
20885
20903
  }).trim();
20886
20904
  if (/tmux/.test(comm)) return true;
20887
- const ppid = execSync11(`ps -p ${pid} -o ppid= 2>/dev/null`, {
20905
+ const ppid = execSync12(`ps -p ${pid} -o ppid= 2>/dev/null`, {
20888
20906
  encoding: "utf8",
20889
20907
  timeout: 1e3
20890
20908
  }).trim();
@@ -20897,7 +20915,7 @@ function inTmux() {
20897
20915
  }
20898
20916
  function listTmuxSessions() {
20899
20917
  try {
20900
- const out = execSync11("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
20918
+ const out = execSync12("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
20901
20919
  encoding: "utf8",
20902
20920
  timeout: 3e3
20903
20921
  });
@@ -20908,7 +20926,7 @@ function listTmuxSessions() {
20908
20926
  }
20909
20927
  function capturePaneLines(windowName, lines = 10) {
20910
20928
  try {
20911
- const out = execSync11(
20929
+ const out = execSync12(
20912
20930
  `tmux capture-pane -t ${JSON.stringify(windowName)} -p 2>/dev/null | tail -${lines}`,
20913
20931
  { encoding: "utf8", timeout: 3e3 }
20914
20932
  );
@@ -20919,7 +20937,7 @@ function capturePaneLines(windowName, lines = 10) {
20919
20937
  }
20920
20938
  function getPaneCwd(windowName) {
20921
20939
  try {
20922
- const out = execSync11(
20940
+ const out = execSync12(
20923
20941
  `tmux display-message -t ${JSON.stringify(windowName)} -p '#{pane_current_path}' 2>/dev/null`,
20924
20942
  { encoding: "utf8", timeout: 3e3 }
20925
20943
  );
@@ -20930,7 +20948,7 @@ function getPaneCwd(windowName) {
20930
20948
  }
20931
20949
  function projectFromPath(dir) {
20932
20950
  try {
20933
- const root = execSync11("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
20951
+ const root = execSync12("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
20934
20952
  encoding: "utf8",
20935
20953
  timeout: 3e3
20936
20954
  }).trim();
@@ -20999,7 +21017,7 @@ function getEmployeeStatuses(employeeNames) {
20999
21017
  }
21000
21018
  let paneAlive = true;
21001
21019
  try {
21002
- const paneStatus = execSync11(
21020
+ const paneStatus = execSync12(
21003
21021
  `tmux list-panes -t ${JSON.stringify(sessionName)} -F '#{pane_dead}' 2>/dev/null`,
21004
21022
  { encoding: "utf8", timeout: 3e3 }
21005
21023
  ).trim();
@@ -21245,7 +21263,7 @@ __export(daemon_orchestration_exports, {
21245
21263
  shouldKillSession: () => shouldKillSession,
21246
21264
  shouldNudgeEmployee: () => shouldNudgeEmployee
21247
21265
  });
21248
- import { execSync as execSync12 } from "child_process";
21266
+ import { execSync as execSync13 } from "child_process";
21249
21267
  import { existsSync as existsSync29, readFileSync as readFileSync24, writeFileSync as writeFileSync15 } from "fs";
21250
21268
  import { homedir as homedir5 } from "os";
21251
21269
  import { join as join3 } from "path";
@@ -21563,7 +21581,7 @@ function createSessionTTLRealDeps(getClient2) {
21563
21581
  },
21564
21582
  getSessionCreatedEpoch: (sessionName) => {
21565
21583
  try {
21566
- const out = execSync12(
21584
+ const out = execSync13(
21567
21585
  `tmux display-message -t ${JSON.stringify(sessionName)} -p '#{session_created}' 2>/dev/null`,
21568
21586
  { encoding: "utf8", timeout: 3e3 }
21569
21587
  ).trim();
@@ -21790,7 +21808,7 @@ function reapOrphanedMcpProcesses(deps) {
21790
21808
  function createOrphanReaperRealDeps() {
21791
21809
  return {
21792
21810
  listProcesses: () => {
21793
- const output = execSync12("ps -eo pid,ppid,args", {
21811
+ const output = execSync13("ps -eo pid,ppid,args", {
21794
21812
  encoding: "utf8",
21795
21813
  timeout: 5e3
21796
21814
  });
@@ -26901,7 +26919,7 @@ var init_trigger_engine = __esm({
26901
26919
 
26902
26920
  // src/lib/schedules.ts
26903
26921
  import crypto17 from "crypto";
26904
- import { execSync as execSync13 } from "child_process";
26922
+ import { execSync as execSync14 } from "child_process";
26905
26923
  function isValidCron(cron) {
26906
26924
  const fields = cron.trim().split(/\s+/);
26907
26925
  if (fields.length !== 5) return false;
@@ -27025,7 +27043,7 @@ function addToCrontab(id, cron, prompt, projectDir) {
27025
27043
  const cwd = projectDir ? `cd ${JSON.stringify(projectDir)} && ` : "";
27026
27044
  const escapedPrompt = prompt.replace(/"/g, '\\"');
27027
27045
  const entry = `${cron} ${cwd}claude -p --dangerously-skip-permissions "${escapedPrompt}" # exe-schedule:${id}`;
27028
- execSync13(
27046
+ execSync14(
27029
27047
  `(crontab -l 2>/dev/null; echo ${JSON.stringify(entry)}) | crontab -`,
27030
27048
  { timeout: 5e3, stdio: "ignore" }
27031
27049
  );
@@ -30441,11 +30459,75 @@ function registerSupportTools(server) {
30441
30459
  };
30442
30460
  }
30443
30461
  );
30462
+ server.registerTool(
30463
+ "list_my_bug_reports",
30464
+ {
30465
+ title: "My Bug Reports",
30466
+ description: "List bug reports you've filed, scoped to your license. Shows status (open/triaged/fixed/closed), severity, and fixed_version so you know when to update.",
30467
+ inputSchema: {
30468
+ status: z89.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("all").describe("Filter by status. Default: all"),
30469
+ limit: z89.number().min(1).max(50).default(25).describe("Max results")
30470
+ }
30471
+ },
30472
+ async ({ status: status2, limit }) => {
30473
+ const licenseKey = loadLicense();
30474
+ const licenseToken = readCachedLicenseToken();
30475
+ if (!licenseKey && !licenseToken) {
30476
+ return {
30477
+ content: [{ type: "text", text: "No license key found. Run `exe-os setup` or `exe-os cloud setup` first." }],
30478
+ isError: true
30479
+ };
30480
+ }
30481
+ const endpoint2 = new URL("https://askexe.com/v1/support/my-reports");
30482
+ endpoint2.searchParams.set("status", status2);
30483
+ endpoint2.searchParams.set("limit", String(limit));
30484
+ const headers = { "content-type": "application/json" };
30485
+ if (licenseKey) headers["x-exe-license-key"] = licenseKey;
30486
+ if (licenseToken) headers["x-exe-license-token"] = licenseToken;
30487
+ try {
30488
+ const res = await fetch(endpoint2.toString(), { method: "GET", headers, signal: AbortSignal.timeout(15e3) });
30489
+ if (!res.ok) {
30490
+ const body = await res.text().catch(() => "");
30491
+ return {
30492
+ content: [{ type: "text", text: `Failed to fetch bug reports: HTTP ${res.status}${body ? ` \u2014 ${body}` : ""}` }],
30493
+ isError: true
30494
+ };
30495
+ }
30496
+ const data = await res.json();
30497
+ if (data.count === 0) {
30498
+ return {
30499
+ content: [{ type: "text", text: `No bug reports found${status2 !== "all" ? ` with status '${status2}'` : ""}.` }],
30500
+ structuredContent: { items: [], count: 0 }
30501
+ };
30502
+ }
30503
+ const lines = [`Bug reports (${data.count}):`, ""];
30504
+ for (const r of data.items) {
30505
+ const sevIcon = r.severity === "p0" ? "\u{1F534}" : r.severity === "p1" ? "\u{1F534}" : r.severity === "p2" ? "\u{1F7E0}" : "\u{1F7E2}";
30506
+ const statusIcon = r.status === "fixed" ? "\u2705" : r.status === "closed" ? "\u2611\uFE0F" : r.status === "triaged" ? "\u{1F50D}" : r.status === "wontfix" ? "\u26D4" : "\u{1F535}";
30507
+ lines.push(`${sevIcon} ${r.severity.toUpperCase()} ${statusIcon} ${r.status} \u2014 ${r.title}`);
30508
+ lines.push(` ID: ${r.id} | Filed: ${r.created_at?.slice(0, 10) ?? "?"}`);
30509
+ if (r.fixed_version) lines.push(` \u{1F527} Fixed in: ${r.fixed_version} \u2014 run \`exe-os update\` to get this fix`);
30510
+ if (r.triage_notes) lines.push(` \u{1F4DD} AskExe: ${r.triage_notes}`);
30511
+ lines.push("");
30512
+ }
30513
+ return {
30514
+ content: [{ type: "text", text: lines.join("\n") }],
30515
+ structuredContent: data
30516
+ };
30517
+ } catch (err) {
30518
+ return {
30519
+ content: [{ type: "text", text: `Error fetching bug reports: ${err instanceof Error ? err.message : String(err)}` }],
30520
+ isError: true
30521
+ };
30522
+ }
30523
+ }
30524
+ );
30444
30525
  }
30445
30526
  var init_support = __esm({
30446
30527
  "src/mcp/tools/support.ts"() {
30447
30528
  "use strict";
30448
30529
  init_exe_support();
30530
+ init_license();
30449
30531
  }
30450
30532
  });
30451
30533
 
@@ -30515,7 +30597,7 @@ var init_exe_status = __esm({
30515
30597
  // src/bin/exe-healthcheck.ts
30516
30598
  import { existsSync as existsSync43, readFileSync as readFileSync36, readdirSync as readdirSync14 } from "fs";
30517
30599
  import path55 from "path";
30518
- import { execSync as execSync14 } from "child_process";
30600
+ import { execSync as execSync15 } from "child_process";
30519
30601
  import { fileURLToPath as fileURLToPath6 } from "url";
30520
30602
  function findPackageRoot2() {
30521
30603
  let dir = path55.dirname(fileURLToPath6(import.meta.url));
@@ -30612,7 +30694,7 @@ function checkTaskSystem(pkgRoot) {
30612
30694
  return results;
30613
30695
  }
30614
30696
  try {
30615
- execSync14(`node "${scannerPath}" /tmp/nonexistent-healthcheck-test --format=json 2>/dev/null`, {
30697
+ execSync15(`node "${scannerPath}" /tmp/nonexistent-healthcheck-test --format=json 2>/dev/null`, {
30616
30698
  timeout: 1e4,
30617
30699
  encoding: "utf-8"
30618
30700
  });
@@ -30635,7 +30717,7 @@ function checkWorkerSpawning(pkgRoot) {
30635
30717
  return results;
30636
30718
  }
30637
30719
  try {
30638
- execSync14(`node --check "${workerPath}" 2>&1`, { timeout: 1e4, encoding: "utf-8" });
30720
+ execSync15(`node --check "${workerPath}" 2>&1`, { timeout: 1e4, encoding: "utf-8" });
30639
30721
  results.push({ name: "workers/ingest-worker", pass: true, detail: "ingest-worker.js parses OK" });
30640
30722
  } catch (err) {
30641
30723
  results.push({
@@ -30651,7 +30733,7 @@ function checkWorkerSpawning(pkgRoot) {
30651
30733
  const hooksFailed = [];
30652
30734
  for (const hook of hookFiles) {
30653
30735
  try {
30654
- execSync14(`node --check "${path55.join(hooksDir, hook)}" 2>&1`, { timeout: 1e4, encoding: "utf-8" });
30736
+ execSync15(`node --check "${path55.join(hooksDir, hook)}" 2>&1`, { timeout: 1e4, encoding: "utf-8" });
30655
30737
  hooksPassed++;
30656
30738
  } catch {
30657
30739
  hooksFailed.push(hook);
@@ -30693,7 +30775,7 @@ function checkMcpTransport() {
30693
30775
  if (daemonAlive && existsSync43(tokenPath)) {
30694
30776
  try {
30695
30777
  const token = readFileSync36(tokenPath, "utf8").trim();
30696
- const response = execSync14(
30778
+ const response = execSync15(
30697
30779
  `curl -sS -i -m 2 -H "Authorization: Bearer ${token}" -H 'Accept: application/json, text/event-stream' http://127.0.0.1:48739/mcp`,
30698
30780
  { encoding: "utf8", timeout: 3e3 }
30699
30781
  );
@@ -30744,7 +30826,7 @@ function checkClaudeCodeInstall() {
30744
30826
  });
30745
30827
  }
30746
30828
  try {
30747
- const claudePath = execSync14("which claude 2>/dev/null || true", { encoding: "utf8", timeout: 5e3 }).trim();
30829
+ const claudePath = execSync15("which claude 2>/dev/null || true", { encoding: "utf8", timeout: 5e3 }).trim();
30748
30830
  if (!claudePath) {
30749
30831
  results.push({
30750
30832
  name: "cc/cli-binary",
@@ -30754,7 +30836,7 @@ function checkClaudeCodeInstall() {
30754
30836
  } else {
30755
30837
  let resolved = claudePath;
30756
30838
  try {
30757
- resolved = execSync14(`readlink -f "${claudePath}" 2>/dev/null || readlink "${claudePath}" 2>/dev/null || echo "${claudePath}"`, {
30839
+ resolved = execSync15(`readlink -f "${claudePath}" 2>/dev/null || readlink "${claudePath}" 2>/dev/null || echo "${claudePath}"`, {
30758
30840
  encoding: "utf8",
30759
30841
  timeout: 5e3
30760
30842
  }).trim();
@@ -30838,7 +30920,7 @@ function checkClaudeCodeInstall() {
30838
30920
  });
30839
30921
  }
30840
30922
  try {
30841
- const ccVersion = execSync14("claude --version 2>/dev/null || echo unknown", {
30923
+ const ccVersion = execSync15("claude --version 2>/dev/null || echo unknown", {
30842
30924
  encoding: "utf8",
30843
30925
  timeout: 5e3
30844
30926
  }).trim();
@@ -30900,7 +30982,7 @@ __export(update_check_exports, {
30900
30982
  getLocalVersion: () => getLocalVersion,
30901
30983
  getRemoteVersion: () => getRemoteVersion
30902
30984
  });
30903
- import { execSync as execSync15 } from "child_process";
30985
+ import { execSync as execSync16 } from "child_process";
30904
30986
  import { readFileSync as readFileSync37 } from "fs";
30905
30987
  import path56 from "path";
30906
30988
  function getLocalVersion(packageRoot) {
@@ -30910,7 +30992,7 @@ function getLocalVersion(packageRoot) {
30910
30992
  }
30911
30993
  function getRemoteVersion() {
30912
30994
  try {
30913
- const output = execSync15("npm view @askexenow/exe-os version", {
30995
+ const output = execSync16("npm view @askexenow/exe-os version", {
30914
30996
  encoding: "utf-8",
30915
30997
  timeout: 15e3,
30916
30998
  stdio: ["pipe", "pipe", "pipe"]
@@ -32383,7 +32465,7 @@ __export(review_polling_exports, {
32383
32465
  createRealDeps: () => createRealDeps,
32384
32466
  pollPendingReviews: () => pollPendingReviews
32385
32467
  });
32386
- import { execSync as execSync16 } from "child_process";
32468
+ import { execSync as execSync17 } from "child_process";
32387
32469
  async function pollPendingReviews(deps, _state) {
32388
32470
  let sessions;
32389
32471
  try {
@@ -32490,7 +32572,7 @@ async function pollPendingReviews(deps, _state) {
32490
32572
  function createRealDeps(getClient2) {
32491
32573
  return {
32492
32574
  listTmuxSessions: () => {
32493
- return execSync16("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
32575
+ return execSync17("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
32494
32576
  encoding: "utf8",
32495
32577
  timeout: 3e3
32496
32578
  }).trim().split("\n").filter(Boolean);
@@ -34983,6 +35065,23 @@ function checkExistingDaemon() {
34983
35065
  return false;
34984
35066
  }
34985
35067
  process.kill(pid, 0);
35068
+ try {
35069
+ const state = __require("child_process").execSync(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
35070
+ if (state.startsWith("Z")) {
35071
+ process.stderr.write(`[exed] PID ${pid} is a zombie \u2014 cleaning up and proceeding.
35072
+ `);
35073
+ try {
35074
+ unlinkSync15(PID_PATH4);
35075
+ } catch {
35076
+ }
35077
+ try {
35078
+ unlinkSync15(SOCKET_PATH2);
35079
+ } catch {
35080
+ }
35081
+ return false;
35082
+ }
35083
+ } catch {
35084
+ }
34986
35085
  process.stderr.write(`[exed] Another daemon is already running (PID ${pid}). Exiting.
34987
35086
  `);
34988
35087
  return true;
@@ -35018,8 +35117,8 @@ function startAutoUpdateCheck() {
35018
35117
  );
35019
35118
  if (autoInstall) {
35020
35119
  process.stderr.write("[exed] Auto-installing update...\n");
35021
- const { execSync: execSync17 } = await import("child_process");
35022
- execSync17("npm install -g @askexenow/exe-os@latest", {
35120
+ const { execSync: execSync18 } = await import("child_process");
35121
+ execSync18("npm install -g @askexenow/exe-os@latest", {
35023
35122
  timeout: 12e4,
35024
35123
  stdio: ["pipe", "pipe", "pipe"]
35025
35124
  });