@probelabs/visor 0.1.171 → 0.1.172-ee

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/agent-protocol/task-store.d.ts +8 -0
  2. package/dist/agent-protocol/task-store.d.ts.map +1 -1
  3. package/dist/agent-protocol/tasks-cli-handler.d.ts.map +1 -1
  4. package/dist/cli-main.d.ts.map +1 -1
  5. package/dist/index.js +2033 -99
  6. package/dist/sdk/{a2a-frontend-GUEGI5SX.mjs → a2a-frontend-N4VU3PHW.mjs} +36 -1
  7. package/dist/sdk/a2a-frontend-N4VU3PHW.mjs.map +1 -0
  8. package/dist/sdk/{check-provider-registry-YTI4PU5F.mjs → check-provider-registry-4KW2YPZW.mjs} +3 -3
  9. package/dist/sdk/{check-provider-registry-ZUU7KSKR.mjs → check-provider-registry-H5GQGT2X.mjs} +3 -3
  10. package/dist/sdk/{chunk-CXA3WUOB.mjs → chunk-CNZ7XHLN.mjs} +9 -9
  11. package/dist/sdk/{chunk-2VDUNKIP.mjs → chunk-ONN7TBQM.mjs} +14 -14
  12. package/dist/sdk/{chunk-XUQSI5SR.mjs.map → chunk-ONN7TBQM.mjs.map} +1 -1
  13. package/dist/sdk/{chunk-AVMMKGLQ.mjs → chunk-PDQTEBOJ.mjs} +18 -18
  14. package/dist/sdk/chunk-PDQTEBOJ.mjs.map +1 -0
  15. package/dist/sdk/{host-A7UNRBQU.mjs → host-DOJQVREK.mjs} +3 -3
  16. package/dist/sdk/{host-A4GGQVEN.mjs → host-YATAT2B4.mjs} +4 -4
  17. package/dist/sdk/knex-store-CRORFJE6.mjs +527 -0
  18. package/dist/sdk/knex-store-CRORFJE6.mjs.map +1 -0
  19. package/dist/sdk/loader-QMJFFST6.mjs +89 -0
  20. package/dist/sdk/loader-QMJFFST6.mjs.map +1 -0
  21. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs +655 -0
  22. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
  23. package/dist/sdk/{schedule-tool-DGVJDHJM.mjs → schedule-tool-HCJUIF4H.mjs} +3 -3
  24. package/dist/sdk/{schedule-tool-4MTFIHCA.mjs → schedule-tool-KUGCECKZ.mjs} +3 -3
  25. package/dist/sdk/{schedule-tool-handler-LMXQ4BZQ.mjs → schedule-tool-handler-DCMMLWLB.mjs} +3 -3
  26. package/dist/sdk/{schedule-tool-handler-XLCSBU3E.mjs → schedule-tool-handler-IZU43FC2.mjs} +3 -3
  27. package/dist/sdk/sdk.js +1700 -291
  28. package/dist/sdk/sdk.js.map +1 -1
  29. package/dist/sdk/sdk.mjs +5 -5
  30. package/dist/sdk/{slack-frontend-QO7LW5BH.mjs → slack-frontend-7T5UISCX.mjs} +2 -2
  31. package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
  32. package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
  33. package/dist/sdk/{workflow-check-provider-KQNLEQEY.mjs → workflow-check-provider-LO2X6XOJ.mjs} +3 -3
  34. package/dist/sdk/{workflow-check-provider-X5EMAJUZ.mjs → workflow-check-provider-O2SIH3PC.mjs} +3 -3
  35. package/dist/slack/markdown.d.ts.map +1 -1
  36. package/package.json +1 -1
  37. package/dist/output/traces/run-2026-03-08T07-55-35-120Z.ndjson +0 -138
  38. package/dist/output/traces/run-2026-03-08T07-56-13-035Z.ndjson +0 -2266
  39. package/dist/sdk/a2a-frontend-FGJ3UBHX.mjs +0 -1622
  40. package/dist/sdk/a2a-frontend-FGJ3UBHX.mjs.map +0 -1
  41. package/dist/sdk/a2a-frontend-GUEGI5SX.mjs.map +0 -1
  42. package/dist/sdk/check-provider-registry-PVTV5G5R.mjs +0 -30
  43. package/dist/sdk/chunk-2VDUNKIP.mjs.map +0 -1
  44. package/dist/sdk/chunk-6FDBLSGV.mjs +0 -739
  45. package/dist/sdk/chunk-6FDBLSGV.mjs.map +0 -1
  46. package/dist/sdk/chunk-AJK3FAA2.mjs +0 -1502
  47. package/dist/sdk/chunk-AJK3FAA2.mjs.map +0 -1
  48. package/dist/sdk/chunk-AVMMKGLQ.mjs.map +0 -1
  49. package/dist/sdk/chunk-O72J3ORS.mjs +0 -449
  50. package/dist/sdk/chunk-O72J3ORS.mjs.map +0 -1
  51. package/dist/sdk/chunk-XUQSI5SR.mjs +0 -44810
  52. package/dist/sdk/failure-condition-evaluator-EFMCQVAK.mjs +0 -18
  53. package/dist/sdk/github-frontend-XG55VJ4R.mjs +0 -1386
  54. package/dist/sdk/github-frontend-XG55VJ4R.mjs.map +0 -1
  55. package/dist/sdk/routing-BVEHVZHK.mjs +0 -26
  56. package/dist/sdk/schedule-tool-PHSF5U2B.mjs +0 -36
  57. package/dist/sdk/schedule-tool-handler-EFNCZNS7.mjs +0 -40
  58. package/dist/sdk/schedule-tool-handler-EFNCZNS7.mjs.map +0 -1
  59. package/dist/sdk/schedule-tool-handler-LMXQ4BZQ.mjs.map +0 -1
  60. package/dist/sdk/schedule-tool-handler-XLCSBU3E.mjs.map +0 -1
  61. package/dist/sdk/trace-helpers-P5L4COO4.mjs +0 -26
  62. package/dist/sdk/trace-helpers-P5L4COO4.mjs.map +0 -1
  63. package/dist/sdk/workflow-check-provider-KQNLEQEY.mjs.map +0 -1
  64. package/dist/sdk/workflow-check-provider-WLMTCFRA.mjs +0 -30
  65. package/dist/sdk/workflow-check-provider-WLMTCFRA.mjs.map +0 -1
  66. package/dist/sdk/workflow-check-provider-X5EMAJUZ.mjs.map +0 -1
  67. package/dist/traces/run-2026-03-08T07-55-35-120Z.ndjson +0 -138
  68. package/dist/traces/run-2026-03-08T07-56-13-035Z.ndjson +0 -2266
  69. /package/dist/sdk/{check-provider-registry-PVTV5G5R.mjs.map → check-provider-registry-4KW2YPZW.mjs.map} +0 -0
  70. /package/dist/sdk/{check-provider-registry-YTI4PU5F.mjs.map → check-provider-registry-H5GQGT2X.mjs.map} +0 -0
  71. /package/dist/sdk/{chunk-CXA3WUOB.mjs.map → chunk-CNZ7XHLN.mjs.map} +0 -0
  72. /package/dist/sdk/{host-A4GGQVEN.mjs.map → host-DOJQVREK.mjs.map} +0 -0
  73. /package/dist/sdk/{host-A7UNRBQU.mjs.map → host-YATAT2B4.mjs.map} +0 -0
  74. /package/dist/sdk/{check-provider-registry-ZUU7KSKR.mjs.map → schedule-tool-HCJUIF4H.mjs.map} +0 -0
  75. /package/dist/sdk/{failure-condition-evaluator-EFMCQVAK.mjs.map → schedule-tool-KUGCECKZ.mjs.map} +0 -0
  76. /package/dist/sdk/{routing-BVEHVZHK.mjs.map → schedule-tool-handler-DCMMLWLB.mjs.map} +0 -0
  77. /package/dist/sdk/{schedule-tool-4MTFIHCA.mjs.map → schedule-tool-handler-IZU43FC2.mjs.map} +0 -0
  78. /package/dist/sdk/{slack-frontend-QO7LW5BH.mjs.map → slack-frontend-7T5UISCX.mjs.map} +0 -0
  79. /package/dist/sdk/{schedule-tool-DGVJDHJM.mjs.map → workflow-check-provider-LO2X6XOJ.mjs.map} +0 -0
  80. /package/dist/sdk/{schedule-tool-PHSF5U2B.mjs.map → workflow-check-provider-O2SIH3PC.mjs.map} +0 -0
