@probelabs/visor 0.1.170 → 0.1.171-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 (130) hide show
  1. package/defaults/code-talk.yaml +39 -238
  2. package/defaults/intent-router.yaml +1 -0
  3. package/dist/agent-protocol/task-store.d.ts +5 -0
  4. package/dist/agent-protocol/task-store.d.ts.map +1 -1
  5. package/dist/agent-protocol/tasks-cli-handler.d.ts.map +1 -1
  6. package/dist/agent-protocol/track-execution.d.ts +34 -0
  7. package/dist/agent-protocol/track-execution.d.ts.map +1 -0
  8. package/dist/cli-main.d.ts.map +1 -1
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/defaults/code-talk.yaml +39 -238
  11. package/dist/defaults/intent-router.yaml +1 -0
  12. package/dist/frontends/host.d.ts +2 -0
  13. package/dist/frontends/host.d.ts.map +1 -1
  14. package/dist/generated/config-schema.d.ts +10 -6
  15. package/dist/generated/config-schema.d.ts.map +1 -1
  16. package/dist/generated/config-schema.json +10 -6
  17. package/dist/index.js +2534 -116
  18. package/dist/scheduler/scheduler.d.ts +4 -0
  19. package/dist/scheduler/scheduler.d.ts.map +1 -1
  20. package/dist/sdk/{a2a-frontend-YTXQGUDH.mjs → a2a-frontend-GUEGI5SX.mjs} +20 -3
  21. package/dist/sdk/a2a-frontend-GUEGI5SX.mjs.map +1 -0
  22. package/dist/sdk/{check-provider-registry-5CMLUEFG.mjs → check-provider-registry-7P2QIKJR.mjs} +8 -8
  23. package/dist/sdk/{check-provider-registry-STRAOYRJ.mjs → check-provider-registry-ZUU7KSKR.mjs} +7 -7
  24. package/dist/sdk/{chunk-WNLCRRQO.mjs → chunk-5SBX4KLG.mjs} +2 -2
  25. package/dist/sdk/{chunk-2CNT2EB3.mjs → chunk-6FXVWL6M.mjs} +3 -3
  26. package/dist/sdk/{chunk-KFKHU6CM.mjs → chunk-6VVXKXTI.mjs} +19 -2
  27. package/dist/sdk/chunk-6VVXKXTI.mjs.map +1 -0
  28. package/dist/sdk/{chunk-SVBF7Y2R.mjs → chunk-A2YVTICA.mjs} +11 -7
  29. package/dist/sdk/chunk-A2YVTICA.mjs.map +1 -0
  30. package/dist/sdk/{chunk-DLO46M5M.mjs → chunk-CXA3WUOB.mjs} +62 -23
  31. package/dist/sdk/chunk-CXA3WUOB.mjs.map +1 -0
  32. package/dist/sdk/{chunk-62PXPI6Q.mjs → chunk-GGNR347O.mjs} +8 -2
  33. package/dist/sdk/chunk-GGNR347O.mjs.map +1 -0
  34. package/dist/sdk/{chunk-NYQTQYGU.mjs → chunk-YCPJBOJB.mjs} +68 -29
  35. package/dist/sdk/chunk-YCPJBOJB.mjs.map +1 -0
  36. package/dist/sdk/{config-IHECYTNT.mjs → config-6GWD673K.mjs} +2 -2
  37. package/dist/sdk/{failure-condition-evaluator-NJO6DSL4.mjs → failure-condition-evaluator-5HRNHZCC.mjs} +4 -3
  38. package/dist/sdk/{github-frontend-BAPXDLBB.mjs → github-frontend-ZZRU6P43.mjs} +7 -7
  39. package/dist/sdk/{host-6HV5FMD7.mjs → host-A7UNRBQU.mjs} +3 -3
  40. package/dist/sdk/host-A7UNRBQU.mjs.map +1 -0
  41. package/dist/sdk/{host-K6IZWJG3.mjs → host-ECXTIDWG.mjs} +3 -3
  42. package/dist/sdk/host-ECXTIDWG.mjs.map +1 -0
  43. package/dist/sdk/knex-store-CRORFJE6.mjs +527 -0
  44. package/dist/sdk/knex-store-CRORFJE6.mjs.map +1 -0
  45. package/dist/sdk/loader-QMJFFST6.mjs +89 -0
  46. package/dist/sdk/loader-QMJFFST6.mjs.map +1 -0
  47. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs +655 -0
  48. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
  49. package/dist/sdk/{routing-RWZEXSRZ.mjs → routing-AMRQYI7J.mjs} +5 -4
  50. package/dist/sdk/{schedule-tool-JCKV47FU.mjs → schedule-tool-DGVJDHJM.mjs} +7 -7
  51. package/dist/sdk/{schedule-tool-TGWPINHO.mjs → schedule-tool-I6VG3ZVA.mjs} +8 -8
  52. package/dist/sdk/{schedule-tool-handler-OEBLE5AB.mjs → schedule-tool-handler-DFUC5S55.mjs} +8 -8
  53. package/dist/sdk/{schedule-tool-handler-UQWDPFP6.mjs → schedule-tool-handler-XLCSBU3E.mjs} +7 -7
  54. package/dist/sdk/sdk.d.mts +4 -0
  55. package/dist/sdk/sdk.d.ts +4 -0
  56. package/dist/sdk/sdk.js +1926 -408
  57. package/dist/sdk/sdk.js.map +1 -1
  58. package/dist/sdk/sdk.mjs +7 -7
  59. package/dist/sdk/{trace-helpers-ZYN23GBG.mjs → trace-helpers-4ZBZWH5W.mjs} +3 -2
  60. package/dist/sdk/track-execution-VWLQIGY7.mjs +82 -0
  61. package/dist/sdk/track-execution-VWLQIGY7.mjs.map +1 -0
  62. package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
  63. package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
  64. package/dist/sdk/{workflow-check-provider-OAOD3A5U.mjs → workflow-check-provider-AKXDIL2Y.mjs} +8 -8
  65. package/dist/sdk/{workflow-check-provider-VDSZR7Y5.mjs → workflow-check-provider-KQNLEQEY.mjs} +7 -7
  66. package/dist/slack/socket-runner.d.ts +4 -0
  67. package/dist/slack/socket-runner.d.ts.map +1 -1
  68. package/dist/telemetry/trace-helpers.d.ts.map +1 -1
  69. package/dist/tui/chat-runner.d.ts +4 -0
  70. package/dist/tui/chat-runner.d.ts.map +1 -1
  71. package/dist/types/cli.d.ts +2 -0
  72. package/dist/types/cli.d.ts.map +1 -1
  73. package/dist/types/config.d.ts +4 -0
  74. package/dist/types/config.d.ts.map +1 -1
  75. package/dist/utils/instance-id.d.ts +9 -0
  76. package/dist/utils/instance-id.d.ts.map +1 -0
  77. package/package.json +2 -2
  78. package/dist/output/traces/run-2026-03-07T15-43-18-430Z.ndjson +0 -138
  79. package/dist/output/traces/run-2026-03-07T15-43-56-196Z.ndjson +0 -2266
  80. package/dist/sdk/a2a-frontend-IPLHACI6.mjs +0 -1605
  81. package/dist/sdk/a2a-frontend-IPLHACI6.mjs.map +0 -1
  82. package/dist/sdk/a2a-frontend-YTXQGUDH.mjs.map +0 -1
  83. package/dist/sdk/check-provider-registry-T5FWS4SW.mjs +0 -30
  84. package/dist/sdk/chunk-47WAHGHK.mjs +0 -1502
  85. package/dist/sdk/chunk-47WAHGHK.mjs.map +0 -1
  86. package/dist/sdk/chunk-62PXPI6Q.mjs.map +0 -1
  87. package/dist/sdk/chunk-DLO46M5M.mjs.map +0 -1
  88. package/dist/sdk/chunk-FTUGQP5L.mjs +0 -739
  89. package/dist/sdk/chunk-KFKHU6CM.mjs.map +0 -1
  90. package/dist/sdk/chunk-LB77GR4Q.mjs +0 -44771
  91. package/dist/sdk/chunk-LB77GR4Q.mjs.map +0 -1
  92. package/dist/sdk/chunk-NYQTQYGU.mjs.map +0 -1
  93. package/dist/sdk/chunk-SVBF7Y2R.mjs.map +0 -1
  94. package/dist/sdk/chunk-WNLCRRQO.mjs.map +0 -1
  95. package/dist/sdk/chunk-ZM7ALGTE.mjs +0 -443
  96. package/dist/sdk/chunk-ZM7ALGTE.mjs.map +0 -1
  97. package/dist/sdk/failure-condition-evaluator-T67YFO2Z.mjs +0 -17
  98. package/dist/sdk/github-frontend-WPTKI4AY.mjs +0 -1386
  99. package/dist/sdk/github-frontend-WPTKI4AY.mjs.map +0 -1
  100. package/dist/sdk/host-6HV5FMD7.mjs.map +0 -1
  101. package/dist/sdk/host-K6IZWJG3.mjs.map +0 -1
  102. package/dist/sdk/routing-SAGHEUOA.mjs +0 -25
  103. package/dist/sdk/schedule-tool-H4G5ITNL.mjs +0 -36
  104. package/dist/sdk/schedule-tool-handler-UQWDPFP6.mjs.map +0 -1
  105. package/dist/sdk/schedule-tool-handler-ZDAD6SWM.mjs +0 -40
  106. package/dist/sdk/schedule-tool-handler-ZDAD6SWM.mjs.map +0 -1
  107. package/dist/sdk/trace-helpers-M7RVAZQ2.mjs +0 -25
  108. package/dist/sdk/trace-helpers-M7RVAZQ2.mjs.map +0 -1
  109. package/dist/sdk/trace-helpers-ZYN23GBG.mjs.map +0 -1
  110. package/dist/sdk/workflow-check-provider-FAO4AUGB.mjs +0 -30
  111. package/dist/sdk/workflow-check-provider-FAO4AUGB.mjs.map +0 -1
  112. package/dist/sdk/workflow-check-provider-OAOD3A5U.mjs.map +0 -1
  113. package/dist/sdk/workflow-check-provider-VDSZR7Y5.mjs.map +0 -1
  114. package/dist/traces/run-2026-03-07T15-43-18-430Z.ndjson +0 -138
  115. package/dist/traces/run-2026-03-07T15-43-56-196Z.ndjson +0 -2266
  116. /package/dist/sdk/{check-provider-registry-5CMLUEFG.mjs.map → check-provider-registry-7P2QIKJR.mjs.map} +0 -0
  117. /package/dist/sdk/{check-provider-registry-STRAOYRJ.mjs.map → check-provider-registry-ZUU7KSKR.mjs.map} +0 -0
  118. /package/dist/sdk/{chunk-FTUGQP5L.mjs.map → chunk-5SBX4KLG.mjs.map} +0 -0
  119. /package/dist/sdk/{chunk-2CNT2EB3.mjs.map → chunk-6FXVWL6M.mjs.map} +0 -0
  120. /package/dist/sdk/{check-provider-registry-T5FWS4SW.mjs.map → config-6GWD673K.mjs.map} +0 -0
  121. /package/dist/sdk/{config-IHECYTNT.mjs.map → failure-condition-evaluator-5HRNHZCC.mjs.map} +0 -0
  122. /package/dist/sdk/{github-frontend-BAPXDLBB.mjs.map → github-frontend-ZZRU6P43.mjs.map} +0 -0
  123. /package/dist/sdk/{failure-condition-evaluator-NJO6DSL4.mjs.map → routing-AMRQYI7J.mjs.map} +0 -0
  124. /package/dist/sdk/{failure-condition-evaluator-T67YFO2Z.mjs.map → schedule-tool-DGVJDHJM.mjs.map} +0 -0
  125. /package/dist/sdk/{routing-RWZEXSRZ.mjs.map → schedule-tool-I6VG3ZVA.mjs.map} +0 -0
  126. /package/dist/sdk/{routing-SAGHEUOA.mjs.map → schedule-tool-handler-DFUC5S55.mjs.map} +0 -0
  127. /package/dist/sdk/{schedule-tool-H4G5ITNL.mjs.map → schedule-tool-handler-XLCSBU3E.mjs.map} +0 -0
  128. /package/dist/sdk/{schedule-tool-JCKV47FU.mjs.map → trace-helpers-4ZBZWH5W.mjs.map} +0 -0
  129. /package/dist/sdk/{schedule-tool-TGWPINHO.mjs.map → workflow-check-provider-AKXDIL2Y.mjs.map} +0 -0
  130. /package/dist/sdk/{schedule-tool-handler-OEBLE5AB.mjs.map → workflow-check-provider-KQNLEQEY.mjs.map} +0 -0
package/dist/sdk/sdk.js CHANGED
@@ -570,6 +570,21 @@ var init_logger = __esm({
570
570
  }
571
571
  });
572
572
 
573
+ // src/utils/instance-id.ts
574
+ function getInstanceId() {
575
+ if (!_instanceId) {
576
+ _instanceId = generateHumanId();
577
+ }
578
+ return _instanceId;
579
+ }
580
+ var _instanceId;
581
+ var init_instance_id = __esm({
582
+ "src/utils/instance-id.ts"() {
583
+ "use strict";
584
+ init_human_id();
585
+ }
586
+ });
587
+
573
588
  // src/telemetry/fallback-ndjson.ts
574
589
  var fallback_ndjson_exports = {};
