@probelabs/visor 0.1.167 → 0.1.168-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/defaults/code-talk.yaml +3 -8
- package/dist/defaults/code-talk.yaml +3 -8
- package/dist/index.js +1857 -32
- package/dist/sdk/{check-provider-registry-GPV5DYN5.mjs → check-provider-registry-OJNYM7I6.mjs} +5 -5
- package/dist/sdk/{check-provider-registry-P356JWTA.mjs → check-provider-registry-TVZL4EDZ.mjs} +5 -5
- package/dist/sdk/{chunk-YSQV7N5H.mjs → chunk-6UY7MK7Z.mjs} +17 -17
- package/dist/sdk/chunk-6UY7MK7Z.mjs.map +1 -0
- package/dist/sdk/{chunk-E7NRUDWL.mjs → chunk-FUO4IFQD.mjs} +2 -2
- package/dist/sdk/{chunk-RV5SK4FZ.mjs → chunk-JT5DGR4J.mjs} +3 -3
- package/dist/sdk/{chunk-T5USZCCM.mjs → chunk-MVKLVG5R.mjs} +2 -2
- package/dist/sdk/{chunk-T5USZCCM.mjs.map → chunk-MVKLVG5R.mjs.map} +1 -1
- package/dist/sdk/{chunk-2G2PJKHM.mjs → chunk-QERE2WXY.mjs} +16 -16
- package/dist/sdk/chunk-QERE2WXY.mjs.map +1 -0
- package/dist/sdk/{failure-condition-evaluator-VWQ54IK4.mjs → failure-condition-evaluator-HPUEA3XS.mjs} +3 -3
- package/dist/sdk/{github-frontend-SOVBEAK4.mjs → github-frontend-QZ4CF563.mjs} +3 -3
- package/dist/sdk/{host-7MGCKSHM.mjs → host-L4Q3U2XG.mjs} +2 -2
- package/dist/sdk/{host-JHMDZR6P.mjs → host-P65NNMYN.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-3WG46XWU.mjs → routing-R4DGYG6Y.mjs} +4 -4
- package/dist/sdk/{schedule-tool-MPHHE2IM.mjs → schedule-tool-FRWG5RG5.mjs} +5 -5
- package/dist/sdk/{schedule-tool-SPJWY2Y2.mjs → schedule-tool-ZLRHDABX.mjs} +5 -5
- package/dist/sdk/{schedule-tool-handler-SUYGQJ63.mjs → schedule-tool-handler-LJDYKV3G.mjs} +5 -5
- package/dist/sdk/{schedule-tool-handler-V7A4AQGS.mjs → schedule-tool-handler-NLBCVAQE.mjs} +5 -5
- package/dist/sdk/sdk.js +1637 -263
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +4 -4
- package/dist/sdk/{trace-helpers-7BSOH35A.mjs → trace-helpers-45BTGOUW.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-N4ZTFOH6.mjs → workflow-check-provider-ALB4BINK.mjs} +5 -5
- package/dist/sdk/{workflow-check-provider-X7ZGHZA6.mjs → workflow-check-provider-BHMQN234.mjs} +5 -5
- package/package.json +2 -2
- package/dist/output/traces/run-2026-03-06T13-29-14-416Z.ndjson +0 -138
- package/dist/output/traces/run-2026-03-06T13-29-52-749Z.ndjson +0 -2235
- package/dist/sdk/check-provider-registry-6WR2SG66.mjs +0 -29
- package/dist/sdk/chunk-2G2PJKHM.mjs.map +0 -1
- package/dist/sdk/chunk-HM3RZ3NP.mjs +0 -443
- package/dist/sdk/chunk-HM3RZ3NP.mjs.map +0 -1
- package/dist/sdk/chunk-MHLP6P4V.mjs +0 -44323
- package/dist/sdk/chunk-MHLP6P4V.mjs.map +0 -1
- package/dist/sdk/chunk-UNUZFJ5I.mjs +0 -1502
- package/dist/sdk/chunk-UNUZFJ5I.mjs.map +0 -1
- package/dist/sdk/chunk-XYQSWTGC.mjs +0 -739
- package/dist/sdk/chunk-XYQSWTGC.mjs.map +0 -1
- package/dist/sdk/chunk-YSQV7N5H.mjs.map +0 -1
- package/dist/sdk/failure-condition-evaluator-GPANOHP2.mjs +0 -17
- package/dist/sdk/github-frontend-VM52NX7N.mjs +0 -1386
- package/dist/sdk/github-frontend-VM52NX7N.mjs.map +0 -1
- package/dist/sdk/routing-BXHP2E62.mjs +0 -25
- package/dist/sdk/schedule-tool-B6SEZ77N.mjs +0 -35
- package/dist/sdk/schedule-tool-handler-V7A4AQGS.mjs.map +0 -1
- package/dist/sdk/schedule-tool-handler-VNAVYBCM.mjs +0 -39
- package/dist/sdk/schedule-tool-handler-VNAVYBCM.mjs.map +0 -1
- package/dist/sdk/trace-helpers-7BSOH35A.mjs.map +0 -1
- package/dist/sdk/trace-helpers-UG6FOWVV.mjs +0 -25
- package/dist/sdk/trace-helpers-UG6FOWVV.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-AECYZCBK.mjs +0 -29
- package/dist/sdk/workflow-check-provider-AECYZCBK.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-N4ZTFOH6.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-X7ZGHZA6.mjs.map +0 -1
- package/dist/traces/run-2026-03-06T13-29-14-416Z.ndjson +0 -138
- package/dist/traces/run-2026-03-06T13-29-52-749Z.ndjson +0 -2235
- /package/dist/sdk/{check-provider-registry-6WR2SG66.mjs.map → check-provider-registry-OJNYM7I6.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-GPV5DYN5.mjs.map → check-provider-registry-TVZL4EDZ.mjs.map} +0 -0
- /package/dist/sdk/{chunk-E7NRUDWL.mjs.map → chunk-FUO4IFQD.mjs.map} +0 -0
- /package/dist/sdk/{chunk-RV5SK4FZ.mjs.map → chunk-JT5DGR4J.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-P356JWTA.mjs.map → failure-condition-evaluator-HPUEA3XS.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-SOVBEAK4.mjs.map → github-frontend-QZ4CF563.mjs.map} +0 -0
- /package/dist/sdk/{host-7MGCKSHM.mjs.map → host-L4Q3U2XG.mjs.map} +0 -0
- /package/dist/sdk/{host-JHMDZR6P.mjs.map → host-P65NNMYN.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-GPANOHP2.mjs.map → routing-R4DGYG6Y.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-VWQ54IK4.mjs.map → schedule-tool-FRWG5RG5.mjs.map} +0 -0
- /package/dist/sdk/{routing-3WG46XWU.mjs.map → schedule-tool-ZLRHDABX.mjs.map} +0 -0
- /package/dist/sdk/{routing-BXHP2E62.mjs.map → schedule-tool-handler-LJDYKV3G.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-B6SEZ77N.mjs.map → schedule-tool-handler-NLBCVAQE.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-MPHHE2IM.mjs.map → trace-helpers-45BTGOUW.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-SPJWY2Y2.mjs.map → workflow-check-provider-ALB4BINK.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-SUYGQJ63.mjs.map → workflow-check-provider-BHMQN234.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-rc281",
|
|
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
|
);
|
|
@@ -8501,7 +8501,7 @@ ${"=".repeat(60)}
|
|
|
8501
8501
|
}
|
|
8502
8502
|
const explicitPromptType = (process.env.VISOR_PROMPT_TYPE || "").trim();
|
|
8503
8503
|
let systemPrompt = this.config.systemPrompt;
|
|
8504
|
-
if (!systemPrompt && schema !== "code-review") {
|
|
8504
|
+
if (!systemPrompt && schema !== "code-review" && !this.config.promptType) {
|
|
8505
8505
|
systemPrompt = "You are general assistant, follow user instructions.";
|
|
8506
8506
|
}
|
|
8507
8507
|
log(
|
|
@@ -8646,9 +8646,9 @@ ${schemaString}`);
|
|
|
8646
8646
|
const model = this.config.model || "default";
|
|
8647
8647
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8648
8648
|
try {
|
|
8649
|
-
const
|
|
8650
|
-
const
|
|
8651
|
-
const
|
|
8649
|
+
const fs27 = require("fs");
|
|
8650
|
+
const path31 = require("path");
|
|
8651
|
+
const os3 = require("os");
|
|
8652
8652
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8653
8653
|
const debugData = {
|
|
8654
8654
|
timestamp,
|
|
@@ -8720,19 +8720,19 @@ ${"=".repeat(60)}
|
|
|
8720
8720
|
`;
|
|
8721
8721
|
readableVersion += `${"=".repeat(60)}
|
|
8722
8722
|
`;
|
|
8723
|
-
const tempDir =
|
|
8724
|
-
const promptFile =
|
|
8725
|
-
|
|
8723
|
+
const tempDir = os3.tmpdir();
|
|
8724
|
+
const promptFile = path31.join(tempDir, `visor-prompt-${timestamp}.txt`);
|
|
8725
|
+
fs27.writeFileSync(promptFile, prompt, "utf-8");
|
|
8726
8726
|
log(`
|
|
8727
8727
|
\u{1F4BE} Prompt saved to: ${promptFile}`);
|
|
8728
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8728
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path31.join(process.cwd(), "debug-artifacts");
|
|
8729
8729
|
try {
|
|
8730
|
-
const base =
|
|
8730
|
+
const base = path31.join(
|
|
8731
8731
|
debugArtifactsDir,
|
|
8732
8732
|
`prompt-${_checkName || "unknown"}-${timestamp}`
|
|
8733
8733
|
);
|
|
8734
|
-
|
|
8735
|
-
|
|
8734
|
+
fs27.writeFileSync(base + ".json", debugJson, "utf-8");
|
|
8735
|
+
fs27.writeFileSync(base + ".summary.txt", readableVersion, "utf-8");
|
|
8736
8736
|
log(`
|
|
8737
8737
|
\u{1F4BE} Full debug info saved to directory: ${debugArtifactsDir}`);
|
|
8738
8738
|
} catch {
|
|
@@ -8777,8 +8777,8 @@ $ ${cliCommand}
|
|
|
8777
8777
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8778
8778
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8779
8779
|
try {
|
|
8780
|
-
const
|
|
8781
|
-
const
|
|
8780
|
+
const fs27 = require("fs");
|
|
8781
|
+
const path31 = require("path");
|
|
8782
8782
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8783
8783
|
const agentAny = agent;
|
|
8784
8784
|
let fullHistory = [];
|
|
@@ -8789,8 +8789,8 @@ $ ${cliCommand}
|
|
|
8789
8789
|
} else if (agentAny._messages) {
|
|
8790
8790
|
fullHistory = agentAny._messages;
|
|
8791
8791
|
}
|
|
8792
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8793
|
-
const sessionBase =
|
|
8792
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path31.join(process.cwd(), "debug-artifacts");
|
|
8793
|
+
const sessionBase = path31.join(
|
|
8794
8794
|
debugArtifactsDir,
|
|
8795
8795
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
8796
8796
|
);
|
|
@@ -8802,7 +8802,7 @@ $ ${cliCommand}
|
|
|
8802
8802
|
schema: effectiveSchema,
|
|
8803
8803
|
totalMessages: fullHistory.length
|
|
8804
8804
|
};
|
|
8805
|
-
|
|
8805
|
+
fs27.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
8806
8806
|
let readable = `=============================================================
|
|
8807
8807
|
`;
|
|
8808
8808
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -8829,7 +8829,7 @@ ${"=".repeat(60)}
|
|
|
8829
8829
|
`;
|
|
8830
8830
|
readable += content + "\n";
|
|
8831
8831
|
});
|
|
8832
|
-
|
|
8832
|
+
fs27.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
8833
8833
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
8834
8834
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
8835
8835
|
} catch (error) {
|
|
@@ -8838,11 +8838,11 @@ ${"=".repeat(60)}
|
|
|
8838
8838
|
}
|
|
8839
8839
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8840
8840
|
try {
|
|
8841
|
-
const
|
|
8842
|
-
const
|
|
8841
|
+
const fs27 = require("fs");
|
|
8842
|
+
const path31 = require("path");
|
|
8843
8843
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8844
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8845
|
-
const responseFile =
|
|
8844
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path31.join(process.cwd(), "debug-artifacts");
|
|
8845
|
+
const responseFile = path31.join(
|
|
8846
8846
|
debugArtifactsDir,
|
|
8847
8847
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8848
8848
|
);
|
|
@@ -8875,7 +8875,7 @@ ${"=".repeat(60)}
|
|
|
8875
8875
|
`;
|
|
8876
8876
|
responseContent += `${"=".repeat(60)}
|
|
8877
8877
|
`;
|
|
8878
|
-
|
|
8878
|
+
fs27.writeFileSync(responseFile, responseContent, "utf-8");
|
|
8879
8879
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
8880
8880
|
} catch (error) {
|
|
8881
8881
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -8893,9 +8893,9 @@ ${"=".repeat(60)}
|
|
|
8893
8893
|
await telemetry.shutdown();
|
|
8894
8894
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${traceFilePath}`);
|
|
8895
8895
|
if (process.env.GITHUB_ACTIONS) {
|
|
8896
|
-
const
|
|
8897
|
-
if (
|
|
8898
|
-
const stats =
|
|
8896
|
+
const fs27 = require("fs");
|
|
8897
|
+
if (fs27.existsSync(traceFilePath)) {
|
|
8898
|
+
const stats = fs27.statSync(traceFilePath);
|
|
8899
8899
|
console.log(
|
|
8900
8900
|
`::notice title=AI Trace Saved::OpenTelemetry trace file size: ${stats.size} bytes`
|
|
8901
8901
|
);
|
|
@@ -8933,8 +8933,8 @@ ${"=".repeat(60)}
|
|
|
8933
8933
|
* Load schema content from schema files or inline definitions
|
|
8934
8934
|
*/
|
|
8935
8935
|
async loadSchemaContent(schema) {
|
|
8936
|
-
const
|
|
8937
|
-
const
|
|
8936
|
+
const fs27 = require("fs").promises;
|
|
8937
|
+
const path31 = require("path");
|
|
8938
8938
|
if (typeof schema === "object" && schema !== null) {
|
|
8939
8939
|
log("\u{1F4CB} Using inline schema object from configuration");
|
|
8940
8940
|
return JSON.stringify(schema);
|
|
@@ -8947,14 +8947,14 @@ ${"=".repeat(60)}
|
|
|
8947
8947
|
}
|
|
8948
8948
|
} catch {
|
|
8949
8949
|
}
|
|
8950
|
-
if ((schema.startsWith("./") || schema.includes(".json")) && !
|
|
8950
|
+
if ((schema.startsWith("./") || schema.includes(".json")) && !path31.isAbsolute(schema)) {
|
|
8951
8951
|
if (schema.includes("..") || schema.includes("\0")) {
|
|
8952
8952
|
throw new Error("Invalid schema path: path traversal not allowed");
|
|
8953
8953
|
}
|
|
8954
8954
|
try {
|
|
8955
|
-
const schemaPath =
|
|
8955
|
+
const schemaPath = path31.resolve(process.cwd(), schema);
|
|
8956
8956
|
log(`\u{1F4CB} Loading custom schema from file: ${schemaPath}`);
|
|
8957
|
-
const schemaContent = await
|
|
8957
|
+
const schemaContent = await fs27.readFile(schemaPath, "utf-8");
|
|
8958
8958
|
return schemaContent.trim();
|
|
8959
8959
|
} catch (error) {
|
|
8960
8960
|
throw new Error(
|
|
@@ -8968,22 +8968,22 @@ ${"=".repeat(60)}
|
|
|
8968
8968
|
}
|
|
8969
8969
|
const candidatePaths = [
|
|
8970
8970
|
// GitHub Action bundle location
|
|
8971
|
-
|
|
8971
|
+
path31.join(__dirname, "output", sanitizedSchemaName, "schema.json"),
|
|
8972
8972
|
// Historical fallback when src/output was inadvertently bundled as output1/
|
|
8973
|
-
|
|
8973
|
+
path31.join(__dirname, "output1", sanitizedSchemaName, "schema.json"),
|
|
8974
8974
|
// Local dev (repo root)
|
|
8975
|
-
|
|
8975
|
+
path31.join(process.cwd(), "output", sanitizedSchemaName, "schema.json")
|
|
8976
8976
|
];
|
|
8977
8977
|
for (const schemaPath of candidatePaths) {
|
|
8978
8978
|
try {
|
|
8979
|
-
const schemaContent = await
|
|
8979
|
+
const schemaContent = await fs27.readFile(schemaPath, "utf-8");
|
|
8980
8980
|
return schemaContent.trim();
|
|
8981
8981
|
} catch {
|
|
8982
8982
|
}
|
|
8983
8983
|
}
|
|
8984
|
-
const distPath =
|
|
8985
|
-
const distAltPath =
|
|
8986
|
-
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");
|
|
8987
8987
|
throw new Error(
|
|
8988
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.`
|
|
8989
8989
|
);
|
|
@@ -9228,7 +9228,7 @@ ${"=".repeat(60)}
|
|
|
9228
9228
|
* Generate mock response for testing
|
|
9229
9229
|
*/
|
|
9230
9230
|
async generateMockResponse(_prompt, _checkName, _schema) {
|
|
9231
|
-
await new Promise((
|
|
9231
|
+
await new Promise((resolve19) => setTimeout(resolve19, 500));
|
|
9232
9232
|
const name = (_checkName || "").toLowerCase();
|
|
9233
9233
|
if (name.includes("extract-facts")) {
|
|
9234
9234
|
const arr = Array.from({ length: 6 }, (_, i) => ({
|
|
@@ -9589,7 +9589,7 @@ var init_command_executor = __esm({
|
|
|
9589
9589
|
* Execute command with stdin input
|
|
9590
9590
|
*/
|
|
9591
9591
|
executeWithStdin(command, options) {
|
|
9592
|
-
return new Promise((
|
|
9592
|
+
return new Promise((resolve19, reject) => {
|
|
9593
9593
|
const childProcess = (0, import_child_process2.exec)(
|
|
9594
9594
|
command,
|
|
9595
9595
|
{
|
|
@@ -9601,7 +9601,7 @@ var init_command_executor = __esm({
|
|
|
9601
9601
|
if (error && error.killed && (error.code === "ETIMEDOUT" || error.signal === "SIGTERM")) {
|
|
9602
9602
|
reject(new Error(`Command timed out after ${options.timeout || 3e4}ms`));
|
|
9603
9603
|
} else {
|
|
9604
|
-
|
|
9604
|
+
resolve19({
|
|
9605
9605
|
stdout: stdout || "",
|
|
9606
9606
|
stderr: stderr || "",
|
|
9607
9607
|
exitCode: error ? error.code || 1 : 0
|
|
@@ -17710,17 +17710,17 @@ var init_workflow_check_provider = __esm({
|
|
|
17710
17710
|
* so it can be executed by the state machine as a nested workflow.
|
|
17711
17711
|
*/
|
|
17712
17712
|
async loadWorkflowFromConfigPath(sourcePath, baseDir) {
|
|
17713
|
-
const
|
|
17714
|
-
const
|
|
17713
|
+
const path31 = require("path");
|
|
17714
|
+
const fs27 = require("fs");
|
|
17715
17715
|
const yaml5 = require("js-yaml");
|
|
17716
|
-
const resolved =
|
|
17717
|
-
if (!
|
|
17716
|
+
const resolved = path31.isAbsolute(sourcePath) ? sourcePath : path31.resolve(baseDir, sourcePath);
|
|
17717
|
+
if (!fs27.existsSync(resolved)) {
|
|
17718
17718
|
throw new Error(`Workflow config not found at: ${resolved}`);
|
|
17719
17719
|
}
|
|
17720
|
-
const rawContent =
|
|
17720
|
+
const rawContent = fs27.readFileSync(resolved, "utf8");
|
|
17721
17721
|
const rawData = yaml5.load(rawContent);
|
|
17722
17722
|
if (rawData.imports && Array.isArray(rawData.imports)) {
|
|
17723
|
-
const configDir =
|
|
17723
|
+
const configDir = path31.dirname(resolved);
|
|
17724
17724
|
for (const source of rawData.imports) {
|
|
17725
17725
|
const results = await this.registry.import(source, {
|
|
17726
17726
|
basePath: configDir,
|
|
@@ -17750,8 +17750,8 @@ ${errors}`);
|
|
|
17750
17750
|
if (!steps || Object.keys(steps).length === 0) {
|
|
17751
17751
|
throw new Error(`Config '${resolved}' does not contain any steps to execute as a workflow`);
|
|
17752
17752
|
}
|
|
17753
|
-
const id =
|
|
17754
|
-
const name = loaded.name || `Workflow from ${
|
|
17753
|
+
const id = path31.basename(resolved).replace(/\.(ya?ml)$/i, "");
|
|
17754
|
+
const name = loaded.name || `Workflow from ${path31.basename(resolved)}`;
|
|
17755
17755
|
const workflowDef = {
|
|
17756
17756
|
id,
|
|
17757
17757
|
name,
|
|
@@ -18557,8 +18557,8 @@ async function createStoreBackend(storageConfig, haConfig) {
|
|
|
18557
18557
|
case "mssql": {
|
|
18558
18558
|
try {
|
|
18559
18559
|
const loaderPath = "../../enterprise/loader";
|
|
18560
|
-
const { loadEnterpriseStoreBackend } = await import(loaderPath);
|
|
18561
|
-
return await
|
|
18560
|
+
const { loadEnterpriseStoreBackend: loadEnterpriseStoreBackend2 } = await import(loaderPath);
|
|
18561
|
+
return await loadEnterpriseStoreBackend2(driver, storageConfig, haConfig);
|
|
18562
18562
|
} catch (err) {
|
|
18563
18563
|
const msg = err instanceof Error ? err.message : String(err);
|
|
18564
18564
|
logger.error(`[StoreFactory] Failed to load enterprise ${driver} backend: ${msg}`);
|
|
@@ -21129,7 +21129,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21129
21129
|
* Returns the actual bound port number
|
|
21130
21130
|
*/
|
|
21131
21131
|
async start() {
|
|
21132
|
-
return new Promise((
|
|
21132
|
+
return new Promise((resolve19, reject) => {
|
|
21133
21133
|
try {
|
|
21134
21134
|
this.server = import_http.default.createServer((req, res) => {
|
|
21135
21135
|
this.handleRequest(req, res).catch((error) => {
|
|
@@ -21163,7 +21163,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21163
21163
|
);
|
|
21164
21164
|
}
|
|
21165
21165
|
this.startKeepalive();
|
|
21166
|
-
|
|
21166
|
+
resolve19(this.port);
|
|
21167
21167
|
});
|
|
21168
21168
|
} catch (error) {
|
|
21169
21169
|
reject(error);
|
|
@@ -21226,7 +21226,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21226
21226
|
logger.debug(
|
|
21227
21227
|
`[CustomToolsSSEServer:${this.sessionId}] Grace period before stop: ${waitMs}ms (activeToolCalls=${this.activeToolCalls})`
|
|
21228
21228
|
);
|
|
21229
|
-
await new Promise((
|
|
21229
|
+
await new Promise((resolve19) => setTimeout(resolve19, waitMs));
|
|
21230
21230
|
}
|
|
21231
21231
|
}
|
|
21232
21232
|
if (this.activeToolCalls > 0) {
|
|
@@ -21235,7 +21235,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21235
21235
|
`[CustomToolsSSEServer:${this.sessionId}] Waiting for ${this.activeToolCalls} active tool call(s) before stop`
|
|
21236
21236
|
);
|
|
21237
21237
|
while (this.activeToolCalls > 0 && Date.now() - startedAt < effectiveDrainTimeoutMs) {
|
|
21238
|
-
await new Promise((
|
|
21238
|
+
await new Promise((resolve19) => setTimeout(resolve19, 250));
|
|
21239
21239
|
}
|
|
21240
21240
|
if (this.activeToolCalls > 0) {
|
|
21241
21241
|
logger.warn(
|
|
@@ -21260,21 +21260,21 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21260
21260
|
}
|
|
21261
21261
|
this.connections.clear();
|
|
21262
21262
|
if (this.server) {
|
|
21263
|
-
await new Promise((
|
|
21263
|
+
await new Promise((resolve19, reject) => {
|
|
21264
21264
|
const timeout = setTimeout(() => {
|
|
21265
21265
|
if (this.debug) {
|
|
21266
21266
|
logger.debug(
|
|
21267
21267
|
`[CustomToolsSSEServer:${this.sessionId}] Force closing server after timeout`
|
|
21268
21268
|
);
|
|
21269
21269
|
}
|
|
21270
|
-
this.server?.close(() =>
|
|
21270
|
+
this.server?.close(() => resolve19());
|
|
21271
21271
|
}, 5e3);
|
|
21272
21272
|
this.server.close((error) => {
|
|
21273
21273
|
clearTimeout(timeout);
|
|
21274
21274
|
if (error) {
|
|
21275
21275
|
reject(error);
|
|
21276
21276
|
} else {
|
|
21277
|
-
|
|
21277
|
+
resolve19();
|
|
21278
21278
|
}
|
|
21279
21279
|
});
|
|
21280
21280
|
});
|
|
@@ -21709,7 +21709,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21709
21709
|
logger.warn(
|
|
21710
21710
|
`[CustomToolsSSEServer:${this.sessionId}] Tool ${toolName} failed (attempt ${attempt + 1}/${retryCount + 1}): ${errorMsg}. Retrying in ${delay}ms`
|
|
21711
21711
|
);
|
|
21712
|
-
await new Promise((
|
|
21712
|
+
await new Promise((resolve19) => setTimeout(resolve19, delay));
|
|
21713
21713
|
attempt++;
|
|
21714
21714
|
}
|
|
21715
21715
|
}
|
|
@@ -22022,9 +22022,9 @@ var init_ai_check_provider = __esm({
|
|
|
22022
22022
|
} else {
|
|
22023
22023
|
resolvedPath = import_path7.default.resolve(process.cwd(), str);
|
|
22024
22024
|
}
|
|
22025
|
-
const
|
|
22025
|
+
const fs27 = require("fs").promises;
|
|
22026
22026
|
try {
|
|
22027
|
-
const stat2 = await
|
|
22027
|
+
const stat2 = await fs27.stat(resolvedPath);
|
|
22028
22028
|
return stat2.isFile();
|
|
22029
22029
|
} catch {
|
|
22030
22030
|
return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);
|
|
@@ -28126,14 +28126,14 @@ var require_util = __commonJS({
|
|
|
28126
28126
|
}
|
|
28127
28127
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
28128
28128
|
let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`;
|
|
28129
|
-
let
|
|
28129
|
+
let path31 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
28130
28130
|
if (origin.endsWith("/")) {
|
|
28131
28131
|
origin = origin.substring(0, origin.length - 1);
|
|
28132
28132
|
}
|
|
28133
|
-
if (
|
|
28134
|
-
|
|
28133
|
+
if (path31 && !path31.startsWith("/")) {
|
|
28134
|
+
path31 = `/${path31}`;
|
|
28135
28135
|
}
|
|
28136
|
-
url = new URL(origin +
|
|
28136
|
+
url = new URL(origin + path31);
|
|
28137
28137
|
}
|
|
28138
28138
|
return url;
|
|
28139
28139
|
}
|
|
@@ -29747,20 +29747,20 @@ var require_parseParams = __commonJS({
|
|
|
29747
29747
|
var require_basename = __commonJS({
|
|
29748
29748
|
"node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) {
|
|
29749
29749
|
"use strict";
|
|
29750
|
-
module2.exports = function basename4(
|
|
29751
|
-
if (typeof
|
|
29750
|
+
module2.exports = function basename4(path31) {
|
|
29751
|
+
if (typeof path31 !== "string") {
|
|
29752
29752
|
return "";
|
|
29753
29753
|
}
|
|
29754
|
-
for (var i =
|
|
29755
|
-
switch (
|
|
29754
|
+
for (var i = path31.length - 1; i >= 0; --i) {
|
|
29755
|
+
switch (path31.charCodeAt(i)) {
|
|
29756
29756
|
case 47:
|
|
29757
29757
|
// '/'
|
|
29758
29758
|
case 92:
|
|
29759
|
-
|
|
29760
|
-
return
|
|
29759
|
+
path31 = path31.slice(i + 1);
|
|
29760
|
+
return path31 === ".." || path31 === "." ? "" : path31;
|
|
29761
29761
|
}
|
|
29762
29762
|
}
|
|
29763
|
-
return
|
|
29763
|
+
return path31 === ".." || path31 === "." ? "" : path31;
|
|
29764
29764
|
};
|
|
29765
29765
|
}
|
|
29766
29766
|
});
|
|
@@ -30764,11 +30764,11 @@ var require_util2 = __commonJS({
|
|
|
30764
30764
|
var assert = require("assert");
|
|
30765
30765
|
var { isUint8Array } = require("util/types");
|
|
30766
30766
|
var supportedHashes = [];
|
|
30767
|
-
var
|
|
30767
|
+
var crypto4;
|
|
30768
30768
|
try {
|
|
30769
|
-
|
|
30769
|
+
crypto4 = require("crypto");
|
|
30770
30770
|
const possibleRelevantHashes = ["sha256", "sha384", "sha512"];
|
|
30771
|
-
supportedHashes =
|
|
30771
|
+
supportedHashes = crypto4.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
|
|
30772
30772
|
} catch {
|
|
30773
30773
|
}
|
|
30774
30774
|
function responseURL(response) {
|
|
@@ -31045,7 +31045,7 @@ var require_util2 = __commonJS({
|
|
|
31045
31045
|
}
|
|
31046
31046
|
}
|
|
31047
31047
|
function bytesMatch(bytes, metadataList) {
|
|
31048
|
-
if (
|
|
31048
|
+
if (crypto4 === void 0) {
|
|
31049
31049
|
return true;
|
|
31050
31050
|
}
|
|
31051
31051
|
const parsedMetadata = parseMetadata(metadataList);
|
|
@@ -31060,7 +31060,7 @@ var require_util2 = __commonJS({
|
|
|
31060
31060
|
for (const item of metadata) {
|
|
31061
31061
|
const algorithm = item.algo;
|
|
31062
31062
|
const expectedValue = item.hash;
|
|
31063
|
-
let actualValue =
|
|
31063
|
+
let actualValue = crypto4.createHash(algorithm).update(bytes).digest("base64");
|
|
31064
31064
|
if (actualValue[actualValue.length - 1] === "=") {
|
|
31065
31065
|
if (actualValue[actualValue.length - 2] === "=") {
|
|
31066
31066
|
actualValue = actualValue.slice(0, -2);
|
|
@@ -31153,8 +31153,8 @@ var require_util2 = __commonJS({
|
|
|
31153
31153
|
function createDeferredPromise() {
|
|
31154
31154
|
let res;
|
|
31155
31155
|
let rej;
|
|
31156
|
-
const promise = new Promise((
|
|
31157
|
-
res =
|
|
31156
|
+
const promise = new Promise((resolve19, reject) => {
|
|
31157
|
+
res = resolve19;
|
|
31158
31158
|
rej = reject;
|
|
31159
31159
|
});
|
|
31160
31160
|
return { promise, resolve: res, reject: rej };
|
|
@@ -32407,8 +32407,8 @@ var require_body = __commonJS({
|
|
|
32407
32407
|
var { parseMIMEType, serializeAMimeType } = require_dataURL();
|
|
32408
32408
|
var random;
|
|
32409
32409
|
try {
|
|
32410
|
-
const
|
|
32411
|
-
random = (max) =>
|
|
32410
|
+
const crypto4 = require("crypto");
|
|
32411
|
+
random = (max) => crypto4.randomInt(0, max);
|
|
32412
32412
|
} catch {
|
|
32413
32413
|
random = (max) => Math.floor(Math.random(max));
|
|
32414
32414
|
}
|
|
@@ -32659,8 +32659,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r
|
|
|
32659
32659
|
});
|
|
32660
32660
|
}
|
|
32661
32661
|
});
|
|
32662
|
-
const busboyResolve = new Promise((
|
|
32663
|
-
busboy.on("finish",
|
|
32662
|
+
const busboyResolve = new Promise((resolve19, reject) => {
|
|
32663
|
+
busboy.on("finish", resolve19);
|
|
32664
32664
|
busboy.on("error", (err) => reject(new TypeError(err)));
|
|
32665
32665
|
});
|
|
32666
32666
|
if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk);
|
|
@@ -32791,7 +32791,7 @@ var require_request = __commonJS({
|
|
|
32791
32791
|
}
|
|
32792
32792
|
var Request = class _Request {
|
|
32793
32793
|
constructor(origin, {
|
|
32794
|
-
path:
|
|
32794
|
+
path: path31,
|
|
32795
32795
|
method,
|
|
32796
32796
|
body,
|
|
32797
32797
|
headers,
|
|
@@ -32805,11 +32805,11 @@ var require_request = __commonJS({
|
|
|
32805
32805
|
throwOnError,
|
|
32806
32806
|
expectContinue
|
|
32807
32807
|
}, handler) {
|
|
32808
|
-
if (typeof
|
|
32808
|
+
if (typeof path31 !== "string") {
|
|
32809
32809
|
throw new InvalidArgumentError("path must be a string");
|
|
32810
|
-
} else if (
|
|
32810
|
+
} else if (path31[0] !== "/" && !(path31.startsWith("http://") || path31.startsWith("https://")) && method !== "CONNECT") {
|
|
32811
32811
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
32812
|
-
} else if (invalidPathRegex.exec(
|
|
32812
|
+
} else if (invalidPathRegex.exec(path31) !== null) {
|
|
32813
32813
|
throw new InvalidArgumentError("invalid request path");
|
|
32814
32814
|
}
|
|
32815
32815
|
if (typeof method !== "string") {
|
|
@@ -32872,7 +32872,7 @@ var require_request = __commonJS({
|
|
|
32872
32872
|
this.completed = false;
|
|
32873
32873
|
this.aborted = false;
|
|
32874
32874
|
this.upgrade = upgrade || null;
|
|
32875
|
-
this.path = query ? util.buildURL(
|
|
32875
|
+
this.path = query ? util.buildURL(path31, query) : path31;
|
|
32876
32876
|
this.origin = origin;
|
|
32877
32877
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
32878
32878
|
this.blocking = blocking == null ? false : blocking;
|
|
@@ -33194,9 +33194,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
33194
33194
|
}
|
|
33195
33195
|
close(callback) {
|
|
33196
33196
|
if (callback === void 0) {
|
|
33197
|
-
return new Promise((
|
|
33197
|
+
return new Promise((resolve19, reject) => {
|
|
33198
33198
|
this.close((err, data) => {
|
|
33199
|
-
return err ? reject(err) :
|
|
33199
|
+
return err ? reject(err) : resolve19(data);
|
|
33200
33200
|
});
|
|
33201
33201
|
});
|
|
33202
33202
|
}
|
|
@@ -33234,12 +33234,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
33234
33234
|
err = null;
|
|
33235
33235
|
}
|
|
33236
33236
|
if (callback === void 0) {
|
|
33237
|
-
return new Promise((
|
|
33237
|
+
return new Promise((resolve19, reject) => {
|
|
33238
33238
|
this.destroy(err, (err2, data) => {
|
|
33239
33239
|
return err2 ? (
|
|
33240
33240
|
/* istanbul ignore next: should never error */
|
|
33241
33241
|
reject(err2)
|
|
33242
|
-
) :
|
|
33242
|
+
) : resolve19(data);
|
|
33243
33243
|
});
|
|
33244
33244
|
});
|
|
33245
33245
|
}
|
|
@@ -33880,9 +33880,9 @@ var require_RedirectHandler = __commonJS({
|
|
|
33880
33880
|
return this.handler.onHeaders(statusCode, headers, resume, statusText);
|
|
33881
33881
|
}
|
|
33882
33882
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
33883
|
-
const
|
|
33883
|
+
const path31 = search ? `${pathname}${search}` : pathname;
|
|
33884
33884
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
33885
|
-
this.opts.path =
|
|
33885
|
+
this.opts.path = path31;
|
|
33886
33886
|
this.opts.origin = origin;
|
|
33887
33887
|
this.opts.maxRedirections = 0;
|
|
33888
33888
|
this.opts.query = null;
|
|
@@ -34301,16 +34301,16 @@ var require_client = __commonJS({
|
|
|
34301
34301
|
return this[kNeedDrain] < 2;
|
|
34302
34302
|
}
|
|
34303
34303
|
async [kClose]() {
|
|
34304
|
-
return new Promise((
|
|
34304
|
+
return new Promise((resolve19) => {
|
|
34305
34305
|
if (!this[kSize]) {
|
|
34306
|
-
|
|
34306
|
+
resolve19(null);
|
|
34307
34307
|
} else {
|
|
34308
|
-
this[kClosedResolve] =
|
|
34308
|
+
this[kClosedResolve] = resolve19;
|
|
34309
34309
|
}
|
|
34310
34310
|
});
|
|
34311
34311
|
}
|
|
34312
34312
|
async [kDestroy](err) {
|
|
34313
|
-
return new Promise((
|
|
34313
|
+
return new Promise((resolve19) => {
|
|
34314
34314
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
34315
34315
|
for (let i = 0; i < requests.length; i++) {
|
|
34316
34316
|
const request = requests[i];
|
|
@@ -34321,7 +34321,7 @@ var require_client = __commonJS({
|
|
|
34321
34321
|
this[kClosedResolve]();
|
|
34322
34322
|
this[kClosedResolve] = null;
|
|
34323
34323
|
}
|
|
34324
|
-
|
|
34324
|
+
resolve19();
|
|
34325
34325
|
};
|
|
34326
34326
|
if (this[kHTTP2Session] != null) {
|
|
34327
34327
|
util.destroy(this[kHTTP2Session], err);
|
|
@@ -34901,7 +34901,7 @@ var require_client = __commonJS({
|
|
|
34901
34901
|
});
|
|
34902
34902
|
}
|
|
34903
34903
|
try {
|
|
34904
|
-
const socket = await new Promise((
|
|
34904
|
+
const socket = await new Promise((resolve19, reject) => {
|
|
34905
34905
|
client[kConnector]({
|
|
34906
34906
|
host,
|
|
34907
34907
|
hostname,
|
|
@@ -34913,7 +34913,7 @@ var require_client = __commonJS({
|
|
|
34913
34913
|
if (err) {
|
|
34914
34914
|
reject(err);
|
|
34915
34915
|
} else {
|
|
34916
|
-
|
|
34916
|
+
resolve19(socket2);
|
|
34917
34917
|
}
|
|
34918
34918
|
});
|
|
34919
34919
|
});
|
|
@@ -35124,7 +35124,7 @@ var require_client = __commonJS({
|
|
|
35124
35124
|
writeH2(client, client[kHTTP2Session], request);
|
|
35125
35125
|
return;
|
|
35126
35126
|
}
|
|
35127
|
-
const { body, method, path:
|
|
35127
|
+
const { body, method, path: path31, host, upgrade, headers, blocking, reset } = request;
|
|
35128
35128
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
35129
35129
|
if (body && typeof body.read === "function") {
|
|
35130
35130
|
body.read(0);
|
|
@@ -35174,7 +35174,7 @@ var require_client = __commonJS({
|
|
|
35174
35174
|
if (blocking) {
|
|
35175
35175
|
socket[kBlocking] = true;
|
|
35176
35176
|
}
|
|
35177
|
-
let header = `${method} ${
|
|
35177
|
+
let header = `${method} ${path31} HTTP/1.1\r
|
|
35178
35178
|
`;
|
|
35179
35179
|
if (typeof host === "string") {
|
|
35180
35180
|
header += `host: ${host}\r
|
|
@@ -35237,7 +35237,7 @@ upgrade: ${upgrade}\r
|
|
|
35237
35237
|
return true;
|
|
35238
35238
|
}
|
|
35239
35239
|
function writeH2(client, session, request) {
|
|
35240
|
-
const { body, method, path:
|
|
35240
|
+
const { body, method, path: path31, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
|
|
35241
35241
|
let headers;
|
|
35242
35242
|
if (typeof reqHeaders === "string") headers = Request[kHTTP2CopyHeaders](reqHeaders.trim());
|
|
35243
35243
|
else headers = reqHeaders;
|
|
@@ -35280,7 +35280,7 @@ upgrade: ${upgrade}\r
|
|
|
35280
35280
|
});
|
|
35281
35281
|
return true;
|
|
35282
35282
|
}
|
|
35283
|
-
headers[HTTP2_HEADER_PATH] =
|
|
35283
|
+
headers[HTTP2_HEADER_PATH] = path31;
|
|
35284
35284
|
headers[HTTP2_HEADER_SCHEME] = "https";
|
|
35285
35285
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
35286
35286
|
if (body && typeof body.read === "function") {
|
|
@@ -35537,12 +35537,12 @@ upgrade: ${upgrade}\r
|
|
|
35537
35537
|
cb();
|
|
35538
35538
|
}
|
|
35539
35539
|
}
|
|
35540
|
-
const waitForDrain = () => new Promise((
|
|
35540
|
+
const waitForDrain = () => new Promise((resolve19, reject) => {
|
|
35541
35541
|
assert(callback === null);
|
|
35542
35542
|
if (socket[kError]) {
|
|
35543
35543
|
reject(socket[kError]);
|
|
35544
35544
|
} else {
|
|
35545
|
-
callback =
|
|
35545
|
+
callback = resolve19;
|
|
35546
35546
|
}
|
|
35547
35547
|
});
|
|
35548
35548
|
if (client[kHTTPConnVersion] === "h2") {
|
|
@@ -35888,8 +35888,8 @@ var require_pool_base = __commonJS({
|
|
|
35888
35888
|
if (this[kQueue].isEmpty()) {
|
|
35889
35889
|
return Promise.all(this[kClients].map((c) => c.close()));
|
|
35890
35890
|
} else {
|
|
35891
|
-
return new Promise((
|
|
35892
|
-
this[kClosedResolve] =
|
|
35891
|
+
return new Promise((resolve19) => {
|
|
35892
|
+
this[kClosedResolve] = resolve19;
|
|
35893
35893
|
});
|
|
35894
35894
|
}
|
|
35895
35895
|
}
|
|
@@ -36467,7 +36467,7 @@ var require_readable = __commonJS({
|
|
|
36467
36467
|
if (this.closed) {
|
|
36468
36468
|
return Promise.resolve(null);
|
|
36469
36469
|
}
|
|
36470
|
-
return new Promise((
|
|
36470
|
+
return new Promise((resolve19, reject) => {
|
|
36471
36471
|
const signalListenerCleanup = signal ? util.addAbortListener(signal, () => {
|
|
36472
36472
|
this.destroy();
|
|
36473
36473
|
}) : noop;
|
|
@@ -36476,7 +36476,7 @@ var require_readable = __commonJS({
|
|
|
36476
36476
|
if (signal && signal.aborted) {
|
|
36477
36477
|
reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" }));
|
|
36478
36478
|
} else {
|
|
36479
|
-
|
|
36479
|
+
resolve19(null);
|
|
36480
36480
|
}
|
|
36481
36481
|
}).on("error", noop).on("data", function(chunk) {
|
|
36482
36482
|
limit -= chunk.length;
|
|
@@ -36498,11 +36498,11 @@ var require_readable = __commonJS({
|
|
|
36498
36498
|
throw new TypeError("unusable");
|
|
36499
36499
|
}
|
|
36500
36500
|
assert(!stream[kConsume]);
|
|
36501
|
-
return new Promise((
|
|
36501
|
+
return new Promise((resolve19, reject) => {
|
|
36502
36502
|
stream[kConsume] = {
|
|
36503
36503
|
type,
|
|
36504
36504
|
stream,
|
|
36505
|
-
resolve:
|
|
36505
|
+
resolve: resolve19,
|
|
36506
36506
|
reject,
|
|
36507
36507
|
length: 0,
|
|
36508
36508
|
body: []
|
|
@@ -36537,12 +36537,12 @@ var require_readable = __commonJS({
|
|
|
36537
36537
|
}
|
|
36538
36538
|
}
|
|
36539
36539
|
function consumeEnd(consume2) {
|
|
36540
|
-
const { type, body, resolve:
|
|
36540
|
+
const { type, body, resolve: resolve19, stream, length } = consume2;
|
|
36541
36541
|
try {
|
|
36542
36542
|
if (type === "text") {
|
|
36543
|
-
|
|
36543
|
+
resolve19(toUSVString(Buffer.concat(body)));
|
|
36544
36544
|
} else if (type === "json") {
|
|
36545
|
-
|
|
36545
|
+
resolve19(JSON.parse(Buffer.concat(body)));
|
|
36546
36546
|
} else if (type === "arrayBuffer") {
|
|
36547
36547
|
const dst = new Uint8Array(length);
|
|
36548
36548
|
let pos = 0;
|
|
@@ -36550,12 +36550,12 @@ var require_readable = __commonJS({
|
|
|
36550
36550
|
dst.set(buf, pos);
|
|
36551
36551
|
pos += buf.byteLength;
|
|
36552
36552
|
}
|
|
36553
|
-
|
|
36553
|
+
resolve19(dst.buffer);
|
|
36554
36554
|
} else if (type === "blob") {
|
|
36555
36555
|
if (!Blob2) {
|
|
36556
36556
|
Blob2 = require("buffer").Blob;
|
|
36557
36557
|
}
|
|
36558
|
-
|
|
36558
|
+
resolve19(new Blob2(body, { type: stream[kContentType] }));
|
|
36559
36559
|
}
|
|
36560
36560
|
consumeFinish(consume2);
|
|
36561
36561
|
} catch (err) {
|
|
@@ -36812,9 +36812,9 @@ var require_api_request = __commonJS({
|
|
|
36812
36812
|
};
|
|
36813
36813
|
function request(opts, callback) {
|
|
36814
36814
|
if (callback === void 0) {
|
|
36815
|
-
return new Promise((
|
|
36815
|
+
return new Promise((resolve19, reject) => {
|
|
36816
36816
|
request.call(this, opts, (err, data) => {
|
|
36817
|
-
return err ? reject(err) :
|
|
36817
|
+
return err ? reject(err) : resolve19(data);
|
|
36818
36818
|
});
|
|
36819
36819
|
});
|
|
36820
36820
|
}
|
|
@@ -36987,9 +36987,9 @@ var require_api_stream = __commonJS({
|
|
|
36987
36987
|
};
|
|
36988
36988
|
function stream(opts, factory, callback) {
|
|
36989
36989
|
if (callback === void 0) {
|
|
36990
|
-
return new Promise((
|
|
36990
|
+
return new Promise((resolve19, reject) => {
|
|
36991
36991
|
stream.call(this, opts, factory, (err, data) => {
|
|
36992
|
-
return err ? reject(err) :
|
|
36992
|
+
return err ? reject(err) : resolve19(data);
|
|
36993
36993
|
});
|
|
36994
36994
|
});
|
|
36995
36995
|
}
|
|
@@ -37270,9 +37270,9 @@ var require_api_upgrade = __commonJS({
|
|
|
37270
37270
|
};
|
|
37271
37271
|
function upgrade(opts, callback) {
|
|
37272
37272
|
if (callback === void 0) {
|
|
37273
|
-
return new Promise((
|
|
37273
|
+
return new Promise((resolve19, reject) => {
|
|
37274
37274
|
upgrade.call(this, opts, (err, data) => {
|
|
37275
|
-
return err ? reject(err) :
|
|
37275
|
+
return err ? reject(err) : resolve19(data);
|
|
37276
37276
|
});
|
|
37277
37277
|
});
|
|
37278
37278
|
}
|
|
@@ -37361,9 +37361,9 @@ var require_api_connect = __commonJS({
|
|
|
37361
37361
|
};
|
|
37362
37362
|
function connect(opts, callback) {
|
|
37363
37363
|
if (callback === void 0) {
|
|
37364
|
-
return new Promise((
|
|
37364
|
+
return new Promise((resolve19, reject) => {
|
|
37365
37365
|
connect.call(this, opts, (err, data) => {
|
|
37366
|
-
return err ? reject(err) :
|
|
37366
|
+
return err ? reject(err) : resolve19(data);
|
|
37367
37367
|
});
|
|
37368
37368
|
});
|
|
37369
37369
|
}
|
|
@@ -37523,20 +37523,20 @@ var require_mock_utils = __commonJS({
|
|
|
37523
37523
|
}
|
|
37524
37524
|
return true;
|
|
37525
37525
|
}
|
|
37526
|
-
function safeUrl(
|
|
37527
|
-
if (typeof
|
|
37528
|
-
return
|
|
37526
|
+
function safeUrl(path31) {
|
|
37527
|
+
if (typeof path31 !== "string") {
|
|
37528
|
+
return path31;
|
|
37529
37529
|
}
|
|
37530
|
-
const pathSegments =
|
|
37530
|
+
const pathSegments = path31.split("?");
|
|
37531
37531
|
if (pathSegments.length !== 2) {
|
|
37532
|
-
return
|
|
37532
|
+
return path31;
|
|
37533
37533
|
}
|
|
37534
37534
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
37535
37535
|
qp.sort();
|
|
37536
37536
|
return [...pathSegments, qp.toString()].join("?");
|
|
37537
37537
|
}
|
|
37538
|
-
function matchKey(mockDispatch2, { path:
|
|
37539
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
37538
|
+
function matchKey(mockDispatch2, { path: path31, method, body, headers }) {
|
|
37539
|
+
const pathMatch = matchValue(mockDispatch2.path, path31);
|
|
37540
37540
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
37541
37541
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
37542
37542
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -37554,7 +37554,7 @@ var require_mock_utils = __commonJS({
|
|
|
37554
37554
|
function getMockDispatch(mockDispatches, key) {
|
|
37555
37555
|
const basePath = key.query ? buildURL(key.path, key.query) : key.path;
|
|
37556
37556
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
37557
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
37557
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path31 }) => matchValue(safeUrl(path31), resolvedPath));
|
|
37558
37558
|
if (matchedMockDispatches.length === 0) {
|
|
37559
37559
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
37560
37560
|
}
|
|
@@ -37591,9 +37591,9 @@ var require_mock_utils = __commonJS({
|
|
|
37591
37591
|
}
|
|
37592
37592
|
}
|
|
37593
37593
|
function buildKey(opts) {
|
|
37594
|
-
const { path:
|
|
37594
|
+
const { path: path31, method, body, headers, query } = opts;
|
|
37595
37595
|
return {
|
|
37596
|
-
path:
|
|
37596
|
+
path: path31,
|
|
37597
37597
|
method,
|
|
37598
37598
|
body,
|
|
37599
37599
|
headers,
|
|
@@ -38042,10 +38042,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
38042
38042
|
}
|
|
38043
38043
|
format(pendingInterceptors) {
|
|
38044
38044
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
38045
|
-
({ method, path:
|
|
38045
|
+
({ method, path: path31, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
38046
38046
|
Method: method,
|
|
38047
38047
|
Origin: origin,
|
|
38048
|
-
Path:
|
|
38048
|
+
Path: path31,
|
|
38049
38049
|
"Status code": statusCode,
|
|
38050
38050
|
Persistent: persist ? "\u2705" : "\u274C",
|
|
38051
38051
|
Invocations: timesInvoked,
|
|
@@ -40986,7 +40986,7 @@ var require_fetch = __commonJS({
|
|
|
40986
40986
|
async function dispatch({ body }) {
|
|
40987
40987
|
const url = requestCurrentURL(request);
|
|
40988
40988
|
const agent = fetchParams.controller.dispatcher;
|
|
40989
|
-
return new Promise((
|
|
40989
|
+
return new Promise((resolve19, reject) => agent.dispatch(
|
|
40990
40990
|
{
|
|
40991
40991
|
path: url.pathname + url.search,
|
|
40992
40992
|
origin: url.origin,
|
|
@@ -41062,7 +41062,7 @@ var require_fetch = __commonJS({
|
|
|
41062
41062
|
}
|
|
41063
41063
|
}
|
|
41064
41064
|
}
|
|
41065
|
-
|
|
41065
|
+
resolve19({
|
|
41066
41066
|
status,
|
|
41067
41067
|
statusText,
|
|
41068
41068
|
headersList: headers[kHeadersList],
|
|
@@ -41105,7 +41105,7 @@ var require_fetch = __commonJS({
|
|
|
41105
41105
|
const val = headersList[n + 1].toString("latin1");
|
|
41106
41106
|
headers[kHeadersList].append(key, val);
|
|
41107
41107
|
}
|
|
41108
|
-
|
|
41108
|
+
resolve19({
|
|
41109
41109
|
status,
|
|
41110
41110
|
statusText: STATUS_CODES[status],
|
|
41111
41111
|
headersList: headers[kHeadersList],
|
|
@@ -42666,8 +42666,8 @@ var require_util6 = __commonJS({
|
|
|
42666
42666
|
}
|
|
42667
42667
|
}
|
|
42668
42668
|
}
|
|
42669
|
-
function validateCookiePath(
|
|
42670
|
-
for (const char of
|
|
42669
|
+
function validateCookiePath(path31) {
|
|
42670
|
+
for (const char of path31) {
|
|
42671
42671
|
const code = char.charCodeAt(0);
|
|
42672
42672
|
if (code < 33 || char === ";") {
|
|
42673
42673
|
throw new Error("Invalid cookie path");
|
|
@@ -43464,9 +43464,9 @@ var require_connection = __commonJS({
|
|
|
43464
43464
|
channels.open = diagnosticsChannel.channel("undici:websocket:open");
|
|
43465
43465
|
channels.close = diagnosticsChannel.channel("undici:websocket:close");
|
|
43466
43466
|
channels.socketError = diagnosticsChannel.channel("undici:websocket:socket_error");
|
|
43467
|
-
var
|
|
43467
|
+
var crypto4;
|
|
43468
43468
|
try {
|
|
43469
|
-
|
|
43469
|
+
crypto4 = require("crypto");
|
|
43470
43470
|
} catch {
|
|
43471
43471
|
}
|
|
43472
43472
|
function establishWebSocketConnection(url, protocols, ws, onEstablish, options) {
|
|
@@ -43485,7 +43485,7 @@ var require_connection = __commonJS({
|
|
|
43485
43485
|
const headersList = new Headers(options.headers)[kHeadersList];
|
|
43486
43486
|
request.headersList = headersList;
|
|
43487
43487
|
}
|
|
43488
|
-
const keyValue =
|
|
43488
|
+
const keyValue = crypto4.randomBytes(16).toString("base64");
|
|
43489
43489
|
request.headersList.append("sec-websocket-key", keyValue);
|
|
43490
43490
|
request.headersList.append("sec-websocket-version", "13");
|
|
43491
43491
|
for (const protocol of protocols) {
|
|
@@ -43514,7 +43514,7 @@ var require_connection = __commonJS({
|
|
|
43514
43514
|
return;
|
|
43515
43515
|
}
|
|
43516
43516
|
const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
|
|
43517
|
-
const digest =
|
|
43517
|
+
const digest = crypto4.createHash("sha1").update(keyValue + uid).digest("base64");
|
|
43518
43518
|
if (secWSAccept !== digest) {
|
|
43519
43519
|
failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header.");
|
|
43520
43520
|
return;
|
|
@@ -43594,9 +43594,9 @@ var require_frame = __commonJS({
|
|
|
43594
43594
|
"node_modules/undici/lib/websocket/frame.js"(exports2, module2) {
|
|
43595
43595
|
"use strict";
|
|
43596
43596
|
var { maxUnsigned16Bit } = require_constants5();
|
|
43597
|
-
var
|
|
43597
|
+
var crypto4;
|
|
43598
43598
|
try {
|
|
43599
|
-
|
|
43599
|
+
crypto4 = require("crypto");
|
|
43600
43600
|
} catch {
|
|
43601
43601
|
}
|
|
43602
43602
|
var WebsocketFrameSend = class {
|
|
@@ -43605,7 +43605,7 @@ var require_frame = __commonJS({
|
|
|
43605
43605
|
*/
|
|
43606
43606
|
constructor(data) {
|
|
43607
43607
|
this.frameData = data;
|
|
43608
|
-
this.maskKey =
|
|
43608
|
+
this.maskKey = crypto4.randomBytes(4);
|
|
43609
43609
|
}
|
|
43610
43610
|
createFrame(opcode) {
|
|
43611
43611
|
const bodyLength = this.frameData?.byteLength ?? 0;
|
|
@@ -44347,11 +44347,11 @@ var require_undici = __commonJS({
|
|
|
44347
44347
|
if (typeof opts.path !== "string") {
|
|
44348
44348
|
throw new InvalidArgumentError("invalid opts.path");
|
|
44349
44349
|
}
|
|
44350
|
-
let
|
|
44350
|
+
let path31 = opts.path;
|
|
44351
44351
|
if (!opts.path.startsWith("/")) {
|
|
44352
|
-
|
|
44352
|
+
path31 = `/${path31}`;
|
|
44353
44353
|
}
|
|
44354
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
44354
|
+
url = new URL(util.parseOrigin(url).origin + path31);
|
|
44355
44355
|
} else {
|
|
44356
44356
|
if (!opts) {
|
|
44357
44357
|
opts = typeof url === "object" ? url : {};
|
|
@@ -44900,7 +44900,7 @@ var init_mcp_check_provider = __esm({
|
|
|
44900
44900
|
logger.warn(
|
|
44901
44901
|
`MCP ${transportName} failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`
|
|
44902
44902
|
);
|
|
44903
|
-
await new Promise((
|
|
44903
|
+
await new Promise((resolve19) => setTimeout(resolve19, delay));
|
|
44904
44904
|
attempt += 1;
|
|
44905
44905
|
} finally {
|
|
44906
44906
|
try {
|
|
@@ -45193,7 +45193,7 @@ async function acquirePromptLock() {
|
|
|
45193
45193
|
);
|
|
45194
45194
|
}, 1e4);
|
|
45195
45195
|
try {
|
|
45196
|
-
await new Promise((
|
|
45196
|
+
await new Promise((resolve19) => waiters.push(resolve19));
|
|
45197
45197
|
} finally {
|
|
45198
45198
|
clearInterval(reminder);
|
|
45199
45199
|
const waitedMs = Date.now() - queuedAt;
|
|
@@ -45212,7 +45212,7 @@ function releasePromptLock() {
|
|
|
45212
45212
|
}
|
|
45213
45213
|
async function interactivePrompt(options) {
|
|
45214
45214
|
await acquirePromptLock();
|
|
45215
|
-
return new Promise((
|
|
45215
|
+
return new Promise((resolve19, reject) => {
|
|
45216
45216
|
const dbg = process.env.VISOR_DEBUG === "true";
|
|
45217
45217
|
try {
|
|
45218
45218
|
if (dbg) {
|
|
@@ -45299,12 +45299,12 @@ async function interactivePrompt(options) {
|
|
|
45299
45299
|
};
|
|
45300
45300
|
const finish = (value) => {
|
|
45301
45301
|
cleanup();
|
|
45302
|
-
|
|
45302
|
+
resolve19(value);
|
|
45303
45303
|
};
|
|
45304
45304
|
if (options.timeout && options.timeout > 0) {
|
|
45305
45305
|
timeoutId = setTimeout(() => {
|
|
45306
45306
|
cleanup();
|
|
45307
|
-
if (defaultValue !== void 0) return
|
|
45307
|
+
if (defaultValue !== void 0) return resolve19(defaultValue);
|
|
45308
45308
|
return reject(new Error("Input timeout"));
|
|
45309
45309
|
}, options.timeout);
|
|
45310
45310
|
}
|
|
@@ -45436,7 +45436,7 @@ async function interactivePrompt(options) {
|
|
|
45436
45436
|
});
|
|
45437
45437
|
}
|
|
45438
45438
|
async function simplePrompt(prompt) {
|
|
45439
|
-
return new Promise((
|
|
45439
|
+
return new Promise((resolve19) => {
|
|
45440
45440
|
const rl = readline.createInterface({
|
|
45441
45441
|
input: process.stdin,
|
|
45442
45442
|
output: process.stdout
|
|
@@ -45452,7 +45452,7 @@ async function simplePrompt(prompt) {
|
|
|
45452
45452
|
rl.question(`${prompt}
|
|
45453
45453
|
> `, (answer) => {
|
|
45454
45454
|
rl.close();
|
|
45455
|
-
|
|
45455
|
+
resolve19(answer.trim());
|
|
45456
45456
|
});
|
|
45457
45457
|
});
|
|
45458
45458
|
}
|
|
@@ -45620,7 +45620,7 @@ function isStdinAvailable() {
|
|
|
45620
45620
|
return !process.stdin.isTTY;
|
|
45621
45621
|
}
|
|
45622
45622
|
async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
45623
|
-
return new Promise((
|
|
45623
|
+
return new Promise((resolve19, reject) => {
|
|
45624
45624
|
let data = "";
|
|
45625
45625
|
let timeoutId;
|
|
45626
45626
|
if (timeout) {
|
|
@@ -45647,7 +45647,7 @@ async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
|
45647
45647
|
};
|
|
45648
45648
|
const onEnd = () => {
|
|
45649
45649
|
cleanup();
|
|
45650
|
-
|
|
45650
|
+
resolve19(data.trim());
|
|
45651
45651
|
};
|
|
45652
45652
|
const onError = (err) => {
|
|
45653
45653
|
cleanup();
|
|
@@ -49773,23 +49773,23 @@ __export(renderer_schema_exports, {
|
|
|
49773
49773
|
});
|
|
49774
49774
|
async function loadRendererSchema(name) {
|
|
49775
49775
|
try {
|
|
49776
|
-
const
|
|
49777
|
-
const
|
|
49776
|
+
const fs27 = await import("fs/promises");
|
|
49777
|
+
const path31 = await import("path");
|
|
49778
49778
|
const sanitized = String(name).replace(/[^a-zA-Z0-9-]/g, "");
|
|
49779
49779
|
if (!sanitized) return void 0;
|
|
49780
49780
|
const candidates = [
|
|
49781
49781
|
// When bundled with ncc, __dirname is dist/ and output/ is at dist/output/
|
|
49782
|
-
|
|
49782
|
+
path31.join(__dirname, "output", sanitized, "schema.json"),
|
|
49783
49783
|
// When running from source, __dirname is src/state-machine/dispatch/ and output/ is at output/
|
|
49784
|
-
|
|
49784
|
+
path31.join(__dirname, "..", "..", "output", sanitized, "schema.json"),
|
|
49785
49785
|
// When running from a checkout with output/ folder copied to CWD
|
|
49786
|
-
|
|
49786
|
+
path31.join(process.cwd(), "output", sanitized, "schema.json"),
|
|
49787
49787
|
// Fallback: cwd/dist/output/
|
|
49788
|
-
|
|
49788
|
+
path31.join(process.cwd(), "dist", "output", sanitized, "schema.json")
|
|
49789
49789
|
];
|
|
49790
49790
|
for (const p of candidates) {
|
|
49791
49791
|
try {
|
|
49792
|
-
const raw = await
|
|
49792
|
+
const raw = await fs27.readFile(p, "utf-8");
|
|
49793
49793
|
return JSON.parse(raw);
|
|
49794
49794
|
} catch {
|
|
49795
49795
|
}
|
|
@@ -52230,8 +52230,8 @@ function updateStats2(results, state, isForEachIteration = false) {
|
|
|
52230
52230
|
async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
52231
52231
|
try {
|
|
52232
52232
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
52233
|
-
const
|
|
52234
|
-
const
|
|
52233
|
+
const fs27 = await import("fs/promises");
|
|
52234
|
+
const path31 = await import("path");
|
|
52235
52235
|
const schemaRaw = checkConfig.schema || "plain";
|
|
52236
52236
|
const schema = typeof schemaRaw === "string" && !schemaRaw.includes("{{") && !schemaRaw.includes("{%") ? schemaRaw : typeof schemaRaw === "object" ? "code-review" : "plain";
|
|
52237
52237
|
let templateContent;
|
|
@@ -52240,27 +52240,27 @@ async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
|
52240
52240
|
logger.debug(`[LevelDispatch] Using inline template for ${checkId}`);
|
|
52241
52241
|
} else if (checkConfig.template && checkConfig.template.file) {
|
|
52242
52242
|
const file = String(checkConfig.template.file);
|
|
52243
|
-
const resolved =
|
|
52244
|
-
templateContent = await
|
|
52243
|
+
const resolved = path31.resolve(process.cwd(), file);
|
|
52244
|
+
templateContent = await fs27.readFile(resolved, "utf-8");
|
|
52245
52245
|
logger.debug(`[LevelDispatch] Using template file for ${checkId}: ${resolved}`);
|
|
52246
52246
|
} else if (schema && schema !== "plain") {
|
|
52247
52247
|
const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
|
|
52248
52248
|
if (sanitized) {
|
|
52249
52249
|
const candidatePaths = [
|
|
52250
|
-
|
|
52250
|
+
path31.join(__dirname, "output", sanitized, "template.liquid"),
|
|
52251
52251
|
// bundled: dist/output/
|
|
52252
|
-
|
|
52252
|
+
path31.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
52253
52253
|
// source (from state-machine/states)
|
|
52254
|
-
|
|
52254
|
+
path31.join(__dirname, "..", "..", "..", "output", sanitized, "template.liquid"),
|
|
52255
52255
|
// source (alternate)
|
|
52256
|
-
|
|
52256
|
+
path31.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
52257
52257
|
// fallback: cwd/output/
|
|
52258
|
-
|
|
52258
|
+
path31.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
|
|
52259
52259
|
// fallback: cwd/dist/output/
|
|
52260
52260
|
];
|
|
52261
52261
|
for (const p of candidatePaths) {
|
|
52262
52262
|
try {
|
|
52263
|
-
templateContent = await
|
|
52263
|
+
templateContent = await fs27.readFile(p, "utf-8");
|
|
52264
52264
|
if (templateContent) {
|
|
52265
52265
|
logger.debug(`[LevelDispatch] Using schema template for ${checkId}: ${p}`);
|
|
52266
52266
|
break;
|
|
@@ -54400,8 +54400,8 @@ var init_workspace_manager = __esm({
|
|
|
54400
54400
|
);
|
|
54401
54401
|
if (this.cleanupRequested && this.activeOperations === 0) {
|
|
54402
54402
|
logger.debug(`[Workspace] All references released, proceeding with deferred cleanup`);
|
|
54403
|
-
for (const
|
|
54404
|
-
|
|
54403
|
+
for (const resolve19 of this.cleanupResolvers) {
|
|
54404
|
+
resolve19();
|
|
54405
54405
|
}
|
|
54406
54406
|
this.cleanupResolvers = [];
|
|
54407
54407
|
}
|
|
@@ -54558,19 +54558,19 @@ var init_workspace_manager = __esm({
|
|
|
54558
54558
|
);
|
|
54559
54559
|
this.cleanupRequested = true;
|
|
54560
54560
|
await Promise.race([
|
|
54561
|
-
new Promise((
|
|
54561
|
+
new Promise((resolve19) => {
|
|
54562
54562
|
if (this.activeOperations === 0) {
|
|
54563
|
-
|
|
54563
|
+
resolve19();
|
|
54564
54564
|
} else {
|
|
54565
|
-
this.cleanupResolvers.push(
|
|
54565
|
+
this.cleanupResolvers.push(resolve19);
|
|
54566
54566
|
}
|
|
54567
54567
|
}),
|
|
54568
|
-
new Promise((
|
|
54568
|
+
new Promise((resolve19) => {
|
|
54569
54569
|
setTimeout(() => {
|
|
54570
54570
|
logger.warn(
|
|
54571
54571
|
`[Workspace] Cleanup timeout after ${timeout}ms, proceeding anyway (${this.activeOperations} operations still active)`
|
|
54572
54572
|
);
|
|
54573
|
-
|
|
54573
|
+
resolve19();
|
|
54574
54574
|
}, timeout);
|
|
54575
54575
|
})
|
|
54576
54576
|
]);
|
|
@@ -54964,8 +54964,8 @@ var init_fair_concurrency_limiter = __esm({
|
|
|
54964
54964
|
);
|
|
54965
54965
|
const queuedAt = Date.now();
|
|
54966
54966
|
const effectiveTimeout = queueTimeout ?? 12e4;
|
|
54967
|
-
return new Promise((
|
|
54968
|
-
const entry = { resolve:
|
|
54967
|
+
return new Promise((resolve19, reject) => {
|
|
54968
|
+
const entry = { resolve: resolve19, reject, queuedAt };
|
|
54969
54969
|
entry.reminder = setInterval(() => {
|
|
54970
54970
|
const waited = Math.round((Date.now() - queuedAt) / 1e3);
|
|
54971
54971
|
const curQueued = this._totalQueued();
|
|
@@ -55272,6 +55272,1380 @@ var init_build_engine_context = __esm({
|
|
|
55272
55272
|
}
|
|
55273
55273
|
});
|
|
55274
55274
|
|
|
55275
|
+
// src/policy/default-engine.ts
|
|
55276
|
+
var DefaultPolicyEngine;
|
|
55277
|
+
var init_default_engine = __esm({
|
|
55278
|
+
"src/policy/default-engine.ts"() {
|
|
55279
|
+
"use strict";
|
|
55280
|
+
DefaultPolicyEngine = class {
|
|
55281
|
+
async initialize(_config) {
|
|
55282
|
+
}
|
|
55283
|
+
async evaluateCheckExecution(_checkId, _checkConfig) {
|
|
55284
|
+
return { allowed: true };
|
|
55285
|
+
}
|
|
55286
|
+
async evaluateToolInvocation(_serverName, _methodName, _transport) {
|
|
55287
|
+
return { allowed: true };
|
|
55288
|
+
}
|
|
55289
|
+
async evaluateCapabilities(_checkId, _capabilities) {
|
|
55290
|
+
return { allowed: true };
|
|
55291
|
+
}
|
|
55292
|
+
async shutdown() {
|
|
55293
|
+
}
|
|
55294
|
+
};
|
|
55295
|
+
}
|
|
55296
|
+
});
|
|
55297
|
+
|
|
55298
|
+
// src/enterprise/license/validator.ts
|
|
55299
|
+
var validator_exports = {};
|
|
55300
|
+
__export(validator_exports, {
|
|
55301
|
+
LicenseValidator: () => LicenseValidator
|
|
55302
|
+
});
|
|
55303
|
+
var crypto2, fs21, path25, LicenseValidator;
|
|
55304
|
+
var init_validator = __esm({
|
|
55305
|
+
"src/enterprise/license/validator.ts"() {
|
|
55306
|
+
"use strict";
|
|
55307
|
+
crypto2 = __toESM(require("crypto"));
|
|
55308
|
+
fs21 = __toESM(require("fs"));
|
|
55309
|
+
path25 = __toESM(require("path"));
|
|
55310
|
+
LicenseValidator = class _LicenseValidator {
|
|
55311
|
+
/** Ed25519 public key for license verification (PEM format). */
|
|
55312
|
+
static PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAI/Zd08EFmgIdrDm/HXd0l3/5GBt7R1PrdvhdmEXhJlU=\n-----END PUBLIC KEY-----\n";
|
|
55313
|
+
cache = null;
|
|
55314
|
+
static CACHE_TTL = 5 * 60 * 1e3;
|
|
55315
|
+
// 5 minutes
|
|
55316
|
+
static GRACE_PERIOD = 72 * 3600 * 1e3;
|
|
55317
|
+
// 72 hours after expiry
|
|
55318
|
+
/**
|
|
55319
|
+
* Load and validate license from environment or file.
|
|
55320
|
+
*
|
|
55321
|
+
* Resolution order:
|
|
55322
|
+
* 1. VISOR_LICENSE env var (JWT string)
|
|
55323
|
+
* 2. VISOR_LICENSE_FILE env var (path to file)
|
|
55324
|
+
* 3. .visor-license in project root (cwd)
|
|
55325
|
+
* 4. .visor-license in ~/.config/visor/
|
|
55326
|
+
*/
|
|
55327
|
+
async loadAndValidate() {
|
|
55328
|
+
if (this.cache && Date.now() - this.cache.validatedAt < _LicenseValidator.CACHE_TTL) {
|
|
55329
|
+
return this.cache.payload;
|
|
55330
|
+
}
|
|
55331
|
+
const token = this.resolveToken();
|
|
55332
|
+
if (!token) return null;
|
|
55333
|
+
const payload = this.verifyAndDecode(token);
|
|
55334
|
+
if (!payload) return null;
|
|
55335
|
+
this.cache = { payload, validatedAt: Date.now() };
|
|
55336
|
+
return payload;
|
|
55337
|
+
}
|
|
55338
|
+
/** Check if a specific feature is licensed */
|
|
55339
|
+
hasFeature(feature) {
|
|
55340
|
+
if (!this.cache) return false;
|
|
55341
|
+
return this.cache.payload.features.includes(feature);
|
|
55342
|
+
}
|
|
55343
|
+
/** Check if license is valid (with grace period) */
|
|
55344
|
+
isValid() {
|
|
55345
|
+
if (!this.cache) return false;
|
|
55346
|
+
const now = Date.now();
|
|
55347
|
+
const expiryMs = this.cache.payload.exp * 1e3;
|
|
55348
|
+
return now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
55349
|
+
}
|
|
55350
|
+
/** Check if the license is within its grace period (expired but still valid) */
|
|
55351
|
+
isInGracePeriod() {
|
|
55352
|
+
if (!this.cache) return false;
|
|
55353
|
+
const now = Date.now();
|
|
55354
|
+
const expiryMs = this.cache.payload.exp * 1e3;
|
|
55355
|
+
return now >= expiryMs && now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
55356
|
+
}
|
|
55357
|
+
resolveToken() {
|
|
55358
|
+
if (process.env.VISOR_LICENSE) {
|
|
55359
|
+
return process.env.VISOR_LICENSE.trim();
|
|
55360
|
+
}
|
|
55361
|
+
if (process.env.VISOR_LICENSE_FILE) {
|
|
55362
|
+
const resolved = path25.resolve(process.env.VISOR_LICENSE_FILE);
|
|
55363
|
+
const home2 = process.env.HOME || process.env.USERPROFILE || "";
|
|
55364
|
+
const allowedPrefixes = [path25.normalize(process.cwd())];
|
|
55365
|
+
if (home2) allowedPrefixes.push(path25.normalize(path25.join(home2, ".config", "visor")));
|
|
55366
|
+
let realPath;
|
|
55367
|
+
try {
|
|
55368
|
+
realPath = fs21.realpathSync(resolved);
|
|
55369
|
+
} catch {
|
|
55370
|
+
return null;
|
|
55371
|
+
}
|
|
55372
|
+
const isSafe = allowedPrefixes.some(
|
|
55373
|
+
(prefix) => realPath === prefix || realPath.startsWith(prefix + path25.sep)
|
|
55374
|
+
);
|
|
55375
|
+
if (!isSafe) return null;
|
|
55376
|
+
return this.readFile(realPath);
|
|
55377
|
+
}
|
|
55378
|
+
const cwdPath = path25.join(process.cwd(), ".visor-license");
|
|
55379
|
+
const cwdToken = this.readFile(cwdPath);
|
|
55380
|
+
if (cwdToken) return cwdToken;
|
|
55381
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
55382
|
+
if (home) {
|
|
55383
|
+
const configPath = path25.join(home, ".config", "visor", ".visor-license");
|
|
55384
|
+
const configToken = this.readFile(configPath);
|
|
55385
|
+
if (configToken) return configToken;
|
|
55386
|
+
}
|
|
55387
|
+
return null;
|
|
55388
|
+
}
|
|
55389
|
+
readFile(filePath) {
|
|
55390
|
+
try {
|
|
55391
|
+
return fs21.readFileSync(filePath, "utf-8").trim();
|
|
55392
|
+
} catch {
|
|
55393
|
+
return null;
|
|
55394
|
+
}
|
|
55395
|
+
}
|
|
55396
|
+
verifyAndDecode(token) {
|
|
55397
|
+
try {
|
|
55398
|
+
const parts = token.split(".");
|
|
55399
|
+
if (parts.length !== 3) return null;
|
|
55400
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
55401
|
+
const header = JSON.parse(Buffer.from(headerB64, "base64url").toString());
|
|
55402
|
+
if (header.alg !== "EdDSA") return null;
|
|
55403
|
+
const data = `${headerB64}.${payloadB64}`;
|
|
55404
|
+
const signature = Buffer.from(signatureB64, "base64url");
|
|
55405
|
+
const publicKey = crypto2.createPublicKey(_LicenseValidator.PUBLIC_KEY);
|
|
55406
|
+
if (publicKey.asymmetricKeyType !== "ed25519") {
|
|
55407
|
+
return null;
|
|
55408
|
+
}
|
|
55409
|
+
const isValid = crypto2.verify(null, Buffer.from(data), publicKey, signature);
|
|
55410
|
+
if (!isValid) return null;
|
|
55411
|
+
const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
|
|
55412
|
+
if (!payload.org || !Array.isArray(payload.features) || typeof payload.exp !== "number" || typeof payload.iat !== "number" || !payload.sub) {
|
|
55413
|
+
return null;
|
|
55414
|
+
}
|
|
55415
|
+
const now = Date.now();
|
|
55416
|
+
const expiryMs = payload.exp * 1e3;
|
|
55417
|
+
if (now >= expiryMs + _LicenseValidator.GRACE_PERIOD) {
|
|
55418
|
+
return null;
|
|
55419
|
+
}
|
|
55420
|
+
return payload;
|
|
55421
|
+
} catch {
|
|
55422
|
+
return null;
|
|
55423
|
+
}
|
|
55424
|
+
}
|
|
55425
|
+
};
|
|
55426
|
+
}
|
|
55427
|
+
});
|
|
55428
|
+
|
|
55429
|
+
// src/enterprise/policy/opa-compiler.ts
|
|
55430
|
+
var fs22, path26, os2, crypto3, import_child_process8, OpaCompiler;
|
|
55431
|
+
var init_opa_compiler = __esm({
|
|
55432
|
+
"src/enterprise/policy/opa-compiler.ts"() {
|
|
55433
|
+
"use strict";
|
|
55434
|
+
fs22 = __toESM(require("fs"));
|
|
55435
|
+
path26 = __toESM(require("path"));
|
|
55436
|
+
os2 = __toESM(require("os"));
|
|
55437
|
+
crypto3 = __toESM(require("crypto"));
|
|
55438
|
+
import_child_process8 = require("child_process");
|
|
55439
|
+
OpaCompiler = class _OpaCompiler {
|
|
55440
|
+
static CACHE_DIR = path26.join(os2.tmpdir(), "visor-opa-cache");
|
|
55441
|
+
/**
|
|
55442
|
+
* Resolve the input paths to WASM bytes.
|
|
55443
|
+
*
|
|
55444
|
+
* Strategy:
|
|
55445
|
+
* 1. If any path is a .wasm file, read it directly
|
|
55446
|
+
* 2. If a directory contains policy.wasm, read it
|
|
55447
|
+
* 3. Otherwise, collect all .rego files and auto-compile via `opa build`
|
|
55448
|
+
*/
|
|
55449
|
+
async resolveWasmBytes(paths) {
|
|
55450
|
+
const regoFiles = [];
|
|
55451
|
+
for (const p of paths) {
|
|
55452
|
+
const resolved = path26.resolve(p);
|
|
55453
|
+
if (path26.normalize(resolved).includes("..")) {
|
|
55454
|
+
throw new Error(`Policy path contains traversal sequences: ${p}`);
|
|
55455
|
+
}
|
|
55456
|
+
if (resolved.endsWith(".wasm") && fs22.existsSync(resolved)) {
|
|
55457
|
+
return fs22.readFileSync(resolved);
|
|
55458
|
+
}
|
|
55459
|
+
if (!fs22.existsSync(resolved)) continue;
|
|
55460
|
+
const stat2 = fs22.statSync(resolved);
|
|
55461
|
+
if (stat2.isDirectory()) {
|
|
55462
|
+
const wasmCandidate = path26.join(resolved, "policy.wasm");
|
|
55463
|
+
if (fs22.existsSync(wasmCandidate)) {
|
|
55464
|
+
return fs22.readFileSync(wasmCandidate);
|
|
55465
|
+
}
|
|
55466
|
+
const files = fs22.readdirSync(resolved);
|
|
55467
|
+
for (const f of files) {
|
|
55468
|
+
if (f.endsWith(".rego")) {
|
|
55469
|
+
regoFiles.push(path26.join(resolved, f));
|
|
55470
|
+
}
|
|
55471
|
+
}
|
|
55472
|
+
} else if (resolved.endsWith(".rego")) {
|
|
55473
|
+
regoFiles.push(resolved);
|
|
55474
|
+
}
|
|
55475
|
+
}
|
|
55476
|
+
if (regoFiles.length === 0) {
|
|
55477
|
+
throw new Error(
|
|
55478
|
+
`OPA WASM evaluator: no .wasm bundle or .rego files found in: ${paths.join(", ")}`
|
|
55479
|
+
);
|
|
55480
|
+
}
|
|
55481
|
+
return this.compileRego(regoFiles);
|
|
55482
|
+
}
|
|
55483
|
+
/**
|
|
55484
|
+
* Auto-compile .rego files to a WASM bundle using the `opa` CLI.
|
|
55485
|
+
*
|
|
55486
|
+
* Caches the compiled bundle based on a content hash of all input .rego files
|
|
55487
|
+
* so subsequent runs skip compilation if policies haven't changed.
|
|
55488
|
+
*/
|
|
55489
|
+
compileRego(regoFiles) {
|
|
55490
|
+
try {
|
|
55491
|
+
(0, import_child_process8.execFileSync)("opa", ["version"], { stdio: "pipe" });
|
|
55492
|
+
} catch {
|
|
55493
|
+
throw new Error(
|
|
55494
|
+
"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(" ")
|
|
55495
|
+
);
|
|
55496
|
+
}
|
|
55497
|
+
const hash = crypto3.createHash("sha256");
|
|
55498
|
+
for (const f of regoFiles.sort()) {
|
|
55499
|
+
hash.update(fs22.readFileSync(f));
|
|
55500
|
+
hash.update(f);
|
|
55501
|
+
}
|
|
55502
|
+
const cacheKey = hash.digest("hex").slice(0, 16);
|
|
55503
|
+
const cacheDir = _OpaCompiler.CACHE_DIR;
|
|
55504
|
+
const cachedWasm = path26.join(cacheDir, `${cacheKey}.wasm`);
|
|
55505
|
+
if (fs22.existsSync(cachedWasm)) {
|
|
55506
|
+
return fs22.readFileSync(cachedWasm);
|
|
55507
|
+
}
|
|
55508
|
+
fs22.mkdirSync(cacheDir, { recursive: true });
|
|
55509
|
+
const bundleTar = path26.join(cacheDir, `${cacheKey}-bundle.tar.gz`);
|
|
55510
|
+
try {
|
|
55511
|
+
const args = [
|
|
55512
|
+
"build",
|
|
55513
|
+
"-t",
|
|
55514
|
+
"wasm",
|
|
55515
|
+
"-e",
|
|
55516
|
+
"visor",
|
|
55517
|
+
// entrypoint: the visor package tree
|
|
55518
|
+
"-o",
|
|
55519
|
+
bundleTar,
|
|
55520
|
+
...regoFiles
|
|
55521
|
+
];
|
|
55522
|
+
(0, import_child_process8.execFileSync)("opa", args, {
|
|
55523
|
+
stdio: "pipe",
|
|
55524
|
+
timeout: 3e4
|
|
55525
|
+
});
|
|
55526
|
+
} catch (err) {
|
|
55527
|
+
const stderr = err?.stderr?.toString() || "";
|
|
55528
|
+
throw new Error(
|
|
55529
|
+
`Failed to compile .rego files to WASM:
|
|
55530
|
+
${stderr}
|
|
55531
|
+
Ensure your .rego files are valid and the \`opa\` CLI is installed.`
|
|
55532
|
+
);
|
|
55533
|
+
}
|
|
55534
|
+
try {
|
|
55535
|
+
(0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "/policy.wasm"], {
|
|
55536
|
+
stdio: "pipe"
|
|
55537
|
+
});
|
|
55538
|
+
const extractedWasm = path26.join(cacheDir, "policy.wasm");
|
|
55539
|
+
if (fs22.existsSync(extractedWasm)) {
|
|
55540
|
+
fs22.renameSync(extractedWasm, cachedWasm);
|
|
55541
|
+
}
|
|
55542
|
+
} catch {
|
|
55543
|
+
try {
|
|
55544
|
+
(0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "policy.wasm"], {
|
|
55545
|
+
stdio: "pipe"
|
|
55546
|
+
});
|
|
55547
|
+
const extractedWasm = path26.join(cacheDir, "policy.wasm");
|
|
55548
|
+
if (fs22.existsSync(extractedWasm)) {
|
|
55549
|
+
fs22.renameSync(extractedWasm, cachedWasm);
|
|
55550
|
+
}
|
|
55551
|
+
} catch (err2) {
|
|
55552
|
+
throw new Error(`Failed to extract policy.wasm from OPA bundle: ${err2?.message || err2}`);
|
|
55553
|
+
}
|
|
55554
|
+
}
|
|
55555
|
+
try {
|
|
55556
|
+
fs22.unlinkSync(bundleTar);
|
|
55557
|
+
} catch {
|
|
55558
|
+
}
|
|
55559
|
+
if (!fs22.existsSync(cachedWasm)) {
|
|
55560
|
+
throw new Error("OPA build succeeded but policy.wasm was not found in the bundle");
|
|
55561
|
+
}
|
|
55562
|
+
return fs22.readFileSync(cachedWasm);
|
|
55563
|
+
}
|
|
55564
|
+
};
|
|
55565
|
+
}
|
|
55566
|
+
});
|
|
55567
|
+
|
|
55568
|
+
// src/enterprise/policy/opa-wasm-evaluator.ts
|
|
55569
|
+
var fs23, path27, OpaWasmEvaluator;
|
|
55570
|
+
var init_opa_wasm_evaluator = __esm({
|
|
55571
|
+
"src/enterprise/policy/opa-wasm-evaluator.ts"() {
|
|
55572
|
+
"use strict";
|
|
55573
|
+
fs23 = __toESM(require("fs"));
|
|
55574
|
+
path27 = __toESM(require("path"));
|
|
55575
|
+
init_opa_compiler();
|
|
55576
|
+
OpaWasmEvaluator = class {
|
|
55577
|
+
policy = null;
|
|
55578
|
+
dataDocument = {};
|
|
55579
|
+
compiler = new OpaCompiler();
|
|
55580
|
+
async initialize(rulesPath) {
|
|
55581
|
+
const paths = Array.isArray(rulesPath) ? rulesPath : [rulesPath];
|
|
55582
|
+
const wasmBytes = await this.compiler.resolveWasmBytes(paths);
|
|
55583
|
+
try {
|
|
55584
|
+
const { createRequire } = require("module");
|
|
55585
|
+
const runtimeRequire = createRequire(__filename);
|
|
55586
|
+
const opaWasm = runtimeRequire("@open-policy-agent/opa-wasm");
|
|
55587
|
+
const loadPolicy = opaWasm.loadPolicy || opaWasm.default?.loadPolicy;
|
|
55588
|
+
if (!loadPolicy) {
|
|
55589
|
+
throw new Error("loadPolicy not found in @open-policy-agent/opa-wasm");
|
|
55590
|
+
}
|
|
55591
|
+
this.policy = await loadPolicy(wasmBytes);
|
|
55592
|
+
} catch (err) {
|
|
55593
|
+
if (err?.code === "MODULE_NOT_FOUND" || err?.code === "ERR_MODULE_NOT_FOUND") {
|
|
55594
|
+
throw new Error(
|
|
55595
|
+
"OPA WASM evaluator requires @open-policy-agent/opa-wasm. Install it with: npm install @open-policy-agent/opa-wasm"
|
|
55596
|
+
);
|
|
55597
|
+
}
|
|
55598
|
+
throw err;
|
|
55599
|
+
}
|
|
55600
|
+
}
|
|
55601
|
+
/**
|
|
55602
|
+
* Load external data from a JSON file to use as the OPA data document.
|
|
55603
|
+
* The loaded data will be passed to `policy.setData()` during evaluation,
|
|
55604
|
+
* making it available in Rego via `data.<key>`.
|
|
55605
|
+
*/
|
|
55606
|
+
loadData(dataPath) {
|
|
55607
|
+
const resolved = path27.resolve(dataPath);
|
|
55608
|
+
if (path27.normalize(resolved).includes("..")) {
|
|
55609
|
+
throw new Error(`Data path contains traversal sequences: ${dataPath}`);
|
|
55610
|
+
}
|
|
55611
|
+
if (!fs23.existsSync(resolved)) {
|
|
55612
|
+
throw new Error(`OPA data file not found: ${resolved}`);
|
|
55613
|
+
}
|
|
55614
|
+
const stat2 = fs23.statSync(resolved);
|
|
55615
|
+
if (stat2.size > 10 * 1024 * 1024) {
|
|
55616
|
+
throw new Error(`OPA data file exceeds 10MB limit: ${resolved} (${stat2.size} bytes)`);
|
|
55617
|
+
}
|
|
55618
|
+
const raw = fs23.readFileSync(resolved, "utf-8");
|
|
55619
|
+
try {
|
|
55620
|
+
const parsed = JSON.parse(raw);
|
|
55621
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
55622
|
+
throw new Error("OPA data file must contain a JSON object (not an array or primitive)");
|
|
55623
|
+
}
|
|
55624
|
+
this.dataDocument = parsed;
|
|
55625
|
+
} catch (err) {
|
|
55626
|
+
if (err.message.startsWith("OPA data file must")) {
|
|
55627
|
+
throw err;
|
|
55628
|
+
}
|
|
55629
|
+
throw new Error(`Failed to parse OPA data file ${resolved}: ${err.message}`);
|
|
55630
|
+
}
|
|
55631
|
+
}
|
|
55632
|
+
async evaluate(input) {
|
|
55633
|
+
if (!this.policy) {
|
|
55634
|
+
throw new Error("OPA WASM evaluator not initialized");
|
|
55635
|
+
}
|
|
55636
|
+
this.policy.setData(this.dataDocument);
|
|
55637
|
+
const resultSet = this.policy.evaluate(input);
|
|
55638
|
+
if (Array.isArray(resultSet) && resultSet.length > 0) {
|
|
55639
|
+
return resultSet[0].result;
|
|
55640
|
+
}
|
|
55641
|
+
return void 0;
|
|
55642
|
+
}
|
|
55643
|
+
async shutdown() {
|
|
55644
|
+
if (this.policy) {
|
|
55645
|
+
if (typeof this.policy.close === "function") {
|
|
55646
|
+
try {
|
|
55647
|
+
this.policy.close();
|
|
55648
|
+
} catch {
|
|
55649
|
+
}
|
|
55650
|
+
} else if (typeof this.policy.free === "function") {
|
|
55651
|
+
try {
|
|
55652
|
+
this.policy.free();
|
|
55653
|
+
} catch {
|
|
55654
|
+
}
|
|
55655
|
+
}
|
|
55656
|
+
}
|
|
55657
|
+
this.policy = null;
|
|
55658
|
+
}
|
|
55659
|
+
};
|
|
55660
|
+
}
|
|
55661
|
+
});
|
|
55662
|
+
|
|
55663
|
+
// src/enterprise/policy/opa-http-evaluator.ts
|
|
55664
|
+
var OpaHttpEvaluator;
|
|
55665
|
+
var init_opa_http_evaluator = __esm({
|
|
55666
|
+
"src/enterprise/policy/opa-http-evaluator.ts"() {
|
|
55667
|
+
"use strict";
|
|
55668
|
+
OpaHttpEvaluator = class {
|
|
55669
|
+
baseUrl;
|
|
55670
|
+
timeout;
|
|
55671
|
+
constructor(baseUrl, timeout = 5e3) {
|
|
55672
|
+
let parsed;
|
|
55673
|
+
try {
|
|
55674
|
+
parsed = new URL(baseUrl);
|
|
55675
|
+
} catch {
|
|
55676
|
+
throw new Error(`OPA HTTP evaluator: invalid URL: ${baseUrl}`);
|
|
55677
|
+
}
|
|
55678
|
+
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
55679
|
+
throw new Error(
|
|
55680
|
+
`OPA HTTP evaluator: url must use http:// or https:// protocol, got: ${baseUrl}`
|
|
55681
|
+
);
|
|
55682
|
+
}
|
|
55683
|
+
const hostname = parsed.hostname;
|
|
55684
|
+
if (this.isBlockedHostname(hostname)) {
|
|
55685
|
+
throw new Error(
|
|
55686
|
+
`OPA HTTP evaluator: url must not point to internal, loopback, or private network addresses`
|
|
55687
|
+
);
|
|
55688
|
+
}
|
|
55689
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
55690
|
+
this.timeout = timeout;
|
|
55691
|
+
}
|
|
55692
|
+
/**
|
|
55693
|
+
* Check if a hostname is blocked due to SSRF concerns.
|
|
55694
|
+
*
|
|
55695
|
+
* Blocks:
|
|
55696
|
+
* - Loopback addresses (127.x.x.x, localhost, 0.0.0.0, ::1)
|
|
55697
|
+
* - Link-local addresses (169.254.x.x)
|
|
55698
|
+
* - Private networks (10.x.x.x, 172.16-31.x.x, 192.168.x.x)
|
|
55699
|
+
* - IPv6 unique local addresses (fd00::/8)
|
|
55700
|
+
* - Cloud metadata services (*.internal)
|
|
55701
|
+
*/
|
|
55702
|
+
isBlockedHostname(hostname) {
|
|
55703
|
+
if (!hostname) return true;
|
|
55704
|
+
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
55705
|
+
if (normalized === "metadata.google.internal" || normalized.endsWith(".internal")) {
|
|
55706
|
+
return true;
|
|
55707
|
+
}
|
|
55708
|
+
if (normalized === "localhost" || normalized === "localhost.localdomain") {
|
|
55709
|
+
return true;
|
|
55710
|
+
}
|
|
55711
|
+
if (normalized === "::1" || normalized === "0:0:0:0:0:0:0:1") {
|
|
55712
|
+
return true;
|
|
55713
|
+
}
|
|
55714
|
+
const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
55715
|
+
const ipv4Match = normalized.match(ipv4Pattern);
|
|
55716
|
+
if (ipv4Match) {
|
|
55717
|
+
const octets = ipv4Match.slice(1, 5).map(Number);
|
|
55718
|
+
if (octets.some((octet) => octet > 255)) {
|
|
55719
|
+
return false;
|
|
55720
|
+
}
|
|
55721
|
+
const [a, b] = octets;
|
|
55722
|
+
if (a === 127) {
|
|
55723
|
+
return true;
|
|
55724
|
+
}
|
|
55725
|
+
if (a === 0) {
|
|
55726
|
+
return true;
|
|
55727
|
+
}
|
|
55728
|
+
if (a === 169 && b === 254) {
|
|
55729
|
+
return true;
|
|
55730
|
+
}
|
|
55731
|
+
if (a === 10) {
|
|
55732
|
+
return true;
|
|
55733
|
+
}
|
|
55734
|
+
if (a === 172 && b >= 16 && b <= 31) {
|
|
55735
|
+
return true;
|
|
55736
|
+
}
|
|
55737
|
+
if (a === 192 && b === 168) {
|
|
55738
|
+
return true;
|
|
55739
|
+
}
|
|
55740
|
+
}
|
|
55741
|
+
if (normalized.startsWith("fd") || normalized.startsWith("fc")) {
|
|
55742
|
+
return true;
|
|
55743
|
+
}
|
|
55744
|
+
if (normalized.startsWith("fe80:")) {
|
|
55745
|
+
return true;
|
|
55746
|
+
}
|
|
55747
|
+
return false;
|
|
55748
|
+
}
|
|
55749
|
+
/**
|
|
55750
|
+
* Evaluate a policy rule against an input document via OPA REST API.
|
|
55751
|
+
*
|
|
55752
|
+
* @param input - The input document to evaluate
|
|
55753
|
+
* @param rulePath - OPA rule path (e.g., 'visor/check/execute')
|
|
55754
|
+
* @returns The result object from OPA, or undefined on error
|
|
55755
|
+
*/
|
|
55756
|
+
async evaluate(input, rulePath) {
|
|
55757
|
+
const encodedPath = rulePath.split("/").map((s) => encodeURIComponent(s)).join("/");
|
|
55758
|
+
const url = `${this.baseUrl}/v1/data/${encodedPath}`;
|
|
55759
|
+
const controller = new AbortController();
|
|
55760
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
55761
|
+
try {
|
|
55762
|
+
const response = await fetch(url, {
|
|
55763
|
+
method: "POST",
|
|
55764
|
+
headers: { "Content-Type": "application/json" },
|
|
55765
|
+
body: JSON.stringify({ input }),
|
|
55766
|
+
signal: controller.signal
|
|
55767
|
+
});
|
|
55768
|
+
if (!response.ok) {
|
|
55769
|
+
throw new Error(`OPA HTTP ${response.status}: ${response.statusText}`);
|
|
55770
|
+
}
|
|
55771
|
+
let body;
|
|
55772
|
+
try {
|
|
55773
|
+
body = await response.json();
|
|
55774
|
+
} catch (jsonErr) {
|
|
55775
|
+
throw new Error(
|
|
55776
|
+
`OPA HTTP evaluator: failed to parse JSON response: ${jsonErr instanceof Error ? jsonErr.message : String(jsonErr)}`
|
|
55777
|
+
);
|
|
55778
|
+
}
|
|
55779
|
+
return body?.result;
|
|
55780
|
+
} finally {
|
|
55781
|
+
clearTimeout(timer);
|
|
55782
|
+
}
|
|
55783
|
+
}
|
|
55784
|
+
async shutdown() {
|
|
55785
|
+
}
|
|
55786
|
+
};
|
|
55787
|
+
}
|
|
55788
|
+
});
|
|
55789
|
+
|
|
55790
|
+
// src/enterprise/policy/policy-input-builder.ts
|
|
55791
|
+
var PolicyInputBuilder;
|
|
55792
|
+
var init_policy_input_builder = __esm({
|
|
55793
|
+
"src/enterprise/policy/policy-input-builder.ts"() {
|
|
55794
|
+
"use strict";
|
|
55795
|
+
PolicyInputBuilder = class {
|
|
55796
|
+
roles;
|
|
55797
|
+
actor;
|
|
55798
|
+
repository;
|
|
55799
|
+
pullRequest;
|
|
55800
|
+
constructor(policyConfig, actor, repository, pullRequest) {
|
|
55801
|
+
this.roles = policyConfig.roles || {};
|
|
55802
|
+
this.actor = actor;
|
|
55803
|
+
this.repository = repository;
|
|
55804
|
+
this.pullRequest = pullRequest;
|
|
55805
|
+
}
|
|
55806
|
+
/** Resolve which roles apply to the current actor. */
|
|
55807
|
+
resolveRoles() {
|
|
55808
|
+
const matched = [];
|
|
55809
|
+
for (const [roleName, roleConfig] of Object.entries(this.roles)) {
|
|
55810
|
+
let identityMatch = false;
|
|
55811
|
+
if (roleConfig.author_association && this.actor.authorAssociation && roleConfig.author_association.includes(this.actor.authorAssociation)) {
|
|
55812
|
+
identityMatch = true;
|
|
55813
|
+
}
|
|
55814
|
+
if (!identityMatch && roleConfig.users && this.actor.login && roleConfig.users.includes(this.actor.login)) {
|
|
55815
|
+
identityMatch = true;
|
|
55816
|
+
}
|
|
55817
|
+
if (!identityMatch && roleConfig.slack_users && this.actor.slack?.userId && roleConfig.slack_users.includes(this.actor.slack.userId)) {
|
|
55818
|
+
identityMatch = true;
|
|
55819
|
+
}
|
|
55820
|
+
if (!identityMatch && roleConfig.emails && this.actor.slack?.email) {
|
|
55821
|
+
const actorEmail = this.actor.slack.email.toLowerCase();
|
|
55822
|
+
if (roleConfig.emails.some((e) => e.toLowerCase() === actorEmail)) {
|
|
55823
|
+
identityMatch = true;
|
|
55824
|
+
}
|
|
55825
|
+
}
|
|
55826
|
+
if (!identityMatch) continue;
|
|
55827
|
+
if (roleConfig.slack_channels && roleConfig.slack_channels.length > 0) {
|
|
55828
|
+
if (!this.actor.slack?.channelId || !roleConfig.slack_channels.includes(this.actor.slack.channelId)) {
|
|
55829
|
+
continue;
|
|
55830
|
+
}
|
|
55831
|
+
}
|
|
55832
|
+
matched.push(roleName);
|
|
55833
|
+
}
|
|
55834
|
+
return matched;
|
|
55835
|
+
}
|
|
55836
|
+
buildActor() {
|
|
55837
|
+
return {
|
|
55838
|
+
authorAssociation: this.actor.authorAssociation,
|
|
55839
|
+
login: this.actor.login,
|
|
55840
|
+
roles: this.resolveRoles(),
|
|
55841
|
+
isLocalMode: this.actor.isLocalMode,
|
|
55842
|
+
...this.actor.slack && { slack: this.actor.slack }
|
|
55843
|
+
};
|
|
55844
|
+
}
|
|
55845
|
+
forCheckExecution(check) {
|
|
55846
|
+
return {
|
|
55847
|
+
scope: "check.execute",
|
|
55848
|
+
check: {
|
|
55849
|
+
id: check.id,
|
|
55850
|
+
type: check.type,
|
|
55851
|
+
group: check.group,
|
|
55852
|
+
tags: check.tags,
|
|
55853
|
+
criticality: check.criticality,
|
|
55854
|
+
sandbox: check.sandbox,
|
|
55855
|
+
policy: check.policy
|
|
55856
|
+
},
|
|
55857
|
+
actor: this.buildActor(),
|
|
55858
|
+
repository: this.repository,
|
|
55859
|
+
pullRequest: this.pullRequest
|
|
55860
|
+
};
|
|
55861
|
+
}
|
|
55862
|
+
forToolInvocation(serverName, methodName, transport) {
|
|
55863
|
+
return {
|
|
55864
|
+
scope: "tool.invoke",
|
|
55865
|
+
tool: { serverName, methodName, transport },
|
|
55866
|
+
actor: this.buildActor(),
|
|
55867
|
+
repository: this.repository,
|
|
55868
|
+
pullRequest: this.pullRequest
|
|
55869
|
+
};
|
|
55870
|
+
}
|
|
55871
|
+
forCapabilityResolve(checkId, capabilities) {
|
|
55872
|
+
return {
|
|
55873
|
+
scope: "capability.resolve",
|
|
55874
|
+
check: { id: checkId, type: "ai" },
|
|
55875
|
+
capability: capabilities,
|
|
55876
|
+
actor: this.buildActor(),
|
|
55877
|
+
repository: this.repository,
|
|
55878
|
+
pullRequest: this.pullRequest
|
|
55879
|
+
};
|
|
55880
|
+
}
|
|
55881
|
+
};
|
|
55882
|
+
}
|
|
55883
|
+
});
|
|
55884
|
+
|
|
55885
|
+
// src/enterprise/policy/opa-policy-engine.ts
|
|
55886
|
+
var opa_policy_engine_exports = {};
|
|
55887
|
+
__export(opa_policy_engine_exports, {
|
|
55888
|
+
OpaPolicyEngine: () => OpaPolicyEngine
|
|
55889
|
+
});
|
|
55890
|
+
var OpaPolicyEngine;
|
|
55891
|
+
var init_opa_policy_engine = __esm({
|
|
55892
|
+
"src/enterprise/policy/opa-policy-engine.ts"() {
|
|
55893
|
+
"use strict";
|
|
55894
|
+
init_opa_wasm_evaluator();
|
|
55895
|
+
init_opa_http_evaluator();
|
|
55896
|
+
init_policy_input_builder();
|
|
55897
|
+
OpaPolicyEngine = class {
|
|
55898
|
+
evaluator = null;
|
|
55899
|
+
fallback;
|
|
55900
|
+
timeout;
|
|
55901
|
+
config;
|
|
55902
|
+
inputBuilder = null;
|
|
55903
|
+
logger = null;
|
|
55904
|
+
constructor(config) {
|
|
55905
|
+
this.config = config;
|
|
55906
|
+
this.fallback = config.fallback || "deny";
|
|
55907
|
+
this.timeout = config.timeout || 5e3;
|
|
55908
|
+
}
|
|
55909
|
+
async initialize(config) {
|
|
55910
|
+
try {
|
|
55911
|
+
this.logger = (init_logger(), __toCommonJS(logger_exports)).logger;
|
|
55912
|
+
} catch {
|
|
55913
|
+
}
|
|
55914
|
+
const actor = {
|
|
55915
|
+
authorAssociation: process.env.VISOR_AUTHOR_ASSOCIATION,
|
|
55916
|
+
login: process.env.VISOR_AUTHOR_LOGIN || process.env.GITHUB_ACTOR,
|
|
55917
|
+
isLocalMode: !process.env.GITHUB_ACTIONS
|
|
55918
|
+
};
|
|
55919
|
+
const repo = {
|
|
55920
|
+
owner: process.env.GITHUB_REPOSITORY_OWNER,
|
|
55921
|
+
name: process.env.GITHUB_REPOSITORY?.split("/")[1],
|
|
55922
|
+
branch: process.env.GITHUB_HEAD_REF,
|
|
55923
|
+
baseBranch: process.env.GITHUB_BASE_REF,
|
|
55924
|
+
event: process.env.GITHUB_EVENT_NAME
|
|
55925
|
+
};
|
|
55926
|
+
const prNum = process.env.GITHUB_PR_NUMBER ? parseInt(process.env.GITHUB_PR_NUMBER, 10) : void 0;
|
|
55927
|
+
const pullRequest = {
|
|
55928
|
+
number: prNum !== void 0 && Number.isFinite(prNum) ? prNum : void 0
|
|
55929
|
+
};
|
|
55930
|
+
this.inputBuilder = new PolicyInputBuilder(config, actor, repo, pullRequest);
|
|
55931
|
+
if (config.engine === "local") {
|
|
55932
|
+
if (!config.rules) {
|
|
55933
|
+
throw new Error("OPA local mode requires `policy.rules` path to .wasm or .rego files");
|
|
55934
|
+
}
|
|
55935
|
+
const wasm = new OpaWasmEvaluator();
|
|
55936
|
+
await wasm.initialize(config.rules);
|
|
55937
|
+
if (config.data) {
|
|
55938
|
+
wasm.loadData(config.data);
|
|
55939
|
+
}
|
|
55940
|
+
this.evaluator = wasm;
|
|
55941
|
+
} else if (config.engine === "remote") {
|
|
55942
|
+
if (!config.url) {
|
|
55943
|
+
throw new Error("OPA remote mode requires `policy.url` pointing to OPA server");
|
|
55944
|
+
}
|
|
55945
|
+
this.evaluator = new OpaHttpEvaluator(config.url, this.timeout);
|
|
55946
|
+
} else {
|
|
55947
|
+
this.evaluator = null;
|
|
55948
|
+
}
|
|
55949
|
+
}
|
|
55950
|
+
/**
|
|
55951
|
+
* Update actor/repo/PR context (e.g., after PR info becomes available).
|
|
55952
|
+
* Called by the enterprise loader when engine context is enriched.
|
|
55953
|
+
*/
|
|
55954
|
+
setActorContext(actor, repo, pullRequest) {
|
|
55955
|
+
this.inputBuilder = new PolicyInputBuilder(this.config, actor, repo, pullRequest);
|
|
55956
|
+
}
|
|
55957
|
+
async evaluateCheckExecution(checkId, checkConfig) {
|
|
55958
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
55959
|
+
const cfg = checkConfig && typeof checkConfig === "object" ? checkConfig : {};
|
|
55960
|
+
const policyOverride = cfg.policy;
|
|
55961
|
+
const input = this.inputBuilder.forCheckExecution({
|
|
55962
|
+
id: checkId,
|
|
55963
|
+
type: cfg.type || "ai",
|
|
55964
|
+
group: cfg.group,
|
|
55965
|
+
tags: cfg.tags,
|
|
55966
|
+
criticality: cfg.criticality,
|
|
55967
|
+
sandbox: cfg.sandbox,
|
|
55968
|
+
policy: policyOverride
|
|
55969
|
+
});
|
|
55970
|
+
return this.doEvaluate(input, this.resolveRulePath("check.execute", policyOverride?.rule));
|
|
55971
|
+
}
|
|
55972
|
+
async evaluateToolInvocation(serverName, methodName, transport) {
|
|
55973
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
55974
|
+
const input = this.inputBuilder.forToolInvocation(serverName, methodName, transport);
|
|
55975
|
+
return this.doEvaluate(input, "visor/tool/invoke");
|
|
55976
|
+
}
|
|
55977
|
+
async evaluateCapabilities(checkId, capabilities) {
|
|
55978
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
55979
|
+
const input = this.inputBuilder.forCapabilityResolve(checkId, capabilities);
|
|
55980
|
+
return this.doEvaluate(input, "visor/capability/resolve");
|
|
55981
|
+
}
|
|
55982
|
+
async shutdown() {
|
|
55983
|
+
if (this.evaluator && "shutdown" in this.evaluator) {
|
|
55984
|
+
await this.evaluator.shutdown();
|
|
55985
|
+
}
|
|
55986
|
+
this.evaluator = null;
|
|
55987
|
+
this.inputBuilder = null;
|
|
55988
|
+
}
|
|
55989
|
+
resolveRulePath(defaultScope, override) {
|
|
55990
|
+
if (override) {
|
|
55991
|
+
return override.startsWith("visor/") ? override : `visor/${override}`;
|
|
55992
|
+
}
|
|
55993
|
+
return `visor/${defaultScope.replace(/\./g, "/")}`;
|
|
55994
|
+
}
|
|
55995
|
+
async doEvaluate(input, rulePath) {
|
|
55996
|
+
try {
|
|
55997
|
+
this.logger?.debug(`[PolicyEngine] Evaluating ${rulePath}`, JSON.stringify(input));
|
|
55998
|
+
let timer;
|
|
55999
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
56000
|
+
timer = setTimeout(() => reject(new Error("policy evaluation timeout")), this.timeout);
|
|
56001
|
+
});
|
|
56002
|
+
try {
|
|
56003
|
+
const result = await Promise.race([this.rawEvaluate(input, rulePath), timeoutPromise]);
|
|
56004
|
+
const decision = this.parseDecision(result);
|
|
56005
|
+
if (!decision.allowed && this.fallback === "warn") {
|
|
56006
|
+
decision.allowed = true;
|
|
56007
|
+
decision.warn = true;
|
|
56008
|
+
decision.reason = `audit: ${decision.reason || "policy denied"}`;
|
|
56009
|
+
}
|
|
56010
|
+
this.logger?.debug(
|
|
56011
|
+
`[PolicyEngine] Decision for ${rulePath}: allowed=${decision.allowed}, warn=${decision.warn || false}, reason=${decision.reason || "none"}`
|
|
56012
|
+
);
|
|
56013
|
+
return decision;
|
|
56014
|
+
} finally {
|
|
56015
|
+
if (timer) clearTimeout(timer);
|
|
56016
|
+
}
|
|
56017
|
+
} catch (err) {
|
|
56018
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
56019
|
+
this.logger?.warn(`[PolicyEngine] Evaluation failed for ${rulePath}: ${msg}`);
|
|
56020
|
+
return {
|
|
56021
|
+
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
56022
|
+
warn: this.fallback === "warn" ? true : void 0,
|
|
56023
|
+
reason: `policy evaluation failed, fallback=${this.fallback}`
|
|
56024
|
+
};
|
|
56025
|
+
}
|
|
56026
|
+
}
|
|
56027
|
+
async rawEvaluate(input, rulePath) {
|
|
56028
|
+
if (this.evaluator instanceof OpaWasmEvaluator) {
|
|
56029
|
+
const result = await this.evaluator.evaluate(input);
|
|
56030
|
+
return this.navigateWasmResult(result, rulePath);
|
|
56031
|
+
}
|
|
56032
|
+
return this.evaluator.evaluate(input, rulePath);
|
|
56033
|
+
}
|
|
56034
|
+
/**
|
|
56035
|
+
* Navigate nested OPA WASM result tree to reach the specific rule's output.
|
|
56036
|
+
* The WASM entrypoint `-e visor` means the result root IS the visor package,
|
|
56037
|
+
* so we strip the `visor/` prefix and walk the remaining segments.
|
|
56038
|
+
*/
|
|
56039
|
+
navigateWasmResult(result, rulePath) {
|
|
56040
|
+
if (!result || typeof result !== "object") return result;
|
|
56041
|
+
const segments = rulePath.replace(/^visor\//, "").split("/");
|
|
56042
|
+
let current = result;
|
|
56043
|
+
for (const seg of segments) {
|
|
56044
|
+
if (current && typeof current === "object" && seg in current) {
|
|
56045
|
+
current = current[seg];
|
|
56046
|
+
} else {
|
|
56047
|
+
return void 0;
|
|
56048
|
+
}
|
|
56049
|
+
}
|
|
56050
|
+
return current;
|
|
56051
|
+
}
|
|
56052
|
+
parseDecision(result) {
|
|
56053
|
+
if (result === void 0 || result === null) {
|
|
56054
|
+
return {
|
|
56055
|
+
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
56056
|
+
warn: this.fallback === "warn" ? true : void 0,
|
|
56057
|
+
reason: this.fallback === "warn" ? "audit: no policy result" : "no policy result"
|
|
56058
|
+
};
|
|
56059
|
+
}
|
|
56060
|
+
const allowed = result.allowed !== false;
|
|
56061
|
+
const decision = {
|
|
56062
|
+
allowed,
|
|
56063
|
+
reason: result.reason
|
|
56064
|
+
};
|
|
56065
|
+
if (result.capabilities) {
|
|
56066
|
+
decision.capabilities = result.capabilities;
|
|
56067
|
+
}
|
|
56068
|
+
return decision;
|
|
56069
|
+
}
|
|
56070
|
+
};
|
|
56071
|
+
}
|
|
56072
|
+
});
|
|
56073
|
+
|
|
56074
|
+
// src/enterprise/scheduler/knex-store.ts
|
|
56075
|
+
var knex_store_exports = {};
|
|
56076
|
+
__export(knex_store_exports, {
|
|
56077
|
+
KnexStoreBackend: () => KnexStoreBackend
|
|
56078
|
+
});
|
|
56079
|
+
function toNum(val) {
|
|
56080
|
+
if (val === null || val === void 0) return void 0;
|
|
56081
|
+
return typeof val === "string" ? parseInt(val, 10) : val;
|
|
56082
|
+
}
|
|
56083
|
+
function safeJsonParse2(value) {
|
|
56084
|
+
if (!value) return void 0;
|
|
56085
|
+
try {
|
|
56086
|
+
return JSON.parse(value);
|
|
56087
|
+
} catch {
|
|
56088
|
+
return void 0;
|
|
56089
|
+
}
|
|
56090
|
+
}
|
|
56091
|
+
function fromTriggerRow2(row) {
|
|
56092
|
+
return {
|
|
56093
|
+
id: row.id,
|
|
56094
|
+
creatorId: row.creator_id,
|
|
56095
|
+
creatorContext: row.creator_context ?? void 0,
|
|
56096
|
+
creatorName: row.creator_name ?? void 0,
|
|
56097
|
+
description: row.description ?? void 0,
|
|
56098
|
+
channels: safeJsonParse2(row.channels),
|
|
56099
|
+
fromUsers: safeJsonParse2(row.from_users),
|
|
56100
|
+
fromBots: row.from_bots === true || row.from_bots === 1,
|
|
56101
|
+
contains: safeJsonParse2(row.contains),
|
|
56102
|
+
matchPattern: row.match_pattern ?? void 0,
|
|
56103
|
+
threads: row.threads,
|
|
56104
|
+
workflow: row.workflow,
|
|
56105
|
+
inputs: safeJsonParse2(row.inputs),
|
|
56106
|
+
outputContext: safeJsonParse2(row.output_context),
|
|
56107
|
+
status: row.status,
|
|
56108
|
+
enabled: row.enabled === true || row.enabled === 1,
|
|
56109
|
+
createdAt: toNum(row.created_at)
|
|
56110
|
+
};
|
|
56111
|
+
}
|
|
56112
|
+
function toTriggerInsertRow(trigger) {
|
|
56113
|
+
return {
|
|
56114
|
+
id: trigger.id,
|
|
56115
|
+
creator_id: trigger.creatorId,
|
|
56116
|
+
creator_context: trigger.creatorContext ?? null,
|
|
56117
|
+
creator_name: trigger.creatorName ?? null,
|
|
56118
|
+
description: trigger.description ?? null,
|
|
56119
|
+
channels: trigger.channels ? JSON.stringify(trigger.channels) : null,
|
|
56120
|
+
from_users: trigger.fromUsers ? JSON.stringify(trigger.fromUsers) : null,
|
|
56121
|
+
from_bots: trigger.fromBots,
|
|
56122
|
+
contains: trigger.contains ? JSON.stringify(trigger.contains) : null,
|
|
56123
|
+
match_pattern: trigger.matchPattern ?? null,
|
|
56124
|
+
threads: trigger.threads,
|
|
56125
|
+
workflow: trigger.workflow,
|
|
56126
|
+
inputs: trigger.inputs ? JSON.stringify(trigger.inputs) : null,
|
|
56127
|
+
output_context: trigger.outputContext ? JSON.stringify(trigger.outputContext) : null,
|
|
56128
|
+
status: trigger.status,
|
|
56129
|
+
enabled: trigger.enabled,
|
|
56130
|
+
created_at: trigger.createdAt
|
|
56131
|
+
};
|
|
56132
|
+
}
|
|
56133
|
+
function fromDbRow2(row) {
|
|
56134
|
+
return {
|
|
56135
|
+
id: row.id,
|
|
56136
|
+
creatorId: row.creator_id,
|
|
56137
|
+
creatorContext: row.creator_context ?? void 0,
|
|
56138
|
+
creatorName: row.creator_name ?? void 0,
|
|
56139
|
+
timezone: row.timezone,
|
|
56140
|
+
schedule: row.schedule_expr,
|
|
56141
|
+
runAt: toNum(row.run_at),
|
|
56142
|
+
isRecurring: row.is_recurring === true || row.is_recurring === 1,
|
|
56143
|
+
originalExpression: row.original_expression,
|
|
56144
|
+
workflow: row.workflow ?? void 0,
|
|
56145
|
+
workflowInputs: safeJsonParse2(row.workflow_inputs),
|
|
56146
|
+
outputContext: safeJsonParse2(row.output_context),
|
|
56147
|
+
status: row.status,
|
|
56148
|
+
createdAt: toNum(row.created_at),
|
|
56149
|
+
lastRunAt: toNum(row.last_run_at),
|
|
56150
|
+
nextRunAt: toNum(row.next_run_at),
|
|
56151
|
+
runCount: row.run_count,
|
|
56152
|
+
failureCount: row.failure_count,
|
|
56153
|
+
lastError: row.last_error ?? void 0,
|
|
56154
|
+
previousResponse: row.previous_response ?? void 0
|
|
56155
|
+
};
|
|
56156
|
+
}
|
|
56157
|
+
function toInsertRow(schedule) {
|
|
56158
|
+
return {
|
|
56159
|
+
id: schedule.id,
|
|
56160
|
+
creator_id: schedule.creatorId,
|
|
56161
|
+
creator_context: schedule.creatorContext ?? null,
|
|
56162
|
+
creator_name: schedule.creatorName ?? null,
|
|
56163
|
+
timezone: schedule.timezone,
|
|
56164
|
+
schedule_expr: schedule.schedule,
|
|
56165
|
+
run_at: schedule.runAt ?? null,
|
|
56166
|
+
is_recurring: schedule.isRecurring,
|
|
56167
|
+
original_expression: schedule.originalExpression,
|
|
56168
|
+
workflow: schedule.workflow ?? null,
|
|
56169
|
+
workflow_inputs: schedule.workflowInputs ? JSON.stringify(schedule.workflowInputs) : null,
|
|
56170
|
+
output_context: schedule.outputContext ? JSON.stringify(schedule.outputContext) : null,
|
|
56171
|
+
status: schedule.status,
|
|
56172
|
+
created_at: schedule.createdAt,
|
|
56173
|
+
last_run_at: schedule.lastRunAt ?? null,
|
|
56174
|
+
next_run_at: schedule.nextRunAt ?? null,
|
|
56175
|
+
run_count: schedule.runCount,
|
|
56176
|
+
failure_count: schedule.failureCount,
|
|
56177
|
+
last_error: schedule.lastError ?? null,
|
|
56178
|
+
previous_response: schedule.previousResponse ?? null
|
|
56179
|
+
};
|
|
56180
|
+
}
|
|
56181
|
+
var fs24, path28, import_uuid2, KnexStoreBackend;
|
|
56182
|
+
var init_knex_store = __esm({
|
|
56183
|
+
"src/enterprise/scheduler/knex-store.ts"() {
|
|
56184
|
+
"use strict";
|
|
56185
|
+
fs24 = __toESM(require("fs"));
|
|
56186
|
+
path28 = __toESM(require("path"));
|
|
56187
|
+
import_uuid2 = require("uuid");
|
|
56188
|
+
init_logger();
|
|
56189
|
+
KnexStoreBackend = class {
|
|
56190
|
+
knex = null;
|
|
56191
|
+
driver;
|
|
56192
|
+
connection;
|
|
56193
|
+
constructor(driver, storageConfig, _haConfig) {
|
|
56194
|
+
this.driver = driver;
|
|
56195
|
+
this.connection = storageConfig.connection || {};
|
|
56196
|
+
}
|
|
56197
|
+
async initialize() {
|
|
56198
|
+
const { createRequire } = require("module");
|
|
56199
|
+
const runtimeRequire = createRequire(__filename);
|
|
56200
|
+
let knexFactory;
|
|
56201
|
+
try {
|
|
56202
|
+
knexFactory = runtimeRequire("knex");
|
|
56203
|
+
} catch (err) {
|
|
56204
|
+
const code = err?.code;
|
|
56205
|
+
if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
|
|
56206
|
+
throw new Error(
|
|
56207
|
+
"knex is required for PostgreSQL/MySQL/MSSQL schedule storage. Install it with: npm install knex"
|
|
56208
|
+
);
|
|
56209
|
+
}
|
|
56210
|
+
throw err;
|
|
56211
|
+
}
|
|
56212
|
+
const clientMap = {
|
|
56213
|
+
postgresql: "pg",
|
|
56214
|
+
mysql: "mysql2",
|
|
56215
|
+
mssql: "tedious"
|
|
56216
|
+
};
|
|
56217
|
+
const client = clientMap[this.driver];
|
|
56218
|
+
let connection;
|
|
56219
|
+
if (this.connection.connection_string) {
|
|
56220
|
+
connection = this.connection.connection_string;
|
|
56221
|
+
} else if (this.driver === "mssql") {
|
|
56222
|
+
connection = this.buildMssqlConnection();
|
|
56223
|
+
} else {
|
|
56224
|
+
connection = this.buildStandardConnection();
|
|
56225
|
+
}
|
|
56226
|
+
this.knex = knexFactory({
|
|
56227
|
+
client,
|
|
56228
|
+
connection,
|
|
56229
|
+
pool: {
|
|
56230
|
+
min: this.connection.pool?.min ?? 0,
|
|
56231
|
+
max: this.connection.pool?.max ?? 10
|
|
56232
|
+
}
|
|
56233
|
+
});
|
|
56234
|
+
await this.migrateSchema();
|
|
56235
|
+
logger.info(`[KnexStore] Initialized (${this.driver})`);
|
|
56236
|
+
}
|
|
56237
|
+
buildStandardConnection() {
|
|
56238
|
+
return {
|
|
56239
|
+
host: this.connection.host || "localhost",
|
|
56240
|
+
port: this.connection.port,
|
|
56241
|
+
database: this.connection.database || "visor",
|
|
56242
|
+
user: this.connection.user,
|
|
56243
|
+
password: this.connection.password,
|
|
56244
|
+
ssl: this.resolveSslConfig()
|
|
56245
|
+
};
|
|
56246
|
+
}
|
|
56247
|
+
buildMssqlConnection() {
|
|
56248
|
+
const ssl = this.connection.ssl;
|
|
56249
|
+
const sslEnabled = ssl === true || typeof ssl === "object" && ssl.enabled !== false;
|
|
56250
|
+
return {
|
|
56251
|
+
server: this.connection.host || "localhost",
|
|
56252
|
+
port: this.connection.port,
|
|
56253
|
+
database: this.connection.database || "visor",
|
|
56254
|
+
user: this.connection.user,
|
|
56255
|
+
password: this.connection.password,
|
|
56256
|
+
options: {
|
|
56257
|
+
encrypt: sslEnabled,
|
|
56258
|
+
trustServerCertificate: typeof ssl === "object" ? ssl.reject_unauthorized === false : !sslEnabled
|
|
56259
|
+
}
|
|
56260
|
+
};
|
|
56261
|
+
}
|
|
56262
|
+
resolveSslConfig() {
|
|
56263
|
+
const ssl = this.connection.ssl;
|
|
56264
|
+
if (ssl === false || ssl === void 0) return false;
|
|
56265
|
+
if (ssl === true) return { rejectUnauthorized: true };
|
|
56266
|
+
if (ssl.enabled === false) return false;
|
|
56267
|
+
const result = {
|
|
56268
|
+
rejectUnauthorized: ssl.reject_unauthorized !== false
|
|
56269
|
+
};
|
|
56270
|
+
if (ssl.ca) {
|
|
56271
|
+
const caPath = this.validateSslPath(ssl.ca, "CA certificate");
|
|
56272
|
+
result.ca = fs24.readFileSync(caPath, "utf8");
|
|
56273
|
+
}
|
|
56274
|
+
if (ssl.cert) {
|
|
56275
|
+
const certPath = this.validateSslPath(ssl.cert, "client certificate");
|
|
56276
|
+
result.cert = fs24.readFileSync(certPath, "utf8");
|
|
56277
|
+
}
|
|
56278
|
+
if (ssl.key) {
|
|
56279
|
+
const keyPath = this.validateSslPath(ssl.key, "client key");
|
|
56280
|
+
result.key = fs24.readFileSync(keyPath, "utf8");
|
|
56281
|
+
}
|
|
56282
|
+
return result;
|
|
56283
|
+
}
|
|
56284
|
+
validateSslPath(filePath, label) {
|
|
56285
|
+
const resolved = path28.resolve(filePath);
|
|
56286
|
+
if (resolved !== path28.normalize(resolved)) {
|
|
56287
|
+
throw new Error(`SSL ${label} path contains invalid sequences: ${filePath}`);
|
|
56288
|
+
}
|
|
56289
|
+
if (!fs24.existsSync(resolved)) {
|
|
56290
|
+
throw new Error(`SSL ${label} not found: ${filePath}`);
|
|
56291
|
+
}
|
|
56292
|
+
return resolved;
|
|
56293
|
+
}
|
|
56294
|
+
async shutdown() {
|
|
56295
|
+
if (this.knex) {
|
|
56296
|
+
await this.knex.destroy();
|
|
56297
|
+
this.knex = null;
|
|
56298
|
+
}
|
|
56299
|
+
}
|
|
56300
|
+
async migrateSchema() {
|
|
56301
|
+
const knex = this.getKnex();
|
|
56302
|
+
const exists = await knex.schema.hasTable("schedules");
|
|
56303
|
+
if (!exists) {
|
|
56304
|
+
await knex.schema.createTable("schedules", (table) => {
|
|
56305
|
+
table.string("id", 36).primary();
|
|
56306
|
+
table.string("creator_id", 255).notNullable().index();
|
|
56307
|
+
table.string("creator_context", 255);
|
|
56308
|
+
table.string("creator_name", 255);
|
|
56309
|
+
table.string("timezone", 64).notNullable().defaultTo("UTC");
|
|
56310
|
+
table.string("schedule_expr", 255);
|
|
56311
|
+
table.bigInteger("run_at");
|
|
56312
|
+
table.boolean("is_recurring").notNullable();
|
|
56313
|
+
table.text("original_expression");
|
|
56314
|
+
table.string("workflow", 255);
|
|
56315
|
+
table.text("workflow_inputs");
|
|
56316
|
+
table.text("output_context");
|
|
56317
|
+
table.string("status", 20).notNullable().index();
|
|
56318
|
+
table.bigInteger("created_at").notNullable();
|
|
56319
|
+
table.bigInteger("last_run_at");
|
|
56320
|
+
table.bigInteger("next_run_at");
|
|
56321
|
+
table.integer("run_count").notNullable().defaultTo(0);
|
|
56322
|
+
table.integer("failure_count").notNullable().defaultTo(0);
|
|
56323
|
+
table.text("last_error");
|
|
56324
|
+
table.text("previous_response");
|
|
56325
|
+
table.index(["status", "next_run_at"]);
|
|
56326
|
+
});
|
|
56327
|
+
}
|
|
56328
|
+
const triggersExist = await knex.schema.hasTable("message_triggers");
|
|
56329
|
+
if (!triggersExist) {
|
|
56330
|
+
await knex.schema.createTable("message_triggers", (table) => {
|
|
56331
|
+
table.string("id", 36).primary();
|
|
56332
|
+
table.string("creator_id", 255).notNullable().index();
|
|
56333
|
+
table.string("creator_context", 255);
|
|
56334
|
+
table.string("creator_name", 255);
|
|
56335
|
+
table.text("description");
|
|
56336
|
+
table.text("channels");
|
|
56337
|
+
table.text("from_users");
|
|
56338
|
+
table.boolean("from_bots").notNullable().defaultTo(false);
|
|
56339
|
+
table.text("contains");
|
|
56340
|
+
table.text("match_pattern");
|
|
56341
|
+
table.string("threads", 20).notNullable().defaultTo("any");
|
|
56342
|
+
table.string("workflow", 255).notNullable();
|
|
56343
|
+
table.text("inputs");
|
|
56344
|
+
table.text("output_context");
|
|
56345
|
+
table.string("status", 20).notNullable().defaultTo("active").index();
|
|
56346
|
+
table.boolean("enabled").notNullable().defaultTo(true);
|
|
56347
|
+
table.bigInteger("created_at").notNullable();
|
|
56348
|
+
});
|
|
56349
|
+
}
|
|
56350
|
+
const locksExist = await knex.schema.hasTable("scheduler_locks");
|
|
56351
|
+
if (!locksExist) {
|
|
56352
|
+
await knex.schema.createTable("scheduler_locks", (table) => {
|
|
56353
|
+
table.string("lock_id", 255).primary();
|
|
56354
|
+
table.string("node_id", 255).notNullable();
|
|
56355
|
+
table.string("lock_token", 36).notNullable();
|
|
56356
|
+
table.bigInteger("acquired_at").notNullable();
|
|
56357
|
+
table.bigInteger("expires_at").notNullable();
|
|
56358
|
+
});
|
|
56359
|
+
}
|
|
56360
|
+
}
|
|
56361
|
+
getKnex() {
|
|
56362
|
+
if (!this.knex) {
|
|
56363
|
+
throw new Error("[KnexStore] Not initialized. Call initialize() first.");
|
|
56364
|
+
}
|
|
56365
|
+
return this.knex;
|
|
56366
|
+
}
|
|
56367
|
+
// --- CRUD ---
|
|
56368
|
+
async create(schedule) {
|
|
56369
|
+
const knex = this.getKnex();
|
|
56370
|
+
const newSchedule = {
|
|
56371
|
+
...schedule,
|
|
56372
|
+
id: (0, import_uuid2.v4)(),
|
|
56373
|
+
createdAt: Date.now(),
|
|
56374
|
+
runCount: 0,
|
|
56375
|
+
failureCount: 0,
|
|
56376
|
+
status: "active"
|
|
56377
|
+
};
|
|
56378
|
+
await knex("schedules").insert(toInsertRow(newSchedule));
|
|
56379
|
+
logger.info(`[KnexStore] Created schedule ${newSchedule.id} for user ${newSchedule.creatorId}`);
|
|
56380
|
+
return newSchedule;
|
|
56381
|
+
}
|
|
56382
|
+
async importSchedule(schedule) {
|
|
56383
|
+
const knex = this.getKnex();
|
|
56384
|
+
const existing = await knex("schedules").where("id", schedule.id).first();
|
|
56385
|
+
if (existing) return;
|
|
56386
|
+
await knex("schedules").insert(toInsertRow(schedule));
|
|
56387
|
+
}
|
|
56388
|
+
async get(id) {
|
|
56389
|
+
const knex = this.getKnex();
|
|
56390
|
+
const row = await knex("schedules").where("id", id).first();
|
|
56391
|
+
return row ? fromDbRow2(row) : void 0;
|
|
56392
|
+
}
|
|
56393
|
+
async update(id, patch) {
|
|
56394
|
+
const knex = this.getKnex();
|
|
56395
|
+
const existing = await knex("schedules").where("id", id).first();
|
|
56396
|
+
if (!existing) return void 0;
|
|
56397
|
+
const current = fromDbRow2(existing);
|
|
56398
|
+
const updated = { ...current, ...patch, id: current.id };
|
|
56399
|
+
const row = toInsertRow(updated);
|
|
56400
|
+
delete row.id;
|
|
56401
|
+
await knex("schedules").where("id", id).update(row);
|
|
56402
|
+
return updated;
|
|
56403
|
+
}
|
|
56404
|
+
async delete(id) {
|
|
56405
|
+
const knex = this.getKnex();
|
|
56406
|
+
const deleted = await knex("schedules").where("id", id).del();
|
|
56407
|
+
if (deleted > 0) {
|
|
56408
|
+
logger.info(`[KnexStore] Deleted schedule ${id}`);
|
|
56409
|
+
return true;
|
|
56410
|
+
}
|
|
56411
|
+
return false;
|
|
56412
|
+
}
|
|
56413
|
+
// --- Queries ---
|
|
56414
|
+
async getByCreator(creatorId) {
|
|
56415
|
+
const knex = this.getKnex();
|
|
56416
|
+
const rows = await knex("schedules").where("creator_id", creatorId);
|
|
56417
|
+
return rows.map((r) => fromDbRow2(r));
|
|
56418
|
+
}
|
|
56419
|
+
async getActiveSchedules() {
|
|
56420
|
+
const knex = this.getKnex();
|
|
56421
|
+
const rows = await knex("schedules").where("status", "active");
|
|
56422
|
+
return rows.map((r) => fromDbRow2(r));
|
|
56423
|
+
}
|
|
56424
|
+
async getDueSchedules(now) {
|
|
56425
|
+
const ts = now ?? Date.now();
|
|
56426
|
+
const knex = this.getKnex();
|
|
56427
|
+
const bFalse = this.driver === "mssql" ? 0 : false;
|
|
56428
|
+
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
56429
|
+
const rows = await knex("schedules").where("status", "active").andWhere(function() {
|
|
56430
|
+
this.where(function() {
|
|
56431
|
+
this.where("is_recurring", bFalse).whereNotNull("run_at").where("run_at", "<=", ts);
|
|
56432
|
+
}).orWhere(function() {
|
|
56433
|
+
this.where("is_recurring", bTrue).whereNotNull("next_run_at").where("next_run_at", "<=", ts);
|
|
56434
|
+
});
|
|
56435
|
+
});
|
|
56436
|
+
return rows.map((r) => fromDbRow2(r));
|
|
56437
|
+
}
|
|
56438
|
+
async findByWorkflow(creatorId, workflowName) {
|
|
56439
|
+
const knex = this.getKnex();
|
|
56440
|
+
const escaped = workflowName.toLowerCase().replace(/[%_\\]/g, "\\$&");
|
|
56441
|
+
const pattern = `%${escaped}%`;
|
|
56442
|
+
const rows = await knex("schedules").where("creator_id", creatorId).where("status", "active").whereRaw("LOWER(workflow) LIKE ? ESCAPE '\\'", [pattern]);
|
|
56443
|
+
return rows.map((r) => fromDbRow2(r));
|
|
56444
|
+
}
|
|
56445
|
+
async getAll() {
|
|
56446
|
+
const knex = this.getKnex();
|
|
56447
|
+
const rows = await knex("schedules");
|
|
56448
|
+
return rows.map((r) => fromDbRow2(r));
|
|
56449
|
+
}
|
|
56450
|
+
async getStats() {
|
|
56451
|
+
const knex = this.getKnex();
|
|
56452
|
+
const boolTrue = this.driver === "mssql" ? "1" : "true";
|
|
56453
|
+
const boolFalse = this.driver === "mssql" ? "0" : "false";
|
|
56454
|
+
const result = await knex("schedules").select(
|
|
56455
|
+
knex.raw("COUNT(*) as total"),
|
|
56456
|
+
knex.raw("SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active"),
|
|
56457
|
+
knex.raw("SUM(CASE WHEN status = 'paused' THEN 1 ELSE 0 END) as paused"),
|
|
56458
|
+
knex.raw("SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed"),
|
|
56459
|
+
knex.raw("SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed"),
|
|
56460
|
+
knex.raw(`SUM(CASE WHEN is_recurring = ${boolTrue} THEN 1 ELSE 0 END) as recurring`),
|
|
56461
|
+
knex.raw(`SUM(CASE WHEN is_recurring = ${boolFalse} THEN 1 ELSE 0 END) as one_time`)
|
|
56462
|
+
).first();
|
|
56463
|
+
return {
|
|
56464
|
+
total: Number(result.total) || 0,
|
|
56465
|
+
active: Number(result.active) || 0,
|
|
56466
|
+
paused: Number(result.paused) || 0,
|
|
56467
|
+
completed: Number(result.completed) || 0,
|
|
56468
|
+
failed: Number(result.failed) || 0,
|
|
56469
|
+
recurring: Number(result.recurring) || 0,
|
|
56470
|
+
oneTime: Number(result.one_time) || 0
|
|
56471
|
+
};
|
|
56472
|
+
}
|
|
56473
|
+
async validateLimits(creatorId, isRecurring, limits) {
|
|
56474
|
+
const knex = this.getKnex();
|
|
56475
|
+
if (limits.maxGlobal) {
|
|
56476
|
+
const result = await knex("schedules").count("* as cnt").first();
|
|
56477
|
+
if (Number(result?.cnt) >= limits.maxGlobal) {
|
|
56478
|
+
throw new Error(`Global schedule limit reached (${limits.maxGlobal})`);
|
|
56479
|
+
}
|
|
56480
|
+
}
|
|
56481
|
+
if (limits.maxPerUser) {
|
|
56482
|
+
const result = await knex("schedules").where("creator_id", creatorId).count("* as cnt").first();
|
|
56483
|
+
if (Number(result?.cnt) >= limits.maxPerUser) {
|
|
56484
|
+
throw new Error(`You have reached the maximum number of schedules (${limits.maxPerUser})`);
|
|
56485
|
+
}
|
|
56486
|
+
}
|
|
56487
|
+
if (isRecurring && limits.maxRecurringPerUser) {
|
|
56488
|
+
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
56489
|
+
const result = await knex("schedules").where("creator_id", creatorId).where("is_recurring", bTrue).count("* as cnt").first();
|
|
56490
|
+
if (Number(result?.cnt) >= limits.maxRecurringPerUser) {
|
|
56491
|
+
throw new Error(
|
|
56492
|
+
`You have reached the maximum number of recurring schedules (${limits.maxRecurringPerUser})`
|
|
56493
|
+
);
|
|
56494
|
+
}
|
|
56495
|
+
}
|
|
56496
|
+
}
|
|
56497
|
+
// --- HA Distributed Locking (via scheduler_locks table) ---
|
|
56498
|
+
async tryAcquireLock(lockId, nodeId, ttlSeconds) {
|
|
56499
|
+
const knex = this.getKnex();
|
|
56500
|
+
const now = Date.now();
|
|
56501
|
+
const expiresAt = now + ttlSeconds * 1e3;
|
|
56502
|
+
const token = (0, import_uuid2.v4)();
|
|
56503
|
+
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("expires_at", "<", now).update({
|
|
56504
|
+
node_id: nodeId,
|
|
56505
|
+
lock_token: token,
|
|
56506
|
+
acquired_at: now,
|
|
56507
|
+
expires_at: expiresAt
|
|
56508
|
+
});
|
|
56509
|
+
if (updated > 0) return token;
|
|
56510
|
+
try {
|
|
56511
|
+
await knex("scheduler_locks").insert({
|
|
56512
|
+
lock_id: lockId,
|
|
56513
|
+
node_id: nodeId,
|
|
56514
|
+
lock_token: token,
|
|
56515
|
+
acquired_at: now,
|
|
56516
|
+
expires_at: expiresAt
|
|
56517
|
+
});
|
|
56518
|
+
return token;
|
|
56519
|
+
} catch {
|
|
56520
|
+
return null;
|
|
56521
|
+
}
|
|
56522
|
+
}
|
|
56523
|
+
async releaseLock(lockId, lockToken) {
|
|
56524
|
+
const knex = this.getKnex();
|
|
56525
|
+
await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).del();
|
|
56526
|
+
}
|
|
56527
|
+
async renewLock(lockId, lockToken, ttlSeconds) {
|
|
56528
|
+
const knex = this.getKnex();
|
|
56529
|
+
const now = Date.now();
|
|
56530
|
+
const expiresAt = now + ttlSeconds * 1e3;
|
|
56531
|
+
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).update({ acquired_at: now, expires_at: expiresAt });
|
|
56532
|
+
return updated > 0;
|
|
56533
|
+
}
|
|
56534
|
+
async flush() {
|
|
56535
|
+
}
|
|
56536
|
+
// --- Message Trigger CRUD ---
|
|
56537
|
+
async createTrigger(trigger) {
|
|
56538
|
+
const knex = this.getKnex();
|
|
56539
|
+
const newTrigger = {
|
|
56540
|
+
...trigger,
|
|
56541
|
+
id: (0, import_uuid2.v4)(),
|
|
56542
|
+
createdAt: Date.now()
|
|
56543
|
+
};
|
|
56544
|
+
await knex("message_triggers").insert(toTriggerInsertRow(newTrigger));
|
|
56545
|
+
logger.info(`[KnexStore] Created trigger ${newTrigger.id} for user ${newTrigger.creatorId}`);
|
|
56546
|
+
return newTrigger;
|
|
56547
|
+
}
|
|
56548
|
+
async getTrigger(id) {
|
|
56549
|
+
const knex = this.getKnex();
|
|
56550
|
+
const row = await knex("message_triggers").where("id", id).first();
|
|
56551
|
+
return row ? fromTriggerRow2(row) : void 0;
|
|
56552
|
+
}
|
|
56553
|
+
async updateTrigger(id, patch) {
|
|
56554
|
+
const knex = this.getKnex();
|
|
56555
|
+
const existing = await knex("message_triggers").where("id", id).first();
|
|
56556
|
+
if (!existing) return void 0;
|
|
56557
|
+
const current = fromTriggerRow2(existing);
|
|
56558
|
+
const updated = {
|
|
56559
|
+
...current,
|
|
56560
|
+
...patch,
|
|
56561
|
+
id: current.id,
|
|
56562
|
+
createdAt: current.createdAt
|
|
56563
|
+
};
|
|
56564
|
+
const row = toTriggerInsertRow(updated);
|
|
56565
|
+
delete row.id;
|
|
56566
|
+
await knex("message_triggers").where("id", id).update(row);
|
|
56567
|
+
return updated;
|
|
56568
|
+
}
|
|
56569
|
+
async deleteTrigger(id) {
|
|
56570
|
+
const knex = this.getKnex();
|
|
56571
|
+
const deleted = await knex("message_triggers").where("id", id).del();
|
|
56572
|
+
if (deleted > 0) {
|
|
56573
|
+
logger.info(`[KnexStore] Deleted trigger ${id}`);
|
|
56574
|
+
return true;
|
|
56575
|
+
}
|
|
56576
|
+
return false;
|
|
56577
|
+
}
|
|
56578
|
+
async getTriggersByCreator(creatorId) {
|
|
56579
|
+
const knex = this.getKnex();
|
|
56580
|
+
const rows = await knex("message_triggers").where("creator_id", creatorId);
|
|
56581
|
+
return rows.map((r) => fromTriggerRow2(r));
|
|
56582
|
+
}
|
|
56583
|
+
async getActiveTriggers() {
|
|
56584
|
+
const knex = this.getKnex();
|
|
56585
|
+
const rows = await knex("message_triggers").where("status", "active").where("enabled", this.driver === "mssql" ? 1 : true);
|
|
56586
|
+
return rows.map((r) => fromTriggerRow2(r));
|
|
56587
|
+
}
|
|
56588
|
+
};
|
|
56589
|
+
}
|
|
56590
|
+
});
|
|
56591
|
+
|
|
56592
|
+
// src/enterprise/loader.ts
|
|
56593
|
+
var loader_exports = {};
|
|
56594
|
+
__export(loader_exports, {
|
|
56595
|
+
loadEnterprisePolicyEngine: () => loadEnterprisePolicyEngine,
|
|
56596
|
+
loadEnterpriseStoreBackend: () => loadEnterpriseStoreBackend
|
|
56597
|
+
});
|
|
56598
|
+
async function loadEnterprisePolicyEngine(config) {
|
|
56599
|
+
try {
|
|
56600
|
+
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
56601
|
+
const validator = new LicenseValidator2();
|
|
56602
|
+
const license = await validator.loadAndValidate();
|
|
56603
|
+
if (!license || !validator.hasFeature("policy")) {
|
|
56604
|
+
return new DefaultPolicyEngine();
|
|
56605
|
+
}
|
|
56606
|
+
if (validator.isInGracePeriod()) {
|
|
56607
|
+
console.warn(
|
|
56608
|
+
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
56609
|
+
);
|
|
56610
|
+
}
|
|
56611
|
+
const { OpaPolicyEngine: OpaPolicyEngine2 } = await Promise.resolve().then(() => (init_opa_policy_engine(), opa_policy_engine_exports));
|
|
56612
|
+
const engine = new OpaPolicyEngine2(config);
|
|
56613
|
+
await engine.initialize(config);
|
|
56614
|
+
return engine;
|
|
56615
|
+
} catch (err) {
|
|
56616
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
56617
|
+
try {
|
|
56618
|
+
const { logger: logger2 } = (init_logger(), __toCommonJS(logger_exports));
|
|
56619
|
+
logger2.warn(`[PolicyEngine] Enterprise policy init failed, falling back to default: ${msg}`);
|
|
56620
|
+
} catch {
|
|
56621
|
+
}
|
|
56622
|
+
return new DefaultPolicyEngine();
|
|
56623
|
+
}
|
|
56624
|
+
}
|
|
56625
|
+
async function loadEnterpriseStoreBackend(driver, storageConfig, haConfig) {
|
|
56626
|
+
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
56627
|
+
const validator = new LicenseValidator2();
|
|
56628
|
+
const license = await validator.loadAndValidate();
|
|
56629
|
+
if (!license || !validator.hasFeature("scheduler-sql")) {
|
|
56630
|
+
throw new Error(
|
|
56631
|
+
`The ${driver} schedule storage driver requires a Visor Enterprise license with the 'scheduler-sql' feature. Please upgrade or use driver: 'sqlite' (default).`
|
|
56632
|
+
);
|
|
56633
|
+
}
|
|
56634
|
+
if (validator.isInGracePeriod()) {
|
|
56635
|
+
console.warn(
|
|
56636
|
+
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
56637
|
+
);
|
|
56638
|
+
}
|
|
56639
|
+
const { KnexStoreBackend: KnexStoreBackend2 } = await Promise.resolve().then(() => (init_knex_store(), knex_store_exports));
|
|
56640
|
+
return new KnexStoreBackend2(driver, storageConfig, haConfig);
|
|
56641
|
+
}
|
|
56642
|
+
var init_loader = __esm({
|
|
56643
|
+
"src/enterprise/loader.ts"() {
|
|
56644
|
+
"use strict";
|
|
56645
|
+
init_default_engine();
|
|
56646
|
+
}
|
|
56647
|
+
});
|
|
56648
|
+
|
|
55275
56649
|
// src/event-bus/event-bus.ts
|
|
55276
56650
|
var event_bus_exports = {};
|
|
55277
56651
|
__export(event_bus_exports, {
|
|
@@ -56178,8 +57552,8 @@ ${content}
|
|
|
56178
57552
|
* Sleep utility
|
|
56179
57553
|
*/
|
|
56180
57554
|
sleep(ms) {
|
|
56181
|
-
return new Promise((
|
|
56182
|
-
const t = setTimeout(
|
|
57555
|
+
return new Promise((resolve19) => {
|
|
57556
|
+
const t = setTimeout(resolve19, ms);
|
|
56183
57557
|
if (typeof t.unref === "function") {
|
|
56184
57558
|
try {
|
|
56185
57559
|
t.unref();
|
|
@@ -56464,8 +57838,8 @@ ${end}`);
|
|
|
56464
57838
|
async updateGroupedComment(ctx, comments, group, changedIds) {
|
|
56465
57839
|
const existingLock = this.updateLocks.get(group);
|
|
56466
57840
|
let resolveLock;
|
|
56467
|
-
const ourLock = new Promise((
|
|
56468
|
-
resolveLock =
|
|
57841
|
+
const ourLock = new Promise((resolve19) => {
|
|
57842
|
+
resolveLock = resolve19;
|
|
56469
57843
|
});
|
|
56470
57844
|
this.updateLocks.set(group, ourLock);
|
|
56471
57845
|
try {
|
|
@@ -56796,7 +58170,7 @@ ${blocks}
|
|
|
56796
58170
|
* Sleep utility for enforcing delays
|
|
56797
58171
|
*/
|
|
56798
58172
|
sleep(ms) {
|
|
56799
|
-
return new Promise((
|
|
58173
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
56800
58174
|
}
|
|
56801
58175
|
};
|
|
56802
58176
|
}
|
|
@@ -58088,15 +59462,15 @@ function serializeRunState(state) {
|
|
|
58088
59462
|
])
|
|
58089
59463
|
};
|
|
58090
59464
|
}
|
|
58091
|
-
var
|
|
59465
|
+
var path30, fs26, StateMachineExecutionEngine;
|
|
58092
59466
|
var init_state_machine_execution_engine = __esm({
|
|
58093
59467
|
"src/state-machine-execution-engine.ts"() {
|
|
58094
59468
|
"use strict";
|
|
58095
59469
|
init_runner();
|
|
58096
59470
|
init_logger();
|
|
58097
59471
|
init_sandbox_manager();
|
|
58098
|
-
|
|
58099
|
-
|
|
59472
|
+
path30 = __toESM(require("path"));
|
|
59473
|
+
fs26 = __toESM(require("fs"));
|
|
58100
59474
|
StateMachineExecutionEngine = class _StateMachineExecutionEngine {
|
|
58101
59475
|
workingDirectory;
|
|
58102
59476
|
executionContext;
|
|
@@ -58328,8 +59702,8 @@ var init_state_machine_execution_engine = __esm({
|
|
|
58328
59702
|
logger.debug(
|
|
58329
59703
|
`[PolicyEngine] Loading enterprise policy engine (engine=${configWithTagFilter.policy.engine})`
|
|
58330
59704
|
);
|
|
58331
|
-
const { loadEnterprisePolicyEngine } = await
|
|
58332
|
-
context2.policyEngine = await
|
|
59705
|
+
const { loadEnterprisePolicyEngine: loadEnterprisePolicyEngine2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
59706
|
+
context2.policyEngine = await loadEnterprisePolicyEngine2(configWithTagFilter.policy);
|
|
58333
59707
|
logger.debug(
|
|
58334
59708
|
`[PolicyEngine] Initialized: ${context2.policyEngine?.constructor?.name || "unknown"}`
|
|
58335
59709
|
);
|
|
@@ -58481,9 +59855,9 @@ var init_state_machine_execution_engine = __esm({
|
|
|
58481
59855
|
}
|
|
58482
59856
|
const checkId = String(ev?.checkId || "unknown");
|
|
58483
59857
|
const threadKey = ev?.threadKey || (channel && threadTs ? `${channel}:${threadTs}` : "session");
|
|
58484
|
-
const baseDir = process.env.VISOR_SNAPSHOT_DIR ||
|
|
58485
|
-
|
|
58486
|
-
const filePath =
|
|
59858
|
+
const baseDir = process.env.VISOR_SNAPSHOT_DIR || path30.resolve(process.cwd(), ".visor", "snapshots");
|
|
59859
|
+
fs26.mkdirSync(baseDir, { recursive: true });
|
|
59860
|
+
const filePath = path30.join(baseDir, `${threadKey}-${checkId}.json`);
|
|
58487
59861
|
await this.saveSnapshotToFile(filePath);
|
|
58488
59862
|
logger.info(`[Snapshot] Saved run snapshot: ${filePath}`);
|
|
58489
59863
|
try {
|
|
@@ -58624,7 +59998,7 @@ var init_state_machine_execution_engine = __esm({
|
|
|
58624
59998
|
* Does not include secrets. Intended for debugging and future resume support.
|
|
58625
59999
|
*/
|
|
58626
60000
|
async saveSnapshotToFile(filePath) {
|
|
58627
|
-
const
|
|
60001
|
+
const fs27 = await import("fs/promises");
|
|
58628
60002
|
const ctx = this._lastContext;
|
|
58629
60003
|
const runner = this._lastRunner;
|
|
58630
60004
|
if (!ctx || !runner) {
|
|
@@ -58644,14 +60018,14 @@ var init_state_machine_execution_engine = __esm({
|
|
|
58644
60018
|
journal: entries,
|
|
58645
60019
|
requestedChecks: ctx.requestedChecks || []
|
|
58646
60020
|
};
|
|
58647
|
-
await
|
|
60021
|
+
await fs27.writeFile(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
58648
60022
|
}
|
|
58649
60023
|
/**
|
|
58650
60024
|
* Load a snapshot JSON from file and return it. Resume support can build on this.
|
|
58651
60025
|
*/
|
|
58652
60026
|
async loadSnapshotFromFile(filePath) {
|
|
58653
|
-
const
|
|
58654
|
-
const raw = await
|
|
60027
|
+
const fs27 = await import("fs/promises");
|
|
60028
|
+
const raw = await fs27.readFile(filePath, "utf8");
|
|
58655
60029
|
return JSON.parse(raw);
|
|
58656
60030
|
}
|
|
58657
60031
|
/**
|