@askexenow/exe-os 0.9.21 → 0.9.23

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 (60) hide show
  1. package/dist/bin/backfill-conversations.js +17 -4
  2. package/dist/bin/backfill-responses.js +17 -4
  3. package/dist/bin/backfill-vectors.js +2 -2
  4. package/dist/bin/cleanup-stale-review-tasks.js +17 -4
  5. package/dist/bin/cli.js +378 -171
  6. package/dist/bin/exe-assign.js +17 -4
  7. package/dist/bin/exe-boot.js +2 -2
  8. package/dist/bin/exe-dispatch.js +17 -4
  9. package/dist/bin/exe-doctor.js +2 -2
  10. package/dist/bin/exe-export-behaviors.js +17 -4
  11. package/dist/bin/exe-forget.js +17 -4
  12. package/dist/bin/exe-gateway.js +17 -4
  13. package/dist/bin/exe-heartbeat.js +17 -4
  14. package/dist/bin/exe-kill.js +17 -4
  15. package/dist/bin/exe-launch-agent.js +17 -4
  16. package/dist/bin/exe-pending-messages.js +17 -4
  17. package/dist/bin/exe-pending-notifications.js +17 -4
  18. package/dist/bin/exe-pending-reviews.js +17 -4
  19. package/dist/bin/exe-review.js +17 -4
  20. package/dist/bin/exe-search.js +23 -8
  21. package/dist/bin/exe-session-cleanup.js +17 -4
  22. package/dist/bin/exe-start-codex.js +209 -32
  23. package/dist/bin/exe-start-opencode.js +17 -4
  24. package/dist/bin/exe-status.js +17 -4
  25. package/dist/bin/exe-team.js +17 -4
  26. package/dist/bin/git-sweep.js +17 -4
  27. package/dist/bin/graph-backfill.js +17 -4
  28. package/dist/bin/graph-export.js +17 -4
  29. package/dist/bin/install.js +42 -0
  30. package/dist/bin/intercom-check.js +17 -4
  31. package/dist/bin/scan-tasks.js +17 -4
  32. package/dist/bin/shard-migrate.js +17 -4
  33. package/dist/bin/update.js +187 -42
  34. package/dist/gateway/index.js +17 -4
  35. package/dist/hooks/bug-report-worker.js +793 -150
  36. package/dist/hooks/codex-stop-task-finalizer.js +3020 -2375
  37. package/dist/hooks/commit-complete.js +156 -6
  38. package/dist/hooks/error-recall.js +23 -8
  39. package/dist/hooks/ingest.js +17 -4
  40. package/dist/hooks/instructions-loaded.js +17 -4
  41. package/dist/hooks/notification.js +17 -4
  42. package/dist/hooks/post-compact.js +17 -4
  43. package/dist/hooks/post-tool-combined.js +23 -8
  44. package/dist/hooks/pre-compact.js +156 -8
  45. package/dist/hooks/pre-tool-use.js +21 -12
  46. package/dist/hooks/prompt-submit.js +23 -8
  47. package/dist/hooks/session-end.js +156 -8
  48. package/dist/hooks/session-start.js +23 -8
  49. package/dist/hooks/stop.js +306 -9
  50. package/dist/hooks/subagent-stop.js +306 -9
  51. package/dist/hooks/summary-worker.js +2 -2
  52. package/dist/index.js +17 -4
  53. package/dist/lib/exe-daemon.js +37 -14
  54. package/dist/lib/hybrid-search.js +23 -8
  55. package/dist/lib/schedules.js +2 -2
  56. package/dist/lib/store.js +17 -4
  57. package/dist/mcp/server.js +36 -10
  58. package/dist/runtime/index.js +17 -4
  59. package/dist/tui/App.js +17 -4
  60. package/package.json +1 -1
@@ -2596,8 +2596,8 @@ function getShardClient(projectName) {
2596
2596
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
2597
2597
  }
2598
2598
  const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2599
