@askexenow/exe-os 0.9.85 → 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 (80) 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 +152 -77
  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 +40 -22
  21. package/dist/bin/exe-pending-messages.js +35 -17
  22. package/dist/bin/exe-pending-notifications.js +35 -17
  23. package/dist/bin/exe-pending-reviews.js +37 -19
  24. package/dist/bin/exe-rename.js +34 -16
  25. package/dist/bin/exe-review.js +32 -14
  26. package/dist/bin/exe-search.js +40 -22
  27. package/dist/bin/exe-session-cleanup.js +67 -44
  28. package/dist/bin/exe-start-codex.js +39 -21
  29. package/dist/bin/exe-start-opencode.js +37 -19
  30. package/dist/bin/exe-status.js +44 -26
  31. package/dist/bin/exe-team.js +32 -14
  32. package/dist/bin/git-sweep.js +45 -27
  33. package/dist/bin/graph-backfill.js +32 -14
  34. package/dist/bin/graph-export.js +32 -14
  35. package/dist/bin/intercom-check.js +49 -31
  36. package/dist/bin/scan-tasks.js +45 -27
  37. package/dist/bin/setup.js +29 -11
  38. package/dist/bin/shard-migrate.js +32 -14
  39. package/dist/bin/stack-update.js +59 -2
  40. package/dist/bin/update.js +1 -1
  41. package/dist/gateway/index.js +47 -29
  42. package/dist/hooks/bug-report-worker.js +47 -29
  43. package/dist/hooks/codex-stop-task-finalizer.js +41 -23
  44. package/dist/hooks/commit-complete.js +46 -28
  45. package/dist/hooks/error-recall.js +44 -26
  46. package/dist/hooks/ingest-worker.js +4 -4
  47. package/dist/hooks/ingest.js +38 -20
  48. package/dist/hooks/instructions-loaded.js +32 -14
  49. package/dist/hooks/notification.js +32 -14
  50. package/dist/hooks/post-compact.js +32 -14
  51. package/dist/hooks/post-tool-combined.js +45 -27
  52. package/dist/hooks/pre-compact.js +43 -25
  53. package/dist/hooks/pre-tool-use.js +40 -22
  54. package/dist/hooks/prompt-submit.js +60 -42
  55. package/dist/hooks/session-end.js +48 -30
  56. package/dist/hooks/session-start.js +50 -32
  57. package/dist/hooks/stop.js +35 -17
  58. package/dist/hooks/subagent-stop.js +32 -14
  59. package/dist/hooks/summary-worker.js +37 -19
  60. package/dist/index.js +43 -25
  61. package/dist/lib/cloud-sync.js +32 -14
  62. package/dist/lib/database.js +22 -4
  63. package/dist/lib/db-daemon-client.js +16 -4
  64. package/dist/lib/db.js +22 -4
  65. package/dist/lib/device-registry.js +22 -4
  66. package/dist/lib/embedder.js +16 -4
  67. package/dist/lib/exe-daemon-client.js +16 -4
  68. package/dist/lib/exe-daemon.js +165 -66
  69. package/dist/lib/hybrid-search.js +40 -22
  70. package/dist/lib/schedules.js +35 -17
  71. package/dist/lib/skill-learning.js +16 -4
  72. package/dist/lib/store.js +32 -14
  73. package/dist/lib/tasks.js +16 -4
  74. package/dist/lib/tmux-routing.js +18 -6
  75. package/dist/mcp/server.js +142 -60
  76. package/dist/mcp/tools/create-task.js +18 -6
  77. package/dist/mcp/tools/update-task.js +18 -6
  78. package/dist/runtime/index.js +43 -25
  79. package/dist/tui/App.js +73 -55
  80. package/package.json +1 -1
@@ -390,7 +390,7 @@ __export(exe_daemon_client_exports, {
390
390
  });
391
391
  import net from "net";
392
392
  import os2 from "os";
393
- import { spawn } from "child_process";
393
+ import { spawn, execSync } from "child_process";
394
394
  import { randomUUID } from "crypto";
395
395
  import { existsSync as existsSync4, unlinkSync, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
396
396
  import path3 from "path";
@@ -420,6 +420,14 @@ function handleData(chunk) {
420
420
  }
421
421
  }
422
422
  }