package/dist/sdk/sdk.js CHANGED
@@ -661,7 +661,7 @@ var require_package = __commonJS({
661
661
  "package.json"(exports2, module2) {
662
662
  module2.exports = {
663
663
  name: "@probelabs/visor",
664
- version: "0.1.171",
664
+ version: "0.1.42",
665
665
  main: "dist/index.js",
666
666
  bin: {
667
667
  visor: "./dist/index.js"
@@ -879,11 +879,11 @@ function getTracer() {
879
879
  }
880
880
  async function withActiveSpan(name, attrs, fn) {
881
881
  const tracer = getTracer();
882
- return await new Promise((resolve15, reject) => {
882
+ return await new Promise((resolve19, reject) => {
883
883
  const callback = async (span) => {
884
884
  try {
885
885
  const res = await fn(span);
886
- resolve15(res);
886
+ resolve19(res);
887
887
  } catch (err) {
888
888
  try {
889
889
  if (err instanceof Error) span.recordException(err);
@@ -961,19 +961,19 @@ function __getOrCreateNdjsonPath() {
961
961
  try {
962
962
  if (process.env.VISOR_TELEMETRY_SINK && process.env.VISOR_TELEMETRY_SINK !== "file")
963
963
  return null;
964
- const path29 = require("path");
965
- const fs25 = require("fs");
964
+ const path33 = require("path");
965
+ const fs29 = require("fs");
966
966
  if (process.env.VISOR_FALLBACK_TRACE_FILE) {
967
967
  __ndjsonPath = process.env.VISOR_FALLBACK_TRACE_FILE;
968
- const dir = path29.dirname(__ndjsonPath);
969
- if (!fs25.existsSync(dir)) fs25.mkdirSync(dir, { recursive: true });
968
+ const dir = path33.dirname(__ndjsonPath);
969
+ if (!fs29.existsSync(dir)) fs29.mkdirSync(dir, { recursive: true });
970
970
  return __ndjsonPath;
971
971
  }
972
- const outDir = process.env.VISOR_TRACE_DIR || path29.join(process.cwd(), "output", "traces");
973
- if (!fs25.existsSync(outDir)) fs25.mkdirSync(outDir, { recursive: true });
972
+ const outDir = process.env.VISOR_TRACE_DIR || path33.join(process.cwd(), "output", "traces");
973
+ if (!fs29.existsSync(outDir)) fs29.mkdirSync(outDir, { recursive: true });
974
974
  if (!__ndjsonPath) {
975
975
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
976
- __ndjsonPath = path29.join(outDir, `${ts}.ndjson`);
976
+ __ndjsonPath = path33.join(outDir, `${ts}.ndjson`);
977
977
  }
978
978
  return __ndjsonPath;
979
979
  } catch {
@@ -982,11 +982,11 @@ function __getOrCreateNdjsonPath() {
982
982
  }
983
983
  function _appendRunMarker() {
984
984
  try {
985
- const fs25 = require("fs");
985
+ const fs29 = require("fs");
986
986
  const p = __getOrCreateNdjsonPath();
987
987
  if (!p) return;
988
988
  const line = { name: "visor.run", attributes: { started: true } };
989
- fs25.appendFileSync(p, JSON.stringify(line) + "\n", "utf8");
989
+ fs29.appendFileSync(p, JSON.stringify(line) + "\n", "utf8");
990
990
  } catch {
991
991
  }
992
992
  }
@@ -3210,7 +3210,7 @@ var init_failure_condition_evaluator = __esm({
3210
3210
  */
3211
3211
  evaluateExpression(condition, context2) {
3212
3212
  try {
3213
- const normalize4 = (expr) => {
3213
+ const normalize8 = (expr) => {
3214
3214
  const trimmed = expr.trim();
3215
3215
  if (!/[\n;]/.test(trimmed)) return trimmed;
3216
3216
  const parts = trimmed.split(/[\n;]+/).map((s) => s.trim()).filter((s) => s.length > 0 && !s.startsWith("//"));
@@ -3368,7 +3368,7 @@ var init_failure_condition_evaluator = __esm({
3368
3368
  try {
3369
3369
  exec2 = this.sandbox.compile(`return (${raw});`);
3370
3370
  } catch {
3371
- const normalizedExpr = normalize4(condition);
3371
+ const normalizedExpr = normalize8(condition);
3372
3372
  exec2 = this.sandbox.compile(`return (${normalizedExpr});`);
3373
3373
  }
3374
3374
  const result = exec2(scope).run();
@@ -3751,9 +3751,9 @@ function configureLiquidWithExtensions(liquid) {
3751
3751
  });
3752
3752
  liquid.registerFilter("get", (obj, pathExpr) => {
3753
3753
  if (obj == null) return void 0;
3754
- const path29 = typeof pathExpr === "string" ? pathExpr : String(pathExpr || "");
3755
- if (!path29) return obj;
3756
- const parts = path29.split(".");
3754
+ const path33 = typeof pathExpr === "string" ? pathExpr : String(pathExpr || "");
3755
+ if (!path33) return obj;
3756
+ const parts = path33.split(".");
3757
3757
  let cur = obj;
3758
3758
  for (const p of parts) {
3759
3759
  if (cur == null) return void 0;
@@ -3872,9 +3872,9 @@ function configureLiquidWithExtensions(liquid) {
3872
3872
  }
3873
3873
  }
3874
3874
  const defaultRole = typeof rolesCfg.default === "string" && rolesCfg.default.trim() ? rolesCfg.default.trim() : void 0;
3875
- const getNested = (obj, path29) => {
3876
- if (!obj || !path29) return void 0;
3877
- const parts = path29.split(".");
3875
+ const getNested = (obj, path33) => {
3876
+ if (!obj || !path33) return void 0;
3877
+ const parts = path33.split(".");
3878
3878
  let cur = obj;
3879
3879
  for (const p of parts) {
3880
3880
  if (cur == null) return void 0;
@@ -6426,8 +6426,8 @@ var init_dependency_gating = __esm({
6426
6426
  async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
6427
6427
  try {
6428
6428
  const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
6429
- const fs25 = await import("fs/promises");
6430
- const path29 = await import("path");
6429
+ const fs29 = await import("fs/promises");
6430
+ const path33 = await import("path");
6431
6431
  const schemaRaw = checkConfig.schema || "plain";
6432
6432
  const schema = typeof schemaRaw === "string" ? schemaRaw : "code-review";
6433
6433
  let templateContent;
@@ -6435,24 +6435,24 @@ async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
6435
6435
  templateContent = String(checkConfig.template.content);
6436
6436
  } else if (checkConfig.template && checkConfig.template.file) {
6437
6437
  const file = String(checkConfig.template.file);
6438
- const resolved = path29.resolve(process.cwd(), file);
6439
- templateContent = await fs25.readFile(resolved, "utf-8");
6438
+ const resolved = path33.resolve(process.cwd(), file);
6439
+ templateContent = await fs29.readFile(resolved, "utf-8");
6440
6440
  } else if (schema && schema !== "plain") {
6441
6441
  const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
6442
6442
  if (sanitized) {
6443
6443
  const candidatePaths = [
6444
- path29.join(__dirname, "output", sanitized, "template.liquid"),
6444
+ path33.join(__dirname, "output", sanitized, "template.liquid"),
6445
6445
  // bundled: dist/output/
6446
- path29.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
6446
+ path33.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
6447
6447
  // source: output/
6448
- path29.join(process.cwd(), "output", sanitized, "template.liquid"),
6448
+ path33.join(process.cwd(), "output", sanitized, "template.liquid"),
6449
6449
  // fallback: cwd/output/
6450
- path29.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
6450
+ path33.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
6451
6451
  // fallback: cwd/dist/output/
6452
6452
  ];
6453
6453
  for (const p of candidatePaths) {
6454
6454
  try {
6455
- templateContent = await fs25.readFile(p, "utf-8");
6455
+ templateContent = await fs29.readFile(p, "utf-8");
6456
6456
  if (templateContent) break;
6457
6457
  } catch {
6458
6458
  }
@@ -6857,7 +6857,7 @@ async function processDiffWithOutline(diffContent) {
6857
6857
  }
6858
6858
  try {
6859
6859
  const originalProbePath = process.env.PROBE_PATH;
6860
- const fs25 = require("fs");
6860
+ const fs29 = require("fs");
6861
6861
  const possiblePaths = [
6862
6862
  // Relative to current working directory (most common in production)
6863
6863
  path6.join(process.cwd(), "node_modules/@probelabs/probe/bin/probe-binary"),
@@ -6868,7 +6868,7 @@ async function processDiffWithOutline(diffContent) {
6868
6868
  ];
6869
6869
  let probeBinaryPath;
6870
6870
  for (const candidatePath of possiblePaths) {
6871
- if (fs25.existsSync(candidatePath)) {
6871
+ if (fs29.existsSync(candidatePath)) {
6872
6872
  probeBinaryPath = candidatePath;
6873
6873
  break;
6874
6874
  }
@@ -6975,7 +6975,7 @@ async function renderMermaidToPng(mermaidCode) {
6975
6975
  if (chromiumPath) {
6976
6976
  env.PUPPETEER_EXECUTABLE_PATH = chromiumPath;
6977
6977
  }
6978
- const result = await new Promise((resolve15) => {
6978
+ const result = await new Promise((resolve19) => {
6979
6979
  const proc = (0, import_child_process.spawn)(
6980
6980
  "npx",
6981
6981
  [
@@ -7005,13 +7005,13 @@ async function renderMermaidToPng(mermaidCode) {
7005
7005
  });
7006
7006
  proc.on("close", (code) => {
7007
7007
  if (code === 0) {
7008
- resolve15({ success: true });
7008
+ resolve19({ success: true });
7009
7009
  } else {
7010
- resolve15({ success: false, error: stderr || `Exit code ${code}` });
7010
+ resolve19({ success: false, error: stderr || `Exit code ${code}` });
7011
7011
  }
7012
7012
  });
7013
7013
  proc.on("error", (err) => {
7014
- resolve15({ success: false, error: err.message });
7014
+ resolve19({ success: false, error: err.message });
7015
7015
  });
7016
7016
  });
7017
7017
  if (!result.success) {
@@ -7048,28 +7048,27 @@ function replaceMermaidBlocks(text, diagrams, replacement = "_(See diagram above
7048
7048
  }
7049
7049
  function markdownToSlack(text) {
7050
7050
  if (!text || typeof text !== "string") return "";
7051
- let out = text;
7052
- out = out.replace(
7053
- /!\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
7054
- (_m, alt, url) => `<${url}|${alt || "image"}>`
7055
- );
7056
- out = out.replace(
7057
- /\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
7058
- (_m, label, url) => `<${url}|${label}>`
7059
- );
7060
- out = out.replace(/\*\*([^*]+)\*\*/g, (_m, inner) => `*${inner}*`);
7061
- out = out.replace(/__([^_]+)__/g, (_m, inner) => `*${inner}*`);
7062
- const lines = out.split(/\r?\n/);
7051
+ const lines = text.split(/\r?\n/);
7063
7052
  let inCodeBlock = false;
7064
7053
  for (let i = 0; i < lines.length; i++) {
7065
- const line = lines[i];
7066
- const trimmed = line.trimStart();
7054
+ const trimmed = lines[i].trimStart();
7067
7055
  if (/^```/.test(trimmed)) {
7068
7056
  inCodeBlock = !inCodeBlock;
7069
7057
  continue;
7070
7058
  }
7071
7059
  if (inCodeBlock) continue;
7072
- const headerMatch = /^(#{1,6})\s+(.+)$/.exec(trimmed);
7060
+ let line = lines[i];
7061
+ line = line.replace(
7062
+ /!\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
7063
+ (_m, alt, url) => `<${url}|${alt || "image"}>`
7064
+ );
7065
+ line = line.replace(
7066
+ /\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
7067
+ (_m, label, url) => `<${url}|${label}>`
7068
+ );
7069
+ line = line.replace(/\*\*([^*]+)\*\*/g, (_m, inner) => `*${inner}*`);
7070
+ line = line.replace(/__([^_]+)__/g, (_m, inner) => `*${inner}*`);
7071
+ const headerMatch = /^(#{1,6})\s+(.+)$/.exec(line.trimStart());
7073
7072
  if (headerMatch) {
7074
7073
  const [, hashes, headerText] = headerMatch;
7075
7074
  const prevLine = i > 0 ? lines[i - 1].trim() : "";
@@ -7086,10 +7085,11 @@ function markdownToSlack(text) {
7086
7085
  if (bulletMatch) {
7087
7086
  const [, indent, , rest] = bulletMatch;
7088
7087
  lines[i] = `${indent}\u2022 ${rest}`;
7088
+ continue;
7089
7089
  }
7090
+ lines[i] = line;
7090
7091
  }
7091
- out = lines.join("\n");
7092
- return out;
7092
+ return lines.join("\n");
7093
7093
  }
7094
7094
  function extractFileSections(text) {
7095
7095
  const sections = [];
@@ -8173,8 +8173,8 @@ ${schemaString}`);
8173
8173
  }
8174
8174
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8175
8175
  try {
8176
- const fs25 = require("fs");
8177
- const path29 = require("path");
8176
+ const fs29 = require("fs");
8177
+ const path33 = require("path");
8178
8178
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8179
8179
  const provider = this.config.provider || "auto";
8180
8180
  const model = this.config.model || "default";
@@ -8288,20 +8288,20 @@ ${"=".repeat(60)}
8288
8288
  `;
8289
8289
  readableVersion += `${"=".repeat(60)}
8290
8290
  `;
8291
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
8292
- if (!fs25.existsSync(debugArtifactsDir)) {
8293
- fs25.mkdirSync(debugArtifactsDir, { recursive: true });
8291
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8292
+ if (!fs29.existsSync(debugArtifactsDir)) {
8293
+ fs29.mkdirSync(debugArtifactsDir, { recursive: true });
8294
8294
  }
8295
- const debugFile = path29.join(
8295
+ const debugFile = path33.join(
8296
8296
  debugArtifactsDir,
8297
8297
  `prompt-${_checkName || "unknown"}-${timestamp}.json`
8298
8298
  );
8299
- fs25.writeFileSync(debugFile, debugJson, "utf-8");
8300
- const readableFile = path29.join(
8299
+ fs29.writeFileSync(debugFile, debugJson, "utf-8");
8300
+ const readableFile = path33.join(
8301
8301
  debugArtifactsDir,
8302
8302
  `prompt-${_checkName || "unknown"}-${timestamp}.txt`
8303
8303
  );
8304
- fs25.writeFileSync(readableFile, readableVersion, "utf-8");
8304
+ fs29.writeFileSync(readableFile, readableVersion, "utf-8");
8305
8305
  log(`
8306
8306
  \u{1F4BE} Full debug info saved to:`);
8307
8307
  log(` JSON: ${debugFile}`);
@@ -8334,8 +8334,8 @@ ${"=".repeat(60)}
8334
8334
  log(`\u{1F4E4} Response length: ${response.length} characters`);
8335
8335
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8336
8336
  try {
8337
- const fs25 = require("fs");
8338
- const path29 = require("path");
8337
+ const fs29 = require("fs");
8338
+ const path33 = require("path");
8339
8339
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8340
8340
  const agentAny2 = agent;
8341
8341
  let fullHistory = [];
@@ -8346,8 +8346,8 @@ ${"=".repeat(60)}
8346
8346
  } else if (agentAny2._messages) {
8347
8347
  fullHistory = agentAny2._messages;
8348
8348
  }
8349
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
8350
- const sessionBase = path29.join(
8349
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8350
+ const sessionBase = path33.join(
8351
8351
  debugArtifactsDir,
8352
8352
  `session-${_checkName || "unknown"}-${timestamp}`
8353
8353
  );
@@ -8359,7 +8359,7 @@ ${"=".repeat(60)}
8359
8359
  schema: effectiveSchema,
8360
8360
  totalMessages: fullHistory.length
8361
8361
  };
8362
- fs25.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
8362
+ fs29.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
8363
8363
  let readable = `=============================================================
8364
8364
  `;
8365
8365
  readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
@@ -8386,7 +8386,7 @@ ${"=".repeat(60)}
8386
8386
  `;
8387
8387
  readable += content + "\n";
8388
8388
  });
8389
- fs25.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
8389
+ fs29.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
8390
8390
  log(`\u{1F4BE} Complete session history saved:`);
8391
8391
  log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
8392
8392
  } catch (error) {
@@ -8395,11 +8395,11 @@ ${"=".repeat(60)}
8395
8395
  }
8396
8396
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8397
8397
  try {
8398
- const fs25 = require("fs");
8399
- const path29 = require("path");
8398
+ const fs29 = require("fs");
8399
+ const path33 = require("path");
8400
8400
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8401
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
8402
- const responseFile = path29.join(
8401
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8402
+ const responseFile = path33.join(
8403
8403
  debugArtifactsDir,
8404
8404
  `response-${_checkName || "unknown"}-${timestamp}.txt`
8405
8405
  );
@@ -8432,7 +8432,7 @@ ${"=".repeat(60)}
8432
8432
  `;
8433
8433
  responseContent += `${"=".repeat(60)}
8434
8434
  `;
8435
- fs25.writeFileSync(responseFile, responseContent, "utf-8");
8435
+ fs29.writeFileSync(responseFile, responseContent, "utf-8");
8436
8436
  log(`\u{1F4BE} Response saved to: ${responseFile}`);
8437
8437
  } catch (error) {
8438
8438
  log(`\u26A0\uFE0F Could not save response file: ${error}`);
@@ -8448,9 +8448,9 @@ ${"=".repeat(60)}
8448
8448
  await agentAny._telemetryConfig.shutdown();
8449
8449
  log(`\u{1F4CA} OpenTelemetry trace saved to: ${agentAny._traceFilePath}`);
8450
8450
  if (process.env.GITHUB_ACTIONS) {
8451
- const fs25 = require("fs");
8452
- if (fs25.existsSync(agentAny._traceFilePath)) {
8453
- const stats = fs25.statSync(agentAny._traceFilePath);
8451
+ const fs29 = require("fs");
8452
+ if (fs29.existsSync(agentAny._traceFilePath)) {
8453
+ const stats = fs29.statSync(agentAny._traceFilePath);
8454
8454
  console.log(
8455
8455
  `::notice title=AI Trace Saved::${agentAny._traceFilePath} (${stats.size} bytes)`
8456
8456
  );
@@ -8663,9 +8663,9 @@ ${schemaString}`);
8663
8663
  const model = this.config.model || "default";
8664
8664
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8665
8665
  try {
8666
- const fs25 = require("fs");
8667
- const path29 = require("path");
8668
- const os2 = require("os");
8666
+ const fs29 = require("fs");
8667
+ const path33 = require("path");
8668
+ const os3 = require("os");
8669
8669
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8670
8670
  const debugData = {
8671
8671
  timestamp,
@@ -8737,19 +8737,19 @@ ${"=".repeat(60)}
8737
8737
  `;
8738
8738
  readableVersion += `${"=".repeat(60)}
8739
8739
  `;
8740
- const tempDir = os2.tmpdir();
8741
- const promptFile = path29.join(tempDir, `visor-prompt-${timestamp}.txt`);
8742
- fs25.writeFileSync(promptFile, prompt, "utf-8");
8740
+ const tempDir = os3.tmpdir();
8741
+ const promptFile = path33.join(tempDir, `visor-prompt-${timestamp}.txt`);
8742
+ fs29.writeFileSync(promptFile, prompt, "utf-8");
8743
8743
  log(`
8744
8744
  \u{1F4BE} Prompt saved to: ${promptFile}`);
8745
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
8745
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8746
8746
  try {
8747
- const base = path29.join(
8747
+ const base = path33.join(
8748
8748
  debugArtifactsDir,
8749
8749
  `prompt-${_checkName || "unknown"}-${timestamp}`
8750
8750
  );
8751
- fs25.writeFileSync(base + ".json", debugJson, "utf-8");
8752
- fs25.writeFileSync(base + ".summary.txt", readableVersion, "utf-8");
8751
+ fs29.writeFileSync(base + ".json", debugJson, "utf-8");
8752
+ fs29.writeFileSync(base + ".summary.txt", readableVersion, "utf-8");
8753
8753
  log(`
8754
8754
  \u{1F4BE} Full debug info saved to directory: ${debugArtifactsDir}`);
8755
8755
  } catch {
@@ -8794,8 +8794,8 @@ $ ${cliCommand}
8794
8794
  log(`\u{1F4E4} Response length: ${response.length} characters`);
8795
8795
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8796
8796
  try {
8797
- const fs25 = require("fs");
8798
- const path29 = require("path");
8797
+ const fs29 = require("fs");
8798
+ const path33 = require("path");
8799
8799
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8800
8800
  const agentAny = agent;
8801
8801
  let fullHistory = [];
@@ -8806,8 +8806,8 @@ $ ${cliCommand}
8806
8806
  } else if (agentAny._messages) {
8807
8807
  fullHistory = agentAny._messages;
8808
8808
  }
8809
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
8810
- const sessionBase = path29.join(
8809
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8810
+ const sessionBase = path33.join(
8811
8811
  debugArtifactsDir,
8812
8812
  `session-${_checkName || "unknown"}-${timestamp}`
8813
8813
  );
@@ -8819,7 +8819,7 @@ $ ${cliCommand}
8819
8819
  schema: effectiveSchema,
8820
8820
  totalMessages: fullHistory.length
8821
8821
  };
8822
- fs25.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
8822
+ fs29.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
8823
8823
  let readable = `=============================================================
8824
8824
  `;
8825
8825
  readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
@@ -8846,7 +8846,7 @@ ${"=".repeat(60)}
8846
8846
  `;
8847
8847
  readable += content + "\n";
8848
8848
  });
8849
- fs25.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
8849
+ fs29.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
8850
8850
  log(`\u{1F4BE} Complete session history saved:`);
8851
8851
  log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
8852
8852
  } catch (error) {
@@ -8855,11 +8855,11 @@ ${"=".repeat(60)}
8855
8855
  }
8856
8856
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8857
8857
  try {
8858
- const fs25 = require("fs");
8859
- const path29 = require("path");
8858
+ const fs29 = require("fs");
8859
+ const path33 = require("path");
8860
8860
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8861
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
8862
- const responseFile = path29.join(
8861
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8862
+ const responseFile = path33.join(
8863
8863
  debugArtifactsDir,
8864
8864
  `response-${_checkName || "unknown"}-${timestamp}.txt`
8865
8865
  );
@@ -8892,7 +8892,7 @@ ${"=".repeat(60)}
8892
8892
  `;
8893
8893
  responseContent += `${"=".repeat(60)}
8894
8894
  `;
8895
- fs25.writeFileSync(responseFile, responseContent, "utf-8");
8895
+ fs29.writeFileSync(responseFile, responseContent, "utf-8");
8896
8896
  log(`\u{1F4BE} Response saved to: ${responseFile}`);
8897
8897
  } catch (error) {
8898
8898
  log(`\u26A0\uFE0F Could not save response file: ${error}`);
@@ -8910,9 +8910,9 @@ ${"=".repeat(60)}
8910
8910
  await telemetry.shutdown();
8911
8911
  log(`\u{1F4CA} OpenTelemetry trace saved to: ${traceFilePath}`);
8912
8912
  if (process.env.GITHUB_ACTIONS) {
8913
- const fs25 = require("fs");
8914
- if (fs25.existsSync(traceFilePath)) {
8915
- const stats = fs25.statSync(traceFilePath);
8913
+ const fs29 = require("fs");
8914
+ if (fs29.existsSync(traceFilePath)) {
8915
+ const stats = fs29.statSync(traceFilePath);
8916
8916
  console.log(
8917
8917
  `::notice title=AI Trace Saved::OpenTelemetry trace file size: ${stats.size} bytes`
8918
8918
  );
@@ -8950,8 +8950,8 @@ ${"=".repeat(60)}
8950
8950
  * Load schema content from schema files or inline definitions
8951
8951
  */
8952
8952
  async loadSchemaContent(schema) {
8953
- const fs25 = require("fs").promises;
8954
- const path29 = require("path");
8953
+ const fs29 = require("fs").promises;
8954
+ const path33 = require("path");
8955
8955
  if (typeof schema === "object" && schema !== null) {
8956
8956
  log("\u{1F4CB} Using inline schema object from configuration");
8957
8957
  return JSON.stringify(schema);
@@ -8964,14 +8964,14 @@ ${"=".repeat(60)}
8964
8964
  }
8965
8965
  } catch {
8966
8966
  }
8967
- if ((schema.startsWith("./") || schema.includes(".json")) && !path29.isAbsolute(schema)) {
8967
+ if ((schema.startsWith("./") || schema.includes(".json")) && !path33.isAbsolute(schema)) {
8968
8968
  if (schema.includes("..") || schema.includes("\0")) {
8969
8969
  throw new Error("Invalid schema path: path traversal not allowed");
8970
8970
  }
8971
8971
  try {
8972
- const schemaPath = path29.resolve(process.cwd(), schema);
8972
+ const schemaPath = path33.resolve(process.cwd(), schema);
8973
8973
  log(`\u{1F4CB} Loading custom schema from file: ${schemaPath}`);
8974
- const schemaContent = await fs25.readFile(schemaPath, "utf-8");
8974
+ const schemaContent = await fs29.readFile(schemaPath, "utf-8");
8975
8975
  return schemaContent.trim();
8976
8976
  } catch (error) {
8977
8977
  throw new Error(
@@ -8985,22 +8985,22 @@ ${"=".repeat(60)}
8985
8985
  }
8986
8986
  const candidatePaths = [
8987
8987
  // GitHub Action bundle location
8988
- path29.join(__dirname, "output", sanitizedSchemaName, "schema.json"),
8988
+ path33.join(__dirname, "output", sanitizedSchemaName, "schema.json"),
8989
8989
  // Historical fallback when src/output was inadvertently bundled as output1/
8990
- path29.join(__dirname, "output1", sanitizedSchemaName, "schema.json"),
8990
+ path33.join(__dirname, "output1", sanitizedSchemaName, "schema.json"),
8991
8991
  // Local dev (repo root)
8992
- path29.join(process.cwd(), "output", sanitizedSchemaName, "schema.json")
8992
+ path33.join(process.cwd(), "output", sanitizedSchemaName, "schema.json")
8993
8993
  ];
8994
8994
  for (const schemaPath of candidatePaths) {
8995
8995
  try {
8996
- const schemaContent = await fs25.readFile(schemaPath, "utf-8");
8996
+ const schemaContent = await fs29.readFile(schemaPath, "utf-8");
8997
8997
  return schemaContent.trim();
8998
8998
  } catch {
8999
8999
  }
9000
9000
  }
9001
- const distPath = path29.join(__dirname, "output", sanitizedSchemaName, "schema.json");
9002
- const distAltPath = path29.join(__dirname, "output1", sanitizedSchemaName, "schema.json");
9003
- const cwdPath = path29.join(process.cwd(), "output", sanitizedSchemaName, "schema.json");
9001
+ const distPath = path33.join(__dirname, "output", sanitizedSchemaName, "schema.json");
9002
+ const distAltPath = path33.join(__dirname, "output1", sanitizedSchemaName, "schema.json");
9003
+ const cwdPath = path33.join(process.cwd(), "output", sanitizedSchemaName, "schema.json");
9004
9004
  throw new Error(
9005
9005
  `Failed to load schema '${sanitizedSchemaName}'. Tried: ${distPath}, ${distAltPath}, and ${cwdPath}. Ensure build copies 'output/' into dist (build:cli), or provide a custom schema file/path.`
9006
9006
  );
@@ -9245,7 +9245,7 @@ ${"=".repeat(60)}
9245
9245
  * Generate mock response for testing
9246
9246
  */
9247
9247
  async generateMockResponse(_prompt, _checkName, _schema) {
9248
- await new Promise((resolve15) => setTimeout(resolve15, 500));
9248
+ await new Promise((resolve19) => setTimeout(resolve19, 500));
9249
9249
  const name = (_checkName || "").toLowerCase();
9250
9250
  if (name.includes("extract-facts")) {
9251
9251
  const arr = Array.from({ length: 6 }, (_, i) => ({
@@ -9606,7 +9606,7 @@ var init_command_executor = __esm({
9606
9606
  * Execute command with stdin input
9607
9607
  */
9608
9608
  executeWithStdin(command, options) {
9609
- return new Promise((resolve15, reject) => {
9609
+ return new Promise((resolve19, reject) => {
9610
9610
  const childProcess = (0, import_child_process2.exec)(
9611
9611
  command,
9612
9612
  {
@@ -9618,7 +9618,7 @@ var init_command_executor = __esm({
9618
9618
  if (error && error.killed && (error.code === "ETIMEDOUT" || error.signal === "SIGTERM")) {
9619
9619
  reject(new Error(`Command timed out after ${options.timeout || 3e4}ms`));
9620
9620
  } else {
9621
- resolve15({
9621
+ resolve19({
9622
9622
  stdout: stdout || "",
9623
9623
  stderr: stderr || "",
9624
9624
  exitCode: error ? error.code || 1 : 0
@@ -17998,17 +17998,17 @@ var init_workflow_check_provider = __esm({
17998
17998
  * so it can be executed by the state machine as a nested workflow.
17999
17999
  */
18000
18000
  async loadWorkflowFromConfigPath(sourcePath, baseDir) {
18001
- const path29 = require("path");
18002
- const fs25 = require("fs");
18001
+ const path33 = require("path");
18002
+ const fs29 = require("fs");
18003
18003
  const yaml5 = require("js-yaml");
18004
- const resolved = path29.isAbsolute(sourcePath) ? sourcePath : path29.resolve(baseDir, sourcePath);
18005
- if (!fs25.existsSync(resolved)) {
18004
+ const resolved = path33.isAbsolute(sourcePath) ? sourcePath : path33.resolve(baseDir, sourcePath);
18005
+ if (!fs29.existsSync(resolved)) {
18006
18006
  throw new Error(`Workflow config not found at: ${resolved}`);
18007
18007
  }
18008
- const rawContent = fs25.readFileSync(resolved, "utf8");
18008
+ const rawContent = fs29.readFileSync(resolved, "utf8");
18009
18009
  const rawData = yaml5.load(rawContent);
18010
18010
  if (rawData.imports && Array.isArray(rawData.imports)) {
18011
- const configDir = path29.dirname(resolved);
18011
+ const configDir = path33.dirname(resolved);
18012
18012
  for (const source of rawData.imports) {
18013
18013
  const results = await this.registry.import(source, {
18014
18014
  basePath: configDir,
@@ -18038,8 +18038,8 @@ ${errors}`);
18038
18038
  if (!steps || Object.keys(steps).length === 0) {
18039
18039
  throw new Error(`Config '${resolved}' does not contain any steps to execute as a workflow`);
18040
18040
  }
18041
- const id = path29.basename(resolved).replace(/\.(ya?ml)$/i, "");
18042
- const name = loaded.name || `Workflow from ${path29.basename(resolved)}`;
18041
+ const id = path33.basename(resolved).replace(/\.(ya?ml)$/i, "");
18042
+ const name = loaded.name || `Workflow from ${path33.basename(resolved)}`;
18043
18043
  const workflowDef = {
18044
18044
  id,
18045
18045
  name,
@@ -18845,8 +18845,8 @@ async function createStoreBackend(storageConfig, haConfig) {
18845
18845
  case "mssql": {
18846
18846
  try {
18847
18847
  const loaderPath = "../../enterprise/loader";
18848
- const { loadEnterpriseStoreBackend } = await import(loaderPath);
18849
- return await loadEnterpriseStoreBackend(driver, storageConfig, haConfig);
18848
+ const { loadEnterpriseStoreBackend: loadEnterpriseStoreBackend2 } = await import(loaderPath);
18849
+ return await loadEnterpriseStoreBackend2(driver, storageConfig, haConfig);
18850
18850
  } catch (err) {
18851
18851
  const msg = err instanceof Error ? err.message : String(err);
18852
18852
  logger.error(`[StoreFactory] Failed to load enterprise ${driver} backend: ${msg}`);
@@ -21524,7 +21524,7 @@ var init_mcp_custom_sse_server = __esm({
21524
21524
  * Returns the actual bound port number
21525
21525
  */
21526
21526
  async start() {
21527
- return new Promise((resolve15, reject) => {
21527
+ return new Promise((resolve19, reject) => {
21528
21528
  try {
21529
21529
  this.server = import_http.default.createServer((req, res) => {
21530
21530
  this.handleRequest(req, res).catch((error) => {
@@ -21558,7 +21558,7 @@ var init_mcp_custom_sse_server = __esm({
21558
21558
  );
21559
21559
  }
21560
21560
  this.startKeepalive();
21561
- resolve15(this.port);
21561
+ resolve19(this.port);
21562
21562
  });
21563
21563
  } catch (error) {
21564
21564
  reject(error);
@@ -21621,7 +21621,7 @@ var init_mcp_custom_sse_server = __esm({
21621
21621
  logger.debug(
21622
21622
  `[CustomToolsSSEServer:${this.sessionId}] Grace period before stop: ${waitMs}ms (activeToolCalls=${this.activeToolCalls})`
21623
21623
  );
21624
- await new Promise((resolve15) => setTimeout(resolve15, waitMs));
21624
+ await new Promise((resolve19) => setTimeout(resolve19, waitMs));
21625
21625
  }
21626
21626
  }
21627
21627
  if (this.activeToolCalls > 0) {
@@ -21630,7 +21630,7 @@ var init_mcp_custom_sse_server = __esm({
21630
21630
  `[CustomToolsSSEServer:${this.sessionId}] Waiting for ${this.activeToolCalls} active tool call(s) before stop`
21631
21631
  );
21632
21632
  while (this.activeToolCalls > 0 && Date.now() - startedAt < effectiveDrainTimeoutMs) {
21633
- await new Promise((resolve15) => setTimeout(resolve15, 250));
21633
+ await new Promise((resolve19) => setTimeout(resolve19, 250));
21634
21634
  }
21635
21635
  if (this.activeToolCalls > 0) {
21636
21636
  logger.warn(
@@ -21655,21 +21655,21 @@ var init_mcp_custom_sse_server = __esm({
21655
21655
  }
21656
21656
  this.connections.clear();
21657
21657
  if (this.server) {
21658
- await new Promise((resolve15, reject) => {
21658
+ await new Promise((resolve19, reject) => {
21659
21659
  const timeout = setTimeout(() => {
21660
21660
  if (this.debug) {
21661
21661
  logger.debug(
21662
21662
  `[CustomToolsSSEServer:${this.sessionId}] Force closing server after timeout`
21663
21663
  );
21664
21664
  }
21665
- this.server?.close(() => resolve15());
21665
+ this.server?.close(() => resolve19());
21666
21666
  }, 5e3);
21667
21667
  this.server.close((error) => {
21668
21668
  clearTimeout(timeout);
21669
21669
  if (error) {
21670
21670
  reject(error);
21671
21671
  } else {
21672
- resolve15();
21672
+ resolve19();
21673
21673
  }
21674
21674
  });
21675
21675
  });
@@ -22104,7 +22104,7 @@ var init_mcp_custom_sse_server = __esm({
22104
22104
  logger.warn(
22105
22105
  `[CustomToolsSSEServer:${this.sessionId}] Tool ${toolName} failed (attempt ${attempt + 1}/${retryCount + 1}): ${errorMsg}. Retrying in ${delay}ms`
22106
22106
  );
22107
- await new Promise((resolve15) => setTimeout(resolve15, delay));
22107
+ await new Promise((resolve19) => setTimeout(resolve19, delay));
22108
22108
  attempt++;
22109
22109
  }
22110
22110
  }
@@ -22417,9 +22417,9 @@ var init_ai_check_provider = __esm({
22417
22417
  } else {
22418
22418
  resolvedPath = import_path8.default.resolve(process.cwd(), str);
22419
22419
  }
22420
- const fs25 = require("fs").promises;
22420
+ const fs29 = require("fs").promises;
22421
22421
  try {
22422
- const stat2 = await fs25.stat(resolvedPath);
22422
+ const stat2 = await fs29.stat(resolvedPath);
22423
22423
  return stat2.isFile();
22424
22424
  } catch {
22425
22425
  return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);
@@ -28521,14 +28521,14 @@ var require_util = __commonJS({
28521
28521
  }
28522
28522
  const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
28523
28523
  let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`;
28524
- let path29 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
28524
+ let path33 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
28525
28525
  if (origin.endsWith("/")) {
28526
28526
  origin = origin.substring(0, origin.length - 1);
28527
28527
  }
28528
- if (path29 && !path29.startsWith("/")) {
28529
- path29 = `/${path29}`;
28528
+ if (path33 && !path33.startsWith("/")) {
28529
+ path33 = `/${path33}`;
28530
28530
  }
28531
- url = new URL(origin + path29);
28531
+ url = new URL(origin + path33);
28532
28532
  }
28533
28533
  return url;
28534
28534
  }
@@ -30142,20 +30142,20 @@ var require_parseParams = __commonJS({
30142
30142
  var require_basename = __commonJS({
30143
30143
  "node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) {
30144
30144
  "use strict";
30145
- module2.exports = function basename4(path29) {
30146
- if (typeof path29 !== "string") {
30145
+ module2.exports = function basename4(path33) {
30146
+ if (typeof path33 !== "string") {
30147
30147
  return "";
30148
30148
  }
30149
- for (var i = path29.length - 1; i >= 0; --i) {
30150
- switch (path29.charCodeAt(i)) {
30149
+ for (var i = path33.length - 1; i >= 0; --i) {
30150
+ switch (path33.charCodeAt(i)) {
30151
30151
  case 47:
30152
30152
  // '/'
30153
30153
  case 92:
30154
- path29 = path29.slice(i + 1);
30155
- return path29 === ".." || path29 === "." ? "" : path29;
30154
+ path33 = path33.slice(i + 1);
30155
+ return path33 === ".." || path33 === "." ? "" : path33;
30156
30156
  }
30157
30157
  }
30158
- return path29 === ".." || path29 === "." ? "" : path29;
30158
+ return path33 === ".." || path33 === "." ? "" : path33;
30159
30159
  };
30160
30160
  }
30161
30161
  });
@@ -31159,11 +31159,11 @@ var require_util2 = __commonJS({
31159
31159
  var assert = require("assert");
31160
31160
  var { isUint8Array } = require("util/types");
31161
31161
  var supportedHashes = [];
31162
- var crypto7;
31162
+ var crypto9;
31163
31163
  try {
31164
- crypto7 = require("crypto");
31164
+ crypto9 = require("crypto");
31165
31165
  const possibleRelevantHashes = ["sha256", "sha384", "sha512"];
31166
- supportedHashes = crypto7.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
31166
+ supportedHashes = crypto9.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
31167
31167
  } catch {
31168
31168
  }
31169
31169
  function responseURL(response) {
@@ -31440,7 +31440,7 @@ var require_util2 = __commonJS({
31440
31440
  }
31441
31441
  }
31442
31442
  function bytesMatch(bytes, metadataList) {
31443
- if (crypto7 === void 0) {
31443
+ if (crypto9 === void 0) {
31444
31444
  return true;
31445
31445
  }
31446
31446
  const parsedMetadata = parseMetadata(metadataList);
@@ -31455,7 +31455,7 @@ var require_util2 = __commonJS({
31455
31455
  for (const item of metadata) {
31456
31456
  const algorithm = item.algo;
31457
31457
  const expectedValue = item.hash;
31458
- let actualValue = crypto7.createHash(algorithm).update(bytes).digest("base64");
31458
+ let actualValue = crypto9.createHash(algorithm).update(bytes).digest("base64");
31459
31459
  if (actualValue[actualValue.length - 1] === "=") {
31460
31460
  if (actualValue[actualValue.length - 2] === "=") {
31461
31461
  actualValue = actualValue.slice(0, -2);
@@ -31548,8 +31548,8 @@ var require_util2 = __commonJS({
31548
31548
  function createDeferredPromise() {
31549
31549
  let res;
31550
31550
  let rej;
31551
- const promise = new Promise((resolve15, reject) => {
31552
- res = resolve15;
31551
+ const promise = new Promise((resolve19, reject) => {
31552
+ res = resolve19;
31553
31553
  rej = reject;
31554
31554
  });
31555
31555
  return { promise, resolve: res, reject: rej };
@@ -32802,8 +32802,8 @@ var require_body = __commonJS({
32802
32802
  var { parseMIMEType, serializeAMimeType } = require_dataURL();
32803
32803
  var random;
32804
32804
  try {
32805
- const crypto7 = require("crypto");
32806
- random = (max) => crypto7.randomInt(0, max);
32805
+ const crypto9 = require("crypto");
32806
+ random = (max) => crypto9.randomInt(0, max);
32807
32807
  } catch {
32808
32808
  random = (max) => Math.floor(Math.random(max));
32809
32809
  }
@@ -33054,8 +33054,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r
33054
33054
  });
33055
33055
  }
33056
33056
  });
33057
- const busboyResolve = new Promise((resolve15, reject) => {
33058
- busboy.on("finish", resolve15);
33057
+ const busboyResolve = new Promise((resolve19, reject) => {
33058
+ busboy.on("finish", resolve19);
33059
33059
  busboy.on("error", (err) => reject(new TypeError(err)));
33060
33060
  });
33061
33061
  if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk);
@@ -33186,7 +33186,7 @@ var require_request = __commonJS({
33186
33186
  }
33187
33187
  var Request = class _Request {
33188
33188
  constructor(origin, {
33189
- path: path29,
33189
+ path: path33,
33190
33190
  method,
33191
33191
  body,
33192
33192
  headers,
@@ -33200,11 +33200,11 @@ var require_request = __commonJS({
33200
33200
  throwOnError,
33201
33201
  expectContinue
33202
33202
  }, handler) {
33203
- if (typeof path29 !== "string") {
33203
+ if (typeof path33 !== "string") {
33204
33204
  throw new InvalidArgumentError("path must be a string");
33205
- } else if (path29[0] !== "/" && !(path29.startsWith("http://") || path29.startsWith("https://")) && method !== "CONNECT") {
33205
+ } else if (path33[0] !== "/" && !(path33.startsWith("http://") || path33.startsWith("https://")) && method !== "CONNECT") {
33206
33206
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
33207
- } else if (invalidPathRegex.exec(path29) !== null) {
33207
+ } else if (invalidPathRegex.exec(path33) !== null) {
33208
33208
  throw new InvalidArgumentError("invalid request path");
33209
33209
  }
33210
33210
  if (typeof method !== "string") {
@@ -33267,7 +33267,7 @@ var require_request = __commonJS({
33267
33267
  this.completed = false;
33268
33268
  this.aborted = false;
33269
33269
  this.upgrade = upgrade || null;
33270
- this.path = query ? util.buildURL(path29, query) : path29;
33270
+ this.path = query ? util.buildURL(path33, query) : path33;
33271
33271
  this.origin = origin;
33272
33272
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
33273
33273
  this.blocking = blocking == null ? false : blocking;
@@ -33589,9 +33589,9 @@ var require_dispatcher_base = __commonJS({
33589
33589
  }
33590
33590
  close(callback) {
33591
33591
  if (callback === void 0) {
33592
- return new Promise((resolve15, reject) => {
33592
+ return new Promise((resolve19, reject) => {
33593
33593
  this.close((err, data) => {
33594
- return err ? reject(err) : resolve15(data);
33594
+ return err ? reject(err) : resolve19(data);
33595
33595
  });
33596
33596
  });
33597
33597
  }
@@ -33629,12 +33629,12 @@ var require_dispatcher_base = __commonJS({
33629
33629
  err = null;
33630
33630
  }
33631
33631
  if (callback === void 0) {
33632
- return new Promise((resolve15, reject) => {
33632
+ return new Promise((resolve19, reject) => {
33633
33633
  this.destroy(err, (err2, data) => {
33634
33634
  return err2 ? (
33635
33635
  /* istanbul ignore next: should never error */
33636
33636
  reject(err2)
33637
- ) : resolve15(data);
33637
+ ) : resolve19(data);
33638
33638
  });
33639
33639
  });
33640
33640
  }
@@ -34275,9 +34275,9 @@ var require_RedirectHandler = __commonJS({
34275
34275
  return this.handler.onHeaders(statusCode, headers, resume, statusText);
34276
34276
  }
34277
34277
  const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
34278
- const path29 = search ? `${pathname}${search}` : pathname;
34278
+ const path33 = search ? `${pathname}${search}` : pathname;
34279
34279
  this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
34280
- this.opts.path = path29;
34280
+ this.opts.path = path33;
34281
34281
  this.opts.origin = origin;
34282
34282
  this.opts.maxRedirections = 0;
34283
34283
  this.opts.query = null;
@@ -34696,16 +34696,16 @@ var require_client = __commonJS({
34696
34696
  return this[kNeedDrain] < 2;
34697
34697
  }
34698
34698
  async [kClose]() {
34699
- return new Promise((resolve15) => {
34699
+ return new Promise((resolve19) => {
34700
34700
  if (!this[kSize]) {
34701
- resolve15(null);
34701
+ resolve19(null);
34702
34702
  } else {
34703
- this[kClosedResolve] = resolve15;
34703
+ this[kClosedResolve] = resolve19;
34704
34704
  }
34705
34705
  });
34706
34706
  }
34707
34707
  async [kDestroy](err) {
34708
- return new Promise((resolve15) => {
34708
+ return new Promise((resolve19) => {
34709
34709
  const requests = this[kQueue].splice(this[kPendingIdx]);
34710
34710
  for (let i = 0; i < requests.length; i++) {
34711
34711
  const request = requests[i];
@@ -34716,7 +34716,7 @@ var require_client = __commonJS({
34716
34716
  this[kClosedResolve]();
34717
34717
  this[kClosedResolve] = null;
34718
34718
  }
34719
- resolve15();
34719
+ resolve19();
34720
34720
  };
34721
34721
  if (this[kHTTP2Session] != null) {
34722
34722
  util.destroy(this[kHTTP2Session], err);
@@ -35296,7 +35296,7 @@ var require_client = __commonJS({
35296
35296
  });
35297
35297
  }
35298
35298
  try {
35299
- const socket = await new Promise((resolve15, reject) => {
35299
+ const socket = await new Promise((resolve19, reject) => {
35300
35300
  client[kConnector]({
35301
35301
  host,
35302
35302
  hostname,
@@ -35308,7 +35308,7 @@ var require_client = __commonJS({
35308
35308
  if (err) {
35309
35309
  reject(err);
35310
35310
  } else {
35311
- resolve15(socket2);
35311
+ resolve19(socket2);
35312
35312
  }
35313
35313
  });
35314
35314
  });
@@ -35519,7 +35519,7 @@ var require_client = __commonJS({
35519
35519
  writeH2(client, client[kHTTP2Session], request);
35520
35520
  return;
35521
35521
  }
35522
- const { body, method, path: path29, host, upgrade, headers, blocking, reset } = request;
35522
+ const { body, method, path: path33, host, upgrade, headers, blocking, reset } = request;
35523
35523
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
35524
35524
  if (body && typeof body.read === "function") {
35525
35525
  body.read(0);
@@ -35569,7 +35569,7 @@ var require_client = __commonJS({
35569
35569
  if (blocking) {
35570
35570
  socket[kBlocking] = true;
35571
35571
  }
35572
- let header = `${method} ${path29} HTTP/1.1\r
35572
+ let header = `${method} ${path33} HTTP/1.1\r
35573
35573
  `;
35574
35574
  if (typeof host === "string") {
35575
35575
  header += `host: ${host}\r
@@ -35632,7 +35632,7 @@ upgrade: ${upgrade}\r
35632
35632
  return true;
35633
35633
  }
35634
35634
  function writeH2(client, session, request) {
35635
- const { body, method, path: path29, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
35635
+ const { body, method, path: path33, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
35636
35636
  let headers;
35637
35637
  if (typeof reqHeaders === "string") headers = Request[kHTTP2CopyHeaders](reqHeaders.trim());
35638
35638
  else headers = reqHeaders;
@@ -35675,7 +35675,7 @@ upgrade: ${upgrade}\r
35675
35675
  });
35676
35676
  return true;
35677
35677
  }
35678
- headers[HTTP2_HEADER_PATH] = path29;
35678
+ headers[HTTP2_HEADER_PATH] = path33;
35679
35679
  headers[HTTP2_HEADER_SCHEME] = "https";
35680
35680
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
35681
35681
  if (body && typeof body.read === "function") {
@@ -35932,12 +35932,12 @@ upgrade: ${upgrade}\r
35932
35932
  cb();
35933
35933
  }
35934
35934
  }
35935
- const waitForDrain = () => new Promise((resolve15, reject) => {
35935
+ const waitForDrain = () => new Promise((resolve19, reject) => {
35936
35936
  assert(callback === null);
35937
35937
  if (socket[kError]) {
35938
35938
  reject(socket[kError]);
35939
35939
  } else {
35940
- callback = resolve15;
35940
+ callback = resolve19;
35941
35941
  }
35942
35942
  });
35943
35943
  if (client[kHTTPConnVersion] === "h2") {
@@ -36283,8 +36283,8 @@ var require_pool_base = __commonJS({
36283
36283
  if (this[kQueue].isEmpty()) {
36284
36284
  return Promise.all(this[kClients].map((c) => c.close()));
36285
36285
  } else {
36286
- return new Promise((resolve15) => {
36287
- this[kClosedResolve] = resolve15;
36286
+ return new Promise((resolve19) => {
36287
+ this[kClosedResolve] = resolve19;
36288
36288
  });
36289
36289
  }
36290
36290
  }
@@ -36862,7 +36862,7 @@ var require_readable = __commonJS({
36862
36862
  if (this.closed) {
36863
36863
  return Promise.resolve(null);
36864
36864
  }
36865
- return new Promise((resolve15, reject) => {
36865
+ return new Promise((resolve19, reject) => {
36866
36866
  const signalListenerCleanup = signal ? util.addAbortListener(signal, () => {
36867
36867
  this.destroy();
36868
36868
  }) : noop;
@@ -36871,7 +36871,7 @@ var require_readable = __commonJS({
36871
36871
  if (signal && signal.aborted) {
36872
36872
  reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" }));
36873
36873
  } else {
36874
- resolve15(null);
36874
+ resolve19(null);
36875
36875
  }
36876
36876
  }).on("error", noop).on("data", function(chunk) {
36877
36877
  limit -= chunk.length;
@@ -36893,11 +36893,11 @@ var require_readable = __commonJS({
36893
36893
  throw new TypeError("unusable");
36894
36894
  }
36895
36895
  assert(!stream[kConsume]);
36896
- return new Promise((resolve15, reject) => {
36896
+ return new Promise((resolve19, reject) => {
36897
36897
  stream[kConsume] = {
36898
36898
  type,
36899
36899
  stream,
36900
- resolve: resolve15,
36900
+ resolve: resolve19,
36901
36901
  reject,
36902
36902
  length: 0,
36903
36903
  body: []
@@ -36932,12 +36932,12 @@ var require_readable = __commonJS({
36932
36932
  }
36933
36933
  }
36934
36934
  function consumeEnd(consume2) {
36935
- const { type, body, resolve: resolve15, stream, length } = consume2;
36935
+ const { type, body, resolve: resolve19, stream, length } = consume2;
36936
36936
  try {
36937
36937
  if (type === "text") {
36938
- resolve15(toUSVString(Buffer.concat(body)));
36938
+ resolve19(toUSVString(Buffer.concat(body)));
36939
36939
  } else if (type === "json") {
36940
- resolve15(JSON.parse(Buffer.concat(body)));
36940
+ resolve19(JSON.parse(Buffer.concat(body)));
36941
36941
  } else if (type === "arrayBuffer") {
36942
36942
  const dst = new Uint8Array(length);
36943
36943
  let pos = 0;
@@ -36945,12 +36945,12 @@ var require_readable = __commonJS({
36945
36945
  dst.set(buf, pos);
36946
36946
  pos += buf.byteLength;
36947
36947
  }
36948
- resolve15(dst.buffer);
36948
+ resolve19(dst.buffer);
36949
36949
  } else if (type === "blob") {
36950
36950
  if (!Blob2) {
36951
36951
  Blob2 = require("buffer").Blob;
36952
36952
  }
36953
- resolve15(new Blob2(body, { type: stream[kContentType] }));
36953
+ resolve19(new Blob2(body, { type: stream[kContentType] }));
36954
36954
  }
36955
36955
  consumeFinish(consume2);
36956
36956
  } catch (err) {
@@ -37207,9 +37207,9 @@ var require_api_request = __commonJS({
37207
37207
  };
37208
37208
  function request(opts, callback) {
37209
37209
  if (callback === void 0) {
37210
- return new Promise((resolve15, reject) => {
37210
+ return new Promise((resolve19, reject) => {
37211
37211
  request.call(this, opts, (err, data) => {
37212
- return err ? reject(err) : resolve15(data);
37212
+ return err ? reject(err) : resolve19(data);
37213
37213
  });
37214
37214
  });
37215
37215
  }
@@ -37382,9 +37382,9 @@ var require_api_stream = __commonJS({
37382
37382
  };
37383
37383
  function stream(opts, factory, callback) {
37384
37384
  if (callback === void 0) {
37385
- return new Promise((resolve15, reject) => {
37385
+ return new Promise((resolve19, reject) => {
37386
37386
  stream.call(this, opts, factory, (err, data) => {
37387
- return err ? reject(err) : resolve15(data);
37387
+ return err ? reject(err) : resolve19(data);
37388
37388
  });
37389
37389
  });
37390
37390
  }
@@ -37665,9 +37665,9 @@ var require_api_upgrade = __commonJS({
37665
37665
  };
37666
37666
  function upgrade(opts, callback) {
37667
37667
  if (callback === void 0) {
37668
- return new Promise((resolve15, reject) => {
37668
+ return new Promise((resolve19, reject) => {
37669
37669
  upgrade.call(this, opts, (err, data) => {
37670
- return err ? reject(err) : resolve15(data);
37670
+ return err ? reject(err) : resolve19(data);
37671
37671
  });
37672
37672
  });
37673
37673
  }
@@ -37756,9 +37756,9 @@ var require_api_connect = __commonJS({
37756
37756
  };
37757
37757
  function connect(opts, callback) {
37758
37758
  if (callback === void 0) {
37759
- return new Promise((resolve15, reject) => {
37759
+ return new Promise((resolve19, reject) => {
37760
37760
  connect.call(this, opts, (err, data) => {
37761
- return err ? reject(err) : resolve15(data);
37761
+ return err ? reject(err) : resolve19(data);
37762
37762
  });
37763
37763
  });
37764
37764
  }
@@ -37918,20 +37918,20 @@ var require_mock_utils = __commonJS({
37918
37918
  }
37919
37919
  return true;
37920
37920
  }
37921
- function safeUrl(path29) {
37922
- if (typeof path29 !== "string") {
37923
- return path29;
37921
+ function safeUrl(path33) {
37922
+ if (typeof path33 !== "string") {
37923
+ return path33;
37924
37924
  }
37925
- const pathSegments = path29.split("?");
37925
+ const pathSegments = path33.split("?");
37926
37926
  if (pathSegments.length !== 2) {
37927
- return path29;
37927
+ return path33;
37928
37928
  }
37929
37929
  const qp = new URLSearchParams(pathSegments.pop());
37930
37930
  qp.sort();
37931
37931
  return [...pathSegments, qp.toString()].join("?");
37932
37932
  }
37933
- function matchKey(mockDispatch2, { path: path29, method, body, headers }) {
37934
- const pathMatch = matchValue(mockDispatch2.path, path29);
37933
+ function matchKey(mockDispatch2, { path: path33, method, body, headers }) {
37934
+ const pathMatch = matchValue(mockDispatch2.path, path33);
37935
37935
  const methodMatch = matchValue(mockDispatch2.method, method);
37936
37936
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
37937
37937
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -37949,7 +37949,7 @@ var require_mock_utils = __commonJS({
37949
37949
  function getMockDispatch(mockDispatches, key) {
37950
37950
  const basePath = key.query ? buildURL(key.path, key.query) : key.path;
37951
37951
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
37952
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path29 }) => matchValue(safeUrl(path29), resolvedPath));
37952
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path33 }) => matchValue(safeUrl(path33), resolvedPath));
37953
37953
  if (matchedMockDispatches.length === 0) {
37954
37954
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
37955
37955
  }
@@ -37986,9 +37986,9 @@ var require_mock_utils = __commonJS({
37986
37986
  }
37987
37987
  }
37988
37988
  function buildKey(opts) {
37989
- const { path: path29, method, body, headers, query } = opts;
37989
+ const { path: path33, method, body, headers, query } = opts;
37990
37990
  return {
37991
- path: path29,
37991
+ path: path33,
37992
37992
  method,
37993
37993
  body,
37994
37994
  headers,
@@ -38437,10 +38437,10 @@ var require_pending_interceptors_formatter = __commonJS({
38437
38437
  }
38438
38438
  format(pendingInterceptors) {
38439
38439
  const withPrettyHeaders = pendingInterceptors.map(
38440
- ({ method, path: path29, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
38440
+ ({ method, path: path33, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
38441
38441
  Method: method,
38442
38442
  Origin: origin,
38443
- Path: path29,
38443
+ Path: path33,
38444
38444
  "Status code": statusCode,
38445
38445
  Persistent: persist ? "\u2705" : "\u274C",
38446
38446
  Invocations: timesInvoked,
@@ -41381,7 +41381,7 @@ var require_fetch = __commonJS({
41381
41381
  async function dispatch({ body }) {
41382
41382
  const url = requestCurrentURL(request);
41383
41383
  const agent = fetchParams.controller.dispatcher;
41384
- return new Promise((resolve15, reject) => agent.dispatch(
41384
+ return new Promise((resolve19, reject) => agent.dispatch(
41385
41385
  {
41386
41386
  path: url.pathname + url.search,
41387
41387
  origin: url.origin,
@@ -41457,7 +41457,7 @@ var require_fetch = __commonJS({
41457
41457
  }
41458
41458
  }
41459
41459
  }
41460
- resolve15({
41460
+ resolve19({
41461
41461
  status,
41462
41462
  statusText,
41463
41463
  headersList: headers[kHeadersList],
@@ -41500,7 +41500,7 @@ var require_fetch = __commonJS({
41500
41500
  const val = headersList[n + 1].toString("latin1");
41501
41501
  headers[kHeadersList].append(key, val);
41502
41502
  }
41503
- resolve15({
41503
+ resolve19({
41504
41504
  status,
41505
41505
  statusText: STATUS_CODES[status],
41506
41506
  headersList: headers[kHeadersList],
@@ -43061,8 +43061,8 @@ var require_util6 = __commonJS({
43061
43061
  }
43062
43062
  }
43063
43063
  }
43064
- function validateCookiePath(path29) {
43065
- for (const char of path29) {
43064
+ function validateCookiePath(path33) {
43065
+ for (const char of path33) {
43066
43066
  const code = char.charCodeAt(0);
43067
43067
  if (code < 33 || char === ";") {
43068
43068
  throw new Error("Invalid cookie path");
@@ -43859,9 +43859,9 @@ var require_connection = __commonJS({
43859
43859
  channels.open = diagnosticsChannel.channel("undici:websocket:open");
43860
43860
  channels.close = diagnosticsChannel.channel("undici:websocket:close");
43861
43861
  channels.socketError = diagnosticsChannel.channel("undici:websocket:socket_error");
43862
- var crypto7;
43862
+ var crypto9;
43863
43863
  try {
43864
- crypto7 = require("crypto");
43864
+ crypto9 = require("crypto");
43865
43865
  } catch {
43866
43866
  }
43867
43867
  function establishWebSocketConnection(url, protocols, ws, onEstablish, options) {
@@ -43880,7 +43880,7 @@ var require_connection = __commonJS({
43880
43880
  const headersList = new Headers(options.headers)[kHeadersList];
43881
43881
  request.headersList = headersList;
43882
43882
  }
43883
- const keyValue = crypto7.randomBytes(16).toString("base64");
43883
+ const keyValue = crypto9.randomBytes(16).toString("base64");
43884
43884
  request.headersList.append("sec-websocket-key", keyValue);
43885
43885
  request.headersList.append("sec-websocket-version", "13");
43886
43886
  for (const protocol of protocols) {
@@ -43909,7 +43909,7 @@ var require_connection = __commonJS({
43909
43909
  return;
43910
43910
  }
43911
43911
  const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
43912
- const digest = crypto7.createHash("sha1").update(keyValue + uid).digest("base64");
43912
+ const digest = crypto9.createHash("sha1").update(keyValue + uid).digest("base64");
43913
43913
  if (secWSAccept !== digest) {
43914
43914
  failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header.");
43915
43915
  return;
@@ -43989,9 +43989,9 @@ var require_frame = __commonJS({
43989
43989
  "node_modules/undici/lib/websocket/frame.js"(exports2, module2) {
43990
43990
  "use strict";
43991
43991
  var { maxUnsigned16Bit } = require_constants5();
43992
- var crypto7;
43992
+ var crypto9;
43993
43993
  try {
43994
- crypto7 = require("crypto");
43994
+ crypto9 = require("crypto");
43995
43995
  } catch {
43996
43996
  }
43997
43997
  var WebsocketFrameSend = class {
@@ -44000,7 +44000,7 @@ var require_frame = __commonJS({
44000
44000
  */
44001
44001
  constructor(data) {
44002
44002
  this.frameData = data;
44003
- this.maskKey = crypto7.randomBytes(4);
44003
+ this.maskKey = crypto9.randomBytes(4);
44004
44004
  }
44005
44005
  createFrame(opcode) {
44006
44006
  const bodyLength = this.frameData?.byteLength ?? 0;
@@ -44742,11 +44742,11 @@ var require_undici = __commonJS({
44742
44742
  if (typeof opts.path !== "string") {
44743
44743
  throw new InvalidArgumentError("invalid opts.path");
44744
44744
  }
44745
- let path29 = opts.path;
44745
+ let path33 = opts.path;
44746
44746
  if (!opts.path.startsWith("/")) {
44747
- path29 = `/${path29}`;
44747
+ path33 = `/${path33}`;
44748
44748
  }
44749
- url = new URL(util.parseOrigin(url).origin + path29);
44749
+ url = new URL(util.parseOrigin(url).origin + path33);
44750
44750
  } else {
44751
44751
  if (!opts) {
44752
44752
  opts = typeof url === "object" ? url : {};
@@ -45295,7 +45295,7 @@ var init_mcp_check_provider = __esm({
45295
45295
  logger.warn(
45296
45296
  `MCP ${transportName} failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`
45297
45297
  );
45298
- await new Promise((resolve15) => setTimeout(resolve15, delay));
45298
+ await new Promise((resolve19) => setTimeout(resolve19, delay));
45299
45299
  attempt += 1;
45300
45300
  } finally {
45301
45301
  try {
@@ -45588,7 +45588,7 @@ async function acquirePromptLock() {
45588
45588
  );
45589
45589
  }, 1e4);
45590
45590
  try {
45591
- await new Promise((resolve15) => waiters.push(resolve15));
45591
+ await new Promise((resolve19) => waiters.push(resolve19));
45592
45592
  } finally {
45593
45593
  clearInterval(reminder);
45594
45594
  const waitedMs = Date.now() - queuedAt;
@@ -45607,7 +45607,7 @@ function releasePromptLock() {
45607
45607
  }
45608
45608
  async function interactivePrompt(options) {
45609
45609
  await acquirePromptLock();
45610
- return new Promise((resolve15, reject) => {
45610
+ return new Promise((resolve19, reject) => {
45611
45611
  const dbg = process.env.VISOR_DEBUG === "true";
45612
45612
  try {
45613
45613
  if (dbg) {
@@ -45694,12 +45694,12 @@ async function interactivePrompt(options) {
45694
45694
  };
45695
45695
  const finish = (value) => {
45696
45696
  cleanup();
45697
- resolve15(value);
45697
+ resolve19(value);
45698
45698
  };
45699
45699
  if (options.timeout && options.timeout > 0) {
45700
45700
  timeoutId = setTimeout(() => {
45701
45701
  cleanup();
45702
- if (defaultValue !== void 0) return resolve15(defaultValue);
45702
+ if (defaultValue !== void 0) return resolve19(defaultValue);
45703
45703
  return reject(new Error("Input timeout"));
45704
45704
  }, options.timeout);
45705
45705
  }
@@ -45831,7 +45831,7 @@ async function interactivePrompt(options) {
45831
45831
  });
45832
45832
  }
45833
45833
  async function simplePrompt(prompt) {
45834
- return new Promise((resolve15) => {
45834
+ return new Promise((resolve19) => {
45835
45835
  const rl = readline.createInterface({
45836
45836
  input: process.stdin,
45837
45837
  output: process.stdout
@@ -45847,7 +45847,7 @@ async function simplePrompt(prompt) {
45847
45847
  rl.question(`${prompt}
45848
45848
  > `, (answer) => {
45849
45849
  rl.close();
45850
- resolve15(answer.trim());
45850
+ resolve19(answer.trim());
45851
45851
  });
45852
45852
  });
45853
45853
  }
@@ -46015,7 +46015,7 @@ function isStdinAvailable() {
46015
46015
  return !process.stdin.isTTY;
46016
46016
  }
46017
46017
  async function readStdin(timeout, maxSize = 1024 * 1024) {
46018
- return new Promise((resolve15, reject) => {
46018
+ return new Promise((resolve19, reject) => {
46019
46019
  let data = "";
46020
46020
  let timeoutId;
46021
46021
  if (timeout) {
@@ -46042,7 +46042,7 @@ async function readStdin(timeout, maxSize = 1024 * 1024) {
46042
46042
  };
46043
46043
  const onEnd = () => {
46044
46044
  cleanup();
46045
- resolve15(data.trim());
46045
+ resolve19(data.trim());
46046
46046
  };
46047
46047
  const onError = (err) => {
46048
46048
  cleanup();
@@ -50733,23 +50733,23 @@ __export(renderer_schema_exports, {
50733
50733
  });
50734
50734
  async function loadRendererSchema(name) {
50735
50735
  try {
50736
- const fs25 = await import("fs/promises");
50737
- const path29 = await import("path");
50736
+ const fs29 = await import("fs/promises");
50737
+ const path33 = await import("path");
50738
50738
  const sanitized = String(name).replace(/[^a-zA-Z0-9-]/g, "");
50739
50739
  if (!sanitized) return void 0;
50740
50740
  const candidates = [
50741
50741
  // When bundled with ncc, __dirname is dist/ and output/ is at dist/output/
50742
- path29.join(__dirname, "output", sanitized, "schema.json"),
50742
+ path33.join(__dirname, "output", sanitized, "schema.json"),
50743
50743
  // When running from source, __dirname is src/state-machine/dispatch/ and output/ is at output/
50744
- path29.join(__dirname, "..", "..", "output", sanitized, "schema.json"),
50744
+ path33.join(__dirname, "..", "..", "output", sanitized, "schema.json"),
50745
50745
  // When running from a checkout with output/ folder copied to CWD
50746
- path29.join(process.cwd(), "output", sanitized, "schema.json"),
50746
+ path33.join(process.cwd(), "output", sanitized, "schema.json"),
50747
50747
  // Fallback: cwd/dist/output/
50748
- path29.join(process.cwd(), "dist", "output", sanitized, "schema.json")
50748
+ path33.join(process.cwd(), "dist", "output", sanitized, "schema.json")
50749
50749
  ];
50750
50750
  for (const p of candidates) {
50751
50751
  try {
50752
- const raw = await fs25.readFile(p, "utf-8");
50752
+ const raw = await fs29.readFile(p, "utf-8");
50753
50753
  return JSON.parse(raw);
50754
50754
  } catch {
50755
50755
  }
@@ -53190,8 +53190,8 @@ function updateStats2(results, state, isForEachIteration = false) {
53190
53190
  async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
53191
53191
  try {
53192
53192
  const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
53193
- const fs25 = await import("fs/promises");
53194
- const path29 = await import("path");
53193
+ const fs29 = await import("fs/promises");
53194
+ const path33 = await import("path");
53195
53195
  const schemaRaw = checkConfig.schema || "plain";
53196
53196
  const schema = typeof schemaRaw === "string" && !schemaRaw.includes("{{") && !schemaRaw.includes("{%") ? schemaRaw : typeof schemaRaw === "object" ? "code-review" : "plain";
53197
53197
  let templateContent;
@@ -53200,27 +53200,27 @@ async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
53200
53200
  logger.debug(`[LevelDispatch] Using inline template for ${checkId}`);
53201
53201
  } else if (checkConfig.template && checkConfig.template.file) {
53202
53202
  const file = String(checkConfig.template.file);
53203
- const resolved = path29.resolve(process.cwd(), file);
53204
- templateContent = await fs25.readFile(resolved, "utf-8");
53203
+ const resolved = path33.resolve(process.cwd(), file);
53204
+ templateContent = await fs29.readFile(resolved, "utf-8");
53205
53205
  logger.debug(`[LevelDispatch] Using template file for ${checkId}: ${resolved}`);
53206
53206
  } else if (schema && schema !== "plain") {
53207
53207
  const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
53208
53208
  if (sanitized) {
53209
53209
  const candidatePaths = [
53210
- path29.join(__dirname, "output", sanitized, "template.liquid"),
53210
+ path33.join(__dirname, "output", sanitized, "template.liquid"),
53211
53211
  // bundled: dist/output/
53212
- path29.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
53212
+ path33.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
53213
53213
  // source (from state-machine/states)
53214
- path29.join(__dirname, "..", "..", "..", "output", sanitized, "template.liquid"),
53214
+ path33.join(__dirname, "..", "..", "..", "output", sanitized, "template.liquid"),
53215
53215
  // source (alternate)
53216
- path29.join(process.cwd(), "output", sanitized, "template.liquid"),
53216
+ path33.join(process.cwd(), "output", sanitized, "template.liquid"),
53217
53217
  // fallback: cwd/output/
53218
- path29.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
53218
+ path33.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
53219
53219
  // fallback: cwd/dist/output/
53220
53220
  ];
53221
53221
  for (const p of candidatePaths) {
53222
53222
  try {
53223
- templateContent = await fs25.readFile(p, "utf-8");
53223
+ templateContent = await fs29.readFile(p, "utf-8");
53224
53224
  if (templateContent) {
53225
53225
  logger.debug(`[LevelDispatch] Using schema template for ${checkId}: ${p}`);
53226
53226
  break;
@@ -55360,8 +55360,8 @@ var init_workspace_manager = __esm({
55360
55360
  );
55361
55361
  if (this.cleanupRequested && this.activeOperations === 0) {
55362
55362
  logger.debug(`[Workspace] All references released, proceeding with deferred cleanup`);
55363
- for (const resolve15 of this.cleanupResolvers) {
55364
- resolve15();
55363
+ for (const resolve19 of this.cleanupResolvers) {
55364
+ resolve19();
55365
55365
  }
55366
55366
  this.cleanupResolvers = [];
55367
55367
  }
@@ -55540,19 +55540,19 @@ var init_workspace_manager = __esm({
55540
55540
  );
55541
55541
  this.cleanupRequested = true;
55542
55542
  await Promise.race([
55543
- new Promise((resolve15) => {
55543
+ new Promise((resolve19) => {
55544
55544
  if (this.activeOperations === 0) {
55545
- resolve15();
55545
+ resolve19();
55546
55546
  } else {
55547
- this.cleanupResolvers.push(resolve15);
55547
+ this.cleanupResolvers.push(resolve19);
55548
55548
  }
55549
55549
  }),
55550
- new Promise((resolve15) => {
55550
+ new Promise((resolve19) => {
55551
55551
  setTimeout(() => {
55552
55552
  logger.warn(
55553
55553
  `[Workspace] Cleanup timeout after ${timeout}ms, proceeding anyway (${this.activeOperations} operations still active)`
55554
55554
  );
55555
- resolve15();
55555
+ resolve19();
55556
55556
  }, timeout);
55557
55557
  })
55558
55558
  ]);
@@ -55946,8 +55946,8 @@ var init_fair_concurrency_limiter = __esm({
55946
55946
  );
55947
55947
  const queuedAt = Date.now();
55948
55948
  const effectiveTimeout = queueTimeout ?? 12e4;
55949
- return new Promise((resolve15, reject) => {
55950
- const entry = { resolve: resolve15, reject, queuedAt };
55949
+ return new Promise((resolve19, reject) => {
55950
+ const entry = { resolve: resolve19, reject, queuedAt };
55951
55951
  entry.reminder = setInterval(() => {
55952
55952
  const waited = Math.round((Date.now() - queuedAt) / 1e3);
55953
55953
  const curQueued = this._totalQueued();
@@ -56254,6 +56254,1380 @@ var init_build_engine_context = __esm({
56254
56254
  }
56255
56255
  });
56256
56256
 
56257
+ // src/policy/default-engine.ts
56258
+ var DefaultPolicyEngine;
56259
+ var init_default_engine = __esm({
56260
+ "src/policy/default-engine.ts"() {
56261
+ "use strict";
56262
+ DefaultPolicyEngine = class {
56263
+ async initialize(_config) {
56264
+ }
56265
+ async evaluateCheckExecution(_checkId, _checkConfig) {
56266
+ return { allowed: true };
56267
+ }
56268
+ async evaluateToolInvocation(_serverName, _methodName, _transport) {
56269
+ return { allowed: true };
56270
+ }
56271
+ async evaluateCapabilities(_checkId, _capabilities) {
56272
+ return { allowed: true };
56273
+ }
56274
+ async shutdown() {
56275
+ }
56276
+ };
56277
+ }
56278
+ });
56279
+
56280
+ // src/enterprise/license/validator.ts
56281
+ var validator_exports = {};
56282
+ __export(validator_exports, {
56283
+ LicenseValidator: () => LicenseValidator
56284
+ });
56285
+ var crypto3, fs21, path26, LicenseValidator;
56286
+ var init_validator = __esm({
56287
+ "src/enterprise/license/validator.ts"() {
56288
+ "use strict";
56289
+ crypto3 = __toESM(require("crypto"));
56290
+ fs21 = __toESM(require("fs"));
56291
+ path26 = __toESM(require("path"));
56292
+ LicenseValidator = class _LicenseValidator {
56293
+ /** Ed25519 public key for license verification (PEM format). */
56294
+ static PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAI/Zd08EFmgIdrDm/HXd0l3/5GBt7R1PrdvhdmEXhJlU=\n-----END PUBLIC KEY-----\n";
56295
+ cache = null;
56296
+ static CACHE_TTL = 5 * 60 * 1e3;
56297
+ // 5 minutes
56298
+ static GRACE_PERIOD = 72 * 3600 * 1e3;
56299
+ // 72 hours after expiry
56300
+ /**
56301
+ * Load and validate license from environment or file.
56302
+ *
56303
+ * Resolution order:
56304
+ * 1. VISOR_LICENSE env var (JWT string)
56305
+ * 2. VISOR_LICENSE_FILE env var (path to file)
56306
+ * 3. .visor-license in project root (cwd)
56307
+ * 4. .visor-license in ~/.config/visor/
56308
+ */
56309
+ async loadAndValidate() {
56310
+ if (this.cache && Date.now() - this.cache.validatedAt < _LicenseValidator.CACHE_TTL) {
56311
+ return this.cache.payload;
56312
+ }
56313
+ const token = this.resolveToken();
56314
+ if (!token) return null;
56315
+ const payload = this.verifyAndDecode(token);
56316
+ if (!payload) return null;
56317
+ this.cache = { payload, validatedAt: Date.now() };
56318
+ return payload;
56319
+ }
56320
+ /** Check if a specific feature is licensed */
56321
+ hasFeature(feature) {
56322
+ if (!this.cache) return false;
56323
+ return this.cache.payload.features.includes(feature);
56324
+ }
56325
+ /** Check if license is valid (with grace period) */
56326
+ isValid() {
56327
+ if (!this.cache) return false;
56328
+ const now = Date.now();
56329
+ const expiryMs = this.cache.payload.exp * 1e3;
56330
+ return now < expiryMs + _LicenseValidator.GRACE_PERIOD;
56331
+ }
56332
+ /** Check if the license is within its grace period (expired but still valid) */
56333
+ isInGracePeriod() {
56334
+ if (!this.cache) return false;
56335
+ const now = Date.now();
56336
+ const expiryMs = this.cache.payload.exp * 1e3;
56337
+ return now >= expiryMs && now < expiryMs + _LicenseValidator.GRACE_PERIOD;
56338
+ }
56339
+ resolveToken() {
56340
+ if (process.env.VISOR_LICENSE) {
56341
+ return process.env.VISOR_LICENSE.trim();
56342
+ }
56343
+ if (process.env.VISOR_LICENSE_FILE) {
56344
+ const resolved = path26.resolve(process.env.VISOR_LICENSE_FILE);
56345
+ const home2 = process.env.HOME || process.env.USERPROFILE || "";
56346
+ const allowedPrefixes = [path26.normalize(process.cwd())];
56347
+ if (home2) allowedPrefixes.push(path26.normalize(path26.join(home2, ".config", "visor")));
56348
+ let realPath;
56349
+ try {
56350
+ realPath = fs21.realpathSync(resolved);
56351
+ } catch {
56352
+ return null;
56353
+ }
56354
+ const isSafe = allowedPrefixes.some(
56355
+ (prefix) => realPath === prefix || realPath.startsWith(prefix + path26.sep)
56356
+ );
56357
+ if (!isSafe) return null;
56358
+ return this.readFile(realPath);
56359
+ }
56360
+ const cwdPath = path26.join(process.cwd(), ".visor-license");
56361
+ const cwdToken = this.readFile(cwdPath);
56362
+ if (cwdToken) return cwdToken;
56363
+ const home = process.env.HOME || process.env.USERPROFILE || "";
56364
+ if (home) {
56365
+ const configPath = path26.join(home, ".config", "visor", ".visor-license");
56366
+ const configToken = this.readFile(configPath);
56367
+ if (configToken) return configToken;
56368
+ }
56369
+ return null;
56370
+ }
56371
+ readFile(filePath) {
56372
+ try {
56373
+ return fs21.readFileSync(filePath, "utf-8").trim();
56374
+ } catch {
56375
+ return null;
56376
+ }
56377
+ }
56378
+ verifyAndDecode(token) {
56379
+ try {
56380
+ const parts = token.split(".");
56381
+ if (parts.length !== 3) return null;
56382
+ const [headerB64, payloadB64, signatureB64] = parts;
56383
+ const header = JSON.parse(Buffer.from(headerB64, "base64url").toString());
56384
+ if (header.alg !== "EdDSA") return null;
56385
+ const data = `${headerB64}.${payloadB64}`;
56386
+ const signature = Buffer.from(signatureB64, "base64url");
56387
+ const publicKey = crypto3.createPublicKey(_LicenseValidator.PUBLIC_KEY);
56388
+ if (publicKey.asymmetricKeyType !== "ed25519") {
56389
+ return null;
56390
+ }
56391
+ const isValid = crypto3.verify(null, Buffer.from(data), publicKey, signature);
56392
+ if (!isValid) return null;
56393
+ const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
56394
+ if (!payload.org || !Array.isArray(payload.features) || typeof payload.exp !== "number" || typeof payload.iat !== "number" || !payload.sub) {
56395
+ return null;
56396
+ }
56397
+ const now = Date.now();
56398
+ const expiryMs = payload.exp * 1e3;
56399
+ if (now >= expiryMs + _LicenseValidator.GRACE_PERIOD) {
56400
+ return null;
56401
+ }
56402
+ return payload;
56403
+ } catch {
56404
+ return null;
56405
+ }
56406
+ }
56407
+ };
56408
+ }
56409
+ });
56410
+
56411
+ // src/enterprise/policy/opa-compiler.ts
56412
+ var fs22, path27, os2, crypto4, import_child_process8, OpaCompiler;
56413
+ var init_opa_compiler = __esm({
56414
+ "src/enterprise/policy/opa-compiler.ts"() {
56415
+ "use strict";
56416
+ fs22 = __toESM(require("fs"));
56417
+ path27 = __toESM(require("path"));
56418
+ os2 = __toESM(require("os"));
56419
+ crypto4 = __toESM(require("crypto"));
56420
+ import_child_process8 = require("child_process");
56421
+ OpaCompiler = class _OpaCompiler {
56422
+ static CACHE_DIR = path27.join(os2.tmpdir(), "visor-opa-cache");
56423
+ /**
56424
+ * Resolve the input paths to WASM bytes.
56425
+ *
56426
+ * Strategy:
56427
+ * 1. If any path is a .wasm file, read it directly
56428
+ * 2. If a directory contains policy.wasm, read it
56429
+ * 3. Otherwise, collect all .rego files and auto-compile via `opa build`
56430
+ */
56431
+ async resolveWasmBytes(paths) {
56432
+ const regoFiles = [];
56433
+ for (const p of paths) {
56434
+ const resolved = path27.resolve(p);
56435
+ if (path27.normalize(resolved).includes("..")) {
56436
+ throw new Error(`Policy path contains traversal sequences: ${p}`);
56437
+ }
56438
+ if (resolved.endsWith(".wasm") && fs22.existsSync(resolved)) {
56439
+ return fs22.readFileSync(resolved);
56440
+ }
56441
+ if (!fs22.existsSync(resolved)) continue;
56442
+ const stat2 = fs22.statSync(resolved);
56443
+ if (stat2.isDirectory()) {
56444
+ const wasmCandidate = path27.join(resolved, "policy.wasm");
56445
+ if (fs22.existsSync(wasmCandidate)) {
56446
+ return fs22.readFileSync(wasmCandidate);
56447
+ }
56448
+ const files = fs22.readdirSync(resolved);
56449
+ for (const f of files) {
56450
+ if (f.endsWith(".rego")) {
56451
+ regoFiles.push(path27.join(resolved, f));
56452
+ }
56453
+ }
56454
+ } else if (resolved.endsWith(".rego")) {
56455
+ regoFiles.push(resolved);
56456
+ }
56457
+ }
56458
+ if (regoFiles.length === 0) {
56459
+ throw new Error(
56460
+ `OPA WASM evaluator: no .wasm bundle or .rego files found in: ${paths.join(", ")}`
56461
+ );
56462
+ }
56463
+ return this.compileRego(regoFiles);
56464
+ }
56465
+ /**
56466
+ * Auto-compile .rego files to a WASM bundle using the `opa` CLI.
56467
+ *
56468
+ * Caches the compiled bundle based on a content hash of all input .rego files
56469
+ * so subsequent runs skip compilation if policies haven't changed.
56470
+ */
56471
+ compileRego(regoFiles) {
56472
+ try {
56473
+ (0, import_child_process8.execFileSync)("opa", ["version"], { stdio: "pipe" });
56474
+ } catch {
56475
+ throw new Error(
56476
+ "OPA CLI (`opa`) not found on PATH. Install it from https://www.openpolicyagent.org/docs/latest/#running-opa\nOr pre-compile your .rego files: opa build -t wasm -e visor -o bundle.tar.gz " + regoFiles.join(" ")
56477
+ );
56478
+ }
56479
+ const hash = crypto4.createHash("sha256");
56480
+ for (const f of regoFiles.sort()) {
56481
+ hash.update(fs22.readFileSync(f));
56482
+ hash.update(f);
56483
+ }
56484
+ const cacheKey = hash.digest("hex").slice(0, 16);
56485
+ const cacheDir = _OpaCompiler.CACHE_DIR;
56486
+ const cachedWasm = path27.join(cacheDir, `${cacheKey}.wasm`);
56487
+ if (fs22.existsSync(cachedWasm)) {
56488
+ return fs22.readFileSync(cachedWasm);
56489
+ }
56490
+ fs22.mkdirSync(cacheDir, { recursive: true });
56491
+ const bundleTar = path27.join(cacheDir, `${cacheKey}-bundle.tar.gz`);
56492
+ try {
56493
+ const args = [
56494
+ "build",
56495
+ "-t",
56496
+ "wasm",
56497
+ "-e",
56498
+ "visor",
56499
+ // entrypoint: the visor package tree
56500
+ "-o",
56501
+ bundleTar,
56502
+ ...regoFiles
56503
+ ];
56504
+ (0, import_child_process8.execFileSync)("opa", args, {
56505
+ stdio: "pipe",
56506
+ timeout: 3e4
56507
+ });
56508
+ } catch (err) {
56509
+ const stderr = err?.stderr?.toString() || "";
56510
+ throw new Error(
56511
+ `Failed to compile .rego files to WASM:
56512
+ ${stderr}
56513
+ Ensure your .rego files are valid and the \`opa\` CLI is installed.`
56514
+ );
56515
+ }
56516
+ try {
56517
+ (0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "/policy.wasm"], {
56518
+ stdio: "pipe"
56519
+ });
56520
+ const extractedWasm = path27.join(cacheDir, "policy.wasm");
56521
+ if (fs22.existsSync(extractedWasm)) {
56522
+ fs22.renameSync(extractedWasm, cachedWasm);
56523
+ }
56524
+ } catch {
56525
+ try {
56526
+ (0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "policy.wasm"], {
56527
+ stdio: "pipe"
56528
+ });
56529
+ const extractedWasm = path27.join(cacheDir, "policy.wasm");
56530
+ if (fs22.existsSync(extractedWasm)) {
56531
+ fs22.renameSync(extractedWasm, cachedWasm);
56532
+ }
56533
+ } catch (err2) {
56534
+ throw new Error(`Failed to extract policy.wasm from OPA bundle: ${err2?.message || err2}`);
56535
+ }
56536
+ }
56537
+ try {
56538
+ fs22.unlinkSync(bundleTar);
56539
+ } catch {
56540
+ }
56541
+ if (!fs22.existsSync(cachedWasm)) {
56542
+ throw new Error("OPA build succeeded but policy.wasm was not found in the bundle");
56543
+ }
56544
+ return fs22.readFileSync(cachedWasm);
56545
+ }
56546
+ };
56547
+ }
56548
+ });
56549
+
56550
+ // src/enterprise/policy/opa-wasm-evaluator.ts
56551
+ var fs23, path28, OpaWasmEvaluator;
56552
+ var init_opa_wasm_evaluator = __esm({
56553
+ "src/enterprise/policy/opa-wasm-evaluator.ts"() {
56554
+ "use strict";
56555
+ fs23 = __toESM(require("fs"));
56556
+ path28 = __toESM(require("path"));
56557
+ init_opa_compiler();
56558
+ OpaWasmEvaluator = class {
56559
+ policy = null;
56560
+ dataDocument = {};
56561
+ compiler = new OpaCompiler();
56562
+ async initialize(rulesPath) {
56563
+ const paths = Array.isArray(rulesPath) ? rulesPath : [rulesPath];
56564
+ const wasmBytes = await this.compiler.resolveWasmBytes(paths);
56565
+ try {
56566
+ const { createRequire } = require("module");
56567
+ const runtimeRequire = createRequire(__filename);
56568
+ const opaWasm = runtimeRequire("@open-policy-agent/opa-wasm");
56569
+ const loadPolicy = opaWasm.loadPolicy || opaWasm.default?.loadPolicy;
56570
+ if (!loadPolicy) {
56571
+ throw new Error("loadPolicy not found in @open-policy-agent/opa-wasm");
56572
+ }
56573
+ this.policy = await loadPolicy(wasmBytes);
56574
+ } catch (err) {
56575
+ if (err?.code === "MODULE_NOT_FOUND" || err?.code === "ERR_MODULE_NOT_FOUND") {
56576
+ throw new Error(
56577
+ "OPA WASM evaluator requires @open-policy-agent/opa-wasm. Install it with: npm install @open-policy-agent/opa-wasm"
56578
+ );
56579
+ }
56580
+ throw err;
56581
+ }
56582
+ }
56583
+ /**
56584
+ * Load external data from a JSON file to use as the OPA data document.
56585
+ * The loaded data will be passed to `policy.setData()` during evaluation,
56586
+ * making it available in Rego via `data.<key>`.
56587
+ */
56588
+ loadData(dataPath) {
56589
+ const resolved = path28.resolve(dataPath);
56590
+ if (path28.normalize(resolved).includes("..")) {
56591
+ throw new Error(`Data path contains traversal sequences: ${dataPath}`);
56592
+ }
56593
+ if (!fs23.existsSync(resolved)) {
56594
+ throw new Error(`OPA data file not found: ${resolved}`);
56595
+ }
56596
+ const stat2 = fs23.statSync(resolved);
56597
+ if (stat2.size > 10 * 1024 * 1024) {
56598
+ throw new Error(`OPA data file exceeds 10MB limit: ${resolved} (${stat2.size} bytes)`);
56599
+ }
56600
+ const raw = fs23.readFileSync(resolved, "utf-8");
56601
+ try {
56602
+ const parsed = JSON.parse(raw);
56603
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
56604
+ throw new Error("OPA data file must contain a JSON object (not an array or primitive)");
56605
+ }
56606
+ this.dataDocument = parsed;
56607
+ } catch (err) {
56608
+ if (err.message.startsWith("OPA data file must")) {
56609
+ throw err;
56610
+ }
56611
+ throw new Error(`Failed to parse OPA data file ${resolved}: ${err.message}`);
56612
+ }
56613
+ }
56614
+ async evaluate(input) {
56615
+ if (!this.policy) {
56616
+ throw new Error("OPA WASM evaluator not initialized");
56617
+ }
56618
+ this.policy.setData(this.dataDocument);
56619
+ const resultSet = this.policy.evaluate(input);
56620
+ if (Array.isArray(resultSet) && resultSet.length > 0) {
56621
+ return resultSet[0].result;
56622
+ }
56623
+ return void 0;
56624
+ }
56625
+ async shutdown() {
56626
+ if (this.policy) {
56627
+ if (typeof this.policy.close === "function") {
56628
+ try {
56629
+ this.policy.close();
56630
+ } catch {
56631
+ }
56632
+ } else if (typeof this.policy.free === "function") {
56633
+ try {
56634
+ this.policy.free();
56635
+ } catch {
56636
+ }
56637
+ }
56638
+ }
56639
+ this.policy = null;
56640
+ }
56641
+ };
56642
+ }
56643
+ });
56644
+
56645
+ // src/enterprise/policy/opa-http-evaluator.ts
56646
+ var OpaHttpEvaluator;
56647
+ var init_opa_http_evaluator = __esm({
56648
+ "src/enterprise/policy/opa-http-evaluator.ts"() {
56649
+ "use strict";
56650
+ OpaHttpEvaluator = class {
56651
+ baseUrl;
56652
+ timeout;
56653
+ constructor(baseUrl, timeout = 5e3) {
56654
+ let parsed;
56655
+ try {
56656
+ parsed = new URL(baseUrl);
56657
+ } catch {
56658
+ throw new Error(`OPA HTTP evaluator: invalid URL: ${baseUrl}`);
56659
+ }
56660
+ if (!["http:", "https:"].includes(parsed.protocol)) {
56661
+ throw new Error(
56662
+ `OPA HTTP evaluator: url must use http:// or https:// protocol, got: ${baseUrl}`
56663
+ );
56664
+ }
56665
+ const hostname = parsed.hostname;
56666
+ if (this.isBlockedHostname(hostname)) {
56667
+ throw new Error(
56668
+ `OPA HTTP evaluator: url must not point to internal, loopback, or private network addresses`
56669
+ );
56670
+ }
56671
+ this.baseUrl = baseUrl.replace(/\/+$/, "");
56672
+ this.timeout = timeout;
56673
+ }
56674
+ /**
56675
+ * Check if a hostname is blocked due to SSRF concerns.
56676
+ *
56677
+ * Blocks:
56678
+ * - Loopback addresses (127.x.x.x, localhost, 0.0.0.0, ::1)
56679
+ * - Link-local addresses (169.254.x.x)
56680
+ * - Private networks (10.x.x.x, 172.16-31.x.x, 192.168.x.x)
56681
+ * - IPv6 unique local addresses (fd00::/8)
56682
+ * - Cloud metadata services (*.internal)
56683
+ */
56684
+ isBlockedHostname(hostname) {
56685
+ if (!hostname) return true;
56686
+ const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, "");
56687
+ if (normalized === "metadata.google.internal" || normalized.endsWith(".internal")) {
56688
+ return true;
56689
+ }
56690
+ if (normalized === "localhost" || normalized === "localhost.localdomain") {
56691
+ return true;
56692
+ }
56693
+ if (normalized === "::1" || normalized === "0:0:0:0:0:0:0:1") {
56694
+ return true;
56695
+ }
56696
+ const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
56697
+ const ipv4Match = normalized.match(ipv4Pattern);
56698
+ if (ipv4Match) {
56699
+ const octets = ipv4Match.slice(1, 5).map(Number);
56700
+ if (octets.some((octet) => octet > 255)) {
56701
+ return false;
56702
+ }
56703
+ const [a, b] = octets;
56704
+ if (a === 127) {
56705
+ return true;
56706
+ }
56707
+ if (a === 0) {
56708
+ return true;
56709
+ }
56710
+ if (a === 169 && b === 254) {
56711
+ return true;
56712
+ }
56713
+ if (a === 10) {
56714
+ return true;
56715
+ }
56716
+ if (a === 172 && b >= 16 && b <= 31) {
56717
+ return true;
56718
+ }
56719
+ if (a === 192 && b === 168) {
56720
+ return true;
56721
+ }
56722
+ }
56723
+ if (normalized.startsWith("fd") || normalized.startsWith("fc")) {
56724
+ return true;
56725
+ }
56726
+ if (normalized.startsWith("fe80:")) {
56727
+ return true;
56728
+ }
56729
+ return false;
56730
+ }
56731
+ /**
56732
+ * Evaluate a policy rule against an input document via OPA REST API.
56733
+ *
56734
+ * @param input - The input document to evaluate
56735
+ * @param rulePath - OPA rule path (e.g., 'visor/check/execute')
56736
+ * @returns The result object from OPA, or undefined on error
56737
+ */
56738
+ async evaluate(input, rulePath) {
56739
+ const encodedPath = rulePath.split("/").map((s) => encodeURIComponent(s)).join("/");
56740
+ const url = `${this.baseUrl}/v1/data/${encodedPath}`;
56741
+ const controller = new AbortController();
56742
+ const timer = setTimeout(() => controller.abort(), this.timeout);
56743
+ try {
56744
+ const response = await fetch(url, {
56745
+ method: "POST",
56746
+ headers: { "Content-Type": "application/json" },
56747
+ body: JSON.stringify({ input }),
56748
+ signal: controller.signal
56749
+ });
56750
+ if (!response.ok) {
56751
+ throw new Error(`OPA HTTP ${response.status}: ${response.statusText}`);
56752
+ }
56753
+ let body;
56754
+ try {
56755
+ body = await response.json();
56756
+ } catch (jsonErr) {
56757
+ throw new Error(
56758
+ `OPA HTTP evaluator: failed to parse JSON response: ${jsonErr instanceof Error ? jsonErr.message : String(jsonErr)}`
56759
+ );
56760
+ }
56761
+ return body?.result;
56762
+ } finally {
56763
+ clearTimeout(timer);
56764
+ }
56765
+ }
56766
+ async shutdown() {
56767
+ }
56768
+ };
56769
+ }
56770
+ });
56771
+
56772
+ // src/enterprise/policy/policy-input-builder.ts
56773
+ var PolicyInputBuilder;
56774
+ var init_policy_input_builder = __esm({
56775
+ "src/enterprise/policy/policy-input-builder.ts"() {
56776
+ "use strict";
56777
+ PolicyInputBuilder = class {
56778
+ roles;
56779
+ actor;
56780
+ repository;
56781
+ pullRequest;
56782
+ constructor(policyConfig, actor, repository, pullRequest) {
56783
+ this.roles = policyConfig.roles || {};
56784
+ this.actor = actor;
56785
+ this.repository = repository;
56786
+ this.pullRequest = pullRequest;
56787
+ }
56788
+ /** Resolve which roles apply to the current actor. */
56789
+ resolveRoles() {
56790
+ const matched = [];
56791
+ for (const [roleName, roleConfig] of Object.entries(this.roles)) {
56792
+ let identityMatch = false;
56793
+ if (roleConfig.author_association && this.actor.authorAssociation && roleConfig.author_association.includes(this.actor.authorAssociation)) {
56794
+ identityMatch = true;
56795
+ }
56796
+ if (!identityMatch && roleConfig.users && this.actor.login && roleConfig.users.includes(this.actor.login)) {
56797
+ identityMatch = true;
56798
+ }
56799
+ if (!identityMatch && roleConfig.slack_users && this.actor.slack?.userId && roleConfig.slack_users.includes(this.actor.slack.userId)) {
56800
+ identityMatch = true;
56801
+ }
56802
+ if (!identityMatch && roleConfig.emails && this.actor.slack?.email) {
56803
+ const actorEmail = this.actor.slack.email.toLowerCase();
56804
+ if (roleConfig.emails.some((e) => e.toLowerCase() === actorEmail)) {
56805
+ identityMatch = true;
56806
+ }
56807
+ }
56808
+ if (!identityMatch) continue;
56809
+ if (roleConfig.slack_channels && roleConfig.slack_channels.length > 0) {
56810
+ if (!this.actor.slack?.channelId || !roleConfig.slack_channels.includes(this.actor.slack.channelId)) {
56811
+ continue;
56812
+ }
56813
+ }
56814
+ matched.push(roleName);
56815
+ }
56816
+ return matched;
56817
+ }
56818
+ buildActor() {
56819
+ return {
56820
+ authorAssociation: this.actor.authorAssociation,
56821
+ login: this.actor.login,
56822
+ roles: this.resolveRoles(),
56823
+ isLocalMode: this.actor.isLocalMode,
56824
+ ...this.actor.slack && { slack: this.actor.slack }
56825
+ };
56826
+ }
56827
+ forCheckExecution(check) {
56828
+ return {
56829
+ scope: "check.execute",
56830
+ check: {
56831
+ id: check.id,
56832
+ type: check.type,
56833
+ group: check.group,
56834
+ tags: check.tags,
56835
+ criticality: check.criticality,
56836
+ sandbox: check.sandbox,
56837
+ policy: check.policy
56838
+ },
56839
+ actor: this.buildActor(),
56840
+ repository: this.repository,
56841
+ pullRequest: this.pullRequest
56842
+ };
56843
+ }
56844
+ forToolInvocation(serverName, methodName, transport) {
56845
+ return {
56846
+ scope: "tool.invoke",
56847
+ tool: { serverName, methodName, transport },
56848
+ actor: this.buildActor(),
56849
+ repository: this.repository,
56850
+ pullRequest: this.pullRequest
56851
+ };
56852
+ }
56853
+ forCapabilityResolve(checkId, capabilities) {
56854
+ return {
56855
+ scope: "capability.resolve",
56856
+ check: { id: checkId, type: "ai" },
56857
+ capability: capabilities,
56858
+ actor: this.buildActor(),
56859
+ repository: this.repository,
56860
+ pullRequest: this.pullRequest
56861
+ };
56862
+ }
56863
+ };
56864
+ }
56865
+ });
56866
+
56867
+ // src/enterprise/policy/opa-policy-engine.ts
56868
+ var opa_policy_engine_exports = {};
56869
+ __export(opa_policy_engine_exports, {
56870
+ OpaPolicyEngine: () => OpaPolicyEngine
56871
+ });
56872
+ var OpaPolicyEngine;
56873
+ var init_opa_policy_engine = __esm({
56874
+ "src/enterprise/policy/opa-policy-engine.ts"() {
56875
+ "use strict";
56876
+ init_opa_wasm_evaluator();
56877
+ init_opa_http_evaluator();
56878
+ init_policy_input_builder();
56879
+ OpaPolicyEngine = class {
56880
+ evaluator = null;
56881
+ fallback;
56882
+ timeout;
56883
+ config;
56884
+ inputBuilder = null;
56885
+ logger = null;
56886
+ constructor(config) {
56887
+ this.config = config;
56888
+ this.fallback = config.fallback || "deny";
56889
+ this.timeout = config.timeout || 5e3;
56890
+ }
56891
+ async initialize(config) {
56892
+ try {
56893
+ this.logger = (init_logger(), __toCommonJS(logger_exports)).logger;
56894
+ } catch {
56895
+ }
56896
+ const actor = {
56897
+ authorAssociation: process.env.VISOR_AUTHOR_ASSOCIATION,
56898
+ login: process.env.VISOR_AUTHOR_LOGIN || process.env.GITHUB_ACTOR,
56899
+ isLocalMode: !process.env.GITHUB_ACTIONS
56900
+ };
56901
+ const repo = {
56902
+ owner: process.env.GITHUB_REPOSITORY_OWNER,
56903
+ name: process.env.GITHUB_REPOSITORY?.split("/")[1],
56904
+ branch: process.env.GITHUB_HEAD_REF,
56905
+ baseBranch: process.env.GITHUB_BASE_REF,
56906
+ event: process.env.GITHUB_EVENT_NAME
56907
+ };
56908
+ const prNum = process.env.GITHUB_PR_NUMBER ? parseInt(process.env.GITHUB_PR_NUMBER, 10) : void 0;
56909
+ const pullRequest = {
56910
+ number: prNum !== void 0 && Number.isFinite(prNum) ? prNum : void 0
56911
+ };
56912
+ this.inputBuilder = new PolicyInputBuilder(config, actor, repo, pullRequest);
56913
+ if (config.engine === "local") {
56914
+ if (!config.rules) {
56915
+ throw new Error("OPA local mode requires `policy.rules` path to .wasm or .rego files");
56916
+ }
56917
+ const wasm = new OpaWasmEvaluator();
56918
+ await wasm.initialize(config.rules);
56919
+ if (config.data) {
56920
+ wasm.loadData(config.data);
56921
+ }
56922
+ this.evaluator = wasm;
56923
+ } else if (config.engine === "remote") {
56924
+ if (!config.url) {
56925
+ throw new Error("OPA remote mode requires `policy.url` pointing to OPA server");
56926
+ }
56927
+ this.evaluator = new OpaHttpEvaluator(config.url, this.timeout);
56928
+ } else {
56929
+ this.evaluator = null;
56930
+ }
56931
+ }
56932
+ /**
56933
+ * Update actor/repo/PR context (e.g., after PR info becomes available).
56934
+ * Called by the enterprise loader when engine context is enriched.
56935
+ */
56936
+ setActorContext(actor, repo, pullRequest) {
56937
+ this.inputBuilder = new PolicyInputBuilder(this.config, actor, repo, pullRequest);
56938
+ }
56939
+ async evaluateCheckExecution(checkId, checkConfig) {
56940
+ if (!this.evaluator || !this.inputBuilder) return { allowed: true };
56941
+ const cfg = checkConfig && typeof checkConfig === "object" ? checkConfig : {};
56942
+ const policyOverride = cfg.policy;
56943
+ const input = this.inputBuilder.forCheckExecution({
56944
+ id: checkId,
56945
+ type: cfg.type || "ai",
56946
+ group: cfg.group,
56947
+ tags: cfg.tags,
56948
+ criticality: cfg.criticality,
56949
+ sandbox: cfg.sandbox,
56950
+ policy: policyOverride
56951
+ });
56952
+ return this.doEvaluate(input, this.resolveRulePath("check.execute", policyOverride?.rule));
56953
+ }
56954
+ async evaluateToolInvocation(serverName, methodName, transport) {
56955
+ if (!this.evaluator || !this.inputBuilder) return { allowed: true };
56956
+ const input = this.inputBuilder.forToolInvocation(serverName, methodName, transport);
56957
+ return this.doEvaluate(input, "visor/tool/invoke");
56958
+ }
56959
+ async evaluateCapabilities(checkId, capabilities) {
56960
+ if (!this.evaluator || !this.inputBuilder) return { allowed: true };
56961
+ const input = this.inputBuilder.forCapabilityResolve(checkId, capabilities);
56962
+ return this.doEvaluate(input, "visor/capability/resolve");
56963
+ }
56964
+ async shutdown() {
56965
+ if (this.evaluator && "shutdown" in this.evaluator) {
56966
+ await this.evaluator.shutdown();
56967
+ }
56968
+ this.evaluator = null;
56969
+ this.inputBuilder = null;
56970
+ }
56971
+ resolveRulePath(defaultScope, override) {
56972
+ if (override) {
56973
+ return override.startsWith("visor/") ? override : `visor/${override}`;
56974
+ }
56975
+ return `visor/${defaultScope.replace(/\./g, "/")}`;
56976
+ }
56977
+ async doEvaluate(input, rulePath) {
56978
+ try {
56979
+ this.logger?.debug(`[PolicyEngine] Evaluating ${rulePath}`, JSON.stringify(input));
56980
+ let timer;
56981
+ const timeoutPromise = new Promise((_resolve, reject) => {
56982
+ timer = setTimeout(() => reject(new Error("policy evaluation timeout")), this.timeout);
56983
+ });
56984
+ try {
56985
+ const result = await Promise.race([this.rawEvaluate(input, rulePath), timeoutPromise]);
56986
+ const decision = this.parseDecision(result);
56987
+ if (!decision.allowed && this.fallback === "warn") {
56988
+ decision.allowed = true;
56989
+ decision.warn = true;
56990
+ decision.reason = `audit: ${decision.reason || "policy denied"}`;
56991
+ }
56992
+ this.logger?.debug(
56993
+ `[PolicyEngine] Decision for ${rulePath}: allowed=${decision.allowed}, warn=${decision.warn || false}, reason=${decision.reason || "none"}`
56994
+ );
56995
+ return decision;
56996
+ } finally {
56997
+ if (timer) clearTimeout(timer);
56998
+ }
56999
+ } catch (err) {
57000
+ const msg = err instanceof Error ? err.message : String(err);
57001
+ this.logger?.warn(`[PolicyEngine] Evaluation failed for ${rulePath}: ${msg}`);
57002
+ return {
57003
+ allowed: this.fallback === "allow" || this.fallback === "warn",
57004
+ warn: this.fallback === "warn" ? true : void 0,
57005
+ reason: `policy evaluation failed, fallback=${this.fallback}`
57006
+ };
57007
+ }
57008
+ }
57009
+ async rawEvaluate(input, rulePath) {
57010
+ if (this.evaluator instanceof OpaWasmEvaluator) {
57011
+ const result = await this.evaluator.evaluate(input);
57012
+ return this.navigateWasmResult(result, rulePath);
57013
+ }
57014
+ return this.evaluator.evaluate(input, rulePath);
57015
+ }
57016
+ /**
57017
+ * Navigate nested OPA WASM result tree to reach the specific rule's output.
57018
+ * The WASM entrypoint `-e visor` means the result root IS the visor package,
57019
+ * so we strip the `visor/` prefix and walk the remaining segments.
57020
+ */
57021
+ navigateWasmResult(result, rulePath) {
57022
+ if (!result || typeof result !== "object") return result;
57023
+ const segments = rulePath.replace(/^visor\//, "").split("/");
57024
+ let current = result;
57025
+ for (const seg of segments) {
57026
+ if (current && typeof current === "object" && seg in current) {
57027
+ current = current[seg];
57028
+ } else {
57029
+ return void 0;
57030
+ }
57031
+ }
57032
+ return current;
57033
+ }
57034
+ parseDecision(result) {
57035
+ if (result === void 0 || result === null) {
57036
+ return {
57037
+ allowed: this.fallback === "allow" || this.fallback === "warn",
57038
+ warn: this.fallback === "warn" ? true : void 0,
57039
+ reason: this.fallback === "warn" ? "audit: no policy result" : "no policy result"
57040
+ };
57041
+ }
57042
+ const allowed = result.allowed !== false;
57043
+ const decision = {
57044
+ allowed,
57045
+ reason: result.reason
57046
+ };
57047
+ if (result.capabilities) {
57048
+ decision.capabilities = result.capabilities;
57049
+ }
57050
+ return decision;
57051
+ }
57052
+ };
57053
+ }
57054
+ });
57055
+
57056
+ // src/enterprise/scheduler/knex-store.ts
57057
+ var knex_store_exports = {};
57058
+ __export(knex_store_exports, {
57059
+ KnexStoreBackend: () => KnexStoreBackend
57060
+ });
57061
+ function toNum(val) {
57062
+ if (val === null || val === void 0) return void 0;
57063
+ return typeof val === "string" ? parseInt(val, 10) : val;
57064
+ }
57065
+ function safeJsonParse2(value) {
57066
+ if (!value) return void 0;
57067
+ try {
57068
+ return JSON.parse(value);
57069
+ } catch {
57070
+ return void 0;
57071
+ }
57072
+ }
57073
+ function fromTriggerRow2(row) {
57074
+ return {
57075
+ id: row.id,
57076
+ creatorId: row.creator_id,
57077
+ creatorContext: row.creator_context ?? void 0,
57078
+ creatorName: row.creator_name ?? void 0,
57079
+ description: row.description ?? void 0,
57080
+ channels: safeJsonParse2(row.channels),
57081
+ fromUsers: safeJsonParse2(row.from_users),
57082
+ fromBots: row.from_bots === true || row.from_bots === 1,
57083
+ contains: safeJsonParse2(row.contains),
57084
+ matchPattern: row.match_pattern ?? void 0,
57085
+ threads: row.threads,
57086
+ workflow: row.workflow,
57087
+ inputs: safeJsonParse2(row.inputs),
57088
+ outputContext: safeJsonParse2(row.output_context),
57089
+ status: row.status,
57090
+ enabled: row.enabled === true || row.enabled === 1,
57091
+ createdAt: toNum(row.created_at)
57092
+ };
57093
+ }
57094
+ function toTriggerInsertRow(trigger) {
57095
+ return {
57096
+ id: trigger.id,
57097
+ creator_id: trigger.creatorId,
57098
+ creator_context: trigger.creatorContext ?? null,
57099
+ creator_name: trigger.creatorName ?? null,
57100
+ description: trigger.description ?? null,
57101
+ channels: trigger.channels ? JSON.stringify(trigger.channels) : null,
57102
+ from_users: trigger.fromUsers ? JSON.stringify(trigger.fromUsers) : null,
57103
+ from_bots: trigger.fromBots,
57104
+ contains: trigger.contains ? JSON.stringify(trigger.contains) : null,
57105
+ match_pattern: trigger.matchPattern ?? null,
57106
+ threads: trigger.threads,
57107
+ workflow: trigger.workflow,
57108
+ inputs: trigger.inputs ? JSON.stringify(trigger.inputs) : null,
57109
+ output_context: trigger.outputContext ? JSON.stringify(trigger.outputContext) : null,
57110
+ status: trigger.status,
57111
+ enabled: trigger.enabled,
57112
+ created_at: trigger.createdAt
57113
+ };
57114
+ }
57115
+ function fromDbRow2(row) {
57116
+ return {
57117
+ id: row.id,
57118
+ creatorId: row.creator_id,
57119
+ creatorContext: row.creator_context ?? void 0,
57120
+ creatorName: row.creator_name ?? void 0,
57121
+ timezone: row.timezone,
57122
+ schedule: row.schedule_expr,
57123
+ runAt: toNum(row.run_at),
57124
+ isRecurring: row.is_recurring === true || row.is_recurring === 1,
57125
+ originalExpression: row.original_expression,
57126
+ workflow: row.workflow ?? void 0,
57127
+ workflowInputs: safeJsonParse2(row.workflow_inputs),
57128
+ outputContext: safeJsonParse2(row.output_context),
57129
+ status: row.status,
57130
+ createdAt: toNum(row.created_at),
57131
+ lastRunAt: toNum(row.last_run_at),
57132
+ nextRunAt: toNum(row.next_run_at),
57133
+ runCount: row.run_count,
57134
+ failureCount: row.failure_count,
57135
+ lastError: row.last_error ?? void 0,
57136
+ previousResponse: row.previous_response ?? void 0
57137
+ };
57138
+ }
57139
+ function toInsertRow(schedule) {
57140
+ return {
57141
+ id: schedule.id,
57142
+ creator_id: schedule.creatorId,
57143
+ creator_context: schedule.creatorContext ?? null,
57144
+ creator_name: schedule.creatorName ?? null,
57145
+ timezone: schedule.timezone,
57146
+ schedule_expr: schedule.schedule,
57147
+ run_at: schedule.runAt ?? null,
57148
+ is_recurring: schedule.isRecurring,
57149
+ original_expression: schedule.originalExpression,
57150
+ workflow: schedule.workflow ?? null,
57151
+ workflow_inputs: schedule.workflowInputs ? JSON.stringify(schedule.workflowInputs) : null,
57152
+ output_context: schedule.outputContext ? JSON.stringify(schedule.outputContext) : null,
57153
+ status: schedule.status,
57154
+ created_at: schedule.createdAt,
57155
+ last_run_at: schedule.lastRunAt ?? null,
57156
+ next_run_at: schedule.nextRunAt ?? null,
57157
+ run_count: schedule.runCount,
57158
+ failure_count: schedule.failureCount,
57159
+ last_error: schedule.lastError ?? null,
57160
+ previous_response: schedule.previousResponse ?? null
57161
+ };
57162
+ }
57163
+ var fs24, path29, import_uuid2, KnexStoreBackend;
57164
+ var init_knex_store = __esm({
57165
+ "src/enterprise/scheduler/knex-store.ts"() {
57166
+ "use strict";
57167
+ fs24 = __toESM(require("fs"));
57168
+ path29 = __toESM(require("path"));
57169
+ import_uuid2 = require("uuid");
57170
+ init_logger();
57171
+ KnexStoreBackend = class {
57172
+ knex = null;
57173
+ driver;
57174
+ connection;
57175
+ constructor(driver, storageConfig, _haConfig) {
57176
+ this.driver = driver;
57177
+ this.connection = storageConfig.connection || {};
57178
+ }
57179
+ async initialize() {
57180
+ const { createRequire } = require("module");
57181
+ const runtimeRequire = createRequire(__filename);
57182
+ let knexFactory;
57183
+ try {
57184
+ knexFactory = runtimeRequire("knex");
57185
+ } catch (err) {
57186
+ const code = err?.code;
57187
+ if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
57188
+ throw new Error(
57189
+ "knex is required for PostgreSQL/MySQL/MSSQL schedule storage. Install it with: npm install knex"
57190
+ );
57191
+ }
57192
+ throw err;
57193
+ }
57194
+ const clientMap = {
57195
+ postgresql: "pg",
57196
+ mysql: "mysql2",
57197
+ mssql: "tedious"
57198
+ };
57199
+ const client = clientMap[this.driver];
57200
+ let connection;
57201
+ if (this.connection.connection_string) {
57202
+ connection = this.connection.connection_string;
57203
+ } else if (this.driver === "mssql") {
57204
+ connection = this.buildMssqlConnection();
57205
+ } else {
57206
+ connection = this.buildStandardConnection();
57207
+ }
57208
+ this.knex = knexFactory({
57209
+ client,
57210
+ connection,
57211
+ pool: {
57212
+ min: this.connection.pool?.min ?? 0,
57213
+ max: this.connection.pool?.max ?? 10
57214
+ }
57215
+ });
57216
+ await this.migrateSchema();
57217
+ logger.info(`[KnexStore] Initialized (${this.driver})`);
57218
+ }
57219
+ buildStandardConnection() {
57220
+ return {
57221
+ host: this.connection.host || "localhost",
57222
+ port: this.connection.port,
57223
+ database: this.connection.database || "visor",
57224
+ user: this.connection.user,
57225
+ password: this.connection.password,
57226
+ ssl: this.resolveSslConfig()
57227
+ };
57228
+ }
57229
+ buildMssqlConnection() {
57230
+ const ssl = this.connection.ssl;
57231
+ const sslEnabled = ssl === true || typeof ssl === "object" && ssl.enabled !== false;
57232
+ return {
57233
+ server: this.connection.host || "localhost",
57234
+ port: this.connection.port,
57235
+ database: this.connection.database || "visor",
57236
+ user: this.connection.user,
57237
+ password: this.connection.password,
57238
+ options: {
57239
+ encrypt: sslEnabled,
57240
+ trustServerCertificate: typeof ssl === "object" ? ssl.reject_unauthorized === false : !sslEnabled
57241
+ }
57242
+ };
57243
+ }
57244
+ resolveSslConfig() {
57245
+ const ssl = this.connection.ssl;
57246
+ if (ssl === false || ssl === void 0) return false;
57247
+ if (ssl === true) return { rejectUnauthorized: true };
57248
+ if (ssl.enabled === false) return false;
57249
+ const result = {
57250
+ rejectUnauthorized: ssl.reject_unauthorized !== false
57251
+ };
57252
+ if (ssl.ca) {
57253
+ const caPath = this.validateSslPath(ssl.ca, "CA certificate");
57254
+ result.ca = fs24.readFileSync(caPath, "utf8");
57255
+ }
57256
+ if (ssl.cert) {
57257
+ const certPath = this.validateSslPath(ssl.cert, "client certificate");
57258
+ result.cert = fs24.readFileSync(certPath, "utf8");
57259
+ }
57260
+ if (ssl.key) {
57261
+ const keyPath = this.validateSslPath(ssl.key, "client key");
57262
+ result.key = fs24.readFileSync(keyPath, "utf8");
57263
+ }
57264
+ return result;
57265
+ }
57266
+ validateSslPath(filePath, label) {
57267
+ const resolved = path29.resolve(filePath);
57268
+ if (resolved !== path29.normalize(resolved)) {
57269
+ throw new Error(`SSL ${label} path contains invalid sequences: ${filePath}`);
57270
+ }
57271
+ if (!fs24.existsSync(resolved)) {
57272
+ throw new Error(`SSL ${label} not found: ${filePath}`);
57273
+ }
57274
+ return resolved;
57275
+ }
57276
+ async shutdown() {
57277
+ if (this.knex) {
57278
+ await this.knex.destroy();
57279
+ this.knex = null;
57280
+ }
57281
+ }
57282
+ async migrateSchema() {
57283
+ const knex = this.getKnex();
57284
+ const exists = await knex.schema.hasTable("schedules");
57285
+ if (!exists) {
57286
+ await knex.schema.createTable("schedules", (table) => {
57287
+ table.string("id", 36).primary();
57288
+ table.string("creator_id", 255).notNullable().index();
57289
+ table.string("creator_context", 255);
57290
+ table.string("creator_name", 255);
57291
+ table.string("timezone", 64).notNullable().defaultTo("UTC");
57292
+ table.string("schedule_expr", 255);
57293
+ table.bigInteger("run_at");
57294
+ table.boolean("is_recurring").notNullable();
57295
+ table.text("original_expression");
57296
+ table.string("workflow", 255);
57297
+ table.text("workflow_inputs");
57298
+ table.text("output_context");
57299
+ table.string("status", 20).notNullable().index();
57300
+ table.bigInteger("created_at").notNullable();
57301
+ table.bigInteger("last_run_at");
57302
+ table.bigInteger("next_run_at");
57303
+ table.integer("run_count").notNullable().defaultTo(0);
57304
+ table.integer("failure_count").notNullable().defaultTo(0);
57305
+ table.text("last_error");
57306
+ table.text("previous_response");
57307
+ table.index(["status", "next_run_at"]);
57308
+ });
57309
+ }
57310
+ const triggersExist = await knex.schema.hasTable("message_triggers");
57311
+ if (!triggersExist) {
57312
+ await knex.schema.createTable("message_triggers", (table) => {
57313
+ table.string("id", 36).primary();
57314
+ table.string("creator_id", 255).notNullable().index();
57315
+ table.string("creator_context", 255);
57316
+ table.string("creator_name", 255);
57317
+ table.text("description");
57318
+ table.text("channels");
57319
+ table.text("from_users");
57320
+ table.boolean("from_bots").notNullable().defaultTo(false);
57321
+ table.text("contains");
57322
+ table.text("match_pattern");
57323
+ table.string("threads", 20).notNullable().defaultTo("any");
57324
+ table.string("workflow", 255).notNullable();
57325
+ table.text("inputs");
57326
+ table.text("output_context");
57327
+ table.string("status", 20).notNullable().defaultTo("active").index();
57328
+ table.boolean("enabled").notNullable().defaultTo(true);
57329
+ table.bigInteger("created_at").notNullable();
57330
+ });
57331
+ }
57332
+ const locksExist = await knex.schema.hasTable("scheduler_locks");
57333
+ if (!locksExist) {
57334
+ await knex.schema.createTable("scheduler_locks", (table) => {
57335
+ table.string("lock_id", 255).primary();
57336
+ table.string("node_id", 255).notNullable();
57337
+ table.string("lock_token", 36).notNullable();
57338
+ table.bigInteger("acquired_at").notNullable();
57339
+ table.bigInteger("expires_at").notNullable();
57340
+ });
57341
+ }
57342
+ }
57343
+ getKnex() {
57344
+ if (!this.knex) {
57345
+ throw new Error("[KnexStore] Not initialized. Call initialize() first.");
57346
+ }
57347
+ return this.knex;
57348
+ }
57349
+ // --- CRUD ---
57350
+ async create(schedule) {
57351
+ const knex = this.getKnex();
57352
+ const newSchedule = {
57353
+ ...schedule,
57354
+ id: (0, import_uuid2.v4)(),
57355
+ createdAt: Date.now(),
57356
+ runCount: 0,
57357
+ failureCount: 0,
57358
+ status: "active"
57359
+ };
57360
+ await knex("schedules").insert(toInsertRow(newSchedule));
57361
+ logger.info(`[KnexStore] Created schedule ${newSchedule.id} for user ${newSchedule.creatorId}`);
57362
+ return newSchedule;
57363
+ }
57364
+ async importSchedule(schedule) {
57365
+ const knex = this.getKnex();
57366
+ const existing = await knex("schedules").where("id", schedule.id).first();
57367
+ if (existing) return;
57368
+ await knex("schedules").insert(toInsertRow(schedule));
57369
+ }
57370
+ async get(id) {
57371
+ const knex = this.getKnex();
57372
+ const row = await knex("schedules").where("id", id).first();
57373
+ return row ? fromDbRow2(row) : void 0;
57374
+ }
57375
+ async update(id, patch) {
57376
+ const knex = this.getKnex();
57377
+ const existing = await knex("schedules").where("id", id).first();
57378
+ if (!existing) return void 0;
57379
+ const current = fromDbRow2(existing);
57380
+ const updated = { ...current, ...patch, id: current.id };
57381
+ const row = toInsertRow(updated);
57382
+ delete row.id;
57383
+ await knex("schedules").where("id", id).update(row);
57384
+ return updated;
57385
+ }
57386
+ async delete(id) {
57387
+ const knex = this.getKnex();
57388
+ const deleted = await knex("schedules").where("id", id).del();
57389
+ if (deleted > 0) {
57390
+ logger.info(`[KnexStore] Deleted schedule ${id}`);
57391
+ return true;
57392
+ }
57393
+ return false;
57394
+ }
57395
+ // --- Queries ---
57396
+ async getByCreator(creatorId) {
57397
+ const knex = this.getKnex();
57398
+ const rows = await knex("schedules").where("creator_id", creatorId);
57399
+ return rows.map((r) => fromDbRow2(r));
57400
+ }
57401
+ async getActiveSchedules() {
57402
+ const knex = this.getKnex();
57403
+ const rows = await knex("schedules").where("status", "active");
57404
+ return rows.map((r) => fromDbRow2(r));
57405
+ }
57406
+ async getDueSchedules(now) {
57407
+ const ts = now ?? Date.now();
57408
+ const knex = this.getKnex();
57409
+ const bFalse = this.driver === "mssql" ? 0 : false;
57410
+ const bTrue = this.driver === "mssql" ? 1 : true;
57411
+ const rows = await knex("schedules").where("status", "active").andWhere(function() {
57412
+ this.where(function() {
57413
+ this.where("is_recurring", bFalse).whereNotNull("run_at").where("run_at", "<=", ts);
57414
+ }).orWhere(function() {
57415
+ this.where("is_recurring", bTrue).whereNotNull("next_run_at").where("next_run_at", "<=", ts);
57416
+ });
57417
+ });
57418
+ return rows.map((r) => fromDbRow2(r));
57419
+ }
57420
+ async findByWorkflow(creatorId, workflowName) {
57421
+ const knex = this.getKnex();
57422
+ const escaped = workflowName.toLowerCase().replace(/[%_\\]/g, "\\$&");
57423
+ const pattern = `%${escaped}%`;
57424
+ const rows = await knex("schedules").where("creator_id", creatorId).where("status", "active").whereRaw("LOWER(workflow) LIKE ? ESCAPE '\\'", [pattern]);
57425
+ return rows.map((r) => fromDbRow2(r));
57426
+ }
57427
+ async getAll() {
57428
+ const knex = this.getKnex();
57429
+ const rows = await knex("schedules");
57430
+ return rows.map((r) => fromDbRow2(r));
57431
+ }
57432
+ async getStats() {
57433
+ const knex = this.getKnex();
57434
+ const boolTrue = this.driver === "mssql" ? "1" : "true";
57435
+ const boolFalse = this.driver === "mssql" ? "0" : "false";
57436
+ const result = await knex("schedules").select(
57437
+ knex.raw("COUNT(*) as total"),
57438
+ knex.raw("SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active"),
57439
+ knex.raw("SUM(CASE WHEN status = 'paused' THEN 1 ELSE 0 END) as paused"),
57440
+ knex.raw("SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed"),
57441
+ knex.raw("SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed"),
57442
+ knex.raw(`SUM(CASE WHEN is_recurring = ${boolTrue} THEN 1 ELSE 0 END) as recurring`),
57443
+ knex.raw(`SUM(CASE WHEN is_recurring = ${boolFalse} THEN 1 ELSE 0 END) as one_time`)
57444
+ ).first();
57445
+ return {
57446
+ total: Number(result.total) || 0,
57447
+ active: Number(result.active) || 0,
57448
+ paused: Number(result.paused) || 0,
57449
+ completed: Number(result.completed) || 0,
57450
+ failed: Number(result.failed) || 0,
57451
+ recurring: Number(result.recurring) || 0,
57452
+ oneTime: Number(result.one_time) || 0
57453
+ };
57454
+ }
57455
+ async validateLimits(creatorId, isRecurring, limits) {
57456
+ const knex = this.getKnex();
57457
+ if (limits.maxGlobal) {
57458
+ const result = await knex("schedules").count("* as cnt").first();
57459
+ if (Number(result?.cnt) >= limits.maxGlobal) {
57460
+ throw new Error(`Global schedule limit reached (${limits.maxGlobal})`);
57461
+ }
57462
+ }
57463
+ if (limits.maxPerUser) {
57464
+ const result = await knex("schedules").where("creator_id", creatorId).count("* as cnt").first();
57465
+ if (Number(result?.cnt) >= limits.maxPerUser) {
57466
+ throw new Error(`You have reached the maximum number of schedules (${limits.maxPerUser})`);
57467
+ }
57468
+ }
57469
+ if (isRecurring && limits.maxRecurringPerUser) {
57470
+ const bTrue = this.driver === "mssql" ? 1 : true;
57471
+ const result = await knex("schedules").where("creator_id", creatorId).where("is_recurring", bTrue).count("* as cnt").first();
57472
+ if (Number(result?.cnt) >= limits.maxRecurringPerUser) {
57473
+ throw new Error(
57474
+ `You have reached the maximum number of recurring schedules (${limits.maxRecurringPerUser})`
57475
+ );
57476
+ }
57477
+ }
57478
+ }
57479
+ // --- HA Distributed Locking (via scheduler_locks table) ---
57480
+ async tryAcquireLock(lockId, nodeId, ttlSeconds) {
57481
+ const knex = this.getKnex();
57482
+ const now = Date.now();
57483
+ const expiresAt = now + ttlSeconds * 1e3;
57484
+ const token = (0, import_uuid2.v4)();
57485
+ const updated = await knex("scheduler_locks").where("lock_id", lockId).where("expires_at", "<", now).update({
57486
+ node_id: nodeId,
57487
+ lock_token: token,
57488
+ acquired_at: now,
57489
+ expires_at: expiresAt
57490
+ });
57491
+ if (updated > 0) return token;
57492
+ try {
57493
+ await knex("scheduler_locks").insert({
57494
+ lock_id: lockId,
57495
+ node_id: nodeId,
57496
+ lock_token: token,
57497
+ acquired_at: now,
57498
+ expires_at: expiresAt
57499
+ });
57500
+ return token;
57501
+ } catch {
57502
+ return null;
57503
+ }
57504
+ }
57505
+ async releaseLock(lockId, lockToken) {
57506
+ const knex = this.getKnex();
57507
+ await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).del();
57508
+ }
57509
+ async renewLock(lockId, lockToken, ttlSeconds) {
57510
+ const knex = this.getKnex();
57511
+ const now = Date.now();
57512
+ const expiresAt = now + ttlSeconds * 1e3;
57513
+ const updated = await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).update({ acquired_at: now, expires_at: expiresAt });
57514
+ return updated > 0;
57515
+ }
57516
+ async flush() {
57517
+ }
57518
+ // --- Message Trigger CRUD ---
57519
+ async createTrigger(trigger) {
57520
+ const knex = this.getKnex();
57521
+ const newTrigger = {
57522
+ ...trigger,
57523
+ id: (0, import_uuid2.v4)(),
57524
+ createdAt: Date.now()
57525
+ };
57526
+ await knex("message_triggers").insert(toTriggerInsertRow(newTrigger));
57527
+ logger.info(`[KnexStore] Created trigger ${newTrigger.id} for user ${newTrigger.creatorId}`);
57528
+ return newTrigger;
57529
+ }
57530
+ async getTrigger(id) {
57531
+ const knex = this.getKnex();
57532
+ const row = await knex("message_triggers").where("id", id).first();
57533
+ return row ? fromTriggerRow2(row) : void 0;
57534
+ }
57535
+ async updateTrigger(id, patch) {
57536
+ const knex = this.getKnex();
57537
+ const existing = await knex("message_triggers").where("id", id).first();
57538
+ if (!existing) return void 0;
57539
+ const current = fromTriggerRow2(existing);
57540
+ const updated = {
57541
+ ...current,
57542
+ ...patch,
57543
+ id: current.id,
57544
+ createdAt: current.createdAt
57545
+ };
57546
+ const row = toTriggerInsertRow(updated);
57547
+ delete row.id;
57548
+ await knex("message_triggers").where("id", id).update(row);
57549
+ return updated;
57550
+ }
57551
+ async deleteTrigger(id) {
57552
+ const knex = this.getKnex();
57553
+ const deleted = await knex("message_triggers").where("id", id).del();
57554
+ if (deleted > 0) {
57555
+ logger.info(`[KnexStore] Deleted trigger ${id}`);
57556
+ return true;
57557
+ }
57558
+ return false;
57559
+ }
57560
+ async getTriggersByCreator(creatorId) {
57561
+ const knex = this.getKnex();
57562
+ const rows = await knex("message_triggers").where("creator_id", creatorId);
57563
+ return rows.map((r) => fromTriggerRow2(r));
57564
+ }
57565
+ async getActiveTriggers() {
57566
+ const knex = this.getKnex();
57567
+ const rows = await knex("message_triggers").where("status", "active").where("enabled", this.driver === "mssql" ? 1 : true);
57568
+ return rows.map((r) => fromTriggerRow2(r));
57569
+ }
57570
+ };
57571
+ }
57572
+ });
57573
+
57574
+ // src/enterprise/loader.ts
57575
+ var loader_exports = {};
57576
+ __export(loader_exports, {
57577
+ loadEnterprisePolicyEngine: () => loadEnterprisePolicyEngine,
57578
+ loadEnterpriseStoreBackend: () => loadEnterpriseStoreBackend
57579
+ });
57580
+ async function loadEnterprisePolicyEngine(config) {
57581
+ try {
57582
+ const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
57583
+ const validator = new LicenseValidator2();
57584
+ const license = await validator.loadAndValidate();
57585
+ if (!license || !validator.hasFeature("policy")) {
57586
+ return new DefaultPolicyEngine();
57587
+ }
57588
+ if (validator.isInGracePeriod()) {
57589
+ console.warn(
57590
+ "[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
57591
+ );
57592
+ }
57593
+ const { OpaPolicyEngine: OpaPolicyEngine2 } = await Promise.resolve().then(() => (init_opa_policy_engine(), opa_policy_engine_exports));
57594
+ const engine = new OpaPolicyEngine2(config);
57595
+ await engine.initialize(config);
57596
+ return engine;
57597
+ } catch (err) {
57598
+ const msg = err instanceof Error ? err.message : String(err);
57599
+ try {
57600
+ const { logger: logger2 } = (init_logger(), __toCommonJS(logger_exports));
57601
+ logger2.warn(`[PolicyEngine] Enterprise policy init failed, falling back to default: ${msg}`);
57602
+ } catch {
57603
+ }
57604
+ return new DefaultPolicyEngine();
57605
+ }
57606
+ }
57607
+ async function loadEnterpriseStoreBackend(driver, storageConfig, haConfig) {
57608
+ const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
57609
+ const validator = new LicenseValidator2();
57610
+ const license = await validator.loadAndValidate();
57611
+ if (!license || !validator.hasFeature("scheduler-sql")) {
57612
+ throw new Error(
57613
+ `The ${driver} schedule storage driver requires a Visor Enterprise license with the 'scheduler-sql' feature. Please upgrade or use driver: 'sqlite' (default).`
57614
+ );
57615
+ }
57616
+ if (validator.isInGracePeriod()) {
57617
+ console.warn(
57618
+ "[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
57619
+ );
57620
+ }
57621
+ const { KnexStoreBackend: KnexStoreBackend2 } = await Promise.resolve().then(() => (init_knex_store(), knex_store_exports));
57622
+ return new KnexStoreBackend2(driver, storageConfig, haConfig);
57623
+ }
57624
+ var init_loader = __esm({
57625
+ "src/enterprise/loader.ts"() {
57626
+ "use strict";
57627
+ init_default_engine();
57628
+ }
57629
+ });
57630
+
56257
57631
  // src/event-bus/event-bus.ts
56258
57632
  var event_bus_exports = {};
56259
57633
  __export(event_bus_exports, {
@@ -57160,8 +58534,8 @@ ${content}
57160
58534
  * Sleep utility
57161
58535
  */
57162
58536
  sleep(ms) {
57163
- return new Promise((resolve15) => {
57164
- const t = setTimeout(resolve15, ms);
58537
+ return new Promise((resolve19) => {
58538
+ const t = setTimeout(resolve19, ms);
57165
58539
  if (typeof t.unref === "function") {
57166
58540
  try {
57167
58541
  t.unref();
@@ -57446,8 +58820,8 @@ ${end}`);
57446
58820
  async updateGroupedComment(ctx, comments, group, changedIds) {
57447
58821
  const existingLock = this.updateLocks.get(group);
57448
58822
  let resolveLock;
57449
- const ourLock = new Promise((resolve15) => {
57450
- resolveLock = resolve15;
58823
+ const ourLock = new Promise((resolve19) => {
58824
+ resolveLock = resolve19;
57451
58825
  });
57452
58826
  this.updateLocks.set(group, ourLock);
57453
58827
  try {
@@ -57778,7 +59152,7 @@ ${blocks}
57778
59152
  * Sleep utility for enforcing delays
57779
59153
  */
57780
59154
  sleep(ms) {
57781
- return new Promise((resolve15) => setTimeout(resolve15, ms));
59155
+ return new Promise((resolve19) => setTimeout(resolve19, ms));
57782
59156
  }
57783
59157
  };
57784
59158
  }
@@ -58947,7 +60321,7 @@ var init_tui_frontend = __esm({
58947
60321
  });
58948
60322
 
58949
60323
  // src/agent-protocol/task-store.ts
58950
- function safeJsonParse2(value) {
60324
+ function safeJsonParse3(value) {
58951
60325
  if (!value) return void 0;
58952
60326
  try {
58953
60327
  return JSON.parse(value);
@@ -58964,12 +60338,12 @@ function taskRowToAgentTask(row) {
58964
60338
  context_id: row.context_id,
58965
60339
  status: {
58966
60340
  state: row.state,
58967
- message: safeJsonParse2(row.status_message),
60341
+ message: safeJsonParse3(row.status_message),
58968
60342
  timestamp: row.updated_at
58969
60343
  },
58970
- artifacts: safeJsonParse2(row.artifacts) ?? [],
58971
- history: safeJsonParse2(row.history) ?? [],
58972
- metadata: safeJsonParse2(row.request_metadata),
60344
+ artifacts: safeJsonParse3(row.artifacts) ?? [],
60345
+ history: safeJsonParse3(row.history) ?? [],
60346
+ metadata: safeJsonParse3(row.request_metadata),
58973
60347
  workflow_id: row.workflow_id ?? void 0
58974
60348
  };
58975
60349
  }
@@ -59114,6 +60488,15 @@ var init_task_store = __esm({
59114
60488
  conditions.push("workflow_id = ?");
59115
60489
  params.push(filter.workflowId);
59116
60490
  }
60491
+ if (filter.search) {
60492
+ const escaped = filter.search.replace(/[%_\\]/g, "\\$&");
60493
+ conditions.push("request_message LIKE ? ESCAPE '\\'");
60494
+ params.push(`%${escaped}%`);
60495
+ }
60496
+ if (filter.claimedBy) {
60497
+ conditions.push("claimed_by = ?");
60498
+ params.push(filter.claimedBy);
60499
+ }
59117
60500
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
59118
60501
  return { where, params };
59119
60502
  }
@@ -59197,7 +60580,7 @@ var init_task_store = __esm({
59197
60580
  const db = this.getDb();
59198
60581
  const row = db.prepare("SELECT artifacts FROM agent_tasks WHERE id = ?").get(taskId);
59199
60582
  if (!row) throw new TaskNotFoundError(taskId);
59200
- const artifacts = safeJsonParse2(row.artifacts) ?? [];
60583
+ const artifacts = safeJsonParse3(row.artifacts) ?? [];
59201
60584
  artifacts.push(artifact);
59202
60585
  db.prepare("UPDATE agent_tasks SET artifacts = ?, updated_at = ? WHERE id = ?").run(
59203
60586
  JSON.stringify(artifacts),
@@ -59209,7 +60592,7 @@ var init_task_store = __esm({
59209
60592
  const db = this.getDb();
59210
60593
  const row = db.prepare("SELECT history FROM agent_tasks WHERE id = ?").get(taskId);
59211
60594
  if (!row) throw new TaskNotFoundError(taskId);
59212
- const history = safeJsonParse2(row.history) ?? [];
60595
+ const history = safeJsonParse3(row.history) ?? [];
59213
60596
  history.push(message);
59214
60597
  db.prepare("UPDATE agent_tasks SET history = ?, updated_at = ? WHERE id = ?").run(
59215
60598
  JSON.stringify(history),
@@ -59267,6 +60650,32 @@ var init_task_store = __esm({
59267
60650
  // -------------------------------------------------------------------------
59268
60651
  // Cleanup
59269
60652
  // -------------------------------------------------------------------------
60653
+ failStaleTasks(reason) {
60654
+ const db = this.getDb();
60655
+ const now = nowISO();
60656
+ const msg = reason || "Process terminated while task was running";
60657
+ const statusMessage = JSON.stringify({
60658
+ message_id: import_crypto6.default.randomUUID(),
60659
+ role: "agent",
60660
+ parts: [{ text: msg }]
60661
+ });
60662
+ const result = db.prepare(
60663
+ `UPDATE agent_tasks
60664
+ SET state = 'failed', updated_at = ?, status_message = ?
60665
+ WHERE state = 'working'`
60666
+ ).run(now, statusMessage);
60667
+ return result.changes;
60668
+ }
60669
+ purgeOldTasks(olderThanMs) {
60670
+ const db = this.getDb();
60671
+ const cutoff = new Date(Date.now() - olderThanMs).toISOString();
60672
+ const result = db.prepare(
60673
+ `DELETE FROM agent_tasks
60674
+ WHERE state IN ('completed', 'failed', 'canceled', 'rejected')
60675
+ AND updated_at <= ?`
60676
+ ).run(cutoff);
60677
+ return result.changes;
60678
+ }
59270
60679
  deleteExpiredTasks() {
59271
60680
  const db = this.getDb();
59272
60681
  const now = nowISO();
@@ -59695,13 +61104,13 @@ __export(a2a_frontend_exports, {
59695
61104
  resultToArtifacts: () => resultToArtifacts
59696
61105
  });
59697
61106
  function readJsonBody(req) {
59698
- return new Promise((resolve15, reject) => {
61107
+ return new Promise((resolve19, reject) => {
59699
61108
  const chunks = [];
59700
61109
  req.on("data", (chunk) => chunks.push(chunk));
59701
61110
  req.on("end", () => {
59702
61111
  try {
59703
61112
  const body = Buffer.concat(chunks).toString("utf8");
59704
- resolve15(body ? JSON.parse(body) : {});
61113
+ resolve19(body ? JSON.parse(body) : {});
59705
61114
  } catch {
59706
61115
  reject(new ParseError("Malformed JSON body"));
59707
61116
  }
@@ -59944,12 +61353,12 @@ var init_a2a_frontend = __esm({
59944
61353
  }
59945
61354
  const port = this.config.port ?? 9e3;
59946
61355
  const host = this.config.host ?? "0.0.0.0";
59947
- await new Promise((resolve15) => {
61356
+ await new Promise((resolve19) => {
59948
61357
  this.server.listen(port, host, () => {
59949
61358
  const addr = this.server.address();
59950
61359
  this._boundPort = typeof addr === "object" && addr ? addr.port : port;
59951
61360
  logger.info(`A2A server listening on ${host}:${this._boundPort}`);
59952
- resolve15();
61361
+ resolve19();
59953
61362
  });
59954
61363
  });
59955
61364
  if (this.agentCard) {
@@ -59973,8 +61382,8 @@ var init_a2a_frontend = __esm({
59973
61382
  }
59974
61383
  this.streamManager.shutdown();
59975
61384
  if (this.server) {
59976
- await new Promise((resolve15, reject) => {
59977
- this.server.close((err) => err ? reject(err) : resolve15());
61385
+ await new Promise((resolve19, reject) => {
61386
+ this.server.close((err) => err ? reject(err) : resolve19());
59978
61387
  });
59979
61388
  this.server = null;
59980
61389
  }
@@ -60679,15 +62088,15 @@ function serializeRunState(state) {
60679
62088
  ])
60680
62089
  };
60681
62090
  }
60682
- var path28, fs24, StateMachineExecutionEngine;
62091
+ var path32, fs28, StateMachineExecutionEngine;
60683
62092
  var init_state_machine_execution_engine = __esm({
60684
62093
  "src/state-machine-execution-engine.ts"() {
60685
62094
  "use strict";
60686
62095
  init_runner();
60687
62096
  init_logger();
60688
62097
  init_sandbox_manager();
60689
- path28 = __toESM(require("path"));
60690
- fs24 = __toESM(require("fs"));
62098
+ path32 = __toESM(require("path"));
62099
+ fs28 = __toESM(require("fs"));
60691
62100
  StateMachineExecutionEngine = class _StateMachineExecutionEngine {
60692
62101
  workingDirectory;
60693
62102
  executionContext;
@@ -60919,8 +62328,8 @@ var init_state_machine_execution_engine = __esm({
60919
62328
  logger.debug(
60920
62329
  `[PolicyEngine] Loading enterprise policy engine (engine=${configWithTagFilter.policy.engine})`
60921
62330
  );
60922
- const { loadEnterprisePolicyEngine } = await import("./enterprise/loader");
60923
- context2.policyEngine = await loadEnterprisePolicyEngine(configWithTagFilter.policy);
62331
+ const { loadEnterprisePolicyEngine: loadEnterprisePolicyEngine2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
62332
+ context2.policyEngine = await loadEnterprisePolicyEngine2(configWithTagFilter.policy);
60924
62333
  logger.debug(
60925
62334
  `[PolicyEngine] Initialized: ${context2.policyEngine?.constructor?.name || "unknown"}`
60926
62335
  );
@@ -61074,9 +62483,9 @@ var init_state_machine_execution_engine = __esm({
61074
62483
  }
61075
62484
  const checkId = String(ev?.checkId || "unknown");
61076
62485
  const threadKey = ev?.threadKey || (channel && threadTs ? `${channel}:${threadTs}` : "session");
61077
- const baseDir = process.env.VISOR_SNAPSHOT_DIR || path28.resolve(process.cwd(), ".visor", "snapshots");
61078
- fs24.mkdirSync(baseDir, { recursive: true });
61079
- const filePath = path28.join(baseDir, `${threadKey}-${checkId}.json`);
62486
+ const baseDir = process.env.VISOR_SNAPSHOT_DIR || path32.resolve(process.cwd(), ".visor", "snapshots");
62487
+ fs28.mkdirSync(baseDir, { recursive: true });
62488
+ const filePath = path32.join(baseDir, `${threadKey}-${checkId}.json`);
61080
62489
  await this.saveSnapshotToFile(filePath);
61081
62490
  logger.info(`[Snapshot] Saved run snapshot: ${filePath}`);
61082
62491
  try {
@@ -61217,7 +62626,7 @@ var init_state_machine_execution_engine = __esm({
61217
62626
  * Does not include secrets. Intended for debugging and future resume support.
61218
62627
  */
61219
62628
  async saveSnapshotToFile(filePath) {
61220
- const fs25 = await import("fs/promises");
62629
+ const fs29 = await import("fs/promises");
61221
62630
  const ctx = this._lastContext;
61222
62631
  const runner = this._lastRunner;
61223
62632
  if (!ctx || !runner) {
@@ -61237,14 +62646,14 @@ var init_state_machine_execution_engine = __esm({
61237
62646
  journal: entries,
61238
62647
  requestedChecks: ctx.requestedChecks || []
61239
62648
  };
61240
- await fs25.writeFile(filePath, JSON.stringify(payload, null, 2), "utf8");
62649
+ await fs29.writeFile(filePath, JSON.stringify(payload, null, 2), "utf8");
61241
62650
  }
61242
62651
  /**
61243
62652
  * Load a snapshot JSON from file and return it. Resume support can build on this.
61244
62653
  */
61245
62654
  async loadSnapshotFromFile(filePath) {
61246
- const fs25 = await import("fs/promises");
61247
- const raw = await fs25.readFile(filePath, "utf8");
62655
+ const fs29 = await import("fs/promises");
62656
+ const raw = await fs29.readFile(filePath, "utf8");
61248
62657
  return JSON.parse(raw);
61249
62658
  }
61250
62659
  /**