@probelabs/visor 0.1.163 → 0.1.164-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.
- package/dist/ai-review-service.d.ts +2 -0
- package/dist/ai-review-service.d.ts.map +1 -1
- package/dist/generated/config-schema.d.ts +14 -6
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/generated/config-schema.json +14 -6
- package/dist/index.js +1997 -136
- package/dist/providers/ai-check-provider.d.ts.map +1 -1
- package/dist/sdk/{check-provider-registry-JGXU3OEJ.mjs → check-provider-registry-AWFYHQAW.mjs} +6 -6
- package/dist/sdk/{check-provider-registry-XE2FY37D.mjs → check-provider-registry-TTVN3V2O.mjs} +6 -6
- package/dist/sdk/{chunk-AS6LIEO4.mjs → chunk-DEAPFYNX.mjs} +15 -7
- package/dist/sdk/chunk-DEAPFYNX.mjs.map +1 -0
- package/dist/sdk/{chunk-53RHNNWQ.mjs → chunk-GOJRNYTV.mjs} +31 -17
- package/dist/sdk/chunk-GOJRNYTV.mjs.map +1 -0
- package/dist/sdk/{chunk-WBSARB5X.mjs → chunk-J236ZVYX.mjs} +3 -3
- package/dist/sdk/{chunk-PQACCZF7.mjs → chunk-N4SZPYA6.mjs} +32 -18
- package/dist/sdk/chunk-N4SZPYA6.mjs.map +1 -0
- package/dist/sdk/{chunk-ZH6K5NSC.mjs → chunk-S47KBQQK.mjs} +2 -2
- package/dist/sdk/{chunk-ZH6K5NSC.mjs.map → chunk-S47KBQQK.mjs.map} +1 -1
- package/dist/sdk/{chunk-I7J2BNOK.mjs → chunk-XDIBL7QB.mjs} +2 -2
- package/dist/sdk/{config-CWHZO5AL.mjs → config-D6WF2U4B.mjs} +2 -2
- package/dist/sdk/{failure-condition-evaluator-MEX6VNYT.mjs → failure-condition-evaluator-N3VNLWZD.mjs} +3 -3
- package/dist/sdk/{github-frontend-QSXBPYQZ.mjs → github-frontend-ATORHHF6.mjs} +3 -3
- package/dist/sdk/{host-PRANMDPG.mjs → host-OBXKDFT7.mjs} +2 -2
- package/dist/sdk/{host-Q4N357JE.mjs → host-QFABFVSJ.mjs} +2 -2
- package/dist/sdk/knex-store-CRORFJE6.mjs +527 -0
- package/dist/sdk/knex-store-CRORFJE6.mjs.map +1 -0
- package/dist/sdk/loader-NJCF7DUS.mjs +89 -0
- package/dist/sdk/loader-NJCF7DUS.mjs.map +1 -0
- package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs +655 -0
- package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
- package/dist/sdk/{routing-7CQ7QWYE.mjs → routing-TGJD66Q5.mjs} +4 -4
- package/dist/sdk/{schedule-tool-FYV3JUF7.mjs → schedule-tool-D5TSTGP2.mjs} +6 -6
- package/dist/sdk/{schedule-tool-VUAATWZX.mjs → schedule-tool-SPUM47DS.mjs} +6 -6
- package/dist/sdk/{schedule-tool-handler-A5PN6FU3.mjs → schedule-tool-handler-CT5DUQ32.mjs} +6 -6
- package/dist/sdk/{schedule-tool-handler-ALCEOPSP.mjs → schedule-tool-handler-DKHHPZAG.mjs} +6 -6
- package/dist/sdk/sdk.d.mts +4 -0
- package/dist/sdk/sdk.d.ts +4 -0
- package/dist/sdk/sdk.js +1662 -266
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +5 -5
- package/dist/sdk/{trace-helpers-VDR4RKGC.mjs → trace-helpers-J5CJ4PUN.mjs} +2 -2
- package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
- package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-EO2U27T5.mjs → workflow-check-provider-JORTTXVH.mjs} +6 -6
- package/dist/sdk/{workflow-check-provider-XIZZYC3E.mjs → workflow-check-provider-T6WFK4RB.mjs} +6 -6
- package/dist/types/config.d.ts +4 -0
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/output/traces/run-2026-03-05T19-35-29-511Z.ndjson +0 -138
- package/dist/output/traces/run-2026-03-05T19-36-14-950Z.ndjson +0 -2235
- package/dist/sdk/check-provider-registry-BDPHCHX3.mjs +0 -29
- package/dist/sdk/chunk-53RHNNWQ.mjs.map +0 -1
- package/dist/sdk/chunk-7JOA3LUH.mjs +0 -43877
- package/dist/sdk/chunk-7JOA3LUH.mjs.map +0 -1
- package/dist/sdk/chunk-AS6LIEO4.mjs.map +0 -1
- package/dist/sdk/chunk-PQACCZF7.mjs.map +0 -1
- package/dist/sdk/chunk-R5PIUZSD.mjs +0 -1502
- package/dist/sdk/chunk-TH6WMIV7.mjs +0 -739
- package/dist/sdk/chunk-TH6WMIV7.mjs.map +0 -1
- package/dist/sdk/chunk-TLM6C3Q6.mjs +0 -443
- package/dist/sdk/chunk-TLM6C3Q6.mjs.map +0 -1
- package/dist/sdk/chunk-WBSARB5X.mjs.map +0 -1
- package/dist/sdk/failure-condition-evaluator-NBRX4N23.mjs +0 -17
- package/dist/sdk/github-frontend-UKDXNGOG.mjs +0 -1368
- package/dist/sdk/github-frontend-UKDXNGOG.mjs.map +0 -1
- package/dist/sdk/routing-N2XJVSCQ.mjs +0 -25
- package/dist/sdk/schedule-tool-DCODWSDM.mjs +0 -35
- package/dist/sdk/schedule-tool-handler-ALCEOPSP.mjs.map +0 -1
- package/dist/sdk/schedule-tool-handler-D6Z3PCDJ.mjs +0 -39
- package/dist/sdk/schedule-tool-handler-D6Z3PCDJ.mjs.map +0 -1
- package/dist/sdk/trace-helpers-JFELCJZT.mjs +0 -25
- package/dist/sdk/trace-helpers-JFELCJZT.mjs.map +0 -1
- package/dist/sdk/trace-helpers-VDR4RKGC.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-B2FOW6P2.mjs +0 -29
- package/dist/sdk/workflow-check-provider-B2FOW6P2.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-EO2U27T5.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-XIZZYC3E.mjs.map +0 -1
- package/dist/traces/run-2026-03-05T19-35-29-511Z.ndjson +0 -138
- package/dist/traces/run-2026-03-05T19-36-14-950Z.ndjson +0 -2235
- /package/dist/sdk/{check-provider-registry-BDPHCHX3.mjs.map → check-provider-registry-AWFYHQAW.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-JGXU3OEJ.mjs.map → check-provider-registry-TTVN3V2O.mjs.map} +0 -0
- /package/dist/sdk/{chunk-R5PIUZSD.mjs.map → chunk-J236ZVYX.mjs.map} +0 -0
- /package/dist/sdk/{chunk-I7J2BNOK.mjs.map → chunk-XDIBL7QB.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-XE2FY37D.mjs.map → config-D6WF2U4B.mjs.map} +0 -0
- /package/dist/sdk/{config-CWHZO5AL.mjs.map → failure-condition-evaluator-N3VNLWZD.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-QSXBPYQZ.mjs.map → github-frontend-ATORHHF6.mjs.map} +0 -0
- /package/dist/sdk/{host-PRANMDPG.mjs.map → host-OBXKDFT7.mjs.map} +0 -0
- /package/dist/sdk/{host-Q4N357JE.mjs.map → host-QFABFVSJ.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-MEX6VNYT.mjs.map → routing-TGJD66Q5.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-NBRX4N23.mjs.map → schedule-tool-D5TSTGP2.mjs.map} +0 -0
- /package/dist/sdk/{routing-7CQ7QWYE.mjs.map → schedule-tool-SPUM47DS.mjs.map} +0 -0
- /package/dist/sdk/{routing-N2XJVSCQ.mjs.map → schedule-tool-handler-CT5DUQ32.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-DCODWSDM.mjs.map → schedule-tool-handler-DKHHPZAG.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-FYV3JUF7.mjs.map → trace-helpers-J5CJ4PUN.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-VUAATWZX.mjs.map → workflow-check-provider-JORTTXVH.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-A5PN6FU3.mjs.map → workflow-check-provider-T6WFK4RB.mjs.map} +0 -0
package/dist/sdk/sdk.js
CHANGED
|
@@ -646,7 +646,7 @@ var require_package = __commonJS({
|
|
|
646
646
|
"package.json"(exports2, module2) {
|
|
647
647
|
module2.exports = {
|
|
648
648
|
name: "@probelabs/visor",
|
|
649
|
-
version: "0.1.
|
|
649
|
+
version: "0.1.42",
|
|
650
650
|
main: "dist/index.js",
|
|
651
651
|
bin: {
|
|
652
652
|
visor: "./dist/index.js"
|
|
@@ -760,7 +760,7 @@ var require_package = __commonJS({
|
|
|
760
760
|
"@opentelemetry/sdk-node": "^0.203.0",
|
|
761
761
|
"@opentelemetry/sdk-trace-base": "^1.30.1",
|
|
762
762
|
"@opentelemetry/semantic-conventions": "^1.30.1",
|
|
763
|
-
"@probelabs/probe": "^0.6.0-
|
|
763
|
+
"@probelabs/probe": "^0.6.0-rc278",
|
|
764
764
|
"@types/commander": "^2.12.0",
|
|
765
765
|
"@types/uuid": "^10.0.0",
|
|
766
766
|
acorn: "^8.16.0",
|
|
@@ -864,11 +864,11 @@ function getTracer() {
|
|
|
864
864
|
}
|
|
865
865
|
async function withActiveSpan(name, attrs, fn) {
|
|
866
866
|
const tracer = getTracer();
|
|
867
|
-
return await new Promise((
|
|
867
|
+
return await new Promise((resolve19, reject) => {
|
|
868
868
|
const callback = async (span) => {
|
|
869
869
|
try {
|
|
870
870
|
const res = await fn(span);
|
|
871
|
-
|
|
871
|
+
resolve19(res);
|
|
872
872
|
} catch (err) {
|
|
873
873
|
try {
|
|
874
874
|
if (err instanceof Error) span.recordException(err);
|
|
@@ -945,19 +945,19 @@ function __getOrCreateNdjsonPath() {
|
|
|
945
945
|
try {
|
|
946
946
|
if (process.env.VISOR_TELEMETRY_SINK && process.env.VISOR_TELEMETRY_SINK !== "file")
|
|
947
947
|
return null;
|
|
948
|
-
const
|
|
949
|
-
const
|
|
948
|
+
const path31 = require("path");
|
|
949
|
+
const fs27 = require("fs");
|
|
950
950
|
if (process.env.VISOR_FALLBACK_TRACE_FILE) {
|
|
951
951
|
__ndjsonPath = process.env.VISOR_FALLBACK_TRACE_FILE;
|
|
952
|
-
const dir =
|
|
953
|
-
if (!
|
|
952
|
+
const dir = path31.dirname(__ndjsonPath);
|
|
953
|
+
if (!fs27.existsSync(dir)) fs27.mkdirSync(dir, { recursive: true });
|
|
954
954
|
return __ndjsonPath;
|
|
955
955
|
}
|
|
956
|
-
const outDir = process.env.VISOR_TRACE_DIR ||
|
|
957
|
-
if (!
|
|
956
|
+
const outDir = process.env.VISOR_TRACE_DIR || path31.join(process.cwd(), "output", "traces");
|
|
957
|
+
if (!fs27.existsSync(outDir)) fs27.mkdirSync(outDir, { recursive: true });
|
|
958
958
|
if (!__ndjsonPath) {
|
|
959
959
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
960
|
-
__ndjsonPath =
|
|
960
|
+
__ndjsonPath = path31.join(outDir, `${ts}.ndjson`);
|
|
961
961
|
}
|
|
962
962
|
return __ndjsonPath;
|
|
963
963
|
} catch {
|
|
@@ -966,11 +966,11 @@ function __getOrCreateNdjsonPath() {
|
|
|
966
966
|
}
|
|
967
967
|
function _appendRunMarker() {
|
|
968
968
|
try {
|
|
969
|
-
const
|
|
969
|
+
const fs27 = require("fs");
|
|
970
970
|
const p = __getOrCreateNdjsonPath();
|
|
971
971
|
if (!p) return;
|
|
972
972
|
const line = { name: "visor.run", attributes: { started: true } };
|
|
973
|
-
|
|
973
|
+
fs27.appendFileSync(p, JSON.stringify(line) + "\n", "utf8");
|
|
974
974
|
} catch {
|
|
975
975
|
}
|
|
976
976
|
}
|
|
@@ -3193,7 +3193,7 @@ var init_failure_condition_evaluator = __esm({
|
|
|
3193
3193
|
*/
|
|
3194
3194
|
evaluateExpression(condition, context2) {
|
|
3195
3195
|
try {
|
|
3196
|
-
const
|
|
3196
|
+
const normalize8 = (expr) => {
|
|
3197
3197
|
const trimmed = expr.trim();
|
|
3198
3198
|
if (!/[\n;]/.test(trimmed)) return trimmed;
|
|
3199
3199
|
const parts = trimmed.split(/[\n;]+/).map((s) => s.trim()).filter((s) => s.length > 0 && !s.startsWith("//"));
|
|
@@ -3351,7 +3351,7 @@ var init_failure_condition_evaluator = __esm({
|
|
|
3351
3351
|
try {
|
|
3352
3352
|
exec2 = this.sandbox.compile(`return (${raw});`);
|
|
3353
3353
|
} catch {
|
|
3354
|
-
const normalizedExpr =
|
|
3354
|
+
const normalizedExpr = normalize8(condition);
|
|
3355
3355
|
exec2 = this.sandbox.compile(`return (${normalizedExpr});`);
|
|
3356
3356
|
}
|
|
3357
3357
|
const result = exec2(scope).run();
|
|
@@ -3734,9 +3734,9 @@ function configureLiquidWithExtensions(liquid) {
|
|
|
3734
3734
|
});
|
|
3735
3735
|
liquid.registerFilter("get", (obj, pathExpr) => {
|
|
3736
3736
|
if (obj == null) return void 0;
|
|
3737
|
-
const
|
|
3738
|
-
if (!
|
|
3739
|
-
const parts =
|
|
3737
|
+
const path31 = typeof pathExpr === "string" ? pathExpr : String(pathExpr || "");
|
|
3738
|
+
if (!path31) return obj;
|
|
3739
|
+
const parts = path31.split(".");
|
|
3740
3740
|
let cur = obj;
|
|
3741
3741
|
for (const p of parts) {
|
|
3742
3742
|
if (cur == null) return void 0;
|
|
@@ -3855,9 +3855,9 @@ function configureLiquidWithExtensions(liquid) {
|
|
|
3855
3855
|
}
|
|
3856
3856
|
}
|
|
3857
3857
|
const defaultRole = typeof rolesCfg.default === "string" && rolesCfg.default.trim() ? rolesCfg.default.trim() : void 0;
|
|
3858
|
-
const getNested = (obj,
|
|
3859
|
-
if (!obj || !
|
|
3860
|
-
const parts =
|
|
3858
|
+
const getNested = (obj, path31) => {
|
|
3859
|
+
if (!obj || !path31) return void 0;
|
|
3860
|
+
const parts = path31.split(".");
|
|
3861
3861
|
let cur = obj;
|
|
3862
3862
|
for (const p of parts) {
|
|
3863
3863
|
if (cur == null) return void 0;
|
|
@@ -6409,8 +6409,8 @@ var init_dependency_gating = __esm({
|
|
|
6409
6409
|
async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
|
|
6410
6410
|
try {
|
|
6411
6411
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
6412
|
-
const
|
|
6413
|
-
const
|
|
6412
|
+
const fs27 = await import("fs/promises");
|
|
6413
|
+
const path31 = await import("path");
|
|
6414
6414
|
const schemaRaw = checkConfig.schema || "plain";
|
|
6415
6415
|
const schema = typeof schemaRaw === "string" ? schemaRaw : "code-review";
|
|
6416
6416
|
let templateContent;
|
|
@@ -6418,24 +6418,24 @@ async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
|
|
|
6418
6418
|
templateContent = String(checkConfig.template.content);
|
|
6419
6419
|
} else if (checkConfig.template && checkConfig.template.file) {
|
|
6420
6420
|
const file = String(checkConfig.template.file);
|
|
6421
|
-
const resolved =
|
|
6422
|
-
templateContent = await
|
|
6421
|
+
const resolved = path31.resolve(process.cwd(), file);
|
|
6422
|
+
templateContent = await fs27.readFile(resolved, "utf-8");
|
|
6423
6423
|
} else if (schema && schema !== "plain") {
|
|
6424
6424
|
const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
|
|
6425
6425
|
if (sanitized) {
|
|
6426
6426
|
const candidatePaths = [
|
|
6427
|
-
|
|
6427
|
+
path31.join(__dirname, "output", sanitized, "template.liquid"),
|
|
6428
6428
|
// bundled: dist/output/
|
|
6429
|
-
|
|
6429
|
+
path31.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
6430
6430
|
// source: output/
|
|
6431
|
-
|
|
6431
|
+
path31.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
6432
6432
|
// fallback: cwd/output/
|
|
6433
|
-
|
|
6433
|
+
path31.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
|
|
6434
6434
|
// fallback: cwd/dist/output/
|
|
6435
6435
|
];
|
|
6436
6436
|
for (const p of candidatePaths) {
|
|
6437
6437
|
try {
|
|
6438
|
-
templateContent = await
|
|
6438
|
+
templateContent = await fs27.readFile(p, "utf-8");
|
|
6439
6439
|
if (templateContent) break;
|
|
6440
6440
|
} catch {
|
|
6441
6441
|
}
|
|
@@ -6840,7 +6840,7 @@ async function processDiffWithOutline(diffContent) {
|
|
|
6840
6840
|
}
|
|
6841
6841
|
try {
|
|
6842
6842
|
const originalProbePath = process.env.PROBE_PATH;
|
|
6843
|
-
const
|
|
6843
|
+
const fs27 = require("fs");
|
|
6844
6844
|
const possiblePaths = [
|
|
6845
6845
|
// Relative to current working directory (most common in production)
|
|
6846
6846
|
path6.join(process.cwd(), "node_modules/@probelabs/probe/bin/probe-binary"),
|
|
@@ -6851,7 +6851,7 @@ async function processDiffWithOutline(diffContent) {
|
|
|
6851
6851
|
];
|
|
6852
6852
|
let probeBinaryPath;
|
|
6853
6853
|
for (const candidatePath of possiblePaths) {
|
|
6854
|
-
if (
|
|
6854
|
+
if (fs27.existsSync(candidatePath)) {
|
|
6855
6855
|
probeBinaryPath = candidatePath;
|
|
6856
6856
|
break;
|
|
6857
6857
|
}
|
|
@@ -6958,7 +6958,7 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
6958
6958
|
if (chromiumPath) {
|
|
6959
6959
|
env.PUPPETEER_EXECUTABLE_PATH = chromiumPath;
|
|
6960
6960
|
}
|
|
6961
|
-
const result = await new Promise((
|
|
6961
|
+
const result = await new Promise((resolve19) => {
|
|
6962
6962
|
const proc = (0, import_child_process.spawn)(
|
|
6963
6963
|
"npx",
|
|
6964
6964
|
[
|
|
@@ -6988,13 +6988,13 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
6988
6988
|
});
|
|
6989
6989
|
proc.on("close", (code) => {
|
|
6990
6990
|
if (code === 0) {
|
|
6991
|
-
|
|
6991
|
+
resolve19({ success: true });
|
|
6992
6992
|
} else {
|
|
6993
|
-
|
|
6993
|
+
resolve19({ success: false, error: stderr || `Exit code ${code}` });
|
|
6994
6994
|
}
|
|
6995
6995
|
});
|
|
6996
6996
|
proc.on("error", (err) => {
|
|
6997
|
-
|
|
6997
|
+
resolve19({ success: false, error: err.message });
|
|
6998
6998
|
});
|
|
6999
6999
|
});
|
|
7000
7000
|
if (!result.success) {
|
|
@@ -8156,8 +8156,8 @@ ${schemaString}`);
|
|
|
8156
8156
|
}
|
|
8157
8157
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8158
8158
|
try {
|
|
8159
|
-
const
|
|
8160
|
-
const
|
|
8159
|
+
const fs27 = require("fs");
|
|
8160
|
+
const path31 = require("path");
|
|
8161
8161
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8162
8162
|
const provider = this.config.provider || "auto";
|
|
8163
8163
|
const model = this.config.model || "default";
|
|
@@ -8271,20 +8271,20 @@ ${"=".repeat(60)}
|
|
|
8271
8271
|
`;
|
|
8272
8272
|
readableVersion += `${"=".repeat(60)}
|
|
8273
8273
|
`;
|
|
8274
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8275
|
-
if (!
|
|
8276
|
-
|
|
8274
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path31.join(process.cwd(), "debug-artifacts");
|
|
8275
|
+
if (!fs27.existsSync(debugArtifactsDir)) {
|
|
8276
|
+
fs27.mkdirSync(debugArtifactsDir, { recursive: true });
|
|
8277
8277
|
}
|
|
8278
|
-
const debugFile =
|
|
8278
|
+
const debugFile = path31.join(
|
|
8279
8279
|
debugArtifactsDir,
|
|
8280
8280
|
`prompt-${_checkName || "unknown"}-${timestamp}.json`
|
|
8281
8281
|
);
|
|
8282
|
-
|
|
8283
|
-
const readableFile =
|
|
8282
|
+
fs27.writeFileSync(debugFile, debugJson, "utf-8");
|
|
8283
|
+
const readableFile = path31.join(
|
|
8284
8284
|
debugArtifactsDir,
|
|
8285
8285
|
`prompt-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8286
8286
|
);
|
|
8287
|
-
|
|
8287
|
+
fs27.writeFileSync(readableFile, readableVersion, "utf-8");
|
|
8288
8288
|
log(`
|
|
8289
8289
|
\u{1F4BE} Full debug info saved to:`);
|
|
8290
8290
|
log(` JSON: ${debugFile}`);
|
|
@@ -8317,8 +8317,8 @@ ${"=".repeat(60)}
|
|
|
8317
8317
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8318
8318
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8319
8319
|
try {
|
|
8320
|
-
const
|
|
8321
|
-
const
|
|
8320
|
+
const fs27 = require("fs");
|
|
8321
|
+
const path31 = require("path");
|
|
8322
8322
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8323
8323
|
const agentAny2 = agent;
|
|
8324
8324
|
let fullHistory = [];
|
|
@@ -8329,8 +8329,8 @@ ${"=".repeat(60)}
|
|
|
8329
8329
|
} else if (agentAny2._messages) {
|
|
8330
8330
|
fullHistory = agentAny2._messages;
|
|
8331
8331
|
}
|
|
8332
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8333
|
-
const sessionBase =
|
|
8332
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path31.join(process.cwd(), "debug-artifacts");
|
|
8333
|
+
const sessionBase = path31.join(
|
|
8334
8334
|
debugArtifactsDir,
|
|
8335
8335
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
8336
8336
|
);
|
|
@@ -8342,7 +8342,7 @@ ${"=".repeat(60)}
|
|
|
8342
8342
|
schema: effectiveSchema,
|
|
8343
8343
|
totalMessages: fullHistory.length
|
|
8344
8344
|
};
|
|
8345
|
-
|
|
8345
|
+
fs27.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
8346
8346
|
let readable = `=============================================================
|
|
8347
8347
|
`;
|
|
8348
8348
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -8369,7 +8369,7 @@ ${"=".repeat(60)}
|
|
|
8369
8369
|
`;
|
|
8370
8370
|
readable += content + "\n";
|
|
8371
8371
|
});
|
|
8372
|
-
|
|
8372
|
+
fs27.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
8373
8373
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
8374
8374
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
8375
8375
|
} catch (error) {
|
|
@@ -8378,11 +8378,11 @@ ${"=".repeat(60)}
|
|
|
8378
8378
|
}
|
|
8379
8379
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8380
8380
|
try {
|
|
8381
|
-
const
|
|
8382
|
-
const
|
|
8381
|
+
const fs27 = require("fs");
|
|
8382
|
+
const path31 = require("path");
|
|
8383
8383
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8384
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8385
|
-
const responseFile =
|
|
8384
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path31.join(process.cwd(), "debug-artifacts");
|
|
8385
|
+
const responseFile = path31.join(
|
|
8386
8386
|
debugArtifactsDir,
|
|
8387
8387
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8388
8388
|
);
|
|
@@ -8415,7 +8415,7 @@ ${"=".repeat(60)}
|
|
|
8415
8415
|
`;
|
|
8416
8416
|
responseContent += `${"=".repeat(60)}
|
|
8417
8417
|
`;
|
|
8418
|
-
|
|
8418
|
+
fs27.writeFileSync(responseFile, responseContent, "utf-8");
|
|
8419
8419
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
8420
8420
|
} catch (error) {
|
|
8421
8421
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -8431,9 +8431,9 @@ ${"=".repeat(60)}
|
|
|
8431
8431
|
await agentAny._telemetryConfig.shutdown();
|
|
8432
8432
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${agentAny._traceFilePath}`);
|
|
8433
8433
|
if (process.env.GITHUB_ACTIONS) {
|
|
8434
|
-
const
|
|
8435
|
-
if (
|
|
8436
|
-
const stats =
|
|
8434
|
+
const fs27 = require("fs");
|
|
8435
|
+
if (fs27.existsSync(agentAny._traceFilePath)) {
|
|
8436
|
+
const stats = fs27.statSync(agentAny._traceFilePath);
|
|
8437
8437
|
console.log(
|
|
8438
8438
|
`::notice title=AI Trace Saved::${agentAny._traceFilePath} (${stats.size} bytes)`
|
|
8439
8439
|
);
|
|
@@ -8568,6 +8568,12 @@ ${"=".repeat(60)}
|
|
|
8568
8568
|
if (this.config.bashConfig !== void 0) {
|
|
8569
8569
|
options.bashConfig = this.config.bashConfig;
|
|
8570
8570
|
}
|
|
8571
|
+
if (this.config.search_delegate_provider) {
|
|
8572
|
+
options.searchDelegateProvider = this.config.search_delegate_provider;
|
|
8573
|
+
}
|
|
8574
|
+
if (this.config.search_delegate_model) {
|
|
8575
|
+
options.searchDelegateModel = this.config.search_delegate_model;
|
|
8576
|
+
}
|
|
8571
8577
|
if (this.config.completionPrompt !== void 0) {
|
|
8572
8578
|
options.completionPrompt = this.config.completionPrompt;
|
|
8573
8579
|
}
|
|
@@ -8640,9 +8646,9 @@ ${schemaString}`);
|
|
|
8640
8646
|
const model = this.config.model || "default";
|
|
8641
8647
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8642
8648
|
try {
|
|
8643
|
-
const
|
|
8644
|
-
const
|
|
8645
|
-
const
|
|
8649
|
+
const fs27 = require("fs");
|
|
8650
|
+
const path31 = require("path");
|
|
8651
|
+
const os3 = require("os");
|
|
8646
8652
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8647
8653
|
const debugData = {
|
|
8648
8654
|
timestamp,
|
|
@@ -8714,19 +8720,19 @@ ${"=".repeat(60)}
|
|
|
8714
8720
|
`;
|
|
8715
8721
|
readableVersion += `${"=".repeat(60)}
|
|
8716
8722
|
`;
|
|
8717
|
-
const tempDir =
|
|
8718
|
-
const promptFile =
|
|
8719
|
-
|
|
8723
|
+
const tempDir = os3.tmpdir();
|
|
8724
|
+
const promptFile = path31.join(tempDir, `visor-prompt-${timestamp}.txt`);
|
|
8725
|
+
fs27.writeFileSync(promptFile, prompt, "utf-8");
|
|
8720
8726
|
log(`
|
|
8721
8727
|
\u{1F4BE} Prompt saved to: ${promptFile}`);
|
|
8722
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8728
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path31.join(process.cwd(), "debug-artifacts");
|
|
8723
8729
|
try {
|
|
8724
|
-
const base =
|
|
8730
|
+
const base = path31.join(
|
|
8725
8731
|
debugArtifactsDir,
|
|
8726
8732
|
`prompt-${_checkName || "unknown"}-${timestamp}`
|
|
8727
8733
|
);
|
|
8728
|
-
|
|
8729
|
-
|
|
8734
|
+
fs27.writeFileSync(base + ".json", debugJson, "utf-8");
|
|
8735
|
+
fs27.writeFileSync(base + ".summary.txt", readableVersion, "utf-8");
|
|
8730
8736
|
log(`
|
|
8731
8737
|
\u{1F4BE} Full debug info saved to directory: ${debugArtifactsDir}`);
|
|
8732
8738
|
} catch {
|
|
@@ -8771,8 +8777,8 @@ $ ${cliCommand}
|
|
|
8771
8777
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8772
8778
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8773
8779
|
try {
|
|
8774
|
-
const
|
|
8775
|
-
const
|
|
8780
|
+
const fs27 = require("fs");
|
|
8781
|
+
const path31 = require("path");
|
|
8776
8782
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8777
8783
|
const agentAny = agent;
|
|
8778
8784
|
let fullHistory = [];
|
|
@@ -8783,8 +8789,8 @@ $ ${cliCommand}
|
|
|
8783
8789
|
} else if (agentAny._messages) {
|
|
8784
8790
|
fullHistory = agentAny._messages;
|
|
8785
8791
|
}
|
|
8786
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8787
|
-
const sessionBase =
|
|
8792
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path31.join(process.cwd(), "debug-artifacts");
|
|
8793
|
+
const sessionBase = path31.join(
|
|
8788
8794
|
debugArtifactsDir,
|
|
8789
8795
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
8790
8796
|
);
|
|
@@ -8796,7 +8802,7 @@ $ ${cliCommand}
|
|
|
8796
8802
|
schema: effectiveSchema,
|
|
8797
8803
|
totalMessages: fullHistory.length
|
|
8798
8804
|
};
|
|
8799
|
-
|
|
8805
|
+
fs27.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
8800
8806
|
let readable = `=============================================================
|
|
8801
8807
|
`;
|
|
8802
8808
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -8823,7 +8829,7 @@ ${"=".repeat(60)}
|
|
|
8823
8829
|
`;
|
|
8824
8830
|
readable += content + "\n";
|
|
8825
8831
|
});
|
|
8826
|
-
|
|
8832
|
+
fs27.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
8827
8833
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
8828
8834
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
8829
8835
|
} catch (error) {
|
|
@@ -8832,11 +8838,11 @@ ${"=".repeat(60)}
|
|
|
8832
8838
|
}
|
|
8833
8839
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8834
8840
|
try {
|
|
8835
|
-
const
|
|
8836
|
-
const
|
|
8841
|
+
const fs27 = require("fs");
|
|
8842
|
+
const path31 = require("path");
|
|
8837
8843
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8838
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8839
|
-
const responseFile =
|
|
8844
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path31.join(process.cwd(), "debug-artifacts");
|
|
8845
|
+
const responseFile = path31.join(
|
|
8840
8846
|
debugArtifactsDir,
|
|
8841
8847
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8842
8848
|
);
|
|
@@ -8869,7 +8875,7 @@ ${"=".repeat(60)}
|
|
|
8869
8875
|
`;
|
|
8870
8876
|
responseContent += `${"=".repeat(60)}
|
|
8871
8877
|
`;
|
|
8872
|
-
|
|
8878
|
+
fs27.writeFileSync(responseFile, responseContent, "utf-8");
|
|
8873
8879
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
8874
8880
|
} catch (error) {
|
|
8875
8881
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -8887,9 +8893,9 @@ ${"=".repeat(60)}
|
|
|
8887
8893
|
await telemetry.shutdown();
|
|
8888
8894
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${traceFilePath}`);
|
|
8889
8895
|
if (process.env.GITHUB_ACTIONS) {
|
|
8890
|
-
const
|
|
8891
|
-
if (
|
|
8892
|
-
const stats =
|
|
8896
|
+
const fs27 = require("fs");
|
|
8897
|
+
if (fs27.existsSync(traceFilePath)) {
|
|
8898
|
+
const stats = fs27.statSync(traceFilePath);
|
|
8893
8899
|
console.log(
|
|
8894
8900
|
`::notice title=AI Trace Saved::OpenTelemetry trace file size: ${stats.size} bytes`
|
|
8895
8901
|
);
|
|
@@ -8927,8 +8933,8 @@ ${"=".repeat(60)}
|
|
|
8927
8933
|
* Load schema content from schema files or inline definitions
|
|
8928
8934
|
*/
|
|
8929
8935
|
async loadSchemaContent(schema) {
|
|
8930
|
-
const
|
|
8931
|
-
const
|
|
8936
|
+
const fs27 = require("fs").promises;
|
|
8937
|
+
const path31 = require("path");
|
|
8932
8938
|
if (typeof schema === "object" && schema !== null) {
|
|
8933
8939
|
log("\u{1F4CB} Using inline schema object from configuration");
|
|
8934
8940
|
return JSON.stringify(schema);
|
|
@@ -8941,14 +8947,14 @@ ${"=".repeat(60)}
|
|
|
8941
8947
|
}
|
|
8942
8948
|
} catch {
|
|
8943
8949
|
}
|
|
8944
|
-
if ((schema.startsWith("./") || schema.includes(".json")) && !
|
|
8950
|
+
if ((schema.startsWith("./") || schema.includes(".json")) && !path31.isAbsolute(schema)) {
|
|
8945
8951
|
if (schema.includes("..") || schema.includes("\0")) {
|
|
8946
8952
|
throw new Error("Invalid schema path: path traversal not allowed");
|
|
8947
8953
|
}
|
|
8948
8954
|
try {
|
|
8949
|
-
const schemaPath =
|
|
8955
|
+
const schemaPath = path31.resolve(process.cwd(), schema);
|
|
8950
8956
|
log(`\u{1F4CB} Loading custom schema from file: ${schemaPath}`);
|
|
8951
|
-
const schemaContent = await
|
|
8957
|
+
const schemaContent = await fs27.readFile(schemaPath, "utf-8");
|
|
8952
8958
|
return schemaContent.trim();
|
|
8953
8959
|
} catch (error) {
|
|
8954
8960
|
throw new Error(
|
|
@@ -8962,22 +8968,22 @@ ${"=".repeat(60)}
|
|
|
8962
8968
|
}
|
|
8963
8969
|
const candidatePaths = [
|
|
8964
8970
|
// GitHub Action bundle location
|
|
8965
|
-
|
|
8971
|
+
path31.join(__dirname, "output", sanitizedSchemaName, "schema.json"),
|
|
8966
8972
|
// Historical fallback when src/output was inadvertently bundled as output1/
|
|
8967
|
-
|
|
8973
|
+
path31.join(__dirname, "output1", sanitizedSchemaName, "schema.json"),
|
|
8968
8974
|
// Local dev (repo root)
|
|
8969
|
-
|
|
8975
|
+
path31.join(process.cwd(), "output", sanitizedSchemaName, "schema.json")
|
|
8970
8976
|
];
|
|
8971
8977
|
for (const schemaPath of candidatePaths) {
|
|
8972
8978
|
try {
|
|
8973
|
-
const schemaContent = await
|
|
8979
|
+
const schemaContent = await fs27.readFile(schemaPath, "utf-8");
|
|
8974
8980
|
return schemaContent.trim();
|
|
8975
8981
|
} catch {
|
|
8976
8982
|
}
|
|
8977
8983
|
}
|
|
8978
|
-
const distPath =
|
|
8979
|
-
const distAltPath =
|
|
8980
|
-
const cwdPath =
|
|
8984
|
+
const distPath = path31.join(__dirname, "output", sanitizedSchemaName, "schema.json");
|
|
8985
|
+
const distAltPath = path31.join(__dirname, "output1", sanitizedSchemaName, "schema.json");
|
|
8986
|
+
const cwdPath = path31.join(process.cwd(), "output", sanitizedSchemaName, "schema.json");
|
|
8981
8987
|
throw new Error(
|
|
8982
8988
|
`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.`
|
|
8983
8989
|
);
|
|
@@ -9222,7 +9228,7 @@ ${"=".repeat(60)}
|
|
|
9222
9228
|
* Generate mock response for testing
|
|
9223
9229
|
*/
|
|
9224
9230
|
async generateMockResponse(_prompt, _checkName, _schema) {
|
|
9225
|
-
await new Promise((
|
|
9231
|
+
await new Promise((resolve19) => setTimeout(resolve19, 500));
|
|
9226
9232
|
const name = (_checkName || "").toLowerCase();
|
|
9227
9233
|
if (name.includes("extract-facts")) {
|
|
9228
9234
|
const arr = Array.from({ length: 6 }, (_, i) => ({
|
|
@@ -9583,7 +9589,7 @@ var init_command_executor = __esm({
|
|
|
9583
9589
|
* Execute command with stdin input
|
|
9584
9590
|
*/
|
|
9585
9591
|
executeWithStdin(command, options) {
|
|
9586
|
-
return new Promise((
|
|
9592
|
+
return new Promise((resolve19, reject) => {
|
|
9587
9593
|
const childProcess = (0, import_child_process2.exec)(
|
|
9588
9594
|
command,
|
|
9589
9595
|
{
|
|
@@ -9595,7 +9601,7 @@ var init_command_executor = __esm({
|
|
|
9595
9601
|
if (error && error.killed && (error.code === "ETIMEDOUT" || error.signal === "SIGTERM")) {
|
|
9596
9602
|
reject(new Error(`Command timed out after ${options.timeout || 3e4}ms`));
|
|
9597
9603
|
} else {
|
|
9598
|
-
|
|
9604
|
+
resolve19({
|
|
9599
9605
|
stdout: stdout || "",
|
|
9600
9606
|
stderr: stderr || "",
|
|
9601
9607
|
exitCode: error ? error.code || 1 : 0
|
|
@@ -13158,7 +13164,7 @@ var init_config_schema = __esm({
|
|
|
13158
13164
|
description: "Arguments/inputs for the workflow"
|
|
13159
13165
|
},
|
|
13160
13166
|
overrides: {
|
|
13161
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-
|
|
13167
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-13766-28360-src_types_config.ts-0-55512%3E%3E",
|
|
13162
13168
|
description: "Override specific step configurations in the workflow"
|
|
13163
13169
|
},
|
|
13164
13170
|
output_mapping: {
|
|
@@ -13174,7 +13180,7 @@ var init_config_schema = __esm({
|
|
|
13174
13180
|
description: "Config file path - alternative to workflow ID (loads a Visor config file as workflow)"
|
|
13175
13181
|
},
|
|
13176
13182
|
workflow_overrides: {
|
|
13177
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-
|
|
13183
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-13766-28360-src_types_config.ts-0-55512%3E%3E",
|
|
13178
13184
|
description: "Alias for overrides - workflow step overrides (backward compatibility)"
|
|
13179
13185
|
},
|
|
13180
13186
|
ref: {
|
|
@@ -13452,6 +13458,14 @@ var init_config_schema = __esm({
|
|
|
13452
13458
|
type: "boolean",
|
|
13453
13459
|
description: "Enable bash command execution (shorthand for bashConfig.enabled)"
|
|
13454
13460
|
},
|
|
13461
|
+
search_delegate_provider: {
|
|
13462
|
+
type: "string",
|
|
13463
|
+
description: "Override provider for search delegate sub-agents (e.g., 'google' for cheaper search)"
|
|
13464
|
+
},
|
|
13465
|
+
search_delegate_model: {
|
|
13466
|
+
type: "string",
|
|
13467
|
+
description: "Override model for search delegate sub-agents (e.g., 'gemini-2.0-flash')"
|
|
13468
|
+
},
|
|
13455
13469
|
bashConfig: {
|
|
13456
13470
|
$ref: "#/definitions/BashConfig",
|
|
13457
13471
|
description: "Advanced bash command execution configuration"
|
|
@@ -13863,7 +13877,7 @@ var init_config_schema = __esm({
|
|
|
13863
13877
|
description: "Custom output name (defaults to workflow name)"
|
|
13864
13878
|
},
|
|
13865
13879
|
overrides: {
|
|
13866
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-
|
|
13880
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-13766-28360-src_types_config.ts-0-55512%3E%3E",
|
|
13867
13881
|
description: "Step overrides"
|
|
13868
13882
|
},
|
|
13869
13883
|
output_mapping: {
|
|
@@ -13878,13 +13892,13 @@ var init_config_schema = __esm({
|
|
|
13878
13892
|
"^x-": {}
|
|
13879
13893
|
}
|
|
13880
13894
|
},
|
|
13881
|
-
"Record<string,Partial<interface-src_types_config.ts-
|
|
13895
|
+
"Record<string,Partial<interface-src_types_config.ts-13766-28360-src_types_config.ts-0-55512>>": {
|
|
13882
13896
|
type: "object",
|
|
13883
13897
|
additionalProperties: {
|
|
13884
|
-
$ref: "#/definitions/Partial%3Cinterface-src_types_config.ts-
|
|
13898
|
+
$ref: "#/definitions/Partial%3Cinterface-src_types_config.ts-13766-28360-src_types_config.ts-0-55512%3E"
|
|
13885
13899
|
}
|
|
13886
13900
|
},
|
|
13887
|
-
"Partial<interface-src_types_config.ts-
|
|
13901
|
+
"Partial<interface-src_types_config.ts-13766-28360-src_types_config.ts-0-55512>": {
|
|
13888
13902
|
type: "object",
|
|
13889
13903
|
additionalProperties: false
|
|
13890
13904
|
},
|
|
@@ -17690,17 +17704,17 @@ var init_workflow_check_provider = __esm({
|
|
|
17690
17704
|
* so it can be executed by the state machine as a nested workflow.
|
|
17691
17705
|
*/
|
|
17692
17706
|
async loadWorkflowFromConfigPath(sourcePath, baseDir) {
|
|
17693
|
-
const
|
|
17694
|
-
const
|
|
17707
|
+
const path31 = require("path");
|
|
17708
|
+
const fs27 = require("fs");
|
|
17695
17709
|
const yaml5 = require("js-yaml");
|
|
17696
|
-
const resolved =
|
|
17697
|
-
if (!
|
|
17710
|
+
const resolved = path31.isAbsolute(sourcePath) ? sourcePath : path31.resolve(baseDir, sourcePath);
|
|
17711
|
+
if (!fs27.existsSync(resolved)) {
|
|
17698
17712
|
throw new Error(`Workflow config not found at: ${resolved}`);
|
|
17699
17713
|
}
|
|
17700
|
-
const rawContent =
|
|
17714
|
+
const rawContent = fs27.readFileSync(resolved, "utf8");
|
|
17701
17715
|
const rawData = yaml5.load(rawContent);
|
|
17702
17716
|
if (rawData.imports && Array.isArray(rawData.imports)) {
|
|
17703
|
-
const configDir =
|
|
17717
|
+
const configDir = path31.dirname(resolved);
|
|
17704
17718
|
for (const source of rawData.imports) {
|
|
17705
17719
|
const results = await this.registry.import(source, {
|
|
17706
17720
|
basePath: configDir,
|
|
@@ -17730,8 +17744,8 @@ ${errors}`);
|
|
|
17730
17744
|
if (!steps || Object.keys(steps).length === 0) {
|
|
17731
17745
|
throw new Error(`Config '${resolved}' does not contain any steps to execute as a workflow`);
|
|
17732
17746
|
}
|
|
17733
|
-
const id =
|
|
17734
|
-
const name = loaded.name || `Workflow from ${
|
|
17747
|
+
const id = path31.basename(resolved).replace(/\.(ya?ml)$/i, "");
|
|
17748
|
+
const name = loaded.name || `Workflow from ${path31.basename(resolved)}`;
|
|
17735
17749
|
const workflowDef = {
|
|
17736
17750
|
id,
|
|
17737
17751
|
name,
|
|
@@ -18537,8 +18551,8 @@ async function createStoreBackend(storageConfig, haConfig) {
|
|
|
18537
18551
|
case "mssql": {
|
|
18538
18552
|
try {
|
|
18539
18553
|
const loaderPath = "../../enterprise/loader";
|
|
18540
|
-
const { loadEnterpriseStoreBackend } = await import(loaderPath);
|
|
18541
|
-
return await
|
|
18554
|
+
const { loadEnterpriseStoreBackend: loadEnterpriseStoreBackend2 } = await import(loaderPath);
|
|
18555
|
+
return await loadEnterpriseStoreBackend2(driver, storageConfig, haConfig);
|
|
18542
18556
|
} catch (err) {
|
|
18543
18557
|
const msg = err instanceof Error ? err.message : String(err);
|
|
18544
18558
|
logger.error(`[StoreFactory] Failed to load enterprise ${driver} backend: ${msg}`);
|
|
@@ -21109,7 +21123,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21109
21123
|
* Returns the actual bound port number
|
|
21110
21124
|
*/
|
|
21111
21125
|
async start() {
|
|
21112
|
-
return new Promise((
|
|
21126
|
+
return new Promise((resolve19, reject) => {
|
|
21113
21127
|
try {
|
|
21114
21128
|
this.server = import_http.default.createServer((req, res) => {
|
|
21115
21129
|
this.handleRequest(req, res).catch((error) => {
|
|
@@ -21143,7 +21157,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21143
21157
|
);
|
|
21144
21158
|
}
|
|
21145
21159
|
this.startKeepalive();
|
|
21146
|
-
|
|
21160
|
+
resolve19(this.port);
|
|
21147
21161
|
});
|
|
21148
21162
|
} catch (error) {
|
|
21149
21163
|
reject(error);
|
|
@@ -21206,7 +21220,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21206
21220
|
logger.debug(
|
|
21207
21221
|
`[CustomToolsSSEServer:${this.sessionId}] Grace period before stop: ${waitMs}ms (activeToolCalls=${this.activeToolCalls})`
|
|
21208
21222
|
);
|
|
21209
|
-
await new Promise((
|
|
21223
|
+
await new Promise((resolve19) => setTimeout(resolve19, waitMs));
|
|
21210
21224
|
}
|
|
21211
21225
|
}
|
|
21212
21226
|
if (this.activeToolCalls > 0) {
|
|
@@ -21215,7 +21229,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21215
21229
|
`[CustomToolsSSEServer:${this.sessionId}] Waiting for ${this.activeToolCalls} active tool call(s) before stop`
|
|
21216
21230
|
);
|
|
21217
21231
|
while (this.activeToolCalls > 0 && Date.now() - startedAt < effectiveDrainTimeoutMs) {
|
|
21218
|
-
await new Promise((
|
|
21232
|
+
await new Promise((resolve19) => setTimeout(resolve19, 250));
|
|
21219
21233
|
}
|
|
21220
21234
|
if (this.activeToolCalls > 0) {
|
|
21221
21235
|
logger.warn(
|
|
@@ -21240,21 +21254,21 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21240
21254
|
}
|
|
21241
21255
|
this.connections.clear();
|
|
21242
21256
|
if (this.server) {
|
|
21243
|
-
await new Promise((
|
|
21257
|
+
await new Promise((resolve19, reject) => {
|
|
21244
21258
|
const timeout = setTimeout(() => {
|
|
21245
21259
|
if (this.debug) {
|
|
21246
21260
|
logger.debug(
|
|
21247
21261
|
`[CustomToolsSSEServer:${this.sessionId}] Force closing server after timeout`
|
|
21248
21262
|
);
|
|
21249
21263
|
}
|
|
21250
|
-
this.server?.close(() =>
|
|
21264
|
+
this.server?.close(() => resolve19());
|
|
21251
21265
|
}, 5e3);
|
|
21252
21266
|
this.server.close((error) => {
|
|
21253
21267
|
clearTimeout(timeout);
|
|
21254
21268
|
if (error) {
|
|
21255
21269
|
reject(error);
|
|
21256
21270
|
} else {
|
|
21257
|
-
|
|
21271
|
+
resolve19();
|
|
21258
21272
|
}
|
|
21259
21273
|
});
|
|
21260
21274
|
});
|
|
@@ -21689,7 +21703,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21689
21703
|
logger.warn(
|
|
21690
21704
|
`[CustomToolsSSEServer:${this.sessionId}] Tool ${toolName} failed (attempt ${attempt + 1}/${retryCount + 1}): ${errorMsg}. Retrying in ${delay}ms`
|
|
21691
21705
|
);
|
|
21692
|
-
await new Promise((
|
|
21706
|
+
await new Promise((resolve19) => setTimeout(resolve19, delay));
|
|
21693
21707
|
attempt++;
|
|
21694
21708
|
}
|
|
21695
21709
|
}
|
|
@@ -22002,9 +22016,9 @@ var init_ai_check_provider = __esm({
|
|
|
22002
22016
|
} else {
|
|
22003
22017
|
resolvedPath = import_path7.default.resolve(process.cwd(), str);
|
|
22004
22018
|
}
|
|
22005
|
-
const
|
|
22019
|
+
const fs27 = require("fs").promises;
|
|
22006
22020
|
try {
|
|
22007
|
-
const stat2 = await
|
|
22021
|
+
const stat2 = await fs27.stat(resolvedPath);
|
|
22008
22022
|
return stat2.isFile();
|
|
22009
22023
|
} catch {
|
|
22010
22024
|
return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);
|
|
@@ -22436,6 +22450,12 @@ ${preview}`);
|
|
|
22436
22450
|
if (aiAny2.bashConfig !== void 0) {
|
|
22437
22451
|
aiConfig.bashConfig = aiAny2.bashConfig;
|
|
22438
22452
|
}
|
|
22453
|
+
if (aiAny2.search_delegate_provider !== void 0) {
|
|
22454
|
+
aiConfig.search_delegate_provider = aiAny2.search_delegate_provider;
|
|
22455
|
+
}
|
|
22456
|
+
if (aiAny2.search_delegate_model !== void 0) {
|
|
22457
|
+
aiConfig.search_delegate_model = aiAny2.search_delegate_model;
|
|
22458
|
+
}
|
|
22439
22459
|
if (aiAny2.completion_prompt !== void 0) {
|
|
22440
22460
|
aiConfig.completionPrompt = aiAny2.completion_prompt;
|
|
22441
22461
|
}
|
|
@@ -23565,6 +23585,8 @@ ${processedPrompt}` : processedPrompt;
|
|
|
23565
23585
|
"ai.disableTools",
|
|
23566
23586
|
"ai.allowBash",
|
|
23567
23587
|
"ai.bashConfig",
|
|
23588
|
+
"ai.search_delegate_provider",
|
|
23589
|
+
"ai.search_delegate_model",
|
|
23568
23590
|
"ai_model",
|
|
23569
23591
|
"ai_provider",
|
|
23570
23592
|
"ai_mcp_servers",
|
|
@@ -27932,14 +27954,14 @@ var require_util = __commonJS({
|
|
|
27932
27954
|
}
|
|
27933
27955
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
27934
27956
|
let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`;
|
|
27935
|
-
let
|
|
27957
|
+
let path31 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
27936
27958
|
if (origin.endsWith("/")) {
|
|
27937
27959
|
origin = origin.substring(0, origin.length - 1);
|
|
27938
27960
|
}
|
|
27939
|
-
if (
|
|
27940
|
-
|
|
27961
|
+
if (path31 && !path31.startsWith("/")) {
|
|
27962
|
+
path31 = `/${path31}`;
|
|
27941
27963
|
}
|
|
27942
|
-
url = new URL(origin +
|
|
27964
|
+
url = new URL(origin + path31);
|
|
27943
27965
|
}
|
|
27944
27966
|
return url;
|
|
27945
27967
|
}
|
|
@@ -29553,20 +29575,20 @@ var require_parseParams = __commonJS({
|
|
|
29553
29575
|
var require_basename = __commonJS({
|
|
29554
29576
|
"node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) {
|
|
29555
29577
|
"use strict";
|
|
29556
|
-
module2.exports = function basename4(
|
|
29557
|
-
if (typeof
|
|
29578
|
+
module2.exports = function basename4(path31) {
|
|
29579
|
+
if (typeof path31 !== "string") {
|
|
29558
29580
|
return "";
|
|
29559
29581
|
}
|
|
29560
|
-
for (var i =
|
|
29561
|
-
switch (
|
|
29582
|
+
for (var i = path31.length - 1; i >= 0; --i) {
|
|
29583
|
+
switch (path31.charCodeAt(i)) {
|
|
29562
29584
|
case 47:
|
|
29563
29585
|
// '/'
|
|
29564
29586
|
case 92:
|
|
29565
|
-
|
|
29566
|
-
return
|
|
29587
|
+
path31 = path31.slice(i + 1);
|
|
29588
|
+
return path31 === ".." || path31 === "." ? "" : path31;
|
|
29567
29589
|
}
|
|
29568
29590
|
}
|
|
29569
|
-
return
|
|
29591
|
+
return path31 === ".." || path31 === "." ? "" : path31;
|
|
29570
29592
|
};
|
|
29571
29593
|
}
|
|
29572
29594
|
});
|
|
@@ -30570,11 +30592,11 @@ var require_util2 = __commonJS({
|
|
|
30570
30592
|
var assert = require("assert");
|
|
30571
30593
|
var { isUint8Array } = require("util/types");
|
|
30572
30594
|
var supportedHashes = [];
|
|
30573
|
-
var
|
|
30595
|
+
var crypto4;
|
|
30574
30596
|
try {
|
|
30575
|
-
|
|
30597
|
+
crypto4 = require("crypto");
|
|
30576
30598
|
const possibleRelevantHashes = ["sha256", "sha384", "sha512"];
|
|
30577
|
-
supportedHashes =
|
|
30599
|
+
supportedHashes = crypto4.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
|
|
30578
30600
|
} catch {
|
|
30579
30601
|
}
|
|
30580
30602
|
function responseURL(response) {
|
|
@@ -30851,7 +30873,7 @@ var require_util2 = __commonJS({
|
|
|
30851
30873
|
}
|
|
30852
30874
|
}
|
|
30853
30875
|
function bytesMatch(bytes, metadataList) {
|
|
30854
|
-
if (
|
|
30876
|
+
if (crypto4 === void 0) {
|
|
30855
30877
|
return true;
|
|
30856
30878
|
}
|
|
30857
30879
|
const parsedMetadata = parseMetadata(metadataList);
|
|
@@ -30866,7 +30888,7 @@ var require_util2 = __commonJS({
|
|
|
30866
30888
|
for (const item of metadata) {
|
|
30867
30889
|
const algorithm = item.algo;
|
|
30868
30890
|
const expectedValue = item.hash;
|
|
30869
|
-
let actualValue =
|
|
30891
|
+
let actualValue = crypto4.createHash(algorithm).update(bytes).digest("base64");
|
|
30870
30892
|
if (actualValue[actualValue.length - 1] === "=") {
|
|
30871
30893
|
if (actualValue[actualValue.length - 2] === "=") {
|
|
30872
30894
|
actualValue = actualValue.slice(0, -2);
|
|
@@ -30959,8 +30981,8 @@ var require_util2 = __commonJS({
|
|
|
30959
30981
|
function createDeferredPromise() {
|
|
30960
30982
|
let res;
|
|
30961
30983
|
let rej;
|
|
30962
|
-
const promise = new Promise((
|
|
30963
|
-
res =
|
|
30984
|
+
const promise = new Promise((resolve19, reject) => {
|
|
30985
|
+
res = resolve19;
|
|
30964
30986
|
rej = reject;
|
|
30965
30987
|
});
|
|
30966
30988
|
return { promise, resolve: res, reject: rej };
|
|
@@ -32213,8 +32235,8 @@ var require_body = __commonJS({
|
|
|
32213
32235
|
var { parseMIMEType, serializeAMimeType } = require_dataURL();
|
|
32214
32236
|
var random;
|
|
32215
32237
|
try {
|
|
32216
|
-
const
|
|
32217
|
-
random = (max) =>
|
|
32238
|
+
const crypto4 = require("crypto");
|
|
32239
|
+
random = (max) => crypto4.randomInt(0, max);
|
|
32218
32240
|
} catch {
|
|
32219
32241
|
random = (max) => Math.floor(Math.random(max));
|
|
32220
32242
|
}
|
|
@@ -32465,8 +32487,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r
|
|
|
32465
32487
|
});
|
|
32466
32488
|
}
|
|
32467
32489
|
});
|
|
32468
|
-
const busboyResolve = new Promise((
|
|
32469
|
-
busboy.on("finish",
|
|
32490
|
+
const busboyResolve = new Promise((resolve19, reject) => {
|
|
32491
|
+
busboy.on("finish", resolve19);
|
|
32470
32492
|
busboy.on("error", (err) => reject(new TypeError(err)));
|
|
32471
32493
|
});
|
|
32472
32494
|
if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk);
|
|
@@ -32597,7 +32619,7 @@ var require_request = __commonJS({
|
|
|
32597
32619
|
}
|
|
32598
32620
|
var Request = class _Request {
|
|
32599
32621
|
constructor(origin, {
|
|
32600
|
-
path:
|
|
32622
|
+
path: path31,
|
|
32601
32623
|
method,
|
|
32602
32624
|
body,
|
|
32603
32625
|
headers,
|
|
@@ -32611,11 +32633,11 @@ var require_request = __commonJS({
|
|
|
32611
32633
|
throwOnError,
|
|
32612
32634
|
expectContinue
|
|
32613
32635
|
}, handler) {
|
|
32614
|
-
if (typeof
|
|
32636
|
+
if (typeof path31 !== "string") {
|
|
32615
32637
|
throw new InvalidArgumentError("path must be a string");
|
|
32616
|
-
} else if (
|
|
32638
|
+
} else if (path31[0] !== "/" && !(path31.startsWith("http://") || path31.startsWith("https://")) && method !== "CONNECT") {
|
|
32617
32639
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
32618
|
-
} else if (invalidPathRegex.exec(
|
|
32640
|
+
} else if (invalidPathRegex.exec(path31) !== null) {
|
|
32619
32641
|
throw new InvalidArgumentError("invalid request path");
|
|
32620
32642
|
}
|
|
32621
32643
|
if (typeof method !== "string") {
|
|
@@ -32678,7 +32700,7 @@ var require_request = __commonJS({
|
|
|
32678
32700
|
this.completed = false;
|
|
32679
32701
|
this.aborted = false;
|
|
32680
32702
|
this.upgrade = upgrade || null;
|
|
32681
|
-
this.path = query ? util.buildURL(
|
|
32703
|
+
this.path = query ? util.buildURL(path31, query) : path31;
|
|
32682
32704
|
this.origin = origin;
|
|
32683
32705
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
32684
32706
|
this.blocking = blocking == null ? false : blocking;
|
|
@@ -33000,9 +33022,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
33000
33022
|
}
|
|
33001
33023
|
close(callback) {
|
|
33002
33024
|
if (callback === void 0) {
|
|
33003
|
-
return new Promise((
|
|
33025
|
+
return new Promise((resolve19, reject) => {
|
|
33004
33026
|
this.close((err, data) => {
|
|
33005
|
-
return err ? reject(err) :
|
|
33027
|
+
return err ? reject(err) : resolve19(data);
|
|
33006
33028
|
});
|
|
33007
33029
|
});
|
|
33008
33030
|
}
|
|
@@ -33040,12 +33062,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
33040
33062
|
err = null;
|
|
33041
33063
|
}
|
|
33042
33064
|
if (callback === void 0) {
|
|
33043
|
-
return new Promise((
|
|
33065
|
+
return new Promise((resolve19, reject) => {
|
|
33044
33066
|
this.destroy(err, (err2, data) => {
|
|
33045
33067
|
return err2 ? (
|
|
33046
33068
|
/* istanbul ignore next: should never error */
|
|
33047
33069
|
reject(err2)
|
|
33048
|
-
) :
|
|
33070
|
+
) : resolve19(data);
|
|
33049
33071
|
});
|
|
33050
33072
|
});
|
|
33051
33073
|
}
|
|
@@ -33686,9 +33708,9 @@ var require_RedirectHandler = __commonJS({
|
|
|
33686
33708
|
return this.handler.onHeaders(statusCode, headers, resume, statusText);
|
|
33687
33709
|
}
|
|
33688
33710
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
33689
|
-
const
|
|
33711
|
+
const path31 = search ? `${pathname}${search}` : pathname;
|
|
33690
33712
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
33691
|
-
this.opts.path =
|
|
33713
|
+
this.opts.path = path31;
|
|
33692
33714
|
this.opts.origin = origin;
|
|
33693
33715
|
this.opts.maxRedirections = 0;
|
|
33694
33716
|
this.opts.query = null;
|
|
@@ -34107,16 +34129,16 @@ var require_client = __commonJS({
|
|
|
34107
34129
|
return this[kNeedDrain] < 2;
|
|
34108
34130
|
}
|
|
34109
34131
|
async [kClose]() {
|
|
34110
|
-
return new Promise((
|
|
34132
|
+
return new Promise((resolve19) => {
|
|
34111
34133
|
if (!this[kSize]) {
|
|
34112
|
-
|
|
34134
|
+
resolve19(null);
|
|
34113
34135
|
} else {
|
|
34114
|
-
this[kClosedResolve] =
|
|
34136
|
+
this[kClosedResolve] = resolve19;
|
|
34115
34137
|
}
|
|
34116
34138
|
});
|
|
34117
34139
|
}
|
|
34118
34140
|
async [kDestroy](err) {
|
|
34119
|
-
return new Promise((
|
|
34141
|
+
return new Promise((resolve19) => {
|
|
34120
34142
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
34121
34143
|
for (let i = 0; i < requests.length; i++) {
|
|
34122
34144
|
const request = requests[i];
|
|
@@ -34127,7 +34149,7 @@ var require_client = __commonJS({
|
|
|
34127
34149
|
this[kClosedResolve]();
|
|
34128
34150
|
this[kClosedResolve] = null;
|
|
34129
34151
|
}
|
|
34130
|
-
|
|
34152
|
+
resolve19();
|
|
34131
34153
|
};
|
|
34132
34154
|
if (this[kHTTP2Session] != null) {
|
|
34133
34155
|
util.destroy(this[kHTTP2Session], err);
|
|
@@ -34707,7 +34729,7 @@ var require_client = __commonJS({
|
|
|
34707
34729
|
});
|
|
34708
34730
|
}
|
|
34709
34731
|
try {
|
|
34710
|
-
const socket = await new Promise((
|
|
34732
|
+
const socket = await new Promise((resolve19, reject) => {
|
|
34711
34733
|
client[kConnector]({
|
|
34712
34734
|
host,
|
|
34713
34735
|
hostname,
|
|
@@ -34719,7 +34741,7 @@ var require_client = __commonJS({
|
|
|
34719
34741
|
if (err) {
|
|
34720
34742
|
reject(err);
|
|
34721
34743
|
} else {
|
|
34722
|
-
|
|
34744
|
+
resolve19(socket2);
|
|
34723
34745
|
}
|
|
34724
34746
|
});
|
|
34725
34747
|
});
|
|
@@ -34930,7 +34952,7 @@ var require_client = __commonJS({
|
|
|
34930
34952
|
writeH2(client, client[kHTTP2Session], request);
|
|
34931
34953
|
return;
|
|
34932
34954
|
}
|
|
34933
|
-
const { body, method, path:
|
|
34955
|
+
const { body, method, path: path31, host, upgrade, headers, blocking, reset } = request;
|
|
34934
34956
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
34935
34957
|
if (body && typeof body.read === "function") {
|
|
34936
34958
|
body.read(0);
|
|
@@ -34980,7 +35002,7 @@ var require_client = __commonJS({
|
|
|
34980
35002
|
if (blocking) {
|
|
34981
35003
|
socket[kBlocking] = true;
|
|
34982
35004
|
}
|
|
34983
|
-
let header = `${method} ${
|
|
35005
|
+
let header = `${method} ${path31} HTTP/1.1\r
|
|
34984
35006
|
`;
|
|
34985
35007
|
if (typeof host === "string") {
|
|
34986
35008
|
header += `host: ${host}\r
|
|
@@ -35043,7 +35065,7 @@ upgrade: ${upgrade}\r
|
|
|
35043
35065
|
return true;
|
|
35044
35066
|
}
|
|
35045
35067
|
function writeH2(client, session, request) {
|
|
35046
|
-
const { body, method, path:
|
|
35068
|
+
const { body, method, path: path31, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
|
|
35047
35069
|
let headers;
|
|
35048
35070
|
if (typeof reqHeaders === "string") headers = Request[kHTTP2CopyHeaders](reqHeaders.trim());
|
|
35049
35071
|
else headers = reqHeaders;
|
|
@@ -35086,7 +35108,7 @@ upgrade: ${upgrade}\r
|
|
|
35086
35108
|
});
|
|
35087
35109
|
return true;
|
|
35088
35110
|
}
|
|
35089
|
-
headers[HTTP2_HEADER_PATH] =
|
|
35111
|
+
headers[HTTP2_HEADER_PATH] = path31;
|
|
35090
35112
|
headers[HTTP2_HEADER_SCHEME] = "https";
|
|
35091
35113
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
35092
35114
|
if (body && typeof body.read === "function") {
|
|
@@ -35343,12 +35365,12 @@ upgrade: ${upgrade}\r
|
|
|
35343
35365
|
cb();
|
|
35344
35366
|
}
|
|
35345
35367
|
}
|
|
35346
|
-
const waitForDrain = () => new Promise((
|
|
35368
|
+
const waitForDrain = () => new Promise((resolve19, reject) => {
|
|
35347
35369
|
assert(callback === null);
|
|
35348
35370
|
if (socket[kError]) {
|
|
35349
35371
|
reject(socket[kError]);
|
|
35350
35372
|
} else {
|
|
35351
|
-
callback =
|
|
35373
|
+
callback = resolve19;
|
|
35352
35374
|
}
|
|
35353
35375
|
});
|
|
35354
35376
|
if (client[kHTTPConnVersion] === "h2") {
|
|
@@ -35694,8 +35716,8 @@ var require_pool_base = __commonJS({
|
|
|
35694
35716
|
if (this[kQueue].isEmpty()) {
|
|
35695
35717
|
return Promise.all(this[kClients].map((c) => c.close()));
|
|
35696
35718
|
} else {
|
|
35697
|
-
return new Promise((
|
|
35698
|
-
this[kClosedResolve] =
|
|
35719
|
+
return new Promise((resolve19) => {
|
|
35720
|
+
this[kClosedResolve] = resolve19;
|
|
35699
35721
|
});
|
|
35700
35722
|
}
|
|
35701
35723
|
}
|
|
@@ -36273,7 +36295,7 @@ var require_readable = __commonJS({
|
|
|
36273
36295
|
if (this.closed) {
|
|
36274
36296
|
return Promise.resolve(null);
|
|
36275
36297
|
}
|
|
36276
|
-
return new Promise((
|
|
36298
|
+
return new Promise((resolve19, reject) => {
|
|
36277
36299
|
const signalListenerCleanup = signal ? util.addAbortListener(signal, () => {
|
|
36278
36300
|
this.destroy();
|
|
36279
36301
|
}) : noop;
|
|
@@ -36282,7 +36304,7 @@ var require_readable = __commonJS({
|
|
|
36282
36304
|
if (signal && signal.aborted) {
|
|
36283
36305
|
reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" }));
|
|
36284
36306
|
} else {
|
|
36285
|
-
|
|
36307
|
+
resolve19(null);
|
|
36286
36308
|
}
|
|
36287
36309
|
}).on("error", noop).on("data", function(chunk) {
|
|
36288
36310
|
limit -= chunk.length;
|
|
@@ -36304,11 +36326,11 @@ var require_readable = __commonJS({
|
|
|
36304
36326
|
throw new TypeError("unusable");
|
|
36305
36327
|
}
|
|
36306
36328
|
assert(!stream[kConsume]);
|
|
36307
|
-
return new Promise((
|
|
36329
|
+
return new Promise((resolve19, reject) => {
|
|
36308
36330
|
stream[kConsume] = {
|
|
36309
36331
|
type,
|
|
36310
36332
|
stream,
|
|
36311
|
-
resolve:
|
|
36333
|
+
resolve: resolve19,
|
|
36312
36334
|
reject,
|
|
36313
36335
|
length: 0,
|
|
36314
36336
|
body: []
|
|
@@ -36343,12 +36365,12 @@ var require_readable = __commonJS({
|
|
|
36343
36365
|
}
|
|
36344
36366
|
}
|
|
36345
36367
|
function consumeEnd(consume2) {
|
|
36346
|
-
const { type, body, resolve:
|
|
36368
|
+
const { type, body, resolve: resolve19, stream, length } = consume2;
|
|
36347
36369
|
try {
|
|
36348
36370
|
if (type === "text") {
|
|
36349
|
-
|
|
36371
|
+
resolve19(toUSVString(Buffer.concat(body)));
|
|
36350
36372
|
} else if (type === "json") {
|
|
36351
|
-
|
|
36373
|
+
resolve19(JSON.parse(Buffer.concat(body)));
|
|
36352
36374
|
} else if (type === "arrayBuffer") {
|
|
36353
36375
|
const dst = new Uint8Array(length);
|
|
36354
36376
|
let pos = 0;
|
|
@@ -36356,12 +36378,12 @@ var require_readable = __commonJS({
|
|
|
36356
36378
|
dst.set(buf, pos);
|
|
36357
36379
|
pos += buf.byteLength;
|
|
36358
36380
|
}
|
|
36359
|
-
|
|
36381
|
+
resolve19(dst.buffer);
|
|
36360
36382
|
} else if (type === "blob") {
|
|
36361
36383
|
if (!Blob2) {
|
|
36362
36384
|
Blob2 = require("buffer").Blob;
|
|
36363
36385
|
}
|
|
36364
|
-
|
|
36386
|
+
resolve19(new Blob2(body, { type: stream[kContentType] }));
|
|
36365
36387
|
}
|
|
36366
36388
|
consumeFinish(consume2);
|
|
36367
36389
|
} catch (err) {
|
|
@@ -36618,9 +36640,9 @@ var require_api_request = __commonJS({
|
|
|
36618
36640
|
};
|
|
36619
36641
|
function request(opts, callback) {
|
|
36620
36642
|
if (callback === void 0) {
|
|
36621
|
-
return new Promise((
|
|
36643
|
+
return new Promise((resolve19, reject) => {
|
|
36622
36644
|
request.call(this, opts, (err, data) => {
|
|
36623
|
-
return err ? reject(err) :
|
|
36645
|
+
return err ? reject(err) : resolve19(data);
|
|
36624
36646
|
});
|
|
36625
36647
|
});
|
|
36626
36648
|
}
|
|
@@ -36793,9 +36815,9 @@ var require_api_stream = __commonJS({
|
|
|
36793
36815
|
};
|
|
36794
36816
|
function stream(opts, factory, callback) {
|
|
36795
36817
|
if (callback === void 0) {
|
|
36796
|
-
return new Promise((
|
|
36818
|
+
return new Promise((resolve19, reject) => {
|
|
36797
36819
|
stream.call(this, opts, factory, (err, data) => {
|
|
36798
|
-
return err ? reject(err) :
|
|
36820
|
+
return err ? reject(err) : resolve19(data);
|
|
36799
36821
|
});
|
|
36800
36822
|
});
|
|
36801
36823
|
}
|
|
@@ -37076,9 +37098,9 @@ var require_api_upgrade = __commonJS({
|
|
|
37076
37098
|
};
|
|
37077
37099
|
function upgrade(opts, callback) {
|
|
37078
37100
|
if (callback === void 0) {
|
|
37079
|
-
return new Promise((
|
|
37101
|
+
return new Promise((resolve19, reject) => {
|
|
37080
37102
|
upgrade.call(this, opts, (err, data) => {
|
|
37081
|
-
return err ? reject(err) :
|
|
37103
|
+
return err ? reject(err) : resolve19(data);
|
|
37082
37104
|
});
|
|
37083
37105
|
});
|
|
37084
37106
|
}
|
|
@@ -37167,9 +37189,9 @@ var require_api_connect = __commonJS({
|
|
|
37167
37189
|
};
|
|
37168
37190
|
function connect(opts, callback) {
|
|
37169
37191
|
if (callback === void 0) {
|
|
37170
|
-
return new Promise((
|
|
37192
|
+
return new Promise((resolve19, reject) => {
|
|
37171
37193
|
connect.call(this, opts, (err, data) => {
|
|
37172
|
-
return err ? reject(err) :
|
|
37194
|
+
return err ? reject(err) : resolve19(data);
|
|
37173
37195
|
});
|
|
37174
37196
|
});
|
|
37175
37197
|
}
|
|
@@ -37329,20 +37351,20 @@ var require_mock_utils = __commonJS({
|
|
|
37329
37351
|
}
|
|
37330
37352
|
return true;
|
|
37331
37353
|
}
|
|
37332
|
-
function safeUrl(
|
|
37333
|
-
if (typeof
|
|
37334
|
-
return
|
|
37354
|
+
function safeUrl(path31) {
|
|
37355
|
+
if (typeof path31 !== "string") {
|
|
37356
|
+
return path31;
|
|
37335
37357
|
}
|
|
37336
|
-
const pathSegments =
|
|
37358
|
+
const pathSegments = path31.split("?");
|
|
37337
37359
|
if (pathSegments.length !== 2) {
|
|
37338
|
-
return
|
|
37360
|
+
return path31;
|
|
37339
37361
|
}
|
|
37340
37362
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
37341
37363
|
qp.sort();
|
|
37342
37364
|
return [...pathSegments, qp.toString()].join("?");
|
|
37343
37365
|
}
|
|
37344
|
-
function matchKey(mockDispatch2, { path:
|
|
37345
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
37366
|
+
function matchKey(mockDispatch2, { path: path31, method, body, headers }) {
|
|
37367
|
+
const pathMatch = matchValue(mockDispatch2.path, path31);
|
|
37346
37368
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
37347
37369
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
37348
37370
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -37360,7 +37382,7 @@ var require_mock_utils = __commonJS({
|
|
|
37360
37382
|
function getMockDispatch(mockDispatches, key) {
|
|
37361
37383
|
const basePath = key.query ? buildURL(key.path, key.query) : key.path;
|
|
37362
37384
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
37363
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
37385
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path31 }) => matchValue(safeUrl(path31), resolvedPath));
|
|
37364
37386
|
if (matchedMockDispatches.length === 0) {
|
|
37365
37387
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
37366
37388
|
}
|
|
@@ -37397,9 +37419,9 @@ var require_mock_utils = __commonJS({
|
|
|
37397
37419
|
}
|
|
37398
37420
|
}
|
|
37399
37421
|
function buildKey(opts) {
|
|
37400
|
-
const { path:
|
|
37422
|
+
const { path: path31, method, body, headers, query } = opts;
|
|
37401
37423
|
return {
|
|
37402
|
-
path:
|
|
37424
|
+
path: path31,
|
|
37403
37425
|
method,
|
|
37404
37426
|
body,
|
|
37405
37427
|
headers,
|
|
@@ -37848,10 +37870,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
37848
37870
|
}
|
|
37849
37871
|
format(pendingInterceptors) {
|
|
37850
37872
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
37851
|
-
({ method, path:
|
|
37873
|
+
({ method, path: path31, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
37852
37874
|
Method: method,
|
|
37853
37875
|
Origin: origin,
|
|
37854
|
-
Path:
|
|
37876
|
+
Path: path31,
|
|
37855
37877
|
"Status code": statusCode,
|
|
37856
37878
|
Persistent: persist ? "\u2705" : "\u274C",
|
|
37857
37879
|
Invocations: timesInvoked,
|
|
@@ -40792,7 +40814,7 @@ var require_fetch = __commonJS({
|
|
|
40792
40814
|
async function dispatch({ body }) {
|
|
40793
40815
|
const url = requestCurrentURL(request);
|
|
40794
40816
|
const agent = fetchParams.controller.dispatcher;
|
|
40795
|
-
return new Promise((
|
|
40817
|
+
return new Promise((resolve19, reject) => agent.dispatch(
|
|
40796
40818
|
{
|
|
40797
40819
|
path: url.pathname + url.search,
|
|
40798
40820
|
origin: url.origin,
|
|
@@ -40868,7 +40890,7 @@ var require_fetch = __commonJS({
|
|
|
40868
40890
|
}
|
|
40869
40891
|
}
|
|
40870
40892
|
}
|
|
40871
|
-
|
|
40893
|
+
resolve19({
|
|
40872
40894
|
status,
|
|
40873
40895
|
statusText,
|
|
40874
40896
|
headersList: headers[kHeadersList],
|
|
@@ -40911,7 +40933,7 @@ var require_fetch = __commonJS({
|
|
|
40911
40933
|
const val = headersList[n + 1].toString("latin1");
|
|
40912
40934
|
headers[kHeadersList].append(key, val);
|
|
40913
40935
|
}
|
|
40914
|
-
|
|
40936
|
+
resolve19({
|
|
40915
40937
|
status,
|
|
40916
40938
|
statusText: STATUS_CODES[status],
|
|
40917
40939
|
headersList: headers[kHeadersList],
|
|
@@ -42472,8 +42494,8 @@ var require_util6 = __commonJS({
|
|
|
42472
42494
|
}
|
|
42473
42495
|
}
|
|
42474
42496
|
}
|
|
42475
|
-
function validateCookiePath(
|
|
42476
|
-
for (const char of
|
|
42497
|
+
function validateCookiePath(path31) {
|
|
42498
|
+
for (const char of path31) {
|
|
42477
42499
|
const code = char.charCodeAt(0);
|
|
42478
42500
|
if (code < 33 || char === ";") {
|
|
42479
42501
|
throw new Error("Invalid cookie path");
|
|
@@ -43270,9 +43292,9 @@ var require_connection = __commonJS({
|
|
|
43270
43292
|
channels.open = diagnosticsChannel.channel("undici:websocket:open");
|
|
43271
43293
|
channels.close = diagnosticsChannel.channel("undici:websocket:close");
|
|
43272
43294
|
channels.socketError = diagnosticsChannel.channel("undici:websocket:socket_error");
|
|
43273
|
-
var
|
|
43295
|
+
var crypto4;
|
|
43274
43296
|
try {
|
|
43275
|
-
|
|
43297
|
+
crypto4 = require("crypto");
|
|
43276
43298
|
} catch {
|
|
43277
43299
|
}
|
|
43278
43300
|
function establishWebSocketConnection(url, protocols, ws, onEstablish, options) {
|
|
@@ -43291,7 +43313,7 @@ var require_connection = __commonJS({
|
|
|
43291
43313
|
const headersList = new Headers(options.headers)[kHeadersList];
|
|
43292
43314
|
request.headersList = headersList;
|
|
43293
43315
|
}
|
|
43294
|
-
const keyValue =
|
|
43316
|
+
const keyValue = crypto4.randomBytes(16).toString("base64");
|
|
43295
43317
|
request.headersList.append("sec-websocket-key", keyValue);
|
|
43296
43318
|
request.headersList.append("sec-websocket-version", "13");
|
|
43297
43319
|
for (const protocol of protocols) {
|
|
@@ -43320,7 +43342,7 @@ var require_connection = __commonJS({
|
|
|
43320
43342
|
return;
|
|
43321
43343
|
}
|
|
43322
43344
|
const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
|
|
43323
|
-
const digest =
|
|
43345
|
+
const digest = crypto4.createHash("sha1").update(keyValue + uid).digest("base64");
|
|
43324
43346
|
if (secWSAccept !== digest) {
|
|
43325
43347
|
failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header.");
|
|
43326
43348
|
return;
|
|
@@ -43400,9 +43422,9 @@ var require_frame = __commonJS({
|
|
|
43400
43422
|
"node_modules/undici/lib/websocket/frame.js"(exports2, module2) {
|
|
43401
43423
|
"use strict";
|
|
43402
43424
|
var { maxUnsigned16Bit } = require_constants5();
|
|
43403
|
-
var
|
|
43425
|
+
var crypto4;
|
|
43404
43426
|
try {
|
|
43405
|
-
|
|
43427
|
+
crypto4 = require("crypto");
|
|
43406
43428
|
} catch {
|
|
43407
43429
|
}
|
|
43408
43430
|
var WebsocketFrameSend = class {
|
|
@@ -43411,7 +43433,7 @@ var require_frame = __commonJS({
|
|
|
43411
43433
|
*/
|
|
43412
43434
|
constructor(data) {
|
|
43413
43435
|
this.frameData = data;
|
|
43414
|
-
this.maskKey =
|
|
43436
|
+
this.maskKey = crypto4.randomBytes(4);
|
|
43415
43437
|
}
|
|
43416
43438
|
createFrame(opcode) {
|
|
43417
43439
|
const bodyLength = this.frameData?.byteLength ?? 0;
|
|
@@ -44153,11 +44175,11 @@ var require_undici = __commonJS({
|
|
|
44153
44175
|
if (typeof opts.path !== "string") {
|
|
44154
44176
|
throw new InvalidArgumentError("invalid opts.path");
|
|
44155
44177
|
}
|
|
44156
|
-
let
|
|
44178
|
+
let path31 = opts.path;
|
|
44157
44179
|
if (!opts.path.startsWith("/")) {
|
|
44158
|
-
|
|
44180
|
+
path31 = `/${path31}`;
|
|
44159
44181
|
}
|
|
44160
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
44182
|
+
url = new URL(util.parseOrigin(url).origin + path31);
|
|
44161
44183
|
} else {
|
|
44162
44184
|
if (!opts) {
|
|
44163
44185
|
opts = typeof url === "object" ? url : {};
|
|
@@ -44706,7 +44728,7 @@ var init_mcp_check_provider = __esm({
|
|
|
44706
44728
|
logger.warn(
|
|
44707
44729
|
`MCP ${transportName} failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`
|
|
44708
44730
|
);
|
|
44709
|
-
await new Promise((
|
|
44731
|
+
await new Promise((resolve19) => setTimeout(resolve19, delay));
|
|
44710
44732
|
attempt += 1;
|
|
44711
44733
|
} finally {
|
|
44712
44734
|
try {
|
|
@@ -44988,7 +45010,7 @@ async function acquirePromptLock() {
|
|
|
44988
45010
|
activePrompt = true;
|
|
44989
45011
|
return;
|
|
44990
45012
|
}
|
|
44991
|
-
await new Promise((
|
|
45013
|
+
await new Promise((resolve19) => waiters.push(resolve19));
|
|
44992
45014
|
activePrompt = true;
|
|
44993
45015
|
}
|
|
44994
45016
|
function releasePromptLock() {
|
|
@@ -44998,7 +45020,7 @@ function releasePromptLock() {
|
|
|
44998
45020
|
}
|
|
44999
45021
|
async function interactivePrompt(options) {
|
|
45000
45022
|
await acquirePromptLock();
|
|
45001
|
-
return new Promise((
|
|
45023
|
+
return new Promise((resolve19, reject) => {
|
|
45002
45024
|
const dbg = process.env.VISOR_DEBUG === "true";
|
|
45003
45025
|
try {
|
|
45004
45026
|
if (dbg) {
|
|
@@ -45085,12 +45107,12 @@ async function interactivePrompt(options) {
|
|
|
45085
45107
|
};
|
|
45086
45108
|
const finish = (value) => {
|
|
45087
45109
|
cleanup();
|
|
45088
|
-
|
|
45110
|
+
resolve19(value);
|
|
45089
45111
|
};
|
|
45090
45112
|
if (options.timeout && options.timeout > 0) {
|
|
45091
45113
|
timeoutId = setTimeout(() => {
|
|
45092
45114
|
cleanup();
|
|
45093
|
-
if (defaultValue !== void 0) return
|
|
45115
|
+
if (defaultValue !== void 0) return resolve19(defaultValue);
|
|
45094
45116
|
return reject(new Error("Input timeout"));
|
|
45095
45117
|
}, options.timeout);
|
|
45096
45118
|
}
|
|
@@ -45222,7 +45244,7 @@ async function interactivePrompt(options) {
|
|
|
45222
45244
|
});
|
|
45223
45245
|
}
|
|
45224
45246
|
async function simplePrompt(prompt) {
|
|
45225
|
-
return new Promise((
|
|
45247
|
+
return new Promise((resolve19) => {
|
|
45226
45248
|
const rl = readline.createInterface({
|
|
45227
45249
|
input: process.stdin,
|
|
45228
45250
|
output: process.stdout
|
|
@@ -45238,7 +45260,7 @@ async function simplePrompt(prompt) {
|
|
|
45238
45260
|
rl.question(`${prompt}
|
|
45239
45261
|
> `, (answer) => {
|
|
45240
45262
|
rl.close();
|
|
45241
|
-
|
|
45263
|
+
resolve19(answer.trim());
|
|
45242
45264
|
});
|
|
45243
45265
|
});
|
|
45244
45266
|
}
|
|
@@ -45406,7 +45428,7 @@ function isStdinAvailable() {
|
|
|
45406
45428
|
return !process.stdin.isTTY;
|
|
45407
45429
|
}
|
|
45408
45430
|
async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
45409
|
-
return new Promise((
|
|
45431
|
+
return new Promise((resolve19, reject) => {
|
|
45410
45432
|
let data = "";
|
|
45411
45433
|
let timeoutId;
|
|
45412
45434
|
if (timeout) {
|
|
@@ -45433,7 +45455,7 @@ async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
|
45433
45455
|
};
|
|
45434
45456
|
const onEnd = () => {
|
|
45435
45457
|
cleanup();
|
|
45436
|
-
|
|
45458
|
+
resolve19(data.trim());
|
|
45437
45459
|
};
|
|
45438
45460
|
const onError = (err) => {
|
|
45439
45461
|
cleanup();
|
|
@@ -49559,23 +49581,23 @@ __export(renderer_schema_exports, {
|
|
|
49559
49581
|
});
|
|
49560
49582
|
async function loadRendererSchema(name) {
|
|
49561
49583
|
try {
|
|
49562
|
-
const
|
|
49563
|
-
const
|
|
49584
|
+
const fs27 = await import("fs/promises");
|
|
49585
|
+
const path31 = await import("path");
|
|
49564
49586
|
const sanitized = String(name).replace(/[^a-zA-Z0-9-]/g, "");
|
|
49565
49587
|
if (!sanitized) return void 0;
|
|
49566
49588
|
const candidates = [
|
|
49567
49589
|
// When bundled with ncc, __dirname is dist/ and output/ is at dist/output/
|
|
49568
|
-
|
|
49590
|
+
path31.join(__dirname, "output", sanitized, "schema.json"),
|
|
49569
49591
|
// When running from source, __dirname is src/state-machine/dispatch/ and output/ is at output/
|
|
49570
|
-
|
|
49592
|
+
path31.join(__dirname, "..", "..", "output", sanitized, "schema.json"),
|
|
49571
49593
|
// When running from a checkout with output/ folder copied to CWD
|
|
49572
|
-
|
|
49594
|
+
path31.join(process.cwd(), "output", sanitized, "schema.json"),
|
|
49573
49595
|
// Fallback: cwd/dist/output/
|
|
49574
|
-
|
|
49596
|
+
path31.join(process.cwd(), "dist", "output", sanitized, "schema.json")
|
|
49575
49597
|
];
|
|
49576
49598
|
for (const p of candidates) {
|
|
49577
49599
|
try {
|
|
49578
|
-
const raw = await
|
|
49600
|
+
const raw = await fs27.readFile(p, "utf-8");
|
|
49579
49601
|
return JSON.parse(raw);
|
|
49580
49602
|
} catch {
|
|
49581
49603
|
}
|
|
@@ -51994,8 +52016,8 @@ function updateStats2(results, state, isForEachIteration = false) {
|
|
|
51994
52016
|
async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
51995
52017
|
try {
|
|
51996
52018
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
51997
|
-
const
|
|
51998
|
-
const
|
|
52019
|
+
const fs27 = await import("fs/promises");
|
|
52020
|
+
const path31 = await import("path");
|
|
51999
52021
|
const schemaRaw = checkConfig.schema || "plain";
|
|
52000
52022
|
const schema = typeof schemaRaw === "string" && !schemaRaw.includes("{{") && !schemaRaw.includes("{%") ? schemaRaw : typeof schemaRaw === "object" ? "code-review" : "plain";
|
|
52001
52023
|
let templateContent;
|
|
@@ -52004,27 +52026,27 @@ async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
|
52004
52026
|
logger.debug(`[LevelDispatch] Using inline template for ${checkId}`);
|
|
52005
52027
|
} else if (checkConfig.template && checkConfig.template.file) {
|
|
52006
52028
|
const file = String(checkConfig.template.file);
|
|
52007
|
-
const resolved =
|
|
52008
|
-
templateContent = await
|
|
52029
|
+
const resolved = path31.resolve(process.cwd(), file);
|
|
52030
|
+
templateContent = await fs27.readFile(resolved, "utf-8");
|
|
52009
52031
|
logger.debug(`[LevelDispatch] Using template file for ${checkId}: ${resolved}`);
|
|
52010
52032
|
} else if (schema && schema !== "plain") {
|
|
52011
52033
|
const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
|
|
52012
52034
|
if (sanitized) {
|
|
52013
52035
|
const candidatePaths = [
|
|
52014
|
-
|
|
52036
|
+
path31.join(__dirname, "output", sanitized, "template.liquid"),
|
|
52015
52037
|
// bundled: dist/output/
|
|
52016
|
-
|
|
52038
|
+
path31.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
52017
52039
|
// source (from state-machine/states)
|
|
52018
|
-
|
|
52040
|
+
path31.join(__dirname, "..", "..", "..", "output", sanitized, "template.liquid"),
|
|
52019
52041
|
// source (alternate)
|
|
52020
|
-
|
|
52042
|
+
path31.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
52021
52043
|
// fallback: cwd/output/
|
|
52022
|
-
|
|
52044
|
+
path31.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
|
|
52023
52045
|
// fallback: cwd/dist/output/
|
|
52024
52046
|
];
|
|
52025
52047
|
for (const p of candidatePaths) {
|
|
52026
52048
|
try {
|
|
52027
|
-
templateContent = await
|
|
52049
|
+
templateContent = await fs27.readFile(p, "utf-8");
|
|
52028
52050
|
if (templateContent) {
|
|
52029
52051
|
logger.debug(`[LevelDispatch] Using schema template for ${checkId}: ${p}`);
|
|
52030
52052
|
break;
|
|
@@ -54164,8 +54186,8 @@ var init_workspace_manager = __esm({
|
|
|
54164
54186
|
);
|
|
54165
54187
|
if (this.cleanupRequested && this.activeOperations === 0) {
|
|
54166
54188
|
logger.debug(`[Workspace] All references released, proceeding with deferred cleanup`);
|
|
54167
|
-
for (const
|
|
54168
|
-
|
|
54189
|
+
for (const resolve19 of this.cleanupResolvers) {
|
|
54190
|
+
resolve19();
|
|
54169
54191
|
}
|
|
54170
54192
|
this.cleanupResolvers = [];
|
|
54171
54193
|
}
|
|
@@ -54322,19 +54344,19 @@ var init_workspace_manager = __esm({
|
|
|
54322
54344
|
);
|
|
54323
54345
|
this.cleanupRequested = true;
|
|
54324
54346
|
await Promise.race([
|
|
54325
|
-
new Promise((
|
|
54347
|
+
new Promise((resolve19) => {
|
|
54326
54348
|
if (this.activeOperations === 0) {
|
|
54327
|
-
|
|
54349
|
+
resolve19();
|
|
54328
54350
|
} else {
|
|
54329
|
-
this.cleanupResolvers.push(
|
|
54351
|
+
this.cleanupResolvers.push(resolve19);
|
|
54330
54352
|
}
|
|
54331
54353
|
}),
|
|
54332
|
-
new Promise((
|
|
54354
|
+
new Promise((resolve19) => {
|
|
54333
54355
|
setTimeout(() => {
|
|
54334
54356
|
logger.warn(
|
|
54335
54357
|
`[Workspace] Cleanup timeout after ${timeout}ms, proceeding anyway (${this.activeOperations} operations still active)`
|
|
54336
54358
|
);
|
|
54337
|
-
|
|
54359
|
+
resolve19();
|
|
54338
54360
|
}, timeout);
|
|
54339
54361
|
})
|
|
54340
54362
|
]);
|
|
@@ -54812,6 +54834,1380 @@ var init_build_engine_context = __esm({
|
|
|
54812
54834
|
}
|
|
54813
54835
|
});
|
|
54814
54836
|
|
|
54837
|
+
// src/policy/default-engine.ts
|
|
54838
|
+
var DefaultPolicyEngine;
|
|
54839
|
+
var init_default_engine = __esm({
|
|
54840
|
+
"src/policy/default-engine.ts"() {
|
|
54841
|
+
"use strict";
|
|
54842
|
+
DefaultPolicyEngine = class {
|
|
54843
|
+
async initialize(_config) {
|
|
54844
|
+
}
|
|
54845
|
+
async evaluateCheckExecution(_checkId, _checkConfig) {
|
|
54846
|
+
return { allowed: true };
|
|
54847
|
+
}
|
|
54848
|
+
async evaluateToolInvocation(_serverName, _methodName, _transport) {
|
|
54849
|
+
return { allowed: true };
|
|
54850
|
+
}
|
|
54851
|
+
async evaluateCapabilities(_checkId, _capabilities) {
|
|
54852
|
+
return { allowed: true };
|
|
54853
|
+
}
|
|
54854
|
+
async shutdown() {
|
|
54855
|
+
}
|
|
54856
|
+
};
|
|
54857
|
+
}
|
|
54858
|
+
});
|
|
54859
|
+
|
|
54860
|
+
// src/enterprise/license/validator.ts
|
|
54861
|
+
var validator_exports = {};
|
|
54862
|
+
__export(validator_exports, {
|
|
54863
|
+
LicenseValidator: () => LicenseValidator
|
|
54864
|
+
});
|
|
54865
|
+
var crypto2, fs21, path25, LicenseValidator;
|
|
54866
|
+
var init_validator = __esm({
|
|
54867
|
+
"src/enterprise/license/validator.ts"() {
|
|
54868
|
+
"use strict";
|
|
54869
|
+
crypto2 = __toESM(require("crypto"));
|
|
54870
|
+
fs21 = __toESM(require("fs"));
|
|
54871
|
+
path25 = __toESM(require("path"));
|
|
54872
|
+
LicenseValidator = class _LicenseValidator {
|
|
54873
|
+
/** Ed25519 public key for license verification (PEM format). */
|
|
54874
|
+
static PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAI/Zd08EFmgIdrDm/HXd0l3/5GBt7R1PrdvhdmEXhJlU=\n-----END PUBLIC KEY-----\n";
|
|
54875
|
+
cache = null;
|
|
54876
|
+
static CACHE_TTL = 5 * 60 * 1e3;
|
|
54877
|
+
// 5 minutes
|
|
54878
|
+
static GRACE_PERIOD = 72 * 3600 * 1e3;
|
|
54879
|
+
// 72 hours after expiry
|
|
54880
|
+
/**
|
|
54881
|
+
* Load and validate license from environment or file.
|
|
54882
|
+
*
|
|
54883
|
+
* Resolution order:
|
|
54884
|
+
* 1. VISOR_LICENSE env var (JWT string)
|
|
54885
|
+
* 2. VISOR_LICENSE_FILE env var (path to file)
|
|
54886
|
+
* 3. .visor-license in project root (cwd)
|
|
54887
|
+
* 4. .visor-license in ~/.config/visor/
|
|
54888
|
+
*/
|
|
54889
|
+
async loadAndValidate() {
|
|
54890
|
+
if (this.cache && Date.now() - this.cache.validatedAt < _LicenseValidator.CACHE_TTL) {
|
|
54891
|
+
return this.cache.payload;
|
|
54892
|
+
}
|
|
54893
|
+
const token = this.resolveToken();
|
|
54894
|
+
if (!token) return null;
|
|
54895
|
+
const payload = this.verifyAndDecode(token);
|
|
54896
|
+
if (!payload) return null;
|
|
54897
|
+
this.cache = { payload, validatedAt: Date.now() };
|
|
54898
|
+
return payload;
|
|
54899
|
+
}
|
|
54900
|
+
/** Check if a specific feature is licensed */
|
|
54901
|
+
hasFeature(feature) {
|
|
54902
|
+
if (!this.cache) return false;
|
|
54903
|
+
return this.cache.payload.features.includes(feature);
|
|
54904
|
+
}
|
|
54905
|
+
/** Check if license is valid (with grace period) */
|
|
54906
|
+
isValid() {
|
|
54907
|
+
if (!this.cache) return false;
|
|
54908
|
+
const now = Date.now();
|
|
54909
|
+
const expiryMs = this.cache.payload.exp * 1e3;
|
|
54910
|
+
return now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
54911
|
+
}
|
|
54912
|
+
/** Check if the license is within its grace period (expired but still valid) */
|
|
54913
|
+
isInGracePeriod() {
|
|
54914
|
+
if (!this.cache) return false;
|
|
54915
|
+
const now = Date.now();
|
|
54916
|
+
const expiryMs = this.cache.payload.exp * 1e3;
|
|
54917
|
+
return now >= expiryMs && now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
54918
|
+
}
|
|
54919
|
+
resolveToken() {
|
|
54920
|
+
if (process.env.VISOR_LICENSE) {
|
|
54921
|
+
return process.env.VISOR_LICENSE.trim();
|
|
54922
|
+
}
|
|
54923
|
+
if (process.env.VISOR_LICENSE_FILE) {
|
|
54924
|
+
const resolved = path25.resolve(process.env.VISOR_LICENSE_FILE);
|
|
54925
|
+
const home2 = process.env.HOME || process.env.USERPROFILE || "";
|
|
54926
|
+
const allowedPrefixes = [path25.normalize(process.cwd())];
|
|
54927
|
+
if (home2) allowedPrefixes.push(path25.normalize(path25.join(home2, ".config", "visor")));
|
|
54928
|
+
let realPath;
|
|
54929
|
+
try {
|
|
54930
|
+
realPath = fs21.realpathSync(resolved);
|
|
54931
|
+
} catch {
|
|
54932
|
+
return null;
|
|
54933
|
+
}
|
|
54934
|
+
const isSafe = allowedPrefixes.some(
|
|
54935
|
+
(prefix) => realPath === prefix || realPath.startsWith(prefix + path25.sep)
|
|
54936
|
+
);
|
|
54937
|
+
if (!isSafe) return null;
|
|
54938
|
+
return this.readFile(realPath);
|
|
54939
|
+
}
|
|
54940
|
+
const cwdPath = path25.join(process.cwd(), ".visor-license");
|
|
54941
|
+
const cwdToken = this.readFile(cwdPath);
|
|
54942
|
+
if (cwdToken) return cwdToken;
|
|
54943
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
54944
|
+
if (home) {
|
|
54945
|
+
const configPath = path25.join(home, ".config", "visor", ".visor-license");
|
|
54946
|
+
const configToken = this.readFile(configPath);
|
|
54947
|
+
if (configToken) return configToken;
|
|
54948
|
+
}
|
|
54949
|
+
return null;
|
|
54950
|
+
}
|
|
54951
|
+
readFile(filePath) {
|
|
54952
|
+
try {
|
|
54953
|
+
return fs21.readFileSync(filePath, "utf-8").trim();
|
|
54954
|
+
} catch {
|
|
54955
|
+
return null;
|
|
54956
|
+
}
|
|
54957
|
+
}
|
|
54958
|
+
verifyAndDecode(token) {
|
|
54959
|
+
try {
|
|
54960
|
+
const parts = token.split(".");
|
|
54961
|
+
if (parts.length !== 3) return null;
|
|
54962
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
54963
|
+
const header = JSON.parse(Buffer.from(headerB64, "base64url").toString());
|
|
54964
|
+
if (header.alg !== "EdDSA") return null;
|
|
54965
|
+
const data = `${headerB64}.${payloadB64}`;
|
|
54966
|
+
const signature = Buffer.from(signatureB64, "base64url");
|
|
54967
|
+
const publicKey = crypto2.createPublicKey(_LicenseValidator.PUBLIC_KEY);
|
|
54968
|
+
if (publicKey.asymmetricKeyType !== "ed25519") {
|
|
54969
|
+
return null;
|
|
54970
|
+
}
|
|
54971
|
+
const isValid = crypto2.verify(null, Buffer.from(data), publicKey, signature);
|
|
54972
|
+
if (!isValid) return null;
|
|
54973
|
+
const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
|
|
54974
|
+
if (!payload.org || !Array.isArray(payload.features) || typeof payload.exp !== "number" || typeof payload.iat !== "number" || !payload.sub) {
|
|
54975
|
+
return null;
|
|
54976
|
+
}
|
|
54977
|
+
const now = Date.now();
|
|
54978
|
+
const expiryMs = payload.exp * 1e3;
|
|
54979
|
+
if (now >= expiryMs + _LicenseValidator.GRACE_PERIOD) {
|
|
54980
|
+
return null;
|
|
54981
|
+
}
|
|
54982
|
+
return payload;
|
|
54983
|
+
} catch {
|
|
54984
|
+
return null;
|
|
54985
|
+
}
|
|
54986
|
+
}
|
|
54987
|
+
};
|
|
54988
|
+
}
|
|
54989
|
+
});
|
|
54990
|
+
|
|
54991
|
+
// src/enterprise/policy/opa-compiler.ts
|
|
54992
|
+
var fs22, path26, os2, crypto3, import_child_process8, OpaCompiler;
|
|
54993
|
+
var init_opa_compiler = __esm({
|
|
54994
|
+
"src/enterprise/policy/opa-compiler.ts"() {
|
|
54995
|
+
"use strict";
|
|
54996
|
+
fs22 = __toESM(require("fs"));
|
|
54997
|
+
path26 = __toESM(require("path"));
|
|
54998
|
+
os2 = __toESM(require("os"));
|
|
54999
|
+
crypto3 = __toESM(require("crypto"));
|
|
55000
|
+
import_child_process8 = require("child_process");
|
|
55001
|
+
OpaCompiler = class _OpaCompiler {
|
|
55002
|
+
static CACHE_DIR = path26.join(os2.tmpdir(), "visor-opa-cache");
|
|
55003
|
+
/**
|
|
55004
|
+
* Resolve the input paths to WASM bytes.
|
|
55005
|
+
*
|
|
55006
|
+
* Strategy:
|
|
55007
|
+
* 1. If any path is a .wasm file, read it directly
|
|
55008
|
+
* 2. If a directory contains policy.wasm, read it
|
|
55009
|
+
* 3. Otherwise, collect all .rego files and auto-compile via `opa build`
|
|
55010
|
+
*/
|
|
55011
|
+
async resolveWasmBytes(paths) {
|
|
55012
|
+
const regoFiles = [];
|
|
55013
|
+
for (const p of paths) {
|
|
55014
|
+
const resolved = path26.resolve(p);
|
|
55015
|
+
if (path26.normalize(resolved).includes("..")) {
|
|
55016
|
+
throw new Error(`Policy path contains traversal sequences: ${p}`);
|
|
55017
|
+
}
|
|
55018
|
+
if (resolved.endsWith(".wasm") && fs22.existsSync(resolved)) {
|
|
55019
|
+
return fs22.readFileSync(resolved);
|
|
55020
|
+
}
|
|
55021
|
+
if (!fs22.existsSync(resolved)) continue;
|
|
55022
|
+
const stat2 = fs22.statSync(resolved);
|
|
55023
|
+
if (stat2.isDirectory()) {
|
|
55024
|
+
const wasmCandidate = path26.join(resolved, "policy.wasm");
|
|
55025
|
+
if (fs22.existsSync(wasmCandidate)) {
|
|
55026
|
+
return fs22.readFileSync(wasmCandidate);
|
|
55027
|
+
}
|
|
55028
|
+
const files = fs22.readdirSync(resolved);
|
|
55029
|
+
for (const f of files) {
|
|
55030
|
+
if (f.endsWith(".rego")) {
|
|
55031
|
+
regoFiles.push(path26.join(resolved, f));
|
|
55032
|
+
}
|
|
55033
|
+
}
|
|
55034
|
+
} else if (resolved.endsWith(".rego")) {
|
|
55035
|
+
regoFiles.push(resolved);
|
|
55036
|
+
}
|
|
55037
|
+
}
|
|
55038
|
+
if (regoFiles.length === 0) {
|
|
55039
|
+
throw new Error(
|
|
55040
|
+
`OPA WASM evaluator: no .wasm bundle or .rego files found in: ${paths.join(", ")}`
|
|
55041
|
+
);
|
|
55042
|
+
}
|
|
55043
|
+
return this.compileRego(regoFiles);
|
|
55044
|
+
}
|
|
55045
|
+
/**
|
|
55046
|
+
* Auto-compile .rego files to a WASM bundle using the `opa` CLI.
|
|
55047
|
+
*
|
|
55048
|
+
* Caches the compiled bundle based on a content hash of all input .rego files
|
|
55049
|
+
* so subsequent runs skip compilation if policies haven't changed.
|
|
55050
|
+
*/
|
|
55051
|
+
compileRego(regoFiles) {
|
|
55052
|
+
try {
|
|
55053
|
+
(0, import_child_process8.execFileSync)("opa", ["version"], { stdio: "pipe" });
|
|
55054
|
+
} catch {
|
|
55055
|
+
throw new Error(
|
|
55056
|
+
"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(" ")
|
|
55057
|
+
);
|
|
55058
|
+
}
|
|
55059
|
+
const hash = crypto3.createHash("sha256");
|
|
55060
|
+
for (const f of regoFiles.sort()) {
|
|
55061
|
+
hash.update(fs22.readFileSync(f));
|
|
55062
|
+
hash.update(f);
|
|
55063
|
+
}
|
|
55064
|
+
const cacheKey = hash.digest("hex").slice(0, 16);
|
|
55065
|
+
const cacheDir = _OpaCompiler.CACHE_DIR;
|
|
55066
|
+
const cachedWasm = path26.join(cacheDir, `${cacheKey}.wasm`);
|
|
55067
|
+
if (fs22.existsSync(cachedWasm)) {
|
|
55068
|
+
return fs22.readFileSync(cachedWasm);
|
|
55069
|
+
}
|
|
55070
|
+
fs22.mkdirSync(cacheDir, { recursive: true });
|
|
55071
|
+
const bundleTar = path26.join(cacheDir, `${cacheKey}-bundle.tar.gz`);
|
|
55072
|
+
try {
|
|
55073
|
+
const args = [
|
|
55074
|
+
"build",
|
|
55075
|
+
"-t",
|
|
55076
|
+
"wasm",
|
|
55077
|
+
"-e",
|
|
55078
|
+
"visor",
|
|
55079
|
+
// entrypoint: the visor package tree
|
|
55080
|
+
"-o",
|
|
55081
|
+
bundleTar,
|
|
55082
|
+
...regoFiles
|
|
55083
|
+
];
|
|
55084
|
+
(0, import_child_process8.execFileSync)("opa", args, {
|
|
55085
|
+
stdio: "pipe",
|
|
55086
|
+
timeout: 3e4
|
|
55087
|
+
});
|
|
55088
|
+
} catch (err) {
|
|
55089
|
+
const stderr = err?.stderr?.toString() || "";
|
|
55090
|
+
throw new Error(
|
|
55091
|
+
`Failed to compile .rego files to WASM:
|
|
55092
|
+
${stderr}
|
|
55093
|
+
Ensure your .rego files are valid and the \`opa\` CLI is installed.`
|
|
55094
|
+
);
|
|
55095
|
+
}
|
|
55096
|
+
try {
|
|
55097
|
+
(0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "/policy.wasm"], {
|
|
55098
|
+
stdio: "pipe"
|
|
55099
|
+
});
|
|
55100
|
+
const extractedWasm = path26.join(cacheDir, "policy.wasm");
|
|
55101
|
+
if (fs22.existsSync(extractedWasm)) {
|
|
55102
|
+
fs22.renameSync(extractedWasm, cachedWasm);
|
|
55103
|
+
}
|
|
55104
|
+
} catch {
|
|
55105
|
+
try {
|
|
55106
|
+
(0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "policy.wasm"], {
|
|
55107
|
+
stdio: "pipe"
|
|
55108
|
+
});
|
|
55109
|
+
const extractedWasm = path26.join(cacheDir, "policy.wasm");
|
|
55110
|
+
if (fs22.existsSync(extractedWasm)) {
|
|
55111
|
+
fs22.renameSync(extractedWasm, cachedWasm);
|
|
55112
|
+
}
|
|
55113
|
+
} catch (err2) {
|
|
55114
|
+
throw new Error(`Failed to extract policy.wasm from OPA bundle: ${err2?.message || err2}`);
|
|
55115
|
+
}
|
|
55116
|
+
}
|
|
55117
|
+
try {
|
|
55118
|
+
fs22.unlinkSync(bundleTar);
|
|
55119
|
+
} catch {
|
|
55120
|
+
}
|
|
55121
|
+
if (!fs22.existsSync(cachedWasm)) {
|
|
55122
|
+
throw new Error("OPA build succeeded but policy.wasm was not found in the bundle");
|
|
55123
|
+
}
|
|
55124
|
+
return fs22.readFileSync(cachedWasm);
|
|
55125
|
+
}
|
|
55126
|
+
};
|
|
55127
|
+
}
|
|
55128
|
+
});
|
|
55129
|
+
|
|
55130
|
+
// src/enterprise/policy/opa-wasm-evaluator.ts
|
|
55131
|
+
var fs23, path27, OpaWasmEvaluator;
|
|
55132
|
+
var init_opa_wasm_evaluator = __esm({
|
|
55133
|
+
"src/enterprise/policy/opa-wasm-evaluator.ts"() {
|
|
55134
|
+
"use strict";
|
|
55135
|
+
fs23 = __toESM(require("fs"));
|
|
55136
|
+
path27 = __toESM(require("path"));
|
|
55137
|
+
init_opa_compiler();
|
|
55138
|
+
OpaWasmEvaluator = class {
|
|
55139
|
+
policy = null;
|
|
55140
|
+
dataDocument = {};
|
|
55141
|
+
compiler = new OpaCompiler();
|
|
55142
|
+
async initialize(rulesPath) {
|
|
55143
|
+
const paths = Array.isArray(rulesPath) ? rulesPath : [rulesPath];
|
|
55144
|
+
const wasmBytes = await this.compiler.resolveWasmBytes(paths);
|
|
55145
|
+
try {
|
|
55146
|
+
const { createRequire } = require("module");
|
|
55147
|
+
const runtimeRequire = createRequire(__filename);
|
|
55148
|
+
const opaWasm = runtimeRequire("@open-policy-agent/opa-wasm");
|
|
55149
|
+
const loadPolicy = opaWasm.loadPolicy || opaWasm.default?.loadPolicy;
|
|
55150
|
+
if (!loadPolicy) {
|
|
55151
|
+
throw new Error("loadPolicy not found in @open-policy-agent/opa-wasm");
|
|
55152
|
+
}
|
|
55153
|
+
this.policy = await loadPolicy(wasmBytes);
|
|
55154
|
+
} catch (err) {
|
|
55155
|
+
if (err?.code === "MODULE_NOT_FOUND" || err?.code === "ERR_MODULE_NOT_FOUND") {
|
|
55156
|
+
throw new Error(
|
|
55157
|
+
"OPA WASM evaluator requires @open-policy-agent/opa-wasm. Install it with: npm install @open-policy-agent/opa-wasm"
|
|
55158
|
+
);
|
|
55159
|
+
}
|
|
55160
|
+
throw err;
|
|
55161
|
+
}
|
|
55162
|
+
}
|
|
55163
|
+
/**
|
|
55164
|
+
* Load external data from a JSON file to use as the OPA data document.
|
|
55165
|
+
* The loaded data will be passed to `policy.setData()` during evaluation,
|
|
55166
|
+
* making it available in Rego via `data.<key>`.
|
|
55167
|
+
*/
|
|
55168
|
+
loadData(dataPath) {
|
|
55169
|
+
const resolved = path27.resolve(dataPath);
|
|
55170
|
+
if (path27.normalize(resolved).includes("..")) {
|
|
55171
|
+
throw new Error(`Data path contains traversal sequences: ${dataPath}`);
|
|
55172
|
+
}
|
|
55173
|
+
if (!fs23.existsSync(resolved)) {
|
|
55174
|
+
throw new Error(`OPA data file not found: ${resolved}`);
|
|
55175
|
+
}
|
|
55176
|
+
const stat2 = fs23.statSync(resolved);
|
|
55177
|
+
if (stat2.size > 10 * 1024 * 1024) {
|
|
55178
|
+
throw new Error(`OPA data file exceeds 10MB limit: ${resolved} (${stat2.size} bytes)`);
|
|
55179
|
+
}
|
|
55180
|
+
const raw = fs23.readFileSync(resolved, "utf-8");
|
|
55181
|
+
try {
|
|
55182
|
+
const parsed = JSON.parse(raw);
|
|
55183
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
55184
|
+
throw new Error("OPA data file must contain a JSON object (not an array or primitive)");
|
|
55185
|
+
}
|
|
55186
|
+
this.dataDocument = parsed;
|
|
55187
|
+
} catch (err) {
|
|
55188
|
+
if (err.message.startsWith("OPA data file must")) {
|
|
55189
|
+
throw err;
|
|
55190
|
+
}
|
|
55191
|
+
throw new Error(`Failed to parse OPA data file ${resolved}: ${err.message}`);
|
|
55192
|
+
}
|
|
55193
|
+
}
|
|
55194
|
+
async evaluate(input) {
|
|
55195
|
+
if (!this.policy) {
|
|
55196
|
+
throw new Error("OPA WASM evaluator not initialized");
|
|
55197
|
+
}
|
|
55198
|
+
this.policy.setData(this.dataDocument);
|
|
55199
|
+
const resultSet = this.policy.evaluate(input);
|
|
55200
|
+
if (Array.isArray(resultSet) && resultSet.length > 0) {
|
|
55201
|
+
return resultSet[0].result;
|
|
55202
|
+
}
|
|
55203
|
+
return void 0;
|
|
55204
|
+
}
|
|
55205
|
+
async shutdown() {
|
|
55206
|
+
if (this.policy) {
|
|
55207
|
+
if (typeof this.policy.close === "function") {
|
|
55208
|
+
try {
|
|
55209
|
+
this.policy.close();
|
|
55210
|
+
} catch {
|
|
55211
|
+
}
|
|
55212
|
+
} else if (typeof this.policy.free === "function") {
|
|
55213
|
+
try {
|
|
55214
|
+
this.policy.free();
|
|
55215
|
+
} catch {
|
|
55216
|
+
}
|
|
55217
|
+
}
|
|
55218
|
+
}
|
|
55219
|
+
this.policy = null;
|
|
55220
|
+
}
|
|
55221
|
+
};
|
|
55222
|
+
}
|
|
55223
|
+
});
|
|
55224
|
+
|
|
55225
|
+
// src/enterprise/policy/opa-http-evaluator.ts
|
|
55226
|
+
var OpaHttpEvaluator;
|
|
55227
|
+
var init_opa_http_evaluator = __esm({
|
|
55228
|
+
"src/enterprise/policy/opa-http-evaluator.ts"() {
|
|
55229
|
+
"use strict";
|
|
55230
|
+
OpaHttpEvaluator = class {
|
|
55231
|
+
baseUrl;
|
|
55232
|
+
timeout;
|
|
55233
|
+
constructor(baseUrl, timeout = 5e3) {
|
|
55234
|
+
let parsed;
|
|
55235
|
+
try {
|
|
55236
|
+
parsed = new URL(baseUrl);
|
|
55237
|
+
} catch {
|
|
55238
|
+
throw new Error(`OPA HTTP evaluator: invalid URL: ${baseUrl}`);
|
|
55239
|
+
}
|
|
55240
|
+
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
55241
|
+
throw new Error(
|
|
55242
|
+
`OPA HTTP evaluator: url must use http:// or https:// protocol, got: ${baseUrl}`
|
|
55243
|
+
);
|
|
55244
|
+
}
|
|
55245
|
+
const hostname = parsed.hostname;
|
|
55246
|
+
if (this.isBlockedHostname(hostname)) {
|
|
55247
|
+
throw new Error(
|
|
55248
|
+
`OPA HTTP evaluator: url must not point to internal, loopback, or private network addresses`
|
|
55249
|
+
);
|
|
55250
|
+
}
|
|
55251
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
55252
|
+
this.timeout = timeout;
|
|
55253
|
+
}
|
|
55254
|
+
/**
|
|
55255
|
+
* Check if a hostname is blocked due to SSRF concerns.
|
|
55256
|
+
*
|
|
55257
|
+
* Blocks:
|
|
55258
|
+
* - Loopback addresses (127.x.x.x, localhost, 0.0.0.0, ::1)
|
|
55259
|
+
* - Link-local addresses (169.254.x.x)
|
|
55260
|
+
* - Private networks (10.x.x.x, 172.16-31.x.x, 192.168.x.x)
|
|
55261
|
+
* - IPv6 unique local addresses (fd00::/8)
|
|
55262
|
+
* - Cloud metadata services (*.internal)
|
|
55263
|
+
*/
|
|
55264
|
+
isBlockedHostname(hostname) {
|
|
55265
|
+
if (!hostname) return true;
|
|
55266
|
+
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
55267
|
+
if (normalized === "metadata.google.internal" || normalized.endsWith(".internal")) {
|
|
55268
|
+
return true;
|
|
55269
|
+
}
|
|
55270
|
+
if (normalized === "localhost" || normalized === "localhost.localdomain") {
|
|
55271
|
+
return true;
|
|
55272
|
+
}
|
|
55273
|
+
if (normalized === "::1" || normalized === "0:0:0:0:0:0:0:1") {
|
|
55274
|
+
return true;
|
|
55275
|
+
}
|
|
55276
|
+
const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
55277
|
+
const ipv4Match = normalized.match(ipv4Pattern);
|
|
55278
|
+
if (ipv4Match) {
|
|
55279
|
+
const octets = ipv4Match.slice(1, 5).map(Number);
|
|
55280
|
+
if (octets.some((octet) => octet > 255)) {
|
|
55281
|
+
return false;
|
|
55282
|
+
}
|
|
55283
|
+
const [a, b] = octets;
|
|
55284
|
+
if (a === 127) {
|
|
55285
|
+
return true;
|
|
55286
|
+
}
|
|
55287
|
+
if (a === 0) {
|
|
55288
|
+
return true;
|
|
55289
|
+
}
|
|
55290
|
+
if (a === 169 && b === 254) {
|
|
55291
|
+
return true;
|
|
55292
|
+
}
|
|
55293
|
+
if (a === 10) {
|
|
55294
|
+
return true;
|
|
55295
|
+
}
|
|
55296
|
+
if (a === 172 && b >= 16 && b <= 31) {
|
|
55297
|
+
return true;
|
|
55298
|
+
}
|
|
55299
|
+
if (a === 192 && b === 168) {
|
|
55300
|
+
return true;
|
|
55301
|
+
}
|
|
55302
|
+
}
|
|
55303
|
+
if (normalized.startsWith("fd") || normalized.startsWith("fc")) {
|
|
55304
|
+
return true;
|
|
55305
|
+
}
|
|
55306
|
+
if (normalized.startsWith("fe80:")) {
|
|
55307
|
+
return true;
|
|
55308
|
+
}
|
|
55309
|
+
return false;
|
|
55310
|
+
}
|
|
55311
|
+
/**
|
|
55312
|
+
* Evaluate a policy rule against an input document via OPA REST API.
|
|
55313
|
+
*
|
|
55314
|
+
* @param input - The input document to evaluate
|
|
55315
|
+
* @param rulePath - OPA rule path (e.g., 'visor/check/execute')
|
|
55316
|
+
* @returns The result object from OPA, or undefined on error
|
|
55317
|
+
*/
|
|
55318
|
+
async evaluate(input, rulePath) {
|
|
55319
|
+
const encodedPath = rulePath.split("/").map((s) => encodeURIComponent(s)).join("/");
|
|
55320
|
+
const url = `${this.baseUrl}/v1/data/${encodedPath}`;
|
|
55321
|
+
const controller = new AbortController();
|
|
55322
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
55323
|
+
try {
|
|
55324
|
+
const response = await fetch(url, {
|
|
55325
|
+
method: "POST",
|
|
55326
|
+
headers: { "Content-Type": "application/json" },
|
|
55327
|
+
body: JSON.stringify({ input }),
|
|
55328
|
+
signal: controller.signal
|
|
55329
|
+
});
|
|
55330
|
+
if (!response.ok) {
|
|
55331
|
+
throw new Error(`OPA HTTP ${response.status}: ${response.statusText}`);
|
|
55332
|
+
}
|
|
55333
|
+
let body;
|
|
55334
|
+
try {
|
|
55335
|
+
body = await response.json();
|
|
55336
|
+
} catch (jsonErr) {
|
|
55337
|
+
throw new Error(
|
|
55338
|
+
`OPA HTTP evaluator: failed to parse JSON response: ${jsonErr instanceof Error ? jsonErr.message : String(jsonErr)}`
|
|
55339
|
+
);
|
|
55340
|
+
}
|
|
55341
|
+
return body?.result;
|
|
55342
|
+
} finally {
|
|
55343
|
+
clearTimeout(timer);
|
|
55344
|
+
}
|
|
55345
|
+
}
|
|
55346
|
+
async shutdown() {
|
|
55347
|
+
}
|
|
55348
|
+
};
|
|
55349
|
+
}
|
|
55350
|
+
});
|
|
55351
|
+
|
|
55352
|
+
// src/enterprise/policy/policy-input-builder.ts
|
|
55353
|
+
var PolicyInputBuilder;
|
|
55354
|
+
var init_policy_input_builder = __esm({
|
|
55355
|
+
"src/enterprise/policy/policy-input-builder.ts"() {
|
|
55356
|
+
"use strict";
|
|
55357
|
+
PolicyInputBuilder = class {
|
|
55358
|
+
roles;
|
|
55359
|
+
actor;
|
|
55360
|
+
repository;
|
|
55361
|
+
pullRequest;
|
|
55362
|
+
constructor(policyConfig, actor, repository, pullRequest) {
|
|
55363
|
+
this.roles = policyConfig.roles || {};
|
|
55364
|
+
this.actor = actor;
|
|
55365
|
+
this.repository = repository;
|
|
55366
|
+
this.pullRequest = pullRequest;
|
|
55367
|
+
}
|
|
55368
|
+
/** Resolve which roles apply to the current actor. */
|
|
55369
|
+
resolveRoles() {
|
|
55370
|
+
const matched = [];
|
|
55371
|
+
for (const [roleName, roleConfig] of Object.entries(this.roles)) {
|
|
55372
|
+
let identityMatch = false;
|
|
55373
|
+
if (roleConfig.author_association && this.actor.authorAssociation && roleConfig.author_association.includes(this.actor.authorAssociation)) {
|
|
55374
|
+
identityMatch = true;
|
|
55375
|
+
}
|
|
55376
|
+
if (!identityMatch && roleConfig.users && this.actor.login && roleConfig.users.includes(this.actor.login)) {
|
|
55377
|
+
identityMatch = true;
|
|
55378
|
+
}
|
|
55379
|
+
if (!identityMatch && roleConfig.slack_users && this.actor.slack?.userId && roleConfig.slack_users.includes(this.actor.slack.userId)) {
|
|
55380
|
+
identityMatch = true;
|
|
55381
|
+
}
|
|
55382
|
+
if (!identityMatch && roleConfig.emails && this.actor.slack?.email) {
|
|
55383
|
+
const actorEmail = this.actor.slack.email.toLowerCase();
|
|
55384
|
+
if (roleConfig.emails.some((e) => e.toLowerCase() === actorEmail)) {
|
|
55385
|
+
identityMatch = true;
|
|
55386
|
+
}
|
|
55387
|
+
}
|
|
55388
|
+
if (!identityMatch) continue;
|
|
55389
|
+
if (roleConfig.slack_channels && roleConfig.slack_channels.length > 0) {
|
|
55390
|
+
if (!this.actor.slack?.channelId || !roleConfig.slack_channels.includes(this.actor.slack.channelId)) {
|
|
55391
|
+
continue;
|
|
55392
|
+
}
|
|
55393
|
+
}
|
|
55394
|
+
matched.push(roleName);
|
|
55395
|
+
}
|
|
55396
|
+
return matched;
|
|
55397
|
+
}
|
|
55398
|
+
buildActor() {
|
|
55399
|
+
return {
|
|
55400
|
+
authorAssociation: this.actor.authorAssociation,
|
|
55401
|
+
login: this.actor.login,
|
|
55402
|
+
roles: this.resolveRoles(),
|
|
55403
|
+
isLocalMode: this.actor.isLocalMode,
|
|
55404
|
+
...this.actor.slack && { slack: this.actor.slack }
|
|
55405
|
+
};
|
|
55406
|
+
}
|
|
55407
|
+
forCheckExecution(check) {
|
|
55408
|
+
return {
|
|
55409
|
+
scope: "check.execute",
|
|
55410
|
+
check: {
|
|
55411
|
+
id: check.id,
|
|
55412
|
+
type: check.type,
|
|
55413
|
+
group: check.group,
|
|
55414
|
+
tags: check.tags,
|
|
55415
|
+
criticality: check.criticality,
|
|
55416
|
+
sandbox: check.sandbox,
|
|
55417
|
+
policy: check.policy
|
|
55418
|
+
},
|
|
55419
|
+
actor: this.buildActor(),
|
|
55420
|
+
repository: this.repository,
|
|
55421
|
+
pullRequest: this.pullRequest
|
|
55422
|
+
};
|
|
55423
|
+
}
|
|
55424
|
+
forToolInvocation(serverName, methodName, transport) {
|
|
55425
|
+
return {
|
|
55426
|
+
scope: "tool.invoke",
|
|
55427
|
+
tool: { serverName, methodName, transport },
|
|
55428
|
+
actor: this.buildActor(),
|
|
55429
|
+
repository: this.repository,
|
|
55430
|
+
pullRequest: this.pullRequest
|
|
55431
|
+
};
|
|
55432
|
+
}
|
|
55433
|
+
forCapabilityResolve(checkId, capabilities) {
|
|
55434
|
+
return {
|
|
55435
|
+
scope: "capability.resolve",
|
|
55436
|
+
check: { id: checkId, type: "ai" },
|
|
55437
|
+
capability: capabilities,
|
|
55438
|
+
actor: this.buildActor(),
|
|
55439
|
+
repository: this.repository,
|
|
55440
|
+
pullRequest: this.pullRequest
|
|
55441
|
+
};
|
|
55442
|
+
}
|
|
55443
|
+
};
|
|
55444
|
+
}
|
|
55445
|
+
});
|
|
55446
|
+
|
|
55447
|
+
// src/enterprise/policy/opa-policy-engine.ts
|
|
55448
|
+
var opa_policy_engine_exports = {};
|
|
55449
|
+
__export(opa_policy_engine_exports, {
|
|
55450
|
+
OpaPolicyEngine: () => OpaPolicyEngine
|
|
55451
|
+
});
|
|
55452
|
+
var OpaPolicyEngine;
|
|
55453
|
+
var init_opa_policy_engine = __esm({
|
|
55454
|
+
"src/enterprise/policy/opa-policy-engine.ts"() {
|
|
55455
|
+
"use strict";
|
|
55456
|
+
init_opa_wasm_evaluator();
|
|
55457
|
+
init_opa_http_evaluator();
|
|
55458
|
+
init_policy_input_builder();
|
|
55459
|
+
OpaPolicyEngine = class {
|
|
55460
|
+
evaluator = null;
|
|
55461
|
+
fallback;
|
|
55462
|
+
timeout;
|
|
55463
|
+
config;
|
|
55464
|
+
inputBuilder = null;
|
|
55465
|
+
logger = null;
|
|
55466
|
+
constructor(config) {
|
|
55467
|
+
this.config = config;
|
|
55468
|
+
this.fallback = config.fallback || "deny";
|
|
55469
|
+
this.timeout = config.timeout || 5e3;
|
|
55470
|
+
}
|
|
55471
|
+
async initialize(config) {
|
|
55472
|
+
try {
|
|
55473
|
+
this.logger = (init_logger(), __toCommonJS(logger_exports)).logger;
|
|
55474
|
+
} catch {
|
|
55475
|
+
}
|
|
55476
|
+
const actor = {
|
|
55477
|
+
authorAssociation: process.env.VISOR_AUTHOR_ASSOCIATION,
|
|
55478
|
+
login: process.env.VISOR_AUTHOR_LOGIN || process.env.GITHUB_ACTOR,
|
|
55479
|
+
isLocalMode: !process.env.GITHUB_ACTIONS
|
|
55480
|
+
};
|
|
55481
|
+
const repo = {
|
|
55482
|
+
owner: process.env.GITHUB_REPOSITORY_OWNER,
|
|
55483
|
+
name: process.env.GITHUB_REPOSITORY?.split("/")[1],
|
|
55484
|
+
branch: process.env.GITHUB_HEAD_REF,
|
|
55485
|
+
baseBranch: process.env.GITHUB_BASE_REF,
|
|
55486
|
+
event: process.env.GITHUB_EVENT_NAME
|
|
55487
|
+
};
|
|
55488
|
+
const prNum = process.env.GITHUB_PR_NUMBER ? parseInt(process.env.GITHUB_PR_NUMBER, 10) : void 0;
|
|
55489
|
+
const pullRequest = {
|
|
55490
|
+
number: prNum !== void 0 && Number.isFinite(prNum) ? prNum : void 0
|
|
55491
|
+
};
|
|
55492
|
+
this.inputBuilder = new PolicyInputBuilder(config, actor, repo, pullRequest);
|
|
55493
|
+
if (config.engine === "local") {
|
|
55494
|
+
if (!config.rules) {
|
|
55495
|
+
throw new Error("OPA local mode requires `policy.rules` path to .wasm or .rego files");
|
|
55496
|
+
}
|
|
55497
|
+
const wasm = new OpaWasmEvaluator();
|
|
55498
|
+
await wasm.initialize(config.rules);
|
|
55499
|
+
if (config.data) {
|
|
55500
|
+
wasm.loadData(config.data);
|
|
55501
|
+
}
|
|
55502
|
+
this.evaluator = wasm;
|
|
55503
|
+
} else if (config.engine === "remote") {
|
|
55504
|
+
if (!config.url) {
|
|
55505
|
+
throw new Error("OPA remote mode requires `policy.url` pointing to OPA server");
|
|
55506
|
+
}
|
|
55507
|
+
this.evaluator = new OpaHttpEvaluator(config.url, this.timeout);
|
|
55508
|
+
} else {
|
|
55509
|
+
this.evaluator = null;
|
|
55510
|
+
}
|
|
55511
|
+
}
|
|
55512
|
+
/**
|
|
55513
|
+
* Update actor/repo/PR context (e.g., after PR info becomes available).
|
|
55514
|
+
* Called by the enterprise loader when engine context is enriched.
|
|
55515
|
+
*/
|
|
55516
|
+
setActorContext(actor, repo, pullRequest) {
|
|
55517
|
+
this.inputBuilder = new PolicyInputBuilder(this.config, actor, repo, pullRequest);
|
|
55518
|
+
}
|
|
55519
|
+
async evaluateCheckExecution(checkId, checkConfig) {
|
|
55520
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
55521
|
+
const cfg = checkConfig && typeof checkConfig === "object" ? checkConfig : {};
|
|
55522
|
+
const policyOverride = cfg.policy;
|
|
55523
|
+
const input = this.inputBuilder.forCheckExecution({
|
|
55524
|
+
id: checkId,
|
|
55525
|
+
type: cfg.type || "ai",
|
|
55526
|
+
group: cfg.group,
|
|
55527
|
+
tags: cfg.tags,
|
|
55528
|
+
criticality: cfg.criticality,
|
|
55529
|
+
sandbox: cfg.sandbox,
|
|
55530
|
+
policy: policyOverride
|
|
55531
|
+
});
|
|
55532
|
+
return this.doEvaluate(input, this.resolveRulePath("check.execute", policyOverride?.rule));
|
|
55533
|
+
}
|
|
55534
|
+
async evaluateToolInvocation(serverName, methodName, transport) {
|
|
55535
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
55536
|
+
const input = this.inputBuilder.forToolInvocation(serverName, methodName, transport);
|
|
55537
|
+
return this.doEvaluate(input, "visor/tool/invoke");
|
|
55538
|
+
}
|
|
55539
|
+
async evaluateCapabilities(checkId, capabilities) {
|
|
55540
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
55541
|
+
const input = this.inputBuilder.forCapabilityResolve(checkId, capabilities);
|
|
55542
|
+
return this.doEvaluate(input, "visor/capability/resolve");
|
|
55543
|
+
}
|
|
55544
|
+
async shutdown() {
|
|
55545
|
+
if (this.evaluator && "shutdown" in this.evaluator) {
|
|
55546
|
+
await this.evaluator.shutdown();
|
|
55547
|
+
}
|
|
55548
|
+
this.evaluator = null;
|
|
55549
|
+
this.inputBuilder = null;
|
|
55550
|
+
}
|
|
55551
|
+
resolveRulePath(defaultScope, override) {
|
|
55552
|
+
if (override) {
|
|
55553
|
+
return override.startsWith("visor/") ? override : `visor/${override}`;
|
|
55554
|
+
}
|
|
55555
|
+
return `visor/${defaultScope.replace(/\./g, "/")}`;
|
|
55556
|
+
}
|
|
55557
|
+
async doEvaluate(input, rulePath) {
|
|
55558
|
+
try {
|
|
55559
|
+
this.logger?.debug(`[PolicyEngine] Evaluating ${rulePath}`, JSON.stringify(input));
|
|
55560
|
+
let timer;
|
|
55561
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
55562
|
+
timer = setTimeout(() => reject(new Error("policy evaluation timeout")), this.timeout);
|
|
55563
|
+
});
|
|
55564
|
+
try {
|
|
55565
|
+
const result = await Promise.race([this.rawEvaluate(input, rulePath), timeoutPromise]);
|
|
55566
|
+
const decision = this.parseDecision(result);
|
|
55567
|
+
if (!decision.allowed && this.fallback === "warn") {
|
|
55568
|
+
decision.allowed = true;
|
|
55569
|
+
decision.warn = true;
|
|
55570
|
+
decision.reason = `audit: ${decision.reason || "policy denied"}`;
|
|
55571
|
+
}
|
|
55572
|
+
this.logger?.debug(
|
|
55573
|
+
`[PolicyEngine] Decision for ${rulePath}: allowed=${decision.allowed}, warn=${decision.warn || false}, reason=${decision.reason || "none"}`
|
|
55574
|
+
);
|
|
55575
|
+
return decision;
|
|
55576
|
+
} finally {
|
|
55577
|
+
if (timer) clearTimeout(timer);
|
|
55578
|
+
}
|
|
55579
|
+
} catch (err) {
|
|
55580
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
55581
|
+
this.logger?.warn(`[PolicyEngine] Evaluation failed for ${rulePath}: ${msg}`);
|
|
55582
|
+
return {
|
|
55583
|
+
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
55584
|
+
warn: this.fallback === "warn" ? true : void 0,
|
|
55585
|
+
reason: `policy evaluation failed, fallback=${this.fallback}`
|
|
55586
|
+
};
|
|
55587
|
+
}
|
|
55588
|
+
}
|
|
55589
|
+
async rawEvaluate(input, rulePath) {
|
|
55590
|
+
if (this.evaluator instanceof OpaWasmEvaluator) {
|
|
55591
|
+
const result = await this.evaluator.evaluate(input);
|
|
55592
|
+
return this.navigateWasmResult(result, rulePath);
|
|
55593
|
+
}
|
|
55594
|
+
return this.evaluator.evaluate(input, rulePath);
|
|
55595
|
+
}
|
|
55596
|
+
/**
|
|
55597
|
+
* Navigate nested OPA WASM result tree to reach the specific rule's output.
|
|
55598
|
+
* The WASM entrypoint `-e visor` means the result root IS the visor package,
|
|
55599
|
+
* so we strip the `visor/` prefix and walk the remaining segments.
|
|
55600
|
+
*/
|
|
55601
|
+
navigateWasmResult(result, rulePath) {
|
|
55602
|
+
if (!result || typeof result !== "object") return result;
|
|
55603
|
+
const segments = rulePath.replace(/^visor\//, "").split("/");
|
|
55604
|
+
let current = result;
|
|
55605
|
+
for (const seg of segments) {
|
|
55606
|
+
if (current && typeof current === "object" && seg in current) {
|
|
55607
|
+
current = current[seg];
|
|
55608
|
+
} else {
|
|
55609
|
+
return void 0;
|
|
55610
|
+
}
|
|
55611
|
+
}
|
|
55612
|
+
return current;
|
|
55613
|
+
}
|
|
55614
|
+
parseDecision(result) {
|
|
55615
|
+
if (result === void 0 || result === null) {
|
|
55616
|
+
return {
|
|
55617
|
+
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
55618
|
+
warn: this.fallback === "warn" ? true : void 0,
|
|
55619
|
+
reason: this.fallback === "warn" ? "audit: no policy result" : "no policy result"
|
|
55620
|
+
};
|
|
55621
|
+
}
|
|
55622
|
+
const allowed = result.allowed !== false;
|
|
55623
|
+
const decision = {
|
|
55624
|
+
allowed,
|
|
55625
|
+
reason: result.reason
|
|
55626
|
+
};
|
|
55627
|
+
if (result.capabilities) {
|
|
55628
|
+
decision.capabilities = result.capabilities;
|
|
55629
|
+
}
|
|
55630
|
+
return decision;
|
|
55631
|
+
}
|
|
55632
|
+
};
|
|
55633
|
+
}
|
|
55634
|
+
});
|
|
55635
|
+
|
|
55636
|
+
// src/enterprise/scheduler/knex-store.ts
|
|
55637
|
+
var knex_store_exports = {};
|
|
55638
|
+
__export(knex_store_exports, {
|
|
55639
|
+
KnexStoreBackend: () => KnexStoreBackend
|
|
55640
|
+
});
|
|
55641
|
+
function toNum(val) {
|
|
55642
|
+
if (val === null || val === void 0) return void 0;
|
|
55643
|
+
return typeof val === "string" ? parseInt(val, 10) : val;
|
|
55644
|
+
}
|
|
55645
|
+
function safeJsonParse2(value) {
|
|
55646
|
+
if (!value) return void 0;
|
|
55647
|
+
try {
|
|
55648
|
+
return JSON.parse(value);
|
|
55649
|
+
} catch {
|
|
55650
|
+
return void 0;
|
|
55651
|
+
}
|
|
55652
|
+
}
|
|
55653
|
+
function fromTriggerRow2(row) {
|
|
55654
|
+
return {
|
|
55655
|
+
id: row.id,
|
|
55656
|
+
creatorId: row.creator_id,
|
|
55657
|
+
creatorContext: row.creator_context ?? void 0,
|
|
55658
|
+
creatorName: row.creator_name ?? void 0,
|
|
55659
|
+
description: row.description ?? void 0,
|
|
55660
|
+
channels: safeJsonParse2(row.channels),
|
|
55661
|
+
fromUsers: safeJsonParse2(row.from_users),
|
|
55662
|
+
fromBots: row.from_bots === true || row.from_bots === 1,
|
|
55663
|
+
contains: safeJsonParse2(row.contains),
|
|
55664
|
+
matchPattern: row.match_pattern ?? void 0,
|
|
55665
|
+
threads: row.threads,
|
|
55666
|
+
workflow: row.workflow,
|
|
55667
|
+
inputs: safeJsonParse2(row.inputs),
|
|
55668
|
+
outputContext: safeJsonParse2(row.output_context),
|
|
55669
|
+
status: row.status,
|
|
55670
|
+
enabled: row.enabled === true || row.enabled === 1,
|
|
55671
|
+
createdAt: toNum(row.created_at)
|
|
55672
|
+
};
|
|
55673
|
+
}
|
|
55674
|
+
function toTriggerInsertRow(trigger) {
|
|
55675
|
+
return {
|
|
55676
|
+
id: trigger.id,
|
|
55677
|
+
creator_id: trigger.creatorId,
|
|
55678
|
+
creator_context: trigger.creatorContext ?? null,
|
|
55679
|
+
creator_name: trigger.creatorName ?? null,
|
|
55680
|
+
description: trigger.description ?? null,
|
|
55681
|
+
channels: trigger.channels ? JSON.stringify(trigger.channels) : null,
|
|
55682
|
+
from_users: trigger.fromUsers ? JSON.stringify(trigger.fromUsers) : null,
|
|
55683
|
+
from_bots: trigger.fromBots,
|
|
55684
|
+
contains: trigger.contains ? JSON.stringify(trigger.contains) : null,
|
|
55685
|
+
match_pattern: trigger.matchPattern ?? null,
|
|
55686
|
+
threads: trigger.threads,
|
|
55687
|
+
workflow: trigger.workflow,
|
|
55688
|
+
inputs: trigger.inputs ? JSON.stringify(trigger.inputs) : null,
|
|
55689
|
+
output_context: trigger.outputContext ? JSON.stringify(trigger.outputContext) : null,
|
|
55690
|
+
status: trigger.status,
|
|
55691
|
+
enabled: trigger.enabled,
|
|
55692
|
+
created_at: trigger.createdAt
|
|
55693
|
+
};
|
|
55694
|
+
}
|
|
55695
|
+
function fromDbRow2(row) {
|
|
55696
|
+
return {
|
|
55697
|
+
id: row.id,
|
|
55698
|
+
creatorId: row.creator_id,
|
|
55699
|
+
creatorContext: row.creator_context ?? void 0,
|
|
55700
|
+
creatorName: row.creator_name ?? void 0,
|
|
55701
|
+
timezone: row.timezone,
|
|
55702
|
+
schedule: row.schedule_expr,
|
|
55703
|
+
runAt: toNum(row.run_at),
|
|
55704
|
+
isRecurring: row.is_recurring === true || row.is_recurring === 1,
|
|
55705
|
+
originalExpression: row.original_expression,
|
|
55706
|
+
workflow: row.workflow ?? void 0,
|
|
55707
|
+
workflowInputs: safeJsonParse2(row.workflow_inputs),
|
|
55708
|
+
outputContext: safeJsonParse2(row.output_context),
|
|
55709
|
+
status: row.status,
|
|
55710
|
+
createdAt: toNum(row.created_at),
|
|
55711
|
+
lastRunAt: toNum(row.last_run_at),
|
|
55712
|
+
nextRunAt: toNum(row.next_run_at),
|
|
55713
|
+
runCount: row.run_count,
|
|
55714
|
+
failureCount: row.failure_count,
|
|
55715
|
+
lastError: row.last_error ?? void 0,
|
|
55716
|
+
previousResponse: row.previous_response ?? void 0
|
|
55717
|
+
};
|
|
55718
|
+
}
|
|
55719
|
+
function toInsertRow(schedule) {
|
|
55720
|
+
return {
|
|
55721
|
+
id: schedule.id,
|
|
55722
|
+
creator_id: schedule.creatorId,
|
|
55723
|
+
creator_context: schedule.creatorContext ?? null,
|
|
55724
|
+
creator_name: schedule.creatorName ?? null,
|
|
55725
|
+
timezone: schedule.timezone,
|
|
55726
|
+
schedule_expr: schedule.schedule,
|
|
55727
|
+
run_at: schedule.runAt ?? null,
|
|
55728
|
+
is_recurring: schedule.isRecurring,
|
|
55729
|
+
original_expression: schedule.originalExpression,
|
|
55730
|
+
workflow: schedule.workflow ?? null,
|
|
55731
|
+
workflow_inputs: schedule.workflowInputs ? JSON.stringify(schedule.workflowInputs) : null,
|
|
55732
|
+
output_context: schedule.outputContext ? JSON.stringify(schedule.outputContext) : null,
|
|
55733
|
+
status: schedule.status,
|
|
55734
|
+
created_at: schedule.createdAt,
|
|
55735
|
+
last_run_at: schedule.lastRunAt ?? null,
|
|
55736
|
+
next_run_at: schedule.nextRunAt ?? null,
|
|
55737
|
+
run_count: schedule.runCount,
|
|
55738
|
+
failure_count: schedule.failureCount,
|
|
55739
|
+
last_error: schedule.lastError ?? null,
|
|
55740
|
+
previous_response: schedule.previousResponse ?? null
|
|
55741
|
+
};
|
|
55742
|
+
}
|
|
55743
|
+
var fs24, path28, import_uuid2, KnexStoreBackend;
|
|
55744
|
+
var init_knex_store = __esm({
|
|
55745
|
+
"src/enterprise/scheduler/knex-store.ts"() {
|
|
55746
|
+
"use strict";
|
|
55747
|
+
fs24 = __toESM(require("fs"));
|
|
55748
|
+
path28 = __toESM(require("path"));
|
|
55749
|
+
import_uuid2 = require("uuid");
|
|
55750
|
+
init_logger();
|
|
55751
|
+
KnexStoreBackend = class {
|
|
55752
|
+
knex = null;
|
|
55753
|
+
driver;
|
|
55754
|
+
connection;
|
|
55755
|
+
constructor(driver, storageConfig, _haConfig) {
|
|
55756
|
+
this.driver = driver;
|
|
55757
|
+
this.connection = storageConfig.connection || {};
|
|
55758
|
+
}
|
|
55759
|
+
async initialize() {
|
|
55760
|
+
const { createRequire } = require("module");
|
|
55761
|
+
const runtimeRequire = createRequire(__filename);
|
|
55762
|
+
let knexFactory;
|
|
55763
|
+
try {
|
|
55764
|
+
knexFactory = runtimeRequire("knex");
|
|
55765
|
+
} catch (err) {
|
|
55766
|
+
const code = err?.code;
|
|
55767
|
+
if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
|
|
55768
|
+
throw new Error(
|
|
55769
|
+
"knex is required for PostgreSQL/MySQL/MSSQL schedule storage. Install it with: npm install knex"
|
|
55770
|
+
);
|
|
55771
|
+
}
|
|
55772
|
+
throw err;
|
|
55773
|
+
}
|
|
55774
|
+
const clientMap = {
|
|
55775
|
+
postgresql: "pg",
|
|
55776
|
+
mysql: "mysql2",
|
|
55777
|
+
mssql: "tedious"
|
|
55778
|
+
};
|
|
55779
|
+
const client = clientMap[this.driver];
|
|
55780
|
+
let connection;
|
|
55781
|
+
if (this.connection.connection_string) {
|
|
55782
|
+
connection = this.connection.connection_string;
|
|
55783
|
+
} else if (this.driver === "mssql") {
|
|
55784
|
+
connection = this.buildMssqlConnection();
|
|
55785
|
+
} else {
|
|
55786
|
+
connection = this.buildStandardConnection();
|
|
55787
|
+
}
|
|
55788
|
+
this.knex = knexFactory({
|
|
55789
|
+
client,
|
|
55790
|
+
connection,
|
|
55791
|
+
pool: {
|
|
55792
|
+
min: this.connection.pool?.min ?? 0,
|
|
55793
|
+
max: this.connection.pool?.max ?? 10
|
|
55794
|
+
}
|
|
55795
|
+
});
|
|
55796
|
+
await this.migrateSchema();
|
|
55797
|
+
logger.info(`[KnexStore] Initialized (${this.driver})`);
|
|
55798
|
+
}
|
|
55799
|
+
buildStandardConnection() {
|
|
55800
|
+
return {
|
|
55801
|
+
host: this.connection.host || "localhost",
|
|
55802
|
+
port: this.connection.port,
|
|
55803
|
+
database: this.connection.database || "visor",
|
|
55804
|
+
user: this.connection.user,
|
|
55805
|
+
password: this.connection.password,
|
|
55806
|
+
ssl: this.resolveSslConfig()
|
|
55807
|
+
};
|
|
55808
|
+
}
|
|
55809
|
+
buildMssqlConnection() {
|
|
55810
|
+
const ssl = this.connection.ssl;
|
|
55811
|
+
const sslEnabled = ssl === true || typeof ssl === "object" && ssl.enabled !== false;
|
|
55812
|
+
return {
|
|
55813
|
+
server: this.connection.host || "localhost",
|
|
55814
|
+
port: this.connection.port,
|
|
55815
|
+
database: this.connection.database || "visor",
|
|
55816
|
+
user: this.connection.user,
|
|
55817
|
+
password: this.connection.password,
|
|
55818
|
+
options: {
|
|
55819
|
+
encrypt: sslEnabled,
|
|
55820
|
+
trustServerCertificate: typeof ssl === "object" ? ssl.reject_unauthorized === false : !sslEnabled
|
|
55821
|
+
}
|
|
55822
|
+
};
|
|
55823
|
+
}
|
|
55824
|
+
resolveSslConfig() {
|
|
55825
|
+
const ssl = this.connection.ssl;
|
|
55826
|
+
if (ssl === false || ssl === void 0) return false;
|
|
55827
|
+
if (ssl === true) return { rejectUnauthorized: true };
|
|
55828
|
+
if (ssl.enabled === false) return false;
|
|
55829
|
+
const result = {
|
|
55830
|
+
rejectUnauthorized: ssl.reject_unauthorized !== false
|
|
55831
|
+
};
|
|
55832
|
+
if (ssl.ca) {
|
|
55833
|
+
const caPath = this.validateSslPath(ssl.ca, "CA certificate");
|
|
55834
|
+
result.ca = fs24.readFileSync(caPath, "utf8");
|
|
55835
|
+
}
|
|
55836
|
+
if (ssl.cert) {
|
|
55837
|
+
const certPath = this.validateSslPath(ssl.cert, "client certificate");
|
|
55838
|
+
result.cert = fs24.readFileSync(certPath, "utf8");
|
|
55839
|
+
}
|
|
55840
|
+
if (ssl.key) {
|
|
55841
|
+
const keyPath = this.validateSslPath(ssl.key, "client key");
|
|
55842
|
+
result.key = fs24.readFileSync(keyPath, "utf8");
|
|
55843
|
+
}
|
|
55844
|
+
return result;
|
|
55845
|
+
}
|
|
55846
|
+
validateSslPath(filePath, label) {
|
|
55847
|
+
const resolved = path28.resolve(filePath);
|
|
55848
|
+
if (resolved !== path28.normalize(resolved)) {
|
|
55849
|
+
throw new Error(`SSL ${label} path contains invalid sequences: ${filePath}`);
|
|
55850
|
+
}
|
|
55851
|
+
if (!fs24.existsSync(resolved)) {
|
|
55852
|
+
throw new Error(`SSL ${label} not found: ${filePath}`);
|
|
55853
|
+
}
|
|
55854
|
+
return resolved;
|
|
55855
|
+
}
|
|
55856
|
+
async shutdown() {
|
|
55857
|
+
if (this.knex) {
|
|
55858
|
+
await this.knex.destroy();
|
|
55859
|
+
this.knex = null;
|
|
55860
|
+
}
|
|
55861
|
+
}
|
|
55862
|
+
async migrateSchema() {
|
|
55863
|
+
const knex = this.getKnex();
|
|
55864
|
+
const exists = await knex.schema.hasTable("schedules");
|
|
55865
|
+
if (!exists) {
|
|
55866
|
+
await knex.schema.createTable("schedules", (table) => {
|
|
55867
|
+
table.string("id", 36).primary();
|
|
55868
|
+
table.string("creator_id", 255).notNullable().index();
|
|
55869
|
+
table.string("creator_context", 255);
|
|
55870
|
+
table.string("creator_name", 255);
|
|
55871
|
+
table.string("timezone", 64).notNullable().defaultTo("UTC");
|
|
55872
|
+
table.string("schedule_expr", 255);
|
|
55873
|
+
table.bigInteger("run_at");
|
|
55874
|
+
table.boolean("is_recurring").notNullable();
|
|
55875
|
+
table.text("original_expression");
|
|
55876
|
+
table.string("workflow", 255);
|
|
55877
|
+
table.text("workflow_inputs");
|
|
55878
|
+
table.text("output_context");
|
|
55879
|
+
table.string("status", 20).notNullable().index();
|
|
55880
|
+
table.bigInteger("created_at").notNullable();
|
|
55881
|
+
table.bigInteger("last_run_at");
|
|
55882
|
+
table.bigInteger("next_run_at");
|
|
55883
|
+
table.integer("run_count").notNullable().defaultTo(0);
|
|
55884
|
+
table.integer("failure_count").notNullable().defaultTo(0);
|
|
55885
|
+
table.text("last_error");
|
|
55886
|
+
table.text("previous_response");
|
|
55887
|
+
table.index(["status", "next_run_at"]);
|
|
55888
|
+
});
|
|
55889
|
+
}
|
|
55890
|
+
const triggersExist = await knex.schema.hasTable("message_triggers");
|
|
55891
|
+
if (!triggersExist) {
|
|
55892
|
+
await knex.schema.createTable("message_triggers", (table) => {
|
|
55893
|
+
table.string("id", 36).primary();
|
|
55894
|
+
table.string("creator_id", 255).notNullable().index();
|
|
55895
|
+
table.string("creator_context", 255);
|
|
55896
|
+
table.string("creator_name", 255);
|
|
55897
|
+
table.text("description");
|
|
55898
|
+
table.text("channels");
|
|
55899
|
+
table.text("from_users");
|
|
55900
|
+
table.boolean("from_bots").notNullable().defaultTo(false);
|
|
55901
|
+
table.text("contains");
|
|
55902
|
+
table.text("match_pattern");
|
|
55903
|
+
table.string("threads", 20).notNullable().defaultTo("any");
|
|
55904
|
+
table.string("workflow", 255).notNullable();
|
|
55905
|
+
table.text("inputs");
|
|
55906
|
+
table.text("output_context");
|
|
55907
|
+
table.string("status", 20).notNullable().defaultTo("active").index();
|
|
55908
|
+
table.boolean("enabled").notNullable().defaultTo(true);
|
|
55909
|
+
table.bigInteger("created_at").notNullable();
|
|
55910
|
+
});
|
|
55911
|
+
}
|
|
55912
|
+
const locksExist = await knex.schema.hasTable("scheduler_locks");
|
|
55913
|
+
if (!locksExist) {
|
|
55914
|
+
await knex.schema.createTable("scheduler_locks", (table) => {
|
|
55915
|
+
table.string("lock_id", 255).primary();
|
|
55916
|
+
table.string("node_id", 255).notNullable();
|
|
55917
|
+
table.string("lock_token", 36).notNullable();
|
|
55918
|
+
table.bigInteger("acquired_at").notNullable();
|
|
55919
|
+
table.bigInteger("expires_at").notNullable();
|
|
55920
|
+
});
|
|
55921
|
+
}
|
|
55922
|
+
}
|
|
55923
|
+
getKnex() {
|
|
55924
|
+
if (!this.knex) {
|
|
55925
|
+
throw new Error("[KnexStore] Not initialized. Call initialize() first.");
|
|
55926
|
+
}
|
|
55927
|
+
return this.knex;
|
|
55928
|
+
}
|
|
55929
|
+
// --- CRUD ---
|
|
55930
|
+
async create(schedule) {
|
|
55931
|
+
const knex = this.getKnex();
|
|
55932
|
+
const newSchedule = {
|
|
55933
|
+
...schedule,
|
|
55934
|
+
id: (0, import_uuid2.v4)(),
|
|
55935
|
+
createdAt: Date.now(),
|
|
55936
|
+
runCount: 0,
|
|
55937
|
+
failureCount: 0,
|
|
55938
|
+
status: "active"
|
|
55939
|
+
};
|
|
55940
|
+
await knex("schedules").insert(toInsertRow(newSchedule));
|
|
55941
|
+
logger.info(`[KnexStore] Created schedule ${newSchedule.id} for user ${newSchedule.creatorId}`);
|
|
55942
|
+
return newSchedule;
|
|
55943
|
+
}
|
|
55944
|
+
async importSchedule(schedule) {
|
|
55945
|
+
const knex = this.getKnex();
|
|
55946
|
+
const existing = await knex("schedules").where("id", schedule.id).first();
|
|
55947
|
+
if (existing) return;
|
|
55948
|
+
await knex("schedules").insert(toInsertRow(schedule));
|
|
55949
|
+
}
|
|
55950
|
+
async get(id) {
|
|
55951
|
+
const knex = this.getKnex();
|
|
55952
|
+
const row = await knex("schedules").where("id", id).first();
|
|
55953
|
+
return row ? fromDbRow2(row) : void 0;
|
|
55954
|
+
}
|
|
55955
|
+
async update(id, patch) {
|
|
55956
|
+
const knex = this.getKnex();
|
|
55957
|
+
const existing = await knex("schedules").where("id", id).first();
|
|
55958
|
+
if (!existing) return void 0;
|
|
55959
|
+
const current = fromDbRow2(existing);
|
|
55960
|
+
const updated = { ...current, ...patch, id: current.id };
|
|
55961
|
+
const row = toInsertRow(updated);
|
|
55962
|
+
delete row.id;
|
|
55963
|
+
await knex("schedules").where("id", id).update(row);
|
|
55964
|
+
return updated;
|
|
55965
|
+
}
|
|
55966
|
+
async delete(id) {
|
|
55967
|
+
const knex = this.getKnex();
|
|
55968
|
+
const deleted = await knex("schedules").where("id", id).del();
|
|
55969
|
+
if (deleted > 0) {
|
|
55970
|
+
logger.info(`[KnexStore] Deleted schedule ${id}`);
|
|
55971
|
+
return true;
|
|
55972
|
+
}
|
|
55973
|
+
return false;
|
|
55974
|
+
}
|
|
55975
|
+
// --- Queries ---
|
|
55976
|
+
async getByCreator(creatorId) {
|
|
55977
|
+
const knex = this.getKnex();
|
|
55978
|
+
const rows = await knex("schedules").where("creator_id", creatorId);
|
|
55979
|
+
return rows.map((r) => fromDbRow2(r));
|
|
55980
|
+
}
|
|
55981
|
+
async getActiveSchedules() {
|
|
55982
|
+
const knex = this.getKnex();
|
|
55983
|
+
const rows = await knex("schedules").where("status", "active");
|
|
55984
|
+
return rows.map((r) => fromDbRow2(r));
|
|
55985
|
+
}
|
|
55986
|
+
async getDueSchedules(now) {
|
|
55987
|
+
const ts = now ?? Date.now();
|
|
55988
|
+
const knex = this.getKnex();
|
|
55989
|
+
const bFalse = this.driver === "mssql" ? 0 : false;
|
|
55990
|
+
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
55991
|
+
const rows = await knex("schedules").where("status", "active").andWhere(function() {
|
|
55992
|
+
this.where(function() {
|
|
55993
|
+
this.where("is_recurring", bFalse).whereNotNull("run_at").where("run_at", "<=", ts);
|
|
55994
|
+
}).orWhere(function() {
|
|
55995
|
+
this.where("is_recurring", bTrue).whereNotNull("next_run_at").where("next_run_at", "<=", ts);
|
|
55996
|
+
});
|
|
55997
|
+
});
|
|
55998
|
+
return rows.map((r) => fromDbRow2(r));
|
|
55999
|
+
}
|
|
56000
|
+
async findByWorkflow(creatorId, workflowName) {
|
|
56001
|
+
const knex = this.getKnex();
|
|
56002
|
+
const escaped = workflowName.toLowerCase().replace(/[%_\\]/g, "\\$&");
|
|
56003
|
+
const pattern = `%${escaped}%`;
|
|
56004
|
+
const rows = await knex("schedules").where("creator_id", creatorId).where("status", "active").whereRaw("LOWER(workflow) LIKE ? ESCAPE '\\'", [pattern]);
|
|
56005
|
+
return rows.map((r) => fromDbRow2(r));
|
|
56006
|
+
}
|
|
56007
|
+
async getAll() {
|
|
56008
|
+
const knex = this.getKnex();
|
|
56009
|
+
const rows = await knex("schedules");
|
|
56010
|
+
return rows.map((r) => fromDbRow2(r));
|
|
56011
|
+
}
|
|
56012
|
+
async getStats() {
|
|
56013
|
+
const knex = this.getKnex();
|
|
56014
|
+
const boolTrue = this.driver === "mssql" ? "1" : "true";
|
|
56015
|
+
const boolFalse = this.driver === "mssql" ? "0" : "false";
|
|
56016
|
+
const result = await knex("schedules").select(
|
|
56017
|
+
knex.raw("COUNT(*) as total"),
|
|
56018
|
+
knex.raw("SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active"),
|
|
56019
|
+
knex.raw("SUM(CASE WHEN status = 'paused' THEN 1 ELSE 0 END) as paused"),
|
|
56020
|
+
knex.raw("SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed"),
|
|
56021
|
+
knex.raw("SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed"),
|
|
56022
|
+
knex.raw(`SUM(CASE WHEN is_recurring = ${boolTrue} THEN 1 ELSE 0 END) as recurring`),
|
|
56023
|
+
knex.raw(`SUM(CASE WHEN is_recurring = ${boolFalse} THEN 1 ELSE 0 END) as one_time`)
|
|
56024
|
+
).first();
|
|
56025
|
+
return {
|
|
56026
|
+
total: Number(result.total) || 0,
|
|
56027
|
+
active: Number(result.active) || 0,
|
|
56028
|
+
paused: Number(result.paused) || 0,
|
|
56029
|
+
completed: Number(result.completed) || 0,
|
|
56030
|
+
failed: Number(result.failed) || 0,
|
|
56031
|
+
recurring: Number(result.recurring) || 0,
|
|
56032
|
+
oneTime: Number(result.one_time) || 0
|
|
56033
|
+
};
|
|
56034
|
+
}
|
|
56035
|
+
async validateLimits(creatorId, isRecurring, limits) {
|
|
56036
|
+
const knex = this.getKnex();
|
|
56037
|
+
if (limits.maxGlobal) {
|
|
56038
|
+
const result = await knex("schedules").count("* as cnt").first();
|
|
56039
|
+
if (Number(result?.cnt) >= limits.maxGlobal) {
|
|
56040
|
+
throw new Error(`Global schedule limit reached (${limits.maxGlobal})`);
|
|
56041
|
+
}
|
|
56042
|
+
}
|
|
56043
|
+
if (limits.maxPerUser) {
|
|
56044
|
+
const result = await knex("schedules").where("creator_id", creatorId).count("* as cnt").first();
|
|
56045
|
+
if (Number(result?.cnt) >= limits.maxPerUser) {
|
|
56046
|
+
throw new Error(`You have reached the maximum number of schedules (${limits.maxPerUser})`);
|
|
56047
|
+
}
|
|
56048
|
+
}
|
|
56049
|
+
if (isRecurring && limits.maxRecurringPerUser) {
|
|
56050
|
+
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
56051
|
+
const result = await knex("schedules").where("creator_id", creatorId).where("is_recurring", bTrue).count("* as cnt").first();
|
|
56052
|
+
if (Number(result?.cnt) >= limits.maxRecurringPerUser) {
|
|
56053
|
+
throw new Error(
|
|
56054
|
+
`You have reached the maximum number of recurring schedules (${limits.maxRecurringPerUser})`
|
|
56055
|
+
);
|
|
56056
|
+
}
|
|
56057
|
+
}
|
|
56058
|
+
}
|
|
56059
|
+
// --- HA Distributed Locking (via scheduler_locks table) ---
|
|
56060
|
+
async tryAcquireLock(lockId, nodeId, ttlSeconds) {
|
|
56061
|
+
const knex = this.getKnex();
|
|
56062
|
+
const now = Date.now();
|
|
56063
|
+
const expiresAt = now + ttlSeconds * 1e3;
|
|
56064
|
+
const token = (0, import_uuid2.v4)();
|
|
56065
|
+
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("expires_at", "<", now).update({
|
|
56066
|
+
node_id: nodeId,
|
|
56067
|
+
lock_token: token,
|
|
56068
|
+
acquired_at: now,
|
|
56069
|
+
expires_at: expiresAt
|
|
56070
|
+
});
|
|
56071
|
+
if (updated > 0) return token;
|
|
56072
|
+
try {
|
|
56073
|
+
await knex("scheduler_locks").insert({
|
|
56074
|
+
lock_id: lockId,
|
|
56075
|
+
node_id: nodeId,
|
|
56076
|
+
lock_token: token,
|
|
56077
|
+
acquired_at: now,
|
|
56078
|
+
expires_at: expiresAt
|
|
56079
|
+
});
|
|
56080
|
+
return token;
|
|
56081
|
+
} catch {
|
|
56082
|
+
return null;
|
|
56083
|
+
}
|
|
56084
|
+
}
|
|
56085
|
+
async releaseLock(lockId, lockToken) {
|
|
56086
|
+
const knex = this.getKnex();
|
|
56087
|
+
await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).del();
|
|
56088
|
+
}
|
|
56089
|
+
async renewLock(lockId, lockToken, ttlSeconds) {
|
|
56090
|
+
const knex = this.getKnex();
|
|
56091
|
+
const now = Date.now();
|
|
56092
|
+
const expiresAt = now + ttlSeconds * 1e3;
|
|
56093
|
+
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).update({ acquired_at: now, expires_at: expiresAt });
|
|
56094
|
+
return updated > 0;
|
|
56095
|
+
}
|
|
56096
|
+
async flush() {
|
|
56097
|
+
}
|
|
56098
|
+
// --- Message Trigger CRUD ---
|
|
56099
|
+
async createTrigger(trigger) {
|
|
56100
|
+
const knex = this.getKnex();
|
|
56101
|
+
const newTrigger = {
|
|
56102
|
+
...trigger,
|
|
56103
|
+
id: (0, import_uuid2.v4)(),
|
|
56104
|
+
createdAt: Date.now()
|
|
56105
|
+
};
|
|
56106
|
+
await knex("message_triggers").insert(toTriggerInsertRow(newTrigger));
|
|
56107
|
+
logger.info(`[KnexStore] Created trigger ${newTrigger.id} for user ${newTrigger.creatorId}`);
|
|
56108
|
+
return newTrigger;
|
|
56109
|
+
}
|
|
56110
|
+
async getTrigger(id) {
|
|
56111
|
+
const knex = this.getKnex();
|
|
56112
|
+
const row = await knex("message_triggers").where("id", id).first();
|
|
56113
|
+
return row ? fromTriggerRow2(row) : void 0;
|
|
56114
|
+
}
|
|
56115
|
+
async updateTrigger(id, patch) {
|
|
56116
|
+
const knex = this.getKnex();
|
|
56117
|
+
const existing = await knex("message_triggers").where("id", id).first();
|
|
56118
|
+
if (!existing) return void 0;
|
|
56119
|
+
const current = fromTriggerRow2(existing);
|
|
56120
|
+
const updated = {
|
|
56121
|
+
...current,
|
|
56122
|
+
...patch,
|
|
56123
|
+
id: current.id,
|
|
56124
|
+
createdAt: current.createdAt
|
|
56125
|
+
};
|
|
56126
|
+
const row = toTriggerInsertRow(updated);
|
|
56127
|
+
delete row.id;
|
|
56128
|
+
await knex("message_triggers").where("id", id).update(row);
|
|
56129
|
+
return updated;
|
|
56130
|
+
}
|
|
56131
|
+
async deleteTrigger(id) {
|
|
56132
|
+
const knex = this.getKnex();
|
|
56133
|
+
const deleted = await knex("message_triggers").where("id", id).del();
|
|
56134
|
+
if (deleted > 0) {
|
|
56135
|
+
logger.info(`[KnexStore] Deleted trigger ${id}`);
|
|
56136
|
+
return true;
|
|
56137
|
+
}
|
|
56138
|
+
return false;
|
|
56139
|
+
}
|
|
56140
|
+
async getTriggersByCreator(creatorId) {
|
|
56141
|
+
const knex = this.getKnex();
|
|
56142
|
+
const rows = await knex("message_triggers").where("creator_id", creatorId);
|
|
56143
|
+
return rows.map((r) => fromTriggerRow2(r));
|
|
56144
|
+
}
|
|
56145
|
+
async getActiveTriggers() {
|
|
56146
|
+
const knex = this.getKnex();
|
|
56147
|
+
const rows = await knex("message_triggers").where("status", "active").where("enabled", this.driver === "mssql" ? 1 : true);
|
|
56148
|
+
return rows.map((r) => fromTriggerRow2(r));
|
|
56149
|
+
}
|
|
56150
|
+
};
|
|
56151
|
+
}
|
|
56152
|
+
});
|
|
56153
|
+
|
|
56154
|
+
// src/enterprise/loader.ts
|
|
56155
|
+
var loader_exports = {};
|
|
56156
|
+
__export(loader_exports, {
|
|
56157
|
+
loadEnterprisePolicyEngine: () => loadEnterprisePolicyEngine,
|
|
56158
|
+
loadEnterpriseStoreBackend: () => loadEnterpriseStoreBackend
|
|
56159
|
+
});
|
|
56160
|
+
async function loadEnterprisePolicyEngine(config) {
|
|
56161
|
+
try {
|
|
56162
|
+
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
56163
|
+
const validator = new LicenseValidator2();
|
|
56164
|
+
const license = await validator.loadAndValidate();
|
|
56165
|
+
if (!license || !validator.hasFeature("policy")) {
|
|
56166
|
+
return new DefaultPolicyEngine();
|
|
56167
|
+
}
|
|
56168
|
+
if (validator.isInGracePeriod()) {
|
|
56169
|
+
console.warn(
|
|
56170
|
+
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
56171
|
+
);
|
|
56172
|
+
}
|
|
56173
|
+
const { OpaPolicyEngine: OpaPolicyEngine2 } = await Promise.resolve().then(() => (init_opa_policy_engine(), opa_policy_engine_exports));
|
|
56174
|
+
const engine = new OpaPolicyEngine2(config);
|
|
56175
|
+
await engine.initialize(config);
|
|
56176
|
+
return engine;
|
|
56177
|
+
} catch (err) {
|
|
56178
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
56179
|
+
try {
|
|
56180
|
+
const { logger: logger2 } = (init_logger(), __toCommonJS(logger_exports));
|
|
56181
|
+
logger2.warn(`[PolicyEngine] Enterprise policy init failed, falling back to default: ${msg}`);
|
|
56182
|
+
} catch {
|
|
56183
|
+
}
|
|
56184
|
+
return new DefaultPolicyEngine();
|
|
56185
|
+
}
|
|
56186
|
+
}
|
|
56187
|
+
async function loadEnterpriseStoreBackend(driver, storageConfig, haConfig) {
|
|
56188
|
+
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
56189
|
+
const validator = new LicenseValidator2();
|
|
56190
|
+
const license = await validator.loadAndValidate();
|
|
56191
|
+
if (!license || !validator.hasFeature("scheduler-sql")) {
|
|
56192
|
+
throw new Error(
|
|
56193
|
+
`The ${driver} schedule storage driver requires a Visor Enterprise license with the 'scheduler-sql' feature. Please upgrade or use driver: 'sqlite' (default).`
|
|
56194
|
+
);
|
|
56195
|
+
}
|
|
56196
|
+
if (validator.isInGracePeriod()) {
|
|
56197
|
+
console.warn(
|
|
56198
|
+
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
56199
|
+
);
|
|
56200
|
+
}
|
|
56201
|
+
const { KnexStoreBackend: KnexStoreBackend2 } = await Promise.resolve().then(() => (init_knex_store(), knex_store_exports));
|
|
56202
|
+
return new KnexStoreBackend2(driver, storageConfig, haConfig);
|
|
56203
|
+
}
|
|
56204
|
+
var init_loader = __esm({
|
|
56205
|
+
"src/enterprise/loader.ts"() {
|
|
56206
|
+
"use strict";
|
|
56207
|
+
init_default_engine();
|
|
56208
|
+
}
|
|
56209
|
+
});
|
|
56210
|
+
|
|
54815
56211
|
// src/event-bus/event-bus.ts
|
|
54816
56212
|
var event_bus_exports = {};
|
|
54817
56213
|
__export(event_bus_exports, {
|
|
@@ -55718,8 +57114,8 @@ ${content}
|
|
|
55718
57114
|
* Sleep utility
|
|
55719
57115
|
*/
|
|
55720
57116
|
sleep(ms) {
|
|
55721
|
-
return new Promise((
|
|
55722
|
-
const t = setTimeout(
|
|
57117
|
+
return new Promise((resolve19) => {
|
|
57118
|
+
const t = setTimeout(resolve19, ms);
|
|
55723
57119
|
if (typeof t.unref === "function") {
|
|
55724
57120
|
try {
|
|
55725
57121
|
t.unref();
|
|
@@ -56004,8 +57400,8 @@ ${end}`);
|
|
|
56004
57400
|
async updateGroupedComment(ctx, comments, group, changedIds) {
|
|
56005
57401
|
const existingLock = this.updateLocks.get(group);
|
|
56006
57402
|
let resolveLock;
|
|
56007
|
-
const ourLock = new Promise((
|
|
56008
|
-
resolveLock =
|
|
57403
|
+
const ourLock = new Promise((resolve19) => {
|
|
57404
|
+
resolveLock = resolve19;
|
|
56009
57405
|
});
|
|
56010
57406
|
this.updateLocks.set(group, ourLock);
|
|
56011
57407
|
try {
|
|
@@ -56318,7 +57714,7 @@ ${blocks}
|
|
|
56318
57714
|
* Sleep utility for enforcing delays
|
|
56319
57715
|
*/
|
|
56320
57716
|
sleep(ms) {
|
|
56321
|
-
return new Promise((
|
|
57717
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
56322
57718
|
}
|
|
56323
57719
|
};
|
|
56324
57720
|
}
|
|
@@ -57610,15 +59006,15 @@ function serializeRunState(state) {
|
|
|
57610
59006
|
])
|
|
57611
59007
|
};
|
|
57612
59008
|
}
|
|
57613
|
-
var
|
|
59009
|
+
var path30, fs26, StateMachineExecutionEngine;
|
|
57614
59010
|
var init_state_machine_execution_engine = __esm({
|
|
57615
59011
|
"src/state-machine-execution-engine.ts"() {
|
|
57616
59012
|
"use strict";
|
|
57617
59013
|
init_runner();
|
|
57618
59014
|
init_logger();
|
|
57619
59015
|
init_sandbox_manager();
|
|
57620
|
-
|
|
57621
|
-
|
|
59016
|
+
path30 = __toESM(require("path"));
|
|
59017
|
+
fs26 = __toESM(require("fs"));
|
|
57622
59018
|
StateMachineExecutionEngine = class _StateMachineExecutionEngine {
|
|
57623
59019
|
workingDirectory;
|
|
57624
59020
|
executionContext;
|
|
@@ -57850,8 +59246,8 @@ var init_state_machine_execution_engine = __esm({
|
|
|
57850
59246
|
logger.debug(
|
|
57851
59247
|
`[PolicyEngine] Loading enterprise policy engine (engine=${configWithTagFilter.policy.engine})`
|
|
57852
59248
|
);
|
|
57853
|
-
const { loadEnterprisePolicyEngine } = await
|
|
57854
|
-
context2.policyEngine = await
|
|
59249
|
+
const { loadEnterprisePolicyEngine: loadEnterprisePolicyEngine2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
59250
|
+
context2.policyEngine = await loadEnterprisePolicyEngine2(configWithTagFilter.policy);
|
|
57855
59251
|
logger.debug(
|
|
57856
59252
|
`[PolicyEngine] Initialized: ${context2.policyEngine?.constructor?.name || "unknown"}`
|
|
57857
59253
|
);
|
|
@@ -58003,9 +59399,9 @@ var init_state_machine_execution_engine = __esm({
|
|
|
58003
59399
|
}
|
|
58004
59400
|
const checkId = String(ev?.checkId || "unknown");
|
|
58005
59401
|
const threadKey = ev?.threadKey || (channel && threadTs ? `${channel}:${threadTs}` : "session");
|
|
58006
|
-
const baseDir = process.env.VISOR_SNAPSHOT_DIR ||
|
|
58007
|
-
|
|
58008
|
-
const filePath =
|
|
59402
|
+
const baseDir = process.env.VISOR_SNAPSHOT_DIR || path30.resolve(process.cwd(), ".visor", "snapshots");
|
|
59403
|
+
fs26.mkdirSync(baseDir, { recursive: true });
|
|
59404
|
+
const filePath = path30.join(baseDir, `${threadKey}-${checkId}.json`);
|
|
58009
59405
|
await this.saveSnapshotToFile(filePath);
|
|
58010
59406
|
logger.info(`[Snapshot] Saved run snapshot: ${filePath}`);
|
|
58011
59407
|
try {
|
|
@@ -58146,7 +59542,7 @@ var init_state_machine_execution_engine = __esm({
|
|
|
58146
59542
|
* Does not include secrets. Intended for debugging and future resume support.
|
|
58147
59543
|
*/
|
|
58148
59544
|
async saveSnapshotToFile(filePath) {
|
|
58149
|
-
const
|
|
59545
|
+
const fs27 = await import("fs/promises");
|
|
58150
59546
|
const ctx = this._lastContext;
|
|
58151
59547
|
const runner = this._lastRunner;
|
|
58152
59548
|
if (!ctx || !runner) {
|
|
@@ -58166,14 +59562,14 @@ var init_state_machine_execution_engine = __esm({
|
|
|
58166
59562
|
journal: entries,
|
|
58167
59563
|
requestedChecks: ctx.requestedChecks || []
|
|
58168
59564
|
};
|
|
58169
|
-
await
|
|
59565
|
+
await fs27.writeFile(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
58170
59566
|
}
|
|
58171
59567
|
/**
|
|
58172
59568
|
* Load a snapshot JSON from file and return it. Resume support can build on this.
|
|
58173
59569
|
*/
|
|
58174
59570
|
async loadSnapshotFromFile(filePath) {
|
|
58175
|
-
const
|
|
58176
|
-
const raw = await
|
|
59571
|
+
const fs27 = await import("fs/promises");
|
|
59572
|
+
const raw = await fs27.readFile(filePath, "utf8");
|
|
58177
59573
|
return JSON.parse(raw);
|
|
58178
59574
|
}
|
|
58179
59575
|
/**
|