423
+ function isZombie(pid) {
424
+ try {
425
+ const state = execSync(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
426
+ return state.startsWith("Z");
427
+ } catch {
428
+ return false;
429
+ }
430
+ }
423
431
  function cleanupStaleFiles() {
424
432
  if (existsSync4(PID_PATH)) {
425
433
  try {
@@ -427,7 +435,11 @@ function cleanupStaleFiles() {
427
435
  if (pid > 0) {
428
436
  try {
429
437
  process.kill(pid, 0);
430
- return;
438
+ if (!isZombie(pid)) {
439
+ return;
440
+ }
441
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
442
+ `);
431
443
  } catch {
432
444
  }
433
445
  }
@@ -455,8 +467,8 @@ function findPackageRoot() {
455
467
  function getAvailableMemoryGB() {
456
468
  if (process.platform === "darwin") {
457
469
  try {
458
- const { execSync: execSync15 } = __require("child_process");
459
- const vmstat = execSync15("vm_stat", { encoding: "utf8" });
470
+ const { execSync: execSync16 } = __require("child_process");
471
+ const vmstat = execSync16("vm_stat", { encoding: "utf8" });
460
472
  const pageSize = 16384;
461
473
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
462
474
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -1107,7 +1119,7 @@ __export(employees_exports, {
1107
1119
  });
1108
1120
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
1109
1121
  import { existsSync as existsSync6, symlinkSync, readlinkSync, readFileSync as readFileSync5, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "fs";
1110
- import { execSync } from "child_process";
1122
+ import { execSync as execSync2 } from "child_process";
1111
1123
  import path5 from "path";
1112
1124
  import os3 from "os";
1113
1125
  function normalizeRole(role) {
@@ -1283,7 +1295,7 @@ async function normalizeRosterCase(rosterPath) {
1283
1295
  }
1284
1296
  function findExeBin() {
1285
1297
  try {
1286
- return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
1298
+ return execSync2(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
1287
1299
  } catch {
1288
1300
  return null;
1289
1301
  }
@@ -3526,6 +3538,12 @@ async function disposeDatabase() {
3526
3538
  clearInterval(_walCheckpointTimer);
3527
3539
  _walCheckpointTimer = null;
3528
3540
  }
3541
+ if (_client) {
3542
+ try {
3543
+ await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
3544
+ } catch {
3545
+ }
3546
+ }
3529
3547
  if (_daemonClient) {
3530
3548
  _daemonClient.close();
3531
3549
  _daemonClient = null;
@@ -3571,7 +3589,7 @@ __export(keychain_exports, {
3571
3589
  });
3572
3590
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3573
3591
  import { existsSync as existsSync7, statSync as statSync2 } from "fs";
3574
- import { execSync as execSync2 } from "child_process";
3592
+ import { execSync as execSync3 } from "child_process";
3575
3593
  import path7 from "path";
3576
3594
  import os5 from "os";
3577
3595
  function getKeyDir() {
@@ -3588,13 +3606,13 @@ function linuxSecretAvailable() {
3588
3606
  if (process.platform !== "linux") return false;
3589
3607
  if (linuxSecretAvailability !== null) return linuxSecretAvailability;
3590
3608
  try {
3591
- execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
3609
+ execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
3592
3610
  } catch {
3593
3611
  linuxSecretAvailability = false;
3594
3612
  return false;
3595
3613
  }
3596
3614
  try {
3597
- execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
3615
+ execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
3598
3616
  linuxSecretAvailability = true;
3599
3617
  } catch {
3600
3618
  linuxSecretAvailability = false;
@@ -3618,7 +3636,7 @@ function macKeychainGet(service = SERVICE) {
3618
3636
  if (!nativeKeychainAllowed()) return null;
3619
3637
  if (process.platform !== "darwin") return null;
3620
3638
  try {
3621
- return execSync2(
3639
+ return execSync3(
3622
3640
  `security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
3623
3641
  { encoding: "utf-8", timeout: 5e3 }
3624
3642
  ).trim();
@@ -3631,13 +3649,13 @@ function macKeychainSet(value, service = SERVICE) {
3631
3649
  if (process.platform !== "darwin") return false;
3632
3650
  try {
3633
3651
  try {
3634
- execSync2(
3652
+ execSync3(
3635
3653
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
3636
3654
  { timeout: 5e3 }
3637
3655
  );
3638
3656
  } catch {
3639
3657
  }
3640
- execSync2(
3658
+ execSync3(
3641
3659
  `security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
3642
3660
  { timeout: 5e3 }
3643
3661
  );
@@ -3650,7 +3668,7 @@ function macKeychainDelete(service = SERVICE) {
3650
3668
  if (!nativeKeychainAllowed()) return false;
3651
3669
  if (process.platform !== "darwin") return false;
3652
3670
  try {
3653
- execSync2(
3671
+ execSync3(
3654
3672
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
3655
3673
  { timeout: 5e3 }
3656
3674
  );
@@ -3662,7 +3680,7 @@ function macKeychainDelete(service = SERVICE) {
3662
3680
  function linuxSecretGet(service = SERVICE) {
3663
3681
  if (!linuxSecretAvailable()) return null;
3664
3682
  try {
3665
- return execSync2(
3683
+ return execSync3(
3666
3684
  `secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3667
3685
  { encoding: "utf-8", timeout: 5e3 }
3668
3686
  ).trim();
@@ -3673,7 +3691,7 @@ function linuxSecretGet(service = SERVICE) {
3673
3691
  function linuxSecretSet(value, service = SERVICE) {
3674
3692
  if (!linuxSecretAvailable()) return false;
3675
3693
  try {
3676
- execSync2(
3694
+ execSync3(
3677
3695
  `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3678
3696
  { timeout: 5e3 }
3679
3697
  );
@@ -3686,7 +3704,7 @@ function linuxSecretDelete(service = SERVICE) {
3686
3704
  if (!nativeKeychainAllowed()) return false;
3687
3705
  if (process.platform !== "linux") return false;
3688
3706
  try {
3689
- execSync2(
3707
+ execSync3(
3690
3708
  `secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3691
3709
  { timeout: 5e3 }
3692
3710
  );
@@ -6246,7 +6264,7 @@ __export(project_name_exports, {
6246
6264
  _resetCache: () => _resetCache,
6247
6265
  getProjectName: () => getProjectName
6248
6266
  });
6249
- import { execSync as execSync3 } from "child_process";
6267
+ import { execSync as execSync4 } from "child_process";
6250
6268
  import path10 from "path";
6251
6269
  function getProjectName(cwd) {
6252
6270
  const dir = cwd ?? process.cwd();
@@ -6254,7 +6272,7 @@ function getProjectName(cwd) {
6254
6272
  try {
6255
6273
  let repoRoot;
6256
6274
  try {
6257
- const gitCommonDir = execSync3("git rev-parse --path-format=absolute --git-common-dir", {
6275
+ const gitCommonDir = execSync4("git rev-parse --path-format=absolute --git-common-dir", {
6258
6276
  cwd: dir,
6259
6277
  encoding: "utf8",
6260
6278
  timeout: 2e3,
@@ -6262,7 +6280,7 @@ function getProjectName(cwd) {
6262
6280
  }).trim();
6263
6281
  repoRoot = path10.dirname(gitCommonDir);
6264
6282
  } catch {
6265
- repoRoot = execSync3("git rev-parse --show-toplevel", {
6283
+ repoRoot = execSync4("git rev-parse --show-toplevel", {
6266
6284
  cwd: dir,
6267
6285
  encoding: "utf8",
6268
6286
  timeout: 2e3,
@@ -6296,14 +6314,14 @@ var file_grep_exports = {};
6296
6314
  __export(file_grep_exports, {
6297
6315
  grepProjectFiles: () => grepProjectFiles
6298
6316
  });
6299
- import { execSync as execSync4 } from "child_process";
6317
+ import { execSync as execSync5 } from "child_process";
6300
6318
  import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync4, existsSync as existsSync10 } from "fs";
6301
6319
  import path11 from "path";
6302
6320
  import crypto2 from "crypto";
6303
6321
  function hasRipgrep() {
6304
6322
  if (_hasRg === null) {
6305
6323
  try {
6306
- execSync4("rg --version", { stdio: "ignore", timeout: 2e3 });
6324
+ execSync5("rg --version", { stdio: "ignore", timeout: 2e3 });
6307
6325
  _hasRg = true;
6308
6326
  } catch {
6309
6327
  _hasRg = false;
@@ -6369,7 +6387,7 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
6369
6387
  const globs = (patterns ?? DEFAULT_PATTERNS).map((p) => `--glob '${p}'`).join(" ");
6370
6388
  const excludes = EXCLUDE_DIRS.map((d) => `--glob '!${d}'`).join(" ");
6371
6389
  const cmd = `rg -i -c --hidden --no-config --no-ignore '${pattern.replace(/'/g, "\\'")}' . ${globs} ${excludes} --max-filesize ${MAX_FILE_SIZE} 2>/dev/null || true`;
6372
- const output = execSync4(cmd, {
6390
+ const output = execSync5(cmd, {
6373
6391
  cwd: projectRoot,
6374
6392
  encoding: "utf8",
6375
6393
  timeout: 3e3,
@@ -6384,12 +6402,12 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
6384
6402
  const matchCount = parseInt(line.slice(colonIdx + 1));
6385
6403
  if (isNaN(matchCount) || matchCount === 0) continue;
6386
6404
  try {
6387
- const firstMatch = execSync4(
6405
+ const firstMatch = execSync5(
6388
6406
  `rg -i -n --hidden '${pattern.replace(/'/g, "\\'")}' '${filePath}' --max-count 1 2>/dev/null | head -1`,
6389
6407
  { cwd: projectRoot, encoding: "utf8", timeout: 1e3 }
6390
6408
  ).trim();
6391
6409
  const lineNum = parseInt(firstMatch.split(":")[0] ?? "1");
6392
- const totalLines = execSync4(`wc -l < '${filePath}'`, {
6410
+ const totalLines = execSync5(`wc -l < '${filePath}'`, {
6393
6411
  cwd: projectRoot,
6394
6412
  encoding: "utf8",
6395
6413
  timeout: 1e3
@@ -7740,7 +7758,7 @@ var init_hybrid_search = __esm({
7740
7758
  });
7741
7759
 
7742
7760
  // src/lib/session-key.ts
7743
- import { execSync as execSync5 } from "child_process";
7761
+ import { execSync as execSync6 } from "child_process";
7744
7762
  function normalizeCommand(command) {
7745
7763
  const trimmed = command.trim().toLowerCase();
7746
7764
  const parts = trimmed.split(/[\\/]/);
@@ -7759,7 +7777,7 @@ function resolveRuntimeProcess() {
7759
7777
  let pid = process.ppid;
7760
7778
  for (let i = 0; i < 10; i++) {
7761
7779
  try {
7762
- const info = execSync5(`ps -p ${pid} -o ppid=,comm=`, {
7780
+ const info = execSync6(`ps -p ${pid} -o ppid=,comm=`, {
7763
7781
  encoding: "utf8",
7764
7782
  timeout: 2e3
7765
7783
  }).trim();
@@ -7831,7 +7849,7 @@ __export(active_agent_exports, {
7831
7849
  writeActiveAgent: () => writeActiveAgent
7832
7850
  });
7833
7851
  import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, unlinkSync as unlinkSync3, readdirSync as readdirSync3 } from "fs";
7834
- import { execSync as execSync6 } from "child_process";
7852
+ import { execSync as execSync7 } from "child_process";
7835
7853
  import path12 from "path";
7836
7854
  function isNameWithOptionalInstance(candidate, baseName) {
7837
7855
  if (candidate === baseName) return true;
@@ -7925,7 +7943,7 @@ function getActiveAgent() {
7925
7943
  } catch {
7926
7944
  }
7927
7945
  try {
7928
- const sessionName = execSync6(
7946
+ const sessionName = execSync7(
7929
7947
  "tmux display-message -p '#{session_name}' 2>/dev/null",
7930
7948
  { encoding: "utf8", timeout: 2e3 }
7931
7949
  ).trim();
@@ -9291,14 +9309,14 @@ var init_transport = __esm({
9291
9309
  });
9292
9310
 
9293
9311
  // src/lib/cc-agent-support.ts
9294
- import { execSync as execSync7 } from "child_process";
9312
+ import { execSync as execSync8 } from "child_process";
9295
9313
  function _resetCcAgentSupportCache() {
9296
9314
  _cachedSupport = null;
9297
9315
  }
9298
9316
  function claudeSupportsAgentFlag() {
9299
9317
  if (_cachedSupport !== null) return _cachedSupport;
9300
9318
  try {
9301
- const helpOutput = execSync7("claude --help 2>&1", {
9319
+ const helpOutput = execSync8("claude --help 2>&1", {
9302
9320
  encoding: "utf-8",
9303
9321
  timeout: 5e3
9304
9322
  });
@@ -10235,7 +10253,7 @@ __export(tmux_routing_exports, {
10235
10253
  spawnEmployee: () => spawnEmployee,
10236
10254
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
10237
10255
  });
10238
- import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
10256
+ import { execFileSync as execFileSync2, execSync as execSync9 } from "child_process";
10239
10257
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync10, mkdirSync as mkdirSync8, existsSync as existsSync17, appendFileSync, readdirSync as readdirSync5 } from "fs";
10240
10258
  import path21 from "path";
10241
10259
  import os10 from "os";
@@ -10956,7 +10974,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
10956
10974
  let booted = false;
10957
10975
  for (let i = 0; i < 30; i++) {
10958
10976
  try {
10959
- execSync8("sleep 0.5");
10977
+ execSync9("sleep 0.5");
10960
10978
  } catch {
10961
10979
  }
10962
10980
  try {
@@ -11204,7 +11222,7 @@ __export(tasks_crud_exports, {
11204
11222
  import crypto7 from "crypto";
11205
11223
  import path23 from "path";
11206
11224
  import os12 from "os";
11207
- import { execSync as execSync9 } from "child_process";
11225
+ import { execSync as execSync10 } from "child_process";
11208
11226
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
11209
11227
  import { existsSync as existsSync19, readFileSync as readFileSync14 } from "fs";
11210
11228
  async function writeCheckpoint(input) {
@@ -11549,14 +11567,14 @@ function isTmuxSessionAlive(identifier) {
11549
11567
  if (!identifier || identifier === "unknown") return true;
11550
11568
  try {
11551
11569
  if (identifier.startsWith("%")) {
11552
- const output = execSync9("tmux list-panes -a -F '#{pane_id}'", {
11570
+ const output = execSync10("tmux list-panes -a -F '#{pane_id}'", {
11553
11571
  timeout: 2e3,
11554
11572
  encoding: "utf8",
11555
11573
  stdio: ["pipe", "pipe", "pipe"]
11556
11574
  });
11557
11575
  return output.split("\n").some((l) => l.trim() === identifier);
11558
11576
  } else {
11559
- execSync9(`tmux has-session -t ${JSON.stringify(identifier)}`, {
11577
+ execSync10(`tmux has-session -t ${JSON.stringify(identifier)}`, {
11560
11578
  timeout: 2e3,
11561
11579
  stdio: ["pipe", "pipe", "pipe"]
11562
11580
  });
@@ -11565,7 +11583,7 @@ function isTmuxSessionAlive(identifier) {
11565
11583
  } catch {
11566
11584
  if (identifier.startsWith("%")) return true;
11567
11585
  try {
11568
- execSync9("tmux list-sessions", {
11586
+ execSync10("tmux list-sessions", {
11569
11587
  timeout: 2e3,
11570
11588
  stdio: ["pipe", "pipe", "pipe"]
11571
11589
  });
@@ -11580,12 +11598,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
11580
11598
  if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
11581
11599
  try {
11582
11600
  const since = new Date(taskCreatedAt).toISOString();
11583
- const branch = execSync9(
11601
+ const branch = execSync10(
11584
11602
  "git rev-parse --abbrev-ref HEAD 2>/dev/null",
11585
11603
  { encoding: "utf8", timeout: 3e3 }
11586
11604
  ).trim();
11587
11605
  const branchArg = branch && branch !== "HEAD" ? branch : "";
11588
- const commitCount = execSync9(
11606
+ const commitCount = execSync10(
11589
11607
  `git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
11590
11608
  { encoding: "utf8", timeout: 5e3 }
11591
11609
  ).trim();
@@ -13957,13 +13975,13 @@ var init_crdt_sync = __esm({
13957
13975
  });
13958
13976
 
13959
13977
  // src/lib/tmux-status.ts
13960
- import { execSync as execSync12 } from "child_process";
13978
+ import { execSync as execSync13 } from "child_process";
13961
13979
  function inTmux() {
13962
13980
  if (process.env.TMUX || process.env.TMUX_PANE) return true;
13963
13981
  const term = process.env.TERM ?? "";
13964
13982
  if (term.startsWith("tmux") || term.startsWith("screen")) return true;
13965
13983
  try {
13966
- execSync12("tmux display-message -p '#{session_name}' 2>/dev/null", {
13984
+ execSync13("tmux display-message -p '#{session_name}' 2>/dev/null", {
13967
13985
  encoding: "utf8",
13968
13986
  timeout: 2e3
13969
13987
  });
@@ -13973,12 +13991,12 @@ function inTmux() {
13973
13991
  try {
13974
13992
  let pid = process.ppid;
13975
13993
  for (let depth = 0; depth < 8 && pid > 1; depth++) {
13976
- const comm = execSync12(`ps -p ${pid} -o comm= 2>/dev/null`, {
13994
+ const comm = execSync13(`ps -p ${pid} -o comm= 2>/dev/null`, {
13977
13995
  encoding: "utf8",
13978
13996
  timeout: 1e3
13979
13997
  }).trim();
13980
13998
  if (/tmux/.test(comm)) return true;
13981
- const ppid = execSync12(`ps -p ${pid} -o ppid= 2>/dev/null`, {
13999
+ const ppid = execSync13(`ps -p ${pid} -o ppid= 2>/dev/null`, {
13982
14000
  encoding: "utf8",
13983
14001
  timeout: 1e3
13984
14002
  }).trim();
@@ -13991,7 +14009,7 @@ function inTmux() {
13991
14009
  }
13992
14010
  function listTmuxSessions() {
13993
14011
  try {
13994
- const out = execSync12("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
14012
+ const out = execSync13("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
13995
14013
  encoding: "utf8",
13996
14014
  timeout: 3e3
13997
14015
  });
@@ -14002,7 +14020,7 @@ function listTmuxSessions() {
14002
14020
  }
14003
14021
  function capturePaneLines(windowName, lines = 10) {
14004
14022
  try {
14005
- const out = execSync12(
14023
+ const out = execSync13(
14006
14024
  `tmux capture-pane -t ${JSON.stringify(windowName)} -p 2>/dev/null | tail -${lines}`,
14007
14025
  { encoding: "utf8", timeout: 3e3 }
14008
14026
  );
@@ -14013,7 +14031,7 @@ function capturePaneLines(windowName, lines = 10) {
14013
14031
  }
14014
14032
  function getPaneCwd(windowName) {
14015
14033
  try {
14016
- const out = execSync12(
14034
+ const out = execSync13(
14017
14035
  `tmux display-message -t ${JSON.stringify(windowName)} -p '#{pane_current_path}' 2>/dev/null`,
14018
14036
  { encoding: "utf8", timeout: 3e3 }
14019
14037
  );
@@ -14024,7 +14042,7 @@ function getPaneCwd(windowName) {
14024
14042
  }
14025
14043
  function projectFromPath(dir) {
14026
14044
  try {
14027
- const root = execSync12("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
14045
+ const root = execSync13("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
14028
14046
  encoding: "utf8",
14029
14047
  timeout: 3e3
14030
14048
  }).trim();
@@ -14083,7 +14101,7 @@ function getEmployeeStatuses(employeeNames) {
14083
14101
  }
14084
14102
  let paneAlive = true;
14085
14103
  try {
14086
- const paneStatus = execSync12(
14104
+ const paneStatus = execSync13(
14087
14105
  `tmux list-panes -t ${JSON.stringify(sessionName)} -F '#{pane_dead}' 2>/dev/null`,
14088
14106
  { encoding: "utf8", timeout: 3e3 }
14089
14107
  ).trim();
@@ -19953,7 +19971,7 @@ import { z as z55 } from "zod";
19953
19971
  init_tmux_routing();
19954
19972
  init_task_scope();
19955
19973
  init_employees();
19956
- import { execSync as execSync10 } from "child_process";
19974
+ import { execSync as execSync11 } from "child_process";
19957
19975
  import { existsSync as existsSync25, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "fs";
19958
19976
  import { homedir as homedir5 } from "os";
19959
19977
  import { join as join3 } from "path";
@@ -24288,7 +24306,7 @@ function isScheduledTrigger(trigger) {
24288
24306
  init_database();
24289
24307
  init_store();
24290
24308
  import crypto16 from "crypto";
24291
- import { execSync as execSync11 } from "child_process";
24309
+ import { execSync as execSync12 } from "child_process";
24292
24310
  var CRON_FIELD = /^[\d*/,\-]+$/;
24293
24311
  function isValidCron(cron) {
24294
24312
  const fields = cron.trim().split(/\s+/);
@@ -24414,7 +24432,7 @@ function addToCrontab(id, cron, prompt, projectDir) {
24414
24432
  const cwd = projectDir ? `cd ${JSON.stringify(projectDir)} && ` : "";
24415
24433
  const escapedPrompt = prompt.replace(/"/g, '\\"');
24416
24434
  const entry = `${cron} ${cwd}claude -p --dangerously-skip-permissions "${escapedPrompt}" # exe-schedule:${id}`;
24417
- execSync11(
24435
+ execSync12(
24418
24436
  `(crontab -l 2>/dev/null; echo ${JSON.stringify(entry)}) | crontab -`,
24419
24437
  { timeout: 5e3, stdio: "ignore" }
24420
24438
  );
@@ -27573,6 +27591,7 @@ function nextForPostFailure(status2) {
27573
27591
  }
27574
27592
 
27575
27593
  // src/mcp/tools/support.ts
27594
+ init_license();
27576
27595
  function formatRows(rows, mode) {
27577
27596
  const lines = [`exe-os support ${mode}`, ""];
27578
27597
  for (const row of rows) {
@@ -27625,6 +27644,69 @@ function registerSupportTools(server2) {
27625
27644
  };
27626
27645
  }
27627
27646
  );
27647
+ server2.registerTool(
27648
+ "list_my_bug_reports",
27649
+ {
27650
+ title: "My Bug Reports",
27651
+ 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.",
27652
+ inputSchema: {
27653
+ status: z89.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("all").describe("Filter by status. Default: all"),
27654
+ limit: z89.number().min(1).max(50).default(25).describe("Max results")
27655
+ }
27656
+ },
27657
+ async ({ status: status2, limit }) => {
27658
+ const licenseKey = loadLicense();
27659
+ const licenseToken = readCachedLicenseToken();
27660
+ if (!licenseKey && !licenseToken) {
27661
+ return {
27662
+ content: [{ type: "text", text: "No license key found. Run `exe-os setup` or `exe-os cloud setup` first." }],
27663
+ isError: true
27664
+ };
27665
+ }
27666
+ const endpoint2 = new URL("https://askexe.com/v1/support/my-reports");
27667
+ endpoint2.searchParams.set("status", status2);
27668
+ endpoint2.searchParams.set("limit", String(limit));
27669
+ const headers = { "content-type": "application/json" };
27670
+ if (licenseKey) headers["x-exe-license-key"] = licenseKey;
27671
+ if (licenseToken) headers["x-exe-license-token"] = licenseToken;
27672
+ try {
27673
+ const res = await fetch(endpoint2.toString(), { method: "GET", headers, signal: AbortSignal.timeout(15e3) });
27674
+ if (!res.ok) {
27675
+ const body = await res.text().catch(() => "");
27676
+ return {
27677
+ content: [{ type: "text", text: `Failed to fetch bug reports: HTTP ${res.status}${body ? ` \u2014 ${body}` : ""}` }],
27678
+ isError: true
27679
+ };
27680
+ }
27681
+ const data = await res.json();
27682
+ if (data.count === 0) {
27683
+ return {
27684
+ content: [{ type: "text", text: `No bug reports found${status2 !== "all" ? ` with status '${status2}'` : ""}.` }],
27685
+ structuredContent: { items: [], count: 0 }
27686
+ };
27687
+ }
27688
+ const lines = [`Bug reports (${data.count}):`, ""];
27689
+ for (const r of data.items) {
27690
+ const sevIcon = r.severity === "p0" ? "\u{1F534}" : r.severity === "p1" ? "\u{1F534}" : r.severity === "p2" ? "\u{1F7E0}" : "\u{1F7E2}";
27691
+ const statusIcon = r.status === "fixed" ? "\u2705" : r.status === "closed" ? "\u2611\uFE0F" : r.status === "triaged" ? "\u{1F50D}" : r.status === "wontfix" ? "\u26D4" : "\u{1F535}";
27692
+ lines.push(`${sevIcon} ${r.severity.toUpperCase()} ${statusIcon} ${r.status} \u2014 ${r.title}`);
27693
+ lines.push(` ID: ${r.id} | Filed: ${r.created_at?.slice(0, 10) ?? "?"}`);
27694
+ if (r.fixed_version) lines.push(` \u{1F527} Fixed in: ${r.fixed_version} \u2014 run \`exe-os update\` to get this fix`);
27695
+ if (r.triage_notes) lines.push(` \u{1F4DD} AskExe: ${r.triage_notes}`);
27696
+ lines.push("");
27697
+ }
27698
+ return {
27699
+ content: [{ type: "text", text: lines.join("\n") }],
27700
+ structuredContent: data
27701
+ };
27702
+ } catch (err) {
27703
+ return {
27704
+ content: [{ type: "text", text: `Error fetching bug reports: ${err instanceof Error ? err.message : String(err)}` }],
27705
+ isError: true
27706
+ };
27707
+ }
27708
+ }
27709
+ );
27628
27710
  }
27629
27711
 
27630
27712
  // src/mcp/tools/cli-parity.ts
@@ -27692,7 +27774,7 @@ if (isMainModule(import.meta.url)) {
27692
27774
  // src/bin/exe-healthcheck.ts
27693
27775
  import { existsSync as existsSync39, readFileSync as readFileSync33, readdirSync as readdirSync14 } from "fs";
27694
27776
  import path51 from "path";
27695
- import { execSync as execSync13 } from "child_process";
27777
+ import { execSync as execSync14 } from "child_process";
27696
27778
  import { fileURLToPath as fileURLToPath6 } from "url";
27697
27779
  init_config();
27698
27780
  function findPackageRoot2() {
@@ -27790,7 +27872,7 @@ function checkTaskSystem(pkgRoot) {
27790
27872
  return results;
27791
27873
  }
27792
27874
  try {
27793
- execSync13(`node "${scannerPath}" /tmp/nonexistent-healthcheck-test --format=json 2>/dev/null`, {
27875
+ execSync14(`node "${scannerPath}" /tmp/nonexistent-healthcheck-test --format=json 2>/dev/null`, {
27794
27876
  timeout: 1e4,
27795
27877
  encoding: "utf-8"
27796
27878
  });
@@ -27813,7 +27895,7 @@ function checkWorkerSpawning(pkgRoot) {
27813
27895
  return results;
27814
27896
  }
27815
27897
  try {
27816
- execSync13(`node --check "${workerPath}" 2>&1`, { timeout: 1e4, encoding: "utf-8" });
27898
+ execSync14(`node --check "${workerPath}" 2>&1`, { timeout: 1e4, encoding: "utf-8" });
27817
27899
  results.push({ name: "workers/ingest-worker", pass: true, detail: "ingest-worker.js parses OK" });
27818
27900
  } catch (err) {
27819
27901
  results.push({
@@ -27829,7 +27911,7 @@ function checkWorkerSpawning(pkgRoot) {
27829
27911
  const hooksFailed = [];
27830
27912
  for (const hook of hookFiles) {
27831
27913
  try {
27832
- execSync13(`node --check "${path51.join(hooksDir, hook)}" 2>&1`, { timeout: 1e4, encoding: "utf-8" });
27914
+ execSync14(`node --check "${path51.join(hooksDir, hook)}" 2>&1`, { timeout: 1e4, encoding: "utf-8" });
27833
27915
  hooksPassed++;
27834
27916
  } catch {
27835
27917
  hooksFailed.push(hook);
@@ -27871,7 +27953,7 @@ function checkMcpTransport() {
27871
27953
  if (daemonAlive && existsSync39(tokenPath)) {
27872
27954
  try {
27873
27955
  const token = readFileSync33(tokenPath, "utf8").trim();
27874
- const response = execSync13(
27956
+ const response = execSync14(
27875
27957
  `curl -sS -i -m 2 -H "Authorization: Bearer ${token}" -H 'Accept: application/json, text/event-stream' http://127.0.0.1:48739/mcp`,
27876
27958
  { encoding: "utf8", timeout: 3e3 }
27877
27959
  );
@@ -27922,7 +28004,7 @@ function checkClaudeCodeInstall() {
27922
28004
  });
27923
28005
  }
27924
28006
  try {
27925
- const claudePath = execSync13("which claude 2>/dev/null || true", { encoding: "utf8", timeout: 5e3 }).trim();
28007
+ const claudePath = execSync14("which claude 2>/dev/null || true", { encoding: "utf8", timeout: 5e3 }).trim();
27926
28008
  if (!claudePath) {
27927
28009
  results.push({
27928
28010
  name: "cc/cli-binary",
@@ -27932,7 +28014,7 @@ function checkClaudeCodeInstall() {
27932
28014
  } else {
27933
28015
  let resolved = claudePath;
27934
28016
  try {
27935
- resolved = execSync13(`readlink -f "${claudePath}" 2>/dev/null || readlink "${claudePath}" 2>/dev/null || echo "${claudePath}"`, {
28017
+ resolved = execSync14(`readlink -f "${claudePath}" 2>/dev/null || readlink "${claudePath}" 2>/dev/null || echo "${claudePath}"`, {
27936
28018
  encoding: "utf8",
27937
28019
  timeout: 5e3
27938
28020
  }).trim();
@@ -28016,7 +28098,7 @@ function checkClaudeCodeInstall() {
28016
28098
  });
28017
28099
  }
28018
28100
  try {
28019
- const ccVersion = execSync13("claude --version 2>/dev/null || echo unknown", {
28101
+ const ccVersion = execSync14("claude --version 2>/dev/null || echo unknown", {
28020
28102
  encoding: "utf8",
28021
28103
  timeout: 5e3
28022
28104
  }).trim();
@@ -28064,7 +28146,7 @@ if (isMainModule(import.meta.url)) {
28064
28146
  }
28065
28147
 
28066
28148
  // src/lib/update-check.ts
28067
- import { execSync as execSync14 } from "child_process";
28149
+ import { execSync as execSync15 } from "child_process";
28068
28150
  import { readFileSync as readFileSync34 } from "fs";
28069
28151
  import path52 from "path";
28070
28152
  function getLocalVersion(packageRoot) {
@@ -28074,7 +28156,7 @@ function getLocalVersion(packageRoot) {
28074
28156
  }
28075
28157
  function getRemoteVersion() {
28076
28158
  try {
28077
- const output = execSync14("npm view @askexenow/exe-os version", {
28159
+ const output = execSync15("npm view @askexenow/exe-os version", {
28078
28160
  encoding: "utf-8",
28079
28161
  timeout: 15e3,
28080
28162
  stdio: ["pipe", "pipe", "pipe"]
@@ -3876,7 +3876,7 @@ var init_daemon_auth = __esm({
3876
3876
  // src/lib/exe-daemon-client.ts
3877
3877
  import net from "net";
3878
3878
  import os11 from "os";
3879
- import { spawn } from "child_process";
3879
+ import { spawn, execSync as execSync7 } from "child_process";
3880
3880
  import { randomUUID as randomUUID2 } from "crypto";
3881
3881
  import { existsSync as existsSync15, unlinkSync as unlinkSync5, readFileSync as readFileSync12, openSync, closeSync, statSync } from "fs";
3882
3882
  import path17 from "path";
@@ -3906,6 +3906,14 @@ function handleData(chunk) {
3906
3906
  }
3907
3907
  }
3908
3908
  }
3909
+ function isZombie(pid) {
3910
+ try {
3911
+ const state = execSync7(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
3912
+ return state.startsWith("Z");
3913
+ } catch {
3914
+ return false;
3915
+ }
3916
+ }
3909
3917
  function cleanupStaleFiles() {
3910
3918
  if (existsSync15(PID_PATH)) {
3911
3919
  try {
@@ -3913,7 +3921,11 @@ function cleanupStaleFiles() {
3913
3921
  if (pid > 0) {
3914
3922
  try {
3915
3923
  process.kill(pid, 0);
3916
- return;
3924
+ if (!isZombie(pid)) {
3925
+ return;
3926
+ }
3927
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
3928
+ `);
3917
3929
  } catch {
3918
3930
  }
3919
3931
  }
@@ -3941,8 +3953,8 @@ function findPackageRoot() {
3941
3953
  function getAvailableMemoryGB() {
3942
3954
  if (process.platform === "darwin") {
3943
3955
  try {
3944
- const { execSync: execSync8 } = __require("child_process");
3945
- const vmstat = execSync8("vm_stat", { encoding: "utf8" });
3956
+ const { execSync: execSync9 } = __require("child_process");
3957
+ const vmstat = execSync9("vm_stat", { encoding: "utf8" });
3946
3958
  const pageSize = 16384;
3947
3959
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
3948
3960
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -5579,7 +5591,7 @@ import { z } from "zod";
5579
5591
  init_config();
5580
5592
  init_session_key();
5581
5593
  import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7, readdirSync as readdirSync4 } from "fs";
5582
- import { execSync as execSync7 } from "child_process";
5594
+ import { execSync as execSync8 } from "child_process";
5583
5595
  import path19 from "path";
5584
5596
 
5585
5597
  // src/mcp/agent-context.ts
@@ -5669,7 +5681,7 @@ function getActiveAgent() {
5669
5681
  } catch {
5670
5682
  }
5671
5683
  try {
5672
- const sessionName = execSync7(
5684
+ const sessionName = execSync8(
5673
5685
  "tmux display-message -p '#{session_name}' 2>/dev/null",
5674
5686
  { encoding: "utf8", timeout: 2e3 }
5675
5687
  ).trim();