- if (!safeName) {
2600
- throw new Error(`Invalid project name for shard: "${projectName}"`);
2599
+ if (!safeName || safeName === "unknown") {
2600
+ throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
2601
2601
  }
2602
2602
  const cached = _shards.get(safeName);
2603
2603
  if (cached) {
@@ -3441,19 +3441,32 @@ async function flushBatch() {
3441
3441
  const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
3442
3442
  if (isShardingEnabled2()) {
3443
3443
  const byProject = /* @__PURE__ */ new Map();
3444
+ let skippedUnknown = 0;
3444
3445
  for (const row of batch) {
3445
- const proj = row.project_name || "unknown";
3446
+ const proj = row.project_name?.trim();
3447
+ if (!proj) {
3448
+ skippedUnknown++;
3449
+ continue;
3450
+ }
3446
3451
  if (!byProject.has(proj)) byProject.set(proj, []);
3447
3452
  byProject.get(proj).push(row);
3448
3453
  }
3454
+ if (skippedUnknown > 0) {
3455
+ process.stderr.write(
3456
+ `[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
3457
+ `
3458
+ );
3459
+ }
3449
3460
  for (const [project, rows] of byProject) {
3450
3461
  try {
3451
3462
  const shardClient = await getReadyShardClient2(project);
3452
3463
  const shardStmts = rows.map(buildStmt);
3453
3464
  await shardClient.batch(shardStmts, "write");
3454
3465
  } catch (err) {
3466
+ const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
3467
+ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
3455
3468
  process.stderr.write(
3456
- `[store] Shard write failed for ${project}: ${err instanceof Error ? err.message : String(err)}
3469
+ `[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
3457
3470
  `
3458
3471
  );
3459
3472
  }
@@ -2923,8 +2923,8 @@ function getShardClient(projectName) {
2923
2923
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
2924
2924
  }
2925
2925
  const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2926
- if (!safeName) {
2927
- throw new Error(`Invalid project name for shard: "${projectName}"`);
2926
+ if (!safeName || safeName === "unknown") {
2927
+ throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
2928
2928
  }
2929
2929
  const cached = _shards.get(safeName);
2930
2930
  if (cached) {
@@ -3793,19 +3793,32 @@ async function flushBatch() {
3793
3793
  const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
3794
3794
  if (isShardingEnabled2()) {
3795
3795
  const byProject = /* @__PURE__ */ new Map();
3796
+ let skippedUnknown = 0;
3796
3797
  for (const row of batch) {
3797
- const proj = row.project_name || "unknown";
3798
+ const proj = row.project_name?.trim();
3799
+ if (!proj) {
3800
+ skippedUnknown++;
3801
+ continue;
3802
+ }
3798
3803
  if (!byProject.has(proj)) byProject.set(proj, []);
3799
3804
  byProject.get(proj).push(row);
3800
3805
  }
3806
+ if (skippedUnknown > 0) {
3807
+ process.stderr.write(
3808
+ `[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
3809
+ `
3810
+ );
3811
+ }
3801
3812
  for (const [project, rows] of byProject) {
3802
3813
  try {
3803
3814
  const shardClient = await getReadyShardClient2(project);
3804
3815
  const shardStmts = rows.map(buildStmt);
3805
3816
  await shardClient.batch(shardStmts, "write");
3806
3817
  } catch (err) {
3818
+ const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
3819
+ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
3807
3820
  process.stderr.write(
3808
- `[store] Shard write failed for ${project}: ${err instanceof Error ? err.message : String(err)}
3821
+ `[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
3809
3822
  `
3810
3823
  );
3811
3824
  }
@@ -1418,6 +1418,7 @@ var installer_exports = {};
1418
1418
  __export(installer_exports, {
1419
1419
  installCodexStatusLine: () => installCodexStatusLine,
1420
1420
  mergeCodexHooks: () => mergeCodexHooks,
1421
+ registerCodexMcpServer: () => registerCodexMcpServer,
1421
1422
  runCodexInstaller: () => runCodexInstaller,
1422
1423
  verifyCodexHooks: () => verifyCodexHooks
1423
1424
  });
@@ -1589,11 +1590,52 @@ status_line = [${DEFAULT_CODEX_STATUS_LINE.map((s) => `"${s}"`).join(", ")}]`;
1589
1590
  await writeFile4(configPath, content);
1590
1591
  return "installed";
1591
1592
  }
1593
+ async function registerCodexMcpServer(packageRoot, homeDir = os6.homedir()) {
1594
+ const codexDir = path8.join(homeDir, ".codex");
1595
+ const configPath = path8.join(codexDir, "config.toml");
1596
+ const serverJsPath = path8.join(packageRoot, "dist", "mcp", "server.js");
1597
+ await mkdir4(codexDir, { recursive: true });
1598
+ let content = "";
1599
+ if (existsSync9(configPath)) {
1600
+ content = await readFile4(configPath, "utf-8");
1601
+ }
1602
+ const sectionHeader = "[mcp_servers.exe-os]";
1603
+ const headerIndex = content.indexOf(sectionHeader);
1604
+ if (headerIndex !== -1) {
1605
+ const afterHeader = content.slice(headerIndex + sectionHeader.length);
1606
+ const nextSectionMatch = afterHeader.match(/\n\[(?!mcp_servers\.exe-os)/);
1607
+ const sectionEnd = nextSectionMatch ? headerIndex + sectionHeader.length + nextSectionMatch.index : content.length;
1608
+ const sectionContent = content.slice(headerIndex, sectionEnd);
1609
+ if (sectionContent.includes(serverJsPath)) {
1610
+ return "already-registered";
1611
+ }
1612
+ const newSection2 = `${sectionHeader}
1613
+ command = "node"
1614
+ args = ["${serverJsPath}"]
1615
+ `;
1616
+ content = content.slice(0, headerIndex) + newSection2 + content.slice(sectionEnd);
1617
+ await writeFile4(configPath, content);
1618
+ return "updated";
1619
+ }
1620
+ const newSection = `[mcp_servers.exe-os]
1621
+ command = "node"
1622
+ args = ["${serverJsPath}"]
1623
+ `;
1624
+ const separator = content.length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
1625
+ content = content + separator + newSection;
1626
+ await writeFile4(configPath, content);
1627
+ return "registered";
1628
+ }
1592
1629
  async function runCodexInstaller(homeDir) {
1593
1630
  const packageRoot = resolvePackageRoot();
1594
1631
  const result = await mergeCodexHooks(packageRoot, homeDir);
1595
1632
  process.stderr.write(
1596
1633
  `[exe-os] Codex hooks: ${result.added} added, ${result.skipped} unchanged
1634
+ `
1635
+ );
1636
+ const mcpResult = await registerCodexMcpServer(packageRoot, homeDir);
1637
+ process.stderr.write(
1638
+ `[exe-os] Codex MCP server: ${mcpResult}
1597
1639
  `
1598
1640
  );
1599
1641
  const statusResult = await installCodexStatusLine(homeDir);
@@ -3022,8 +3022,8 @@ function getShardClient(projectName) {
3022
3022
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
3023
3023
  }
3024
3024
  const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3025
- if (!safeName) {
3026
- throw new Error(`Invalid project name for shard: "${projectName}"`);
3025
+ if (!safeName || safeName === "unknown") {
3026
+ throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
3027
3027
  }
3028
3028
  const cached = _shards.get(safeName);
3029
3029
  if (cached) {
@@ -3892,19 +3892,32 @@ async function flushBatch() {
3892
3892
  const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
3893
3893
  if (isShardingEnabled2()) {
3894
3894
  const byProject = /* @__PURE__ */ new Map();
3895
+ let skippedUnknown = 0;
3895
3896
  for (const row of batch) {
3896
- const proj = row.project_name || "unknown";
3897
+ const proj = row.project_name?.trim();
3898
+ if (!proj) {
3899
+ skippedUnknown++;
3900
+ continue;
3901
+ }
3897
3902
  if (!byProject.has(proj)) byProject.set(proj, []);
3898
3903
  byProject.get(proj).push(row);
3899
3904
  }
3905
+ if (skippedUnknown > 0) {
3906
+ process.stderr.write(
3907
+ `[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
3908
+ `
3909
+ );
3910
+ }
3900
3911
  for (const [project, rows] of byProject) {
3901
3912
  try {
3902
3913
  const shardClient = await getReadyShardClient2(project);
3903
3914
  const shardStmts = rows.map(buildStmt);
3904
3915
  await shardClient.batch(shardStmts, "write");
3905
3916
  } catch (err) {
3917
+ const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
3918
+ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
3906
3919
  process.stderr.write(
3907
- `[store] Shard write failed for ${project}: ${err instanceof Error ? err.message : String(err)}
3920
+ `[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
3908
3921
  `
3909
3922
  );
3910
3923
  }
@@ -6624,8 +6624,8 @@ function getShardClient(projectName) {
6624
6624
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
6625
6625
  }
6626
6626
  const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
6627
- if (!safeName) {
6628
- throw new Error(`Invalid project name for shard: "${projectName}"`);
6627
+ if (!safeName || safeName === "unknown") {
6628
+ throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
6629
6629
  }
6630
6630
  const cached = _shards.get(safeName);
6631
6631
  if (cached) {
@@ -7494,19 +7494,32 @@ async function flushBatch() {
7494
7494
  const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
7495
7495
  if (isShardingEnabled2()) {
7496
7496
  const byProject = /* @__PURE__ */ new Map();
7497
+ let skippedUnknown = 0;
7497
7498
  for (const row of batch) {
7498
- const proj = row.project_name || "unknown";
7499
+ const proj = row.project_name?.trim();
7500
+ if (!proj) {
7501
+ skippedUnknown++;
7502
+ continue;
7503
+ }
7499
7504
  if (!byProject.has(proj)) byProject.set(proj, []);
7500
7505
  byProject.get(proj).push(row);
7501
7506
  }
7507
+ if (skippedUnknown > 0) {
7508
+ process.stderr.write(
7509
+ `[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
7510
+ `
7511
+ );
7512
+ }
7502
7513
  for (const [project, rows] of byProject) {
7503
7514
  try {
7504
7515
  const shardClient = await getReadyShardClient2(project);
7505
7516
  const shardStmts = rows.map(buildStmt);
7506
7517
  await shardClient.batch(shardStmts, "write");
7507
7518
  } catch (err) {
7519
+ const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
7520
+ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
7508
7521
  process.stderr.write(
7509
- `[store] Shard write failed for ${project}: ${err instanceof Error ? err.message : String(err)}
7522
+ `[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
7510
7523
  `
7511
7524
  );
7512
7525
  }
@@ -2596,8 +2596,8 @@ function getShardClient(projectName) {
2596
2596
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
2597
2597
  }
2598
2598
  const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2599
- if (!safeName) {
2600
- throw new Error(`Invalid project name for shard: "${projectName}"`);
2599
+ if (!safeName || safeName === "unknown") {
2600
+ throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
2601
2601
  }
2602
2602
  const cached = _shards.get(safeName);
2603
2603
  if (cached) {
@@ -3441,19 +3441,32 @@ async function flushBatch() {
3441
3441
  const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
3442
3442
  if (isShardingEnabled2()) {
3443
3443
  const byProject = /* @__PURE__ */ new Map();
3444
+ let skippedUnknown = 0;
3444
3445
  for (const row of batch) {
3445
- const proj = row.project_name || "unknown";
3446
+ const proj = row.project_name?.trim();
3447
+ if (!proj) {
3448
+ skippedUnknown++;
3449
+ continue;
3450
+ }
3446
3451
  if (!byProject.has(proj)) byProject.set(proj, []);
3447
3452
  byProject.get(proj).push(row);
3448
3453
  }
3454
+ if (skippedUnknown > 0) {
3455
+ process.stderr.write(
3456
+ `[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
3457
+ `
3458
+ );
3459
+ }
3449
3460
  for (const [project, rows] of byProject) {
3450
3461
  try {
3451
3462
  const shardClient = await getReadyShardClient2(project);
3452
3463
  const shardStmts = rows.map(buildStmt);
3453
3464
  await shardClient.batch(shardStmts, "write");
3454
3465
  } catch (err) {
3466
+ const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
3467
+ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
3455
3468
  process.stderr.write(
3456
- `[store] Shard write failed for ${project}: ${err instanceof Error ? err.message : String(err)}
3469
+ `[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
3457
3470
  `
3458
3471
  );
3459
3472
  }