575
590
  __export(fallback_ndjson_exports, {
@@ -646,7 +661,7 @@ var require_package = __commonJS({
646
661
  "package.json"(exports2, module2) {
647
662
  module2.exports = {
648
663
  name: "@probelabs/visor",
649
- version: "0.1.170",
664
+ version: "0.1.42",
650
665
  main: "dist/index.js",
651
666
  bin: {
652
667
  visor: "./dist/index.js"
@@ -760,7 +775,7 @@ var require_package = __commonJS({
760
775
  "@opentelemetry/sdk-node": "^0.203.0",
761
776
  "@opentelemetry/sdk-trace-base": "^1.30.1",
762
777
  "@opentelemetry/semantic-conventions": "^1.30.1",
763
- "@probelabs/probe": "^0.6.0-rc286",
778
+ "@probelabs/probe": "^0.6.0-rc290",
764
779
  "@types/commander": "^2.12.0",
765
780
  "@types/uuid": "^10.0.0",
766
781
  acorn: "^8.16.0",
@@ -864,11 +879,11 @@ function getTracer() {
864
879
  }
865
880
  async function withActiveSpan(name, attrs, fn) {
866
881
  const tracer = getTracer();
867
- return await new Promise((resolve15, reject) => {
882
+ return await new Promise((resolve19, reject) => {
868
883
  const callback = async (span) => {
869
884
  try {
870
885
  const res = await fn(span);
871
- resolve15(res);
886
+ resolve19(res);
872
887
  } catch (err) {
873
888
  try {
874
889
  if (err instanceof Error) span.recordException(err);
@@ -939,25 +954,26 @@ function getVisorRunAttributes() {
939
954
  if (commitFull) {
940
955
  attrs["visor.commit.sha"] = commitFull;
941
956
  }
957
+ attrs["visor.instance_id"] = getInstanceId();
942
958
  return attrs;
943
959
  }
944
960
  function __getOrCreateNdjsonPath() {
945
961
  try {
946
962
  if (process.env.VISOR_TELEMETRY_SINK && process.env.VISOR_TELEMETRY_SINK !== "file")
947
963
  return null;
948
- const path28 = require("path");
949
- const fs25 = require("fs");
964
+ const path33 = require("path");
965
+ const fs29 = require("fs");
950
966
  if (process.env.VISOR_FALLBACK_TRACE_FILE) {
951
967
  __ndjsonPath = process.env.VISOR_FALLBACK_TRACE_FILE;
952
- const dir = path28.dirname(__ndjsonPath);
953
- 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 });
954
970
  return __ndjsonPath;
955
971
  }
956
- const outDir = process.env.VISOR_TRACE_DIR || path28.join(process.cwd(), "output", "traces");
957
- 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 });
958
974
  if (!__ndjsonPath) {
959
975
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
960
- __ndjsonPath = path28.join(outDir, `${ts}.ndjson`);
976
+ __ndjsonPath = path33.join(outDir, `${ts}.ndjson`);
961
977
  }
962
978
  return __ndjsonPath;
963
979
  } catch {
@@ -966,11 +982,11 @@ function __getOrCreateNdjsonPath() {
966
982
  }
967
983
  function _appendRunMarker() {
968
984
  try {
969
- const fs25 = require("fs");
985
+ const fs29 = require("fs");
970
986
  const p = __getOrCreateNdjsonPath();
971
987
  if (!p) return;
972
988
  const line = { name: "visor.run", attributes: { started: true } };
973
- fs25.appendFileSync(p, JSON.stringify(line) + "\n", "utf8");
989
+ fs29.appendFileSync(p, JSON.stringify(line) + "\n", "utf8");
974
990
  } catch {
975
991
  }
976
992
  }
@@ -979,6 +995,7 @@ var init_trace_helpers = __esm({
979
995
  "src/telemetry/trace-helpers.ts"() {
980
996
  "use strict";
981
997
  init_lazy_otel();
998
+ init_instance_id();
982
999
  __ndjsonPath = null;
983
1000
  }
984
1001
  });
@@ -3193,7 +3210,7 @@ var init_failure_condition_evaluator = __esm({
3193
3210
  */
3194
3211
  evaluateExpression(condition, context2) {
3195
3212
  try {
3196
- const normalize4 = (expr) => {
3213
+ const normalize8 = (expr) => {
3197
3214
  const trimmed = expr.trim();
3198
3215
  if (!/[\n;]/.test(trimmed)) return trimmed;
3199
3216
  const parts = trimmed.split(/[\n;]+/).map((s) => s.trim()).filter((s) => s.length > 0 && !s.startsWith("//"));
@@ -3351,7 +3368,7 @@ var init_failure_condition_evaluator = __esm({
3351
3368
  try {
3352
3369
  exec2 = this.sandbox.compile(`return (${raw});`);
3353
3370
  } catch {
3354
- const normalizedExpr = normalize4(condition);
3371
+ const normalizedExpr = normalize8(condition);
3355
3372
  exec2 = this.sandbox.compile(`return (${normalizedExpr});`);
3356
3373
  }
3357
3374
  const result = exec2(scope).run();
@@ -3734,9 +3751,9 @@ function configureLiquidWithExtensions(liquid) {
3734
3751
  });
3735
3752
  liquid.registerFilter("get", (obj, pathExpr) => {
3736
3753
  if (obj == null) return void 0;
3737
- const path28 = typeof pathExpr === "string" ? pathExpr : String(pathExpr || "");
3738
- if (!path28) return obj;
3739
- const parts = path28.split(".");
3754
+ const path33 = typeof pathExpr === "string" ? pathExpr : String(pathExpr || "");
3755
+ if (!path33) return obj;
3756
+ const parts = path33.split(".");
3740
3757
  let cur = obj;
3741
3758
  for (const p of parts) {
3742
3759
  if (cur == null) return void 0;
@@ -3855,9 +3872,9 @@ function configureLiquidWithExtensions(liquid) {
3855
3872
  }
3856
3873
  }
3857
3874
  const defaultRole = typeof rolesCfg.default === "string" && rolesCfg.default.trim() ? rolesCfg.default.trim() : void 0;
3858
- const getNested = (obj, path28) => {
3859
- if (!obj || !path28) return void 0;
3860
- const parts = path28.split(".");
3875
+ const getNested = (obj, path33) => {
3876
+ if (!obj || !path33) return void 0;
3877
+ const parts = path33.split(".");
3861
3878
  let cur = obj;
3862
3879
  for (const p of parts) {
3863
3880
  if (cur == null) return void 0;
@@ -6409,8 +6426,8 @@ var init_dependency_gating = __esm({
6409
6426
  async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
6410
6427
  try {
6411
6428
  const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
6412
- const fs25 = await import("fs/promises");
6413
- const path28 = await import("path");
6429
+ const fs29 = await import("fs/promises");
6430
+ const path33 = await import("path");
6414
6431
  const schemaRaw = checkConfig.schema || "plain";
6415
6432
  const schema = typeof schemaRaw === "string" ? schemaRaw : "code-review";
6416
6433
  let templateContent;
@@ -6418,24 +6435,24 @@ async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
6418
6435
  templateContent = String(checkConfig.template.content);
6419
6436
  } else if (checkConfig.template && checkConfig.template.file) {
6420
6437
  const file = String(checkConfig.template.file);
6421
- const resolved = path28.resolve(process.cwd(), file);
6422
- templateContent = await fs25.readFile(resolved, "utf-8");
6438
+ const resolved = path33.resolve(process.cwd(), file);
6439
+ templateContent = await fs29.readFile(resolved, "utf-8");
6423
6440
  } else if (schema && schema !== "plain") {
6424
6441
  const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
6425
6442
  if (sanitized) {
6426
6443
  const candidatePaths = [
6427
- path28.join(__dirname, "output", sanitized, "template.liquid"),
6444
+ path33.join(__dirname, "output", sanitized, "template.liquid"),
6428
6445
  // bundled: dist/output/
6429
- path28.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
6446
+ path33.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
6430
6447
  // source: output/
6431
- path28.join(process.cwd(), "output", sanitized, "template.liquid"),
6448
+ path33.join(process.cwd(), "output", sanitized, "template.liquid"),
6432
6449
  // fallback: cwd/output/
6433
- path28.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
6450
+ path33.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
6434
6451
  // fallback: cwd/dist/output/
6435
6452
  ];
6436
6453
  for (const p of candidatePaths) {
6437
6454
  try {
6438
- templateContent = await fs25.readFile(p, "utf-8");
6455
+ templateContent = await fs29.readFile(p, "utf-8");
6439
6456
  if (templateContent) break;
6440
6457
  } catch {
6441
6458
  }
@@ -6840,7 +6857,7 @@ async function processDiffWithOutline(diffContent) {
6840
6857
  }
6841
6858
  try {
6842
6859
  const originalProbePath = process.env.PROBE_PATH;
6843
- const fs25 = require("fs");
6860
+ const fs29 = require("fs");
6844
6861
  const possiblePaths = [
6845
6862
  // Relative to current working directory (most common in production)
6846
6863
  path6.join(process.cwd(), "node_modules/@probelabs/probe/bin/probe-binary"),
@@ -6851,7 +6868,7 @@ async function processDiffWithOutline(diffContent) {
6851
6868
  ];
6852
6869
  let probeBinaryPath;
6853
6870
  for (const candidatePath of possiblePaths) {
6854
- if (fs25.existsSync(candidatePath)) {
6871
+ if (fs29.existsSync(candidatePath)) {
6855
6872
  probeBinaryPath = candidatePath;
6856
6873
  break;
6857
6874
  }
@@ -6958,7 +6975,7 @@ async function renderMermaidToPng(mermaidCode) {
6958
6975
  if (chromiumPath) {
6959
6976
  env.PUPPETEER_EXECUTABLE_PATH = chromiumPath;
6960
6977
  }
6961
- const result = await new Promise((resolve15) => {
6978
+ const result = await new Promise((resolve19) => {
6962
6979
  const proc = (0, import_child_process.spawn)(
6963
6980
  "npx",
6964
6981
  [
@@ -6988,13 +7005,13 @@ async function renderMermaidToPng(mermaidCode) {
6988
7005
  });
6989
7006
  proc.on("close", (code) => {
6990
7007
  if (code === 0) {
6991
- resolve15({ success: true });
7008
+ resolve19({ success: true });
6992
7009
  } else {
6993
- resolve15({ success: false, error: stderr || `Exit code ${code}` });
7010
+ resolve19({ success: false, error: stderr || `Exit code ${code}` });
6994
7011
  }
6995
7012
  });
6996
7013
  proc.on("error", (err) => {
6997
- resolve15({ success: false, error: err.message });
7014
+ resolve19({ success: false, error: err.message });
6998
7015
  });
6999
7016
  });
7000
7017
  if (!result.success) {
@@ -8156,8 +8173,8 @@ ${schemaString}`);
8156
8173
  }
8157
8174
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8158
8175
  try {
8159
- const fs25 = require("fs");
8160
- const path28 = require("path");
8176
+ const fs29 = require("fs");
8177
+ const path33 = require("path");
8161
8178
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8162
8179
  const provider = this.config.provider || "auto";
8163
8180
  const model = this.config.model || "default";
@@ -8271,20 +8288,20 @@ ${"=".repeat(60)}
8271
8288
  `;
8272
8289
  readableVersion += `${"=".repeat(60)}
8273
8290
  `;
8274
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path28.join(process.cwd(), "debug-artifacts");
8275
- if (!fs25.existsSync(debugArtifactsDir)) {
8276
- 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 });
8277
8294
  }
8278
- const debugFile = path28.join(
8295
+ const debugFile = path33.join(
8279
8296
  debugArtifactsDir,
8280
8297
  `prompt-${_checkName || "unknown"}-${timestamp}.json`
8281
8298
  );
8282
- fs25.writeFileSync(debugFile, debugJson, "utf-8");
8283
- const readableFile = path28.join(
8299
+ fs29.writeFileSync(debugFile, debugJson, "utf-8");
8300
+ const readableFile = path33.join(
8284
8301
  debugArtifactsDir,
8285
8302
  `prompt-${_checkName || "unknown"}-${timestamp}.txt`
8286
8303
  );
8287
- fs25.writeFileSync(readableFile, readableVersion, "utf-8");
8304
+ fs29.writeFileSync(readableFile, readableVersion, "utf-8");
8288
8305
  log(`
8289
8306
  \u{1F4BE} Full debug info saved to:`);
8290
8307
  log(` JSON: ${debugFile}`);
@@ -8317,8 +8334,8 @@ ${"=".repeat(60)}
8317
8334
  log(`\u{1F4E4} Response length: ${response.length} characters`);
8318
8335
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8319
8336
  try {
8320
- const fs25 = require("fs");
8321
- const path28 = require("path");
8337
+ const fs29 = require("fs");
8338
+ const path33 = require("path");
8322
8339
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8323
8340
  const agentAny2 = agent;
8324
8341
  let fullHistory = [];
@@ -8329,8 +8346,8 @@ ${"=".repeat(60)}
8329
8346
  } else if (agentAny2._messages) {
8330
8347
  fullHistory = agentAny2._messages;
8331
8348
  }
8332
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path28.join(process.cwd(), "debug-artifacts");
8333
- const sessionBase = path28.join(
8349
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8350
+ const sessionBase = path33.join(
8334
8351
  debugArtifactsDir,
8335
8352
  `session-${_checkName || "unknown"}-${timestamp}`
8336
8353
  );
@@ -8342,7 +8359,7 @@ ${"=".repeat(60)}
8342
8359
  schema: effectiveSchema,
8343
8360
  totalMessages: fullHistory.length
8344
8361
  };
8345
- fs25.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
8362
+ fs29.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
8346
8363
  let readable = `=============================================================
8347
8364
  `;
8348
8365
  readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
@@ -8369,7 +8386,7 @@ ${"=".repeat(60)}
8369
8386
  `;
8370
8387
  readable += content + "\n";
8371
8388
  });
8372
- fs25.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
8389
+ fs29.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
8373
8390
  log(`\u{1F4BE} Complete session history saved:`);
8374
8391
  log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
8375
8392
  } catch (error) {
@@ -8378,11 +8395,11 @@ ${"=".repeat(60)}
8378
8395
  }
8379
8396
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8380
8397
  try {
8381
- const fs25 = require("fs");
8382
- const path28 = require("path");
8398
+ const fs29 = require("fs");
8399
+ const path33 = require("path");
8383
8400
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8384
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path28.join(process.cwd(), "debug-artifacts");
8385
- const responseFile = path28.join(
8401
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8402
+ const responseFile = path33.join(
8386
8403
  debugArtifactsDir,
8387
8404
  `response-${_checkName || "unknown"}-${timestamp}.txt`
8388
8405
  );
@@ -8415,7 +8432,7 @@ ${"=".repeat(60)}
8415
8432
  `;
8416
8433
  responseContent += `${"=".repeat(60)}
8417
8434
  `;
8418
- fs25.writeFileSync(responseFile, responseContent, "utf-8");
8435
+ fs29.writeFileSync(responseFile, responseContent, "utf-8");
8419
8436
  log(`\u{1F4BE} Response saved to: ${responseFile}`);
8420
8437
  } catch (error) {
8421
8438
  log(`\u26A0\uFE0F Could not save response file: ${error}`);
@@ -8431,9 +8448,9 @@ ${"=".repeat(60)}
8431
8448
  await agentAny._telemetryConfig.shutdown();
8432
8449
  log(`\u{1F4CA} OpenTelemetry trace saved to: ${agentAny._traceFilePath}`);
8433
8450
  if (process.env.GITHUB_ACTIONS) {
8434
- const fs25 = require("fs");
8435
- if (fs25.existsSync(agentAny._traceFilePath)) {
8436
- const stats = fs25.statSync(agentAny._traceFilePath);
8451
+ const fs29 = require("fs");
8452
+ if (fs29.existsSync(agentAny._traceFilePath)) {
8453
+ const stats = fs29.statSync(agentAny._traceFilePath);
8437
8454
  console.log(
8438
8455
  `::notice title=AI Trace Saved::${agentAny._traceFilePath} (${stats.size} bytes)`
8439
8456
  );
@@ -8646,9 +8663,9 @@ ${schemaString}`);
8646
8663
  const model = this.config.model || "default";
8647
8664
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8648
8665
  try {
8649
- const fs25 = require("fs");
8650
- const path28 = require("path");
8651
- const os2 = require("os");
8666
+ const fs29 = require("fs");
8667
+ const path33 = require("path");
8668
+ const os3 = require("os");
8652
8669
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8653
8670
  const debugData = {
8654
8671
  timestamp,
@@ -8720,19 +8737,19 @@ ${"=".repeat(60)}
8720
8737
  `;
8721
8738
  readableVersion += `${"=".repeat(60)}
8722
8739
  `;
8723
- const tempDir = os2.tmpdir();
8724
- const promptFile = path28.join(tempDir, `visor-prompt-${timestamp}.txt`);
8725
- 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");
8726
8743
  log(`
8727
8744
  \u{1F4BE} Prompt saved to: ${promptFile}`);
8728
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path28.join(process.cwd(), "debug-artifacts");
8745
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8729
8746
  try {
8730
- const base = path28.join(
8747
+ const base = path33.join(
8731
8748
  debugArtifactsDir,
8732
8749
  `prompt-${_checkName || "unknown"}-${timestamp}`
8733
8750
  );
8734
- fs25.writeFileSync(base + ".json", debugJson, "utf-8");
8735
- 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");
8736
8753
  log(`
8737
8754
  \u{1F4BE} Full debug info saved to directory: ${debugArtifactsDir}`);
8738
8755
  } catch {
@@ -8777,8 +8794,8 @@ $ ${cliCommand}
8777
8794
  log(`\u{1F4E4} Response length: ${response.length} characters`);
8778
8795
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8779
8796
  try {
8780
- const fs25 = require("fs");
8781
- const path28 = require("path");
8797
+ const fs29 = require("fs");
8798
+ const path33 = require("path");
8782
8799
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8783
8800
  const agentAny = agent;
8784
8801
  let fullHistory = [];
@@ -8789,8 +8806,8 @@ $ ${cliCommand}
8789
8806
  } else if (agentAny._messages) {
8790
8807
  fullHistory = agentAny._messages;
8791
8808
  }
8792
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path28.join(process.cwd(), "debug-artifacts");
8793
- const sessionBase = path28.join(
8809
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8810
+ const sessionBase = path33.join(
8794
8811
  debugArtifactsDir,
8795
8812
  `session-${_checkName || "unknown"}-${timestamp}`
8796
8813
  );
@@ -8802,7 +8819,7 @@ $ ${cliCommand}
8802
8819
  schema: effectiveSchema,
8803
8820
  totalMessages: fullHistory.length
8804
8821
  };
8805
- fs25.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
8822
+ fs29.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
8806
8823
  let readable = `=============================================================
8807
8824
  `;
8808
8825
  readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
@@ -8829,7 +8846,7 @@ ${"=".repeat(60)}
8829
8846
  `;
8830
8847
  readable += content + "\n";
8831
8848
  });
8832
- fs25.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
8849
+ fs29.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
8833
8850
  log(`\u{1F4BE} Complete session history saved:`);
8834
8851
  log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
8835
8852
  } catch (error) {
@@ -8838,11 +8855,11 @@ ${"=".repeat(60)}
8838
8855
  }
8839
8856
  if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
8840
8857
  try {
8841
- const fs25 = require("fs");
8842
- const path28 = require("path");
8858
+ const fs29 = require("fs");
8859
+ const path33 = require("path");
8843
8860
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8844
- const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path28.join(process.cwd(), "debug-artifacts");
8845
- const responseFile = path28.join(
8861
+ const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
8862
+ const responseFile = path33.join(
8846
8863
  debugArtifactsDir,
8847
8864
  `response-${_checkName || "unknown"}-${timestamp}.txt`
8848
8865
  );
@@ -8875,7 +8892,7 @@ ${"=".repeat(60)}
8875
8892
  `;
8876
8893
  responseContent += `${"=".repeat(60)}
8877
8894
  `;
8878
- fs25.writeFileSync(responseFile, responseContent, "utf-8");
8895
+ fs29.writeFileSync(responseFile, responseContent, "utf-8");
8879
8896
  log(`\u{1F4BE} Response saved to: ${responseFile}`);
8880
8897
  } catch (error) {
8881
8898
  log(`\u26A0\uFE0F Could not save response file: ${error}`);
@@ -8893,9 +8910,9 @@ ${"=".repeat(60)}
8893
8910
  await telemetry.shutdown();
8894
8911
  log(`\u{1F4CA} OpenTelemetry trace saved to: ${traceFilePath}`);
8895
8912
  if (process.env.GITHUB_ACTIONS) {
8896
- const fs25 = require("fs");
8897
- if (fs25.existsSync(traceFilePath)) {
8898
- const stats = fs25.statSync(traceFilePath);
8913
+ const fs29 = require("fs");
8914
+ if (fs29.existsSync(traceFilePath)) {
8915
+ const stats = fs29.statSync(traceFilePath);
8899
8916
  console.log(
8900
8917
  `::notice title=AI Trace Saved::OpenTelemetry trace file size: ${stats.size} bytes`
8901
8918
  );
@@ -8933,8 +8950,8 @@ ${"=".repeat(60)}
8933
8950
  * Load schema content from schema files or inline definitions
8934
8951
  */
8935
8952
  async loadSchemaContent(schema) {
8936
- const fs25 = require("fs").promises;
8937
- const path28 = require("path");
8953
+ const fs29 = require("fs").promises;
8954
+ const path33 = require("path");
8938
8955
  if (typeof schema === "object" && schema !== null) {
8939
8956
  log("\u{1F4CB} Using inline schema object from configuration");
8940
8957
  return JSON.stringify(schema);
@@ -8947,14 +8964,14 @@ ${"=".repeat(60)}
8947
8964
  }
8948
8965
  } catch {
8949
8966
  }
8950
- if ((schema.startsWith("./") || schema.includes(".json")) && !path28.isAbsolute(schema)) {
8967
+ if ((schema.startsWith("./") || schema.includes(".json")) && !path33.isAbsolute(schema)) {
8951
8968
  if (schema.includes("..") || schema.includes("\0")) {
8952
8969
  throw new Error("Invalid schema path: path traversal not allowed");
8953
8970
  }
8954
8971
  try {
8955
- const schemaPath = path28.resolve(process.cwd(), schema);
8972
+ const schemaPath = path33.resolve(process.cwd(), schema);
8956
8973
  log(`\u{1F4CB} Loading custom schema from file: ${schemaPath}`);
8957
- const schemaContent = await fs25.readFile(schemaPath, "utf-8");
8974
+ const schemaContent = await fs29.readFile(schemaPath, "utf-8");
8958
8975
  return schemaContent.trim();
8959
8976
  } catch (error) {
8960
8977
  throw new Error(
@@ -8968,22 +8985,22 @@ ${"=".repeat(60)}
8968
8985
  }
8969
8986
  const candidatePaths = [
8970
8987
  // GitHub Action bundle location
8971
- path28.join(__dirname, "output", sanitizedSchemaName, "schema.json"),
8988
+ path33.join(__dirname, "output", sanitizedSchemaName, "schema.json"),
8972
8989
  // Historical fallback when src/output was inadvertently bundled as output1/
8973
- path28.join(__dirname, "output1", sanitizedSchemaName, "schema.json"),
8990
+ path33.join(__dirname, "output1", sanitizedSchemaName, "schema.json"),
8974
8991
  // Local dev (repo root)
8975
- path28.join(process.cwd(), "output", sanitizedSchemaName, "schema.json")
8992
+ path33.join(process.cwd(), "output", sanitizedSchemaName, "schema.json")
8976
8993
  ];
8977
8994
  for (const schemaPath of candidatePaths) {
8978
8995
  try {
8979
- const schemaContent = await fs25.readFile(schemaPath, "utf-8");
8996
+ const schemaContent = await fs29.readFile(schemaPath, "utf-8");
8980
8997
  return schemaContent.trim();
8981
8998
  } catch {
8982
8999
  }
8983
9000
  }
8984
- const distPath = path28.join(__dirname, "output", sanitizedSchemaName, "schema.json");
8985
- const distAltPath = path28.join(__dirname, "output1", sanitizedSchemaName, "schema.json");
8986
- const cwdPath = path28.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");
8987
9004
  throw new Error(
8988
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.`
8989
9006
  );
@@ -9228,7 +9245,7 @@ ${"=".repeat(60)}
9228
9245
  * Generate mock response for testing
9229
9246
  */
9230
9247
  async generateMockResponse(_prompt, _checkName, _schema) {
9231
- await new Promise((resolve15) => setTimeout(resolve15, 500));
9248
+ await new Promise((resolve19) => setTimeout(resolve19, 500));
9232
9249
  const name = (_checkName || "").toLowerCase();
9233
9250
  if (name.includes("extract-facts")) {
9234
9251
  const arr = Array.from({ length: 6 }, (_, i) => ({
@@ -9589,7 +9606,7 @@ var init_command_executor = __esm({
9589
9606
  * Execute command with stdin input
9590
9607
  */
9591
9608
  executeWithStdin(command, options) {
9592
- return new Promise((resolve15, reject) => {
9609
+ return new Promise((resolve19, reject) => {
9593
9610
  const childProcess = (0, import_child_process2.exec)(
9594
9611
  command,
9595
9612
  {
@@ -9601,7 +9618,7 @@ var init_command_executor = __esm({
9601
9618
  if (error && error.killed && (error.code === "ETIMEDOUT" || error.signal === "SIGTERM")) {
9602
9619
  reject(new Error(`Command timed out after ${options.timeout || 3e4}ms`));
9603
9620
  } else {
9604
- resolve15({
9621
+ resolve19({
9605
9622
  stdout: stdout || "",
9606
9623
  stderr: stderr || "",
9607
9624
  exitCode: error ? error.code || 1 : 0
@@ -12432,6 +12449,10 @@ var init_config_schema = __esm({
12432
12449
  agent_protocol: {
12433
12450
  $ref: "#/definitions/AgentProtocolConfig",
12434
12451
  description: "Agent protocol (A2A) server configuration"
12452
+ },
12453
+ task_tracking: {
12454
+ type: "boolean",
12455
+ description: "Enable cross-frontend task tracking (default: false). When true, all workflow executions (CLI, Slack, TUI, Scheduler) are recorded in a shared SQLite TaskStore visible via `visor tasks`."
12435
12456
  }
12436
12457
  },
12437
12458
  required: ["version"],
@@ -13168,7 +13189,7 @@ var init_config_schema = __esm({
13168
13189
  description: "Arguments/inputs for the workflow"
13169
13190
  },
13170
13191
  overrides: {
13171
- $ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-13844-28438-src_types_config.ts-0-55681%3E%3E",
13192
+ $ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-13844-28438-src_types_config.ts-0-55916%3E%3E",
13172
13193
  description: "Override specific step configurations in the workflow"
13173
13194
  },
13174
13195
  output_mapping: {
@@ -13184,7 +13205,7 @@ var init_config_schema = __esm({
13184
13205
  description: "Config file path - alternative to workflow ID (loads a Visor config file as workflow)"
13185
13206
  },
13186
13207
  workflow_overrides: {
13187
- $ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-13844-28438-src_types_config.ts-0-55681%3E%3E",
13208
+ $ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-13844-28438-src_types_config.ts-0-55916%3E%3E",
13188
13209
  description: "Alias for overrides - workflow step overrides (backward compatibility)"
13189
13210
  },
13190
13211
  ref: {
@@ -13882,7 +13903,7 @@ var init_config_schema = __esm({
13882
13903
  description: "Custom output name (defaults to workflow name)"
13883
13904
  },
13884
13905
  overrides: {
13885
- $ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-13844-28438-src_types_config.ts-0-55681%3E%3E",
13906
+ $ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-13844-28438-src_types_config.ts-0-55916%3E%3E",
13886
13907
  description: "Step overrides"
13887
13908
  },
13888
13909
  output_mapping: {
@@ -13897,13 +13918,13 @@ var init_config_schema = __esm({
13897
13918
  "^x-": {}
13898
13919
  }
13899
13920
  },
13900
- "Record<string,Partial<interface-src_types_config.ts-13844-28438-src_types_config.ts-0-55681>>": {
13921
+ "Record<string,Partial<interface-src_types_config.ts-13844-28438-src_types_config.ts-0-55916>>": {
13901
13922
  type: "object",
13902
13923
  additionalProperties: {
13903
- $ref: "#/definitions/Partial%3Cinterface-src_types_config.ts-13844-28438-src_types_config.ts-0-55681%3E"
13924
+ $ref: "#/definitions/Partial%3Cinterface-src_types_config.ts-13844-28438-src_types_config.ts-0-55916%3E"
13904
13925
  }
13905
13926
  },
13906
- "Partial<interface-src_types_config.ts-13844-28438-src_types_config.ts-0-55681>": {
13927
+ "Partial<interface-src_types_config.ts-13844-28438-src_types_config.ts-0-55916>": {
13907
13928
  type: "object",
13908
13929
  additionalProperties: false
13909
13930
  },
@@ -17977,17 +17998,17 @@ var init_workflow_check_provider = __esm({
17977
17998
  * so it can be executed by the state machine as a nested workflow.
17978
17999
  */
17979
18000
  async loadWorkflowFromConfigPath(sourcePath, baseDir) {
17980
- const path28 = require("path");
17981
- const fs25 = require("fs");
18001
+ const path33 = require("path");
18002
+ const fs29 = require("fs");
17982
18003
  const yaml5 = require("js-yaml");
17983
- const resolved = path28.isAbsolute(sourcePath) ? sourcePath : path28.resolve(baseDir, sourcePath);
17984
- if (!fs25.existsSync(resolved)) {
18004
+ const resolved = path33.isAbsolute(sourcePath) ? sourcePath : path33.resolve(baseDir, sourcePath);
18005
+ if (!fs29.existsSync(resolved)) {
17985
18006
  throw new Error(`Workflow config not found at: ${resolved}`);
17986
18007
  }
17987
- const rawContent = fs25.readFileSync(resolved, "utf8");
18008
+ const rawContent = fs29.readFileSync(resolved, "utf8");
17988
18009
  const rawData = yaml5.load(rawContent);
17989
18010
  if (rawData.imports && Array.isArray(rawData.imports)) {
17990
- const configDir = path28.dirname(resolved);
18011
+ const configDir = path33.dirname(resolved);
17991
18012
  for (const source of rawData.imports) {
17992
18013
  const results = await this.registry.import(source, {
17993
18014
  basePath: configDir,
@@ -18017,8 +18038,8 @@ ${errors}`);
18017
18038
  if (!steps || Object.keys(steps).length === 0) {
18018
18039
  throw new Error(`Config '${resolved}' does not contain any steps to execute as a workflow`);
18019
18040
  }
18020
- const id = path28.basename(resolved).replace(/\.(ya?ml)$/i, "");
18021
- const name = loaded.name || `Workflow from ${path28.basename(resolved)}`;
18041
+ const id = path33.basename(resolved).replace(/\.(ya?ml)$/i, "");
18042
+ const name = loaded.name || `Workflow from ${path33.basename(resolved)}`;
18022
18043
  const workflowDef = {
18023
18044
  id,
18024
18045
  name,
@@ -18824,8 +18845,8 @@ async function createStoreBackend(storageConfig, haConfig) {
18824
18845
  case "mssql": {
18825
18846
  try {
18826
18847
  const loaderPath = "../../enterprise/loader";
18827
- const { loadEnterpriseStoreBackend } = await import(loaderPath);
18828
- return await loadEnterpriseStoreBackend(driver, storageConfig, haConfig);
18848
+ const { loadEnterpriseStoreBackend: loadEnterpriseStoreBackend2 } = await import(loaderPath);
18849
+ return await loadEnterpriseStoreBackend2(driver, storageConfig, haConfig);
18829
18850
  } catch (err) {
18830
18851
  const msg = err instanceof Error ? err.message : String(err);
18831
18852
  logger.error(`[StoreFactory] Failed to load enterprise ${driver} backend: ${msg}`);
@@ -19431,6 +19452,74 @@ var init_github_auth = __esm({
19431
19452
  }
19432
19453
  });
19433
19454
 
19455
+ // src/agent-protocol/track-execution.ts
19456
+ var track_execution_exports = {};
19457
+ __export(track_execution_exports, {
19458
+ trackExecution: () => trackExecution
19459
+ });
19460
+ async function trackExecution(opts, executor) {
19461
+ const { taskStore, source, configPath, metadata, messageText } = opts;
19462
+ const configName = configPath ? import_path7.default.basename(configPath, import_path7.default.extname(configPath)) : void 0;
19463
+ const workflowId = configName && opts.workflowId ? `${configName}#${opts.workflowId}` : opts.workflowId;
19464
+ const requestMessage = {
19465
+ message_id: import_crypto2.default.randomUUID(),
19466
+ role: "user",
19467
+ parts: [{ text: messageText }]
19468
+ };
19469
+ const task = taskStore.createTask({
19470
+ contextId: import_crypto2.default.randomUUID(),
19471
+ requestMessage,
19472
+ workflowId,
19473
+ requestMetadata: {
19474
+ source,
19475
+ instance_id: getInstanceId(),
19476
+ trace_id: trace.getActiveSpan()?.spanContext().traceId || void 0,
19477
+ ...metadata
19478
+ }
19479
+ });
19480
+ const instanceId = getInstanceId();
19481
+ taskStore.updateTaskState(task.id, "working");
19482
+ taskStore.claimTask(task.id, instanceId);
19483
+ logger.info(
19484
+ `[TaskTracking] Task ${task.id} started (source=${source}, workflow=${workflowId || "-"}, instance=${instanceId})`
19485
+ );
19486
+ try {
19487
+ const result = await executor();
19488
+ const completedMsg = {
19489
+ message_id: import_crypto2.default.randomUUID(),
19490
+ role: "agent",
19491
+ parts: [{ text: "Execution completed" }]
19492
+ };
19493
+ taskStore.updateTaskState(task.id, "completed", completedMsg);
19494
+ logger.info(`[TaskTracking] Task ${task.id} completed`);
19495
+ return { task, result };
19496
+ } catch (err) {
19497
+ const errorText = err instanceof Error ? err.message : String(err);
19498
+ const failMessage = {
19499
+ message_id: import_crypto2.default.randomUUID(),
19500
+ role: "agent",
19501
+ parts: [{ text: errorText }]
19502
+ };
19503
+ try {
19504
+ taskStore.updateTaskState(task.id, "failed", failMessage);
19505
+ logger.info(`[TaskTracking] Task ${task.id} failed: ${errorText}`);
19506
+ } catch {
19507
+ }
19508
+ throw err;
19509
+ }
19510
+ }
19511
+ var import_crypto2, import_path7;
19512
+ var init_track_execution = __esm({
19513
+ "src/agent-protocol/track-execution.ts"() {
19514
+ "use strict";
19515
+ import_crypto2 = __toESM(require("crypto"));
19516
+ import_path7 = __toESM(require("path"));
19517
+ init_logger();
19518
+ init_lazy_otel();
19519
+ init_instance_id();
19520
+ }
19521
+ });
19522
+
19434
19523
  // src/scheduler/scheduler.ts
19435
19524
  function getScheduler(visorConfig, config) {
19436
19525
  if (!schedulerInstance && visorConfig) {
@@ -19460,6 +19549,8 @@ var init_scheduler = __esm({
19460
19549
  outputAdapters = /* @__PURE__ */ new Map();
19461
19550
  executionContext = {};
19462
19551
  contextEnricher;
19552
+ taskStore;
19553
+ configPath;
19463
19554
  // HA fields
19464
19555
  haConfig;
19465
19556
  nodeId;
@@ -19485,6 +19576,11 @@ var init_scheduler = __esm({
19485
19576
  setEngine(engine) {
19486
19577
  this.engine = engine;
19487
19578
  }
19579
+ /** Set shared task store for execution tracking. */
19580
+ setTaskStore(store, configPath) {
19581
+ this.taskStore = store;
19582
+ this.configPath = configPath;
19583
+ }
19488
19584
  /**
19489
19585
  * Set the execution context (e.g., Slack client) for workflow executions
19490
19586
  */
@@ -20026,7 +20122,7 @@ var init_scheduler = __esm({
20026
20122
  } catch {
20027
20123
  }
20028
20124
  const { engine: runEngine, config: cfgForRun } = this.prepareExecution(schedule);
20029
- await runEngine.executeChecks({
20125
+ const schedExecFn = () => runEngine.executeChecks({
20030
20126
  checks: checksToRun,
20031
20127
  showDetails: true,
20032
20128
  outputFormat: "json",
@@ -20035,6 +20131,22 @@ var init_scheduler = __esm({
20035
20131
  debug: process.env.VISOR_DEBUG === "true",
20036
20132
  inputs: schedule.workflowInputs
20037
20133
  });
20134
+ if (this.taskStore) {
20135
+ const { trackExecution: trackExecution2 } = await Promise.resolve().then(() => (init_track_execution(), track_execution_exports));
20136
+ await trackExecution2(
20137
+ {
20138
+ taskStore: this.taskStore,
20139
+ source: "scheduler",
20140
+ workflowId: schedule.workflow,
20141
+ configPath: this.configPath,
20142
+ messageText: `Scheduled: ${schedule.workflow} (${schedule.id})`,
20143
+ metadata: { schedule_id: schedule.id, is_recurring: schedule.isRecurring }
20144
+ },
20145
+ schedExecFn
20146
+ );
20147
+ } else {
20148
+ await schedExecFn();
20149
+ }
20038
20150
  return { message: "Workflow completed", workflow: schedule.workflow };
20039
20151
  }
20040
20152
  /**
@@ -20140,7 +20252,7 @@ Please provide an updated response based on the reminder above. You may referenc
20140
20252
  responseRef
20141
20253
  } = this.prepareExecution(schedule, reminderText);
20142
20254
  try {
20143
- await runEngine.executeChecks({
20255
+ const reminderExecFn = () => runEngine.executeChecks({
20144
20256
  checks: allChecks,
20145
20257
  showDetails: true,
20146
20258
  outputFormat: "json",
@@ -20148,6 +20260,22 @@ Please provide an updated response based on the reminder above. You may referenc
20148
20260
  webhookContext: { webhookData, eventType: "schedule" },
20149
20261
  debug: process.env.VISOR_DEBUG === "true"
20150
20262
  });
20263
+ if (this.taskStore) {
20264
+ const { trackExecution: trackExecution2 } = await Promise.resolve().then(() => (init_track_execution(), track_execution_exports));
20265
+ await trackExecution2(
20266
+ {
20267
+ taskStore: this.taskStore,
20268
+ source: "scheduler",
20269
+ workflowId: schedule.workflow,
20270
+ configPath: this.configPath,
20271
+ messageText: reminderText || `Reminder: ${schedule.id}`,
20272
+ metadata: { schedule_id: schedule.id, is_recurring: schedule.isRecurring }
20273
+ },
20274
+ reminderExecFn
20275
+ );
20276
+ } else {
20277
+ await reminderExecFn();
20278
+ }
20151
20279
  if (schedule.isRecurring && responseRef.captured) {
20152
20280
  await this.store.updateAsync(schedule.id, { previousResponse: responseRef.captured });
20153
20281
  logger.info(
@@ -21396,7 +21524,7 @@ var init_mcp_custom_sse_server = __esm({
21396
21524
  * Returns the actual bound port number
21397
21525
  */
21398
21526
  async start() {
21399
- return new Promise((resolve15, reject) => {
21527
+ return new Promise((resolve19, reject) => {
21400
21528
  try {
21401
21529
  this.server = import_http.default.createServer((req, res) => {
21402
21530
  this.handleRequest(req, res).catch((error) => {
@@ -21430,7 +21558,7 @@ var init_mcp_custom_sse_server = __esm({
21430
21558
  );
21431
21559
  }
21432
21560
  this.startKeepalive();
21433
- resolve15(this.port);
21561
+ resolve19(this.port);
21434
21562
  });
21435
21563
  } catch (error) {
21436
21564
  reject(error);
@@ -21493,7 +21621,7 @@ var init_mcp_custom_sse_server = __esm({
21493
21621
  logger.debug(
21494
21622
  `[CustomToolsSSEServer:${this.sessionId}] Grace period before stop: ${waitMs}ms (activeToolCalls=${this.activeToolCalls})`
21495
21623
  );
21496
- await new Promise((resolve15) => setTimeout(resolve15, waitMs));
21624
+ await new Promise((resolve19) => setTimeout(resolve19, waitMs));
21497
21625
  }
21498
21626
  }
21499
21627
  if (this.activeToolCalls > 0) {
@@ -21502,7 +21630,7 @@ var init_mcp_custom_sse_server = __esm({
21502
21630
  `[CustomToolsSSEServer:${this.sessionId}] Waiting for ${this.activeToolCalls} active tool call(s) before stop`
21503
21631
  );
21504
21632
  while (this.activeToolCalls > 0 && Date.now() - startedAt < effectiveDrainTimeoutMs) {
21505
- await new Promise((resolve15) => setTimeout(resolve15, 250));
21633
+ await new Promise((resolve19) => setTimeout(resolve19, 250));
21506
21634
  }
21507
21635
  if (this.activeToolCalls > 0) {
21508
21636
  logger.warn(
@@ -21527,21 +21655,21 @@ var init_mcp_custom_sse_server = __esm({
21527
21655
  }
21528
21656
  this.connections.clear();
21529
21657
  if (this.server) {
21530
- await new Promise((resolve15, reject) => {
21658
+ await new Promise((resolve19, reject) => {
21531
21659
  const timeout = setTimeout(() => {
21532
21660
  if (this.debug) {
21533
21661
  logger.debug(
21534
21662
  `[CustomToolsSSEServer:${this.sessionId}] Force closing server after timeout`
21535
21663
  );
21536
21664
  }
21537
- this.server?.close(() => resolve15());
21665
+ this.server?.close(() => resolve19());
21538
21666
  }, 5e3);
21539
21667
  this.server.close((error) => {
21540
21668
  clearTimeout(timeout);
21541
21669
  if (error) {
21542
21670
  reject(error);
21543
21671
  } else {
21544
- resolve15();
21672
+ resolve19();
21545
21673
  }
21546
21674
  });
21547
21675
  });
@@ -21976,7 +22104,7 @@ var init_mcp_custom_sse_server = __esm({
21976
22104
  logger.warn(
21977
22105
  `[CustomToolsSSEServer:${this.sessionId}] Tool ${toolName} failed (attempt ${attempt + 1}/${retryCount + 1}): ${errorMsg}. Retrying in ${delay}ms`
21978
22106
  );
21979
- await new Promise((resolve15) => setTimeout(resolve15, delay));
22107
+ await new Promise((resolve19) => setTimeout(resolve19, delay));
21980
22108
  attempt++;
21981
22109
  }
21982
22110
  }
@@ -22099,7 +22227,7 @@ var init_tool_resolver = __esm({
22099
22227
  });
22100
22228
 
22101
22229
  // src/providers/ai-check-provider.ts
22102
- var import_promises4, import_path7, AICheckProvider;
22230
+ var import_promises4, import_path8, AICheckProvider;
22103
22231
  var init_ai_check_provider = __esm({
22104
22232
  "src/providers/ai-check-provider.ts"() {
22105
22233
  "use strict";
@@ -22109,7 +22237,7 @@ var init_ai_check_provider = __esm({
22109
22237
  init_issue_filter();
22110
22238
  init_liquid_extensions();
22111
22239
  import_promises4 = __toESM(require("fs/promises"));
22112
- import_path7 = __toESM(require("path"));
22240
+ import_path8 = __toESM(require("path"));
22113
22241
  init_lazy_otel();
22114
22242
  init_state_capture();
22115
22243
  init_mcp_custom_sse_server();
@@ -22274,7 +22402,7 @@ var init_ai_check_provider = __esm({
22274
22402
  const hasFileExtension = /\.[a-zA-Z0-9]{1,10}$/i.test(str);
22275
22403
  const hasPathSeparators = /[\/\\]/.test(str);
22276
22404
  const isRelativePath = /^\.{1,2}\//.test(str);
22277
- const isAbsolutePath = import_path7.default.isAbsolute(str);
22405
+ const isAbsolutePath = import_path8.default.isAbsolute(str);
22278
22406
  const hasTypicalFileChars = /^[a-zA-Z0-9._\-\/\\:~]+$/.test(str);
22279
22407
  if (!(hasFileExtension || isRelativePath || isAbsolutePath || hasPathSeparators)) {
22280
22408
  return false;
@@ -22284,14 +22412,14 @@ var init_ai_check_provider = __esm({
22284
22412
  }
22285
22413
  try {
22286
22414
  let resolvedPath;
22287
- if (import_path7.default.isAbsolute(str)) {
22288
- resolvedPath = import_path7.default.normalize(str);
22415
+ if (import_path8.default.isAbsolute(str)) {
22416
+ resolvedPath = import_path8.default.normalize(str);
22289
22417
  } else {
22290
- resolvedPath = import_path7.default.resolve(process.cwd(), str);
22418
+ resolvedPath = import_path8.default.resolve(process.cwd(), str);
22291
22419
  }
22292
- const fs25 = require("fs").promises;
22420
+ const fs29 = require("fs").promises;
22293
22421
  try {
22294
- const stat2 = await fs25.stat(resolvedPath);
22422
+ const stat2 = await fs29.stat(resolvedPath);
22295
22423
  return stat2.isFile();
22296
22424
  } catch {
22297
22425
  return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);
@@ -22308,14 +22436,14 @@ var init_ai_check_provider = __esm({
22308
22436
  throw new Error("Prompt file must have .liquid extension");
22309
22437
  }
22310
22438
  let resolvedPath;
22311
- if (import_path7.default.isAbsolute(promptPath)) {
22439
+ if (import_path8.default.isAbsolute(promptPath)) {
22312
22440
  resolvedPath = promptPath;
22313
22441
  } else {
22314
- resolvedPath = import_path7.default.resolve(process.cwd(), promptPath);
22442
+ resolvedPath = import_path8.default.resolve(process.cwd(), promptPath);
22315
22443
  }
22316
- if (!import_path7.default.isAbsolute(promptPath)) {
22317
- const normalizedPath = import_path7.default.normalize(resolvedPath);
22318
- const currentDir = import_path7.default.resolve(process.cwd());
22444
+ if (!import_path8.default.isAbsolute(promptPath)) {
22445
+ const normalizedPath = import_path8.default.normalize(resolvedPath);
22446
+ const currentDir = import_path8.default.resolve(process.cwd());
22319
22447
  if (!normalizedPath.startsWith(currentDir)) {
22320
22448
  throw new Error("Invalid prompt file path: path traversal detected");
22321
22449
  }
@@ -24494,7 +24622,7 @@ var init_oauth2_token_cache = __esm({
24494
24622
  });
24495
24623
 
24496
24624
  // src/providers/http-client-provider.ts
24497
- var fs15, path18, HttpClientProvider;
24625
+ var fs15, path19, HttpClientProvider;
24498
24626
  var init_http_client_provider = __esm({
24499
24627
  "src/providers/http-client-provider.ts"() {
24500
24628
  "use strict";
@@ -24506,7 +24634,7 @@ var init_http_client_provider = __esm({
24506
24634
  init_oauth2_token_cache();
24507
24635
  init_logger();
24508
24636
  fs15 = __toESM(require("fs"));
24509
- path18 = __toESM(require("path"));
24637
+ path19 = __toESM(require("path"));
24510
24638
  HttpClientProvider = class extends CheckProvider {
24511
24639
  liquid;
24512
24640
  sandbox;
@@ -24629,8 +24757,8 @@ var init_http_client_provider = __esm({
24629
24757
  const parentContext = context2?._parentContext;
24630
24758
  const workingDirectory = parentContext?.workingDirectory;
24631
24759
  const workspaceEnabled = parentContext?.workspace?.isEnabled?.();
24632
- if (workspaceEnabled && workingDirectory && !path18.isAbsolute(resolvedOutputFile)) {
24633
- resolvedOutputFile = path18.join(workingDirectory, resolvedOutputFile);
24760
+ if (workspaceEnabled && workingDirectory && !path19.isAbsolute(resolvedOutputFile)) {
24761
+ resolvedOutputFile = path19.join(workingDirectory, resolvedOutputFile);
24634
24762
  logger.debug(
24635
24763
  `[http_client] Resolved relative output_file to workspace: ${resolvedOutputFile}`
24636
24764
  );
@@ -24847,7 +24975,7 @@ var init_http_client_provider = __esm({
24847
24975
  ]
24848
24976
  };
24849
24977
  }
24850
- const parentDir = path18.dirname(outputFile);
24978
+ const parentDir = path19.dirname(outputFile);
24851
24979
  if (parentDir && !fs15.existsSync(parentDir)) {
24852
24980
  fs15.mkdirSync(parentDir, { recursive: true });
24853
24981
  }
@@ -25617,7 +25745,7 @@ var init_claude_code_types = __esm({
25617
25745
  function isClaudeCodeConstructor(value) {
25618
25746
  return typeof value === "function";
25619
25747
  }
25620
- var import_promises5, import_path8, ClaudeCodeSDKNotInstalledError, ClaudeCodeAPIKeyMissingError, ClaudeCodeCheckProvider;
25748
+ var import_promises5, import_path9, ClaudeCodeSDKNotInstalledError, ClaudeCodeAPIKeyMissingError, ClaudeCodeCheckProvider;
25621
25749
  var init_claude_code_check_provider = __esm({
25622
25750
  "src/providers/claude-code-check-provider.ts"() {
25623
25751
  "use strict";
@@ -25626,7 +25754,7 @@ var init_claude_code_check_provider = __esm({
25626
25754
  init_issue_filter();
25627
25755
  init_liquid_extensions();
25628
25756
  import_promises5 = __toESM(require("fs/promises"));
25629
- import_path8 = __toESM(require("path"));
25757
+ import_path9 = __toESM(require("path"));
25630
25758
  init_claude_code_types();
25631
25759
  ClaudeCodeSDKNotInstalledError = class extends Error {
25632
25760
  constructor() {
@@ -25774,7 +25902,7 @@ var init_claude_code_check_provider = __esm({
25774
25902
  const hasFileExtension = /\.[a-zA-Z0-9]{1,10}$/i.test(str);
25775
25903
  const hasPathSeparators = /[\/\\]/.test(str);
25776
25904
  const isRelativePath = /^\.{1,2}\//.test(str);
25777
- const isAbsolutePath = import_path8.default.isAbsolute(str);
25905
+ const isAbsolutePath = import_path9.default.isAbsolute(str);
25778
25906
  const hasTypicalFileChars = /^[a-zA-Z0-9._\-\/\\:~]+$/.test(str);
25779
25907
  if (!(hasFileExtension || isRelativePath || isAbsolutePath || hasPathSeparators)) {
25780
25908
  return false;
@@ -25784,10 +25912,10 @@ var init_claude_code_check_provider = __esm({
25784
25912
  }
25785
25913
  try {
25786
25914
  let resolvedPath;
25787
- if (import_path8.default.isAbsolute(str)) {
25788
- resolvedPath = import_path8.default.normalize(str);
25915
+ if (import_path9.default.isAbsolute(str)) {
25916
+ resolvedPath = import_path9.default.normalize(str);
25789
25917
  } else {
25790
- resolvedPath = import_path8.default.resolve(process.cwd(), str);
25918
+ resolvedPath = import_path9.default.resolve(process.cwd(), str);
25791
25919
  }
25792
25920
  try {
25793
25921
  const stat2 = await import_promises5.default.stat(resolvedPath);
@@ -25807,14 +25935,14 @@ var init_claude_code_check_provider = __esm({
25807
25935
  throw new Error("Prompt file must have .liquid extension");
25808
25936
  }
25809
25937
  let resolvedPath;
25810
- if (import_path8.default.isAbsolute(promptPath)) {
25938
+ if (import_path9.default.isAbsolute(promptPath)) {
25811
25939
  resolvedPath = promptPath;
25812
25940
  } else {
25813
- resolvedPath = import_path8.default.resolve(process.cwd(), promptPath);
25941
+ resolvedPath = import_path9.default.resolve(process.cwd(), promptPath);
25814
25942
  }
25815
- if (!import_path8.default.isAbsolute(promptPath)) {
25816
- const normalizedPath = import_path8.default.normalize(resolvedPath);
25817
- const currentDir = import_path8.default.resolve(process.cwd());
25943
+ if (!import_path9.default.isAbsolute(promptPath)) {
25944
+ const normalizedPath = import_path9.default.normalize(resolvedPath);
25945
+ const currentDir = import_path9.default.resolve(process.cwd());
25818
25946
  if (!normalizedPath.startsWith(currentDir)) {
25819
25947
  throw new Error("Invalid prompt file path: path traversal detected");
25820
25948
  }
@@ -28393,14 +28521,14 @@ var require_util = __commonJS({
28393
28521
  }
28394
28522
  const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
28395
28523
  let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`;
28396
- let path28 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
28524
+ let path33 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
28397
28525
  if (origin.endsWith("/")) {
28398
28526
  origin = origin.substring(0, origin.length - 1);
28399
28527
  }
28400
- if (path28 && !path28.startsWith("/")) {
28401
- path28 = `/${path28}`;
28528
+ if (path33 && !path33.startsWith("/")) {
28529
+ path33 = `/${path33}`;
28402
28530
  }
28403
- url = new URL(origin + path28);
28531
+ url = new URL(origin + path33);
28404
28532
  }
28405
28533
  return url;
28406
28534
  }
@@ -30014,20 +30142,20 @@ var require_parseParams = __commonJS({
30014
30142
  var require_basename = __commonJS({
30015
30143
  "node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) {
30016
30144
  "use strict";
30017
- module2.exports = function basename4(path28) {
30018
- if (typeof path28 !== "string") {
30145
+ module2.exports = function basename4(path33) {
30146
+ if (typeof path33 !== "string") {
30019
30147
  return "";
30020
30148
  }
30021
- for (var i = path28.length - 1; i >= 0; --i) {
30022
- switch (path28.charCodeAt(i)) {
30149
+ for (var i = path33.length - 1; i >= 0; --i) {
30150
+ switch (path33.charCodeAt(i)) {
30023
30151
  case 47:
30024
30152
  // '/'
30025
30153
  case 92:
30026
- path28 = path28.slice(i + 1);
30027
- return path28 === ".." || path28 === "." ? "" : path28;
30154
+ path33 = path33.slice(i + 1);
30155
+ return path33 === ".." || path33 === "." ? "" : path33;
30028
30156
  }
30029
30157
  }
30030
- return path28 === ".." || path28 === "." ? "" : path28;
30158
+ return path33 === ".." || path33 === "." ? "" : path33;
30031
30159
  };
30032
30160
  }
30033
30161
  });
@@ -31031,11 +31159,11 @@ var require_util2 = __commonJS({
31031
31159
  var assert = require("assert");
31032
31160
  var { isUint8Array } = require("util/types");
31033
31161
  var supportedHashes = [];
31034
- var crypto6;
31162
+ var crypto9;
31035
31163
  try {
31036
- crypto6 = require("crypto");
31164
+ crypto9 = require("crypto");
31037
31165
  const possibleRelevantHashes = ["sha256", "sha384", "sha512"];
31038
- supportedHashes = crypto6.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
31166
+ supportedHashes = crypto9.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
31039
31167
  } catch {
31040
31168
  }
31041
31169
  function responseURL(response) {
@@ -31312,7 +31440,7 @@ var require_util2 = __commonJS({
31312
31440
  }
31313
31441
  }
31314
31442
  function bytesMatch(bytes, metadataList) {
31315
- if (crypto6 === void 0) {
31443
+ if (crypto9 === void 0) {
31316
31444
  return true;
31317
31445
  }
31318
31446
  const parsedMetadata = parseMetadata(metadataList);
@@ -31327,7 +31455,7 @@ var require_util2 = __commonJS({
31327
31455
  for (const item of metadata) {
31328
31456
  const algorithm = item.algo;
31329
31457
  const expectedValue = item.hash;
31330
- let actualValue = crypto6.createHash(algorithm).update(bytes).digest("base64");
31458
+ let actualValue = crypto9.createHash(algorithm).update(bytes).digest("base64");
31331
31459
  if (actualValue[actualValue.length - 1] === "=") {
31332
31460
  if (actualValue[actualValue.length - 2] === "=") {
31333
31461
  actualValue = actualValue.slice(0, -2);
@@ -31420,8 +31548,8 @@ var require_util2 = __commonJS({
31420
31548
  function createDeferredPromise() {
31421
31549
  let res;
31422
31550
  let rej;
31423
- const promise = new Promise((resolve15, reject) => {
31424
- res = resolve15;
31551
+ const promise = new Promise((resolve19, reject) => {
31552
+ res = resolve19;
31425
31553
  rej = reject;
31426
31554
  });
31427
31555
  return { promise, resolve: res, reject: rej };
@@ -32674,8 +32802,8 @@ var require_body = __commonJS({
32674
32802
  var { parseMIMEType, serializeAMimeType } = require_dataURL();
32675
32803
  var random;
32676
32804
  try {
32677
- const crypto6 = require("crypto");
32678
- random = (max) => crypto6.randomInt(0, max);
32805
+ const crypto9 = require("crypto");
32806
+ random = (max) => crypto9.randomInt(0, max);
32679
32807
  } catch {
32680
32808
  random = (max) => Math.floor(Math.random(max));
32681
32809
  }
@@ -32926,8 +33054,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r
32926
33054
  });
32927
33055
  }
32928
33056
  });
32929
- const busboyResolve = new Promise((resolve15, reject) => {
32930
- busboy.on("finish", resolve15);
33057
+ const busboyResolve = new Promise((resolve19, reject) => {
33058
+ busboy.on("finish", resolve19);
32931
33059
  busboy.on("error", (err) => reject(new TypeError(err)));
32932
33060
  });
32933
33061
  if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk);
@@ -33058,7 +33186,7 @@ var require_request = __commonJS({
33058
33186
  }
33059
33187
  var Request = class _Request {
33060
33188
  constructor(origin, {
33061
- path: path28,
33189
+ path: path33,
33062
33190
  method,
33063
33191
  body,
33064
33192
  headers,
@@ -33072,11 +33200,11 @@ var require_request = __commonJS({
33072
33200
  throwOnError,
33073
33201
  expectContinue
33074
33202
  }, handler) {
33075
- if (typeof path28 !== "string") {
33203
+ if (typeof path33 !== "string") {
33076
33204
  throw new InvalidArgumentError("path must be a string");
33077
- } else if (path28[0] !== "/" && !(path28.startsWith("http://") || path28.startsWith("https://")) && method !== "CONNECT") {
33205
+ } else if (path33[0] !== "/" && !(path33.startsWith("http://") || path33.startsWith("https://")) && method !== "CONNECT") {
33078
33206
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
33079
- } else if (invalidPathRegex.exec(path28) !== null) {
33207
+ } else if (invalidPathRegex.exec(path33) !== null) {
33080
33208
  throw new InvalidArgumentError("invalid request path");
33081
33209
  }
33082
33210
  if (typeof method !== "string") {
@@ -33139,7 +33267,7 @@ var require_request = __commonJS({
33139
33267
  this.completed = false;
33140
33268
  this.aborted = false;
33141
33269
  this.upgrade = upgrade || null;
33142
- this.path = query ? util.buildURL(path28, query) : path28;
33270
+ this.path = query ? util.buildURL(path33, query) : path33;
33143
33271
  this.origin = origin;
33144
33272
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
33145
33273
  this.blocking = blocking == null ? false : blocking;
@@ -33461,9 +33589,9 @@ var require_dispatcher_base = __commonJS({
33461
33589
  }
33462
33590
  close(callback) {
33463
33591
  if (callback === void 0) {
33464
- return new Promise((resolve15, reject) => {
33592
+ return new Promise((resolve19, reject) => {
33465
33593
  this.close((err, data) => {
33466
- return err ? reject(err) : resolve15(data);
33594
+ return err ? reject(err) : resolve19(data);
33467
33595
  });
33468
33596
  });
33469
33597
  }
@@ -33501,12 +33629,12 @@ var require_dispatcher_base = __commonJS({
33501
33629
  err = null;
33502
33630
  }
33503
33631
  if (callback === void 0) {
33504
- return new Promise((resolve15, reject) => {
33632
+ return new Promise((resolve19, reject) => {
33505
33633
  this.destroy(err, (err2, data) => {
33506
33634
  return err2 ? (
33507
33635
  /* istanbul ignore next: should never error */
33508
33636
  reject(err2)
33509
- ) : resolve15(data);
33637
+ ) : resolve19(data);
33510
33638
  });
33511
33639
  });
33512
33640
  }
@@ -34147,9 +34275,9 @@ var require_RedirectHandler = __commonJS({
34147
34275
  return this.handler.onHeaders(statusCode, headers, resume, statusText);
34148
34276
  }
34149
34277
  const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
34150
- const path28 = search ? `${pathname}${search}` : pathname;
34278
+ const path33 = search ? `${pathname}${search}` : pathname;
34151
34279
  this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
34152
- this.opts.path = path28;
34280
+ this.opts.path = path33;
34153
34281
  this.opts.origin = origin;
34154
34282
  this.opts.maxRedirections = 0;
34155
34283
  this.opts.query = null;
@@ -34568,16 +34696,16 @@ var require_client = __commonJS({
34568
34696
  return this[kNeedDrain] < 2;
34569
34697
  }
34570
34698
  async [kClose]() {
34571
- return new Promise((resolve15) => {
34699
+ return new Promise((resolve19) => {
34572
34700
  if (!this[kSize]) {
34573
- resolve15(null);
34701
+ resolve19(null);
34574
34702
  } else {
34575
- this[kClosedResolve] = resolve15;
34703
+ this[kClosedResolve] = resolve19;
34576
34704
  }
34577
34705
  });
34578
34706
  }
34579
34707
  async [kDestroy](err) {
34580
- return new Promise((resolve15) => {
34708
+ return new Promise((resolve19) => {
34581
34709
  const requests = this[kQueue].splice(this[kPendingIdx]);
34582
34710
  for (let i = 0; i < requests.length; i++) {
34583
34711
  const request = requests[i];
@@ -34588,7 +34716,7 @@ var require_client = __commonJS({
34588
34716
  this[kClosedResolve]();
34589
34717
  this[kClosedResolve] = null;
34590
34718
  }
34591
- resolve15();
34719
+ resolve19();
34592
34720
  };
34593
34721
  if (this[kHTTP2Session] != null) {
34594
34722
  util.destroy(this[kHTTP2Session], err);
@@ -35168,7 +35296,7 @@ var require_client = __commonJS({
35168
35296
  });
35169
35297
  }
35170
35298
  try {
35171
- const socket = await new Promise((resolve15, reject) => {
35299
+ const socket = await new Promise((resolve19, reject) => {
35172
35300
  client[kConnector]({
35173
35301
  host,
35174
35302
  hostname,
@@ -35180,7 +35308,7 @@ var require_client = __commonJS({
35180
35308
  if (err) {
35181
35309
  reject(err);
35182
35310
  } else {
35183
- resolve15(socket2);
35311
+ resolve19(socket2);
35184
35312
  }
35185
35313
  });
35186
35314
  });
@@ -35391,7 +35519,7 @@ var require_client = __commonJS({
35391
35519
  writeH2(client, client[kHTTP2Session], request);
35392
35520
  return;
35393
35521
  }
35394
- const { body, method, path: path28, host, upgrade, headers, blocking, reset } = request;
35522
+ const { body, method, path: path33, host, upgrade, headers, blocking, reset } = request;
35395
35523
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
35396
35524
  if (body && typeof body.read === "function") {
35397
35525
  body.read(0);
@@ -35441,7 +35569,7 @@ var require_client = __commonJS({
35441
35569
  if (blocking) {
35442
35570
  socket[kBlocking] = true;
35443
35571
  }
35444
- let header = `${method} ${path28} HTTP/1.1\r
35572
+ let header = `${method} ${path33} HTTP/1.1\r
35445
35573
  `;
35446
35574
  if (typeof host === "string") {
35447
35575
  header += `host: ${host}\r
@@ -35504,7 +35632,7 @@ upgrade: ${upgrade}\r
35504
35632
  return true;
35505
35633
  }
35506
35634
  function writeH2(client, session, request) {
35507
- const { body, method, path: path28, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
35635
+ const { body, method, path: path33, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
35508
35636
  let headers;
35509
35637
  if (typeof reqHeaders === "string") headers = Request[kHTTP2CopyHeaders](reqHeaders.trim());
35510
35638
  else headers = reqHeaders;
@@ -35547,7 +35675,7 @@ upgrade: ${upgrade}\r
35547
35675
  });
35548
35676
  return true;
35549
35677
  }
35550
- headers[HTTP2_HEADER_PATH] = path28;
35678
+ headers[HTTP2_HEADER_PATH] = path33;
35551
35679
  headers[HTTP2_HEADER_SCHEME] = "https";
35552
35680
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
35553
35681
  if (body && typeof body.read === "function") {
@@ -35804,12 +35932,12 @@ upgrade: ${upgrade}\r
35804
35932
  cb();
35805
35933
  }
35806
35934
  }
35807
- const waitForDrain = () => new Promise((resolve15, reject) => {
35935
+ const waitForDrain = () => new Promise((resolve19, reject) => {
35808
35936
  assert(callback === null);
35809
35937
  if (socket[kError]) {
35810
35938
  reject(socket[kError]);
35811
35939
  } else {
35812
- callback = resolve15;
35940
+ callback = resolve19;
35813
35941
  }
35814
35942
  });
35815
35943
  if (client[kHTTPConnVersion] === "h2") {
@@ -36155,8 +36283,8 @@ var require_pool_base = __commonJS({
36155
36283
  if (this[kQueue].isEmpty()) {
36156
36284
  return Promise.all(this[kClients].map((c) => c.close()));
36157
36285
  } else {
36158
- return new Promise((resolve15) => {
36159
- this[kClosedResolve] = resolve15;
36286
+ return new Promise((resolve19) => {
36287
+ this[kClosedResolve] = resolve19;
36160
36288
  });
36161
36289
  }
36162
36290
  }
@@ -36734,7 +36862,7 @@ var require_readable = __commonJS({
36734
36862
  if (this.closed) {
36735
36863
  return Promise.resolve(null);
36736
36864
  }
36737
- return new Promise((resolve15, reject) => {
36865
+ return new Promise((resolve19, reject) => {
36738
36866
  const signalListenerCleanup = signal ? util.addAbortListener(signal, () => {
36739
36867
  this.destroy();
36740
36868
  }) : noop;
@@ -36743,7 +36871,7 @@ var require_readable = __commonJS({
36743
36871
  if (signal && signal.aborted) {
36744
36872
  reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" }));
36745
36873
  } else {
36746
- resolve15(null);
36874
+ resolve19(null);
36747
36875
  }
36748
36876
  }).on("error", noop).on("data", function(chunk) {
36749
36877
  limit -= chunk.length;
@@ -36765,11 +36893,11 @@ var require_readable = __commonJS({
36765
36893
  throw new TypeError("unusable");
36766
36894
  }
36767
36895
  assert(!stream[kConsume]);
36768
- return new Promise((resolve15, reject) => {
36896
+ return new Promise((resolve19, reject) => {
36769
36897
  stream[kConsume] = {
36770
36898
  type,
36771
36899
  stream,
36772
- resolve: resolve15,
36900
+ resolve: resolve19,
36773
36901
  reject,
36774
36902
  length: 0,
36775
36903
  body: []
@@ -36804,12 +36932,12 @@ var require_readable = __commonJS({
36804
36932
  }
36805
36933
  }
36806
36934
  function consumeEnd(consume2) {
36807
- const { type, body, resolve: resolve15, stream, length } = consume2;
36935
+ const { type, body, resolve: resolve19, stream, length } = consume2;
36808
36936
  try {
36809
36937
  if (type === "text") {
36810
- resolve15(toUSVString(Buffer.concat(body)));
36938
+ resolve19(toUSVString(Buffer.concat(body)));
36811
36939
  } else if (type === "json") {
36812
- resolve15(JSON.parse(Buffer.concat(body)));
36940
+ resolve19(JSON.parse(Buffer.concat(body)));
36813
36941
  } else if (type === "arrayBuffer") {
36814
36942
  const dst = new Uint8Array(length);
36815
36943
  let pos = 0;
@@ -36817,12 +36945,12 @@ var require_readable = __commonJS({
36817
36945
  dst.set(buf, pos);
36818
36946
  pos += buf.byteLength;
36819
36947
  }
36820
- resolve15(dst.buffer);
36948
+ resolve19(dst.buffer);
36821
36949
  } else if (type === "blob") {
36822
36950
  if (!Blob2) {
36823
36951
  Blob2 = require("buffer").Blob;
36824
36952
  }
36825
- resolve15(new Blob2(body, { type: stream[kContentType] }));
36953
+ resolve19(new Blob2(body, { type: stream[kContentType] }));
36826
36954
  }
36827
36955
  consumeFinish(consume2);
36828
36956
  } catch (err) {
@@ -37079,9 +37207,9 @@ var require_api_request = __commonJS({
37079
37207
  };
37080
37208
  function request(opts, callback) {
37081
37209
  if (callback === void 0) {
37082
- return new Promise((resolve15, reject) => {
37210
+ return new Promise((resolve19, reject) => {
37083
37211
  request.call(this, opts, (err, data) => {
37084
- return err ? reject(err) : resolve15(data);
37212
+ return err ? reject(err) : resolve19(data);
37085
37213
  });
37086
37214
  });
37087
37215
  }
@@ -37254,9 +37382,9 @@ var require_api_stream = __commonJS({
37254
37382
  };
37255
37383
  function stream(opts, factory, callback) {
37256
37384
  if (callback === void 0) {
37257
- return new Promise((resolve15, reject) => {
37385
+ return new Promise((resolve19, reject) => {
37258
37386
  stream.call(this, opts, factory, (err, data) => {
37259
- return err ? reject(err) : resolve15(data);
37387
+ return err ? reject(err) : resolve19(data);
37260
37388
  });
37261
37389
  });
37262
37390
  }
@@ -37537,9 +37665,9 @@ var require_api_upgrade = __commonJS({
37537
37665
  };
37538
37666
  function upgrade(opts, callback) {
37539
37667
  if (callback === void 0) {
37540
- return new Promise((resolve15, reject) => {
37668
+ return new Promise((resolve19, reject) => {
37541
37669
  upgrade.call(this, opts, (err, data) => {
37542
- return err ? reject(err) : resolve15(data);
37670
+ return err ? reject(err) : resolve19(data);
37543
37671
  });
37544
37672
  });
37545
37673
  }
@@ -37628,9 +37756,9 @@ var require_api_connect = __commonJS({
37628
37756
  };
37629
37757
  function connect(opts, callback) {
37630
37758
  if (callback === void 0) {
37631
- return new Promise((resolve15, reject) => {
37759
+ return new Promise((resolve19, reject) => {
37632
37760
  connect.call(this, opts, (err, data) => {
37633
- return err ? reject(err) : resolve15(data);
37761
+ return err ? reject(err) : resolve19(data);
37634
37762
  });
37635
37763
  });
37636
37764
  }
@@ -37790,20 +37918,20 @@ var require_mock_utils = __commonJS({
37790
37918
  }
37791
37919
  return true;
37792
37920
  }
37793
- function safeUrl(path28) {
37794
- if (typeof path28 !== "string") {
37795
- return path28;
37921
+ function safeUrl(path33) {
37922
+ if (typeof path33 !== "string") {
37923
+ return path33;
37796
37924
  }
37797
- const pathSegments = path28.split("?");
37925
+ const pathSegments = path33.split("?");
37798
37926
  if (pathSegments.length !== 2) {
37799
- return path28;
37927
+ return path33;
37800
37928
  }
37801
37929
  const qp = new URLSearchParams(pathSegments.pop());
37802
37930
  qp.sort();
37803
37931
  return [...pathSegments, qp.toString()].join("?");
37804
37932
  }
37805
- function matchKey(mockDispatch2, { path: path28, method, body, headers }) {
37806
- const pathMatch = matchValue(mockDispatch2.path, path28);
37933
+ function matchKey(mockDispatch2, { path: path33, method, body, headers }) {
37934
+ const pathMatch = matchValue(mockDispatch2.path, path33);
37807
37935
  const methodMatch = matchValue(mockDispatch2.method, method);
37808
37936
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
37809
37937
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -37821,7 +37949,7 @@ var require_mock_utils = __commonJS({
37821
37949
  function getMockDispatch(mockDispatches, key) {
37822
37950
  const basePath = key.query ? buildURL(key.path, key.query) : key.path;
37823
37951
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
37824
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path28 }) => matchValue(safeUrl(path28), resolvedPath));
37952
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path33 }) => matchValue(safeUrl(path33), resolvedPath));
37825
37953
  if (matchedMockDispatches.length === 0) {
37826
37954
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
37827
37955
  }
@@ -37858,9 +37986,9 @@ var require_mock_utils = __commonJS({
37858
37986
  }
37859
37987
  }
37860
37988
  function buildKey(opts) {
37861
- const { path: path28, method, body, headers, query } = opts;
37989
+ const { path: path33, method, body, headers, query } = opts;
37862
37990
  return {
37863
- path: path28,
37991
+ path: path33,
37864
37992
  method,
37865
37993
  body,
37866
37994
  headers,
@@ -38309,10 +38437,10 @@ var require_pending_interceptors_formatter = __commonJS({
38309
38437
  }
38310
38438
  format(pendingInterceptors) {
38311
38439
  const withPrettyHeaders = pendingInterceptors.map(
38312
- ({ method, path: path28, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
38440
+ ({ method, path: path33, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
38313
38441
  Method: method,
38314
38442
  Origin: origin,
38315
- Path: path28,
38443
+ Path: path33,
38316
38444
  "Status code": statusCode,
38317
38445
  Persistent: persist ? "\u2705" : "\u274C",
38318
38446
  Invocations: timesInvoked,
@@ -41253,7 +41381,7 @@ var require_fetch = __commonJS({
41253
41381
  async function dispatch({ body }) {
41254
41382
  const url = requestCurrentURL(request);
41255
41383
  const agent = fetchParams.controller.dispatcher;
41256
- return new Promise((resolve15, reject) => agent.dispatch(
41384
+ return new Promise((resolve19, reject) => agent.dispatch(
41257
41385
  {
41258
41386
  path: url.pathname + url.search,
41259
41387
  origin: url.origin,
@@ -41329,7 +41457,7 @@ var require_fetch = __commonJS({
41329
41457
  }
41330
41458
  }
41331
41459
  }
41332
- resolve15({
41460
+ resolve19({
41333
41461
  status,
41334
41462
  statusText,
41335
41463
  headersList: headers[kHeadersList],
@@ -41372,7 +41500,7 @@ var require_fetch = __commonJS({
41372
41500
  const val = headersList[n + 1].toString("latin1");
41373
41501
  headers[kHeadersList].append(key, val);
41374
41502
  }
41375
- resolve15({
41503
+ resolve19({
41376
41504
  status,
41377
41505
  statusText: STATUS_CODES[status],
41378
41506
  headersList: headers[kHeadersList],
@@ -42933,8 +43061,8 @@ var require_util6 = __commonJS({
42933
43061
  }
42934
43062
  }
42935
43063
  }
42936
- function validateCookiePath(path28) {
42937
- for (const char of path28) {
43064
+ function validateCookiePath(path33) {
43065
+ for (const char of path33) {
42938
43066
  const code = char.charCodeAt(0);
42939
43067
  if (code < 33 || char === ";") {
42940
43068
  throw new Error("Invalid cookie path");
@@ -43731,9 +43859,9 @@ var require_connection = __commonJS({
43731
43859
  channels.open = diagnosticsChannel.channel("undici:websocket:open");
43732
43860
  channels.close = diagnosticsChannel.channel("undici:websocket:close");
43733
43861
  channels.socketError = diagnosticsChannel.channel("undici:websocket:socket_error");
43734
- var crypto6;
43862
+ var crypto9;
43735
43863
  try {
43736
- crypto6 = require("crypto");
43864
+ crypto9 = require("crypto");
43737
43865
  } catch {
43738
43866
  }
43739
43867
  function establishWebSocketConnection(url, protocols, ws, onEstablish, options) {
@@ -43752,7 +43880,7 @@ var require_connection = __commonJS({
43752
43880
  const headersList = new Headers(options.headers)[kHeadersList];
43753
43881
  request.headersList = headersList;
43754
43882
  }
43755
- const keyValue = crypto6.randomBytes(16).toString("base64");
43883
+ const keyValue = crypto9.randomBytes(16).toString("base64");
43756
43884
  request.headersList.append("sec-websocket-key", keyValue);
43757
43885
  request.headersList.append("sec-websocket-version", "13");
43758
43886
  for (const protocol of protocols) {
@@ -43781,7 +43909,7 @@ var require_connection = __commonJS({
43781
43909
  return;
43782
43910
  }
43783
43911
  const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
43784
- const digest = crypto6.createHash("sha1").update(keyValue + uid).digest("base64");
43912
+ const digest = crypto9.createHash("sha1").update(keyValue + uid).digest("base64");
43785
43913
  if (secWSAccept !== digest) {
43786
43914
  failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header.");
43787
43915
  return;
@@ -43861,9 +43989,9 @@ var require_frame = __commonJS({
43861
43989
  "node_modules/undici/lib/websocket/frame.js"(exports2, module2) {
43862
43990
  "use strict";
43863
43991
  var { maxUnsigned16Bit } = require_constants5();
43864
- var crypto6;
43992
+ var crypto9;
43865
43993
  try {
43866
- crypto6 = require("crypto");
43994
+ crypto9 = require("crypto");
43867
43995
  } catch {
43868
43996
  }
43869
43997
  var WebsocketFrameSend = class {
@@ -43872,7 +44000,7 @@ var require_frame = __commonJS({
43872
44000
  */
43873
44001
  constructor(data) {
43874
44002
  this.frameData = data;
43875
- this.maskKey = crypto6.randomBytes(4);
44003
+ this.maskKey = crypto9.randomBytes(4);
43876
44004
  }
43877
44005
  createFrame(opcode) {
43878
44006
  const bodyLength = this.frameData?.byteLength ?? 0;
@@ -44614,11 +44742,11 @@ var require_undici = __commonJS({
44614
44742
  if (typeof opts.path !== "string") {
44615
44743
  throw new InvalidArgumentError("invalid opts.path");
44616
44744
  }
44617
- let path28 = opts.path;
44745
+ let path33 = opts.path;
44618
44746
  if (!opts.path.startsWith("/")) {
44619
- path28 = `/${path28}`;
44747
+ path33 = `/${path33}`;
44620
44748
  }
44621
- url = new URL(util.parseOrigin(url).origin + path28);
44749
+ url = new URL(util.parseOrigin(url).origin + path33);
44622
44750
  } else {
44623
44751
  if (!opts) {
44624
44752
  opts = typeof url === "object" ? url : {};
@@ -45167,7 +45295,7 @@ var init_mcp_check_provider = __esm({
45167
45295
  logger.warn(
45168
45296
  `MCP ${transportName} failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`
45169
45297
  );
45170
- await new Promise((resolve15) => setTimeout(resolve15, delay));
45298
+ await new Promise((resolve19) => setTimeout(resolve19, delay));
45171
45299
  attempt += 1;
45172
45300
  } finally {
45173
45301
  try {
@@ -45460,7 +45588,7 @@ async function acquirePromptLock() {
45460
45588
  );
45461
45589
  }, 1e4);
45462
45590
  try {
45463
- await new Promise((resolve15) => waiters.push(resolve15));
45591
+ await new Promise((resolve19) => waiters.push(resolve19));
45464
45592
  } finally {
45465
45593
  clearInterval(reminder);
45466
45594
  const waitedMs = Date.now() - queuedAt;
@@ -45479,7 +45607,7 @@ function releasePromptLock() {
45479
45607
  }
45480
45608
  async function interactivePrompt(options) {
45481
45609
  await acquirePromptLock();
45482
- return new Promise((resolve15, reject) => {
45610
+ return new Promise((resolve19, reject) => {
45483
45611
  const dbg = process.env.VISOR_DEBUG === "true";
45484
45612
  try {
45485
45613
  if (dbg) {
@@ -45566,12 +45694,12 @@ async function interactivePrompt(options) {
45566
45694
  };
45567
45695
  const finish = (value) => {
45568
45696
  cleanup();
45569
- resolve15(value);
45697
+ resolve19(value);
45570
45698
  };
45571
45699
  if (options.timeout && options.timeout > 0) {
45572
45700
  timeoutId = setTimeout(() => {
45573
45701
  cleanup();
45574
- if (defaultValue !== void 0) return resolve15(defaultValue);
45702
+ if (defaultValue !== void 0) return resolve19(defaultValue);
45575
45703
  return reject(new Error("Input timeout"));
45576
45704
  }, options.timeout);
45577
45705
  }
@@ -45703,7 +45831,7 @@ async function interactivePrompt(options) {
45703
45831
  });
45704
45832
  }
45705
45833
  async function simplePrompt(prompt) {
45706
- return new Promise((resolve15) => {
45834
+ return new Promise((resolve19) => {
45707
45835
  const rl = readline.createInterface({
45708
45836
  input: process.stdin,
45709
45837
  output: process.stdout
@@ -45719,7 +45847,7 @@ async function simplePrompt(prompt) {
45719
45847
  rl.question(`${prompt}
45720
45848
  > `, (answer) => {
45721
45849
  rl.close();
45722
- resolve15(answer.trim());
45850
+ resolve19(answer.trim());
45723
45851
  });
45724
45852
  });
45725
45853
  }
@@ -45887,7 +46015,7 @@ function isStdinAvailable() {
45887
46015
  return !process.stdin.isTTY;
45888
46016
  }
45889
46017
  async function readStdin(timeout, maxSize = 1024 * 1024) {
45890
- return new Promise((resolve15, reject) => {
46018
+ return new Promise((resolve19, reject) => {
45891
46019
  let data = "";
45892
46020
  let timeoutId;
45893
46021
  if (timeout) {
@@ -45914,7 +46042,7 @@ async function readStdin(timeout, maxSize = 1024 * 1024) {
45914
46042
  };
45915
46043
  const onEnd = () => {
45916
46044
  cleanup();
45917
- resolve15(data.trim());
46045
+ resolve19(data.trim());
45918
46046
  };
45919
46047
  const onError = (err) => {
45920
46048
  cleanup();
@@ -45944,7 +46072,7 @@ var init_stdin_reader = __esm({
45944
46072
  });
45945
46073
 
45946
46074
  // src/providers/human-input-check-provider.ts
45947
- var fs17, path20, HumanInputCheckProvider;
46075
+ var fs17, path21, HumanInputCheckProvider;
45948
46076
  var init_human_input_check_provider = __esm({
45949
46077
  "src/providers/human-input-check-provider.ts"() {
45950
46078
  "use strict";
@@ -45954,7 +46082,7 @@ var init_human_input_check_provider = __esm({
45954
46082
  init_liquid_extensions();
45955
46083
  init_stdin_reader();
45956
46084
  fs17 = __toESM(require("fs"));
45957
- path20 = __toESM(require("path"));
46085
+ path21 = __toESM(require("path"));
45958
46086
  HumanInputCheckProvider = class _HumanInputCheckProvider extends CheckProvider {
45959
46087
  liquid;
45960
46088
  /**
@@ -46128,10 +46256,10 @@ var init_human_input_check_provider = __esm({
46128
46256
  */
46129
46257
  async tryReadFile(filePath) {
46130
46258
  try {
46131
- const absolutePath = path20.isAbsolute(filePath) ? filePath : path20.resolve(process.cwd(), filePath);
46132
- const normalizedPath = path20.normalize(absolutePath);
46259
+ const absolutePath = path21.isAbsolute(filePath) ? filePath : path21.resolve(process.cwd(), filePath);
46260
+ const normalizedPath = path21.normalize(absolutePath);
46133
46261
  const cwd = process.cwd();
46134
- if (!normalizedPath.startsWith(cwd + path20.sep) && normalizedPath !== cwd) {
46262
+ if (!normalizedPath.startsWith(cwd + path21.sep) && normalizedPath !== cwd) {
46135
46263
  return null;
46136
46264
  }
46137
46265
  try {
@@ -47286,14 +47414,14 @@ var init_script_check_provider = __esm({
47286
47414
  });
47287
47415
 
47288
47416
  // src/utils/worktree-manager.ts
47289
- var fs18, fsp, path21, crypto, WorktreeManager, worktreeManager;
47417
+ var fs18, fsp, path22, crypto2, WorktreeManager, worktreeManager;
47290
47418
  var init_worktree_manager = __esm({
47291
47419
  "src/utils/worktree-manager.ts"() {
47292
47420
  "use strict";
47293
47421
  fs18 = __toESM(require("fs"));
47294
47422
  fsp = __toESM(require("fs/promises"));
47295
- path21 = __toESM(require("path"));
47296
- crypto = __toESM(require("crypto"));
47423
+ path22 = __toESM(require("path"));
47424
+ crypto2 = __toESM(require("crypto"));
47297
47425
  init_command_executor();
47298
47426
  init_logger();
47299
47427
  WorktreeManager = class _WorktreeManager {
@@ -47308,7 +47436,7 @@ var init_worktree_manager = __esm({
47308
47436
  } catch {
47309
47437
  cwd = "/tmp";
47310
47438
  }
47311
- const defaultBasePath = process.env.VISOR_WORKTREE_PATH || path21.join(cwd, ".visor", "worktrees");
47439
+ const defaultBasePath = process.env.VISOR_WORKTREE_PATH || path22.join(cwd, ".visor", "worktrees");
47312
47440
  this.config = {
47313
47441
  enabled: true,
47314
47442
  base_path: defaultBasePath,
@@ -47355,10 +47483,10 @@ var init_worktree_manager = __esm({
47355
47483
  }
47356
47484
  }
47357
47485
  getReposDir() {
47358
- return path21.join(this.config.base_path, "repos");
47486
+ return path22.join(this.config.base_path, "repos");
47359
47487
  }
47360
47488
  getWorktreesDir() {
47361
- return path21.join(this.config.base_path, "worktrees");
47489
+ return path22.join(this.config.base_path, "worktrees");
47362
47490
  }
47363
47491
  /**
47364
47492
  * Generate a worktree ID based on repository, ref, and session.
@@ -47374,7 +47502,7 @@ var init_worktree_manager = __esm({
47374
47502
  const sanitizedRepo = repository.replace(/[^a-zA-Z0-9-]/g, "-");
47375
47503
  const sanitizedRef = ref.replace(/[^a-zA-Z0-9-]/g, "-");
47376
47504
  const hashInput = sessionId ? `${repository}:${ref}:${sessionId}` : `${repository}:${ref}`;
47377
- const hash = crypto.createHash("md5").update(hashInput).digest("hex").substring(0, 8);
47505
+ const hash = crypto2.createHash("md5").update(hashInput).digest("hex").substring(0, 8);
47378
47506
  return `${sanitizedRepo}-${sanitizedRef}-${hash}`;
47379
47507
  }
47380
47508
  /**
@@ -47383,7 +47511,7 @@ var init_worktree_manager = __esm({
47383
47511
  async getOrCreateBareRepo(repository, repoUrl, _token, fetchDepth, cloneTimeoutMs) {
47384
47512
  const reposDir = this.getReposDir();
47385
47513
  const repoName = repository.replace(/\//g, "-");
47386
- const bareRepoPath = path21.join(reposDir, `${repoName}.git`);
47514
+ const bareRepoPath = path22.join(reposDir, `${repoName}.git`);
47387
47515
  if (fs18.existsSync(bareRepoPath)) {
47388
47516
  logger.debug(`Bare repository already exists: ${bareRepoPath}`);
47389
47517
  const verifyResult = await this.verifyBareRepoRemote(bareRepoPath, repoUrl);
@@ -47531,7 +47659,7 @@ var init_worktree_manager = __esm({
47531
47659
  options.cloneTimeoutMs
47532
47660
  );
47533
47661
  const worktreeId = this.generateWorktreeId(repository, ref, options.sessionId);
47534
- let worktreePath = options.workingDirectory || path21.join(this.getWorktreesDir(), worktreeId);
47662
+ let worktreePath = options.workingDirectory || path22.join(this.getWorktreesDir(), worktreeId);
47535
47663
  if (options.workingDirectory) {
47536
47664
  worktreePath = this.validatePath(options.workingDirectory);
47537
47665
  }
@@ -47852,7 +47980,7 @@ var init_worktree_manager = __esm({
47852
47980
  */
47853
47981
  async loadMetadata(worktreePath) {
47854
47982
  const metadataPath = this.getMetadataPath(worktreePath);
47855
- const legacyPath = path21.join(worktreePath, ".visor-metadata.json");
47983
+ const legacyPath = path22.join(worktreePath, ".visor-metadata.json");
47856
47984
  const pathToRead = fs18.existsSync(metadataPath) ? metadataPath : fs18.existsSync(legacyPath) ? legacyPath : null;
47857
47985
  if (!pathToRead) {
47858
47986
  return null;
@@ -47877,7 +48005,7 @@ var init_worktree_manager = __esm({
47877
48005
  const worktrees = [];
47878
48006
  for (const entry of entries) {
47879
48007
  if (!entry.isDirectory()) continue;
47880
- const worktreePath = path21.join(worktreesDir, entry.name);
48008
+ const worktreePath = path22.join(worktreesDir, entry.name);
47881
48009
  const metadata = await this.loadMetadata(worktreePath);
47882
48010
  if (metadata) {
47883
48011
  worktrees.push({
@@ -48009,8 +48137,8 @@ var init_worktree_manager = __esm({
48009
48137
  * Validate path to prevent directory traversal
48010
48138
  */
48011
48139
  validatePath(userPath) {
48012
- const resolvedPath = path21.resolve(userPath);
48013
- if (!path21.isAbsolute(resolvedPath)) {
48140
+ const resolvedPath = path22.resolve(userPath);
48141
+ if (!path22.isAbsolute(resolvedPath)) {
48014
48142
  throw new Error("Path must be absolute");
48015
48143
  }
48016
48144
  const sensitivePatterns = [
@@ -50605,23 +50733,23 @@ __export(renderer_schema_exports, {
50605
50733
  });
50606
50734
  async function loadRendererSchema(name) {
50607
50735
  try {
50608
- const fs25 = await import("fs/promises");
50609
- const path28 = await import("path");
50736
+ const fs29 = await import("fs/promises");
50737
+ const path33 = await import("path");
50610
50738
  const sanitized = String(name).replace(/[^a-zA-Z0-9-]/g, "");
50611
50739
  if (!sanitized) return void 0;
50612
50740
  const candidates = [
50613
50741
  // When bundled with ncc, __dirname is dist/ and output/ is at dist/output/
50614
- path28.join(__dirname, "output", sanitized, "schema.json"),
50742
+ path33.join(__dirname, "output", sanitized, "schema.json"),
50615
50743
  // When running from source, __dirname is src/state-machine/dispatch/ and output/ is at output/
50616
- path28.join(__dirname, "..", "..", "output", sanitized, "schema.json"),
50744
+ path33.join(__dirname, "..", "..", "output", sanitized, "schema.json"),
50617
50745
  // When running from a checkout with output/ folder copied to CWD
50618
- path28.join(process.cwd(), "output", sanitized, "schema.json"),
50746
+ path33.join(process.cwd(), "output", sanitized, "schema.json"),
50619
50747
  // Fallback: cwd/dist/output/
50620
- path28.join(process.cwd(), "dist", "output", sanitized, "schema.json")
50748
+ path33.join(process.cwd(), "dist", "output", sanitized, "schema.json")
50621
50749
  ];
50622
50750
  for (const p of candidates) {
50623
50751
  try {
50624
- const raw = await fs25.readFile(p, "utf-8");
50752
+ const raw = await fs29.readFile(p, "utf-8");
50625
50753
  return JSON.parse(raw);
50626
50754
  } catch {
50627
50755
  }
@@ -53062,8 +53190,8 @@ function updateStats2(results, state, isForEachIteration = false) {
53062
53190
  async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
53063
53191
  try {
53064
53192
  const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
53065
- const fs25 = await import("fs/promises");
53066
- const path28 = await import("path");
53193
+ const fs29 = await import("fs/promises");
53194
+ const path33 = await import("path");
53067
53195
  const schemaRaw = checkConfig.schema || "plain";
53068
53196
  const schema = typeof schemaRaw === "string" && !schemaRaw.includes("{{") && !schemaRaw.includes("{%") ? schemaRaw : typeof schemaRaw === "object" ? "code-review" : "plain";
53069
53197
  let templateContent;
@@ -53072,27 +53200,27 @@ async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
53072
53200
  logger.debug(`[LevelDispatch] Using inline template for ${checkId}`);
53073
53201
  } else if (checkConfig.template && checkConfig.template.file) {
53074
53202
  const file = String(checkConfig.template.file);
53075
- const resolved = path28.resolve(process.cwd(), file);
53076
- templateContent = await fs25.readFile(resolved, "utf-8");
53203
+ const resolved = path33.resolve(process.cwd(), file);
53204
+ templateContent = await fs29.readFile(resolved, "utf-8");
53077
53205
  logger.debug(`[LevelDispatch] Using template file for ${checkId}: ${resolved}`);
53078
53206
  } else if (schema && schema !== "plain") {
53079
53207
  const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
53080
53208
  if (sanitized) {
53081
53209
  const candidatePaths = [
53082
- path28.join(__dirname, "output", sanitized, "template.liquid"),
53210
+ path33.join(__dirname, "output", sanitized, "template.liquid"),
53083
53211
  // bundled: dist/output/
53084
- path28.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
53212
+ path33.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
53085
53213
  // source (from state-machine/states)
53086
- path28.join(__dirname, "..", "..", "..", "output", sanitized, "template.liquid"),
53214
+ path33.join(__dirname, "..", "..", "..", "output", sanitized, "template.liquid"),
53087
53215
  // source (alternate)
53088
- path28.join(process.cwd(), "output", sanitized, "template.liquid"),
53216
+ path33.join(process.cwd(), "output", sanitized, "template.liquid"),
53089
53217
  // fallback: cwd/output/
53090
- path28.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
53218
+ path33.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
53091
53219
  // fallback: cwd/dist/output/
53092
53220
  ];
53093
53221
  for (const p of candidatePaths) {
53094
53222
  try {
53095
- templateContent = await fs25.readFile(p, "utf-8");
53223
+ templateContent = await fs29.readFile(p, "utf-8");
53096
53224
  if (templateContent) {
53097
53225
  logger.debug(`[LevelDispatch] Using schema template for ${checkId}: ${p}`);
53098
53226
  break;
@@ -53699,16 +53827,16 @@ var init_runner = __esm({
53699
53827
  });
53700
53828
 
53701
53829
  // src/sandbox/docker-image-sandbox.ts
53702
- var import_util2, import_child_process3, import_fs5, import_path9, import_os, import_crypto2, execFileAsync, EXEC_MAX_BUFFER, DockerImageSandbox;
53830
+ var import_util2, import_child_process3, import_fs5, import_path10, import_os, import_crypto3, execFileAsync, EXEC_MAX_BUFFER, DockerImageSandbox;
53703
53831
  var init_docker_image_sandbox = __esm({
53704
53832
  "src/sandbox/docker-image-sandbox.ts"() {
53705
53833
  "use strict";
53706
53834
  import_util2 = require("util");
53707
53835
  import_child_process3 = require("child_process");
53708
53836
  import_fs5 = require("fs");
53709
- import_path9 = require("path");
53837
+ import_path10 = require("path");
53710
53838
  import_os = require("os");
53711
- import_crypto2 = require("crypto");
53839
+ import_crypto3 = require("crypto");
53712
53840
  init_logger();
53713
53841
  init_sandbox_telemetry();
53714
53842
  execFileAsync = (0, import_util2.promisify)(import_child_process3.execFile);
@@ -53726,7 +53854,7 @@ var init_docker_image_sandbox = __esm({
53726
53854
  this.config = config;
53727
53855
  this.repoPath = repoPath;
53728
53856
  this.visorDistPath = visorDistPath;
53729
- this.containerName = `visor-${name}-${(0, import_crypto2.randomUUID)().slice(0, 8)}`;
53857
+ this.containerName = `visor-${name}-${(0, import_crypto3.randomUUID)().slice(0, 8)}`;
53730
53858
  this.cacheVolumeMounts = cacheVolumeMounts;
53731
53859
  }
53732
53860
  /**
@@ -53751,8 +53879,8 @@ var init_docker_image_sandbox = __esm({
53751
53879
  `Sandbox '${this.name}' has invalid dockerfile_inline: must contain a FROM instruction`
53752
53880
  );
53753
53881
  }
53754
- const tmpDir = (0, import_fs5.mkdtempSync)((0, import_path9.join)((0, import_os.tmpdir)(), "visor-build-"));
53755
- const dockerfilePath = (0, import_path9.join)(tmpDir, "Dockerfile");
53882
+ const tmpDir = (0, import_fs5.mkdtempSync)((0, import_path10.join)((0, import_os.tmpdir)(), "visor-build-"));
53883
+ const dockerfilePath = (0, import_path10.join)(tmpDir, "Dockerfile");
53756
53884
  (0, import_fs5.writeFileSync)(dockerfilePath, this.config.dockerfile_inline, "utf8");
53757
53885
  try {
53758
53886
  logger.info(`Building sandbox image '${imageName}' from inline Dockerfile`);
@@ -53820,7 +53948,7 @@ var init_docker_image_sandbox = __esm({
53820
53948
  }
53821
53949
  if (this.config.bind_paths) {
53822
53950
  for (const bp of this.config.bind_paths) {
53823
- const hostPath = bp.host.startsWith("~") ? (0, import_path9.resolve)((process.env.HOME || "/root") + bp.host.slice(1)) : (0, import_path9.resolve)(bp.host);
53951
+ const hostPath = bp.host.startsWith("~") ? (0, import_path10.resolve)((process.env.HOME || "/root") + bp.host.slice(1)) : (0, import_path10.resolve)(bp.host);
53824
53952
  const containerPath = bp.container || hostPath;
53825
53953
  const readOnly = bp.read_only !== false;
53826
53954
  args.push("-v", `${hostPath}:${containerPath}${readOnly ? ":ro" : ""}`);
@@ -53891,13 +54019,13 @@ var init_docker_image_sandbox = __esm({
53891
54019
  });
53892
54020
 
53893
54021
  // src/sandbox/docker-compose-sandbox.ts
53894
- var import_util3, import_child_process4, import_crypto3, execFileAsync2, EXEC_MAX_BUFFER2, DockerComposeSandbox;
54022
+ var import_util3, import_child_process4, import_crypto4, execFileAsync2, EXEC_MAX_BUFFER2, DockerComposeSandbox;
53895
54023
  var init_docker_compose_sandbox = __esm({
53896
54024
  "src/sandbox/docker-compose-sandbox.ts"() {
53897
54025
  "use strict";
53898
54026
  import_util3 = require("util");
53899
54027
  import_child_process4 = require("child_process");
53900
- import_crypto3 = require("crypto");
54028
+ import_crypto4 = require("crypto");
53901
54029
  init_logger();
53902
54030
  execFileAsync2 = (0, import_util3.promisify)(import_child_process4.execFile);
53903
54031
  EXEC_MAX_BUFFER2 = 50 * 1024 * 1024;
@@ -53909,7 +54037,7 @@ var init_docker_compose_sandbox = __esm({
53909
54037
  constructor(name, config) {
53910
54038
  this.name = name;
53911
54039
  this.config = config;
53912
- this.projectName = `visor-${name}-${(0, import_crypto3.randomUUID)().slice(0, 8)}`;
54040
+ this.projectName = `visor-${name}-${(0, import_crypto4.randomUUID)().slice(0, 8)}`;
53913
54041
  }
53914
54042
  /**
53915
54043
  * Start the compose services
@@ -54001,7 +54129,7 @@ var init_docker_compose_sandbox = __esm({
54001
54129
 
54002
54130
  // src/sandbox/cache-volume-manager.ts
54003
54131
  function pathHash(containerPath) {
54004
- return (0, import_crypto4.createHash)("sha256").update(containerPath).digest("hex").slice(0, 8);
54132
+ return (0, import_crypto5.createHash)("sha256").update(containerPath).digest("hex").slice(0, 8);
54005
54133
  }
54006
54134
  function parseTtl(ttl) {
54007
54135
  let ms = 0;
@@ -54013,13 +54141,13 @@ function parseTtl(ttl) {
54013
54141
  if (minMatch) ms += parseInt(minMatch[1], 10) * 6e4;
54014
54142
  return ms || 6048e5;
54015
54143
  }
54016
- var import_util4, import_child_process5, import_crypto4, execFileAsync3, EXEC_MAX_BUFFER3, CacheVolumeManager;
54144
+ var import_util4, import_child_process5, import_crypto5, execFileAsync3, EXEC_MAX_BUFFER3, CacheVolumeManager;
54017
54145
  var init_cache_volume_manager = __esm({
54018
54146
  "src/sandbox/cache-volume-manager.ts"() {
54019
54147
  "use strict";
54020
54148
  import_util4 = require("util");
54021
54149
  import_child_process5 = require("child_process");
54022
- import_crypto4 = require("crypto");
54150
+ import_crypto5 = require("crypto");
54023
54151
  init_logger();
54024
54152
  execFileAsync3 = (0, import_util4.promisify)(import_child_process5.execFile);
54025
54153
  EXEC_MAX_BUFFER3 = 10 * 1024 * 1024;
@@ -54201,14 +54329,14 @@ var bubblewrap_sandbox_exports = {};
54201
54329
  __export(bubblewrap_sandbox_exports, {
54202
54330
  BubblewrapSandbox: () => BubblewrapSandbox
54203
54331
  });
54204
- var import_util5, import_child_process6, import_fs6, import_path10, execFileAsync4, EXEC_MAX_BUFFER4, BubblewrapSandbox;
54332
+ var import_util5, import_child_process6, import_fs6, import_path11, execFileAsync4, EXEC_MAX_BUFFER4, BubblewrapSandbox;
54205
54333
  var init_bubblewrap_sandbox = __esm({
54206
54334
  "src/sandbox/bubblewrap-sandbox.ts"() {
54207
54335
  "use strict";
54208
54336
  import_util5 = require("util");
54209
54337
  import_child_process6 = require("child_process");
54210
54338
  import_fs6 = require("fs");
54211
- import_path10 = require("path");
54339
+ import_path11 = require("path");
54212
54340
  init_logger();
54213
54341
  init_sandbox_telemetry();
54214
54342
  execFileAsync4 = (0, import_util5.promisify)(import_child_process6.execFile);
@@ -54221,8 +54349,8 @@ var init_bubblewrap_sandbox = __esm({
54221
54349
  constructor(name, config, repoPath, visorDistPath) {
54222
54350
  this.name = name;
54223
54351
  this.config = config;
54224
- this.repoPath = (0, import_path10.resolve)(repoPath);
54225
- this.visorDistPath = (0, import_path10.resolve)(visorDistPath);
54352
+ this.repoPath = (0, import_path11.resolve)(repoPath);
54353
+ this.visorDistPath = (0, import_path11.resolve)(visorDistPath);
54226
54354
  }
54227
54355
  /**
54228
54356
  * Check if bwrap binary is available on the system.
@@ -54307,7 +54435,7 @@ var init_bubblewrap_sandbox = __esm({
54307
54435
  args.push("--ro-bind", this.visorDistPath, visorPath);
54308
54436
  if (this.config.bind_paths) {
54309
54437
  for (const bp of this.config.bind_paths) {
54310
- const hostPath = bp.host.startsWith("~") ? (0, import_path10.resolve)((process.env.HOME || "/root") + bp.host.slice(1)) : (0, import_path10.resolve)(bp.host);
54438
+ const hostPath = bp.host.startsWith("~") ? (0, import_path11.resolve)((process.env.HOME || "/root") + bp.host.slice(1)) : (0, import_path11.resolve)(bp.host);
54311
54439
  const containerPath = bp.container || hostPath;
54312
54440
  const readOnly = bp.read_only !== false;
54313
54441
  args.push(readOnly ? "--ro-bind" : "--bind", hostPath, containerPath);
@@ -54338,13 +54466,13 @@ var seatbelt_sandbox_exports = {};
54338
54466
  __export(seatbelt_sandbox_exports, {
54339
54467
  SeatbeltSandbox: () => SeatbeltSandbox
54340
54468
  });
54341
- var import_util6, import_child_process7, import_path11, import_fs7, execFileAsync5, EXEC_MAX_BUFFER5, SeatbeltSandbox;
54469
+ var import_util6, import_child_process7, import_path12, import_fs7, execFileAsync5, EXEC_MAX_BUFFER5, SeatbeltSandbox;
54342
54470
  var init_seatbelt_sandbox = __esm({
54343
54471
  "src/sandbox/seatbelt-sandbox.ts"() {
54344
54472
  "use strict";
54345
54473
  import_util6 = require("util");
54346
54474
  import_child_process7 = require("child_process");
54347
- import_path11 = require("path");
54475
+ import_path12 = require("path");
54348
54476
  import_fs7 = require("fs");
54349
54477
  init_logger();
54350
54478
  init_sandbox_telemetry();
@@ -54358,8 +54486,8 @@ var init_seatbelt_sandbox = __esm({
54358
54486
  constructor(name, config, repoPath, visorDistPath) {
54359
54487
  this.name = name;
54360
54488
  this.config = config;
54361
- this.repoPath = (0, import_fs7.realpathSync)((0, import_path11.resolve)(repoPath));
54362
- this.visorDistPath = (0, import_fs7.realpathSync)((0, import_path11.resolve)(visorDistPath));
54489
+ this.repoPath = (0, import_fs7.realpathSync)((0, import_path12.resolve)(repoPath));
54490
+ this.visorDistPath = (0, import_fs7.realpathSync)((0, import_path12.resolve)(visorDistPath));
54363
54491
  }
54364
54492
  /**
54365
54493
  * Check if sandbox-exec binary is available on the system.
@@ -54464,7 +54592,7 @@ var init_seatbelt_sandbox = __esm({
54464
54592
  lines.push(`(allow file-read* (subpath "${visorDistPath}"))`);
54465
54593
  if (this.config.bind_paths) {
54466
54594
  for (const bp of this.config.bind_paths) {
54467
- const hostPath = bp.host.startsWith("~") ? (0, import_path11.resolve)((process.env.HOME || "/root") + bp.host.slice(1)) : (0, import_path11.resolve)(bp.host);
54595
+ const hostPath = bp.host.startsWith("~") ? (0, import_path12.resolve)((process.env.HOME || "/root") + bp.host.slice(1)) : (0, import_path12.resolve)(bp.host);
54468
54596
  const escapedPath = this.escapePath(hostPath);
54469
54597
  lines.push(`(allow file-read* (subpath "${escapedPath}"))`);
54470
54598
  if (bp.read_only === false) {
@@ -54485,11 +54613,11 @@ var init_seatbelt_sandbox = __esm({
54485
54613
  });
54486
54614
 
54487
54615
  // src/sandbox/sandbox-manager.ts
54488
- var import_path12, import_fs8, SandboxManager;
54616
+ var import_path13, import_fs8, SandboxManager;
54489
54617
  var init_sandbox_manager = __esm({
54490
54618
  "src/sandbox/sandbox-manager.ts"() {
54491
54619
  "use strict";
54492
- import_path12 = require("path");
54620
+ import_path13 = require("path");
54493
54621
  import_fs8 = require("fs");
54494
54622
  init_docker_image_sandbox();
54495
54623
  init_docker_compose_sandbox();
@@ -54509,10 +54637,10 @@ var init_sandbox_manager = __esm({
54509
54637
  }
54510
54638
  constructor(sandboxDefs, repoPath, gitBranch) {
54511
54639
  this.sandboxDefs = sandboxDefs;
54512
- this.repoPath = (0, import_path12.resolve)(repoPath);
54640
+ this.repoPath = (0, import_path13.resolve)(repoPath);
54513
54641
  this.gitBranch = gitBranch;
54514
54642
  this.cacheManager = new CacheVolumeManager();
54515
- this.visorDistPath = (0, import_fs8.existsSync)((0, import_path12.join)(__dirname, "index.js")) ? __dirname : (0, import_path12.resolve)((0, import_path12.dirname)(__dirname));
54643
+ this.visorDistPath = (0, import_fs8.existsSync)((0, import_path13.join)(__dirname, "index.js")) ? __dirname : (0, import_path13.resolve)((0, import_path13.dirname)(__dirname));
54516
54644
  }
54517
54645
  /**
54518
54646
  * Resolve which sandbox a check should use.
@@ -54641,13 +54769,13 @@ var init_sandbox_manager = __esm({
54641
54769
  });
54642
54770
 
54643
54771
  // src/utils/file-exclusion.ts
54644
- var import_ignore, fs19, path22, DEFAULT_EXCLUSION_PATTERNS, FileExclusionHelper;
54772
+ var import_ignore, fs19, path23, DEFAULT_EXCLUSION_PATTERNS, FileExclusionHelper;
54645
54773
  var init_file_exclusion = __esm({
54646
54774
  "src/utils/file-exclusion.ts"() {
54647
54775
  "use strict";
54648
54776
  import_ignore = __toESM(require("ignore"));
54649
54777
  fs19 = __toESM(require("fs"));
54650
- path22 = __toESM(require("path"));
54778
+ path23 = __toESM(require("path"));
54651
54779
  DEFAULT_EXCLUSION_PATTERNS = [
54652
54780
  "dist/",
54653
54781
  "build/",
@@ -54666,7 +54794,7 @@ var init_file_exclusion = __esm({
54666
54794
  * @param additionalPatterns - Additional patterns to include (optional, defaults to common build artifacts)
54667
54795
  */
54668
54796
  constructor(workingDirectory = process.cwd(), additionalPatterns = DEFAULT_EXCLUSION_PATTERNS) {
54669
- const normalizedPath = path22.resolve(workingDirectory);
54797
+ const normalizedPath = path23.resolve(workingDirectory);
54670
54798
  if (normalizedPath.includes("\0")) {
54671
54799
  throw new Error("Invalid workingDirectory: contains null bytes");
54672
54800
  }
@@ -54678,11 +54806,11 @@ var init_file_exclusion = __esm({
54678
54806
  * @param additionalPatterns - Additional patterns to add to gitignore rules
54679
54807
  */
54680
54808
  loadGitignore(additionalPatterns) {
54681
- const gitignorePath = path22.resolve(this.workingDirectory, ".gitignore");
54682
- const resolvedWorkingDir = path22.resolve(this.workingDirectory);
54809
+ const gitignorePath = path23.resolve(this.workingDirectory, ".gitignore");
54810
+ const resolvedWorkingDir = path23.resolve(this.workingDirectory);
54683
54811
  try {
54684
- const relativePath = path22.relative(resolvedWorkingDir, gitignorePath);
54685
- if (relativePath.startsWith("..") || path22.isAbsolute(relativePath)) {
54812
+ const relativePath = path23.relative(resolvedWorkingDir, gitignorePath);
54813
+ if (relativePath.startsWith("..") || path23.isAbsolute(relativePath)) {
54686
54814
  throw new Error("Invalid gitignore path: path traversal detected");
54687
54815
  }
54688
54816
  if (relativePath !== ".gitignore") {
@@ -54725,12 +54853,12 @@ var git_repository_analyzer_exports = {};
54725
54853
  __export(git_repository_analyzer_exports, {
54726
54854
  GitRepositoryAnalyzer: () => GitRepositoryAnalyzer
54727
54855
  });
54728
- var import_simple_git2, path23, fs20, MAX_PATCH_SIZE, GitRepositoryAnalyzer;
54856
+ var import_simple_git2, path24, fs20, MAX_PATCH_SIZE, GitRepositoryAnalyzer;
54729
54857
  var init_git_repository_analyzer = __esm({
54730
54858
  "src/git-repository-analyzer.ts"() {
54731
54859
  "use strict";
54732
54860
  import_simple_git2 = require("simple-git");
54733
- path23 = __toESM(require("path"));
54861
+ path24 = __toESM(require("path"));
54734
54862
  fs20 = __toESM(require("fs"));
54735
54863
  init_file_exclusion();
54736
54864
  MAX_PATCH_SIZE = 50 * 1024;
@@ -54920,7 +55048,7 @@ ${file.patch}`).join("\n\n");
54920
55048
  console.error(`\u23ED\uFE0F Skipping excluded file: ${file}`);
54921
55049
  continue;
54922
55050
  }
54923
- const filePath = path23.join(this.cwd, file);
55051
+ const filePath = path24.join(this.cwd, file);
54924
55052
  const fileChange = await this.analyzeFileChange(file, status2, filePath, includeContext);
54925
55053
  changes.push(fileChange);
54926
55054
  }
@@ -55146,12 +55274,12 @@ function shellEscape(str) {
55146
55274
  function sanitizePathComponent(name) {
55147
55275
  return name.replace(/\.\./g, "").replace(/[\/\\]/g, "-").replace(/^\.+/, "").trim() || "unnamed";
55148
55276
  }
55149
- var fsp2, path24, WorkspaceManager;
55277
+ var fsp2, path25, WorkspaceManager;
55150
55278
  var init_workspace_manager = __esm({
55151
55279
  "src/utils/workspace-manager.ts"() {
55152
55280
  "use strict";
55153
55281
  fsp2 = __toESM(require("fs/promises"));
55154
- path24 = __toESM(require("path"));
55282
+ path25 = __toESM(require("path"));
55155
55283
  init_command_executor();
55156
55284
  init_logger();
55157
55285
  WorkspaceManager = class _WorkspaceManager {
@@ -55185,7 +55313,7 @@ var init_workspace_manager = __esm({
55185
55313
  };
55186
55314
  this.basePath = this.config.basePath;
55187
55315
  const workspaceDirName = sanitizePathComponent(this.config.name || this.sessionId);
55188
- this.workspacePath = path24.join(this.basePath, workspaceDirName);
55316
+ this.workspacePath = path25.join(this.basePath, workspaceDirName);
55189
55317
  }
55190
55318
  /**
55191
55319
  * Get or create a WorkspaceManager instance for a session
@@ -55232,8 +55360,8 @@ var init_workspace_manager = __esm({
55232
55360
  );
55233
55361
  if (this.cleanupRequested && this.activeOperations === 0) {
55234
55362
  logger.debug(`[Workspace] All references released, proceeding with deferred cleanup`);
55235
- for (const resolve15 of this.cleanupResolvers) {
55236
- resolve15();
55363
+ for (const resolve19 of this.cleanupResolvers) {
55364
+ resolve19();
55237
55365
  }
55238
55366
  this.cleanupResolvers = [];
55239
55367
  }
@@ -55280,7 +55408,7 @@ var init_workspace_manager = __esm({
55280
55408
  configuredMainProjectName || this.extractProjectName(this.originalPath)
55281
55409
  );
55282
55410
  this.usedNames.add(mainProjectName);
55283
- const mainProjectPath = path24.join(this.workspacePath, mainProjectName);
55411
+ const mainProjectPath = path25.join(this.workspacePath, mainProjectName);
55284
55412
  const isGitRepo = await this.isGitRepository(this.originalPath);
55285
55413
  if (isGitRepo) {
55286
55414
  const exists = await this.pathExists(mainProjectPath);
@@ -55366,7 +55494,7 @@ var init_workspace_manager = __esm({
55366
55494
  let projectName = sanitizePathComponent(description || this.extractRepoName(repository));
55367
55495
  projectName = this.getUniqueName(projectName);
55368
55496
  this.usedNames.add(projectName);
55369
- const workspacePath = path24.join(this.workspacePath, projectName);
55497
+ const workspacePath = path25.join(this.workspacePath, projectName);
55370
55498
  await fsp2.rm(workspacePath, { recursive: true, force: true });
55371
55499
  try {
55372
55500
  await fsp2.symlink(worktreePath, workspacePath);
@@ -55412,19 +55540,19 @@ var init_workspace_manager = __esm({
55412
55540
  );
55413
55541
  this.cleanupRequested = true;
55414
55542
  await Promise.race([
55415
- new Promise((resolve15) => {
55543
+ new Promise((resolve19) => {
55416
55544
  if (this.activeOperations === 0) {
55417
- resolve15();
55545
+ resolve19();
55418
55546
  } else {
55419
- this.cleanupResolvers.push(resolve15);
55547
+ this.cleanupResolvers.push(resolve19);
55420
55548
  }
55421
55549
  }),
55422
- new Promise((resolve15) => {
55550
+ new Promise((resolve19) => {
55423
55551
  setTimeout(() => {
55424
55552
  logger.warn(
55425
55553
  `[Workspace] Cleanup timeout after ${timeout}ms, proceeding anyway (${this.activeOperations} operations still active)`
55426
55554
  );
55427
- resolve15();
55555
+ resolve19();
55428
55556
  }, timeout);
55429
55557
  })
55430
55558
  ]);
@@ -55476,7 +55604,7 @@ var init_workspace_manager = __esm({
55476
55604
  const now = Date.now();
55477
55605
  for (const entry of entries) {
55478
55606
  if (!entry.isDirectory()) continue;
55479
- const dirPath = path24.join(basePath, entry.name);
55607
+ const dirPath = path25.join(basePath, entry.name);
55480
55608
  try {
55481
55609
  const stat2 = await fsp2.stat(dirPath);
55482
55610
  if (now - stat2.mtimeMs > maxAgeMs) {
@@ -55484,8 +55612,8 @@ var init_workspace_manager = __esm({
55484
55612
  const subdirs = await fsp2.readdir(dirPath, { withFileTypes: true });
55485
55613
  for (const sub of subdirs) {
55486
55614
  if (!sub.isDirectory()) continue;
55487
- const subPath = path24.join(dirPath, sub.name);
55488
- const gitFilePath = path24.join(subPath, ".git");
55615
+ const subPath = path25.join(dirPath, sub.name);
55616
+ const gitFilePath = path25.join(subPath, ".git");
55489
55617
  try {
55490
55618
  const gitContent = await fsp2.readFile(gitFilePath, "utf-8");
55491
55619
  const match = gitContent.match(/gitdir:\s*(.+)/);
@@ -55710,7 +55838,7 @@ var init_workspace_manager = __esm({
55710
55838
  * Extract project name from path
55711
55839
  */
55712
55840
  extractProjectName(dirPath) {
55713
- return path24.basename(dirPath);
55841
+ return path25.basename(dirPath);
55714
55842
  }
55715
55843
  /**
55716
55844
  * Extract repository name from owner/repo format
@@ -55818,8 +55946,8 @@ var init_fair_concurrency_limiter = __esm({
55818
55946
  );
55819
55947
  const queuedAt = Date.now();
55820
55948
  const effectiveTimeout = queueTimeout ?? 12e4;
55821
- return new Promise((resolve15, reject) => {
55822
- const entry = { resolve: resolve15, reject, queuedAt };
55949
+ return new Promise((resolve19, reject) => {
55950
+ const entry = { resolve: resolve19, reject, queuedAt };
55823
55951
  entry.reminder = setInterval(() => {
55824
55952
  const waited = Math.round((Date.now() - queuedAt) / 1e3);
55825
55953
  const curQueued = this._totalQueued();
@@ -56126,6 +56254,1380 @@ var init_build_engine_context = __esm({
56126
56254
  }
56127
56255
  });
56128
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
+
56129
57631
  // src/event-bus/event-bus.ts
56130
57632
  var event_bus_exports = {};
56131
57633
  __export(event_bus_exports, {
@@ -56171,12 +57673,12 @@ var ndjson_sink_exports = {};
56171
57673
  __export(ndjson_sink_exports, {
56172
57674
  NdjsonSink: () => NdjsonSink
56173
57675
  });
56174
- var import_fs9, import_path13, NdjsonSink;
57676
+ var import_fs9, import_path14, NdjsonSink;
56175
57677
  var init_ndjson_sink = __esm({
56176
57678
  "src/frontends/ndjson-sink.ts"() {
56177
57679
  "use strict";
56178
57680
  import_fs9 = __toESM(require("fs"));
56179
- import_path13 = __toESM(require("path"));
57681
+ import_path14 = __toESM(require("path"));
56180
57682
  NdjsonSink = class {
56181
57683
  name = "ndjson-sink";
56182
57684
  cfg;
@@ -56208,8 +57710,8 @@ var init_ndjson_sink = __esm({
56208
57710
  this.unsub = void 0;
56209
57711
  }
56210
57712
  resolveFile(p) {
56211
- if (import_path13.default.isAbsolute(p)) return p;
56212
- return import_path13.default.join(process.cwd(), p);
57713
+ if (import_path14.default.isAbsolute(p)) return p;
57714
+ return import_path14.default.join(process.cwd(), p);
56213
57715
  }
56214
57716
  };
56215
57717
  }
@@ -57032,8 +58534,8 @@ ${content}
57032
58534
  * Sleep utility
57033
58535
  */
57034
58536
  sleep(ms) {
57035
- return new Promise((resolve15) => {
57036
- const t = setTimeout(resolve15, ms);
58537
+ return new Promise((resolve19) => {
58538
+ const t = setTimeout(resolve19, ms);
57037
58539
  if (typeof t.unref === "function") {
57038
58540
  try {
57039
58541
  t.unref();
@@ -57318,8 +58820,8 @@ ${end}`);
57318
58820
  async updateGroupedComment(ctx, comments, group, changedIds) {
57319
58821
  const existingLock = this.updateLocks.get(group);
57320
58822
  let resolveLock;
57321
- const ourLock = new Promise((resolve15) => {
57322
- resolveLock = resolve15;
58823
+ const ourLock = new Promise((resolve19) => {
58824
+ resolveLock = resolve19;
57323
58825
  });
57324
58826
  this.updateLocks.set(group, ourLock);
57325
58827
  try {
@@ -57650,7 +59152,7 @@ ${blocks}
57650
59152
  * Sleep utility for enforcing delays
57651
59153
  */
57652
59154
  sleep(ms) {
57653
- return new Promise((resolve15) => setTimeout(resolve15, ms));
59155
+ return new Promise((resolve19) => setTimeout(resolve19, ms));
57654
59156
  }
57655
59157
  };
57656
59158
  }
@@ -58819,7 +60321,7 @@ var init_tui_frontend = __esm({
58819
60321
  });
58820
60322
 
58821
60323
  // src/agent-protocol/task-store.ts
58822
- function safeJsonParse2(value) {
60324
+ function safeJsonParse3(value) {
58823
60325
  if (!value) return void 0;
58824
60326
  try {
58825
60327
  return JSON.parse(value);
@@ -58836,22 +60338,22 @@ function taskRowToAgentTask(row) {
58836
60338
  context_id: row.context_id,
58837
60339
  status: {
58838
60340
  state: row.state,
58839
- message: safeJsonParse2(row.status_message),
60341
+ message: safeJsonParse3(row.status_message),
58840
60342
  timestamp: row.updated_at
58841
60343
  },
58842
- artifacts: safeJsonParse2(row.artifacts) ?? [],
58843
- history: safeJsonParse2(row.history) ?? [],
58844
- metadata: safeJsonParse2(row.request_metadata),
60344
+ artifacts: safeJsonParse3(row.artifacts) ?? [],
60345
+ history: safeJsonParse3(row.history) ?? [],
60346
+ metadata: safeJsonParse3(row.request_metadata),
58845
60347
  workflow_id: row.workflow_id ?? void 0
58846
60348
  };
58847
60349
  }
58848
- var import_path14, import_fs10, import_crypto5, SqliteTaskStore;
60350
+ var import_path15, import_fs10, import_crypto6, SqliteTaskStore;
58849
60351
  var init_task_store = __esm({
58850
60352
  "src/agent-protocol/task-store.ts"() {
58851
60353
  "use strict";
58852
- import_path14 = __toESM(require("path"));
60354
+ import_path15 = __toESM(require("path"));
58853
60355
  import_fs10 = __toESM(require("fs"));
58854
- import_crypto5 = __toESM(require("crypto"));
60356
+ import_crypto6 = __toESM(require("crypto"));
58855
60357
  init_logger();
58856
60358
  init_types();
58857
60359
  init_state_transitions();
@@ -58862,8 +60364,8 @@ var init_task_store = __esm({
58862
60364
  this.dbPath = filename || ".visor/agent-tasks.db";
58863
60365
  }
58864
60366
  async initialize() {
58865
- const resolvedPath = import_path14.default.resolve(process.cwd(), this.dbPath);
58866
- const dir = import_path14.default.dirname(resolvedPath);
60367
+ const resolvedPath = import_path15.default.resolve(process.cwd(), this.dbPath);
60368
+ const dir = import_path15.default.dirname(resolvedPath);
58867
60369
  import_fs10.default.mkdirSync(dir, { recursive: true });
58868
60370
  const { createRequire } = require("module");
58869
60371
  const runtimeRequire = createRequire(__filename);
@@ -58932,7 +60434,7 @@ var init_task_store = __esm({
58932
60434
  // -------------------------------------------------------------------------
58933
60435
  createTask(params) {
58934
60436
  const db = this.getDb();
58935
- const id = import_crypto5.default.randomUUID();
60437
+ const id = import_crypto6.default.randomUUID();
58936
60438
  const now = nowISO();
58937
60439
  const contextId = this.resolveContextId(params.requestMessage, params.contextId);
58938
60440
  const expiresAt = params.expiresAt ?? null;
@@ -59019,6 +60521,13 @@ var init_task_store = __esm({
59019
60521
  messageText = textPart?.text ?? "";
59020
60522
  } catch {
59021
60523
  }
60524
+ let source = "-";
60525
+ let metadata = {};
60526
+ try {
60527
+ metadata = JSON.parse(r.request_metadata || "{}");
60528
+ source = metadata.source || "-";
60529
+ } catch {
60530
+ }
59022
60531
  return {
59023
60532
  id: r.id,
59024
60533
  context_id: r.context_id,
@@ -59029,7 +60538,9 @@ var init_task_store = __esm({
59029
60538
  claimed_at: r.claimed_at,
59030
60539
  workflow_id: r.workflow_id,
59031
60540
  run_id: r.run_id,
59032
- request_message: messageText
60541
+ request_message: messageText,
60542
+ source,
60543
+ metadata
59033
60544
  };
59034
60545
  });
59035
60546
  return { rows, total };
@@ -59049,11 +60560,18 @@ var init_task_store = __esm({
59049
60560
  WHERE id = ?`
59050
60561
  ).run(newState, now, statusMessage ? JSON.stringify(statusMessage) : null, taskId);
59051
60562
  }
60563
+ claimTask(taskId, workerId) {
60564
+ const db = this.getDb();
60565
+ const now = nowISO();
60566
+ db.prepare(
60567
+ `UPDATE agent_tasks SET claimed_by = ?, claimed_at = ?, updated_at = ? WHERE id = ?`
60568
+ ).run(workerId, now, now, taskId);
60569
+ }
59052
60570
  addArtifact(taskId, artifact) {
59053
60571
  const db = this.getDb();
59054
60572
  const row = db.prepare("SELECT artifacts FROM agent_tasks WHERE id = ?").get(taskId);
59055
60573
  if (!row) throw new TaskNotFoundError(taskId);
59056
- const artifacts = safeJsonParse2(row.artifacts) ?? [];
60574
+ const artifacts = safeJsonParse3(row.artifacts) ?? [];
59057
60575
  artifacts.push(artifact);
59058
60576
  db.prepare("UPDATE agent_tasks SET artifacts = ?, updated_at = ? WHERE id = ?").run(
59059
60577
  JSON.stringify(artifacts),
@@ -59065,7 +60583,7 @@ var init_task_store = __esm({
59065
60583
  const db = this.getDb();
59066
60584
  const row = db.prepare("SELECT history FROM agent_tasks WHERE id = ?").get(taskId);
59067
60585
  if (!row) throw new TaskNotFoundError(taskId);
59068
- const history = safeJsonParse2(row.history) ?? [];
60586
+ const history = safeJsonParse3(row.history) ?? [];
59069
60587
  history.push(message);
59070
60588
  db.prepare("UPDATE agent_tasks SET history = ?, updated_at = ? WHERE id = ?").run(
59071
60589
  JSON.stringify(history),
@@ -59270,11 +60788,11 @@ var init_task_stream_manager = __esm({
59270
60788
  });
59271
60789
 
59272
60790
  // src/agent-protocol/push-notification-manager.ts
59273
- var import_crypto6, PushNotificationManager;
60791
+ var import_crypto7, PushNotificationManager;
59274
60792
  var init_push_notification_manager = __esm({
59275
60793
  "src/agent-protocol/push-notification-manager.ts"() {
59276
60794
  "use strict";
59277
- import_crypto6 = __toESM(require("crypto"));
60795
+ import_crypto7 = __toESM(require("crypto"));
59278
60796
  init_logger();
59279
60797
  PushNotificationManager = class {
59280
60798
  db = null;
@@ -59319,7 +60837,7 @@ var init_push_notification_manager = __esm({
59319
60837
  // -------------------------------------------------------------------------
59320
60838
  create(config) {
59321
60839
  const db = this.getDb();
59322
- const id = config.id ?? import_crypto6.default.randomUUID();
60840
+ const id = config.id ?? import_crypto7.default.randomUUID();
59323
60841
  const now = (/* @__PURE__ */ new Date()).toISOString();
59324
60842
  db.prepare(
59325
60843
  `INSERT INTO agent_push_configs (id, task_id, url, token, auth_scheme, auth_credentials, created_at)
@@ -59417,11 +60935,11 @@ var init_push_notification_manager = __esm({
59417
60935
  });
59418
60936
 
59419
60937
  // src/agent-protocol/task-queue.ts
59420
- var import_crypto7, DEFAULT_CONFIG, TaskQueue;
60938
+ var import_crypto8, DEFAULT_CONFIG, TaskQueue;
59421
60939
  var init_task_queue = __esm({
59422
60940
  "src/agent-protocol/task-queue.ts"() {
59423
60941
  "use strict";
59424
- import_crypto7 = __toESM(require("crypto"));
60942
+ import_crypto8 = __toESM(require("crypto"));
59425
60943
  init_logger();
59426
60944
  init_trace_helpers();
59427
60945
  DEFAULT_CONFIG = {
@@ -59434,7 +60952,7 @@ var init_task_queue = __esm({
59434
60952
  this.taskStore = taskStore;
59435
60953
  this.executor = executor;
59436
60954
  this.config = { ...DEFAULT_CONFIG, ...config };
59437
- this.workerId = workerId ?? import_crypto7.default.randomUUID();
60955
+ this.workerId = workerId ?? import_crypto8.default.randomUUID();
59438
60956
  }
59439
60957
  running = false;
59440
60958
  timer = null;
@@ -59508,7 +61026,7 @@ var init_task_queue = __esm({
59508
61026
  }
59509
61027
  if (result.success) {
59510
61028
  const completedMsg = {
59511
- message_id: import_crypto7.default.randomUUID(),
61029
+ message_id: import_crypto8.default.randomUUID(),
59512
61030
  role: "agent",
59513
61031
  parts: [
59514
61032
  {
@@ -59520,7 +61038,7 @@ var init_task_queue = __esm({
59520
61038
  this.taskStore.updateTaskState(task.id, "completed", completedMsg);
59521
61039
  } else {
59522
61040
  this.taskStore.updateTaskState(task.id, "failed", {
59523
- message_id: import_crypto7.default.randomUUID(),
61041
+ message_id: import_crypto8.default.randomUUID(),
59524
61042
  role: "agent",
59525
61043
  parts: [{ text: result.error ?? "Task execution failed" }]
59526
61044
  });
@@ -59531,7 +61049,7 @@ var init_task_queue = __esm({
59531
61049
  );
59532
61050
  try {
59533
61051
  this.taskStore.updateTaskState(task.id, "failed", {
59534
- message_id: import_crypto7.default.randomUUID(),
61052
+ message_id: import_crypto8.default.randomUUID(),
59535
61053
  role: "agent",
59536
61054
  parts: [{ text: err instanceof Error ? err.message : "Unknown error" }]
59537
61055
  });
@@ -59551,13 +61069,13 @@ __export(a2a_frontend_exports, {
59551
61069
  resultToArtifacts: () => resultToArtifacts
59552
61070
  });
59553
61071
  function readJsonBody(req) {
59554
- return new Promise((resolve15, reject) => {
61072
+ return new Promise((resolve19, reject) => {
59555
61073
  const chunks = [];
59556
61074
  req.on("data", (chunk) => chunks.push(chunk));
59557
61075
  req.on("end", () => {
59558
61076
  try {
59559
61077
  const body = Buffer.concat(chunks).toString("utf8");
59560
- resolve15(body ? JSON.parse(body) : {});
61078
+ resolve19(body ? JSON.parse(body) : {});
59561
61079
  } catch {
59562
61080
  reject(new ParseError("Malformed JSON body"));
59563
61081
  }
@@ -59585,7 +61103,7 @@ function timingSafeEqual(a, b) {
59585
61103
  if (!a || !b) return false;
59586
61104
  if (a.length !== b.length) return false;
59587
61105
  try {
59588
- return import_crypto8.default.timingSafeEqual(Buffer.from(a), Buffer.from(b));
61106
+ return import_crypto9.default.timingSafeEqual(Buffer.from(a), Buffer.from(b));
59589
61107
  } catch {
59590
61108
  return false;
59591
61109
  }
@@ -59659,7 +61177,7 @@ function resultToArtifacts(checkResults) {
59659
61177
  }
59660
61178
  if (parts.length > 0) {
59661
61179
  artifacts.push({
59662
- artifact_id: import_crypto8.default.randomUUID(),
61180
+ artifact_id: import_crypto9.default.randomUUID(),
59663
61181
  name: checkId,
59664
61182
  description: `Output from check: ${checkId}`,
59665
61183
  parts
@@ -59668,14 +61186,14 @@ function resultToArtifacts(checkResults) {
59668
61186
  }
59669
61187
  return artifacts;
59670
61188
  }
59671
- var import_http2, import_https, import_fs11, import_crypto8, A2AFrontend;
61189
+ var import_http2, import_https, import_fs11, import_crypto9, A2AFrontend;
59672
61190
  var init_a2a_frontend = __esm({
59673
61191
  "src/agent-protocol/a2a-frontend.ts"() {
59674
61192
  "use strict";
59675
61193
  import_http2 = __toESM(require("http"));
59676
61194
  import_https = __toESM(require("https"));
59677
61195
  import_fs11 = __toESM(require("fs"));
59678
- import_crypto8 = __toESM(require("crypto"));
61196
+ import_crypto9 = __toESM(require("crypto"));
59679
61197
  init_logger();
59680
61198
  init_task_store();
59681
61199
  init_types();
@@ -59769,7 +61287,7 @@ var init_a2a_frontend = __esm({
59769
61287
  if (!taskId) return;
59770
61288
  try {
59771
61289
  const statusMessage = {
59772
- message_id: import_crypto8.default.randomUUID(),
61290
+ message_id: import_crypto9.default.randomUUID(),
59773
61291
  role: "agent",
59774
61292
  parts: [{ text: envelope.payload?.prompt ?? "Agent requires input" }]
59775
61293
  };
@@ -59800,12 +61318,12 @@ var init_a2a_frontend = __esm({
59800
61318
  }
59801
61319
  const port = this.config.port ?? 9e3;
59802
61320
  const host = this.config.host ?? "0.0.0.0";
59803
- await new Promise((resolve15) => {
61321
+ await new Promise((resolve19) => {
59804
61322
  this.server.listen(port, host, () => {
59805
61323
  const addr = this.server.address();
59806
61324
  this._boundPort = typeof addr === "object" && addr ? addr.port : port;
59807
61325
  logger.info(`A2A server listening on ${host}:${this._boundPort}`);
59808
- resolve15();
61326
+ resolve19();
59809
61327
  });
59810
61328
  });
59811
61329
  if (this.agentCard) {
@@ -59829,8 +61347,8 @@ var init_a2a_frontend = __esm({
59829
61347
  }
59830
61348
  this.streamManager.shutdown();
59831
61349
  if (this.server) {
59832
- await new Promise((resolve15, reject) => {
59833
- this.server.close((err) => err ? reject(err) : resolve15());
61350
+ await new Promise((resolve19, reject) => {
61351
+ this.server.close((err) => err ? reject(err) : resolve19());
59834
61352
  });
59835
61353
  this.server = null;
59836
61354
  }
@@ -59941,7 +61459,7 @@ var init_a2a_frontend = __esm({
59941
61459
  const response = await this.handleFollowUpMessage(existingTaskId, body);
59942
61460
  return sendJson(res, 200, response);
59943
61461
  }
59944
- const contextId = body.message.context_id ?? import_crypto8.default.randomUUID();
61462
+ const contextId = body.message.context_id ?? import_crypto9.default.randomUUID();
59945
61463
  const workflowId = resolveWorkflow(body, this.config);
59946
61464
  const blocking = body.configuration?.blocking ?? false;
59947
61465
  await withActiveSpan(
@@ -60054,7 +61572,7 @@ var init_a2a_frontend = __esm({
60054
61572
  if (!body.message?.parts?.length) {
60055
61573
  throw new InvalidRequestError("Message must contain at least one part");
60056
61574
  }
60057
- const contextId = body.message.context_id ?? import_crypto8.default.randomUUID();
61575
+ const contextId = body.message.context_id ?? import_crypto9.default.randomUUID();
60058
61576
  const workflowId = resolveWorkflow(body, this.config);
60059
61577
  const task = this.taskStore.createTask({
60060
61578
  contextId,
@@ -60188,7 +61706,7 @@ var init_a2a_frontend = __esm({
60188
61706
  await this.executeTaskViaEngine(task, message);
60189
61707
  } else {
60190
61708
  const agentResponse = {
60191
- message_id: import_crypto8.default.randomUUID(),
61709
+ message_id: import_crypto9.default.randomUUID(),
60192
61710
  role: "agent",
60193
61711
  parts: [{ text: `Task ${task.id} received and processed.`, media_type: "text/markdown" }]
60194
61712
  };
@@ -60200,7 +61718,7 @@ var init_a2a_frontend = __esm({
60200
61718
  logger.error(`[A2A] Task ${task.id} execution failed: ${errorMsg}`);
60201
61719
  try {
60202
61720
  const failMessage = {
60203
- message_id: import_crypto8.default.randomUUID(),
61721
+ message_id: import_crypto9.default.randomUUID(),
60204
61722
  role: "agent",
60205
61723
  parts: [{ text: errorMsg }]
60206
61724
  };
@@ -60243,7 +61761,7 @@ ${issueText}`, media_type: "text/markdown" });
60243
61761
  }
60244
61762
  if (summaryParts.length > 0) {
60245
61763
  artifacts.push({
60246
- artifact_id: import_crypto8.default.randomUUID(),
61764
+ artifact_id: import_crypto9.default.randomUUID(),
60247
61765
  name: "review-summary",
60248
61766
  description: "Review summary with issues found",
60249
61767
  parts: summaryParts
@@ -60263,7 +61781,7 @@ ${issueText}`, media_type: "text/markdown" });
60263
61781
  }
60264
61782
  if (parts.length > 0) {
60265
61783
  artifacts.push({
60266
- artifact_id: import_crypto8.default.randomUUID(),
61784
+ artifact_id: import_crypto9.default.randomUUID(),
60267
61785
  name: cr.checkName ?? groupName,
60268
61786
  description: `Output from check: ${cr.checkName ?? groupName}`,
60269
61787
  parts
@@ -60274,7 +61792,7 @@ ${issueText}`, media_type: "text/markdown" });
60274
61792
  }
60275
61793
  if (artifacts.length === 0) {
60276
61794
  artifacts.push({
60277
- artifact_id: import_crypto8.default.randomUUID(),
61795
+ artifact_id: import_crypto9.default.randomUUID(),
60278
61796
  name: "result",
60279
61797
  description: "Execution result",
60280
61798
  parts: [
@@ -60296,7 +61814,7 @@ ${issueText}`, media_type: "text/markdown" });
60296
61814
  );
60297
61815
  }
60298
61816
  const agentResponse = {
60299
- message_id: import_crypto8.default.randomUUID(),
61817
+ message_id: import_crypto9.default.randomUUID(),
60300
61818
  role: "agent",
60301
61819
  parts: [
60302
61820
  {
@@ -60349,7 +61867,7 @@ ${issueText}`, media_type: "text/markdown" });
60349
61867
  }
60350
61868
  if (parts.length === 0) return null;
60351
61869
  return {
60352
- artifact_id: import_crypto8.default.randomUUID(),
61870
+ artifact_id: import_crypto9.default.randomUUID(),
60353
61871
  name: p.checkId ?? "check-result",
60354
61872
  parts
60355
61873
  };
@@ -60535,15 +62053,15 @@ function serializeRunState(state) {
60535
62053
  ])
60536
62054
  };
60537
62055
  }
60538
- var path27, fs24, StateMachineExecutionEngine;
62056
+ var path32, fs28, StateMachineExecutionEngine;
60539
62057
  var init_state_machine_execution_engine = __esm({
60540
62058
  "src/state-machine-execution-engine.ts"() {
60541
62059
  "use strict";
60542
62060
  init_runner();
60543
62061
  init_logger();
60544
62062
  init_sandbox_manager();
60545
- path27 = __toESM(require("path"));
60546
- fs24 = __toESM(require("fs"));
62063
+ path32 = __toESM(require("path"));
62064
+ fs28 = __toESM(require("fs"));
60547
62065
  StateMachineExecutionEngine = class _StateMachineExecutionEngine {
60548
62066
  workingDirectory;
60549
62067
  executionContext;
@@ -60775,8 +62293,8 @@ var init_state_machine_execution_engine = __esm({
60775
62293
  logger.debug(
60776
62294
  `[PolicyEngine] Loading enterprise policy engine (engine=${configWithTagFilter.policy.engine})`
60777
62295
  );
60778
- const { loadEnterprisePolicyEngine } = await import("./enterprise/loader");
60779
- context2.policyEngine = await loadEnterprisePolicyEngine(configWithTagFilter.policy);
62296
+ const { loadEnterprisePolicyEngine: loadEnterprisePolicyEngine2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
62297
+ context2.policyEngine = await loadEnterprisePolicyEngine2(configWithTagFilter.policy);
60780
62298
  logger.debug(
60781
62299
  `[PolicyEngine] Initialized: ${context2.policyEngine?.constructor?.name || "unknown"}`
60782
62300
  );
@@ -60930,9 +62448,9 @@ var init_state_machine_execution_engine = __esm({
60930
62448
  }
60931
62449
  const checkId = String(ev?.checkId || "unknown");
60932
62450
  const threadKey = ev?.threadKey || (channel && threadTs ? `${channel}:${threadTs}` : "session");
60933
- const baseDir = process.env.VISOR_SNAPSHOT_DIR || path27.resolve(process.cwd(), ".visor", "snapshots");
60934
- fs24.mkdirSync(baseDir, { recursive: true });
60935
- const filePath = path27.join(baseDir, `${threadKey}-${checkId}.json`);
62451
+ const baseDir = process.env.VISOR_SNAPSHOT_DIR || path32.resolve(process.cwd(), ".visor", "snapshots");
62452
+ fs28.mkdirSync(baseDir, { recursive: true });
62453
+ const filePath = path32.join(baseDir, `${threadKey}-${checkId}.json`);
60936
62454
  await this.saveSnapshotToFile(filePath);
60937
62455
  logger.info(`[Snapshot] Saved run snapshot: ${filePath}`);
60938
62456
  try {
@@ -61073,7 +62591,7 @@ var init_state_machine_execution_engine = __esm({
61073
62591
  * Does not include secrets. Intended for debugging and future resume support.
61074
62592
  */
61075
62593
  async saveSnapshotToFile(filePath) {
61076
- const fs25 = await import("fs/promises");
62594
+ const fs29 = await import("fs/promises");
61077
62595
  const ctx = this._lastContext;
61078
62596
  const runner = this._lastRunner;
61079
62597
  if (!ctx || !runner) {
@@ -61093,14 +62611,14 @@ var init_state_machine_execution_engine = __esm({
61093
62611
  journal: entries,
61094
62612
  requestedChecks: ctx.requestedChecks || []
61095
62613
  };
61096
- await fs25.writeFile(filePath, JSON.stringify(payload, null, 2), "utf8");
62614
+ await fs29.writeFile(filePath, JSON.stringify(payload, null, 2), "utf8");
61097
62615
  }
61098
62616
  /**
61099
62617
  * Load a snapshot JSON from file and return it. Resume support can build on this.
61100
62618
  */
61101
62619
  async loadSnapshotFromFile(filePath) {
61102
- const fs25 = await import("fs/promises");
61103
- const raw = await fs25.readFile(filePath, "utf8");
62620
+ const fs29 = await import("fs/promises");
62621
+ const raw = await fs29.readFile(filePath, "utf8");
61104
62622
  return JSON.parse(raw);
61105
62623
  }
61106
62624
  /**