@probelabs/visor 0.1.138 → 0.1.139-ee
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1744 -35
- package/dist/providers/mcp-check-provider.d.ts.map +1 -1
- package/dist/providers/workflow-check-provider.d.ts.map +1 -1
- package/dist/sdk/{check-provider-registry-XRD3J74K.mjs → check-provider-registry-BQD6S2SI.mjs} +3 -3
- package/dist/sdk/{check-provider-registry-JX7FK3MS.mjs → check-provider-registry-EHLKMSLE.mjs} +2 -2
- package/dist/sdk/{chunk-QSB2P6VY.mjs → chunk-LZJATBWH.mjs} +36 -24
- package/dist/sdk/{chunk-3CREE2RR.mjs.map → chunk-LZJATBWH.mjs.map} +1 -1
- package/dist/sdk/{chunk-3CREE2RR.mjs → chunk-TJXIVJ37.mjs} +30 -18
- package/dist/sdk/{chunk-QSB2P6VY.mjs.map → chunk-TJXIVJ37.mjs.map} +1 -1
- package/dist/sdk/{host-FISPPQTH.mjs → host-RF2UEKMG.mjs} +2 -2
- package/dist/sdk/knex-store-HPXJILBL.mjs +411 -0
- package/dist/sdk/knex-store-HPXJILBL.mjs.map +1 -0
- package/dist/sdk/loader-ZC5G3JGJ.mjs +89 -0
- package/dist/sdk/loader-ZC5G3JGJ.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/{schedule-tool-handler-WHB5AGLT.mjs → schedule-tool-handler-7FGVBTTW.mjs} +2 -2
- package/dist/sdk/{schedule-tool-handler-LBSAGK6P.mjs → schedule-tool-handler-AVPJACU6.mjs} +3 -3
- package/dist/sdk/sdk.js +1556 -286
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +5 -5
- package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
- package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-MIFPOENL.mjs → workflow-check-provider-A6J5AEK4.mjs} +2 -2
- package/dist/sdk/{workflow-check-provider-I3SB5RG7.mjs → workflow-check-provider-KCNRNZEO.mjs} +3 -3
- package/dist/state-machine/workflow-projection.d.ts.map +1 -1
- package/dist/types/workflow.d.ts +2 -0
- package/dist/types/workflow.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/output/traces/run-2026-02-23T15-25-03-052Z.ndjson +0 -138
- package/dist/output/traces/run-2026-02-23T15-25-53-483Z.ndjson +0 -1442
- package/dist/sdk/check-provider-registry-ZVPNBYEA.mjs +0 -29
- package/dist/sdk/chunk-GIGTDZHF.mjs +0 -443
- package/dist/sdk/chunk-GIGTDZHF.mjs.map +0 -1
- package/dist/sdk/chunk-HIRALSSN.mjs +0 -40235
- package/dist/sdk/chunk-HIRALSSN.mjs.map +0 -1
- package/dist/sdk/chunk-K7O7DMJU.mjs +0 -1502
- package/dist/sdk/chunk-K7O7DMJU.mjs.map +0 -1
- package/dist/sdk/chunk-ROCFDJFL.mjs +0 -739
- package/dist/sdk/chunk-ROCFDJFL.mjs.map +0 -1
- package/dist/sdk/failure-condition-evaluator-DPLWUGYG.mjs +0 -17
- package/dist/sdk/github-frontend-QSMW366Z.mjs +0 -1356
- package/dist/sdk/github-frontend-QSMW366Z.mjs.map +0 -1
- package/dist/sdk/routing-7QCNYAVE.mjs +0 -25
- package/dist/sdk/schedule-tool-handler-RU76H4W5.mjs +0 -39
- package/dist/sdk/schedule-tool-handler-RU76H4W5.mjs.map +0 -1
- package/dist/sdk/schedule-tool-handler-WHB5AGLT.mjs.map +0 -1
- package/dist/sdk/trace-helpers-2ADE6X4I.mjs +0 -25
- package/dist/sdk/trace-helpers-2ADE6X4I.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-I3SB5RG7.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-MIFPOENL.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-YDA7DL3O.mjs +0 -29
- package/dist/sdk/workflow-check-provider-YDA7DL3O.mjs.map +0 -1
- package/dist/traces/run-2026-02-23T15-25-03-052Z.ndjson +0 -138
- package/dist/traces/run-2026-02-23T15-25-53-483Z.ndjson +0 -1442
- /package/dist/sdk/{check-provider-registry-JX7FK3MS.mjs.map → check-provider-registry-BQD6S2SI.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-XRD3J74K.mjs.map → check-provider-registry-EHLKMSLE.mjs.map} +0 -0
- /package/dist/sdk/{host-FISPPQTH.mjs.map → host-RF2UEKMG.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-ZVPNBYEA.mjs.map → schedule-tool-handler-7FGVBTTW.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-DPLWUGYG.mjs.map → schedule-tool-handler-AVPJACU6.mjs.map} +0 -0
- /package/dist/sdk/{routing-7QCNYAVE.mjs.map → workflow-check-provider-A6J5AEK4.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-LBSAGK6P.mjs.map → workflow-check-provider-KCNRNZEO.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"
|
|
@@ -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((resolve15, reject) => {
|
|
868
868
|
const callback = async (span) => {
|
|
869
869
|
try {
|
|
870
870
|
const res = await fn(span);
|
|
871
|
-
|
|
871
|
+
resolve15(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 path30 = require("path");
|
|
949
|
+
const fs26 = 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 = path30.dirname(__ndjsonPath);
|
|
953
|
+
if (!fs26.existsSync(dir)) fs26.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 || path30.join(process.cwd(), "output", "traces");
|
|
957
|
+
if (!fs26.existsSync(outDir)) fs26.mkdirSync(outDir, { recursive: true });
|
|
958
958
|
if (!__ndjsonPath) {
|
|
959
959
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
960
|
-
__ndjsonPath =
|
|
960
|
+
__ndjsonPath = path30.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 fs26 = require("fs");
|
|
970
970
|
const p = __getOrCreateNdjsonPath();
|
|
971
971
|
if (!p) return;
|
|
972
972
|
const line = { name: "visor.run", attributes: { started: true } };
|
|
973
|
-
|
|
973
|
+
fs26.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 path30 = typeof pathExpr === "string" ? pathExpr : String(pathExpr || "");
|
|
3738
|
+
if (!path30) return obj;
|
|
3739
|
+
const parts = path30.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, path30) => {
|
|
3859
|
+
if (!obj || !path30) return void 0;
|
|
3860
|
+
const parts = path30.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 fs26 = await import("fs/promises");
|
|
6413
|
+
const path30 = 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 = path30.resolve(process.cwd(), file);
|
|
6422
|
+
templateContent = await fs26.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
|
+
path30.join(__dirname, "output", sanitized, "template.liquid"),
|
|
6428
6428
|
// bundled: dist/output/
|
|
6429
|
-
|
|
6429
|
+
path30.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
6430
6430
|
// source: output/
|
|
6431
|
-
|
|
6431
|
+
path30.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
6432
6432
|
// fallback: cwd/output/
|
|
6433
|
-
|
|
6433
|
+
path30.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 fs26.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 fs26 = 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 (fs26.existsSync(candidatePath)) {
|
|
6855
6855
|
probeBinaryPath = candidatePath;
|
|
6856
6856
|
break;
|
|
6857
6857
|
}
|
|
@@ -7937,8 +7937,8 @@ ${schemaString}`);
|
|
|
7937
7937
|
}
|
|
7938
7938
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
7939
7939
|
try {
|
|
7940
|
-
const
|
|
7941
|
-
const
|
|
7940
|
+
const fs26 = require("fs");
|
|
7941
|
+
const path30 = require("path");
|
|
7942
7942
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7943
7943
|
const provider = this.config.provider || "auto";
|
|
7944
7944
|
const model = this.config.model || "default";
|
|
@@ -8052,20 +8052,20 @@ ${"=".repeat(60)}
|
|
|
8052
8052
|
`;
|
|
8053
8053
|
readableVersion += `${"=".repeat(60)}
|
|
8054
8054
|
`;
|
|
8055
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8056
|
-
if (!
|
|
8057
|
-
|
|
8055
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path30.join(process.cwd(), "debug-artifacts");
|
|
8056
|
+
if (!fs26.existsSync(debugArtifactsDir)) {
|
|
8057
|
+
fs26.mkdirSync(debugArtifactsDir, { recursive: true });
|
|
8058
8058
|
}
|
|
8059
|
-
const debugFile =
|
|
8059
|
+
const debugFile = path30.join(
|
|
8060
8060
|
debugArtifactsDir,
|
|
8061
8061
|
`prompt-${_checkName || "unknown"}-${timestamp}.json`
|
|
8062
8062
|
);
|
|
8063
|
-
|
|
8064
|
-
const readableFile =
|
|
8063
|
+
fs26.writeFileSync(debugFile, debugJson, "utf-8");
|
|
8064
|
+
const readableFile = path30.join(
|
|
8065
8065
|
debugArtifactsDir,
|
|
8066
8066
|
`prompt-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8067
8067
|
);
|
|
8068
|
-
|
|
8068
|
+
fs26.writeFileSync(readableFile, readableVersion, "utf-8");
|
|
8069
8069
|
log(`
|
|
8070
8070
|
\u{1F4BE} Full debug info saved to:`);
|
|
8071
8071
|
log(` JSON: ${debugFile}`);
|
|
@@ -8098,8 +8098,8 @@ ${"=".repeat(60)}
|
|
|
8098
8098
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8099
8099
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8100
8100
|
try {
|
|
8101
|
-
const
|
|
8102
|
-
const
|
|
8101
|
+
const fs26 = require("fs");
|
|
8102
|
+
const path30 = require("path");
|
|
8103
8103
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8104
8104
|
const agentAny2 = agent;
|
|
8105
8105
|
let fullHistory = [];
|
|
@@ -8110,8 +8110,8 @@ ${"=".repeat(60)}
|
|
|
8110
8110
|
} else if (agentAny2._messages) {
|
|
8111
8111
|
fullHistory = agentAny2._messages;
|
|
8112
8112
|
}
|
|
8113
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8114
|
-
const sessionBase =
|
|
8113
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path30.join(process.cwd(), "debug-artifacts");
|
|
8114
|
+
const sessionBase = path30.join(
|
|
8115
8115
|
debugArtifactsDir,
|
|
8116
8116
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
8117
8117
|
);
|
|
@@ -8123,7 +8123,7 @@ ${"=".repeat(60)}
|
|
|
8123
8123
|
schema: effectiveSchema,
|
|
8124
8124
|
totalMessages: fullHistory.length
|
|
8125
8125
|
};
|
|
8126
|
-
|
|
8126
|
+
fs26.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
8127
8127
|
let readable = `=============================================================
|
|
8128
8128
|
`;
|
|
8129
8129
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -8150,7 +8150,7 @@ ${"=".repeat(60)}
|
|
|
8150
8150
|
`;
|
|
8151
8151
|
readable += content + "\n";
|
|
8152
8152
|
});
|
|
8153
|
-
|
|
8153
|
+
fs26.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
8154
8154
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
8155
8155
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
8156
8156
|
} catch (error) {
|
|
@@ -8159,11 +8159,11 @@ ${"=".repeat(60)}
|
|
|
8159
8159
|
}
|
|
8160
8160
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8161
8161
|
try {
|
|
8162
|
-
const
|
|
8163
|
-
const
|
|
8162
|
+
const fs26 = require("fs");
|
|
8163
|
+
const path30 = require("path");
|
|
8164
8164
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8165
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8166
|
-
const responseFile =
|
|
8165
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path30.join(process.cwd(), "debug-artifacts");
|
|
8166
|
+
const responseFile = path30.join(
|
|
8167
8167
|
debugArtifactsDir,
|
|
8168
8168
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8169
8169
|
);
|
|
@@ -8196,7 +8196,7 @@ ${"=".repeat(60)}
|
|
|
8196
8196
|
`;
|
|
8197
8197
|
responseContent += `${"=".repeat(60)}
|
|
8198
8198
|
`;
|
|
8199
|
-
|
|
8199
|
+
fs26.writeFileSync(responseFile, responseContent, "utf-8");
|
|
8200
8200
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
8201
8201
|
} catch (error) {
|
|
8202
8202
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -8212,9 +8212,9 @@ ${"=".repeat(60)}
|
|
|
8212
8212
|
await agentAny._telemetryConfig.shutdown();
|
|
8213
8213
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${agentAny._traceFilePath}`);
|
|
8214
8214
|
if (process.env.GITHUB_ACTIONS) {
|
|
8215
|
-
const
|
|
8216
|
-
if (
|
|
8217
|
-
const stats =
|
|
8215
|
+
const fs26 = require("fs");
|
|
8216
|
+
if (fs26.existsSync(agentAny._traceFilePath)) {
|
|
8217
|
+
const stats = fs26.statSync(agentAny._traceFilePath);
|
|
8218
8218
|
console.log(
|
|
8219
8219
|
`::notice title=AI Trace Saved::${agentAny._traceFilePath} (${stats.size} bytes)`
|
|
8220
8220
|
);
|
|
@@ -8415,9 +8415,9 @@ ${schemaString}`);
|
|
|
8415
8415
|
const model = this.config.model || "default";
|
|
8416
8416
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8417
8417
|
try {
|
|
8418
|
-
const
|
|
8419
|
-
const
|
|
8420
|
-
const
|
|
8418
|
+
const fs26 = require("fs");
|
|
8419
|
+
const path30 = require("path");
|
|
8420
|
+
const os3 = require("os");
|
|
8421
8421
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8422
8422
|
const debugData = {
|
|
8423
8423
|
timestamp,
|
|
@@ -8489,19 +8489,19 @@ ${"=".repeat(60)}
|
|
|
8489
8489
|
`;
|
|
8490
8490
|
readableVersion += `${"=".repeat(60)}
|
|
8491
8491
|
`;
|
|
8492
|
-
const tempDir =
|
|
8493
|
-
const promptFile =
|
|
8494
|
-
|
|
8492
|
+
const tempDir = os3.tmpdir();
|
|
8493
|
+
const promptFile = path30.join(tempDir, `visor-prompt-${timestamp}.txt`);
|
|
8494
|
+
fs26.writeFileSync(promptFile, prompt, "utf-8");
|
|
8495
8495
|
log(`
|
|
8496
8496
|
\u{1F4BE} Prompt saved to: ${promptFile}`);
|
|
8497
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8497
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path30.join(process.cwd(), "debug-artifacts");
|
|
8498
8498
|
try {
|
|
8499
|
-
const base =
|
|
8499
|
+
const base = path30.join(
|
|
8500
8500
|
debugArtifactsDir,
|
|
8501
8501
|
`prompt-${_checkName || "unknown"}-${timestamp}`
|
|
8502
8502
|
);
|
|
8503
|
-
|
|
8504
|
-
|
|
8503
|
+
fs26.writeFileSync(base + ".json", debugJson, "utf-8");
|
|
8504
|
+
fs26.writeFileSync(base + ".summary.txt", readableVersion, "utf-8");
|
|
8505
8505
|
log(`
|
|
8506
8506
|
\u{1F4BE} Full debug info saved to directory: ${debugArtifactsDir}`);
|
|
8507
8507
|
} catch {
|
|
@@ -8546,8 +8546,8 @@ $ ${cliCommand}
|
|
|
8546
8546
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8547
8547
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8548
8548
|
try {
|
|
8549
|
-
const
|
|
8550
|
-
const
|
|
8549
|
+
const fs26 = require("fs");
|
|
8550
|
+
const path30 = require("path");
|
|
8551
8551
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8552
8552
|
const agentAny = agent;
|
|
8553
8553
|
let fullHistory = [];
|
|
@@ -8558,8 +8558,8 @@ $ ${cliCommand}
|
|
|
8558
8558
|
} else if (agentAny._messages) {
|
|
8559
8559
|
fullHistory = agentAny._messages;
|
|
8560
8560
|
}
|
|
8561
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8562
|
-
const sessionBase =
|
|
8561
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path30.join(process.cwd(), "debug-artifacts");
|
|
8562
|
+
const sessionBase = path30.join(
|
|
8563
8563
|
debugArtifactsDir,
|
|
8564
8564
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
8565
8565
|
);
|
|
@@ -8571,7 +8571,7 @@ $ ${cliCommand}
|
|
|
8571
8571
|
schema: effectiveSchema,
|
|
8572
8572
|
totalMessages: fullHistory.length
|
|
8573
8573
|
};
|
|
8574
|
-
|
|
8574
|
+
fs26.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
8575
8575
|
let readable = `=============================================================
|
|
8576
8576
|
`;
|
|
8577
8577
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -8598,7 +8598,7 @@ ${"=".repeat(60)}
|
|
|
8598
8598
|
`;
|
|
8599
8599
|
readable += content + "\n";
|
|
8600
8600
|
});
|
|
8601
|
-
|
|
8601
|
+
fs26.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
8602
8602
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
8603
8603
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
8604
8604
|
} catch (error) {
|
|
@@ -8607,11 +8607,11 @@ ${"=".repeat(60)}
|
|
|
8607
8607
|
}
|
|
8608
8608
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8609
8609
|
try {
|
|
8610
|
-
const
|
|
8611
|
-
const
|
|
8610
|
+
const fs26 = require("fs");
|
|
8611
|
+
const path30 = require("path");
|
|
8612
8612
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8613
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8614
|
-
const responseFile =
|
|
8613
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path30.join(process.cwd(), "debug-artifacts");
|
|
8614
|
+
const responseFile = path30.join(
|
|
8615
8615
|
debugArtifactsDir,
|
|
8616
8616
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8617
8617
|
);
|
|
@@ -8644,7 +8644,7 @@ ${"=".repeat(60)}
|
|
|
8644
8644
|
`;
|
|
8645
8645
|
responseContent += `${"=".repeat(60)}
|
|
8646
8646
|
`;
|
|
8647
|
-
|
|
8647
|
+
fs26.writeFileSync(responseFile, responseContent, "utf-8");
|
|
8648
8648
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
8649
8649
|
} catch (error) {
|
|
8650
8650
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -8662,9 +8662,9 @@ ${"=".repeat(60)}
|
|
|
8662
8662
|
await telemetry.shutdown();
|
|
8663
8663
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${traceFilePath}`);
|
|
8664
8664
|
if (process.env.GITHUB_ACTIONS) {
|
|
8665
|
-
const
|
|
8666
|
-
if (
|
|
8667
|
-
const stats =
|
|
8665
|
+
const fs26 = require("fs");
|
|
8666
|
+
if (fs26.existsSync(traceFilePath)) {
|
|
8667
|
+
const stats = fs26.statSync(traceFilePath);
|
|
8668
8668
|
console.log(
|
|
8669
8669
|
`::notice title=AI Trace Saved::OpenTelemetry trace file size: ${stats.size} bytes`
|
|
8670
8670
|
);
|
|
@@ -8702,8 +8702,8 @@ ${"=".repeat(60)}
|
|
|
8702
8702
|
* Load schema content from schema files or inline definitions
|
|
8703
8703
|
*/
|
|
8704
8704
|
async loadSchemaContent(schema) {
|
|
8705
|
-
const
|
|
8706
|
-
const
|
|
8705
|
+
const fs26 = require("fs").promises;
|
|
8706
|
+
const path30 = require("path");
|
|
8707
8707
|
if (typeof schema === "object" && schema !== null) {
|
|
8708
8708
|
log("\u{1F4CB} Using inline schema object from configuration");
|
|
8709
8709
|
return JSON.stringify(schema);
|
|
@@ -8716,14 +8716,14 @@ ${"=".repeat(60)}
|
|
|
8716
8716
|
}
|
|
8717
8717
|
} catch {
|
|
8718
8718
|
}
|
|
8719
|
-
if ((schema.startsWith("./") || schema.includes(".json")) && !
|
|
8719
|
+
if ((schema.startsWith("./") || schema.includes(".json")) && !path30.isAbsolute(schema)) {
|
|
8720
8720
|
if (schema.includes("..") || schema.includes("\0")) {
|
|
8721
8721
|
throw new Error("Invalid schema path: path traversal not allowed");
|
|
8722
8722
|
}
|
|
8723
8723
|
try {
|
|
8724
|
-
const schemaPath =
|
|
8724
|
+
const schemaPath = path30.resolve(process.cwd(), schema);
|
|
8725
8725
|
log(`\u{1F4CB} Loading custom schema from file: ${schemaPath}`);
|
|
8726
|
-
const schemaContent = await
|
|
8726
|
+
const schemaContent = await fs26.readFile(schemaPath, "utf-8");
|
|
8727
8727
|
return schemaContent.trim();
|
|
8728
8728
|
} catch (error) {
|
|
8729
8729
|
throw new Error(
|
|
@@ -8737,22 +8737,22 @@ ${"=".repeat(60)}
|
|
|
8737
8737
|
}
|
|
8738
8738
|
const candidatePaths = [
|
|
8739
8739
|
// GitHub Action bundle location
|
|
8740
|
-
|
|
8740
|
+
path30.join(__dirname, "output", sanitizedSchemaName, "schema.json"),
|
|
8741
8741
|
// Historical fallback when src/output was inadvertently bundled as output1/
|
|
8742
|
-
|
|
8742
|
+
path30.join(__dirname, "output1", sanitizedSchemaName, "schema.json"),
|
|
8743
8743
|
// Local dev (repo root)
|
|
8744
|
-
|
|
8744
|
+
path30.join(process.cwd(), "output", sanitizedSchemaName, "schema.json")
|
|
8745
8745
|
];
|
|
8746
8746
|
for (const schemaPath of candidatePaths) {
|
|
8747
8747
|
try {
|
|
8748
|
-
const schemaContent = await
|
|
8748
|
+
const schemaContent = await fs26.readFile(schemaPath, "utf-8");
|
|
8749
8749
|
return schemaContent.trim();
|
|
8750
8750
|
} catch {
|
|
8751
8751
|
}
|
|
8752
8752
|
}
|
|
8753
|
-
const distPath =
|
|
8754
|
-
const distAltPath =
|
|
8755
|
-
const cwdPath =
|
|
8753
|
+
const distPath = path30.join(__dirname, "output", sanitizedSchemaName, "schema.json");
|
|
8754
|
+
const distAltPath = path30.join(__dirname, "output1", sanitizedSchemaName, "schema.json");
|
|
8755
|
+
const cwdPath = path30.join(process.cwd(), "output", sanitizedSchemaName, "schema.json");
|
|
8756
8756
|
throw new Error(
|
|
8757
8757
|
`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.`
|
|
8758
8758
|
);
|
|
@@ -8987,7 +8987,7 @@ ${"=".repeat(60)}
|
|
|
8987
8987
|
* Generate mock response for testing
|
|
8988
8988
|
*/
|
|
8989
8989
|
async generateMockResponse(_prompt, _checkName, _schema) {
|
|
8990
|
-
await new Promise((
|
|
8990
|
+
await new Promise((resolve15) => setTimeout(resolve15, 500));
|
|
8991
8991
|
const name = (_checkName || "").toLowerCase();
|
|
8992
8992
|
if (name.includes("extract-facts")) {
|
|
8993
8993
|
const arr = Array.from({ length: 6 }, (_, i) => ({
|
|
@@ -9348,7 +9348,7 @@ var init_command_executor = __esm({
|
|
|
9348
9348
|
* Execute command with stdin input
|
|
9349
9349
|
*/
|
|
9350
9350
|
executeWithStdin(command, options) {
|
|
9351
|
-
return new Promise((
|
|
9351
|
+
return new Promise((resolve15, reject) => {
|
|
9352
9352
|
const childProcess = (0, import_child_process.exec)(
|
|
9353
9353
|
command,
|
|
9354
9354
|
{
|
|
@@ -9360,7 +9360,7 @@ var init_command_executor = __esm({
|
|
|
9360
9360
|
if (error && error.killed && (error.code === "ETIMEDOUT" || error.signal === "SIGTERM")) {
|
|
9361
9361
|
reject(new Error(`Command timed out after ${options.timeout || 3e4}ms`));
|
|
9362
9362
|
} else {
|
|
9363
|
-
|
|
9363
|
+
resolve15({
|
|
9364
9364
|
stdout: stdout || "",
|
|
9365
9365
|
stderr: stderr || "",
|
|
9366
9366
|
exitCode: error ? error.code || 1 : 0
|
|
@@ -11238,6 +11238,7 @@ function projectWorkflowToGraph(workflow, workflowInputs, _parentCheckId) {
|
|
|
11238
11238
|
}
|
|
11239
11239
|
const config = {
|
|
11240
11240
|
checks,
|
|
11241
|
+
tools: workflow.tools,
|
|
11241
11242
|
version: "1.0",
|
|
11242
11243
|
output: {
|
|
11243
11244
|
pr_comment: {
|
|
@@ -17137,17 +17138,17 @@ var init_workflow_check_provider = __esm({
|
|
|
17137
17138
|
* so it can be executed by the state machine as a nested workflow.
|
|
17138
17139
|
*/
|
|
17139
17140
|
async loadWorkflowFromConfigPath(sourcePath, baseDir) {
|
|
17140
|
-
const
|
|
17141
|
-
const
|
|
17141
|
+
const path30 = require("path");
|
|
17142
|
+
const fs26 = require("fs");
|
|
17142
17143
|
const yaml5 = require("js-yaml");
|
|
17143
|
-
const resolved =
|
|
17144
|
-
if (!
|
|
17144
|
+
const resolved = path30.isAbsolute(sourcePath) ? sourcePath : path30.resolve(baseDir, sourcePath);
|
|
17145
|
+
if (!fs26.existsSync(resolved)) {
|
|
17145
17146
|
throw new Error(`Workflow config not found at: ${resolved}`);
|
|
17146
17147
|
}
|
|
17147
|
-
const rawContent =
|
|
17148
|
+
const rawContent = fs26.readFileSync(resolved, "utf8");
|
|
17148
17149
|
const rawData = yaml5.load(rawContent);
|
|
17149
17150
|
if (rawData.imports && Array.isArray(rawData.imports)) {
|
|
17150
|
-
const configDir =
|
|
17151
|
+
const configDir = path30.dirname(resolved);
|
|
17151
17152
|
for (const source of rawData.imports) {
|
|
17152
17153
|
const results = await this.registry.import(source, {
|
|
17153
17154
|
basePath: configDir,
|
|
@@ -17177,8 +17178,8 @@ ${errors}`);
|
|
|
17177
17178
|
if (!steps || Object.keys(steps).length === 0) {
|
|
17178
17179
|
throw new Error(`Config '${resolved}' does not contain any steps to execute as a workflow`);
|
|
17179
17180
|
}
|
|
17180
|
-
const id =
|
|
17181
|
-
const name = loaded.name || `Workflow from ${
|
|
17181
|
+
const id = path30.basename(resolved).replace(/\.(ya?ml)$/i, "");
|
|
17182
|
+
const name = loaded.name || `Workflow from ${path30.basename(resolved)}`;
|
|
17182
17183
|
const workflowDef = {
|
|
17183
17184
|
id,
|
|
17184
17185
|
name,
|
|
@@ -17189,7 +17190,8 @@ ${errors}`);
|
|
|
17189
17190
|
on: loaded.on,
|
|
17190
17191
|
// Carry over optional inputs/outputs if present so callers can consume them
|
|
17191
17192
|
inputs: loaded.inputs,
|
|
17192
|
-
outputs: loaded.outputs
|
|
17193
|
+
outputs: loaded.outputs,
|
|
17194
|
+
tools: loaded.tools
|
|
17193
17195
|
};
|
|
17194
17196
|
return workflowDef;
|
|
17195
17197
|
}
|
|
@@ -17807,8 +17809,8 @@ async function createStoreBackend(storageConfig, haConfig) {
|
|
|
17807
17809
|
case "mssql": {
|
|
17808
17810
|
try {
|
|
17809
17811
|
const loaderPath = "../../enterprise/loader";
|
|
17810
|
-
const { loadEnterpriseStoreBackend } = await import(loaderPath);
|
|
17811
|
-
return await
|
|
17812
|
+
const { loadEnterpriseStoreBackend: loadEnterpriseStoreBackend2 } = await import(loaderPath);
|
|
17813
|
+
return await loadEnterpriseStoreBackend2(driver, storageConfig, haConfig);
|
|
17812
17814
|
} catch (err) {
|
|
17813
17815
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17814
17816
|
logger.error(`[StoreFactory] Failed to load enterprise ${driver} backend: ${msg}`);
|
|
@@ -19082,7 +19084,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19082
19084
|
* Returns the actual bound port number
|
|
19083
19085
|
*/
|
|
19084
19086
|
async start() {
|
|
19085
|
-
return new Promise((
|
|
19087
|
+
return new Promise((resolve15, reject) => {
|
|
19086
19088
|
try {
|
|
19087
19089
|
this.server = import_http.default.createServer((req, res) => {
|
|
19088
19090
|
this.handleRequest(req, res).catch((error) => {
|
|
@@ -19116,7 +19118,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19116
19118
|
);
|
|
19117
19119
|
}
|
|
19118
19120
|
this.startKeepalive();
|
|
19119
|
-
|
|
19121
|
+
resolve15(this.port);
|
|
19120
19122
|
});
|
|
19121
19123
|
} catch (error) {
|
|
19122
19124
|
reject(error);
|
|
@@ -19179,7 +19181,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19179
19181
|
logger.debug(
|
|
19180
19182
|
`[CustomToolsSSEServer:${this.sessionId}] Grace period before stop: ${waitMs}ms (activeToolCalls=${this.activeToolCalls})`
|
|
19181
19183
|
);
|
|
19182
|
-
await new Promise((
|
|
19184
|
+
await new Promise((resolve15) => setTimeout(resolve15, waitMs));
|
|
19183
19185
|
}
|
|
19184
19186
|
}
|
|
19185
19187
|
if (this.activeToolCalls > 0) {
|
|
@@ -19188,7 +19190,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19188
19190
|
`[CustomToolsSSEServer:${this.sessionId}] Waiting for ${this.activeToolCalls} active tool call(s) before stop`
|
|
19189
19191
|
);
|
|
19190
19192
|
while (this.activeToolCalls > 0 && Date.now() - startedAt < effectiveDrainTimeoutMs) {
|
|
19191
|
-
await new Promise((
|
|
19193
|
+
await new Promise((resolve15) => setTimeout(resolve15, 250));
|
|
19192
19194
|
}
|
|
19193
19195
|
if (this.activeToolCalls > 0) {
|
|
19194
19196
|
logger.warn(
|
|
@@ -19213,21 +19215,21 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19213
19215
|
}
|
|
19214
19216
|
this.connections.clear();
|
|
19215
19217
|
if (this.server) {
|
|
19216
|
-
await new Promise((
|
|
19218
|
+
await new Promise((resolve15, reject) => {
|
|
19217
19219
|
const timeout = setTimeout(() => {
|
|
19218
19220
|
if (this.debug) {
|
|
19219
19221
|
logger.debug(
|
|
19220
19222
|
`[CustomToolsSSEServer:${this.sessionId}] Force closing server after timeout`
|
|
19221
19223
|
);
|
|
19222
19224
|
}
|
|
19223
|
-
this.server?.close(() =>
|
|
19225
|
+
this.server?.close(() => resolve15());
|
|
19224
19226
|
}, 5e3);
|
|
19225
19227
|
this.server.close((error) => {
|
|
19226
19228
|
clearTimeout(timeout);
|
|
19227
19229
|
if (error) {
|
|
19228
19230
|
reject(error);
|
|
19229
19231
|
} else {
|
|
19230
|
-
|
|
19232
|
+
resolve15();
|
|
19231
19233
|
}
|
|
19232
19234
|
});
|
|
19233
19235
|
});
|
|
@@ -19653,7 +19655,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19653
19655
|
logger.warn(
|
|
19654
19656
|
`[CustomToolsSSEServer:${this.sessionId}] Tool ${toolName} failed (attempt ${attempt + 1}/${retryCount + 1}): ${errorMsg}. Retrying in ${delay}ms`
|
|
19655
19657
|
);
|
|
19656
|
-
await new Promise((
|
|
19658
|
+
await new Promise((resolve15) => setTimeout(resolve15, delay));
|
|
19657
19659
|
attempt++;
|
|
19658
19660
|
}
|
|
19659
19661
|
}
|
|
@@ -19956,9 +19958,9 @@ var init_ai_check_provider = __esm({
|
|
|
19956
19958
|
} else {
|
|
19957
19959
|
resolvedPath = import_path7.default.resolve(process.cwd(), str);
|
|
19958
19960
|
}
|
|
19959
|
-
const
|
|
19961
|
+
const fs26 = require("fs").promises;
|
|
19960
19962
|
try {
|
|
19961
|
-
const stat = await
|
|
19963
|
+
const stat = await fs26.stat(resolvedPath);
|
|
19962
19964
|
return stat.isFile();
|
|
19963
19965
|
} catch {
|
|
19964
19966
|
return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);
|
|
@@ -25810,14 +25812,14 @@ var require_util = __commonJS({
|
|
|
25810
25812
|
}
|
|
25811
25813
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
25812
25814
|
let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`;
|
|
25813
|
-
let
|
|
25815
|
+
let path30 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
25814
25816
|
if (origin.endsWith("/")) {
|
|
25815
25817
|
origin = origin.substring(0, origin.length - 1);
|
|
25816
25818
|
}
|
|
25817
|
-
if (
|
|
25818
|
-
|
|
25819
|
+
if (path30 && !path30.startsWith("/")) {
|
|
25820
|
+
path30 = `/${path30}`;
|
|
25819
25821
|
}
|
|
25820
|
-
url = new URL(origin +
|
|
25822
|
+
url = new URL(origin + path30);
|
|
25821
25823
|
}
|
|
25822
25824
|
return url;
|
|
25823
25825
|
}
|
|
@@ -27431,20 +27433,20 @@ var require_parseParams = __commonJS({
|
|
|
27431
27433
|
var require_basename = __commonJS({
|
|
27432
27434
|
"node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) {
|
|
27433
27435
|
"use strict";
|
|
27434
|
-
module2.exports = function basename4(
|
|
27435
|
-
if (typeof
|
|
27436
|
+
module2.exports = function basename4(path30) {
|
|
27437
|
+
if (typeof path30 !== "string") {
|
|
27436
27438
|
return "";
|
|
27437
27439
|
}
|
|
27438
|
-
for (var i =
|
|
27439
|
-
switch (
|
|
27440
|
+
for (var i = path30.length - 1; i >= 0; --i) {
|
|
27441
|
+
switch (path30.charCodeAt(i)) {
|
|
27440
27442
|
case 47:
|
|
27441
27443
|
// '/'
|
|
27442
27444
|
case 92:
|
|
27443
|
-
|
|
27444
|
-
return
|
|
27445
|
+
path30 = path30.slice(i + 1);
|
|
27446
|
+
return path30 === ".." || path30 === "." ? "" : path30;
|
|
27445
27447
|
}
|
|
27446
27448
|
}
|
|
27447
|
-
return
|
|
27449
|
+
return path30 === ".." || path30 === "." ? "" : path30;
|
|
27448
27450
|
};
|
|
27449
27451
|
}
|
|
27450
27452
|
});
|
|
@@ -28448,11 +28450,11 @@ var require_util2 = __commonJS({
|
|
|
28448
28450
|
var assert = require("assert");
|
|
28449
28451
|
var { isUint8Array } = require("util/types");
|
|
28450
28452
|
var supportedHashes = [];
|
|
28451
|
-
var
|
|
28453
|
+
var crypto4;
|
|
28452
28454
|
try {
|
|
28453
|
-
|
|
28455
|
+
crypto4 = require("crypto");
|
|
28454
28456
|
const possibleRelevantHashes = ["sha256", "sha384", "sha512"];
|
|
28455
|
-
supportedHashes =
|
|
28457
|
+
supportedHashes = crypto4.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
|
|
28456
28458
|
} catch {
|
|
28457
28459
|
}
|
|
28458
28460
|
function responseURL(response) {
|
|
@@ -28729,7 +28731,7 @@ var require_util2 = __commonJS({
|
|
|
28729
28731
|
}
|
|
28730
28732
|
}
|
|
28731
28733
|
function bytesMatch(bytes, metadataList) {
|
|
28732
|
-
if (
|
|
28734
|
+
if (crypto4 === void 0) {
|
|
28733
28735
|
return true;
|
|
28734
28736
|
}
|
|
28735
28737
|
const parsedMetadata = parseMetadata(metadataList);
|
|
@@ -28744,7 +28746,7 @@ var require_util2 = __commonJS({
|
|
|
28744
28746
|
for (const item of metadata) {
|
|
28745
28747
|
const algorithm = item.algo;
|
|
28746
28748
|
const expectedValue = item.hash;
|
|
28747
|
-
let actualValue =
|
|
28749
|
+
let actualValue = crypto4.createHash(algorithm).update(bytes).digest("base64");
|
|
28748
28750
|
if (actualValue[actualValue.length - 1] === "=") {
|
|
28749
28751
|
if (actualValue[actualValue.length - 2] === "=") {
|
|
28750
28752
|
actualValue = actualValue.slice(0, -2);
|
|
@@ -28837,8 +28839,8 @@ var require_util2 = __commonJS({
|
|
|
28837
28839
|
function createDeferredPromise() {
|
|
28838
28840
|
let res;
|
|
28839
28841
|
let rej;
|
|
28840
|
-
const promise = new Promise((
|
|
28841
|
-
res =
|
|
28842
|
+
const promise = new Promise((resolve15, reject) => {
|
|
28843
|
+
res = resolve15;
|
|
28842
28844
|
rej = reject;
|
|
28843
28845
|
});
|
|
28844
28846
|
return { promise, resolve: res, reject: rej };
|
|
@@ -30091,8 +30093,8 @@ var require_body = __commonJS({
|
|
|
30091
30093
|
var { parseMIMEType, serializeAMimeType } = require_dataURL();
|
|
30092
30094
|
var random;
|
|
30093
30095
|
try {
|
|
30094
|
-
const
|
|
30095
|
-
random = (max) =>
|
|
30096
|
+
const crypto4 = require("crypto");
|
|
30097
|
+
random = (max) => crypto4.randomInt(0, max);
|
|
30096
30098
|
} catch {
|
|
30097
30099
|
random = (max) => Math.floor(Math.random(max));
|
|
30098
30100
|
}
|
|
@@ -30343,8 +30345,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r
|
|
|
30343
30345
|
});
|
|
30344
30346
|
}
|
|
30345
30347
|
});
|
|
30346
|
-
const busboyResolve = new Promise((
|
|
30347
|
-
busboy.on("finish",
|
|
30348
|
+
const busboyResolve = new Promise((resolve15, reject) => {
|
|
30349
|
+
busboy.on("finish", resolve15);
|
|
30348
30350
|
busboy.on("error", (err) => reject(new TypeError(err)));
|
|
30349
30351
|
});
|
|
30350
30352
|
if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk);
|
|
@@ -30475,7 +30477,7 @@ var require_request = __commonJS({
|
|
|
30475
30477
|
}
|
|
30476
30478
|
var Request = class _Request {
|
|
30477
30479
|
constructor(origin, {
|
|
30478
|
-
path:
|
|
30480
|
+
path: path30,
|
|
30479
30481
|
method,
|
|
30480
30482
|
body,
|
|
30481
30483
|
headers,
|
|
@@ -30489,11 +30491,11 @@ var require_request = __commonJS({
|
|
|
30489
30491
|
throwOnError,
|
|
30490
30492
|
expectContinue
|
|
30491
30493
|
}, handler) {
|
|
30492
|
-
if (typeof
|
|
30494
|
+
if (typeof path30 !== "string") {
|
|
30493
30495
|
throw new InvalidArgumentError("path must be a string");
|
|
30494
|
-
} else if (
|
|
30496
|
+
} else if (path30[0] !== "/" && !(path30.startsWith("http://") || path30.startsWith("https://")) && method !== "CONNECT") {
|
|
30495
30497
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
30496
|
-
} else if (invalidPathRegex.exec(
|
|
30498
|
+
} else if (invalidPathRegex.exec(path30) !== null) {
|
|
30497
30499
|
throw new InvalidArgumentError("invalid request path");
|
|
30498
30500
|
}
|
|
30499
30501
|
if (typeof method !== "string") {
|
|
@@ -30556,7 +30558,7 @@ var require_request = __commonJS({
|
|
|
30556
30558
|
this.completed = false;
|
|
30557
30559
|
this.aborted = false;
|
|
30558
30560
|
this.upgrade = upgrade || null;
|
|
30559
|
-
this.path = query ? util.buildURL(
|
|
30561
|
+
this.path = query ? util.buildURL(path30, query) : path30;
|
|
30560
30562
|
this.origin = origin;
|
|
30561
30563
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
30562
30564
|
this.blocking = blocking == null ? false : blocking;
|
|
@@ -30878,9 +30880,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
30878
30880
|
}
|
|
30879
30881
|
close(callback) {
|
|
30880
30882
|
if (callback === void 0) {
|
|
30881
|
-
return new Promise((
|
|
30883
|
+
return new Promise((resolve15, reject) => {
|
|
30882
30884
|
this.close((err, data) => {
|
|
30883
|
-
return err ? reject(err) :
|
|
30885
|
+
return err ? reject(err) : resolve15(data);
|
|
30884
30886
|
});
|
|
30885
30887
|
});
|
|
30886
30888
|
}
|
|
@@ -30918,12 +30920,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
30918
30920
|
err = null;
|
|
30919
30921
|
}
|
|
30920
30922
|
if (callback === void 0) {
|
|
30921
|
-
return new Promise((
|
|
30923
|
+
return new Promise((resolve15, reject) => {
|
|
30922
30924
|
this.destroy(err, (err2, data) => {
|
|
30923
30925
|
return err2 ? (
|
|
30924
30926
|
/* istanbul ignore next: should never error */
|
|
30925
30927
|
reject(err2)
|
|
30926
|
-
) :
|
|
30928
|
+
) : resolve15(data);
|
|
30927
30929
|
});
|
|
30928
30930
|
});
|
|
30929
30931
|
}
|
|
@@ -31564,9 +31566,9 @@ var require_RedirectHandler = __commonJS({
|
|
|
31564
31566
|
return this.handler.onHeaders(statusCode, headers, resume, statusText);
|
|
31565
31567
|
}
|
|
31566
31568
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
31567
|
-
const
|
|
31569
|
+
const path30 = search ? `${pathname}${search}` : pathname;
|
|
31568
31570
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
31569
|
-
this.opts.path =
|
|
31571
|
+
this.opts.path = path30;
|
|
31570
31572
|
this.opts.origin = origin;
|
|
31571
31573
|
this.opts.maxRedirections = 0;
|
|
31572
31574
|
this.opts.query = null;
|
|
@@ -31985,16 +31987,16 @@ var require_client = __commonJS({
|
|
|
31985
31987
|
return this[kNeedDrain] < 2;
|
|
31986
31988
|
}
|
|
31987
31989
|
async [kClose]() {
|
|
31988
|
-
return new Promise((
|
|
31990
|
+
return new Promise((resolve15) => {
|
|
31989
31991
|
if (!this[kSize]) {
|
|
31990
|
-
|
|
31992
|
+
resolve15(null);
|
|
31991
31993
|
} else {
|
|
31992
|
-
this[kClosedResolve] =
|
|
31994
|
+
this[kClosedResolve] = resolve15;
|
|
31993
31995
|
}
|
|
31994
31996
|
});
|
|
31995
31997
|
}
|
|
31996
31998
|
async [kDestroy](err) {
|
|
31997
|
-
return new Promise((
|
|
31999
|
+
return new Promise((resolve15) => {
|
|
31998
32000
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
31999
32001
|
for (let i = 0; i < requests.length; i++) {
|
|
32000
32002
|
const request = requests[i];
|
|
@@ -32005,7 +32007,7 @@ var require_client = __commonJS({
|
|
|
32005
32007
|
this[kClosedResolve]();
|
|
32006
32008
|
this[kClosedResolve] = null;
|
|
32007
32009
|
}
|
|
32008
|
-
|
|
32010
|
+
resolve15();
|
|
32009
32011
|
};
|
|
32010
32012
|
if (this[kHTTP2Session] != null) {
|
|
32011
32013
|
util.destroy(this[kHTTP2Session], err);
|
|
@@ -32585,7 +32587,7 @@ var require_client = __commonJS({
|
|
|
32585
32587
|
});
|
|
32586
32588
|
}
|
|
32587
32589
|
try {
|
|
32588
|
-
const socket = await new Promise((
|
|
32590
|
+
const socket = await new Promise((resolve15, reject) => {
|
|
32589
32591
|
client[kConnector]({
|
|
32590
32592
|
host,
|
|
32591
32593
|
hostname,
|
|
@@ -32597,7 +32599,7 @@ var require_client = __commonJS({
|
|
|
32597
32599
|
if (err) {
|
|
32598
32600
|
reject(err);
|
|
32599
32601
|
} else {
|
|
32600
|
-
|
|
32602
|
+
resolve15(socket2);
|
|
32601
32603
|
}
|
|
32602
32604
|
});
|
|
32603
32605
|
});
|
|
@@ -32808,7 +32810,7 @@ var require_client = __commonJS({
|
|
|
32808
32810
|
writeH2(client, client[kHTTP2Session], request);
|
|
32809
32811
|
return;
|
|
32810
32812
|
}
|
|
32811
|
-
const { body, method, path:
|
|
32813
|
+
const { body, method, path: path30, host, upgrade, headers, blocking, reset } = request;
|
|
32812
32814
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
32813
32815
|
if (body && typeof body.read === "function") {
|
|
32814
32816
|
body.read(0);
|
|
@@ -32858,7 +32860,7 @@ var require_client = __commonJS({
|
|
|
32858
32860
|
if (blocking) {
|
|
32859
32861
|
socket[kBlocking] = true;
|
|
32860
32862
|
}
|
|
32861
|
-
let header = `${method} ${
|
|
32863
|
+
let header = `${method} ${path30} HTTP/1.1\r
|
|
32862
32864
|
`;
|
|
32863
32865
|
if (typeof host === "string") {
|
|
32864
32866
|
header += `host: ${host}\r
|
|
@@ -32921,7 +32923,7 @@ upgrade: ${upgrade}\r
|
|
|
32921
32923
|
return true;
|
|
32922
32924
|
}
|
|
32923
32925
|
function writeH2(client, session, request) {
|
|
32924
|
-
const { body, method, path:
|
|
32926
|
+
const { body, method, path: path30, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
|
|
32925
32927
|
let headers;
|
|
32926
32928
|
if (typeof reqHeaders === "string") headers = Request[kHTTP2CopyHeaders](reqHeaders.trim());
|
|
32927
32929
|
else headers = reqHeaders;
|
|
@@ -32964,7 +32966,7 @@ upgrade: ${upgrade}\r
|
|
|
32964
32966
|
});
|
|
32965
32967
|
return true;
|
|
32966
32968
|
}
|
|
32967
|
-
headers[HTTP2_HEADER_PATH] =
|
|
32969
|
+
headers[HTTP2_HEADER_PATH] = path30;
|
|
32968
32970
|
headers[HTTP2_HEADER_SCHEME] = "https";
|
|
32969
32971
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
32970
32972
|
if (body && typeof body.read === "function") {
|
|
@@ -33221,12 +33223,12 @@ upgrade: ${upgrade}\r
|
|
|
33221
33223
|
cb();
|
|
33222
33224
|
}
|
|
33223
33225
|
}
|
|
33224
|
-
const waitForDrain = () => new Promise((
|
|
33226
|
+
const waitForDrain = () => new Promise((resolve15, reject) => {
|
|
33225
33227
|
assert(callback === null);
|
|
33226
33228
|
if (socket[kError]) {
|
|
33227
33229
|
reject(socket[kError]);
|
|
33228
33230
|
} else {
|
|
33229
|
-
callback =
|
|
33231
|
+
callback = resolve15;
|
|
33230
33232
|
}
|
|
33231
33233
|
});
|
|
33232
33234
|
if (client[kHTTPConnVersion] === "h2") {
|
|
@@ -33572,8 +33574,8 @@ var require_pool_base = __commonJS({
|
|
|
33572
33574
|
if (this[kQueue].isEmpty()) {
|
|
33573
33575
|
return Promise.all(this[kClients].map((c) => c.close()));
|
|
33574
33576
|
} else {
|
|
33575
|
-
return new Promise((
|
|
33576
|
-
this[kClosedResolve] =
|
|
33577
|
+
return new Promise((resolve15) => {
|
|
33578
|
+
this[kClosedResolve] = resolve15;
|
|
33577
33579
|
});
|
|
33578
33580
|
}
|
|
33579
33581
|
}
|
|
@@ -34151,7 +34153,7 @@ var require_readable = __commonJS({
|
|
|
34151
34153
|
if (this.closed) {
|
|
34152
34154
|
return Promise.resolve(null);
|
|
34153
34155
|
}
|
|
34154
|
-
return new Promise((
|
|
34156
|
+
return new Promise((resolve15, reject) => {
|
|
34155
34157
|
const signalListenerCleanup = signal ? util.addAbortListener(signal, () => {
|
|
34156
34158
|
this.destroy();
|
|
34157
34159
|
}) : noop;
|
|
@@ -34160,7 +34162,7 @@ var require_readable = __commonJS({
|
|
|
34160
34162
|
if (signal && signal.aborted) {
|
|
34161
34163
|
reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" }));
|
|
34162
34164
|
} else {
|
|
34163
|
-
|
|
34165
|
+
resolve15(null);
|
|
34164
34166
|
}
|
|
34165
34167
|
}).on("error", noop).on("data", function(chunk) {
|
|
34166
34168
|
limit -= chunk.length;
|
|
@@ -34182,11 +34184,11 @@ var require_readable = __commonJS({
|
|
|
34182
34184
|
throw new TypeError("unusable");
|
|
34183
34185
|
}
|
|
34184
34186
|
assert(!stream[kConsume]);
|
|
34185
|
-
return new Promise((
|
|
34187
|
+
return new Promise((resolve15, reject) => {
|
|
34186
34188
|
stream[kConsume] = {
|
|
34187
34189
|
type,
|
|
34188
34190
|
stream,
|
|
34189
|
-
resolve:
|
|
34191
|
+
resolve: resolve15,
|
|
34190
34192
|
reject,
|
|
34191
34193
|
length: 0,
|
|
34192
34194
|
body: []
|
|
@@ -34221,12 +34223,12 @@ var require_readable = __commonJS({
|
|
|
34221
34223
|
}
|
|
34222
34224
|
}
|
|
34223
34225
|
function consumeEnd(consume2) {
|
|
34224
|
-
const { type, body, resolve:
|
|
34226
|
+
const { type, body, resolve: resolve15, stream, length } = consume2;
|
|
34225
34227
|
try {
|
|
34226
34228
|
if (type === "text") {
|
|
34227
|
-
|
|
34229
|
+
resolve15(toUSVString(Buffer.concat(body)));
|
|
34228
34230
|
} else if (type === "json") {
|
|
34229
|
-
|
|
34231
|
+
resolve15(JSON.parse(Buffer.concat(body)));
|
|
34230
34232
|
} else if (type === "arrayBuffer") {
|
|
34231
34233
|
const dst = new Uint8Array(length);
|
|
34232
34234
|
let pos = 0;
|
|
@@ -34234,12 +34236,12 @@ var require_readable = __commonJS({
|
|
|
34234
34236
|
dst.set(buf, pos);
|
|
34235
34237
|
pos += buf.byteLength;
|
|
34236
34238
|
}
|
|
34237
|
-
|
|
34239
|
+
resolve15(dst.buffer);
|
|
34238
34240
|
} else if (type === "blob") {
|
|
34239
34241
|
if (!Blob2) {
|
|
34240
34242
|
Blob2 = require("buffer").Blob;
|
|
34241
34243
|
}
|
|
34242
|
-
|
|
34244
|
+
resolve15(new Blob2(body, { type: stream[kContentType] }));
|
|
34243
34245
|
}
|
|
34244
34246
|
consumeFinish(consume2);
|
|
34245
34247
|
} catch (err) {
|
|
@@ -34496,9 +34498,9 @@ var require_api_request = __commonJS({
|
|
|
34496
34498
|
};
|
|
34497
34499
|
function request(opts, callback) {
|
|
34498
34500
|
if (callback === void 0) {
|
|
34499
|
-
return new Promise((
|
|
34501
|
+
return new Promise((resolve15, reject) => {
|
|
34500
34502
|
request.call(this, opts, (err, data) => {
|
|
34501
|
-
return err ? reject(err) :
|
|
34503
|
+
return err ? reject(err) : resolve15(data);
|
|
34502
34504
|
});
|
|
34503
34505
|
});
|
|
34504
34506
|
}
|
|
@@ -34671,9 +34673,9 @@ var require_api_stream = __commonJS({
|
|
|
34671
34673
|
};
|
|
34672
34674
|
function stream(opts, factory, callback) {
|
|
34673
34675
|
if (callback === void 0) {
|
|
34674
|
-
return new Promise((
|
|
34676
|
+
return new Promise((resolve15, reject) => {
|
|
34675
34677
|
stream.call(this, opts, factory, (err, data) => {
|
|
34676
|
-
return err ? reject(err) :
|
|
34678
|
+
return err ? reject(err) : resolve15(data);
|
|
34677
34679
|
});
|
|
34678
34680
|
});
|
|
34679
34681
|
}
|
|
@@ -34954,9 +34956,9 @@ var require_api_upgrade = __commonJS({
|
|
|
34954
34956
|
};
|
|
34955
34957
|
function upgrade(opts, callback) {
|
|
34956
34958
|
if (callback === void 0) {
|
|
34957
|
-
return new Promise((
|
|
34959
|
+
return new Promise((resolve15, reject) => {
|
|
34958
34960
|
upgrade.call(this, opts, (err, data) => {
|
|
34959
|
-
return err ? reject(err) :
|
|
34961
|
+
return err ? reject(err) : resolve15(data);
|
|
34960
34962
|
});
|
|
34961
34963
|
});
|
|
34962
34964
|
}
|
|
@@ -35045,9 +35047,9 @@ var require_api_connect = __commonJS({
|
|
|
35045
35047
|
};
|
|
35046
35048
|
function connect(opts, callback) {
|
|
35047
35049
|
if (callback === void 0) {
|
|
35048
|
-
return new Promise((
|
|
35050
|
+
return new Promise((resolve15, reject) => {
|
|
35049
35051
|
connect.call(this, opts, (err, data) => {
|
|
35050
|
-
return err ? reject(err) :
|
|
35052
|
+
return err ? reject(err) : resolve15(data);
|
|
35051
35053
|
});
|
|
35052
35054
|
});
|
|
35053
35055
|
}
|
|
@@ -35207,20 +35209,20 @@ var require_mock_utils = __commonJS({
|
|
|
35207
35209
|
}
|
|
35208
35210
|
return true;
|
|
35209
35211
|
}
|
|
35210
|
-
function safeUrl(
|
|
35211
|
-
if (typeof
|
|
35212
|
-
return
|
|
35212
|
+
function safeUrl(path30) {
|
|
35213
|
+
if (typeof path30 !== "string") {
|
|
35214
|
+
return path30;
|
|
35213
35215
|
}
|
|
35214
|
-
const pathSegments =
|
|
35216
|
+
const pathSegments = path30.split("?");
|
|
35215
35217
|
if (pathSegments.length !== 2) {
|
|
35216
|
-
return
|
|
35218
|
+
return path30;
|
|
35217
35219
|
}
|
|
35218
35220
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
35219
35221
|
qp.sort();
|
|
35220
35222
|
return [...pathSegments, qp.toString()].join("?");
|
|
35221
35223
|
}
|
|
35222
|
-
function matchKey(mockDispatch2, { path:
|
|
35223
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
35224
|
+
function matchKey(mockDispatch2, { path: path30, method, body, headers }) {
|
|
35225
|
+
const pathMatch = matchValue(mockDispatch2.path, path30);
|
|
35224
35226
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
35225
35227
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
35226
35228
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -35238,7 +35240,7 @@ var require_mock_utils = __commonJS({
|
|
|
35238
35240
|
function getMockDispatch(mockDispatches, key) {
|
|
35239
35241
|
const basePath = key.query ? buildURL(key.path, key.query) : key.path;
|
|
35240
35242
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
35241
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
35243
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path30 }) => matchValue(safeUrl(path30), resolvedPath));
|
|
35242
35244
|
if (matchedMockDispatches.length === 0) {
|
|
35243
35245
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
35244
35246
|
}
|
|
@@ -35275,9 +35277,9 @@ var require_mock_utils = __commonJS({
|
|
|
35275
35277
|
}
|
|
35276
35278
|
}
|
|
35277
35279
|
function buildKey(opts) {
|
|
35278
|
-
const { path:
|
|
35280
|
+
const { path: path30, method, body, headers, query } = opts;
|
|
35279
35281
|
return {
|
|
35280
|
-
path:
|
|
35282
|
+
path: path30,
|
|
35281
35283
|
method,
|
|
35282
35284
|
body,
|
|
35283
35285
|
headers,
|
|
@@ -35726,10 +35728,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
35726
35728
|
}
|
|
35727
35729
|
format(pendingInterceptors) {
|
|
35728
35730
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
35729
|
-
({ method, path:
|
|
35731
|
+
({ method, path: path30, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
35730
35732
|
Method: method,
|
|
35731
35733
|
Origin: origin,
|
|
35732
|
-
Path:
|
|
35734
|
+
Path: path30,
|
|
35733
35735
|
"Status code": statusCode,
|
|
35734
35736
|
Persistent: persist ? "\u2705" : "\u274C",
|
|
35735
35737
|
Invocations: timesInvoked,
|
|
@@ -38670,7 +38672,7 @@ var require_fetch = __commonJS({
|
|
|
38670
38672
|
async function dispatch({ body }) {
|
|
38671
38673
|
const url = requestCurrentURL(request);
|
|
38672
38674
|
const agent = fetchParams.controller.dispatcher;
|
|
38673
|
-
return new Promise((
|
|
38675
|
+
return new Promise((resolve15, reject) => agent.dispatch(
|
|
38674
38676
|
{
|
|
38675
38677
|
path: url.pathname + url.search,
|
|
38676
38678
|
origin: url.origin,
|
|
@@ -38746,7 +38748,7 @@ var require_fetch = __commonJS({
|
|
|
38746
38748
|
}
|
|
38747
38749
|
}
|
|
38748
38750
|
}
|
|
38749
|
-
|
|
38751
|
+
resolve15({
|
|
38750
38752
|
status,
|
|
38751
38753
|
statusText,
|
|
38752
38754
|
headersList: headers[kHeadersList],
|
|
@@ -38789,7 +38791,7 @@ var require_fetch = __commonJS({
|
|
|
38789
38791
|
const val = headersList[n + 1].toString("latin1");
|
|
38790
38792
|
headers[kHeadersList].append(key, val);
|
|
38791
38793
|
}
|
|
38792
|
-
|
|
38794
|
+
resolve15({
|
|
38793
38795
|
status,
|
|
38794
38796
|
statusText: STATUS_CODES[status],
|
|
38795
38797
|
headersList: headers[kHeadersList],
|
|
@@ -40350,8 +40352,8 @@ var require_util6 = __commonJS({
|
|
|
40350
40352
|
}
|
|
40351
40353
|
}
|
|
40352
40354
|
}
|
|
40353
|
-
function validateCookiePath(
|
|
40354
|
-
for (const char of
|
|
40355
|
+
function validateCookiePath(path30) {
|
|
40356
|
+
for (const char of path30) {
|
|
40355
40357
|
const code = char.charCodeAt(0);
|
|
40356
40358
|
if (code < 33 || char === ";") {
|
|
40357
40359
|
throw new Error("Invalid cookie path");
|
|
@@ -41148,9 +41150,9 @@ var require_connection = __commonJS({
|
|
|
41148
41150
|
channels.open = diagnosticsChannel.channel("undici:websocket:open");
|
|
41149
41151
|
channels.close = diagnosticsChannel.channel("undici:websocket:close");
|
|
41150
41152
|
channels.socketError = diagnosticsChannel.channel("undici:websocket:socket_error");
|
|
41151
|
-
var
|
|
41153
|
+
var crypto4;
|
|
41152
41154
|
try {
|
|
41153
|
-
|
|
41155
|
+
crypto4 = require("crypto");
|
|
41154
41156
|
} catch {
|
|
41155
41157
|
}
|
|
41156
41158
|
function establishWebSocketConnection(url, protocols, ws, onEstablish, options) {
|
|
@@ -41169,7 +41171,7 @@ var require_connection = __commonJS({
|
|
|
41169
41171
|
const headersList = new Headers(options.headers)[kHeadersList];
|
|
41170
41172
|
request.headersList = headersList;
|
|
41171
41173
|
}
|
|
41172
|
-
const keyValue =
|
|
41174
|
+
const keyValue = crypto4.randomBytes(16).toString("base64");
|
|
41173
41175
|
request.headersList.append("sec-websocket-key", keyValue);
|
|
41174
41176
|
request.headersList.append("sec-websocket-version", "13");
|
|
41175
41177
|
for (const protocol of protocols) {
|
|
@@ -41198,7 +41200,7 @@ var require_connection = __commonJS({
|
|
|
41198
41200
|
return;
|
|
41199
41201
|
}
|
|
41200
41202
|
const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
|
|
41201
|
-
const digest =
|
|
41203
|
+
const digest = crypto4.createHash("sha1").update(keyValue + uid).digest("base64");
|
|
41202
41204
|
if (secWSAccept !== digest) {
|
|
41203
41205
|
failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header.");
|
|
41204
41206
|
return;
|
|
@@ -41278,9 +41280,9 @@ var require_frame = __commonJS({
|
|
|
41278
41280
|
"node_modules/undici/lib/websocket/frame.js"(exports2, module2) {
|
|
41279
41281
|
"use strict";
|
|
41280
41282
|
var { maxUnsigned16Bit } = require_constants5();
|
|
41281
|
-
var
|
|
41283
|
+
var crypto4;
|
|
41282
41284
|
try {
|
|
41283
|
-
|
|
41285
|
+
crypto4 = require("crypto");
|
|
41284
41286
|
} catch {
|
|
41285
41287
|
}
|
|
41286
41288
|
var WebsocketFrameSend = class {
|
|
@@ -41289,7 +41291,7 @@ var require_frame = __commonJS({
|
|
|
41289
41291
|
*/
|
|
41290
41292
|
constructor(data) {
|
|
41291
41293
|
this.frameData = data;
|
|
41292
|
-
this.maskKey =
|
|
41294
|
+
this.maskKey = crypto4.randomBytes(4);
|
|
41293
41295
|
}
|
|
41294
41296
|
createFrame(opcode) {
|
|
41295
41297
|
const bodyLength = this.frameData?.byteLength ?? 0;
|
|
@@ -42031,11 +42033,11 @@ var require_undici = __commonJS({
|
|
|
42031
42033
|
if (typeof opts.path !== "string") {
|
|
42032
42034
|
throw new InvalidArgumentError("invalid opts.path");
|
|
42033
42035
|
}
|
|
42034
|
-
let
|
|
42036
|
+
let path30 = opts.path;
|
|
42035
42037
|
if (!opts.path.startsWith("/")) {
|
|
42036
|
-
|
|
42038
|
+
path30 = `/${path30}`;
|
|
42037
42039
|
}
|
|
42038
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
42040
|
+
url = new URL(util.parseOrigin(url).origin + path30);
|
|
42039
42041
|
} else {
|
|
42040
42042
|
if (!opts) {
|
|
42041
42043
|
opts = typeof url === "object" ? url : {};
|
|
@@ -42353,7 +42355,13 @@ var init_mcp_check_provider = __esm({
|
|
|
42353
42355
|
};
|
|
42354
42356
|
}
|
|
42355
42357
|
}
|
|
42356
|
-
const result = await this.executeMcpMethod(
|
|
42358
|
+
const result = await this.executeMcpMethod(
|
|
42359
|
+
cfg,
|
|
42360
|
+
methodArgs,
|
|
42361
|
+
prInfo,
|
|
42362
|
+
dependencyResults,
|
|
42363
|
+
sessionInfo
|
|
42364
|
+
);
|
|
42357
42365
|
let finalOutput = result;
|
|
42358
42366
|
if (cfg.transform) {
|
|
42359
42367
|
try {
|
|
@@ -42454,22 +42462,26 @@ var init_mcp_check_provider = __esm({
|
|
|
42454
42462
|
/**
|
|
42455
42463
|
* Execute an MCP method using the configured transport
|
|
42456
42464
|
*/
|
|
42457
|
-
async executeMcpMethod(config, methodArgs, prInfo, dependencyResults) {
|
|
42465
|
+
async executeMcpMethod(config, methodArgs, prInfo, dependencyResults, sessionInfo) {
|
|
42458
42466
|
const transport = config.transport || "stdio";
|
|
42459
42467
|
const timeout = (config.timeout || 60) * 1e3;
|
|
42460
42468
|
if (transport === "custom") {
|
|
42461
|
-
|
|
42462
|
-
|
|
42463
|
-
|
|
42464
|
-
);
|
|
42465
|
-
}
|
|
42466
|
-
const
|
|
42467
|
-
|
|
42468
|
-
|
|
42469
|
+
const localTools = sessionInfo?._parentContext?.config?.tools || sessionInfo?.config?.tools || {};
|
|
42470
|
+
let localExecutor;
|
|
42471
|
+
if (Object.keys(localTools).length > 0) {
|
|
42472
|
+
localExecutor = new CustomToolExecutor(localTools);
|
|
42473
|
+
}
|
|
42474
|
+
const hasLocalTool = localExecutor ? await localExecutor.hasTool(config.method) : false;
|
|
42475
|
+
const hasGlobalTool = this.customToolExecutor ? await this.customToolExecutor.hasTool(config.method) : false;
|
|
42476
|
+
if (!hasLocalTool && !hasGlobalTool) {
|
|
42477
|
+
const localNames = localExecutor ? await localExecutor.getToolNames() : [];
|
|
42478
|
+
const globalNames = this.customToolExecutor ? await this.customToolExecutor.getToolNames() : [];
|
|
42479
|
+
const availableToolNames = [.../* @__PURE__ */ new Set([...localNames, ...globalNames])];
|
|
42469
42480
|
throw new Error(
|
|
42470
42481
|
`Custom tool not found: ${config.method}. Available tools: ${availableToolNames.join(", ")}`
|
|
42471
42482
|
);
|
|
42472
42483
|
}
|
|
42484
|
+
const activeExecutor = hasLocalTool ? localExecutor : this.customToolExecutor;
|
|
42473
42485
|
const context2 = {
|
|
42474
42486
|
pr: prInfo ? {
|
|
42475
42487
|
number: prInfo.number,
|
|
@@ -42482,7 +42494,7 @@ var init_mcp_check_provider = __esm({
|
|
|
42482
42494
|
outputs: this.buildOutputContext(dependencyResults),
|
|
42483
42495
|
env: this.getSafeEnvironmentVariables()
|
|
42484
42496
|
};
|
|
42485
|
-
return await
|
|
42497
|
+
return await activeExecutor.execute(config.method, methodArgs, context2);
|
|
42486
42498
|
} else if (transport === "stdio") {
|
|
42487
42499
|
return await this.executeStdioMethod(config, methodArgs, timeout);
|
|
42488
42500
|
} else if (transport === "sse") {
|
|
@@ -42563,7 +42575,7 @@ var init_mcp_check_provider = __esm({
|
|
|
42563
42575
|
logger.warn(
|
|
42564
42576
|
`MCP ${transportName} failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`
|
|
42565
42577
|
);
|
|
42566
|
-
await new Promise((
|
|
42578
|
+
await new Promise((resolve15) => setTimeout(resolve15, delay));
|
|
42567
42579
|
attempt += 1;
|
|
42568
42580
|
} finally {
|
|
42569
42581
|
try {
|
|
@@ -42845,7 +42857,7 @@ async function acquirePromptLock() {
|
|
|
42845
42857
|
activePrompt = true;
|
|
42846
42858
|
return;
|
|
42847
42859
|
}
|
|
42848
|
-
await new Promise((
|
|
42860
|
+
await new Promise((resolve15) => waiters.push(resolve15));
|
|
42849
42861
|
activePrompt = true;
|
|
42850
42862
|
}
|
|
42851
42863
|
function releasePromptLock() {
|
|
@@ -42855,7 +42867,7 @@ function releasePromptLock() {
|
|
|
42855
42867
|
}
|
|
42856
42868
|
async function interactivePrompt(options) {
|
|
42857
42869
|
await acquirePromptLock();
|
|
42858
|
-
return new Promise((
|
|
42870
|
+
return new Promise((resolve15, reject) => {
|
|
42859
42871
|
const dbg = process.env.VISOR_DEBUG === "true";
|
|
42860
42872
|
try {
|
|
42861
42873
|
if (dbg) {
|
|
@@ -42942,12 +42954,12 @@ async function interactivePrompt(options) {
|
|
|
42942
42954
|
};
|
|
42943
42955
|
const finish = (value) => {
|
|
42944
42956
|
cleanup();
|
|
42945
|
-
|
|
42957
|
+
resolve15(value);
|
|
42946
42958
|
};
|
|
42947
42959
|
if (options.timeout && options.timeout > 0) {
|
|
42948
42960
|
timeoutId = setTimeout(() => {
|
|
42949
42961
|
cleanup();
|
|
42950
|
-
if (defaultValue !== void 0) return
|
|
42962
|
+
if (defaultValue !== void 0) return resolve15(defaultValue);
|
|
42951
42963
|
return reject(new Error("Input timeout"));
|
|
42952
42964
|
}, options.timeout);
|
|
42953
42965
|
}
|
|
@@ -43079,7 +43091,7 @@ async function interactivePrompt(options) {
|
|
|
43079
43091
|
});
|
|
43080
43092
|
}
|
|
43081
43093
|
async function simplePrompt(prompt) {
|
|
43082
|
-
return new Promise((
|
|
43094
|
+
return new Promise((resolve15) => {
|
|
43083
43095
|
const rl = readline.createInterface({
|
|
43084
43096
|
input: process.stdin,
|
|
43085
43097
|
output: process.stdout
|
|
@@ -43095,7 +43107,7 @@ async function simplePrompt(prompt) {
|
|
|
43095
43107
|
rl.question(`${prompt}
|
|
43096
43108
|
> `, (answer) => {
|
|
43097
43109
|
rl.close();
|
|
43098
|
-
|
|
43110
|
+
resolve15(answer.trim());
|
|
43099
43111
|
});
|
|
43100
43112
|
});
|
|
43101
43113
|
}
|
|
@@ -43263,7 +43275,7 @@ function isStdinAvailable() {
|
|
|
43263
43275
|
return !process.stdin.isTTY;
|
|
43264
43276
|
}
|
|
43265
43277
|
async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
43266
|
-
return new Promise((
|
|
43278
|
+
return new Promise((resolve15, reject) => {
|
|
43267
43279
|
let data = "";
|
|
43268
43280
|
let timeoutId;
|
|
43269
43281
|
if (timeout) {
|
|
@@ -43290,7 +43302,7 @@ async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
|
43290
43302
|
};
|
|
43291
43303
|
const onEnd = () => {
|
|
43292
43304
|
cleanup();
|
|
43293
|
-
|
|
43305
|
+
resolve15(data.trim());
|
|
43294
43306
|
};
|
|
43295
43307
|
const onError = (err) => {
|
|
43296
43308
|
cleanup();
|
|
@@ -47320,23 +47332,23 @@ __export(renderer_schema_exports, {
|
|
|
47320
47332
|
});
|
|
47321
47333
|
async function loadRendererSchema(name) {
|
|
47322
47334
|
try {
|
|
47323
|
-
const
|
|
47324
|
-
const
|
|
47335
|
+
const fs26 = await import("fs/promises");
|
|
47336
|
+
const path30 = await import("path");
|
|
47325
47337
|
const sanitized = String(name).replace(/[^a-zA-Z0-9-]/g, "");
|
|
47326
47338
|
if (!sanitized) return void 0;
|
|
47327
47339
|
const candidates = [
|
|
47328
47340
|
// When bundled with ncc, __dirname is dist/ and output/ is at dist/output/
|
|
47329
|
-
|
|
47341
|
+
path30.join(__dirname, "output", sanitized, "schema.json"),
|
|
47330
47342
|
// When running from source, __dirname is src/state-machine/dispatch/ and output/ is at output/
|
|
47331
|
-
|
|
47343
|
+
path30.join(__dirname, "..", "..", "output", sanitized, "schema.json"),
|
|
47332
47344
|
// When running from a checkout with output/ folder copied to CWD
|
|
47333
|
-
|
|
47345
|
+
path30.join(process.cwd(), "output", sanitized, "schema.json"),
|
|
47334
47346
|
// Fallback: cwd/dist/output/
|
|
47335
|
-
|
|
47347
|
+
path30.join(process.cwd(), "dist", "output", sanitized, "schema.json")
|
|
47336
47348
|
];
|
|
47337
47349
|
for (const p of candidates) {
|
|
47338
47350
|
try {
|
|
47339
|
-
const raw = await
|
|
47351
|
+
const raw = await fs26.readFile(p, "utf-8");
|
|
47340
47352
|
return JSON.parse(raw);
|
|
47341
47353
|
} catch {
|
|
47342
47354
|
}
|
|
@@ -49755,8 +49767,8 @@ function updateStats2(results, state, isForEachIteration = false) {
|
|
|
49755
49767
|
async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
49756
49768
|
try {
|
|
49757
49769
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
49758
|
-
const
|
|
49759
|
-
const
|
|
49770
|
+
const fs26 = await import("fs/promises");
|
|
49771
|
+
const path30 = await import("path");
|
|
49760
49772
|
const schemaRaw = checkConfig.schema || "plain";
|
|
49761
49773
|
const schema = typeof schemaRaw === "string" && !schemaRaw.includes("{{") && !schemaRaw.includes("{%") ? schemaRaw : typeof schemaRaw === "object" ? "code-review" : "plain";
|
|
49762
49774
|
let templateContent;
|
|
@@ -49765,27 +49777,27 @@ async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
|
49765
49777
|
logger.debug(`[LevelDispatch] Using inline template for ${checkId}`);
|
|
49766
49778
|
} else if (checkConfig.template && checkConfig.template.file) {
|
|
49767
49779
|
const file = String(checkConfig.template.file);
|
|
49768
|
-
const resolved =
|
|
49769
|
-
templateContent = await
|
|
49780
|
+
const resolved = path30.resolve(process.cwd(), file);
|
|
49781
|
+
templateContent = await fs26.readFile(resolved, "utf-8");
|
|
49770
49782
|
logger.debug(`[LevelDispatch] Using template file for ${checkId}: ${resolved}`);
|
|
49771
49783
|
} else if (schema && schema !== "plain") {
|
|
49772
49784
|
const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
|
|
49773
49785
|
if (sanitized) {
|
|
49774
49786
|
const candidatePaths = [
|
|
49775
|
-
|
|
49787
|
+
path30.join(__dirname, "output", sanitized, "template.liquid"),
|
|
49776
49788
|
// bundled: dist/output/
|
|
49777
|
-
|
|
49789
|
+
path30.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
49778
49790
|
// source (from state-machine/states)
|
|
49779
|
-
|
|
49791
|
+
path30.join(__dirname, "..", "..", "..", "output", sanitized, "template.liquid"),
|
|
49780
49792
|
// source (alternate)
|
|
49781
|
-
|
|
49793
|
+
path30.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
49782
49794
|
// fallback: cwd/output/
|
|
49783
|
-
|
|
49795
|
+
path30.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
|
|
49784
49796
|
// fallback: cwd/dist/output/
|
|
49785
49797
|
];
|
|
49786
49798
|
for (const p of candidatePaths) {
|
|
49787
49799
|
try {
|
|
49788
|
-
templateContent = await
|
|
49800
|
+
templateContent = await fs26.readFile(p, "utf-8");
|
|
49789
49801
|
if (templateContent) {
|
|
49790
49802
|
logger.debug(`[LevelDispatch] Using schema template for ${checkId}: ${p}`);
|
|
49791
49803
|
break;
|
|
@@ -51586,8 +51598,8 @@ var init_workspace_manager = __esm({
|
|
|
51586
51598
|
);
|
|
51587
51599
|
if (this.cleanupRequested && this.activeOperations === 0) {
|
|
51588
51600
|
logger.debug(`[Workspace] All references released, proceeding with deferred cleanup`);
|
|
51589
|
-
for (const
|
|
51590
|
-
|
|
51601
|
+
for (const resolve15 of this.cleanupResolvers) {
|
|
51602
|
+
resolve15();
|
|
51591
51603
|
}
|
|
51592
51604
|
this.cleanupResolvers = [];
|
|
51593
51605
|
}
|
|
@@ -51712,19 +51724,19 @@ var init_workspace_manager = __esm({
|
|
|
51712
51724
|
);
|
|
51713
51725
|
this.cleanupRequested = true;
|
|
51714
51726
|
await Promise.race([
|
|
51715
|
-
new Promise((
|
|
51727
|
+
new Promise((resolve15) => {
|
|
51716
51728
|
if (this.activeOperations === 0) {
|
|
51717
|
-
|
|
51729
|
+
resolve15();
|
|
51718
51730
|
} else {
|
|
51719
|
-
this.cleanupResolvers.push(
|
|
51731
|
+
this.cleanupResolvers.push(resolve15);
|
|
51720
51732
|
}
|
|
51721
51733
|
}),
|
|
51722
|
-
new Promise((
|
|
51734
|
+
new Promise((resolve15) => {
|
|
51723
51735
|
setTimeout(() => {
|
|
51724
51736
|
logger.warn(
|
|
51725
51737
|
`[Workspace] Cleanup timeout after ${timeout}ms, proceeding anyway (${this.activeOperations} operations still active)`
|
|
51726
51738
|
);
|
|
51727
|
-
|
|
51739
|
+
resolve15();
|
|
51728
51740
|
}, timeout);
|
|
51729
51741
|
})
|
|
51730
51742
|
]);
|
|
@@ -52003,6 +52015,1264 @@ var init_build_engine_context = __esm({
|
|
|
52003
52015
|
}
|
|
52004
52016
|
});
|
|
52005
52017
|
|
|
52018
|
+
// src/policy/default-engine.ts
|
|
52019
|
+
var DefaultPolicyEngine;
|
|
52020
|
+
var init_default_engine = __esm({
|
|
52021
|
+
"src/policy/default-engine.ts"() {
|
|
52022
|
+
"use strict";
|
|
52023
|
+
DefaultPolicyEngine = class {
|
|
52024
|
+
async initialize(_config) {
|
|
52025
|
+
}
|
|
52026
|
+
async evaluateCheckExecution(_checkId, _checkConfig) {
|
|
52027
|
+
return { allowed: true };
|
|
52028
|
+
}
|
|
52029
|
+
async evaluateToolInvocation(_serverName, _methodName, _transport) {
|
|
52030
|
+
return { allowed: true };
|
|
52031
|
+
}
|
|
52032
|
+
async evaluateCapabilities(_checkId, _capabilities) {
|
|
52033
|
+
return { allowed: true };
|
|
52034
|
+
}
|
|
52035
|
+
async shutdown() {
|
|
52036
|
+
}
|
|
52037
|
+
};
|
|
52038
|
+
}
|
|
52039
|
+
});
|
|
52040
|
+
|
|
52041
|
+
// src/enterprise/license/validator.ts
|
|
52042
|
+
var validator_exports = {};
|
|
52043
|
+
__export(validator_exports, {
|
|
52044
|
+
LicenseValidator: () => LicenseValidator
|
|
52045
|
+
});
|
|
52046
|
+
var crypto2, fs19, path23, LicenseValidator;
|
|
52047
|
+
var init_validator = __esm({
|
|
52048
|
+
"src/enterprise/license/validator.ts"() {
|
|
52049
|
+
"use strict";
|
|
52050
|
+
crypto2 = __toESM(require("crypto"));
|
|
52051
|
+
fs19 = __toESM(require("fs"));
|
|
52052
|
+
path23 = __toESM(require("path"));
|
|
52053
|
+
LicenseValidator = class _LicenseValidator {
|
|
52054
|
+
/** Ed25519 public key for license verification (PEM format). */
|
|
52055
|
+
static PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAI/Zd08EFmgIdrDm/HXd0l3/5GBt7R1PrdvhdmEXhJlU=\n-----END PUBLIC KEY-----\n";
|
|
52056
|
+
cache = null;
|
|
52057
|
+
static CACHE_TTL = 5 * 60 * 1e3;
|
|
52058
|
+
// 5 minutes
|
|
52059
|
+
static GRACE_PERIOD = 72 * 3600 * 1e3;
|
|
52060
|
+
// 72 hours after expiry
|
|
52061
|
+
/**
|
|
52062
|
+
* Load and validate license from environment or file.
|
|
52063
|
+
*
|
|
52064
|
+
* Resolution order:
|
|
52065
|
+
* 1. VISOR_LICENSE env var (JWT string)
|
|
52066
|
+
* 2. VISOR_LICENSE_FILE env var (path to file)
|
|
52067
|
+
* 3. .visor-license in project root (cwd)
|
|
52068
|
+
* 4. .visor-license in ~/.config/visor/
|
|
52069
|
+
*/
|
|
52070
|
+
async loadAndValidate() {
|
|
52071
|
+
if (this.cache && Date.now() - this.cache.validatedAt < _LicenseValidator.CACHE_TTL) {
|
|
52072
|
+
return this.cache.payload;
|
|
52073
|
+
}
|
|
52074
|
+
const token = this.resolveToken();
|
|
52075
|
+
if (!token) return null;
|
|
52076
|
+
const payload = this.verifyAndDecode(token);
|
|
52077
|
+
if (!payload) return null;
|
|
52078
|
+
this.cache = { payload, validatedAt: Date.now() };
|
|
52079
|
+
return payload;
|
|
52080
|
+
}
|
|
52081
|
+
/** Check if a specific feature is licensed */
|
|
52082
|
+
hasFeature(feature) {
|
|
52083
|
+
if (!this.cache) return false;
|
|
52084
|
+
return this.cache.payload.features.includes(feature);
|
|
52085
|
+
}
|
|
52086
|
+
/** Check if license is valid (with grace period) */
|
|
52087
|
+
isValid() {
|
|
52088
|
+
if (!this.cache) return false;
|
|
52089
|
+
const now = Date.now();
|
|
52090
|
+
const expiryMs = this.cache.payload.exp * 1e3;
|
|
52091
|
+
return now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
52092
|
+
}
|
|
52093
|
+
/** Check if the license is within its grace period (expired but still valid) */
|
|
52094
|
+
isInGracePeriod() {
|
|
52095
|
+
if (!this.cache) return false;
|
|
52096
|
+
const now = Date.now();
|
|
52097
|
+
const expiryMs = this.cache.payload.exp * 1e3;
|
|
52098
|
+
return now >= expiryMs && now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
52099
|
+
}
|
|
52100
|
+
resolveToken() {
|
|
52101
|
+
if (process.env.VISOR_LICENSE) {
|
|
52102
|
+
return process.env.VISOR_LICENSE.trim();
|
|
52103
|
+
}
|
|
52104
|
+
if (process.env.VISOR_LICENSE_FILE) {
|
|
52105
|
+
const resolved = path23.resolve(process.env.VISOR_LICENSE_FILE);
|
|
52106
|
+
const home2 = process.env.HOME || process.env.USERPROFILE || "";
|
|
52107
|
+
const allowedPrefixes = [path23.normalize(process.cwd())];
|
|
52108
|
+
if (home2) allowedPrefixes.push(path23.normalize(path23.join(home2, ".config", "visor")));
|
|
52109
|
+
let realPath;
|
|
52110
|
+
try {
|
|
52111
|
+
realPath = fs19.realpathSync(resolved);
|
|
52112
|
+
} catch {
|
|
52113
|
+
return null;
|
|
52114
|
+
}
|
|
52115
|
+
const isSafe = allowedPrefixes.some(
|
|
52116
|
+
(prefix) => realPath === prefix || realPath.startsWith(prefix + path23.sep)
|
|
52117
|
+
);
|
|
52118
|
+
if (!isSafe) return null;
|
|
52119
|
+
return this.readFile(realPath);
|
|
52120
|
+
}
|
|
52121
|
+
const cwdPath = path23.join(process.cwd(), ".visor-license");
|
|
52122
|
+
const cwdToken = this.readFile(cwdPath);
|
|
52123
|
+
if (cwdToken) return cwdToken;
|
|
52124
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
52125
|
+
if (home) {
|
|
52126
|
+
const configPath = path23.join(home, ".config", "visor", ".visor-license");
|
|
52127
|
+
const configToken = this.readFile(configPath);
|
|
52128
|
+
if (configToken) return configToken;
|
|
52129
|
+
}
|
|
52130
|
+
return null;
|
|
52131
|
+
}
|
|
52132
|
+
readFile(filePath) {
|
|
52133
|
+
try {
|
|
52134
|
+
return fs19.readFileSync(filePath, "utf-8").trim();
|
|
52135
|
+
} catch {
|
|
52136
|
+
return null;
|
|
52137
|
+
}
|
|
52138
|
+
}
|
|
52139
|
+
verifyAndDecode(token) {
|
|
52140
|
+
try {
|
|
52141
|
+
const parts = token.split(".");
|
|
52142
|
+
if (parts.length !== 3) return null;
|
|
52143
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
52144
|
+
const header = JSON.parse(Buffer.from(headerB64, "base64url").toString());
|
|
52145
|
+
if (header.alg !== "EdDSA") return null;
|
|
52146
|
+
const data = `${headerB64}.${payloadB64}`;
|
|
52147
|
+
const signature = Buffer.from(signatureB64, "base64url");
|
|
52148
|
+
const publicKey = crypto2.createPublicKey(_LicenseValidator.PUBLIC_KEY);
|
|
52149
|
+
if (publicKey.asymmetricKeyType !== "ed25519") {
|
|
52150
|
+
return null;
|
|
52151
|
+
}
|
|
52152
|
+
const isValid = crypto2.verify(null, Buffer.from(data), publicKey, signature);
|
|
52153
|
+
if (!isValid) return null;
|
|
52154
|
+
const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
|
|
52155
|
+
if (!payload.org || !Array.isArray(payload.features) || typeof payload.exp !== "number" || typeof payload.iat !== "number" || !payload.sub) {
|
|
52156
|
+
return null;
|
|
52157
|
+
}
|
|
52158
|
+
const now = Date.now();
|
|
52159
|
+
const expiryMs = payload.exp * 1e3;
|
|
52160
|
+
if (now >= expiryMs + _LicenseValidator.GRACE_PERIOD) {
|
|
52161
|
+
return null;
|
|
52162
|
+
}
|
|
52163
|
+
return payload;
|
|
52164
|
+
} catch {
|
|
52165
|
+
return null;
|
|
52166
|
+
}
|
|
52167
|
+
}
|
|
52168
|
+
};
|
|
52169
|
+
}
|
|
52170
|
+
});
|
|
52171
|
+
|
|
52172
|
+
// src/enterprise/policy/opa-compiler.ts
|
|
52173
|
+
var fs20, path24, os, crypto3, import_child_process5, OpaCompiler;
|
|
52174
|
+
var init_opa_compiler = __esm({
|
|
52175
|
+
"src/enterprise/policy/opa-compiler.ts"() {
|
|
52176
|
+
"use strict";
|
|
52177
|
+
fs20 = __toESM(require("fs"));
|
|
52178
|
+
path24 = __toESM(require("path"));
|
|
52179
|
+
os = __toESM(require("os"));
|
|
52180
|
+
crypto3 = __toESM(require("crypto"));
|
|
52181
|
+
import_child_process5 = require("child_process");
|
|
52182
|
+
OpaCompiler = class _OpaCompiler {
|
|
52183
|
+
static CACHE_DIR = path24.join(os.tmpdir(), "visor-opa-cache");
|
|
52184
|
+
/**
|
|
52185
|
+
* Resolve the input paths to WASM bytes.
|
|
52186
|
+
*
|
|
52187
|
+
* Strategy:
|
|
52188
|
+
* 1. If any path is a .wasm file, read it directly
|
|
52189
|
+
* 2. If a directory contains policy.wasm, read it
|
|
52190
|
+
* 3. Otherwise, collect all .rego files and auto-compile via `opa build`
|
|
52191
|
+
*/
|
|
52192
|
+
async resolveWasmBytes(paths) {
|
|
52193
|
+
const regoFiles = [];
|
|
52194
|
+
for (const p of paths) {
|
|
52195
|
+
const resolved = path24.resolve(p);
|
|
52196
|
+
if (path24.normalize(resolved).includes("..")) {
|
|
52197
|
+
throw new Error(`Policy path contains traversal sequences: ${p}`);
|
|
52198
|
+
}
|
|
52199
|
+
if (resolved.endsWith(".wasm") && fs20.existsSync(resolved)) {
|
|
52200
|
+
return fs20.readFileSync(resolved);
|
|
52201
|
+
}
|
|
52202
|
+
if (!fs20.existsSync(resolved)) continue;
|
|
52203
|
+
const stat = fs20.statSync(resolved);
|
|
52204
|
+
if (stat.isDirectory()) {
|
|
52205
|
+
const wasmCandidate = path24.join(resolved, "policy.wasm");
|
|
52206
|
+
if (fs20.existsSync(wasmCandidate)) {
|
|
52207
|
+
return fs20.readFileSync(wasmCandidate);
|
|
52208
|
+
}
|
|
52209
|
+
const files = fs20.readdirSync(resolved);
|
|
52210
|
+
for (const f of files) {
|
|
52211
|
+
if (f.endsWith(".rego")) {
|
|
52212
|
+
regoFiles.push(path24.join(resolved, f));
|
|
52213
|
+
}
|
|
52214
|
+
}
|
|
52215
|
+
} else if (resolved.endsWith(".rego")) {
|
|
52216
|
+
regoFiles.push(resolved);
|
|
52217
|
+
}
|
|
52218
|
+
}
|
|
52219
|
+
if (regoFiles.length === 0) {
|
|
52220
|
+
throw new Error(
|
|
52221
|
+
`OPA WASM evaluator: no .wasm bundle or .rego files found in: ${paths.join(", ")}`
|
|
52222
|
+
);
|
|
52223
|
+
}
|
|
52224
|
+
return this.compileRego(regoFiles);
|
|
52225
|
+
}
|
|
52226
|
+
/**
|
|
52227
|
+
* Auto-compile .rego files to a WASM bundle using the `opa` CLI.
|
|
52228
|
+
*
|
|
52229
|
+
* Caches the compiled bundle based on a content hash of all input .rego files
|
|
52230
|
+
* so subsequent runs skip compilation if policies haven't changed.
|
|
52231
|
+
*/
|
|
52232
|
+
compileRego(regoFiles) {
|
|
52233
|
+
try {
|
|
52234
|
+
(0, import_child_process5.execFileSync)("opa", ["version"], { stdio: "pipe" });
|
|
52235
|
+
} catch {
|
|
52236
|
+
throw new Error(
|
|
52237
|
+
"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(" ")
|
|
52238
|
+
);
|
|
52239
|
+
}
|
|
52240
|
+
const hash = crypto3.createHash("sha256");
|
|
52241
|
+
for (const f of regoFiles.sort()) {
|
|
52242
|
+
hash.update(fs20.readFileSync(f));
|
|
52243
|
+
hash.update(f);
|
|
52244
|
+
}
|
|
52245
|
+
const cacheKey = hash.digest("hex").slice(0, 16);
|
|
52246
|
+
const cacheDir = _OpaCompiler.CACHE_DIR;
|
|
52247
|
+
const cachedWasm = path24.join(cacheDir, `${cacheKey}.wasm`);
|
|
52248
|
+
if (fs20.existsSync(cachedWasm)) {
|
|
52249
|
+
return fs20.readFileSync(cachedWasm);
|
|
52250
|
+
}
|
|
52251
|
+
fs20.mkdirSync(cacheDir, { recursive: true });
|
|
52252
|
+
const bundleTar = path24.join(cacheDir, `${cacheKey}-bundle.tar.gz`);
|
|
52253
|
+
try {
|
|
52254
|
+
const args = [
|
|
52255
|
+
"build",
|
|
52256
|
+
"-t",
|
|
52257
|
+
"wasm",
|
|
52258
|
+
"-e",
|
|
52259
|
+
"visor",
|
|
52260
|
+
// entrypoint: the visor package tree
|
|
52261
|
+
"-o",
|
|
52262
|
+
bundleTar,
|
|
52263
|
+
...regoFiles
|
|
52264
|
+
];
|
|
52265
|
+
(0, import_child_process5.execFileSync)("opa", args, {
|
|
52266
|
+
stdio: "pipe",
|
|
52267
|
+
timeout: 3e4
|
|
52268
|
+
});
|
|
52269
|
+
} catch (err) {
|
|
52270
|
+
const stderr = err?.stderr?.toString() || "";
|
|
52271
|
+
throw new Error(
|
|
52272
|
+
`Failed to compile .rego files to WASM:
|
|
52273
|
+
${stderr}
|
|
52274
|
+
Ensure your .rego files are valid and the \`opa\` CLI is installed.`
|
|
52275
|
+
);
|
|
52276
|
+
}
|
|
52277
|
+
try {
|
|
52278
|
+
(0, import_child_process5.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "/policy.wasm"], {
|
|
52279
|
+
stdio: "pipe"
|
|
52280
|
+
});
|
|
52281
|
+
const extractedWasm = path24.join(cacheDir, "policy.wasm");
|
|
52282
|
+
if (fs20.existsSync(extractedWasm)) {
|
|
52283
|
+
fs20.renameSync(extractedWasm, cachedWasm);
|
|
52284
|
+
}
|
|
52285
|
+
} catch {
|
|
52286
|
+
try {
|
|
52287
|
+
(0, import_child_process5.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "policy.wasm"], {
|
|
52288
|
+
stdio: "pipe"
|
|
52289
|
+
});
|
|
52290
|
+
const extractedWasm = path24.join(cacheDir, "policy.wasm");
|
|
52291
|
+
if (fs20.existsSync(extractedWasm)) {
|
|
52292
|
+
fs20.renameSync(extractedWasm, cachedWasm);
|
|
52293
|
+
}
|
|
52294
|
+
} catch (err2) {
|
|
52295
|
+
throw new Error(`Failed to extract policy.wasm from OPA bundle: ${err2?.message || err2}`);
|
|
52296
|
+
}
|
|
52297
|
+
}
|
|
52298
|
+
try {
|
|
52299
|
+
fs20.unlinkSync(bundleTar);
|
|
52300
|
+
} catch {
|
|
52301
|
+
}
|
|
52302
|
+
if (!fs20.existsSync(cachedWasm)) {
|
|
52303
|
+
throw new Error("OPA build succeeded but policy.wasm was not found in the bundle");
|
|
52304
|
+
}
|
|
52305
|
+
return fs20.readFileSync(cachedWasm);
|
|
52306
|
+
}
|
|
52307
|
+
};
|
|
52308
|
+
}
|
|
52309
|
+
});
|
|
52310
|
+
|
|
52311
|
+
// src/enterprise/policy/opa-wasm-evaluator.ts
|
|
52312
|
+
var fs21, path25, OpaWasmEvaluator;
|
|
52313
|
+
var init_opa_wasm_evaluator = __esm({
|
|
52314
|
+
"src/enterprise/policy/opa-wasm-evaluator.ts"() {
|
|
52315
|
+
"use strict";
|
|
52316
|
+
fs21 = __toESM(require("fs"));
|
|
52317
|
+
path25 = __toESM(require("path"));
|
|
52318
|
+
init_opa_compiler();
|
|
52319
|
+
OpaWasmEvaluator = class {
|
|
52320
|
+
policy = null;
|
|
52321
|
+
dataDocument = {};
|
|
52322
|
+
compiler = new OpaCompiler();
|
|
52323
|
+
async initialize(rulesPath) {
|
|
52324
|
+
const paths = Array.isArray(rulesPath) ? rulesPath : [rulesPath];
|
|
52325
|
+
const wasmBytes = await this.compiler.resolveWasmBytes(paths);
|
|
52326
|
+
try {
|
|
52327
|
+
const { createRequire } = require("module");
|
|
52328
|
+
const runtimeRequire = createRequire(__filename);
|
|
52329
|
+
const opaWasm = runtimeRequire("@open-policy-agent/opa-wasm");
|
|
52330
|
+
const loadPolicy = opaWasm.loadPolicy || opaWasm.default?.loadPolicy;
|
|
52331
|
+
if (!loadPolicy) {
|
|
52332
|
+
throw new Error("loadPolicy not found in @open-policy-agent/opa-wasm");
|
|
52333
|
+
}
|
|
52334
|
+
this.policy = await loadPolicy(wasmBytes);
|
|
52335
|
+
} catch (err) {
|
|
52336
|
+
if (err?.code === "MODULE_NOT_FOUND" || err?.code === "ERR_MODULE_NOT_FOUND") {
|
|
52337
|
+
throw new Error(
|
|
52338
|
+
"OPA WASM evaluator requires @open-policy-agent/opa-wasm. Install it with: npm install @open-policy-agent/opa-wasm"
|
|
52339
|
+
);
|
|
52340
|
+
}
|
|
52341
|
+
throw err;
|
|
52342
|
+
}
|
|
52343
|
+
}
|
|
52344
|
+
/**
|
|
52345
|
+
* Load external data from a JSON file to use as the OPA data document.
|
|
52346
|
+
* The loaded data will be passed to `policy.setData()` during evaluation,
|
|
52347
|
+
* making it available in Rego via `data.<key>`.
|
|
52348
|
+
*/
|
|
52349
|
+
loadData(dataPath) {
|
|
52350
|
+
const resolved = path25.resolve(dataPath);
|
|
52351
|
+
if (path25.normalize(resolved).includes("..")) {
|
|
52352
|
+
throw new Error(`Data path contains traversal sequences: ${dataPath}`);
|
|
52353
|
+
}
|
|
52354
|
+
if (!fs21.existsSync(resolved)) {
|
|
52355
|
+
throw new Error(`OPA data file not found: ${resolved}`);
|
|
52356
|
+
}
|
|
52357
|
+
const stat = fs21.statSync(resolved);
|
|
52358
|
+
if (stat.size > 10 * 1024 * 1024) {
|
|
52359
|
+
throw new Error(`OPA data file exceeds 10MB limit: ${resolved} (${stat.size} bytes)`);
|
|
52360
|
+
}
|
|
52361
|
+
const raw = fs21.readFileSync(resolved, "utf-8");
|
|
52362
|
+
try {
|
|
52363
|
+
const parsed = JSON.parse(raw);
|
|
52364
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
52365
|
+
throw new Error("OPA data file must contain a JSON object (not an array or primitive)");
|
|
52366
|
+
}
|
|
52367
|
+
this.dataDocument = parsed;
|
|
52368
|
+
} catch (err) {
|
|
52369
|
+
if (err.message.startsWith("OPA data file must")) {
|
|
52370
|
+
throw err;
|
|
52371
|
+
}
|
|
52372
|
+
throw new Error(`Failed to parse OPA data file ${resolved}: ${err.message}`);
|
|
52373
|
+
}
|
|
52374
|
+
}
|
|
52375
|
+
async evaluate(input) {
|
|
52376
|
+
if (!this.policy) {
|
|
52377
|
+
throw new Error("OPA WASM evaluator not initialized");
|
|
52378
|
+
}
|
|
52379
|
+
this.policy.setData(this.dataDocument);
|
|
52380
|
+
const resultSet = this.policy.evaluate(input);
|
|
52381
|
+
if (Array.isArray(resultSet) && resultSet.length > 0) {
|
|
52382
|
+
return resultSet[0].result;
|
|
52383
|
+
}
|
|
52384
|
+
return void 0;
|
|
52385
|
+
}
|
|
52386
|
+
async shutdown() {
|
|
52387
|
+
if (this.policy) {
|
|
52388
|
+
if (typeof this.policy.close === "function") {
|
|
52389
|
+
try {
|
|
52390
|
+
this.policy.close();
|
|
52391
|
+
} catch {
|
|
52392
|
+
}
|
|
52393
|
+
} else if (typeof this.policy.free === "function") {
|
|
52394
|
+
try {
|
|
52395
|
+
this.policy.free();
|
|
52396
|
+
} catch {
|
|
52397
|
+
}
|
|
52398
|
+
}
|
|
52399
|
+
}
|
|
52400
|
+
this.policy = null;
|
|
52401
|
+
}
|
|
52402
|
+
};
|
|
52403
|
+
}
|
|
52404
|
+
});
|
|
52405
|
+
|
|
52406
|
+
// src/enterprise/policy/opa-http-evaluator.ts
|
|
52407
|
+
var OpaHttpEvaluator;
|
|
52408
|
+
var init_opa_http_evaluator = __esm({
|
|
52409
|
+
"src/enterprise/policy/opa-http-evaluator.ts"() {
|
|
52410
|
+
"use strict";
|
|
52411
|
+
OpaHttpEvaluator = class {
|
|
52412
|
+
baseUrl;
|
|
52413
|
+
timeout;
|
|
52414
|
+
constructor(baseUrl, timeout = 5e3) {
|
|
52415
|
+
let parsed;
|
|
52416
|
+
try {
|
|
52417
|
+
parsed = new URL(baseUrl);
|
|
52418
|
+
} catch {
|
|
52419
|
+
throw new Error(`OPA HTTP evaluator: invalid URL: ${baseUrl}`);
|
|
52420
|
+
}
|
|
52421
|
+
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
52422
|
+
throw new Error(
|
|
52423
|
+
`OPA HTTP evaluator: url must use http:// or https:// protocol, got: ${baseUrl}`
|
|
52424
|
+
);
|
|
52425
|
+
}
|
|
52426
|
+
const hostname = parsed.hostname;
|
|
52427
|
+
if (this.isBlockedHostname(hostname)) {
|
|
52428
|
+
throw new Error(
|
|
52429
|
+
`OPA HTTP evaluator: url must not point to internal, loopback, or private network addresses`
|
|
52430
|
+
);
|
|
52431
|
+
}
|
|
52432
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
52433
|
+
this.timeout = timeout;
|
|
52434
|
+
}
|
|
52435
|
+
/**
|
|
52436
|
+
* Check if a hostname is blocked due to SSRF concerns.
|
|
52437
|
+
*
|
|
52438
|
+
* Blocks:
|
|
52439
|
+
* - Loopback addresses (127.x.x.x, localhost, 0.0.0.0, ::1)
|
|
52440
|
+
* - Link-local addresses (169.254.x.x)
|
|
52441
|
+
* - Private networks (10.x.x.x, 172.16-31.x.x, 192.168.x.x)
|
|
52442
|
+
* - IPv6 unique local addresses (fd00::/8)
|
|
52443
|
+
* - Cloud metadata services (*.internal)
|
|
52444
|
+
*/
|
|
52445
|
+
isBlockedHostname(hostname) {
|
|
52446
|
+
if (!hostname) return true;
|
|
52447
|
+
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
52448
|
+
if (normalized === "metadata.google.internal" || normalized.endsWith(".internal")) {
|
|
52449
|
+
return true;
|
|
52450
|
+
}
|
|
52451
|
+
if (normalized === "localhost" || normalized === "localhost.localdomain") {
|
|
52452
|
+
return true;
|
|
52453
|
+
}
|
|
52454
|
+
if (normalized === "::1" || normalized === "0:0:0:0:0:0:0:1") {
|
|
52455
|
+
return true;
|
|
52456
|
+
}
|
|
52457
|
+
const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
52458
|
+
const ipv4Match = normalized.match(ipv4Pattern);
|
|
52459
|
+
if (ipv4Match) {
|
|
52460
|
+
const octets = ipv4Match.slice(1, 5).map(Number);
|
|
52461
|
+
if (octets.some((octet) => octet > 255)) {
|
|
52462
|
+
return false;
|
|
52463
|
+
}
|
|
52464
|
+
const [a, b] = octets;
|
|
52465
|
+
if (a === 127) {
|
|
52466
|
+
return true;
|
|
52467
|
+
}
|
|
52468
|
+
if (a === 0) {
|
|
52469
|
+
return true;
|
|
52470
|
+
}
|
|
52471
|
+
if (a === 169 && b === 254) {
|
|
52472
|
+
return true;
|
|
52473
|
+
}
|
|
52474
|
+
if (a === 10) {
|
|
52475
|
+
return true;
|
|
52476
|
+
}
|
|
52477
|
+
if (a === 172 && b >= 16 && b <= 31) {
|
|
52478
|
+
return true;
|
|
52479
|
+
}
|
|
52480
|
+
if (a === 192 && b === 168) {
|
|
52481
|
+
return true;
|
|
52482
|
+
}
|
|
52483
|
+
}
|
|
52484
|
+
if (normalized.startsWith("fd") || normalized.startsWith("fc")) {
|
|
52485
|
+
return true;
|
|
52486
|
+
}
|
|
52487
|
+
if (normalized.startsWith("fe80:")) {
|
|
52488
|
+
return true;
|
|
52489
|
+
}
|
|
52490
|
+
return false;
|
|
52491
|
+
}
|
|
52492
|
+
/**
|
|
52493
|
+
* Evaluate a policy rule against an input document via OPA REST API.
|
|
52494
|
+
*
|
|
52495
|
+
* @param input - The input document to evaluate
|
|
52496
|
+
* @param rulePath - OPA rule path (e.g., 'visor/check/execute')
|
|
52497
|
+
* @returns The result object from OPA, or undefined on error
|
|
52498
|
+
*/
|
|
52499
|
+
async evaluate(input, rulePath) {
|
|
52500
|
+
const encodedPath = rulePath.split("/").map((s) => encodeURIComponent(s)).join("/");
|
|
52501
|
+
const url = `${this.baseUrl}/v1/data/${encodedPath}`;
|
|
52502
|
+
const controller = new AbortController();
|
|
52503
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
52504
|
+
try {
|
|
52505
|
+
const response = await fetch(url, {
|
|
52506
|
+
method: "POST",
|
|
52507
|
+
headers: { "Content-Type": "application/json" },
|
|
52508
|
+
body: JSON.stringify({ input }),
|
|
52509
|
+
signal: controller.signal
|
|
52510
|
+
});
|
|
52511
|
+
if (!response.ok) {
|
|
52512
|
+
throw new Error(`OPA HTTP ${response.status}: ${response.statusText}`);
|
|
52513
|
+
}
|
|
52514
|
+
let body;
|
|
52515
|
+
try {
|
|
52516
|
+
body = await response.json();
|
|
52517
|
+
} catch (jsonErr) {
|
|
52518
|
+
throw new Error(
|
|
52519
|
+
`OPA HTTP evaluator: failed to parse JSON response: ${jsonErr instanceof Error ? jsonErr.message : String(jsonErr)}`
|
|
52520
|
+
);
|
|
52521
|
+
}
|
|
52522
|
+
return body?.result;
|
|
52523
|
+
} finally {
|
|
52524
|
+
clearTimeout(timer);
|
|
52525
|
+
}
|
|
52526
|
+
}
|
|
52527
|
+
async shutdown() {
|
|
52528
|
+
}
|
|
52529
|
+
};
|
|
52530
|
+
}
|
|
52531
|
+
});
|
|
52532
|
+
|
|
52533
|
+
// src/enterprise/policy/policy-input-builder.ts
|
|
52534
|
+
var PolicyInputBuilder;
|
|
52535
|
+
var init_policy_input_builder = __esm({
|
|
52536
|
+
"src/enterprise/policy/policy-input-builder.ts"() {
|
|
52537
|
+
"use strict";
|
|
52538
|
+
PolicyInputBuilder = class {
|
|
52539
|
+
roles;
|
|
52540
|
+
actor;
|
|
52541
|
+
repository;
|
|
52542
|
+
pullRequest;
|
|
52543
|
+
constructor(policyConfig, actor, repository, pullRequest) {
|
|
52544
|
+
this.roles = policyConfig.roles || {};
|
|
52545
|
+
this.actor = actor;
|
|
52546
|
+
this.repository = repository;
|
|
52547
|
+
this.pullRequest = pullRequest;
|
|
52548
|
+
}
|
|
52549
|
+
/** Resolve which roles apply to the current actor. */
|
|
52550
|
+
resolveRoles() {
|
|
52551
|
+
const matched = [];
|
|
52552
|
+
for (const [roleName, roleConfig] of Object.entries(this.roles)) {
|
|
52553
|
+
let identityMatch = false;
|
|
52554
|
+
if (roleConfig.author_association && this.actor.authorAssociation && roleConfig.author_association.includes(this.actor.authorAssociation)) {
|
|
52555
|
+
identityMatch = true;
|
|
52556
|
+
}
|
|
52557
|
+
if (!identityMatch && roleConfig.users && this.actor.login && roleConfig.users.includes(this.actor.login)) {
|
|
52558
|
+
identityMatch = true;
|
|
52559
|
+
}
|
|
52560
|
+
if (!identityMatch && roleConfig.slack_users && this.actor.slack?.userId && roleConfig.slack_users.includes(this.actor.slack.userId)) {
|
|
52561
|
+
identityMatch = true;
|
|
52562
|
+
}
|
|
52563
|
+
if (!identityMatch && roleConfig.emails && this.actor.slack?.email) {
|
|
52564
|
+
const actorEmail = this.actor.slack.email.toLowerCase();
|
|
52565
|
+
if (roleConfig.emails.some((e) => e.toLowerCase() === actorEmail)) {
|
|
52566
|
+
identityMatch = true;
|
|
52567
|
+
}
|
|
52568
|
+
}
|
|
52569
|
+
if (!identityMatch) continue;
|
|
52570
|
+
if (roleConfig.slack_channels && roleConfig.slack_channels.length > 0) {
|
|
52571
|
+
if (!this.actor.slack?.channelId || !roleConfig.slack_channels.includes(this.actor.slack.channelId)) {
|
|
52572
|
+
continue;
|
|
52573
|
+
}
|
|
52574
|
+
}
|
|
52575
|
+
matched.push(roleName);
|
|
52576
|
+
}
|
|
52577
|
+
return matched;
|
|
52578
|
+
}
|
|
52579
|
+
buildActor() {
|
|
52580
|
+
return {
|
|
52581
|
+
authorAssociation: this.actor.authorAssociation,
|
|
52582
|
+
login: this.actor.login,
|
|
52583
|
+
roles: this.resolveRoles(),
|
|
52584
|
+
isLocalMode: this.actor.isLocalMode,
|
|
52585
|
+
...this.actor.slack && { slack: this.actor.slack }
|
|
52586
|
+
};
|
|
52587
|
+
}
|
|
52588
|
+
forCheckExecution(check) {
|
|
52589
|
+
return {
|
|
52590
|
+
scope: "check.execute",
|
|
52591
|
+
check: {
|
|
52592
|
+
id: check.id,
|
|
52593
|
+
type: check.type,
|
|
52594
|
+
group: check.group,
|
|
52595
|
+
tags: check.tags,
|
|
52596
|
+
criticality: check.criticality,
|
|
52597
|
+
sandbox: check.sandbox,
|
|
52598
|
+
policy: check.policy
|
|
52599
|
+
},
|
|
52600
|
+
actor: this.buildActor(),
|
|
52601
|
+
repository: this.repository,
|
|
52602
|
+
pullRequest: this.pullRequest
|
|
52603
|
+
};
|
|
52604
|
+
}
|
|
52605
|
+
forToolInvocation(serverName, methodName, transport) {
|
|
52606
|
+
return {
|
|
52607
|
+
scope: "tool.invoke",
|
|
52608
|
+
tool: { serverName, methodName, transport },
|
|
52609
|
+
actor: this.buildActor(),
|
|
52610
|
+
repository: this.repository,
|
|
52611
|
+
pullRequest: this.pullRequest
|
|
52612
|
+
};
|
|
52613
|
+
}
|
|
52614
|
+
forCapabilityResolve(checkId, capabilities) {
|
|
52615
|
+
return {
|
|
52616
|
+
scope: "capability.resolve",
|
|
52617
|
+
check: { id: checkId, type: "ai" },
|
|
52618
|
+
capability: capabilities,
|
|
52619
|
+
actor: this.buildActor(),
|
|
52620
|
+
repository: this.repository,
|
|
52621
|
+
pullRequest: this.pullRequest
|
|
52622
|
+
};
|
|
52623
|
+
}
|
|
52624
|
+
};
|
|
52625
|
+
}
|
|
52626
|
+
});
|
|
52627
|
+
|
|
52628
|
+
// src/enterprise/policy/opa-policy-engine.ts
|
|
52629
|
+
var opa_policy_engine_exports = {};
|
|
52630
|
+
__export(opa_policy_engine_exports, {
|
|
52631
|
+
OpaPolicyEngine: () => OpaPolicyEngine
|
|
52632
|
+
});
|
|
52633
|
+
var OpaPolicyEngine;
|
|
52634
|
+
var init_opa_policy_engine = __esm({
|
|
52635
|
+
"src/enterprise/policy/opa-policy-engine.ts"() {
|
|
52636
|
+
"use strict";
|
|
52637
|
+
init_opa_wasm_evaluator();
|
|
52638
|
+
init_opa_http_evaluator();
|
|
52639
|
+
init_policy_input_builder();
|
|
52640
|
+
OpaPolicyEngine = class {
|
|
52641
|
+
evaluator = null;
|
|
52642
|
+
fallback;
|
|
52643
|
+
timeout;
|
|
52644
|
+
config;
|
|
52645
|
+
inputBuilder = null;
|
|
52646
|
+
logger = null;
|
|
52647
|
+
constructor(config) {
|
|
52648
|
+
this.config = config;
|
|
52649
|
+
this.fallback = config.fallback || "deny";
|
|
52650
|
+
this.timeout = config.timeout || 5e3;
|
|
52651
|
+
}
|
|
52652
|
+
async initialize(config) {
|
|
52653
|
+
try {
|
|
52654
|
+
this.logger = (init_logger(), __toCommonJS(logger_exports)).logger;
|
|
52655
|
+
} catch {
|
|
52656
|
+
}
|
|
52657
|
+
const actor = {
|
|
52658
|
+
authorAssociation: process.env.VISOR_AUTHOR_ASSOCIATION,
|
|
52659
|
+
login: process.env.VISOR_AUTHOR_LOGIN || process.env.GITHUB_ACTOR,
|
|
52660
|
+
isLocalMode: !process.env.GITHUB_ACTIONS
|
|
52661
|
+
};
|
|
52662
|
+
const repo = {
|
|
52663
|
+
owner: process.env.GITHUB_REPOSITORY_OWNER,
|
|
52664
|
+
name: process.env.GITHUB_REPOSITORY?.split("/")[1],
|
|
52665
|
+
branch: process.env.GITHUB_HEAD_REF,
|
|
52666
|
+
baseBranch: process.env.GITHUB_BASE_REF,
|
|
52667
|
+
event: process.env.GITHUB_EVENT_NAME
|
|
52668
|
+
};
|
|
52669
|
+
const prNum = process.env.GITHUB_PR_NUMBER ? parseInt(process.env.GITHUB_PR_NUMBER, 10) : void 0;
|
|
52670
|
+
const pullRequest = {
|
|
52671
|
+
number: prNum !== void 0 && Number.isFinite(prNum) ? prNum : void 0
|
|
52672
|
+
};
|
|
52673
|
+
this.inputBuilder = new PolicyInputBuilder(config, actor, repo, pullRequest);
|
|
52674
|
+
if (config.engine === "local") {
|
|
52675
|
+
if (!config.rules) {
|
|
52676
|
+
throw new Error("OPA local mode requires `policy.rules` path to .wasm or .rego files");
|
|
52677
|
+
}
|
|
52678
|
+
const wasm = new OpaWasmEvaluator();
|
|
52679
|
+
await wasm.initialize(config.rules);
|
|
52680
|
+
if (config.data) {
|
|
52681
|
+
wasm.loadData(config.data);
|
|
52682
|
+
}
|
|
52683
|
+
this.evaluator = wasm;
|
|
52684
|
+
} else if (config.engine === "remote") {
|
|
52685
|
+
if (!config.url) {
|
|
52686
|
+
throw new Error("OPA remote mode requires `policy.url` pointing to OPA server");
|
|
52687
|
+
}
|
|
52688
|
+
this.evaluator = new OpaHttpEvaluator(config.url, this.timeout);
|
|
52689
|
+
} else {
|
|
52690
|
+
this.evaluator = null;
|
|
52691
|
+
}
|
|
52692
|
+
}
|
|
52693
|
+
/**
|
|
52694
|
+
* Update actor/repo/PR context (e.g., after PR info becomes available).
|
|
52695
|
+
* Called by the enterprise loader when engine context is enriched.
|
|
52696
|
+
*/
|
|
52697
|
+
setActorContext(actor, repo, pullRequest) {
|
|
52698
|
+
this.inputBuilder = new PolicyInputBuilder(this.config, actor, repo, pullRequest);
|
|
52699
|
+
}
|
|
52700
|
+
async evaluateCheckExecution(checkId, checkConfig) {
|
|
52701
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
52702
|
+
const cfg = checkConfig && typeof checkConfig === "object" ? checkConfig : {};
|
|
52703
|
+
const policyOverride = cfg.policy;
|
|
52704
|
+
const input = this.inputBuilder.forCheckExecution({
|
|
52705
|
+
id: checkId,
|
|
52706
|
+
type: cfg.type || "ai",
|
|
52707
|
+
group: cfg.group,
|
|
52708
|
+
tags: cfg.tags,
|
|
52709
|
+
criticality: cfg.criticality,
|
|
52710
|
+
sandbox: cfg.sandbox,
|
|
52711
|
+
policy: policyOverride
|
|
52712
|
+
});
|
|
52713
|
+
return this.doEvaluate(input, this.resolveRulePath("check.execute", policyOverride?.rule));
|
|
52714
|
+
}
|
|
52715
|
+
async evaluateToolInvocation(serverName, methodName, transport) {
|
|
52716
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
52717
|
+
const input = this.inputBuilder.forToolInvocation(serverName, methodName, transport);
|
|
52718
|
+
return this.doEvaluate(input, "visor/tool/invoke");
|
|
52719
|
+
}
|
|
52720
|
+
async evaluateCapabilities(checkId, capabilities) {
|
|
52721
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
52722
|
+
const input = this.inputBuilder.forCapabilityResolve(checkId, capabilities);
|
|
52723
|
+
return this.doEvaluate(input, "visor/capability/resolve");
|
|
52724
|
+
}
|
|
52725
|
+
async shutdown() {
|
|
52726
|
+
if (this.evaluator && "shutdown" in this.evaluator) {
|
|
52727
|
+
await this.evaluator.shutdown();
|
|
52728
|
+
}
|
|
52729
|
+
this.evaluator = null;
|
|
52730
|
+
this.inputBuilder = null;
|
|
52731
|
+
}
|
|
52732
|
+
resolveRulePath(defaultScope, override) {
|
|
52733
|
+
if (override) {
|
|
52734
|
+
return override.startsWith("visor/") ? override : `visor/${override}`;
|
|
52735
|
+
}
|
|
52736
|
+
return `visor/${defaultScope.replace(/\./g, "/")}`;
|
|
52737
|
+
}
|
|
52738
|
+
async doEvaluate(input, rulePath) {
|
|
52739
|
+
try {
|
|
52740
|
+
this.logger?.debug(`[PolicyEngine] Evaluating ${rulePath}`, JSON.stringify(input));
|
|
52741
|
+
let timer;
|
|
52742
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
52743
|
+
timer = setTimeout(() => reject(new Error("policy evaluation timeout")), this.timeout);
|
|
52744
|
+
});
|
|
52745
|
+
try {
|
|
52746
|
+
const result = await Promise.race([this.rawEvaluate(input, rulePath), timeoutPromise]);
|
|
52747
|
+
const decision = this.parseDecision(result);
|
|
52748
|
+
if (!decision.allowed && this.fallback === "warn") {
|
|
52749
|
+
decision.allowed = true;
|
|
52750
|
+
decision.warn = true;
|
|
52751
|
+
decision.reason = `audit: ${decision.reason || "policy denied"}`;
|
|
52752
|
+
}
|
|
52753
|
+
this.logger?.debug(
|
|
52754
|
+
`[PolicyEngine] Decision for ${rulePath}: allowed=${decision.allowed}, warn=${decision.warn || false}, reason=${decision.reason || "none"}`
|
|
52755
|
+
);
|
|
52756
|
+
return decision;
|
|
52757
|
+
} finally {
|
|
52758
|
+
if (timer) clearTimeout(timer);
|
|
52759
|
+
}
|
|
52760
|
+
} catch (err) {
|
|
52761
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
52762
|
+
this.logger?.warn(`[PolicyEngine] Evaluation failed for ${rulePath}: ${msg}`);
|
|
52763
|
+
return {
|
|
52764
|
+
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
52765
|
+
warn: this.fallback === "warn" ? true : void 0,
|
|
52766
|
+
reason: `policy evaluation failed, fallback=${this.fallback}`
|
|
52767
|
+
};
|
|
52768
|
+
}
|
|
52769
|
+
}
|
|
52770
|
+
async rawEvaluate(input, rulePath) {
|
|
52771
|
+
if (this.evaluator instanceof OpaWasmEvaluator) {
|
|
52772
|
+
const result = await this.evaluator.evaluate(input);
|
|
52773
|
+
return this.navigateWasmResult(result, rulePath);
|
|
52774
|
+
}
|
|
52775
|
+
return this.evaluator.evaluate(input, rulePath);
|
|
52776
|
+
}
|
|
52777
|
+
/**
|
|
52778
|
+
* Navigate nested OPA WASM result tree to reach the specific rule's output.
|
|
52779
|
+
* The WASM entrypoint `-e visor` means the result root IS the visor package,
|
|
52780
|
+
* so we strip the `visor/` prefix and walk the remaining segments.
|
|
52781
|
+
*/
|
|
52782
|
+
navigateWasmResult(result, rulePath) {
|
|
52783
|
+
if (!result || typeof result !== "object") return result;
|
|
52784
|
+
const segments = rulePath.replace(/^visor\//, "").split("/");
|
|
52785
|
+
let current = result;
|
|
52786
|
+
for (const seg of segments) {
|
|
52787
|
+
if (current && typeof current === "object" && seg in current) {
|
|
52788
|
+
current = current[seg];
|
|
52789
|
+
} else {
|
|
52790
|
+
return void 0;
|
|
52791
|
+
}
|
|
52792
|
+
}
|
|
52793
|
+
return current;
|
|
52794
|
+
}
|
|
52795
|
+
parseDecision(result) {
|
|
52796
|
+
if (result === void 0 || result === null) {
|
|
52797
|
+
return {
|
|
52798
|
+
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
52799
|
+
warn: this.fallback === "warn" ? true : void 0,
|
|
52800
|
+
reason: this.fallback === "warn" ? "audit: no policy result" : "no policy result"
|
|
52801
|
+
};
|
|
52802
|
+
}
|
|
52803
|
+
const allowed = result.allowed !== false;
|
|
52804
|
+
const decision = {
|
|
52805
|
+
allowed,
|
|
52806
|
+
reason: result.reason
|
|
52807
|
+
};
|
|
52808
|
+
if (result.capabilities) {
|
|
52809
|
+
decision.capabilities = result.capabilities;
|
|
52810
|
+
}
|
|
52811
|
+
return decision;
|
|
52812
|
+
}
|
|
52813
|
+
};
|
|
52814
|
+
}
|
|
52815
|
+
});
|
|
52816
|
+
|
|
52817
|
+
// src/enterprise/scheduler/knex-store.ts
|
|
52818
|
+
var knex_store_exports = {};
|
|
52819
|
+
__export(knex_store_exports, {
|
|
52820
|
+
KnexStoreBackend: () => KnexStoreBackend
|
|
52821
|
+
});
|
|
52822
|
+
function toNum(val) {
|
|
52823
|
+
if (val === null || val === void 0) return void 0;
|
|
52824
|
+
return typeof val === "string" ? parseInt(val, 10) : val;
|
|
52825
|
+
}
|
|
52826
|
+
function safeJsonParse2(value) {
|
|
52827
|
+
if (!value) return void 0;
|
|
52828
|
+
try {
|
|
52829
|
+
return JSON.parse(value);
|
|
52830
|
+
} catch {
|
|
52831
|
+
return void 0;
|
|
52832
|
+
}
|
|
52833
|
+
}
|
|
52834
|
+
function fromDbRow2(row) {
|
|
52835
|
+
return {
|
|
52836
|
+
id: row.id,
|
|
52837
|
+
creatorId: row.creator_id,
|
|
52838
|
+
creatorContext: row.creator_context ?? void 0,
|
|
52839
|
+
creatorName: row.creator_name ?? void 0,
|
|
52840
|
+
timezone: row.timezone,
|
|
52841
|
+
schedule: row.schedule_expr,
|
|
52842
|
+
runAt: toNum(row.run_at),
|
|
52843
|
+
isRecurring: row.is_recurring === true || row.is_recurring === 1,
|
|
52844
|
+
originalExpression: row.original_expression,
|
|
52845
|
+
workflow: row.workflow ?? void 0,
|
|
52846
|
+
workflowInputs: safeJsonParse2(row.workflow_inputs),
|
|
52847
|
+
outputContext: safeJsonParse2(row.output_context),
|
|
52848
|
+
status: row.status,
|
|
52849
|
+
createdAt: toNum(row.created_at),
|
|
52850
|
+
lastRunAt: toNum(row.last_run_at),
|
|
52851
|
+
nextRunAt: toNum(row.next_run_at),
|
|
52852
|
+
runCount: row.run_count,
|
|
52853
|
+
failureCount: row.failure_count,
|
|
52854
|
+
lastError: row.last_error ?? void 0,
|
|
52855
|
+
previousResponse: row.previous_response ?? void 0
|
|
52856
|
+
};
|
|
52857
|
+
}
|
|
52858
|
+
function toInsertRow(schedule) {
|
|
52859
|
+
return {
|
|
52860
|
+
id: schedule.id,
|
|
52861
|
+
creator_id: schedule.creatorId,
|
|
52862
|
+
creator_context: schedule.creatorContext ?? null,
|
|
52863
|
+
creator_name: schedule.creatorName ?? null,
|
|
52864
|
+
timezone: schedule.timezone,
|
|
52865
|
+
schedule_expr: schedule.schedule,
|
|
52866
|
+
run_at: schedule.runAt ?? null,
|
|
52867
|
+
is_recurring: schedule.isRecurring,
|
|
52868
|
+
original_expression: schedule.originalExpression,
|
|
52869
|
+
workflow: schedule.workflow ?? null,
|
|
52870
|
+
workflow_inputs: schedule.workflowInputs ? JSON.stringify(schedule.workflowInputs) : null,
|
|
52871
|
+
output_context: schedule.outputContext ? JSON.stringify(schedule.outputContext) : null,
|
|
52872
|
+
status: schedule.status,
|
|
52873
|
+
created_at: schedule.createdAt,
|
|
52874
|
+
last_run_at: schedule.lastRunAt ?? null,
|
|
52875
|
+
next_run_at: schedule.nextRunAt ?? null,
|
|
52876
|
+
run_count: schedule.runCount,
|
|
52877
|
+
failure_count: schedule.failureCount,
|
|
52878
|
+
last_error: schedule.lastError ?? null,
|
|
52879
|
+
previous_response: schedule.previousResponse ?? null
|
|
52880
|
+
};
|
|
52881
|
+
}
|
|
52882
|
+
var fs22, path26, import_uuid2, KnexStoreBackend;
|
|
52883
|
+
var init_knex_store = __esm({
|
|
52884
|
+
"src/enterprise/scheduler/knex-store.ts"() {
|
|
52885
|
+
"use strict";
|
|
52886
|
+
fs22 = __toESM(require("fs"));
|
|
52887
|
+
path26 = __toESM(require("path"));
|
|
52888
|
+
import_uuid2 = require("uuid");
|
|
52889
|
+
init_logger();
|
|
52890
|
+
KnexStoreBackend = class {
|
|
52891
|
+
knex = null;
|
|
52892
|
+
driver;
|
|
52893
|
+
connection;
|
|
52894
|
+
constructor(driver, storageConfig, _haConfig) {
|
|
52895
|
+
this.driver = driver;
|
|
52896
|
+
this.connection = storageConfig.connection || {};
|
|
52897
|
+
}
|
|
52898
|
+
async initialize() {
|
|
52899
|
+
const { createRequire } = require("module");
|
|
52900
|
+
const runtimeRequire = createRequire(__filename);
|
|
52901
|
+
let knexFactory;
|
|
52902
|
+
try {
|
|
52903
|
+
knexFactory = runtimeRequire("knex");
|
|
52904
|
+
} catch (err) {
|
|
52905
|
+
const code = err?.code;
|
|
52906
|
+
if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
|
|
52907
|
+
throw new Error(
|
|
52908
|
+
"knex is required for PostgreSQL/MySQL/MSSQL schedule storage. Install it with: npm install knex"
|
|
52909
|
+
);
|
|
52910
|
+
}
|
|
52911
|
+
throw err;
|
|
52912
|
+
}
|
|
52913
|
+
const clientMap = {
|
|
52914
|
+
postgresql: "pg",
|
|
52915
|
+
mysql: "mysql2",
|
|
52916
|
+
mssql: "tedious"
|
|
52917
|
+
};
|
|
52918
|
+
const client = clientMap[this.driver];
|
|
52919
|
+
let connection;
|
|
52920
|
+
if (this.connection.connection_string) {
|
|
52921
|
+
connection = this.connection.connection_string;
|
|
52922
|
+
} else if (this.driver === "mssql") {
|
|
52923
|
+
connection = this.buildMssqlConnection();
|
|
52924
|
+
} else {
|
|
52925
|
+
connection = this.buildStandardConnection();
|
|
52926
|
+
}
|
|
52927
|
+
this.knex = knexFactory({
|
|
52928
|
+
client,
|
|
52929
|
+
connection,
|
|
52930
|
+
pool: {
|
|
52931
|
+
min: this.connection.pool?.min ?? 0,
|
|
52932
|
+
max: this.connection.pool?.max ?? 10
|
|
52933
|
+
}
|
|
52934
|
+
});
|
|
52935
|
+
await this.migrateSchema();
|
|
52936
|
+
logger.info(`[KnexStore] Initialized (${this.driver})`);
|
|
52937
|
+
}
|
|
52938
|
+
buildStandardConnection() {
|
|
52939
|
+
return {
|
|
52940
|
+
host: this.connection.host || "localhost",
|
|
52941
|
+
port: this.connection.port,
|
|
52942
|
+
database: this.connection.database || "visor",
|
|
52943
|
+
user: this.connection.user,
|
|
52944
|
+
password: this.connection.password,
|
|
52945
|
+
ssl: this.resolveSslConfig()
|
|
52946
|
+
};
|
|
52947
|
+
}
|
|
52948
|
+
buildMssqlConnection() {
|
|
52949
|
+
const ssl = this.connection.ssl;
|
|
52950
|
+
const sslEnabled = ssl === true || typeof ssl === "object" && ssl.enabled !== false;
|
|
52951
|
+
return {
|
|
52952
|
+
server: this.connection.host || "localhost",
|
|
52953
|
+
port: this.connection.port,
|
|
52954
|
+
database: this.connection.database || "visor",
|
|
52955
|
+
user: this.connection.user,
|
|
52956
|
+
password: this.connection.password,
|
|
52957
|
+
options: {
|
|
52958
|
+
encrypt: sslEnabled,
|
|
52959
|
+
trustServerCertificate: typeof ssl === "object" ? ssl.reject_unauthorized === false : !sslEnabled
|
|
52960
|
+
}
|
|
52961
|
+
};
|
|
52962
|
+
}
|
|
52963
|
+
resolveSslConfig() {
|
|
52964
|
+
const ssl = this.connection.ssl;
|
|
52965
|
+
if (ssl === false || ssl === void 0) return false;
|
|
52966
|
+
if (ssl === true) return { rejectUnauthorized: true };
|
|
52967
|
+
if (ssl.enabled === false) return false;
|
|
52968
|
+
const result = {
|
|
52969
|
+
rejectUnauthorized: ssl.reject_unauthorized !== false
|
|
52970
|
+
};
|
|
52971
|
+
if (ssl.ca) {
|
|
52972
|
+
const caPath = this.validateSslPath(ssl.ca, "CA certificate");
|
|
52973
|
+
result.ca = fs22.readFileSync(caPath, "utf8");
|
|
52974
|
+
}
|
|
52975
|
+
if (ssl.cert) {
|
|
52976
|
+
const certPath = this.validateSslPath(ssl.cert, "client certificate");
|
|
52977
|
+
result.cert = fs22.readFileSync(certPath, "utf8");
|
|
52978
|
+
}
|
|
52979
|
+
if (ssl.key) {
|
|
52980
|
+
const keyPath = this.validateSslPath(ssl.key, "client key");
|
|
52981
|
+
result.key = fs22.readFileSync(keyPath, "utf8");
|
|
52982
|
+
}
|
|
52983
|
+
return result;
|
|
52984
|
+
}
|
|
52985
|
+
validateSslPath(filePath, label) {
|
|
52986
|
+
const resolved = path26.resolve(filePath);
|
|
52987
|
+
if (resolved !== path26.normalize(resolved)) {
|
|
52988
|
+
throw new Error(`SSL ${label} path contains invalid sequences: ${filePath}`);
|
|
52989
|
+
}
|
|
52990
|
+
if (!fs22.existsSync(resolved)) {
|
|
52991
|
+
throw new Error(`SSL ${label} not found: ${filePath}`);
|
|
52992
|
+
}
|
|
52993
|
+
return resolved;
|
|
52994
|
+
}
|
|
52995
|
+
async shutdown() {
|
|
52996
|
+
if (this.knex) {
|
|
52997
|
+
await this.knex.destroy();
|
|
52998
|
+
this.knex = null;
|
|
52999
|
+
}
|
|
53000
|
+
}
|
|
53001
|
+
async migrateSchema() {
|
|
53002
|
+
const knex = this.getKnex();
|
|
53003
|
+
const exists = await knex.schema.hasTable("schedules");
|
|
53004
|
+
if (!exists) {
|
|
53005
|
+
await knex.schema.createTable("schedules", (table) => {
|
|
53006
|
+
table.string("id", 36).primary();
|
|
53007
|
+
table.string("creator_id", 255).notNullable().index();
|
|
53008
|
+
table.string("creator_context", 255);
|
|
53009
|
+
table.string("creator_name", 255);
|
|
53010
|
+
table.string("timezone", 64).notNullable().defaultTo("UTC");
|
|
53011
|
+
table.string("schedule_expr", 255);
|
|
53012
|
+
table.bigInteger("run_at");
|
|
53013
|
+
table.boolean("is_recurring").notNullable();
|
|
53014
|
+
table.text("original_expression");
|
|
53015
|
+
table.string("workflow", 255);
|
|
53016
|
+
table.text("workflow_inputs");
|
|
53017
|
+
table.text("output_context");
|
|
53018
|
+
table.string("status", 20).notNullable().index();
|
|
53019
|
+
table.bigInteger("created_at").notNullable();
|
|
53020
|
+
table.bigInteger("last_run_at");
|
|
53021
|
+
table.bigInteger("next_run_at");
|
|
53022
|
+
table.integer("run_count").notNullable().defaultTo(0);
|
|
53023
|
+
table.integer("failure_count").notNullable().defaultTo(0);
|
|
53024
|
+
table.text("last_error");
|
|
53025
|
+
table.text("previous_response");
|
|
53026
|
+
table.index(["status", "next_run_at"]);
|
|
53027
|
+
});
|
|
53028
|
+
}
|
|
53029
|
+
const locksExist = await knex.schema.hasTable("scheduler_locks");
|
|
53030
|
+
if (!locksExist) {
|
|
53031
|
+
await knex.schema.createTable("scheduler_locks", (table) => {
|
|
53032
|
+
table.string("lock_id", 255).primary();
|
|
53033
|
+
table.string("node_id", 255).notNullable();
|
|
53034
|
+
table.string("lock_token", 36).notNullable();
|
|
53035
|
+
table.bigInteger("acquired_at").notNullable();
|
|
53036
|
+
table.bigInteger("expires_at").notNullable();
|
|
53037
|
+
});
|
|
53038
|
+
}
|
|
53039
|
+
}
|
|
53040
|
+
getKnex() {
|
|
53041
|
+
if (!this.knex) {
|
|
53042
|
+
throw new Error("[KnexStore] Not initialized. Call initialize() first.");
|
|
53043
|
+
}
|
|
53044
|
+
return this.knex;
|
|
53045
|
+
}
|
|
53046
|
+
// --- CRUD ---
|
|
53047
|
+
async create(schedule) {
|
|
53048
|
+
const knex = this.getKnex();
|
|
53049
|
+
const newSchedule = {
|
|
53050
|
+
...schedule,
|
|
53051
|
+
id: (0, import_uuid2.v4)(),
|
|
53052
|
+
createdAt: Date.now(),
|
|
53053
|
+
runCount: 0,
|
|
53054
|
+
failureCount: 0,
|
|
53055
|
+
status: "active"
|
|
53056
|
+
};
|
|
53057
|
+
await knex("schedules").insert(toInsertRow(newSchedule));
|
|
53058
|
+
logger.info(`[KnexStore] Created schedule ${newSchedule.id} for user ${newSchedule.creatorId}`);
|
|
53059
|
+
return newSchedule;
|
|
53060
|
+
}
|
|
53061
|
+
async importSchedule(schedule) {
|
|
53062
|
+
const knex = this.getKnex();
|
|
53063
|
+
const existing = await knex("schedules").where("id", schedule.id).first();
|
|
53064
|
+
if (existing) return;
|
|
53065
|
+
await knex("schedules").insert(toInsertRow(schedule));
|
|
53066
|
+
}
|
|
53067
|
+
async get(id) {
|
|
53068
|
+
const knex = this.getKnex();
|
|
53069
|
+
const row = await knex("schedules").where("id", id).first();
|
|
53070
|
+
return row ? fromDbRow2(row) : void 0;
|
|
53071
|
+
}
|
|
53072
|
+
async update(id, patch) {
|
|
53073
|
+
const knex = this.getKnex();
|
|
53074
|
+
const existing = await knex("schedules").where("id", id).first();
|
|
53075
|
+
if (!existing) return void 0;
|
|
53076
|
+
const current = fromDbRow2(existing);
|
|
53077
|
+
const updated = { ...current, ...patch, id: current.id };
|
|
53078
|
+
const row = toInsertRow(updated);
|
|
53079
|
+
delete row.id;
|
|
53080
|
+
await knex("schedules").where("id", id).update(row);
|
|
53081
|
+
return updated;
|
|
53082
|
+
}
|
|
53083
|
+
async delete(id) {
|
|
53084
|
+
const knex = this.getKnex();
|
|
53085
|
+
const deleted = await knex("schedules").where("id", id).del();
|
|
53086
|
+
if (deleted > 0) {
|
|
53087
|
+
logger.info(`[KnexStore] Deleted schedule ${id}`);
|
|
53088
|
+
return true;
|
|
53089
|
+
}
|
|
53090
|
+
return false;
|
|
53091
|
+
}
|
|
53092
|
+
// --- Queries ---
|
|
53093
|
+
async getByCreator(creatorId) {
|
|
53094
|
+
const knex = this.getKnex();
|
|
53095
|
+
const rows = await knex("schedules").where("creator_id", creatorId);
|
|
53096
|
+
return rows.map((r) => fromDbRow2(r));
|
|
53097
|
+
}
|
|
53098
|
+
async getActiveSchedules() {
|
|
53099
|
+
const knex = this.getKnex();
|
|
53100
|
+
const rows = await knex("schedules").where("status", "active");
|
|
53101
|
+
return rows.map((r) => fromDbRow2(r));
|
|
53102
|
+
}
|
|
53103
|
+
async getDueSchedules(now) {
|
|
53104
|
+
const ts = now ?? Date.now();
|
|
53105
|
+
const knex = this.getKnex();
|
|
53106
|
+
const bFalse = this.driver === "mssql" ? 0 : false;
|
|
53107
|
+
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
53108
|
+
const rows = await knex("schedules").where("status", "active").andWhere(function() {
|
|
53109
|
+
this.where(function() {
|
|
53110
|
+
this.where("is_recurring", bFalse).whereNotNull("run_at").where("run_at", "<=", ts);
|
|
53111
|
+
}).orWhere(function() {
|
|
53112
|
+
this.where("is_recurring", bTrue).whereNotNull("next_run_at").where("next_run_at", "<=", ts);
|
|
53113
|
+
});
|
|
53114
|
+
});
|
|
53115
|
+
return rows.map((r) => fromDbRow2(r));
|
|
53116
|
+
}
|
|
53117
|
+
async findByWorkflow(creatorId, workflowName) {
|
|
53118
|
+
const knex = this.getKnex();
|
|
53119
|
+
const escaped = workflowName.toLowerCase().replace(/[%_\\]/g, "\\$&");
|
|
53120
|
+
const pattern = `%${escaped}%`;
|
|
53121
|
+
const rows = await knex("schedules").where("creator_id", creatorId).where("status", "active").whereRaw("LOWER(workflow) LIKE ? ESCAPE '\\'", [pattern]);
|
|
53122
|
+
return rows.map((r) => fromDbRow2(r));
|
|
53123
|
+
}
|
|
53124
|
+
async getAll() {
|
|
53125
|
+
const knex = this.getKnex();
|
|
53126
|
+
const rows = await knex("schedules");
|
|
53127
|
+
return rows.map((r) => fromDbRow2(r));
|
|
53128
|
+
}
|
|
53129
|
+
async getStats() {
|
|
53130
|
+
const knex = this.getKnex();
|
|
53131
|
+
const boolTrue = this.driver === "mssql" ? "1" : "true";
|
|
53132
|
+
const boolFalse = this.driver === "mssql" ? "0" : "false";
|
|
53133
|
+
const result = await knex("schedules").select(
|
|
53134
|
+
knex.raw("COUNT(*) as total"),
|
|
53135
|
+
knex.raw("SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active"),
|
|
53136
|
+
knex.raw("SUM(CASE WHEN status = 'paused' THEN 1 ELSE 0 END) as paused"),
|
|
53137
|
+
knex.raw("SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed"),
|
|
53138
|
+
knex.raw("SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed"),
|
|
53139
|
+
knex.raw(`SUM(CASE WHEN is_recurring = ${boolTrue} THEN 1 ELSE 0 END) as recurring`),
|
|
53140
|
+
knex.raw(`SUM(CASE WHEN is_recurring = ${boolFalse} THEN 1 ELSE 0 END) as one_time`)
|
|
53141
|
+
).first();
|
|
53142
|
+
return {
|
|
53143
|
+
total: Number(result.total) || 0,
|
|
53144
|
+
active: Number(result.active) || 0,
|
|
53145
|
+
paused: Number(result.paused) || 0,
|
|
53146
|
+
completed: Number(result.completed) || 0,
|
|
53147
|
+
failed: Number(result.failed) || 0,
|
|
53148
|
+
recurring: Number(result.recurring) || 0,
|
|
53149
|
+
oneTime: Number(result.one_time) || 0
|
|
53150
|
+
};
|
|
53151
|
+
}
|
|
53152
|
+
async validateLimits(creatorId, isRecurring, limits) {
|
|
53153
|
+
const knex = this.getKnex();
|
|
53154
|
+
if (limits.maxGlobal) {
|
|
53155
|
+
const result = await knex("schedules").count("* as cnt").first();
|
|
53156
|
+
if (Number(result?.cnt) >= limits.maxGlobal) {
|
|
53157
|
+
throw new Error(`Global schedule limit reached (${limits.maxGlobal})`);
|
|
53158
|
+
}
|
|
53159
|
+
}
|
|
53160
|
+
if (limits.maxPerUser) {
|
|
53161
|
+
const result = await knex("schedules").where("creator_id", creatorId).count("* as cnt").first();
|
|
53162
|
+
if (Number(result?.cnt) >= limits.maxPerUser) {
|
|
53163
|
+
throw new Error(`You have reached the maximum number of schedules (${limits.maxPerUser})`);
|
|
53164
|
+
}
|
|
53165
|
+
}
|
|
53166
|
+
if (isRecurring && limits.maxRecurringPerUser) {
|
|
53167
|
+
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
53168
|
+
const result = await knex("schedules").where("creator_id", creatorId).where("is_recurring", bTrue).count("* as cnt").first();
|
|
53169
|
+
if (Number(result?.cnt) >= limits.maxRecurringPerUser) {
|
|
53170
|
+
throw new Error(
|
|
53171
|
+
`You have reached the maximum number of recurring schedules (${limits.maxRecurringPerUser})`
|
|
53172
|
+
);
|
|
53173
|
+
}
|
|
53174
|
+
}
|
|
53175
|
+
}
|
|
53176
|
+
// --- HA Distributed Locking (via scheduler_locks table) ---
|
|
53177
|
+
async tryAcquireLock(lockId, nodeId, ttlSeconds) {
|
|
53178
|
+
const knex = this.getKnex();
|
|
53179
|
+
const now = Date.now();
|
|
53180
|
+
const expiresAt = now + ttlSeconds * 1e3;
|
|
53181
|
+
const token = (0, import_uuid2.v4)();
|
|
53182
|
+
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("expires_at", "<", now).update({
|
|
53183
|
+
node_id: nodeId,
|
|
53184
|
+
lock_token: token,
|
|
53185
|
+
acquired_at: now,
|
|
53186
|
+
expires_at: expiresAt
|
|
53187
|
+
});
|
|
53188
|
+
if (updated > 0) return token;
|
|
53189
|
+
try {
|
|
53190
|
+
await knex("scheduler_locks").insert({
|
|
53191
|
+
lock_id: lockId,
|
|
53192
|
+
node_id: nodeId,
|
|
53193
|
+
lock_token: token,
|
|
53194
|
+
acquired_at: now,
|
|
53195
|
+
expires_at: expiresAt
|
|
53196
|
+
});
|
|
53197
|
+
return token;
|
|
53198
|
+
} catch {
|
|
53199
|
+
return null;
|
|
53200
|
+
}
|
|
53201
|
+
}
|
|
53202
|
+
async releaseLock(lockId, lockToken) {
|
|
53203
|
+
const knex = this.getKnex();
|
|
53204
|
+
await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).del();
|
|
53205
|
+
}
|
|
53206
|
+
async renewLock(lockId, lockToken, ttlSeconds) {
|
|
53207
|
+
const knex = this.getKnex();
|
|
53208
|
+
const now = Date.now();
|
|
53209
|
+
const expiresAt = now + ttlSeconds * 1e3;
|
|
53210
|
+
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).update({ acquired_at: now, expires_at: expiresAt });
|
|
53211
|
+
return updated > 0;
|
|
53212
|
+
}
|
|
53213
|
+
async flush() {
|
|
53214
|
+
}
|
|
53215
|
+
};
|
|
53216
|
+
}
|
|
53217
|
+
});
|
|
53218
|
+
|
|
53219
|
+
// src/enterprise/loader.ts
|
|
53220
|
+
var loader_exports = {};
|
|
53221
|
+
__export(loader_exports, {
|
|
53222
|
+
loadEnterprisePolicyEngine: () => loadEnterprisePolicyEngine,
|
|
53223
|
+
loadEnterpriseStoreBackend: () => loadEnterpriseStoreBackend
|
|
53224
|
+
});
|
|
53225
|
+
async function loadEnterprisePolicyEngine(config) {
|
|
53226
|
+
try {
|
|
53227
|
+
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
53228
|
+
const validator = new LicenseValidator2();
|
|
53229
|
+
const license = await validator.loadAndValidate();
|
|
53230
|
+
if (!license || !validator.hasFeature("policy")) {
|
|
53231
|
+
return new DefaultPolicyEngine();
|
|
53232
|
+
}
|
|
53233
|
+
if (validator.isInGracePeriod()) {
|
|
53234
|
+
console.warn(
|
|
53235
|
+
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
53236
|
+
);
|
|
53237
|
+
}
|
|
53238
|
+
const { OpaPolicyEngine: OpaPolicyEngine2 } = await Promise.resolve().then(() => (init_opa_policy_engine(), opa_policy_engine_exports));
|
|
53239
|
+
const engine = new OpaPolicyEngine2(config);
|
|
53240
|
+
await engine.initialize(config);
|
|
53241
|
+
return engine;
|
|
53242
|
+
} catch (err) {
|
|
53243
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
53244
|
+
try {
|
|
53245
|
+
const { logger: logger2 } = (init_logger(), __toCommonJS(logger_exports));
|
|
53246
|
+
logger2.warn(`[PolicyEngine] Enterprise policy init failed, falling back to default: ${msg}`);
|
|
53247
|
+
} catch {
|
|
53248
|
+
}
|
|
53249
|
+
return new DefaultPolicyEngine();
|
|
53250
|
+
}
|
|
53251
|
+
}
|
|
53252
|
+
async function loadEnterpriseStoreBackend(driver, storageConfig, haConfig) {
|
|
53253
|
+
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
53254
|
+
const validator = new LicenseValidator2();
|
|
53255
|
+
const license = await validator.loadAndValidate();
|
|
53256
|
+
if (!license || !validator.hasFeature("scheduler-sql")) {
|
|
53257
|
+
throw new Error(
|
|
53258
|
+
`The ${driver} schedule storage driver requires a Visor Enterprise license with the 'scheduler-sql' feature. Please upgrade or use driver: 'sqlite' (default).`
|
|
53259
|
+
);
|
|
53260
|
+
}
|
|
53261
|
+
if (validator.isInGracePeriod()) {
|
|
53262
|
+
console.warn(
|
|
53263
|
+
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
53264
|
+
);
|
|
53265
|
+
}
|
|
53266
|
+
const { KnexStoreBackend: KnexStoreBackend2 } = await Promise.resolve().then(() => (init_knex_store(), knex_store_exports));
|
|
53267
|
+
return new KnexStoreBackend2(driver, storageConfig, haConfig);
|
|
53268
|
+
}
|
|
53269
|
+
var init_loader = __esm({
|
|
53270
|
+
"src/enterprise/loader.ts"() {
|
|
53271
|
+
"use strict";
|
|
53272
|
+
init_default_engine();
|
|
53273
|
+
}
|
|
53274
|
+
});
|
|
53275
|
+
|
|
52006
53276
|
// src/event-bus/event-bus.ts
|
|
52007
53277
|
var event_bus_exports = {};
|
|
52008
53278
|
__export(event_bus_exports, {
|
|
@@ -52909,8 +54179,8 @@ ${content}
|
|
|
52909
54179
|
* Sleep utility
|
|
52910
54180
|
*/
|
|
52911
54181
|
sleep(ms) {
|
|
52912
|
-
return new Promise((
|
|
52913
|
-
const t = setTimeout(
|
|
54182
|
+
return new Promise((resolve15) => {
|
|
54183
|
+
const t = setTimeout(resolve15, ms);
|
|
52914
54184
|
if (typeof t.unref === "function") {
|
|
52915
54185
|
try {
|
|
52916
54186
|
t.unref();
|
|
@@ -53184,8 +54454,8 @@ ${end}`);
|
|
|
53184
54454
|
async updateGroupedComment(ctx, comments, group, changedIds) {
|
|
53185
54455
|
const existingLock = this.updateLocks.get(group);
|
|
53186
54456
|
let resolveLock;
|
|
53187
|
-
const ourLock = new Promise((
|
|
53188
|
-
resolveLock =
|
|
54457
|
+
const ourLock = new Promise((resolve15) => {
|
|
54458
|
+
resolveLock = resolve15;
|
|
53189
54459
|
});
|
|
53190
54460
|
this.updateLocks.set(group, ourLock);
|
|
53191
54461
|
try {
|
|
@@ -53497,7 +54767,7 @@ ${blocks}
|
|
|
53497
54767
|
* Sleep utility for enforcing delays
|
|
53498
54768
|
*/
|
|
53499
54769
|
sleep(ms) {
|
|
53500
|
-
return new Promise((
|
|
54770
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
53501
54771
|
}
|
|
53502
54772
|
};
|
|
53503
54773
|
}
|
|
@@ -53812,17 +55082,17 @@ function extractMermaidDiagrams(text) {
|
|
|
53812
55082
|
return diagrams;
|
|
53813
55083
|
}
|
|
53814
55084
|
async function renderMermaidToPng(mermaidCode) {
|
|
53815
|
-
const tmpDir =
|
|
53816
|
-
const inputFile =
|
|
55085
|
+
const tmpDir = os2.tmpdir();
|
|
55086
|
+
const inputFile = path28.join(
|
|
53817
55087
|
tmpDir,
|
|
53818
55088
|
`mermaid-${Date.now()}-${Math.random().toString(36).slice(2)}.mmd`
|
|
53819
55089
|
);
|
|
53820
|
-
const outputFile =
|
|
55090
|
+
const outputFile = path28.join(
|
|
53821
55091
|
tmpDir,
|
|
53822
55092
|
`mermaid-${Date.now()}-${Math.random().toString(36).slice(2)}.png`
|
|
53823
55093
|
);
|
|
53824
55094
|
try {
|
|
53825
|
-
|
|
55095
|
+
fs24.writeFileSync(inputFile, mermaidCode, "utf-8");
|
|
53826
55096
|
const chromiumPaths = [
|
|
53827
55097
|
"/usr/bin/chromium",
|
|
53828
55098
|
"/usr/bin/chromium-browser",
|
|
@@ -53831,7 +55101,7 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
53831
55101
|
];
|
|
53832
55102
|
let chromiumPath;
|
|
53833
55103
|
for (const p of chromiumPaths) {
|
|
53834
|
-
if (
|
|
55104
|
+
if (fs24.existsSync(p)) {
|
|
53835
55105
|
chromiumPath = p;
|
|
53836
55106
|
break;
|
|
53837
55107
|
}
|
|
@@ -53840,8 +55110,8 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
53840
55110
|
if (chromiumPath) {
|
|
53841
55111
|
env.PUPPETEER_EXECUTABLE_PATH = chromiumPath;
|
|
53842
55112
|
}
|
|
53843
|
-
const result = await new Promise((
|
|
53844
|
-
const proc = (0,
|
|
55113
|
+
const result = await new Promise((resolve15) => {
|
|
55114
|
+
const proc = (0, import_child_process6.spawn)(
|
|
53845
55115
|
"npx",
|
|
53846
55116
|
[
|
|
53847
55117
|
"--yes",
|
|
@@ -53870,32 +55140,32 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
53870
55140
|
});
|
|
53871
55141
|
proc.on("close", (code) => {
|
|
53872
55142
|
if (code === 0) {
|
|
53873
|
-
|
|
55143
|
+
resolve15({ success: true });
|
|
53874
55144
|
} else {
|
|
53875
|
-
|
|
55145
|
+
resolve15({ success: false, error: stderr || `Exit code ${code}` });
|
|
53876
55146
|
}
|
|
53877
55147
|
});
|
|
53878
55148
|
proc.on("error", (err) => {
|
|
53879
|
-
|
|
55149
|
+
resolve15({ success: false, error: err.message });
|
|
53880
55150
|
});
|
|
53881
55151
|
});
|
|
53882
55152
|
if (!result.success) {
|
|
53883
55153
|
console.warn(`Mermaid rendering failed: ${result.error}`);
|
|
53884
55154
|
return null;
|
|
53885
55155
|
}
|
|
53886
|
-
if (!
|
|
55156
|
+
if (!fs24.existsSync(outputFile)) {
|
|
53887
55157
|
console.warn("Mermaid output file not created");
|
|
53888
55158
|
return null;
|
|
53889
55159
|
}
|
|
53890
|
-
const pngBuffer =
|
|
55160
|
+
const pngBuffer = fs24.readFileSync(outputFile);
|
|
53891
55161
|
return pngBuffer;
|
|
53892
55162
|
} catch (e) {
|
|
53893
55163
|
console.warn(`Mermaid rendering error: ${e instanceof Error ? e.message : String(e)}`);
|
|
53894
55164
|
return null;
|
|
53895
55165
|
} finally {
|
|
53896
55166
|
try {
|
|
53897
|
-
if (
|
|
53898
|
-
if (
|
|
55167
|
+
if (fs24.existsSync(inputFile)) fs24.unlinkSync(inputFile);
|
|
55168
|
+
if (fs24.existsSync(outputFile)) fs24.unlinkSync(outputFile);
|
|
53899
55169
|
} catch {
|
|
53900
55170
|
}
|
|
53901
55171
|
}
|
|
@@ -54000,14 +55270,14 @@ function replaceFileSections(text, sections, replacement = (idx) => `_(See file:
|
|
|
54000
55270
|
function formatSlackText(text) {
|
|
54001
55271
|
return markdownToSlack(text);
|
|
54002
55272
|
}
|
|
54003
|
-
var
|
|
55273
|
+
var import_child_process6, fs24, path28, os2;
|
|
54004
55274
|
var init_markdown = __esm({
|
|
54005
55275
|
"src/slack/markdown.ts"() {
|
|
54006
55276
|
"use strict";
|
|
54007
|
-
|
|
54008
|
-
|
|
54009
|
-
|
|
54010
|
-
|
|
55277
|
+
import_child_process6 = require("child_process");
|
|
55278
|
+
fs24 = __toESM(require("fs"));
|
|
55279
|
+
path28 = __toESM(require("path"));
|
|
55280
|
+
os2 = __toESM(require("os"));
|
|
54011
55281
|
}
|
|
54012
55282
|
});
|
|
54013
55283
|
|
|
@@ -54983,15 +56253,15 @@ function serializeRunState(state) {
|
|
|
54983
56253
|
])
|
|
54984
56254
|
};
|
|
54985
56255
|
}
|
|
54986
|
-
var
|
|
56256
|
+
var path29, fs25, StateMachineExecutionEngine;
|
|
54987
56257
|
var init_state_machine_execution_engine = __esm({
|
|
54988
56258
|
"src/state-machine-execution-engine.ts"() {
|
|
54989
56259
|
"use strict";
|
|
54990
56260
|
init_runner();
|
|
54991
56261
|
init_logger();
|
|
54992
56262
|
init_sandbox_manager();
|
|
54993
|
-
|
|
54994
|
-
|
|
56263
|
+
path29 = __toESM(require("path"));
|
|
56264
|
+
fs25 = __toESM(require("fs"));
|
|
54995
56265
|
StateMachineExecutionEngine = class _StateMachineExecutionEngine {
|
|
54996
56266
|
workingDirectory;
|
|
54997
56267
|
executionContext;
|
|
@@ -55223,8 +56493,8 @@ var init_state_machine_execution_engine = __esm({
|
|
|
55223
56493
|
logger.debug(
|
|
55224
56494
|
`[PolicyEngine] Loading enterprise policy engine (engine=${configWithTagFilter.policy.engine})`
|
|
55225
56495
|
);
|
|
55226
|
-
const { loadEnterprisePolicyEngine } = await
|
|
55227
|
-
context2.policyEngine = await
|
|
56496
|
+
const { loadEnterprisePolicyEngine: loadEnterprisePolicyEngine2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
56497
|
+
context2.policyEngine = await loadEnterprisePolicyEngine2(configWithTagFilter.policy);
|
|
55228
56498
|
logger.debug(
|
|
55229
56499
|
`[PolicyEngine] Initialized: ${context2.policyEngine?.constructor?.name || "unknown"}`
|
|
55230
56500
|
);
|
|
@@ -55376,9 +56646,9 @@ var init_state_machine_execution_engine = __esm({
|
|
|
55376
56646
|
}
|
|
55377
56647
|
const checkId = String(ev?.checkId || "unknown");
|
|
55378
56648
|
const threadKey = ev?.threadKey || (channel && threadTs ? `${channel}:${threadTs}` : "session");
|
|
55379
|
-
const baseDir = process.env.VISOR_SNAPSHOT_DIR ||
|
|
55380
|
-
|
|
55381
|
-
const filePath =
|
|
56649
|
+
const baseDir = process.env.VISOR_SNAPSHOT_DIR || path29.resolve(process.cwd(), ".visor", "snapshots");
|
|
56650
|
+
fs25.mkdirSync(baseDir, { recursive: true });
|
|
56651
|
+
const filePath = path29.join(baseDir, `${threadKey}-${checkId}.json`);
|
|
55382
56652
|
await this.saveSnapshotToFile(filePath);
|
|
55383
56653
|
logger.info(`[Snapshot] Saved run snapshot: ${filePath}`);
|
|
55384
56654
|
try {
|
|
@@ -55519,7 +56789,7 @@ var init_state_machine_execution_engine = __esm({
|
|
|
55519
56789
|
* Does not include secrets. Intended for debugging and future resume support.
|
|
55520
56790
|
*/
|
|
55521
56791
|
async saveSnapshotToFile(filePath) {
|
|
55522
|
-
const
|
|
56792
|
+
const fs26 = await import("fs/promises");
|
|
55523
56793
|
const ctx = this._lastContext;
|
|
55524
56794
|
const runner = this._lastRunner;
|
|
55525
56795
|
if (!ctx || !runner) {
|
|
@@ -55539,14 +56809,14 @@ var init_state_machine_execution_engine = __esm({
|
|
|
55539
56809
|
journal: entries,
|
|
55540
56810
|
requestedChecks: ctx.requestedChecks || []
|
|
55541
56811
|
};
|
|
55542
|
-
await
|
|
56812
|
+
await fs26.writeFile(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
55543
56813
|
}
|
|
55544
56814
|
/**
|
|
55545
56815
|
* Load a snapshot JSON from file and return it. Resume support can build on this.
|
|
55546
56816
|
*/
|
|
55547
56817
|
async loadSnapshotFromFile(filePath) {
|
|
55548
|
-
const
|
|
55549
|
-
const raw = await
|
|
56818
|
+
const fs26 = await import("fs/promises");
|
|
56819
|
+
const raw = await fs26.readFile(filePath, "utf8");
|
|
55550
56820
|
return JSON.parse(raw);
|
|
55551
56821
|
}
|
|
55552
56822
|
/**
|