@probelabs/visor 0.1.174-ee → 0.1.175
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/README.md +3 -2
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/docs/guides/tdd-assistant-workflows.md +519 -0
- package/dist/docs/testing/dsl-reference.md +93 -0
- package/dist/examples/lifecycle-hooks.tests.yaml +62 -0
- package/dist/generated/config-schema.d.ts +28 -7
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/generated/config-schema.json +31 -7
- package/dist/index.js +352 -1864
- package/dist/output/traces/run-2026-03-09T18-49-07-663Z.ndjson +138 -0
- package/dist/output/traces/run-2026-03-09T18-49-46-345Z.ndjson +2296 -0
- package/dist/providers/ai-check-provider.d.ts.map +1 -1
- package/dist/providers/mcp-custom-sse-server.d.ts +4 -0
- package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -1
- package/dist/sdk/a2a-frontend-ORLAU5GK.mjs +1658 -0
- package/dist/sdk/a2a-frontend-ORLAU5GK.mjs.map +1 -0
- package/dist/sdk/{check-provider-registry-53C2ZIXJ.mjs → check-provider-registry-7JPPJHVM.mjs} +3 -3
- package/dist/sdk/{check-provider-registry-UPQNHHFF.mjs → check-provider-registry-O36CQEGD.mjs} +3 -3
- package/dist/sdk/check-provider-registry-QCDV3SI6.mjs +30 -0
- package/dist/sdk/chunk-4FGX4SA6.mjs +516 -0
- package/dist/sdk/chunk-4FGX4SA6.mjs.map +1 -0
- package/dist/sdk/{chunk-2PL2YH3B.mjs → chunk-FZPCP444.mjs} +153 -14
- package/dist/sdk/chunk-FZPCP444.mjs.map +1 -0
- package/dist/sdk/chunk-HNK5ZJ2L.mjs +739 -0
- package/dist/sdk/chunk-HNK5ZJ2L.mjs.map +1 -0
- package/dist/sdk/{chunk-W4KCJM6J.mjs → chunk-MLXGCLZJ.mjs} +29 -8
- package/dist/sdk/chunk-MLXGCLZJ.mjs.map +1 -0
- package/dist/sdk/chunk-QAO73GUX.mjs +1502 -0
- package/dist/sdk/chunk-QAO73GUX.mjs.map +1 -0
- package/dist/sdk/{chunk-GKSSG5IM.mjs → chunk-TAK5HLAR.mjs} +155 -16
- package/dist/sdk/chunk-TAK5HLAR.mjs.map +1 -0
- package/dist/sdk/chunk-YVVOG7RP.mjs +45155 -0
- package/dist/sdk/chunk-YVVOG7RP.mjs.map +1 -0
- package/dist/sdk/{config-BVL3KFMB.mjs → config-4JMBJKWS.mjs} +2 -2
- package/dist/sdk/failure-condition-evaluator-RM5JJS4Q.mjs +18 -0
- package/dist/sdk/github-frontend-O5IAWXL5.mjs +1386 -0
- package/dist/sdk/github-frontend-O5IAWXL5.mjs.map +1 -0
- package/dist/sdk/{host-LRWIKURZ.mjs → host-WTJBWO4T.mjs} +3 -3
- package/dist/sdk/routing-AWOHU2WP.mjs +26 -0
- package/dist/sdk/{schedule-tool-5KDBDCFO.mjs → schedule-tool-DF5WUVYV.mjs} +3 -3
- package/dist/sdk/schedule-tool-L5G2BRIG.mjs +36 -0
- package/dist/sdk/{schedule-tool-UMDRCNO5.mjs → schedule-tool-XVSYLH4Z.mjs} +3 -3
- package/dist/sdk/{schedule-tool-handler-5EPTHBLS.mjs → schedule-tool-handler-CFMFHDUL.mjs} +3 -3
- package/dist/sdk/schedule-tool-handler-CFMFHDUL.mjs.map +1 -0
- package/dist/sdk/{schedule-tool-handler-MUF5V36L.mjs → schedule-tool-handler-JGWA4N3C.mjs} +3 -3
- package/dist/sdk/schedule-tool-handler-JGWA4N3C.mjs.map +1 -0
- package/dist/sdk/schedule-tool-handler-UJ4RFTW2.mjs +40 -0
- package/dist/sdk/schedule-tool-handler-UJ4RFTW2.mjs.map +1 -0
- package/dist/sdk/sdk.d.mts +9 -1
- package/dist/sdk/sdk.d.ts +9 -1
- package/dist/sdk/sdk.js +453 -1667
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +5 -5
- package/dist/sdk/trace-helpers-4ERTVCZG.mjs +29 -0
- package/dist/sdk/trace-helpers-4ERTVCZG.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-EWMZEEES.mjs → workflow-check-provider-ETM452BO.mjs} +3 -3
- package/dist/sdk/workflow-check-provider-ETM452BO.mjs.map +1 -0
- package/dist/sdk/workflow-check-provider-I3XLJP6V.mjs +30 -0
- package/dist/sdk/workflow-check-provider-I3XLJP6V.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-RQUCBAYY.mjs → workflow-check-provider-Z6U7FZAF.mjs} +3 -3
- package/dist/sdk/workflow-check-provider-Z6U7FZAF.mjs.map +1 -0
- package/dist/test-runner/conversation-sugar.d.ts.map +1 -1
- package/dist/test-runner/index.d.ts +19 -0
- package/dist/test-runner/index.d.ts.map +1 -1
- package/dist/test-runner/validator.d.ts.map +1 -1
- package/dist/traces/run-2026-03-09T18-49-07-663Z.ndjson +138 -0
- package/dist/traces/run-2026-03-09T18-49-46-345Z.ndjson +2296 -0
- package/dist/types/config.d.ts +9 -1
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/sdk/chunk-2PL2YH3B.mjs.map +0 -1
- package/dist/sdk/chunk-GKSSG5IM.mjs.map +0 -1
- package/dist/sdk/chunk-W4KCJM6J.mjs.map +0 -1
- package/dist/sdk/knex-store-QCEW4I4R.mjs +0 -527
- package/dist/sdk/knex-store-QCEW4I4R.mjs.map +0 -1
- package/dist/sdk/loader-Q7K76ZIY.mjs +0 -89
- package/dist/sdk/loader-Q7K76ZIY.mjs.map +0 -1
- package/dist/sdk/opa-policy-engine-QCSSIMUF.mjs +0 -655
- package/dist/sdk/opa-policy-engine-QCSSIMUF.mjs.map +0 -1
- package/dist/sdk/validator-XTZJZZJH.mjs +0 -134
- package/dist/sdk/validator-XTZJZZJH.mjs.map +0 -1
- /package/dist/sdk/{check-provider-registry-53C2ZIXJ.mjs.map → check-provider-registry-7JPPJHVM.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-UPQNHHFF.mjs.map → check-provider-registry-O36CQEGD.mjs.map} +0 -0
- /package/dist/sdk/{config-BVL3KFMB.mjs.map → check-provider-registry-QCDV3SI6.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-5KDBDCFO.mjs.map → config-4JMBJKWS.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-UMDRCNO5.mjs.map → failure-condition-evaluator-RM5JJS4Q.mjs.map} +0 -0
- /package/dist/sdk/{host-LRWIKURZ.mjs.map → host-WTJBWO4T.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-5EPTHBLS.mjs.map → routing-AWOHU2WP.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-MUF5V36L.mjs.map → schedule-tool-DF5WUVYV.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-EWMZEEES.mjs.map → schedule-tool-L5G2BRIG.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-RQUCBAYY.mjs.map → schedule-tool-XVSYLH4Z.mjs.map} +0 -0
package/dist/sdk/sdk.js
CHANGED
|
@@ -704,7 +704,7 @@ var require_package = __commonJS({
|
|
|
704
704
|
"package.json"(exports2, module2) {
|
|
705
705
|
module2.exports = {
|
|
706
706
|
name: "@probelabs/visor",
|
|
707
|
-
version: "0.1.
|
|
707
|
+
version: "0.1.175",
|
|
708
708
|
main: "dist/index.js",
|
|
709
709
|
bin: {
|
|
710
710
|
visor: "./dist/index.js"
|
|
@@ -1152,11 +1152,11 @@ function getTracer() {
|
|
|
1152
1152
|
}
|
|
1153
1153
|
async function withActiveSpan(name, attrs, fn) {
|
|
1154
1154
|
const tracer = getTracer();
|
|
1155
|
-
return await new Promise((
|
|
1155
|
+
return await new Promise((resolve15, reject) => {
|
|
1156
1156
|
const callback = async (span) => {
|
|
1157
1157
|
try {
|
|
1158
1158
|
const res = await fn(span);
|
|
1159
|
-
|
|
1159
|
+
resolve15(res);
|
|
1160
1160
|
} catch (err) {
|
|
1161
1161
|
try {
|
|
1162
1162
|
if (err instanceof Error) span.recordException(err);
|
|
@@ -1281,19 +1281,19 @@ function __getOrCreateNdjsonPath() {
|
|
|
1281
1281
|
try {
|
|
1282
1282
|
if (process.env.VISOR_TELEMETRY_SINK && process.env.VISOR_TELEMETRY_SINK !== "file")
|
|
1283
1283
|
return null;
|
|
1284
|
-
const
|
|
1285
|
-
const
|
|
1284
|
+
const path29 = require("path");
|
|
1285
|
+
const fs25 = require("fs");
|
|
1286
1286
|
if (process.env.VISOR_FALLBACK_TRACE_FILE) {
|
|
1287
1287
|
__ndjsonPath = process.env.VISOR_FALLBACK_TRACE_FILE;
|
|
1288
|
-
const dir =
|
|
1289
|
-
if (!
|
|
1288
|
+
const dir = path29.dirname(__ndjsonPath);
|
|
1289
|
+
if (!fs25.existsSync(dir)) fs25.mkdirSync(dir, { recursive: true });
|
|
1290
1290
|
return __ndjsonPath;
|
|
1291
1291
|
}
|
|
1292
|
-
const outDir = process.env.VISOR_TRACE_DIR ||
|
|
1293
|
-
if (!
|
|
1292
|
+
const outDir = process.env.VISOR_TRACE_DIR || path29.join(process.cwd(), "output", "traces");
|
|
1293
|
+
if (!fs25.existsSync(outDir)) fs25.mkdirSync(outDir, { recursive: true });
|
|
1294
1294
|
if (!__ndjsonPath) {
|
|
1295
1295
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1296
|
-
__ndjsonPath =
|
|
1296
|
+
__ndjsonPath = path29.join(outDir, `${ts}.ndjson`);
|
|
1297
1297
|
}
|
|
1298
1298
|
return __ndjsonPath;
|
|
1299
1299
|
} catch {
|
|
@@ -1302,11 +1302,11 @@ function __getOrCreateNdjsonPath() {
|
|
|
1302
1302
|
}
|
|
1303
1303
|
function _appendRunMarker() {
|
|
1304
1304
|
try {
|
|
1305
|
-
const
|
|
1305
|
+
const fs25 = require("fs");
|
|
1306
1306
|
const p = __getOrCreateNdjsonPath();
|
|
1307
1307
|
if (!p) return;
|
|
1308
1308
|
const line = { name: "visor.run", attributes: { started: true } };
|
|
1309
|
-
|
|
1309
|
+
fs25.appendFileSync(p, JSON.stringify(line) + "\n", "utf8");
|
|
1310
1310
|
} catch {
|
|
1311
1311
|
}
|
|
1312
1312
|
}
|
|
@@ -3393,7 +3393,7 @@ var init_failure_condition_evaluator = __esm({
|
|
|
3393
3393
|
*/
|
|
3394
3394
|
evaluateExpression(condition, context2) {
|
|
3395
3395
|
try {
|
|
3396
|
-
const
|
|
3396
|
+
const normalize4 = (expr) => {
|
|
3397
3397
|
const trimmed = expr.trim();
|
|
3398
3398
|
if (!/[\n;]/.test(trimmed)) return trimmed;
|
|
3399
3399
|
const parts = trimmed.split(/[\n;]+/).map((s) => s.trim()).filter((s) => s.length > 0 && !s.startsWith("//"));
|
|
@@ -3551,7 +3551,7 @@ var init_failure_condition_evaluator = __esm({
|
|
|
3551
3551
|
try {
|
|
3552
3552
|
exec2 = this.sandbox.compile(`return (${raw});`);
|
|
3553
3553
|
} catch {
|
|
3554
|
-
const normalizedExpr =
|
|
3554
|
+
const normalizedExpr = normalize4(condition);
|
|
3555
3555
|
exec2 = this.sandbox.compile(`return (${normalizedExpr});`);
|
|
3556
3556
|
}
|
|
3557
3557
|
const result = exec2(scope).run();
|
|
@@ -3934,9 +3934,9 @@ function configureLiquidWithExtensions(liquid) {
|
|
|
3934
3934
|
});
|
|
3935
3935
|
liquid.registerFilter("get", (obj, pathExpr) => {
|
|
3936
3936
|
if (obj == null) return void 0;
|
|
3937
|
-
const
|
|
3938
|
-
if (!
|
|
3939
|
-
const parts =
|
|
3937
|
+
const path29 = typeof pathExpr === "string" ? pathExpr : String(pathExpr || "");
|
|
3938
|
+
if (!path29) return obj;
|
|
3939
|
+
const parts = path29.split(".");
|
|
3940
3940
|
let cur = obj;
|
|
3941
3941
|
for (const p of parts) {
|
|
3942
3942
|
if (cur == null) return void 0;
|
|
@@ -4055,9 +4055,9 @@ function configureLiquidWithExtensions(liquid) {
|
|
|
4055
4055
|
}
|
|
4056
4056
|
}
|
|
4057
4057
|
const defaultRole = typeof rolesCfg.default === "string" && rolesCfg.default.trim() ? rolesCfg.default.trim() : void 0;
|
|
4058
|
-
const getNested = (obj,
|
|
4059
|
-
if (!obj || !
|
|
4060
|
-
const parts =
|
|
4058
|
+
const getNested = (obj, path29) => {
|
|
4059
|
+
if (!obj || !path29) return void 0;
|
|
4060
|
+
const parts = path29.split(".");
|
|
4061
4061
|
let cur = obj;
|
|
4062
4062
|
for (const p of parts) {
|
|
4063
4063
|
if (cur == null) return void 0;
|
|
@@ -6609,8 +6609,8 @@ var init_dependency_gating = __esm({
|
|
|
6609
6609
|
async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
|
|
6610
6610
|
try {
|
|
6611
6611
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
6612
|
-
const
|
|
6613
|
-
const
|
|
6612
|
+
const fs25 = await import("fs/promises");
|
|
6613
|
+
const path29 = await import("path");
|
|
6614
6614
|
const schemaRaw = checkConfig.schema || "plain";
|
|
6615
6615
|
const schema = typeof schemaRaw === "string" ? schemaRaw : "code-review";
|
|
6616
6616
|
let templateContent;
|
|
@@ -6618,24 +6618,24 @@ async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
|
|
|
6618
6618
|
templateContent = String(checkConfig.template.content);
|
|
6619
6619
|
} else if (checkConfig.template && checkConfig.template.file) {
|
|
6620
6620
|
const file = String(checkConfig.template.file);
|
|
6621
|
-
const resolved =
|
|
6622
|
-
templateContent = await
|
|
6621
|
+
const resolved = path29.resolve(process.cwd(), file);
|
|
6622
|
+
templateContent = await fs25.readFile(resolved, "utf-8");
|
|
6623
6623
|
} else if (schema && schema !== "plain") {
|
|
6624
6624
|
const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
|
|
6625
6625
|
if (sanitized) {
|
|
6626
6626
|
const candidatePaths = [
|
|
6627
|
-
|
|
6627
|
+
path29.join(__dirname, "output", sanitized, "template.liquid"),
|
|
6628
6628
|
// bundled: dist/output/
|
|
6629
|
-
|
|
6629
|
+
path29.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
6630
6630
|
// source: output/
|
|
6631
|
-
|
|
6631
|
+
path29.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
6632
6632
|
// fallback: cwd/output/
|
|
6633
|
-
|
|
6633
|
+
path29.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
|
|
6634
6634
|
// fallback: cwd/dist/output/
|
|
6635
6635
|
];
|
|
6636
6636
|
for (const p of candidatePaths) {
|
|
6637
6637
|
try {
|
|
6638
|
-
templateContent = await
|
|
6638
|
+
templateContent = await fs25.readFile(p, "utf-8");
|
|
6639
6639
|
if (templateContent) break;
|
|
6640
6640
|
} catch {
|
|
6641
6641
|
}
|
|
@@ -7040,7 +7040,7 @@ async function processDiffWithOutline(diffContent) {
|
|
|
7040
7040
|
}
|
|
7041
7041
|
try {
|
|
7042
7042
|
const originalProbePath = process.env.PROBE_PATH;
|
|
7043
|
-
const
|
|
7043
|
+
const fs25 = require("fs");
|
|
7044
7044
|
const possiblePaths = [
|
|
7045
7045
|
// Relative to current working directory (most common in production)
|
|
7046
7046
|
path6.join(process.cwd(), "node_modules/@probelabs/probe/bin/probe-binary"),
|
|
@@ -7051,7 +7051,7 @@ async function processDiffWithOutline(diffContent) {
|
|
|
7051
7051
|
];
|
|
7052
7052
|
let probeBinaryPath;
|
|
7053
7053
|
for (const candidatePath of possiblePaths) {
|
|
7054
|
-
if (
|
|
7054
|
+
if (fs25.existsSync(candidatePath)) {
|
|
7055
7055
|
probeBinaryPath = candidatePath;
|
|
7056
7056
|
break;
|
|
7057
7057
|
}
|
|
@@ -7158,7 +7158,7 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
7158
7158
|
if (chromiumPath) {
|
|
7159
7159
|
env.PUPPETEER_EXECUTABLE_PATH = chromiumPath;
|
|
7160
7160
|
}
|
|
7161
|
-
const result = await new Promise((
|
|
7161
|
+
const result = await new Promise((resolve15) => {
|
|
7162
7162
|
const proc = (0, import_child_process.spawn)(
|
|
7163
7163
|
"npx",
|
|
7164
7164
|
[
|
|
@@ -7188,13 +7188,13 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
7188
7188
|
});
|
|
7189
7189
|
proc.on("close", (code) => {
|
|
7190
7190
|
if (code === 0) {
|
|
7191
|
-
|
|
7191
|
+
resolve15({ success: true });
|
|
7192
7192
|
} else {
|
|
7193
|
-
|
|
7193
|
+
resolve15({ success: false, error: stderr || `Exit code ${code}` });
|
|
7194
7194
|
}
|
|
7195
7195
|
});
|
|
7196
7196
|
proc.on("error", (err) => {
|
|
7197
|
-
|
|
7197
|
+
resolve15({ success: false, error: err.message });
|
|
7198
7198
|
});
|
|
7199
7199
|
});
|
|
7200
7200
|
if (!result.success) {
|
|
@@ -8356,8 +8356,8 @@ ${schemaString}`);
|
|
|
8356
8356
|
}
|
|
8357
8357
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8358
8358
|
try {
|
|
8359
|
-
const
|
|
8360
|
-
const
|
|
8359
|
+
const fs25 = require("fs");
|
|
8360
|
+
const path29 = require("path");
|
|
8361
8361
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8362
8362
|
const provider = this.config.provider || "auto";
|
|
8363
8363
|
const model = this.config.model || "default";
|
|
@@ -8471,20 +8471,20 @@ ${"=".repeat(60)}
|
|
|
8471
8471
|
`;
|
|
8472
8472
|
readableVersion += `${"=".repeat(60)}
|
|
8473
8473
|
`;
|
|
8474
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8475
|
-
if (!
|
|
8476
|
-
|
|
8474
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
|
|
8475
|
+
if (!fs25.existsSync(debugArtifactsDir)) {
|
|
8476
|
+
fs25.mkdirSync(debugArtifactsDir, { recursive: true });
|
|
8477
8477
|
}
|
|
8478
|
-
const debugFile =
|
|
8478
|
+
const debugFile = path29.join(
|
|
8479
8479
|
debugArtifactsDir,
|
|
8480
8480
|
`prompt-${_checkName || "unknown"}-${timestamp}.json`
|
|
8481
8481
|
);
|
|
8482
|
-
|
|
8483
|
-
const readableFile =
|
|
8482
|
+
fs25.writeFileSync(debugFile, debugJson, "utf-8");
|
|
8483
|
+
const readableFile = path29.join(
|
|
8484
8484
|
debugArtifactsDir,
|
|
8485
8485
|
`prompt-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8486
8486
|
);
|
|
8487
|
-
|
|
8487
|
+
fs25.writeFileSync(readableFile, readableVersion, "utf-8");
|
|
8488
8488
|
log(`
|
|
8489
8489
|
\u{1F4BE} Full debug info saved to:`);
|
|
8490
8490
|
log(` JSON: ${debugFile}`);
|
|
@@ -8522,8 +8522,8 @@ ${"=".repeat(60)}
|
|
|
8522
8522
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8523
8523
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8524
8524
|
try {
|
|
8525
|
-
const
|
|
8526
|
-
const
|
|
8525
|
+
const fs25 = require("fs");
|
|
8526
|
+
const path29 = require("path");
|
|
8527
8527
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8528
8528
|
const agentAny2 = agent;
|
|
8529
8529
|
let fullHistory = [];
|
|
@@ -8534,8 +8534,8 @@ ${"=".repeat(60)}
|
|
|
8534
8534
|
} else if (agentAny2._messages) {
|
|
8535
8535
|
fullHistory = agentAny2._messages;
|
|
8536
8536
|
}
|
|
8537
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8538
|
-
const sessionBase =
|
|
8537
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
|
|
8538
|
+
const sessionBase = path29.join(
|
|
8539
8539
|
debugArtifactsDir,
|
|
8540
8540
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
8541
8541
|
);
|
|
@@ -8547,7 +8547,7 @@ ${"=".repeat(60)}
|
|
|
8547
8547
|
schema: effectiveSchema,
|
|
8548
8548
|
totalMessages: fullHistory.length
|
|
8549
8549
|
};
|
|
8550
|
-
|
|
8550
|
+
fs25.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
8551
8551
|
let readable = `=============================================================
|
|
8552
8552
|
`;
|
|
8553
8553
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -8574,7 +8574,7 @@ ${"=".repeat(60)}
|
|
|
8574
8574
|
`;
|
|
8575
8575
|
readable += content + "\n";
|
|
8576
8576
|
});
|
|
8577
|
-
|
|
8577
|
+
fs25.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
8578
8578
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
8579
8579
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
8580
8580
|
} catch (error) {
|
|
@@ -8583,11 +8583,11 @@ ${"=".repeat(60)}
|
|
|
8583
8583
|
}
|
|
8584
8584
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8585
8585
|
try {
|
|
8586
|
-
const
|
|
8587
|
-
const
|
|
8586
|
+
const fs25 = require("fs");
|
|
8587
|
+
const path29 = require("path");
|
|
8588
8588
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8589
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8590
|
-
const responseFile =
|
|
8589
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
|
|
8590
|
+
const responseFile = path29.join(
|
|
8591
8591
|
debugArtifactsDir,
|
|
8592
8592
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8593
8593
|
);
|
|
@@ -8620,7 +8620,7 @@ ${"=".repeat(60)}
|
|
|
8620
8620
|
`;
|
|
8621
8621
|
responseContent += `${"=".repeat(60)}
|
|
8622
8622
|
`;
|
|
8623
|
-
|
|
8623
|
+
fs25.writeFileSync(responseFile, responseContent, "utf-8");
|
|
8624
8624
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
8625
8625
|
} catch (error) {
|
|
8626
8626
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -8636,9 +8636,9 @@ ${"=".repeat(60)}
|
|
|
8636
8636
|
await agentAny._telemetryConfig.shutdown();
|
|
8637
8637
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${agentAny._traceFilePath}`);
|
|
8638
8638
|
if (process.env.GITHUB_ACTIONS) {
|
|
8639
|
-
const
|
|
8640
|
-
if (
|
|
8641
|
-
const stats =
|
|
8639
|
+
const fs25 = require("fs");
|
|
8640
|
+
if (fs25.existsSync(agentAny._traceFilePath)) {
|
|
8641
|
+
const stats = fs25.statSync(agentAny._traceFilePath);
|
|
8642
8642
|
console.log(
|
|
8643
8643
|
`::notice title=AI Trace Saved::${agentAny._traceFilePath} (${stats.size} bytes)`
|
|
8644
8644
|
);
|
|
@@ -8851,9 +8851,9 @@ ${schemaString}`);
|
|
|
8851
8851
|
const model = this.config.model || "default";
|
|
8852
8852
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8853
8853
|
try {
|
|
8854
|
-
const
|
|
8855
|
-
const
|
|
8856
|
-
const
|
|
8854
|
+
const fs25 = require("fs");
|
|
8855
|
+
const path29 = require("path");
|
|
8856
|
+
const os2 = require("os");
|
|
8857
8857
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8858
8858
|
const debugData = {
|
|
8859
8859
|
timestamp,
|
|
@@ -8925,19 +8925,19 @@ ${"=".repeat(60)}
|
|
|
8925
8925
|
`;
|
|
8926
8926
|
readableVersion += `${"=".repeat(60)}
|
|
8927
8927
|
`;
|
|
8928
|
-
const tempDir =
|
|
8929
|
-
const promptFile =
|
|
8930
|
-
|
|
8928
|
+
const tempDir = os2.tmpdir();
|
|
8929
|
+
const promptFile = path29.join(tempDir, `visor-prompt-${timestamp}.txt`);
|
|
8930
|
+
fs25.writeFileSync(promptFile, prompt, "utf-8");
|
|
8931
8931
|
log(`
|
|
8932
8932
|
\u{1F4BE} Prompt saved to: ${promptFile}`);
|
|
8933
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8933
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
|
|
8934
8934
|
try {
|
|
8935
|
-
const base =
|
|
8935
|
+
const base = path29.join(
|
|
8936
8936
|
debugArtifactsDir,
|
|
8937
8937
|
`prompt-${_checkName || "unknown"}-${timestamp}`
|
|
8938
8938
|
);
|
|
8939
|
-
|
|
8940
|
-
|
|
8939
|
+
fs25.writeFileSync(base + ".json", debugJson, "utf-8");
|
|
8940
|
+
fs25.writeFileSync(base + ".summary.txt", readableVersion, "utf-8");
|
|
8941
8941
|
log(`
|
|
8942
8942
|
\u{1F4BE} Full debug info saved to directory: ${debugArtifactsDir}`);
|
|
8943
8943
|
} catch {
|
|
@@ -8987,8 +8987,8 @@ $ ${cliCommand}
|
|
|
8987
8987
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8988
8988
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8989
8989
|
try {
|
|
8990
|
-
const
|
|
8991
|
-
const
|
|
8990
|
+
const fs25 = require("fs");
|
|
8991
|
+
const path29 = require("path");
|
|
8992
8992
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8993
8993
|
const agentAny = agent;
|
|
8994
8994
|
let fullHistory = [];
|
|
@@ -8999,8 +8999,8 @@ $ ${cliCommand}
|
|
|
8999
8999
|
} else if (agentAny._messages) {
|
|
9000
9000
|
fullHistory = agentAny._messages;
|
|
9001
9001
|
}
|
|
9002
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
9003
|
-
const sessionBase =
|
|
9002
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
|
|
9003
|
+
const sessionBase = path29.join(
|
|
9004
9004
|
debugArtifactsDir,
|
|
9005
9005
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
9006
9006
|
);
|
|
@@ -9012,7 +9012,7 @@ $ ${cliCommand}
|
|
|
9012
9012
|
schema: effectiveSchema,
|
|
9013
9013
|
totalMessages: fullHistory.length
|
|
9014
9014
|
};
|
|
9015
|
-
|
|
9015
|
+
fs25.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
9016
9016
|
let readable = `=============================================================
|
|
9017
9017
|
`;
|
|
9018
9018
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -9039,7 +9039,7 @@ ${"=".repeat(60)}
|
|
|
9039
9039
|
`;
|
|
9040
9040
|
readable += content + "\n";
|
|
9041
9041
|
});
|
|
9042
|
-
|
|
9042
|
+
fs25.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
9043
9043
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
9044
9044
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
9045
9045
|
} catch (error) {
|
|
@@ -9048,11 +9048,11 @@ ${"=".repeat(60)}
|
|
|
9048
9048
|
}
|
|
9049
9049
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
9050
9050
|
try {
|
|
9051
|
-
const
|
|
9052
|
-
const
|
|
9051
|
+
const fs25 = require("fs");
|
|
9052
|
+
const path29 = require("path");
|
|
9053
9053
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
9054
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
9055
|
-
const responseFile =
|
|
9054
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path29.join(process.cwd(), "debug-artifacts");
|
|
9055
|
+
const responseFile = path29.join(
|
|
9056
9056
|
debugArtifactsDir,
|
|
9057
9057
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
9058
9058
|
);
|
|
@@ -9085,7 +9085,7 @@ ${"=".repeat(60)}
|
|
|
9085
9085
|
`;
|
|
9086
9086
|
responseContent += `${"=".repeat(60)}
|
|
9087
9087
|
`;
|
|
9088
|
-
|
|
9088
|
+
fs25.writeFileSync(responseFile, responseContent, "utf-8");
|
|
9089
9089
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
9090
9090
|
} catch (error) {
|
|
9091
9091
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -9103,9 +9103,9 @@ ${"=".repeat(60)}
|
|
|
9103
9103
|
await telemetry.shutdown();
|
|
9104
9104
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${traceFilePath}`);
|
|
9105
9105
|
if (process.env.GITHUB_ACTIONS) {
|
|
9106
|
-
const
|
|
9107
|
-
if (
|
|
9108
|
-
const stats =
|
|
9106
|
+
const fs25 = require("fs");
|
|
9107
|
+
if (fs25.existsSync(traceFilePath)) {
|
|
9108
|
+
const stats = fs25.statSync(traceFilePath);
|
|
9109
9109
|
console.log(
|
|
9110
9110
|
`::notice title=AI Trace Saved::OpenTelemetry trace file size: ${stats.size} bytes`
|
|
9111
9111
|
);
|
|
@@ -9143,8 +9143,8 @@ ${"=".repeat(60)}
|
|
|
9143
9143
|
* Load schema content from schema files or inline definitions
|
|
9144
9144
|
*/
|
|
9145
9145
|
async loadSchemaContent(schema) {
|
|
9146
|
-
const
|
|
9147
|
-
const
|
|
9146
|
+
const fs25 = require("fs").promises;
|
|
9147
|
+
const path29 = require("path");
|
|
9148
9148
|
if (typeof schema === "object" && schema !== null) {
|
|
9149
9149
|
log("\u{1F4CB} Using inline schema object from configuration");
|
|
9150
9150
|
return JSON.stringify(schema);
|
|
@@ -9157,14 +9157,14 @@ ${"=".repeat(60)}
|
|
|
9157
9157
|
}
|
|
9158
9158
|
} catch {
|
|
9159
9159
|
}
|
|
9160
|
-
if ((schema.startsWith("./") || schema.includes(".json")) && !
|
|
9160
|
+
if ((schema.startsWith("./") || schema.includes(".json")) && !path29.isAbsolute(schema)) {
|
|
9161
9161
|
if (schema.includes("..") || schema.includes("\0")) {
|
|
9162
9162
|
throw new Error("Invalid schema path: path traversal not allowed");
|
|
9163
9163
|
}
|
|
9164
9164
|
try {
|
|
9165
|
-
const schemaPath =
|
|
9165
|
+
const schemaPath = path29.resolve(process.cwd(), schema);
|
|
9166
9166
|
log(`\u{1F4CB} Loading custom schema from file: ${schemaPath}`);
|
|
9167
|
-
const schemaContent = await
|
|
9167
|
+
const schemaContent = await fs25.readFile(schemaPath, "utf-8");
|
|
9168
9168
|
return schemaContent.trim();
|
|
9169
9169
|
} catch (error) {
|
|
9170
9170
|
throw new Error(
|
|
@@ -9178,22 +9178,22 @@ ${"=".repeat(60)}
|
|
|
9178
9178
|
}
|
|
9179
9179
|
const candidatePaths = [
|
|
9180
9180
|
// GitHub Action bundle location
|
|
9181
|
-
|
|
9181
|
+
path29.join(__dirname, "output", sanitizedSchemaName, "schema.json"),
|
|
9182
9182
|
// Historical fallback when src/output was inadvertently bundled as output1/
|
|
9183
|
-
|
|
9183
|
+
path29.join(__dirname, "output1", sanitizedSchemaName, "schema.json"),
|
|
9184
9184
|
// Local dev (repo root)
|
|
9185
|
-
|
|
9185
|
+
path29.join(process.cwd(), "output", sanitizedSchemaName, "schema.json")
|
|
9186
9186
|
];
|
|
9187
9187
|
for (const schemaPath of candidatePaths) {
|
|
9188
9188
|
try {
|
|
9189
|
-
const schemaContent = await
|
|
9189
|
+
const schemaContent = await fs25.readFile(schemaPath, "utf-8");
|
|
9190
9190
|
return schemaContent.trim();
|
|
9191
9191
|
} catch {
|
|
9192
9192
|
}
|
|
9193
9193
|
}
|
|
9194
|
-
const distPath =
|
|
9195
|
-
const distAltPath =
|
|
9196
|
-
const cwdPath =
|
|
9194
|
+
const distPath = path29.join(__dirname, "output", sanitizedSchemaName, "schema.json");
|
|
9195
|
+
const distAltPath = path29.join(__dirname, "output1", sanitizedSchemaName, "schema.json");
|
|
9196
|
+
const cwdPath = path29.join(process.cwd(), "output", sanitizedSchemaName, "schema.json");
|
|
9197
9197
|
throw new Error(
|
|
9198
9198
|
`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.`
|
|
9199
9199
|
);
|
|
@@ -9435,7 +9435,7 @@ ${"=".repeat(60)}
|
|
|
9435
9435
|
* Generate mock response for testing
|
|
9436
9436
|
*/
|
|
9437
9437
|
async generateMockResponse(_prompt, _checkName, _schema) {
|
|
9438
|
-
await new Promise((
|
|
9438
|
+
await new Promise((resolve15) => setTimeout(resolve15, 500));
|
|
9439
9439
|
const name = (_checkName || "").toLowerCase();
|
|
9440
9440
|
if (name.includes("extract-facts")) {
|
|
9441
9441
|
const arr = Array.from({ length: 6 }, (_, i) => ({
|
|
@@ -9796,7 +9796,7 @@ var init_command_executor = __esm({
|
|
|
9796
9796
|
* Execute command with stdin input
|
|
9797
9797
|
*/
|
|
9798
9798
|
executeWithStdin(command, options) {
|
|
9799
|
-
return new Promise((
|
|
9799
|
+
return new Promise((resolve15, reject) => {
|
|
9800
9800
|
const childProcess = (0, import_child_process2.exec)(
|
|
9801
9801
|
command,
|
|
9802
9802
|
{
|
|
@@ -9808,7 +9808,7 @@ var init_command_executor = __esm({
|
|
|
9808
9808
|
if (error && error.killed && (error.code === "ETIMEDOUT" || error.signal === "SIGTERM")) {
|
|
9809
9809
|
reject(new Error(`Command timed out after ${options.timeout || 3e4}ms`));
|
|
9810
9810
|
} else {
|
|
9811
|
-
|
|
9811
|
+
resolve15({
|
|
9812
9812
|
stdout: stdout || "",
|
|
9813
9813
|
stderr: stderr || "",
|
|
9814
9814
|
exitCode: error ? error.code || 1 : 0
|
|
@@ -12724,7 +12724,7 @@ var init_config_schema = __esm({
|
|
|
12724
12724
|
properties: {
|
|
12725
12725
|
type: {
|
|
12726
12726
|
type: "string",
|
|
12727
|
-
enum: ["command", "api", "workflow"],
|
|
12727
|
+
enum: ["command", "api", "workflow", "http_client"],
|
|
12728
12728
|
description: "Tool implementation type (defaults to 'command')"
|
|
12729
12729
|
},
|
|
12730
12730
|
name: {
|
|
@@ -12921,6 +12921,27 @@ var init_config_schema = __esm({
|
|
|
12921
12921
|
type: "number",
|
|
12922
12922
|
description: "Alias for requestTimeoutMs (snake_case)"
|
|
12923
12923
|
},
|
|
12924
|
+
base_url: {
|
|
12925
|
+
type: "string",
|
|
12926
|
+
description: "Base URL for HTTP client tools"
|
|
12927
|
+
},
|
|
12928
|
+
auth: {
|
|
12929
|
+
type: "object",
|
|
12930
|
+
properties: {
|
|
12931
|
+
type: {
|
|
12932
|
+
type: "string"
|
|
12933
|
+
},
|
|
12934
|
+
token: {
|
|
12935
|
+
type: "string"
|
|
12936
|
+
}
|
|
12937
|
+
},
|
|
12938
|
+
required: ["type"],
|
|
12939
|
+
additionalProperties: {},
|
|
12940
|
+
description: "Authentication config for HTTP client tools",
|
|
12941
|
+
patternProperties: {
|
|
12942
|
+
"^x-": {}
|
|
12943
|
+
}
|
|
12944
|
+
},
|
|
12924
12945
|
workflow: {
|
|
12925
12946
|
type: "string",
|
|
12926
12947
|
description: "Workflow ID (registry lookup) or file path (for type: 'workflow')"
|
|
@@ -13460,7 +13481,7 @@ var init_config_schema = __esm({
|
|
|
13460
13481
|
description: "Arguments/inputs for the workflow"
|
|
13461
13482
|
},
|
|
13462
13483
|
overrides: {
|
|
13463
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-
|
|
13484
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090%3E%3E",
|
|
13464
13485
|
description: "Override specific step configurations in the workflow"
|
|
13465
13486
|
},
|
|
13466
13487
|
output_mapping: {
|
|
@@ -13476,7 +13497,7 @@ var init_config_schema = __esm({
|
|
|
13476
13497
|
description: "Config file path - alternative to workflow ID (loads a Visor config file as workflow)"
|
|
13477
13498
|
},
|
|
13478
13499
|
workflow_overrides: {
|
|
13479
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-
|
|
13500
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090%3E%3E",
|
|
13480
13501
|
description: "Alias for overrides - workflow step overrides (backward compatibility)"
|
|
13481
13502
|
},
|
|
13482
13503
|
ref: {
|
|
@@ -14178,7 +14199,7 @@ var init_config_schema = __esm({
|
|
|
14178
14199
|
description: "Custom output name (defaults to workflow name)"
|
|
14179
14200
|
},
|
|
14180
14201
|
overrides: {
|
|
14181
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-
|
|
14202
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090%3E%3E",
|
|
14182
14203
|
description: "Step overrides"
|
|
14183
14204
|
},
|
|
14184
14205
|
output_mapping: {
|
|
@@ -14193,13 +14214,13 @@ var init_config_schema = __esm({
|
|
|
14193
14214
|
"^x-": {}
|
|
14194
14215
|
}
|
|
14195
14216
|
},
|
|
14196
|
-
"Record<string,Partial<interface-src_types_config.ts-14017-28611-src_types_config.ts-0-
|
|
14217
|
+
"Record<string,Partial<interface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090>>": {
|
|
14197
14218
|
type: "object",
|
|
14198
14219
|
additionalProperties: {
|
|
14199
|
-
$ref: "#/definitions/Partial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-
|
|
14220
|
+
$ref: "#/definitions/Partial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090%3E"
|
|
14200
14221
|
}
|
|
14201
14222
|
},
|
|
14202
|
-
"Partial<interface-src_types_config.ts-14017-28611-src_types_config.ts-0-
|
|
14223
|
+
"Partial<interface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090>": {
|
|
14203
14224
|
type: "object",
|
|
14204
14225
|
additionalProperties: false
|
|
14205
14226
|
},
|
|
@@ -18575,17 +18596,17 @@ var init_workflow_check_provider = __esm({
|
|
|
18575
18596
|
* so it can be executed by the state machine as a nested workflow.
|
|
18576
18597
|
*/
|
|
18577
18598
|
async loadWorkflowFromConfigPath(sourcePath, baseDir) {
|
|
18578
|
-
const
|
|
18579
|
-
const
|
|
18599
|
+
const path29 = require("path");
|
|
18600
|
+
const fs25 = require("fs");
|
|
18580
18601
|
const yaml5 = require("js-yaml");
|
|
18581
|
-
const resolved =
|
|
18582
|
-
if (!
|
|
18602
|
+
const resolved = path29.isAbsolute(sourcePath) ? sourcePath : path29.resolve(baseDir, sourcePath);
|
|
18603
|
+
if (!fs25.existsSync(resolved)) {
|
|
18583
18604
|
throw new Error(`Workflow config not found at: ${resolved}`);
|
|
18584
18605
|
}
|
|
18585
|
-
const rawContent =
|
|
18606
|
+
const rawContent = fs25.readFileSync(resolved, "utf8");
|
|
18586
18607
|
const rawData = yaml5.load(rawContent);
|
|
18587
18608
|
if (rawData.imports && Array.isArray(rawData.imports)) {
|
|
18588
|
-
const configDir =
|
|
18609
|
+
const configDir = path29.dirname(resolved);
|
|
18589
18610
|
for (const source of rawData.imports) {
|
|
18590
18611
|
const results = await this.registry.import(source, {
|
|
18591
18612
|
basePath: configDir,
|
|
@@ -18615,8 +18636,8 @@ ${errors}`);
|
|
|
18615
18636
|
if (!steps || Object.keys(steps).length === 0) {
|
|
18616
18637
|
throw new Error(`Config '${resolved}' does not contain any steps to execute as a workflow`);
|
|
18617
18638
|
}
|
|
18618
|
-
const id =
|
|
18619
|
-
const name = loaded.name || `Workflow from ${
|
|
18639
|
+
const id = path29.basename(resolved).replace(/\.(ya?ml)$/i, "");
|
|
18640
|
+
const name = loaded.name || `Workflow from ${path29.basename(resolved)}`;
|
|
18620
18641
|
const workflowDef = {
|
|
18621
18642
|
id,
|
|
18622
18643
|
name,
|
|
@@ -19425,8 +19446,8 @@ async function createStoreBackend(storageConfig, haConfig) {
|
|
|
19425
19446
|
case "mssql": {
|
|
19426
19447
|
try {
|
|
19427
19448
|
const loaderPath = "../../enterprise/loader";
|
|
19428
|
-
const { loadEnterpriseStoreBackend
|
|
19429
|
-
return await
|
|
19449
|
+
const { loadEnterpriseStoreBackend } = await import(loaderPath);
|
|
19450
|
+
return await loadEnterpriseStoreBackend(driver, storageConfig, haConfig);
|
|
19430
19451
|
} catch (err) {
|
|
19431
19452
|
const msg = err instanceof Error ? err.message : String(err);
|
|
19432
19453
|
logger.error(`[StoreFactory] Failed to load enterprise ${driver} backend: ${msg}`);
|
|
@@ -22043,6 +22064,9 @@ var init_schedule_tool_handler = __esm({
|
|
|
22043
22064
|
});
|
|
22044
22065
|
|
|
22045
22066
|
// src/providers/mcp-custom-sse-server.ts
|
|
22067
|
+
function isHttpClientTool(tool) {
|
|
22068
|
+
return Boolean(tool && tool.type === "http_client" && (tool.base_url || tool.url));
|
|
22069
|
+
}
|
|
22046
22070
|
var import_http, import_events, CustomToolsSSEServer;
|
|
22047
22071
|
var init_mcp_custom_sse_server = __esm({
|
|
22048
22072
|
"src/providers/mcp-custom-sse-server.ts"() {
|
|
@@ -22056,6 +22080,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22056
22080
|
init_workflow_registry();
|
|
22057
22081
|
init_schedule_tool();
|
|
22058
22082
|
init_schedule_tool_handler();
|
|
22083
|
+
init_env_resolver();
|
|
22059
22084
|
CustomToolsSSEServer = class _CustomToolsSSEServer {
|
|
22060
22085
|
server = null;
|
|
22061
22086
|
port = 0;
|
|
@@ -22089,10 +22114,12 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22089
22114
|
}
|
|
22090
22115
|
}
|
|
22091
22116
|
for (const [name, tool] of this.tools.entries()) {
|
|
22092
|
-
if (
|
|
22093
|
-
|
|
22117
|
+
if (isWorkflowTool(tool) || isHttpClientTool(tool)) {
|
|
22118
|
+
if (isWorkflowTool(tool)) {
|
|
22119
|
+
workflowToolNames.push(name);
|
|
22120
|
+
}
|
|
22094
22121
|
} else {
|
|
22095
|
-
|
|
22122
|
+
toolsRecord[name] = tool;
|
|
22096
22123
|
}
|
|
22097
22124
|
}
|
|
22098
22125
|
if (workflowToolNames.length > 0 && !workflowContext) {
|
|
@@ -22114,7 +22141,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22114
22141
|
* Returns the actual bound port number
|
|
22115
22142
|
*/
|
|
22116
22143
|
async start() {
|
|
22117
|
-
return new Promise((
|
|
22144
|
+
return new Promise((resolve15, reject) => {
|
|
22118
22145
|
try {
|
|
22119
22146
|
this.server = import_http.default.createServer((req, res) => {
|
|
22120
22147
|
this.handleRequest(req, res).catch((error) => {
|
|
@@ -22148,7 +22175,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22148
22175
|
);
|
|
22149
22176
|
}
|
|
22150
22177
|
this.startKeepalive();
|
|
22151
|
-
|
|
22178
|
+
resolve15(this.port);
|
|
22152
22179
|
});
|
|
22153
22180
|
} catch (error) {
|
|
22154
22181
|
reject(error);
|
|
@@ -22211,7 +22238,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22211
22238
|
logger.debug(
|
|
22212
22239
|
`[CustomToolsSSEServer:${this.sessionId}] Grace period before stop: ${waitMs}ms (activeToolCalls=${this.activeToolCalls})`
|
|
22213
22240
|
);
|
|
22214
|
-
await new Promise((
|
|
22241
|
+
await new Promise((resolve15) => setTimeout(resolve15, waitMs));
|
|
22215
22242
|
}
|
|
22216
22243
|
}
|
|
22217
22244
|
if (this.activeToolCalls > 0) {
|
|
@@ -22220,7 +22247,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22220
22247
|
`[CustomToolsSSEServer:${this.sessionId}] Waiting for ${this.activeToolCalls} active tool call(s) before stop`
|
|
22221
22248
|
);
|
|
22222
22249
|
while (this.activeToolCalls > 0 && Date.now() - startedAt < effectiveDrainTimeoutMs) {
|
|
22223
|
-
await new Promise((
|
|
22250
|
+
await new Promise((resolve15) => setTimeout(resolve15, 250));
|
|
22224
22251
|
}
|
|
22225
22252
|
if (this.activeToolCalls > 0) {
|
|
22226
22253
|
logger.warn(
|
|
@@ -22245,21 +22272,21 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22245
22272
|
}
|
|
22246
22273
|
this.connections.clear();
|
|
22247
22274
|
if (this.server) {
|
|
22248
|
-
await new Promise((
|
|
22275
|
+
await new Promise((resolve15, reject) => {
|
|
22249
22276
|
const timeout = setTimeout(() => {
|
|
22250
22277
|
if (this.debug) {
|
|
22251
22278
|
logger.debug(
|
|
22252
22279
|
`[CustomToolsSSEServer:${this.sessionId}] Force closing server after timeout`
|
|
22253
22280
|
);
|
|
22254
22281
|
}
|
|
22255
|
-
this.server?.close(() =>
|
|
22282
|
+
this.server?.close(() => resolve15());
|
|
22256
22283
|
}, 5e3);
|
|
22257
22284
|
this.server.close((error) => {
|
|
22258
22285
|
clearTimeout(timeout);
|
|
22259
22286
|
if (error) {
|
|
22260
22287
|
reject(error);
|
|
22261
22288
|
} else {
|
|
22262
|
-
|
|
22289
|
+
resolve15();
|
|
22263
22290
|
}
|
|
22264
22291
|
});
|
|
22265
22292
|
});
|
|
@@ -22572,7 +22599,12 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22572
22599
|
description: tool.description || `Execute ${tool.name}`,
|
|
22573
22600
|
inputSchema: normalizeInputSchema(tool.inputSchema)
|
|
22574
22601
|
}));
|
|
22575
|
-
const
|
|
22602
|
+
const httpClientTools = Array.from(this.tools.values()).filter(isHttpClientTool).map((tool) => ({
|
|
22603
|
+
name: tool.name,
|
|
22604
|
+
description: tool.description || `Call ${tool.name} HTTP API`,
|
|
22605
|
+
inputSchema: normalizeInputSchema(tool.inputSchema)
|
|
22606
|
+
}));
|
|
22607
|
+
const allTools = [...regularTools, ...workflowTools, ...httpClientTools];
|
|
22576
22608
|
if (this.debug) {
|
|
22577
22609
|
logger.debug(
|
|
22578
22610
|
`[CustomToolsSSEServer:${this.sessionId}] Listing ${allTools.length} tools: ${allTools.map((t) => t.name).join(", ")}`
|
|
@@ -22696,6 +22728,8 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22696
22728
|
this.workflowContext,
|
|
22697
22729
|
workflowTool.__argsOverrides
|
|
22698
22730
|
);
|
|
22731
|
+
} else if (tool && isHttpClientTool(tool)) {
|
|
22732
|
+
result = await this.executeHttpClientTool(tool, args);
|
|
22699
22733
|
} else {
|
|
22700
22734
|
result = await this.toolExecutor.execute(toolName, args);
|
|
22701
22735
|
}
|
|
@@ -22709,7 +22743,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22709
22743
|
logger.warn(
|
|
22710
22744
|
`[CustomToolsSSEServer:${this.sessionId}] Tool ${toolName} failed (attempt ${attempt + 1}/${retryCount + 1}): ${errorMsg}. Retrying in ${delay}ms`
|
|
22711
22745
|
);
|
|
22712
|
-
await new Promise((
|
|
22746
|
+
await new Promise((resolve15) => setTimeout(resolve15, delay));
|
|
22713
22747
|
attempt++;
|
|
22714
22748
|
}
|
|
22715
22749
|
}
|
|
@@ -22759,6 +22793,83 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22759
22793
|
}
|
|
22760
22794
|
}
|
|
22761
22795
|
}
|
|
22796
|
+
/**
|
|
22797
|
+
* Execute an http_client tool — proxy REST API calls through the configured base URL.
|
|
22798
|
+
*/
|
|
22799
|
+
async executeHttpClientTool(tool, args) {
|
|
22800
|
+
const baseUrl = (tool.base_url || tool.url).replace(/\/+$/, "");
|
|
22801
|
+
const apiPath = args.path || "";
|
|
22802
|
+
const method = (args.method || "GET").toUpperCase();
|
|
22803
|
+
const queryParams = args.query || {};
|
|
22804
|
+
const body = args.body;
|
|
22805
|
+
const toolHeaders = tool.headers || {};
|
|
22806
|
+
const timeout = tool.timeout || 3e4;
|
|
22807
|
+
let url = apiPath.startsWith("http") ? apiPath : `${baseUrl}/${apiPath.replace(/^\/+/, "")}`;
|
|
22808
|
+
if (Object.keys(queryParams).length > 0) {
|
|
22809
|
+
const qs = new URLSearchParams(queryParams).toString();
|
|
22810
|
+
url += `${url.includes("?") ? "&" : "?"}${qs}`;
|
|
22811
|
+
}
|
|
22812
|
+
const resolvedHeaders = {};
|
|
22813
|
+
for (const [key, value] of Object.entries(toolHeaders)) {
|
|
22814
|
+
resolvedHeaders[key] = String(EnvironmentResolver.resolveValue(value));
|
|
22815
|
+
}
|
|
22816
|
+
if (tool.auth) {
|
|
22817
|
+
const authType = tool.auth.type;
|
|
22818
|
+
if (authType === "bearer" && tool.auth.token) {
|
|
22819
|
+
const token = String(EnvironmentResolver.resolveValue(tool.auth.token));
|
|
22820
|
+
resolvedHeaders["Authorization"] = `Bearer ${token}`;
|
|
22821
|
+
}
|
|
22822
|
+
}
|
|
22823
|
+
if (this.debug) {
|
|
22824
|
+
logger.debug(`[CustomToolsSSEServer:${this.sessionId}] HTTP client: ${method} ${url}`);
|
|
22825
|
+
}
|
|
22826
|
+
const controller = new AbortController();
|
|
22827
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
22828
|
+
try {
|
|
22829
|
+
const requestOptions = {
|
|
22830
|
+
method,
|
|
22831
|
+
headers: resolvedHeaders,
|
|
22832
|
+
signal: controller.signal
|
|
22833
|
+
};
|
|
22834
|
+
if (method !== "GET" && body) {
|
|
22835
|
+
requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
|
|
22836
|
+
if (!resolvedHeaders["Content-Type"] && !resolvedHeaders["content-type"]) {
|
|
22837
|
+
resolvedHeaders["Content-Type"] = "application/json";
|
|
22838
|
+
}
|
|
22839
|
+
}
|
|
22840
|
+
const response = await fetch(url, requestOptions);
|
|
22841
|
+
clearTimeout(timeoutId);
|
|
22842
|
+
if (!response.ok) {
|
|
22843
|
+
let errorBody = "";
|
|
22844
|
+
try {
|
|
22845
|
+
errorBody = await response.text();
|
|
22846
|
+
} catch {
|
|
22847
|
+
}
|
|
22848
|
+
throw new Error(
|
|
22849
|
+
`HTTP ${response.status}: ${response.statusText}${errorBody ? ` - ${errorBody.substring(0, 500)}` : ""}`
|
|
22850
|
+
);
|
|
22851
|
+
}
|
|
22852
|
+
const contentType = response.headers.get("content-type");
|
|
22853
|
+
if (contentType && contentType.includes("application/json")) {
|
|
22854
|
+
return await response.json();
|
|
22855
|
+
}
|
|
22856
|
+
const text = await response.text();
|
|
22857
|
+
if (text.trim().startsWith("{") || text.trim().startsWith("[")) {
|
|
22858
|
+
try {
|
|
22859
|
+
return JSON.parse(text);
|
|
22860
|
+
} catch {
|
|
22861
|
+
return text;
|
|
22862
|
+
}
|
|
22863
|
+
}
|
|
22864
|
+
return text;
|
|
22865
|
+
} catch (error) {
|
|
22866
|
+
clearTimeout(timeoutId);
|
|
22867
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
22868
|
+
throw new Error(`HTTP client request timed out after ${timeout}ms`);
|
|
22869
|
+
}
|
|
22870
|
+
throw error;
|
|
22871
|
+
}
|
|
22872
|
+
}
|
|
22762
22873
|
/**
|
|
22763
22874
|
* Convert a type: 'workflow' tool definition into a WorkflowToolDefinition marker.
|
|
22764
22875
|
*
|
|
@@ -23101,9 +23212,9 @@ var init_ai_check_provider = __esm({
|
|
|
23101
23212
|
} else {
|
|
23102
23213
|
resolvedPath = import_path8.default.resolve(process.cwd(), str);
|
|
23103
23214
|
}
|
|
23104
|
-
const
|
|
23215
|
+
const fs25 = require("fs").promises;
|
|
23105
23216
|
try {
|
|
23106
|
-
const stat2 = await
|
|
23217
|
+
const stat2 = await fs25.stat(resolvedPath);
|
|
23107
23218
|
return stat2.isFile();
|
|
23108
23219
|
} catch {
|
|
23109
23220
|
return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);
|
|
@@ -23842,6 +23953,7 @@ ${preview}`);
|
|
|
23842
23953
|
}
|
|
23843
23954
|
const workflowEntriesFromMcp = [];
|
|
23844
23955
|
const toolEntriesFromMcp = [];
|
|
23956
|
+
const httpClientEntriesFromMcp = [];
|
|
23845
23957
|
const mcpEntriesToRemove = [];
|
|
23846
23958
|
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
|
23847
23959
|
const cfg = serverConfig;
|
|
@@ -23855,6 +23967,12 @@ ${preview}`);
|
|
|
23855
23967
|
logger.debug(
|
|
23856
23968
|
`[AICheckProvider] Extracted workflow tool '${serverName}' (workflow=${cfg.workflow}) from ai_mcp_servers`
|
|
23857
23969
|
);
|
|
23970
|
+
} else if (cfg.type === "http_client" && (cfg.base_url || cfg.url)) {
|
|
23971
|
+
httpClientEntriesFromMcp.push({ name: serverName, config: cfg });
|
|
23972
|
+
mcpEntriesToRemove.push(serverName);
|
|
23973
|
+
logger.debug(
|
|
23974
|
+
`[AICheckProvider] Extracted http_client tool '${serverName}' (base_url=${cfg.base_url || cfg.url}) from ai_mcp_servers`
|
|
23975
|
+
);
|
|
23858
23976
|
} else if (cfg.tool && typeof cfg.tool === "string") {
|
|
23859
23977
|
toolEntriesFromMcp.push(cfg.tool);
|
|
23860
23978
|
mcpEntriesToRemove.push(serverName);
|
|
@@ -23907,7 +24025,7 @@ ${preview}`);
|
|
|
23907
24025
|
logger.debug(`[AICheckProvider] Schedule tool requested (${contextInfo})`);
|
|
23908
24026
|
}
|
|
23909
24027
|
const scheduleToolEnabled = scheduleToolRequested || config.ai?.enable_scheduler === true && !config.ai?.disableTools;
|
|
23910
|
-
if ((customToolsToLoad.length > 0 || scheduleToolEnabled) && (customToolsServerName || scheduleToolEnabled) && !config.ai?.disableTools) {
|
|
24028
|
+
if ((customToolsToLoad.length > 0 || scheduleToolEnabled || httpClientEntriesFromMcp.length > 0) && (customToolsServerName || scheduleToolEnabled || httpClientEntriesFromMcp.length > 0) && !config.ai?.disableTools) {
|
|
23911
24029
|
if (!customToolsServerName) {
|
|
23912
24030
|
customToolsServerName = "__tools__";
|
|
23913
24031
|
}
|
|
@@ -23939,6 +24057,48 @@ ${preview}`);
|
|
|
23939
24057
|
customTools.set(scheduleTool.name, scheduleTool);
|
|
23940
24058
|
logger.debug(`[AICheckProvider] Added built-in schedule tool`);
|
|
23941
24059
|
}
|
|
24060
|
+
for (const entry of httpClientEntriesFromMcp) {
|
|
24061
|
+
const httpTool = {
|
|
24062
|
+
name: entry.name,
|
|
24063
|
+
type: "http_client",
|
|
24064
|
+
description: entry.config.description || `Call ${entry.name} HTTP API (base: ${entry.config.base_url || entry.config.url})`,
|
|
24065
|
+
base_url: entry.config.base_url || entry.config.url,
|
|
24066
|
+
auth: entry.config.auth,
|
|
24067
|
+
headers: entry.config.headers,
|
|
24068
|
+
timeout: entry.config.timeout || 3e4,
|
|
24069
|
+
inputSchema: {
|
|
24070
|
+
type: "object",
|
|
24071
|
+
properties: {
|
|
24072
|
+
path: {
|
|
24073
|
+
type: "string",
|
|
24074
|
+
description: "API path (e.g. /jobs, /candidates/{id})"
|
|
24075
|
+
},
|
|
24076
|
+
method: {
|
|
24077
|
+
type: "string",
|
|
24078
|
+
description: "HTTP method (default: GET)",
|
|
24079
|
+
enum: ["GET", "POST", "PUT", "PATCH", "DELETE"]
|
|
24080
|
+
},
|
|
24081
|
+
query: {
|
|
24082
|
+
type: "object",
|
|
24083
|
+
description: "Query string parameters",
|
|
24084
|
+
additionalProperties: { type: "string" }
|
|
24085
|
+
},
|
|
24086
|
+
body: {
|
|
24087
|
+
type: "object",
|
|
24088
|
+
description: "Request body for POST/PUT/PATCH"
|
|
24089
|
+
}
|
|
24090
|
+
},
|
|
24091
|
+
required: ["path"]
|
|
24092
|
+
}
|
|
24093
|
+
};
|
|
24094
|
+
customTools.set(entry.name, httpTool);
|
|
24095
|
+
logger.debug(
|
|
24096
|
+
`[AICheckProvider] Added http_client tool '${entry.name}' (base_url=${httpTool.base_url})`
|
|
24097
|
+
);
|
|
24098
|
+
}
|
|
24099
|
+
if (httpClientEntriesFromMcp.length > 0 && !customToolsServerName) {
|
|
24100
|
+
customToolsServerName = "__tools__";
|
|
24101
|
+
}
|
|
23942
24102
|
if (customTools.size > 0) {
|
|
23943
24103
|
const sessionId = config.checkName || `ai-check-${Date.now()}`;
|
|
23944
24104
|
const debug = aiConfig.debug || process.env.VISOR_DEBUG === "true";
|
|
@@ -29205,14 +29365,14 @@ var require_util = __commonJS({
|
|
|
29205
29365
|
}
|
|
29206
29366
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
29207
29367
|
let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`;
|
|
29208
|
-
let
|
|
29368
|
+
let path29 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
29209
29369
|
if (origin.endsWith("/")) {
|
|
29210
29370
|
origin = origin.substring(0, origin.length - 1);
|
|
29211
29371
|
}
|
|
29212
|
-
if (
|
|
29213
|
-
|
|
29372
|
+
if (path29 && !path29.startsWith("/")) {
|
|
29373
|
+
path29 = `/${path29}`;
|
|
29214
29374
|
}
|
|
29215
|
-
url = new URL(origin +
|
|
29375
|
+
url = new URL(origin + path29);
|
|
29216
29376
|
}
|
|
29217
29377
|
return url;
|
|
29218
29378
|
}
|
|
@@ -30826,20 +30986,20 @@ var require_parseParams = __commonJS({
|
|
|
30826
30986
|
var require_basename = __commonJS({
|
|
30827
30987
|
"node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) {
|
|
30828
30988
|
"use strict";
|
|
30829
|
-
module2.exports = function basename4(
|
|
30830
|
-
if (typeof
|
|
30989
|
+
module2.exports = function basename4(path29) {
|
|
30990
|
+
if (typeof path29 !== "string") {
|
|
30831
30991
|
return "";
|
|
30832
30992
|
}
|
|
30833
|
-
for (var i =
|
|
30834
|
-
switch (
|
|
30993
|
+
for (var i = path29.length - 1; i >= 0; --i) {
|
|
30994
|
+
switch (path29.charCodeAt(i)) {
|
|
30835
30995
|
case 47:
|
|
30836
30996
|
// '/'
|
|
30837
30997
|
case 92:
|
|
30838
|
-
|
|
30839
|
-
return
|
|
30998
|
+
path29 = path29.slice(i + 1);
|
|
30999
|
+
return path29 === ".." || path29 === "." ? "" : path29;
|
|
30840
31000
|
}
|
|
30841
31001
|
}
|
|
30842
|
-
return
|
|
31002
|
+
return path29 === ".." || path29 === "." ? "" : path29;
|
|
30843
31003
|
};
|
|
30844
31004
|
}
|
|
30845
31005
|
});
|
|
@@ -31843,11 +32003,11 @@ var require_util2 = __commonJS({
|
|
|
31843
32003
|
var assert = require("assert");
|
|
31844
32004
|
var { isUint8Array } = require("util/types");
|
|
31845
32005
|
var supportedHashes = [];
|
|
31846
|
-
var
|
|
32006
|
+
var crypto7;
|
|
31847
32007
|
try {
|
|
31848
|
-
|
|
32008
|
+
crypto7 = require("crypto");
|
|
31849
32009
|
const possibleRelevantHashes = ["sha256", "sha384", "sha512"];
|
|
31850
|
-
supportedHashes =
|
|
32010
|
+
supportedHashes = crypto7.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
|
|
31851
32011
|
} catch {
|
|
31852
32012
|
}
|
|
31853
32013
|
function responseURL(response) {
|
|
@@ -32124,7 +32284,7 @@ var require_util2 = __commonJS({
|
|
|
32124
32284
|
}
|
|
32125
32285
|
}
|
|
32126
32286
|
function bytesMatch(bytes, metadataList) {
|
|
32127
|
-
if (
|
|
32287
|
+
if (crypto7 === void 0) {
|
|
32128
32288
|
return true;
|
|
32129
32289
|
}
|
|
32130
32290
|
const parsedMetadata = parseMetadata(metadataList);
|
|
@@ -32139,7 +32299,7 @@ var require_util2 = __commonJS({
|
|
|
32139
32299
|
for (const item of metadata) {
|
|
32140
32300
|
const algorithm = item.algo;
|
|
32141
32301
|
const expectedValue = item.hash;
|
|
32142
|
-
let actualValue =
|
|
32302
|
+
let actualValue = crypto7.createHash(algorithm).update(bytes).digest("base64");
|
|
32143
32303
|
if (actualValue[actualValue.length - 1] === "=") {
|
|
32144
32304
|
if (actualValue[actualValue.length - 2] === "=") {
|
|
32145
32305
|
actualValue = actualValue.slice(0, -2);
|
|
@@ -32232,8 +32392,8 @@ var require_util2 = __commonJS({
|
|
|
32232
32392
|
function createDeferredPromise() {
|
|
32233
32393
|
let res;
|
|
32234
32394
|
let rej;
|
|
32235
|
-
const promise = new Promise((
|
|
32236
|
-
res =
|
|
32395
|
+
const promise = new Promise((resolve15, reject) => {
|
|
32396
|
+
res = resolve15;
|
|
32237
32397
|
rej = reject;
|
|
32238
32398
|
});
|
|
32239
32399
|
return { promise, resolve: res, reject: rej };
|
|
@@ -33486,8 +33646,8 @@ var require_body = __commonJS({
|
|
|
33486
33646
|
var { parseMIMEType, serializeAMimeType } = require_dataURL();
|
|
33487
33647
|
var random;
|
|
33488
33648
|
try {
|
|
33489
|
-
const
|
|
33490
|
-
random = (max) =>
|
|
33649
|
+
const crypto7 = require("crypto");
|
|
33650
|
+
random = (max) => crypto7.randomInt(0, max);
|
|
33491
33651
|
} catch {
|
|
33492
33652
|
random = (max) => Math.floor(Math.random(max));
|
|
33493
33653
|
}
|
|
@@ -33738,8 +33898,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r
|
|
|
33738
33898
|
});
|
|
33739
33899
|
}
|
|
33740
33900
|
});
|
|
33741
|
-
const busboyResolve = new Promise((
|
|
33742
|
-
busboy.on("finish",
|
|
33901
|
+
const busboyResolve = new Promise((resolve15, reject) => {
|
|
33902
|
+
busboy.on("finish", resolve15);
|
|
33743
33903
|
busboy.on("error", (err) => reject(new TypeError(err)));
|
|
33744
33904
|
});
|
|
33745
33905
|
if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk);
|
|
@@ -33870,7 +34030,7 @@ var require_request = __commonJS({
|
|
|
33870
34030
|
}
|
|
33871
34031
|
var Request2 = class _Request {
|
|
33872
34032
|
constructor(origin, {
|
|
33873
|
-
path:
|
|
34033
|
+
path: path29,
|
|
33874
34034
|
method,
|
|
33875
34035
|
body,
|
|
33876
34036
|
headers,
|
|
@@ -33884,11 +34044,11 @@ var require_request = __commonJS({
|
|
|
33884
34044
|
throwOnError,
|
|
33885
34045
|
expectContinue
|
|
33886
34046
|
}, handler) {
|
|
33887
|
-
if (typeof
|
|
34047
|
+
if (typeof path29 !== "string") {
|
|
33888
34048
|
throw new InvalidArgumentError("path must be a string");
|
|
33889
|
-
} else if (
|
|
34049
|
+
} else if (path29[0] !== "/" && !(path29.startsWith("http://") || path29.startsWith("https://")) && method !== "CONNECT") {
|
|
33890
34050
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
33891
|
-
} else if (invalidPathRegex.exec(
|
|
34051
|
+
} else if (invalidPathRegex.exec(path29) !== null) {
|
|
33892
34052
|
throw new InvalidArgumentError("invalid request path");
|
|
33893
34053
|
}
|
|
33894
34054
|
if (typeof method !== "string") {
|
|
@@ -33951,7 +34111,7 @@ var require_request = __commonJS({
|
|
|
33951
34111
|
this.completed = false;
|
|
33952
34112
|
this.aborted = false;
|
|
33953
34113
|
this.upgrade = upgrade || null;
|
|
33954
|
-
this.path = query ? util.buildURL(
|
|
34114
|
+
this.path = query ? util.buildURL(path29, query) : path29;
|
|
33955
34115
|
this.origin = origin;
|
|
33956
34116
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
33957
34117
|
this.blocking = blocking == null ? false : blocking;
|
|
@@ -34273,9 +34433,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
34273
34433
|
}
|
|
34274
34434
|
close(callback) {
|
|
34275
34435
|
if (callback === void 0) {
|
|
34276
|
-
return new Promise((
|
|
34436
|
+
return new Promise((resolve15, reject) => {
|
|
34277
34437
|
this.close((err, data) => {
|
|
34278
|
-
return err ? reject(err) :
|
|
34438
|
+
return err ? reject(err) : resolve15(data);
|
|
34279
34439
|
});
|
|
34280
34440
|
});
|
|
34281
34441
|
}
|
|
@@ -34313,12 +34473,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
34313
34473
|
err = null;
|
|
34314
34474
|
}
|
|
34315
34475
|
if (callback === void 0) {
|
|
34316
|
-
return new Promise((
|
|
34476
|
+
return new Promise((resolve15, reject) => {
|
|
34317
34477
|
this.destroy(err, (err2, data) => {
|
|
34318
34478
|
return err2 ? (
|
|
34319
34479
|
/* istanbul ignore next: should never error */
|
|
34320
34480
|
reject(err2)
|
|
34321
|
-
) :
|
|
34481
|
+
) : resolve15(data);
|
|
34322
34482
|
});
|
|
34323
34483
|
});
|
|
34324
34484
|
}
|
|
@@ -34959,9 +35119,9 @@ var require_RedirectHandler = __commonJS({
|
|
|
34959
35119
|
return this.handler.onHeaders(statusCode, headers, resume, statusText);
|
|
34960
35120
|
}
|
|
34961
35121
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
34962
|
-
const
|
|
35122
|
+
const path29 = search ? `${pathname}${search}` : pathname;
|
|
34963
35123
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
34964
|
-
this.opts.path =
|
|
35124
|
+
this.opts.path = path29;
|
|
34965
35125
|
this.opts.origin = origin;
|
|
34966
35126
|
this.opts.maxRedirections = 0;
|
|
34967
35127
|
this.opts.query = null;
|
|
@@ -35380,16 +35540,16 @@ var require_client = __commonJS({
|
|
|
35380
35540
|
return this[kNeedDrain] < 2;
|
|
35381
35541
|
}
|
|
35382
35542
|
async [kClose]() {
|
|
35383
|
-
return new Promise((
|
|
35543
|
+
return new Promise((resolve15) => {
|
|
35384
35544
|
if (!this[kSize]) {
|
|
35385
|
-
|
|
35545
|
+
resolve15(null);
|
|
35386
35546
|
} else {
|
|
35387
|
-
this[kClosedResolve] =
|
|
35547
|
+
this[kClosedResolve] = resolve15;
|
|
35388
35548
|
}
|
|
35389
35549
|
});
|
|
35390
35550
|
}
|
|
35391
35551
|
async [kDestroy](err) {
|
|
35392
|
-
return new Promise((
|
|
35552
|
+
return new Promise((resolve15) => {
|
|
35393
35553
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
35394
35554
|
for (let i = 0; i < requests.length; i++) {
|
|
35395
35555
|
const request = requests[i];
|
|
@@ -35400,7 +35560,7 @@ var require_client = __commonJS({
|
|
|
35400
35560
|
this[kClosedResolve]();
|
|
35401
35561
|
this[kClosedResolve] = null;
|
|
35402
35562
|
}
|
|
35403
|
-
|
|
35563
|
+
resolve15();
|
|
35404
35564
|
};
|
|
35405
35565
|
if (this[kHTTP2Session] != null) {
|
|
35406
35566
|
util.destroy(this[kHTTP2Session], err);
|
|
@@ -35980,7 +36140,7 @@ var require_client = __commonJS({
|
|
|
35980
36140
|
});
|
|
35981
36141
|
}
|
|
35982
36142
|
try {
|
|
35983
|
-
const socket = await new Promise((
|
|
36143
|
+
const socket = await new Promise((resolve15, reject) => {
|
|
35984
36144
|
client[kConnector]({
|
|
35985
36145
|
host,
|
|
35986
36146
|
hostname,
|
|
@@ -35992,7 +36152,7 @@ var require_client = __commonJS({
|
|
|
35992
36152
|
if (err) {
|
|
35993
36153
|
reject(err);
|
|
35994
36154
|
} else {
|
|
35995
|
-
|
|
36155
|
+
resolve15(socket2);
|
|
35996
36156
|
}
|
|
35997
36157
|
});
|
|
35998
36158
|
});
|
|
@@ -36203,7 +36363,7 @@ var require_client = __commonJS({
|
|
|
36203
36363
|
writeH2(client, client[kHTTP2Session], request);
|
|
36204
36364
|
return;
|
|
36205
36365
|
}
|
|
36206
|
-
const { body, method, path:
|
|
36366
|
+
const { body, method, path: path29, host, upgrade, headers, blocking, reset } = request;
|
|
36207
36367
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
36208
36368
|
if (body && typeof body.read === "function") {
|
|
36209
36369
|
body.read(0);
|
|
@@ -36253,7 +36413,7 @@ var require_client = __commonJS({
|
|
|
36253
36413
|
if (blocking) {
|
|
36254
36414
|
socket[kBlocking] = true;
|
|
36255
36415
|
}
|
|
36256
|
-
let header = `${method} ${
|
|
36416
|
+
let header = `${method} ${path29} HTTP/1.1\r
|
|
36257
36417
|
`;
|
|
36258
36418
|
if (typeof host === "string") {
|
|
36259
36419
|
header += `host: ${host}\r
|
|
@@ -36316,7 +36476,7 @@ upgrade: ${upgrade}\r
|
|
|
36316
36476
|
return true;
|
|
36317
36477
|
}
|
|
36318
36478
|
function writeH2(client, session, request) {
|
|
36319
|
-
const { body, method, path:
|
|
36479
|
+
const { body, method, path: path29, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
|
|
36320
36480
|
let headers;
|
|
36321
36481
|
if (typeof reqHeaders === "string") headers = Request2[kHTTP2CopyHeaders](reqHeaders.trim());
|
|
36322
36482
|
else headers = reqHeaders;
|
|
@@ -36359,7 +36519,7 @@ upgrade: ${upgrade}\r
|
|
|
36359
36519
|
});
|
|
36360
36520
|
return true;
|
|
36361
36521
|
}
|
|
36362
|
-
headers[HTTP2_HEADER_PATH] =
|
|
36522
|
+
headers[HTTP2_HEADER_PATH] = path29;
|
|
36363
36523
|
headers[HTTP2_HEADER_SCHEME] = "https";
|
|
36364
36524
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
36365
36525
|
if (body && typeof body.read === "function") {
|
|
@@ -36616,12 +36776,12 @@ upgrade: ${upgrade}\r
|
|
|
36616
36776
|
cb();
|
|
36617
36777
|
}
|
|
36618
36778
|
}
|
|
36619
|
-
const waitForDrain = () => new Promise((
|
|
36779
|
+
const waitForDrain = () => new Promise((resolve15, reject) => {
|
|
36620
36780
|
assert(callback === null);
|
|
36621
36781
|
if (socket[kError]) {
|
|
36622
36782
|
reject(socket[kError]);
|
|
36623
36783
|
} else {
|
|
36624
|
-
callback =
|
|
36784
|
+
callback = resolve15;
|
|
36625
36785
|
}
|
|
36626
36786
|
});
|
|
36627
36787
|
if (client[kHTTPConnVersion] === "h2") {
|
|
@@ -36967,8 +37127,8 @@ var require_pool_base = __commonJS({
|
|
|
36967
37127
|
if (this[kQueue].isEmpty()) {
|
|
36968
37128
|
return Promise.all(this[kClients].map((c) => c.close()));
|
|
36969
37129
|
} else {
|
|
36970
|
-
return new Promise((
|
|
36971
|
-
this[kClosedResolve] =
|
|
37130
|
+
return new Promise((resolve15) => {
|
|
37131
|
+
this[kClosedResolve] = resolve15;
|
|
36972
37132
|
});
|
|
36973
37133
|
}
|
|
36974
37134
|
}
|
|
@@ -37546,7 +37706,7 @@ var require_readable = __commonJS({
|
|
|
37546
37706
|
if (this.closed) {
|
|
37547
37707
|
return Promise.resolve(null);
|
|
37548
37708
|
}
|
|
37549
|
-
return new Promise((
|
|
37709
|
+
return new Promise((resolve15, reject) => {
|
|
37550
37710
|
const signalListenerCleanup = signal ? util.addAbortListener(signal, () => {
|
|
37551
37711
|
this.destroy();
|
|
37552
37712
|
}) : noop;
|
|
@@ -37555,7 +37715,7 @@ var require_readable = __commonJS({
|
|
|
37555
37715
|
if (signal && signal.aborted) {
|
|
37556
37716
|
reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" }));
|
|
37557
37717
|
} else {
|
|
37558
|
-
|
|
37718
|
+
resolve15(null);
|
|
37559
37719
|
}
|
|
37560
37720
|
}).on("error", noop).on("data", function(chunk) {
|
|
37561
37721
|
limit -= chunk.length;
|
|
@@ -37577,11 +37737,11 @@ var require_readable = __commonJS({
|
|
|
37577
37737
|
throw new TypeError("unusable");
|
|
37578
37738
|
}
|
|
37579
37739
|
assert(!stream[kConsume]);
|
|
37580
|
-
return new Promise((
|
|
37740
|
+
return new Promise((resolve15, reject) => {
|
|
37581
37741
|
stream[kConsume] = {
|
|
37582
37742
|
type,
|
|
37583
37743
|
stream,
|
|
37584
|
-
resolve:
|
|
37744
|
+
resolve: resolve15,
|
|
37585
37745
|
reject,
|
|
37586
37746
|
length: 0,
|
|
37587
37747
|
body: []
|
|
@@ -37616,12 +37776,12 @@ var require_readable = __commonJS({
|
|
|
37616
37776
|
}
|
|
37617
37777
|
}
|
|
37618
37778
|
function consumeEnd(consume2) {
|
|
37619
|
-
const { type, body, resolve:
|
|
37779
|
+
const { type, body, resolve: resolve15, stream, length } = consume2;
|
|
37620
37780
|
try {
|
|
37621
37781
|
if (type === "text") {
|
|
37622
|
-
|
|
37782
|
+
resolve15(toUSVString(Buffer.concat(body)));
|
|
37623
37783
|
} else if (type === "json") {
|
|
37624
|
-
|
|
37784
|
+
resolve15(JSON.parse(Buffer.concat(body)));
|
|
37625
37785
|
} else if (type === "arrayBuffer") {
|
|
37626
37786
|
const dst = new Uint8Array(length);
|
|
37627
37787
|
let pos = 0;
|
|
@@ -37629,12 +37789,12 @@ var require_readable = __commonJS({
|
|
|
37629
37789
|
dst.set(buf, pos);
|
|
37630
37790
|
pos += buf.byteLength;
|
|
37631
37791
|
}
|
|
37632
|
-
|
|
37792
|
+
resolve15(dst.buffer);
|
|
37633
37793
|
} else if (type === "blob") {
|
|
37634
37794
|
if (!Blob2) {
|
|
37635
37795
|
Blob2 = require("buffer").Blob;
|
|
37636
37796
|
}
|
|
37637
|
-
|
|
37797
|
+
resolve15(new Blob2(body, { type: stream[kContentType] }));
|
|
37638
37798
|
}
|
|
37639
37799
|
consumeFinish(consume2);
|
|
37640
37800
|
} catch (err) {
|
|
@@ -37891,9 +38051,9 @@ var require_api_request = __commonJS({
|
|
|
37891
38051
|
};
|
|
37892
38052
|
function request(opts, callback) {
|
|
37893
38053
|
if (callback === void 0) {
|
|
37894
|
-
return new Promise((
|
|
38054
|
+
return new Promise((resolve15, reject) => {
|
|
37895
38055
|
request.call(this, opts, (err, data) => {
|
|
37896
|
-
return err ? reject(err) :
|
|
38056
|
+
return err ? reject(err) : resolve15(data);
|
|
37897
38057
|
});
|
|
37898
38058
|
});
|
|
37899
38059
|
}
|
|
@@ -38066,9 +38226,9 @@ var require_api_stream = __commonJS({
|
|
|
38066
38226
|
};
|
|
38067
38227
|
function stream(opts, factory, callback) {
|
|
38068
38228
|
if (callback === void 0) {
|
|
38069
|
-
return new Promise((
|
|
38229
|
+
return new Promise((resolve15, reject) => {
|
|
38070
38230
|
stream.call(this, opts, factory, (err, data) => {
|
|
38071
|
-
return err ? reject(err) :
|
|
38231
|
+
return err ? reject(err) : resolve15(data);
|
|
38072
38232
|
});
|
|
38073
38233
|
});
|
|
38074
38234
|
}
|
|
@@ -38349,9 +38509,9 @@ var require_api_upgrade = __commonJS({
|
|
|
38349
38509
|
};
|
|
38350
38510
|
function upgrade(opts, callback) {
|
|
38351
38511
|
if (callback === void 0) {
|
|
38352
|
-
return new Promise((
|
|
38512
|
+
return new Promise((resolve15, reject) => {
|
|
38353
38513
|
upgrade.call(this, opts, (err, data) => {
|
|
38354
|
-
return err ? reject(err) :
|
|
38514
|
+
return err ? reject(err) : resolve15(data);
|
|
38355
38515
|
});
|
|
38356
38516
|
});
|
|
38357
38517
|
}
|
|
@@ -38440,9 +38600,9 @@ var require_api_connect = __commonJS({
|
|
|
38440
38600
|
};
|
|
38441
38601
|
function connect(opts, callback) {
|
|
38442
38602
|
if (callback === void 0) {
|
|
38443
|
-
return new Promise((
|
|
38603
|
+
return new Promise((resolve15, reject) => {
|
|
38444
38604
|
connect.call(this, opts, (err, data) => {
|
|
38445
|
-
return err ? reject(err) :
|
|
38605
|
+
return err ? reject(err) : resolve15(data);
|
|
38446
38606
|
});
|
|
38447
38607
|
});
|
|
38448
38608
|
}
|
|
@@ -38602,20 +38762,20 @@ var require_mock_utils = __commonJS({
|
|
|
38602
38762
|
}
|
|
38603
38763
|
return true;
|
|
38604
38764
|
}
|
|
38605
|
-
function safeUrl(
|
|
38606
|
-
if (typeof
|
|
38607
|
-
return
|
|
38765
|
+
function safeUrl(path29) {
|
|
38766
|
+
if (typeof path29 !== "string") {
|
|
38767
|
+
return path29;
|
|
38608
38768
|
}
|
|
38609
|
-
const pathSegments =
|
|
38769
|
+
const pathSegments = path29.split("?");
|
|
38610
38770
|
if (pathSegments.length !== 2) {
|
|
38611
|
-
return
|
|
38771
|
+
return path29;
|
|
38612
38772
|
}
|
|
38613
38773
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
38614
38774
|
qp.sort();
|
|
38615
38775
|
return [...pathSegments, qp.toString()].join("?");
|
|
38616
38776
|
}
|
|
38617
|
-
function matchKey(mockDispatch2, { path:
|
|
38618
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
38777
|
+
function matchKey(mockDispatch2, { path: path29, method, body, headers }) {
|
|
38778
|
+
const pathMatch = matchValue(mockDispatch2.path, path29);
|
|
38619
38779
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
38620
38780
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
38621
38781
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -38633,7 +38793,7 @@ var require_mock_utils = __commonJS({
|
|
|
38633
38793
|
function getMockDispatch(mockDispatches, key) {
|
|
38634
38794
|
const basePath = key.query ? buildURL(key.path, key.query) : key.path;
|
|
38635
38795
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
38636
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
38796
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path29 }) => matchValue(safeUrl(path29), resolvedPath));
|
|
38637
38797
|
if (matchedMockDispatches.length === 0) {
|
|
38638
38798
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
38639
38799
|
}
|
|
@@ -38670,9 +38830,9 @@ var require_mock_utils = __commonJS({
|
|
|
38670
38830
|
}
|
|
38671
38831
|
}
|
|
38672
38832
|
function buildKey(opts) {
|
|
38673
|
-
const { path:
|
|
38833
|
+
const { path: path29, method, body, headers, query } = opts;
|
|
38674
38834
|
return {
|
|
38675
|
-
path:
|
|
38835
|
+
path: path29,
|
|
38676
38836
|
method,
|
|
38677
38837
|
body,
|
|
38678
38838
|
headers,
|
|
@@ -39121,10 +39281,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
39121
39281
|
}
|
|
39122
39282
|
format(pendingInterceptors) {
|
|
39123
39283
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
39124
|
-
({ method, path:
|
|
39284
|
+
({ method, path: path29, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
39125
39285
|
Method: method,
|
|
39126
39286
|
Origin: origin,
|
|
39127
|
-
Path:
|
|
39287
|
+
Path: path29,
|
|
39128
39288
|
"Status code": statusCode,
|
|
39129
39289
|
Persistent: persist ? "\u2705" : "\u274C",
|
|
39130
39290
|
Invocations: timesInvoked,
|
|
@@ -42065,7 +42225,7 @@ var require_fetch = __commonJS({
|
|
|
42065
42225
|
async function dispatch({ body }) {
|
|
42066
42226
|
const url = requestCurrentURL(request);
|
|
42067
42227
|
const agent = fetchParams.controller.dispatcher;
|
|
42068
|
-
return new Promise((
|
|
42228
|
+
return new Promise((resolve15, reject) => agent.dispatch(
|
|
42069
42229
|
{
|
|
42070
42230
|
path: url.pathname + url.search,
|
|
42071
42231
|
origin: url.origin,
|
|
@@ -42141,7 +42301,7 @@ var require_fetch = __commonJS({
|
|
|
42141
42301
|
}
|
|
42142
42302
|
}
|
|
42143
42303
|
}
|
|
42144
|
-
|
|
42304
|
+
resolve15({
|
|
42145
42305
|
status,
|
|
42146
42306
|
statusText,
|
|
42147
42307
|
headersList: headers[kHeadersList],
|
|
@@ -42184,7 +42344,7 @@ var require_fetch = __commonJS({
|
|
|
42184
42344
|
const val = headersList[n + 1].toString("latin1");
|
|
42185
42345
|
headers[kHeadersList].append(key, val);
|
|
42186
42346
|
}
|
|
42187
|
-
|
|
42347
|
+
resolve15({
|
|
42188
42348
|
status,
|
|
42189
42349
|
statusText: STATUS_CODES[status],
|
|
42190
42350
|
headersList: headers[kHeadersList],
|
|
@@ -43745,8 +43905,8 @@ var require_util6 = __commonJS({
|
|
|
43745
43905
|
}
|
|
43746
43906
|
}
|
|
43747
43907
|
}
|
|
43748
|
-
function validateCookiePath(
|
|
43749
|
-
for (const char of
|
|
43908
|
+
function validateCookiePath(path29) {
|
|
43909
|
+
for (const char of path29) {
|
|
43750
43910
|
const code = char.charCodeAt(0);
|
|
43751
43911
|
if (code < 33 || char === ";") {
|
|
43752
43912
|
throw new Error("Invalid cookie path");
|
|
@@ -44543,9 +44703,9 @@ var require_connection = __commonJS({
|
|
|
44543
44703
|
channels.open = diagnosticsChannel.channel("undici:websocket:open");
|
|
44544
44704
|
channels.close = diagnosticsChannel.channel("undici:websocket:close");
|
|
44545
44705
|
channels.socketError = diagnosticsChannel.channel("undici:websocket:socket_error");
|
|
44546
|
-
var
|
|
44706
|
+
var crypto7;
|
|
44547
44707
|
try {
|
|
44548
|
-
|
|
44708
|
+
crypto7 = require("crypto");
|
|
44549
44709
|
} catch {
|
|
44550
44710
|
}
|
|
44551
44711
|
function establishWebSocketConnection(url, protocols, ws, onEstablish, options) {
|
|
@@ -44564,7 +44724,7 @@ var require_connection = __commonJS({
|
|
|
44564
44724
|
const headersList = new Headers(options.headers)[kHeadersList];
|
|
44565
44725
|
request.headersList = headersList;
|
|
44566
44726
|
}
|
|
44567
|
-
const keyValue =
|
|
44727
|
+
const keyValue = crypto7.randomBytes(16).toString("base64");
|
|
44568
44728
|
request.headersList.append("sec-websocket-key", keyValue);
|
|
44569
44729
|
request.headersList.append("sec-websocket-version", "13");
|
|
44570
44730
|
for (const protocol of protocols) {
|
|
@@ -44593,7 +44753,7 @@ var require_connection = __commonJS({
|
|
|
44593
44753
|
return;
|
|
44594
44754
|
}
|
|
44595
44755
|
const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
|
|
44596
|
-
const digest =
|
|
44756
|
+
const digest = crypto7.createHash("sha1").update(keyValue + uid).digest("base64");
|
|
44597
44757
|
if (secWSAccept !== digest) {
|
|
44598
44758
|
failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header.");
|
|
44599
44759
|
return;
|
|
@@ -44673,9 +44833,9 @@ var require_frame = __commonJS({
|
|
|
44673
44833
|
"node_modules/undici/lib/websocket/frame.js"(exports2, module2) {
|
|
44674
44834
|
"use strict";
|
|
44675
44835
|
var { maxUnsigned16Bit } = require_constants5();
|
|
44676
|
-
var
|
|
44836
|
+
var crypto7;
|
|
44677
44837
|
try {
|
|
44678
|
-
|
|
44838
|
+
crypto7 = require("crypto");
|
|
44679
44839
|
} catch {
|
|
44680
44840
|
}
|
|
44681
44841
|
var WebsocketFrameSend = class {
|
|
@@ -44684,7 +44844,7 @@ var require_frame = __commonJS({
|
|
|
44684
44844
|
*/
|
|
44685
44845
|
constructor(data) {
|
|
44686
44846
|
this.frameData = data;
|
|
44687
|
-
this.maskKey =
|
|
44847
|
+
this.maskKey = crypto7.randomBytes(4);
|
|
44688
44848
|
}
|
|
44689
44849
|
createFrame(opcode) {
|
|
44690
44850
|
const bodyLength = this.frameData?.byteLength ?? 0;
|
|
@@ -45426,11 +45586,11 @@ var require_undici = __commonJS({
|
|
|
45426
45586
|
if (typeof opts.path !== "string") {
|
|
45427
45587
|
throw new InvalidArgumentError("invalid opts.path");
|
|
45428
45588
|
}
|
|
45429
|
-
let
|
|
45589
|
+
let path29 = opts.path;
|
|
45430
45590
|
if (!opts.path.startsWith("/")) {
|
|
45431
|
-
|
|
45591
|
+
path29 = `/${path29}`;
|
|
45432
45592
|
}
|
|
45433
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
45593
|
+
url = new URL(util.parseOrigin(url).origin + path29);
|
|
45434
45594
|
} else {
|
|
45435
45595
|
if (!opts) {
|
|
45436
45596
|
opts = typeof url === "object" ? url : {};
|
|
@@ -45999,7 +46159,7 @@ var init_mcp_check_provider = __esm({
|
|
|
45999
46159
|
logger.warn(
|
|
46000
46160
|
`MCP ${transportName} failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`
|
|
46001
46161
|
);
|
|
46002
|
-
await new Promise((
|
|
46162
|
+
await new Promise((resolve15) => setTimeout(resolve15, delay));
|
|
46003
46163
|
attempt += 1;
|
|
46004
46164
|
} finally {
|
|
46005
46165
|
try {
|
|
@@ -46292,7 +46452,7 @@ async function acquirePromptLock() {
|
|
|
46292
46452
|
);
|
|
46293
46453
|
}, 1e4);
|
|
46294
46454
|
try {
|
|
46295
|
-
await new Promise((
|
|
46455
|
+
await new Promise((resolve15) => waiters.push(resolve15));
|
|
46296
46456
|
} finally {
|
|
46297
46457
|
clearInterval(reminder);
|
|
46298
46458
|
const waitedMs = Date.now() - queuedAt;
|
|
@@ -46311,7 +46471,7 @@ function releasePromptLock() {
|
|
|
46311
46471
|
}
|
|
46312
46472
|
async function interactivePrompt(options) {
|
|
46313
46473
|
await acquirePromptLock();
|
|
46314
|
-
return new Promise((
|
|
46474
|
+
return new Promise((resolve15, reject) => {
|
|
46315
46475
|
const dbg = process.env.VISOR_DEBUG === "true";
|
|
46316
46476
|
try {
|
|
46317
46477
|
if (dbg) {
|
|
@@ -46398,12 +46558,12 @@ async function interactivePrompt(options) {
|
|
|
46398
46558
|
};
|
|
46399
46559
|
const finish = (value) => {
|
|
46400
46560
|
cleanup();
|
|
46401
|
-
|
|
46561
|
+
resolve15(value);
|
|
46402
46562
|
};
|
|
46403
46563
|
if (options.timeout && options.timeout > 0) {
|
|
46404
46564
|
timeoutId = setTimeout(() => {
|
|
46405
46565
|
cleanup();
|
|
46406
|
-
if (defaultValue !== void 0) return
|
|
46566
|
+
if (defaultValue !== void 0) return resolve15(defaultValue);
|
|
46407
46567
|
return reject(new Error("Input timeout"));
|
|
46408
46568
|
}, options.timeout);
|
|
46409
46569
|
}
|
|
@@ -46535,7 +46695,7 @@ async function interactivePrompt(options) {
|
|
|
46535
46695
|
});
|
|
46536
46696
|
}
|
|
46537
46697
|
async function simplePrompt(prompt) {
|
|
46538
|
-
return new Promise((
|
|
46698
|
+
return new Promise((resolve15) => {
|
|
46539
46699
|
const rl = readline.createInterface({
|
|
46540
46700
|
input: process.stdin,
|
|
46541
46701
|
output: process.stdout
|
|
@@ -46551,7 +46711,7 @@ async function simplePrompt(prompt) {
|
|
|
46551
46711
|
rl.question(`${prompt}
|
|
46552
46712
|
> `, (answer) => {
|
|
46553
46713
|
rl.close();
|
|
46554
|
-
|
|
46714
|
+
resolve15(answer.trim());
|
|
46555
46715
|
});
|
|
46556
46716
|
});
|
|
46557
46717
|
}
|
|
@@ -46719,7 +46879,7 @@ function isStdinAvailable() {
|
|
|
46719
46879
|
return !process.stdin.isTTY;
|
|
46720
46880
|
}
|
|
46721
46881
|
async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
46722
|
-
return new Promise((
|
|
46882
|
+
return new Promise((resolve15, reject) => {
|
|
46723
46883
|
let data = "";
|
|
46724
46884
|
let timeoutId;
|
|
46725
46885
|
if (timeout) {
|
|
@@ -46746,7 +46906,7 @@ async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
|
46746
46906
|
};
|
|
46747
46907
|
const onEnd = () => {
|
|
46748
46908
|
cleanup();
|
|
46749
|
-
|
|
46909
|
+
resolve15(data.trim());
|
|
46750
46910
|
};
|
|
46751
46911
|
const onError = (err) => {
|
|
46752
46912
|
cleanup();
|
|
@@ -51446,23 +51606,23 @@ __export(renderer_schema_exports, {
|
|
|
51446
51606
|
});
|
|
51447
51607
|
async function loadRendererSchema(name) {
|
|
51448
51608
|
try {
|
|
51449
|
-
const
|
|
51450
|
-
const
|
|
51609
|
+
const fs25 = await import("fs/promises");
|
|
51610
|
+
const path29 = await import("path");
|
|
51451
51611
|
const sanitized = String(name).replace(/[^a-zA-Z0-9-]/g, "");
|
|
51452
51612
|
if (!sanitized) return void 0;
|
|
51453
51613
|
const candidates = [
|
|
51454
51614
|
// When bundled with ncc, __dirname is dist/ and output/ is at dist/output/
|
|
51455
|
-
|
|
51615
|
+
path29.join(__dirname, "output", sanitized, "schema.json"),
|
|
51456
51616
|
// When running from source, __dirname is src/state-machine/dispatch/ and output/ is at output/
|
|
51457
|
-
|
|
51617
|
+
path29.join(__dirname, "..", "..", "output", sanitized, "schema.json"),
|
|
51458
51618
|
// When running from a checkout with output/ folder copied to CWD
|
|
51459
|
-
|
|
51619
|
+
path29.join(process.cwd(), "output", sanitized, "schema.json"),
|
|
51460
51620
|
// Fallback: cwd/dist/output/
|
|
51461
|
-
|
|
51621
|
+
path29.join(process.cwd(), "dist", "output", sanitized, "schema.json")
|
|
51462
51622
|
];
|
|
51463
51623
|
for (const p of candidates) {
|
|
51464
51624
|
try {
|
|
51465
|
-
const raw = await
|
|
51625
|
+
const raw = await fs25.readFile(p, "utf-8");
|
|
51466
51626
|
return JSON.parse(raw);
|
|
51467
51627
|
} catch {
|
|
51468
51628
|
}
|
|
@@ -53907,8 +54067,8 @@ function updateStats2(results, state, isForEachIteration = false) {
|
|
|
53907
54067
|
async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
53908
54068
|
try {
|
|
53909
54069
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
53910
|
-
const
|
|
53911
|
-
const
|
|
54070
|
+
const fs25 = await import("fs/promises");
|
|
54071
|
+
const path29 = await import("path");
|
|
53912
54072
|
const schemaRaw = checkConfig.schema || "plain";
|
|
53913
54073
|
const schema = typeof schemaRaw === "string" && !schemaRaw.includes("{{") && !schemaRaw.includes("{%") ? schemaRaw : typeof schemaRaw === "object" ? "code-review" : "plain";
|
|
53914
54074
|
let templateContent;
|
|
@@ -53917,27 +54077,27 @@ async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
|
53917
54077
|
logger.debug(`[LevelDispatch] Using inline template for ${checkId}`);
|
|
53918
54078
|
} else if (checkConfig.template && checkConfig.template.file) {
|
|
53919
54079
|
const file = String(checkConfig.template.file);
|
|
53920
|
-
const resolved =
|
|
53921
|
-
templateContent = await
|
|
54080
|
+
const resolved = path29.resolve(process.cwd(), file);
|
|
54081
|
+
templateContent = await fs25.readFile(resolved, "utf-8");
|
|
53922
54082
|
logger.debug(`[LevelDispatch] Using template file for ${checkId}: ${resolved}`);
|
|
53923
54083
|
} else if (schema && schema !== "plain") {
|
|
53924
54084
|
const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
|
|
53925
54085
|
if (sanitized) {
|
|
53926
54086
|
const candidatePaths = [
|
|
53927
|
-
|
|
54087
|
+
path29.join(__dirname, "output", sanitized, "template.liquid"),
|
|
53928
54088
|
// bundled: dist/output/
|
|
53929
|
-
|
|
54089
|
+
path29.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
53930
54090
|
// source (from state-machine/states)
|
|
53931
|
-
|
|
54091
|
+
path29.join(__dirname, "..", "..", "..", "output", sanitized, "template.liquid"),
|
|
53932
54092
|
// source (alternate)
|
|
53933
|
-
|
|
54093
|
+
path29.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
53934
54094
|
// fallback: cwd/output/
|
|
53935
|
-
|
|
54095
|
+
path29.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
|
|
53936
54096
|
// fallback: cwd/dist/output/
|
|
53937
54097
|
];
|
|
53938
54098
|
for (const p of candidatePaths) {
|
|
53939
54099
|
try {
|
|
53940
|
-
templateContent = await
|
|
54100
|
+
templateContent = await fs25.readFile(p, "utf-8");
|
|
53941
54101
|
if (templateContent) {
|
|
53942
54102
|
logger.debug(`[LevelDispatch] Using schema template for ${checkId}: ${p}`);
|
|
53943
54103
|
break;
|
|
@@ -56077,8 +56237,8 @@ var init_workspace_manager = __esm({
|
|
|
56077
56237
|
);
|
|
56078
56238
|
if (this.cleanupRequested && this.activeOperations === 0) {
|
|
56079
56239
|
logger.debug(`[Workspace] All references released, proceeding with deferred cleanup`);
|
|
56080
|
-
for (const
|
|
56081
|
-
|
|
56240
|
+
for (const resolve15 of this.cleanupResolvers) {
|
|
56241
|
+
resolve15();
|
|
56082
56242
|
}
|
|
56083
56243
|
this.cleanupResolvers = [];
|
|
56084
56244
|
}
|
|
@@ -56257,19 +56417,19 @@ var init_workspace_manager = __esm({
|
|
|
56257
56417
|
);
|
|
56258
56418
|
this.cleanupRequested = true;
|
|
56259
56419
|
await Promise.race([
|
|
56260
|
-
new Promise((
|
|
56420
|
+
new Promise((resolve15) => {
|
|
56261
56421
|
if (this.activeOperations === 0) {
|
|
56262
|
-
|
|
56422
|
+
resolve15();
|
|
56263
56423
|
} else {
|
|
56264
|
-
this.cleanupResolvers.push(
|
|
56424
|
+
this.cleanupResolvers.push(resolve15);
|
|
56265
56425
|
}
|
|
56266
56426
|
}),
|
|
56267
|
-
new Promise((
|
|
56427
|
+
new Promise((resolve15) => {
|
|
56268
56428
|
setTimeout(() => {
|
|
56269
56429
|
logger.warn(
|
|
56270
56430
|
`[Workspace] Cleanup timeout after ${timeout}ms, proceeding anyway (${this.activeOperations} operations still active)`
|
|
56271
56431
|
);
|
|
56272
|
-
|
|
56432
|
+
resolve15();
|
|
56273
56433
|
}, timeout);
|
|
56274
56434
|
})
|
|
56275
56435
|
]);
|
|
@@ -56663,8 +56823,8 @@ var init_fair_concurrency_limiter = __esm({
|
|
|
56663
56823
|
);
|
|
56664
56824
|
const queuedAt = Date.now();
|
|
56665
56825
|
const effectiveTimeout = queueTimeout ?? 12e4;
|
|
56666
|
-
return new Promise((
|
|
56667
|
-
const entry = { resolve:
|
|
56826
|
+
return new Promise((resolve15, reject) => {
|
|
56827
|
+
const entry = { resolve: resolve15, reject, queuedAt };
|
|
56668
56828
|
entry.reminder = setInterval(() => {
|
|
56669
56829
|
const waited = Math.round((Date.now() - queuedAt) / 1e3);
|
|
56670
56830
|
const curQueued = this._totalQueued();
|
|
@@ -56971,1380 +57131,6 @@ var init_build_engine_context = __esm({
|
|
|
56971
57131
|
}
|
|
56972
57132
|
});
|
|
56973
57133
|
|
|
56974
|
-
// src/policy/default-engine.ts
|
|
56975
|
-
var DefaultPolicyEngine;
|
|
56976
|
-
var init_default_engine = __esm({
|
|
56977
|
-
"src/policy/default-engine.ts"() {
|
|
56978
|
-
"use strict";
|
|
56979
|
-
DefaultPolicyEngine = class {
|
|
56980
|
-
async initialize(_config) {
|
|
56981
|
-
}
|
|
56982
|
-
async evaluateCheckExecution(_checkId, _checkConfig) {
|
|
56983
|
-
return { allowed: true };
|
|
56984
|
-
}
|
|
56985
|
-
async evaluateToolInvocation(_serverName, _methodName, _transport) {
|
|
56986
|
-
return { allowed: true };
|
|
56987
|
-
}
|
|
56988
|
-
async evaluateCapabilities(_checkId, _capabilities) {
|
|
56989
|
-
return { allowed: true };
|
|
56990
|
-
}
|
|
56991
|
-
async shutdown() {
|
|
56992
|
-
}
|
|
56993
|
-
};
|
|
56994
|
-
}
|
|
56995
|
-
});
|
|
56996
|
-
|
|
56997
|
-
// src/enterprise/license/validator.ts
|
|
56998
|
-
var validator_exports = {};
|
|
56999
|
-
__export(validator_exports, {
|
|
57000
|
-
LicenseValidator: () => LicenseValidator
|
|
57001
|
-
});
|
|
57002
|
-
var crypto3, fs21, path26, LicenseValidator;
|
|
57003
|
-
var init_validator = __esm({
|
|
57004
|
-
"src/enterprise/license/validator.ts"() {
|
|
57005
|
-
"use strict";
|
|
57006
|
-
crypto3 = __toESM(require("crypto"));
|
|
57007
|
-
fs21 = __toESM(require("fs"));
|
|
57008
|
-
path26 = __toESM(require("path"));
|
|
57009
|
-
LicenseValidator = class _LicenseValidator {
|
|
57010
|
-
/** Ed25519 public key for license verification (PEM format). */
|
|
57011
|
-
static PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAI/Zd08EFmgIdrDm/HXd0l3/5GBt7R1PrdvhdmEXhJlU=\n-----END PUBLIC KEY-----\n";
|
|
57012
|
-
cache = null;
|
|
57013
|
-
static CACHE_TTL = 5 * 60 * 1e3;
|
|
57014
|
-
// 5 minutes
|
|
57015
|
-
static GRACE_PERIOD = 72 * 3600 * 1e3;
|
|
57016
|
-
// 72 hours after expiry
|
|
57017
|
-
/**
|
|
57018
|
-
* Load and validate license from environment or file.
|
|
57019
|
-
*
|
|
57020
|
-
* Resolution order:
|
|
57021
|
-
* 1. VISOR_LICENSE env var (JWT string)
|
|
57022
|
-
* 2. VISOR_LICENSE_FILE env var (path to file)
|
|
57023
|
-
* 3. .visor-license in project root (cwd)
|
|
57024
|
-
* 4. .visor-license in ~/.config/visor/
|
|
57025
|
-
*/
|
|
57026
|
-
async loadAndValidate() {
|
|
57027
|
-
if (this.cache && Date.now() - this.cache.validatedAt < _LicenseValidator.CACHE_TTL) {
|
|
57028
|
-
return this.cache.payload;
|
|
57029
|
-
}
|
|
57030
|
-
const token = this.resolveToken();
|
|
57031
|
-
if (!token) return null;
|
|
57032
|
-
const payload = this.verifyAndDecode(token);
|
|
57033
|
-
if (!payload) return null;
|
|
57034
|
-
this.cache = { payload, validatedAt: Date.now() };
|
|
57035
|
-
return payload;
|
|
57036
|
-
}
|
|
57037
|
-
/** Check if a specific feature is licensed */
|
|
57038
|
-
hasFeature(feature) {
|
|
57039
|
-
if (!this.cache) return false;
|
|
57040
|
-
return this.cache.payload.features.includes(feature);
|
|
57041
|
-
}
|
|
57042
|
-
/** Check if license is valid (with grace period) */
|
|
57043
|
-
isValid() {
|
|
57044
|
-
if (!this.cache) return false;
|
|
57045
|
-
const now = Date.now();
|
|
57046
|
-
const expiryMs = this.cache.payload.exp * 1e3;
|
|
57047
|
-
return now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
57048
|
-
}
|
|
57049
|
-
/** Check if the license is within its grace period (expired but still valid) */
|
|
57050
|
-
isInGracePeriod() {
|
|
57051
|
-
if (!this.cache) return false;
|
|
57052
|
-
const now = Date.now();
|
|
57053
|
-
const expiryMs = this.cache.payload.exp * 1e3;
|
|
57054
|
-
return now >= expiryMs && now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
57055
|
-
}
|
|
57056
|
-
resolveToken() {
|
|
57057
|
-
if (process.env.VISOR_LICENSE) {
|
|
57058
|
-
return process.env.VISOR_LICENSE.trim();
|
|
57059
|
-
}
|
|
57060
|
-
if (process.env.VISOR_LICENSE_FILE) {
|
|
57061
|
-
const resolved = path26.resolve(process.env.VISOR_LICENSE_FILE);
|
|
57062
|
-
const home2 = process.env.HOME || process.env.USERPROFILE || "";
|
|
57063
|
-
const allowedPrefixes = [path26.normalize(process.cwd())];
|
|
57064
|
-
if (home2) allowedPrefixes.push(path26.normalize(path26.join(home2, ".config", "visor")));
|
|
57065
|
-
let realPath;
|
|
57066
|
-
try {
|
|
57067
|
-
realPath = fs21.realpathSync(resolved);
|
|
57068
|
-
} catch {
|
|
57069
|
-
return null;
|
|
57070
|
-
}
|
|
57071
|
-
const isSafe = allowedPrefixes.some(
|
|
57072
|
-
(prefix) => realPath === prefix || realPath.startsWith(prefix + path26.sep)
|
|
57073
|
-
);
|
|
57074
|
-
if (!isSafe) return null;
|
|
57075
|
-
return this.readFile(realPath);
|
|
57076
|
-
}
|
|
57077
|
-
const cwdPath = path26.join(process.cwd(), ".visor-license");
|
|
57078
|
-
const cwdToken = this.readFile(cwdPath);
|
|
57079
|
-
if (cwdToken) return cwdToken;
|
|
57080
|
-
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
57081
|
-
if (home) {
|
|
57082
|
-
const configPath = path26.join(home, ".config", "visor", ".visor-license");
|
|
57083
|
-
const configToken = this.readFile(configPath);
|
|
57084
|
-
if (configToken) return configToken;
|
|
57085
|
-
}
|
|
57086
|
-
return null;
|
|
57087
|
-
}
|
|
57088
|
-
readFile(filePath) {
|
|
57089
|
-
try {
|
|
57090
|
-
return fs21.readFileSync(filePath, "utf-8").trim();
|
|
57091
|
-
} catch {
|
|
57092
|
-
return null;
|
|
57093
|
-
}
|
|
57094
|
-
}
|
|
57095
|
-
verifyAndDecode(token) {
|
|
57096
|
-
try {
|
|
57097
|
-
const parts = token.split(".");
|
|
57098
|
-
if (parts.length !== 3) return null;
|
|
57099
|
-
const [headerB64, payloadB64, signatureB64] = parts;
|
|
57100
|
-
const header = JSON.parse(Buffer.from(headerB64, "base64url").toString());
|
|
57101
|
-
if (header.alg !== "EdDSA") return null;
|
|
57102
|
-
const data = `${headerB64}.${payloadB64}`;
|
|
57103
|
-
const signature = Buffer.from(signatureB64, "base64url");
|
|
57104
|
-
const publicKey = crypto3.createPublicKey(_LicenseValidator.PUBLIC_KEY);
|
|
57105
|
-
if (publicKey.asymmetricKeyType !== "ed25519") {
|
|
57106
|
-
return null;
|
|
57107
|
-
}
|
|
57108
|
-
const isValid = crypto3.verify(null, Buffer.from(data), publicKey, signature);
|
|
57109
|
-
if (!isValid) return null;
|
|
57110
|
-
const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
|
|
57111
|
-
if (!payload.org || !Array.isArray(payload.features) || typeof payload.exp !== "number" || typeof payload.iat !== "number" || !payload.sub) {
|
|
57112
|
-
return null;
|
|
57113
|
-
}
|
|
57114
|
-
const now = Date.now();
|
|
57115
|
-
const expiryMs = payload.exp * 1e3;
|
|
57116
|
-
if (now >= expiryMs + _LicenseValidator.GRACE_PERIOD) {
|
|
57117
|
-
return null;
|
|
57118
|
-
}
|
|
57119
|
-
return payload;
|
|
57120
|
-
} catch {
|
|
57121
|
-
return null;
|
|
57122
|
-
}
|
|
57123
|
-
}
|
|
57124
|
-
};
|
|
57125
|
-
}
|
|
57126
|
-
});
|
|
57127
|
-
|
|
57128
|
-
// src/enterprise/policy/opa-compiler.ts
|
|
57129
|
-
var fs22, path27, os2, crypto4, import_child_process8, OpaCompiler;
|
|
57130
|
-
var init_opa_compiler = __esm({
|
|
57131
|
-
"src/enterprise/policy/opa-compiler.ts"() {
|
|
57132
|
-
"use strict";
|
|
57133
|
-
fs22 = __toESM(require("fs"));
|
|
57134
|
-
path27 = __toESM(require("path"));
|
|
57135
|
-
os2 = __toESM(require("os"));
|
|
57136
|
-
crypto4 = __toESM(require("crypto"));
|
|
57137
|
-
import_child_process8 = require("child_process");
|
|
57138
|
-
OpaCompiler = class _OpaCompiler {
|
|
57139
|
-
static CACHE_DIR = path27.join(os2.tmpdir(), "visor-opa-cache");
|
|
57140
|
-
/**
|
|
57141
|
-
* Resolve the input paths to WASM bytes.
|
|
57142
|
-
*
|
|
57143
|
-
* Strategy:
|
|
57144
|
-
* 1. If any path is a .wasm file, read it directly
|
|
57145
|
-
* 2. If a directory contains policy.wasm, read it
|
|
57146
|
-
* 3. Otherwise, collect all .rego files and auto-compile via `opa build`
|
|
57147
|
-
*/
|
|
57148
|
-
async resolveWasmBytes(paths) {
|
|
57149
|
-
const regoFiles = [];
|
|
57150
|
-
for (const p of paths) {
|
|
57151
|
-
const resolved = path27.resolve(p);
|
|
57152
|
-
if (path27.normalize(resolved).includes("..")) {
|
|
57153
|
-
throw new Error(`Policy path contains traversal sequences: ${p}`);
|
|
57154
|
-
}
|
|
57155
|
-
if (resolved.endsWith(".wasm") && fs22.existsSync(resolved)) {
|
|
57156
|
-
return fs22.readFileSync(resolved);
|
|
57157
|
-
}
|
|
57158
|
-
if (!fs22.existsSync(resolved)) continue;
|
|
57159
|
-
const stat2 = fs22.statSync(resolved);
|
|
57160
|
-
if (stat2.isDirectory()) {
|
|
57161
|
-
const wasmCandidate = path27.join(resolved, "policy.wasm");
|
|
57162
|
-
if (fs22.existsSync(wasmCandidate)) {
|
|
57163
|
-
return fs22.readFileSync(wasmCandidate);
|
|
57164
|
-
}
|
|
57165
|
-
const files = fs22.readdirSync(resolved);
|
|
57166
|
-
for (const f of files) {
|
|
57167
|
-
if (f.endsWith(".rego")) {
|
|
57168
|
-
regoFiles.push(path27.join(resolved, f));
|
|
57169
|
-
}
|
|
57170
|
-
}
|
|
57171
|
-
} else if (resolved.endsWith(".rego")) {
|
|
57172
|
-
regoFiles.push(resolved);
|
|
57173
|
-
}
|
|
57174
|
-
}
|
|
57175
|
-
if (regoFiles.length === 0) {
|
|
57176
|
-
throw new Error(
|
|
57177
|
-
`OPA WASM evaluator: no .wasm bundle or .rego files found in: ${paths.join(", ")}`
|
|
57178
|
-
);
|
|
57179
|
-
}
|
|
57180
|
-
return this.compileRego(regoFiles);
|
|
57181
|
-
}
|
|
57182
|
-
/**
|
|
57183
|
-
* Auto-compile .rego files to a WASM bundle using the `opa` CLI.
|
|
57184
|
-
*
|
|
57185
|
-
* Caches the compiled bundle based on a content hash of all input .rego files
|
|
57186
|
-
* so subsequent runs skip compilation if policies haven't changed.
|
|
57187
|
-
*/
|
|
57188
|
-
compileRego(regoFiles) {
|
|
57189
|
-
try {
|
|
57190
|
-
(0, import_child_process8.execFileSync)("opa", ["version"], { stdio: "pipe" });
|
|
57191
|
-
} catch {
|
|
57192
|
-
throw new Error(
|
|
57193
|
-
"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(" ")
|
|
57194
|
-
);
|
|
57195
|
-
}
|
|
57196
|
-
const hash = crypto4.createHash("sha256");
|
|
57197
|
-
for (const f of regoFiles.sort()) {
|
|
57198
|
-
hash.update(fs22.readFileSync(f));
|
|
57199
|
-
hash.update(f);
|
|
57200
|
-
}
|
|
57201
|
-
const cacheKey = hash.digest("hex").slice(0, 16);
|
|
57202
|
-
const cacheDir = _OpaCompiler.CACHE_DIR;
|
|
57203
|
-
const cachedWasm = path27.join(cacheDir, `${cacheKey}.wasm`);
|
|
57204
|
-
if (fs22.existsSync(cachedWasm)) {
|
|
57205
|
-
return fs22.readFileSync(cachedWasm);
|
|
57206
|
-
}
|
|
57207
|
-
fs22.mkdirSync(cacheDir, { recursive: true });
|
|
57208
|
-
const bundleTar = path27.join(cacheDir, `${cacheKey}-bundle.tar.gz`);
|
|
57209
|
-
try {
|
|
57210
|
-
const args = [
|
|
57211
|
-
"build",
|
|
57212
|
-
"-t",
|
|
57213
|
-
"wasm",
|
|
57214
|
-
"-e",
|
|
57215
|
-
"visor",
|
|
57216
|
-
// entrypoint: the visor package tree
|
|
57217
|
-
"-o",
|
|
57218
|
-
bundleTar,
|
|
57219
|
-
...regoFiles
|
|
57220
|
-
];
|
|
57221
|
-
(0, import_child_process8.execFileSync)("opa", args, {
|
|
57222
|
-
stdio: "pipe",
|
|
57223
|
-
timeout: 3e4
|
|
57224
|
-
});
|
|
57225
|
-
} catch (err) {
|
|
57226
|
-
const stderr = err?.stderr?.toString() || "";
|
|
57227
|
-
throw new Error(
|
|
57228
|
-
`Failed to compile .rego files to WASM:
|
|
57229
|
-
${stderr}
|
|
57230
|
-
Ensure your .rego files are valid and the \`opa\` CLI is installed.`
|
|
57231
|
-
);
|
|
57232
|
-
}
|
|
57233
|
-
try {
|
|
57234
|
-
(0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "/policy.wasm"], {
|
|
57235
|
-
stdio: "pipe"
|
|
57236
|
-
});
|
|
57237
|
-
const extractedWasm = path27.join(cacheDir, "policy.wasm");
|
|
57238
|
-
if (fs22.existsSync(extractedWasm)) {
|
|
57239
|
-
fs22.renameSync(extractedWasm, cachedWasm);
|
|
57240
|
-
}
|
|
57241
|
-
} catch {
|
|
57242
|
-
try {
|
|
57243
|
-
(0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "policy.wasm"], {
|
|
57244
|
-
stdio: "pipe"
|
|
57245
|
-
});
|
|
57246
|
-
const extractedWasm = path27.join(cacheDir, "policy.wasm");
|
|
57247
|
-
if (fs22.existsSync(extractedWasm)) {
|
|
57248
|
-
fs22.renameSync(extractedWasm, cachedWasm);
|
|
57249
|
-
}
|
|
57250
|
-
} catch (err2) {
|
|
57251
|
-
throw new Error(`Failed to extract policy.wasm from OPA bundle: ${err2?.message || err2}`);
|
|
57252
|
-
}
|
|
57253
|
-
}
|
|
57254
|
-
try {
|
|
57255
|
-
fs22.unlinkSync(bundleTar);
|
|
57256
|
-
} catch {
|
|
57257
|
-
}
|
|
57258
|
-
if (!fs22.existsSync(cachedWasm)) {
|
|
57259
|
-
throw new Error("OPA build succeeded but policy.wasm was not found in the bundle");
|
|
57260
|
-
}
|
|
57261
|
-
return fs22.readFileSync(cachedWasm);
|
|
57262
|
-
}
|
|
57263
|
-
};
|
|
57264
|
-
}
|
|
57265
|
-
});
|
|
57266
|
-
|
|
57267
|
-
// src/enterprise/policy/opa-wasm-evaluator.ts
|
|
57268
|
-
var fs23, path28, OpaWasmEvaluator;
|
|
57269
|
-
var init_opa_wasm_evaluator = __esm({
|
|
57270
|
-
"src/enterprise/policy/opa-wasm-evaluator.ts"() {
|
|
57271
|
-
"use strict";
|
|
57272
|
-
fs23 = __toESM(require("fs"));
|
|
57273
|
-
path28 = __toESM(require("path"));
|
|
57274
|
-
init_opa_compiler();
|
|
57275
|
-
OpaWasmEvaluator = class {
|
|
57276
|
-
policy = null;
|
|
57277
|
-
dataDocument = {};
|
|
57278
|
-
compiler = new OpaCompiler();
|
|
57279
|
-
async initialize(rulesPath) {
|
|
57280
|
-
const paths = Array.isArray(rulesPath) ? rulesPath : [rulesPath];
|
|
57281
|
-
const wasmBytes = await this.compiler.resolveWasmBytes(paths);
|
|
57282
|
-
try {
|
|
57283
|
-
const { createRequire } = require("module");
|
|
57284
|
-
const runtimeRequire = createRequire(__filename);
|
|
57285
|
-
const opaWasm = runtimeRequire("@open-policy-agent/opa-wasm");
|
|
57286
|
-
const loadPolicy = opaWasm.loadPolicy || opaWasm.default?.loadPolicy;
|
|
57287
|
-
if (!loadPolicy) {
|
|
57288
|
-
throw new Error("loadPolicy not found in @open-policy-agent/opa-wasm");
|
|
57289
|
-
}
|
|
57290
|
-
this.policy = await loadPolicy(wasmBytes);
|
|
57291
|
-
} catch (err) {
|
|
57292
|
-
if (err?.code === "MODULE_NOT_FOUND" || err?.code === "ERR_MODULE_NOT_FOUND") {
|
|
57293
|
-
throw new Error(
|
|
57294
|
-
"OPA WASM evaluator requires @open-policy-agent/opa-wasm. Install it with: npm install @open-policy-agent/opa-wasm"
|
|
57295
|
-
);
|
|
57296
|
-
}
|
|
57297
|
-
throw err;
|
|
57298
|
-
}
|
|
57299
|
-
}
|
|
57300
|
-
/**
|
|
57301
|
-
* Load external data from a JSON file to use as the OPA data document.
|
|
57302
|
-
* The loaded data will be passed to `policy.setData()` during evaluation,
|
|
57303
|
-
* making it available in Rego via `data.<key>`.
|
|
57304
|
-
*/
|
|
57305
|
-
loadData(dataPath) {
|
|
57306
|
-
const resolved = path28.resolve(dataPath);
|
|
57307
|
-
if (path28.normalize(resolved).includes("..")) {
|
|
57308
|
-
throw new Error(`Data path contains traversal sequences: ${dataPath}`);
|
|
57309
|
-
}
|
|
57310
|
-
if (!fs23.existsSync(resolved)) {
|
|
57311
|
-
throw new Error(`OPA data file not found: ${resolved}`);
|
|
57312
|
-
}
|
|
57313
|
-
const stat2 = fs23.statSync(resolved);
|
|
57314
|
-
if (stat2.size > 10 * 1024 * 1024) {
|
|
57315
|
-
throw new Error(`OPA data file exceeds 10MB limit: ${resolved} (${stat2.size} bytes)`);
|
|
57316
|
-
}
|
|
57317
|
-
const raw = fs23.readFileSync(resolved, "utf-8");
|
|
57318
|
-
try {
|
|
57319
|
-
const parsed = JSON.parse(raw);
|
|
57320
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
57321
|
-
throw new Error("OPA data file must contain a JSON object (not an array or primitive)");
|
|
57322
|
-
}
|
|
57323
|
-
this.dataDocument = parsed;
|
|
57324
|
-
} catch (err) {
|
|
57325
|
-
if (err.message.startsWith("OPA data file must")) {
|
|
57326
|
-
throw err;
|
|
57327
|
-
}
|
|
57328
|
-
throw new Error(`Failed to parse OPA data file ${resolved}: ${err.message}`);
|
|
57329
|
-
}
|
|
57330
|
-
}
|
|
57331
|
-
async evaluate(input) {
|
|
57332
|
-
if (!this.policy) {
|
|
57333
|
-
throw new Error("OPA WASM evaluator not initialized");
|
|
57334
|
-
}
|
|
57335
|
-
this.policy.setData(this.dataDocument);
|
|
57336
|
-
const resultSet = this.policy.evaluate(input);
|
|
57337
|
-
if (Array.isArray(resultSet) && resultSet.length > 0) {
|
|
57338
|
-
return resultSet[0].result;
|
|
57339
|
-
}
|
|
57340
|
-
return void 0;
|
|
57341
|
-
}
|
|
57342
|
-
async shutdown() {
|
|
57343
|
-
if (this.policy) {
|
|
57344
|
-
if (typeof this.policy.close === "function") {
|
|
57345
|
-
try {
|
|
57346
|
-
this.policy.close();
|
|
57347
|
-
} catch {
|
|
57348
|
-
}
|
|
57349
|
-
} else if (typeof this.policy.free === "function") {
|
|
57350
|
-
try {
|
|
57351
|
-
this.policy.free();
|
|
57352
|
-
} catch {
|
|
57353
|
-
}
|
|
57354
|
-
}
|
|
57355
|
-
}
|
|
57356
|
-
this.policy = null;
|
|
57357
|
-
}
|
|
57358
|
-
};
|
|
57359
|
-
}
|
|
57360
|
-
});
|
|
57361
|
-
|
|
57362
|
-
// src/enterprise/policy/opa-http-evaluator.ts
|
|
57363
|
-
var OpaHttpEvaluator;
|
|
57364
|
-
var init_opa_http_evaluator = __esm({
|
|
57365
|
-
"src/enterprise/policy/opa-http-evaluator.ts"() {
|
|
57366
|
-
"use strict";
|
|
57367
|
-
OpaHttpEvaluator = class {
|
|
57368
|
-
baseUrl;
|
|
57369
|
-
timeout;
|
|
57370
|
-
constructor(baseUrl, timeout = 5e3) {
|
|
57371
|
-
let parsed;
|
|
57372
|
-
try {
|
|
57373
|
-
parsed = new URL(baseUrl);
|
|
57374
|
-
} catch {
|
|
57375
|
-
throw new Error(`OPA HTTP evaluator: invalid URL: ${baseUrl}`);
|
|
57376
|
-
}
|
|
57377
|
-
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
57378
|
-
throw new Error(
|
|
57379
|
-
`OPA HTTP evaluator: url must use http:// or https:// protocol, got: ${baseUrl}`
|
|
57380
|
-
);
|
|
57381
|
-
}
|
|
57382
|
-
const hostname = parsed.hostname;
|
|
57383
|
-
if (this.isBlockedHostname(hostname)) {
|
|
57384
|
-
throw new Error(
|
|
57385
|
-
`OPA HTTP evaluator: url must not point to internal, loopback, or private network addresses`
|
|
57386
|
-
);
|
|
57387
|
-
}
|
|
57388
|
-
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
57389
|
-
this.timeout = timeout;
|
|
57390
|
-
}
|
|
57391
|
-
/**
|
|
57392
|
-
* Check if a hostname is blocked due to SSRF concerns.
|
|
57393
|
-
*
|
|
57394
|
-
* Blocks:
|
|
57395
|
-
* - Loopback addresses (127.x.x.x, localhost, 0.0.0.0, ::1)
|
|
57396
|
-
* - Link-local addresses (169.254.x.x)
|
|
57397
|
-
* - Private networks (10.x.x.x, 172.16-31.x.x, 192.168.x.x)
|
|
57398
|
-
* - IPv6 unique local addresses (fd00::/8)
|
|
57399
|
-
* - Cloud metadata services (*.internal)
|
|
57400
|
-
*/
|
|
57401
|
-
isBlockedHostname(hostname) {
|
|
57402
|
-
if (!hostname) return true;
|
|
57403
|
-
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
57404
|
-
if (normalized === "metadata.google.internal" || normalized.endsWith(".internal")) {
|
|
57405
|
-
return true;
|
|
57406
|
-
}
|
|
57407
|
-
if (normalized === "localhost" || normalized === "localhost.localdomain") {
|
|
57408
|
-
return true;
|
|
57409
|
-
}
|
|
57410
|
-
if (normalized === "::1" || normalized === "0:0:0:0:0:0:0:1") {
|
|
57411
|
-
return true;
|
|
57412
|
-
}
|
|
57413
|
-
const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
57414
|
-
const ipv4Match = normalized.match(ipv4Pattern);
|
|
57415
|
-
if (ipv4Match) {
|
|
57416
|
-
const octets = ipv4Match.slice(1, 5).map(Number);
|
|
57417
|
-
if (octets.some((octet) => octet > 255)) {
|
|
57418
|
-
return false;
|
|
57419
|
-
}
|
|
57420
|
-
const [a, b] = octets;
|
|
57421
|
-
if (a === 127) {
|
|
57422
|
-
return true;
|
|
57423
|
-
}
|
|
57424
|
-
if (a === 0) {
|
|
57425
|
-
return true;
|
|
57426
|
-
}
|
|
57427
|
-
if (a === 169 && b === 254) {
|
|
57428
|
-
return true;
|
|
57429
|
-
}
|
|
57430
|
-
if (a === 10) {
|
|
57431
|
-
return true;
|
|
57432
|
-
}
|
|
57433
|
-
if (a === 172 && b >= 16 && b <= 31) {
|
|
57434
|
-
return true;
|
|
57435
|
-
}
|
|
57436
|
-
if (a === 192 && b === 168) {
|
|
57437
|
-
return true;
|
|
57438
|
-
}
|
|
57439
|
-
}
|
|
57440
|
-
if (normalized.startsWith("fd") || normalized.startsWith("fc")) {
|
|
57441
|
-
return true;
|
|
57442
|
-
}
|
|
57443
|
-
if (normalized.startsWith("fe80:")) {
|
|
57444
|
-
return true;
|
|
57445
|
-
}
|
|
57446
|
-
return false;
|
|
57447
|
-
}
|
|
57448
|
-
/**
|
|
57449
|
-
* Evaluate a policy rule against an input document via OPA REST API.
|
|
57450
|
-
*
|
|
57451
|
-
* @param input - The input document to evaluate
|
|
57452
|
-
* @param rulePath - OPA rule path (e.g., 'visor/check/execute')
|
|
57453
|
-
* @returns The result object from OPA, or undefined on error
|
|
57454
|
-
*/
|
|
57455
|
-
async evaluate(input, rulePath) {
|
|
57456
|
-
const encodedPath = rulePath.split("/").map((s) => encodeURIComponent(s)).join("/");
|
|
57457
|
-
const url = `${this.baseUrl}/v1/data/${encodedPath}`;
|
|
57458
|
-
const controller = new AbortController();
|
|
57459
|
-
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
57460
|
-
try {
|
|
57461
|
-
const response = await fetch(url, {
|
|
57462
|
-
method: "POST",
|
|
57463
|
-
headers: { "Content-Type": "application/json" },
|
|
57464
|
-
body: JSON.stringify({ input }),
|
|
57465
|
-
signal: controller.signal
|
|
57466
|
-
});
|
|
57467
|
-
if (!response.ok) {
|
|
57468
|
-
throw new Error(`OPA HTTP ${response.status}: ${response.statusText}`);
|
|
57469
|
-
}
|
|
57470
|
-
let body;
|
|
57471
|
-
try {
|
|
57472
|
-
body = await response.json();
|
|
57473
|
-
} catch (jsonErr) {
|
|
57474
|
-
throw new Error(
|
|
57475
|
-
`OPA HTTP evaluator: failed to parse JSON response: ${jsonErr instanceof Error ? jsonErr.message : String(jsonErr)}`
|
|
57476
|
-
);
|
|
57477
|
-
}
|
|
57478
|
-
return body?.result;
|
|
57479
|
-
} finally {
|
|
57480
|
-
clearTimeout(timer);
|
|
57481
|
-
}
|
|
57482
|
-
}
|
|
57483
|
-
async shutdown() {
|
|
57484
|
-
}
|
|
57485
|
-
};
|
|
57486
|
-
}
|
|
57487
|
-
});
|
|
57488
|
-
|
|
57489
|
-
// src/enterprise/policy/policy-input-builder.ts
|
|
57490
|
-
var PolicyInputBuilder;
|
|
57491
|
-
var init_policy_input_builder = __esm({
|
|
57492
|
-
"src/enterprise/policy/policy-input-builder.ts"() {
|
|
57493
|
-
"use strict";
|
|
57494
|
-
PolicyInputBuilder = class {
|
|
57495
|
-
roles;
|
|
57496
|
-
actor;
|
|
57497
|
-
repository;
|
|
57498
|
-
pullRequest;
|
|
57499
|
-
constructor(policyConfig, actor, repository, pullRequest) {
|
|
57500
|
-
this.roles = policyConfig.roles || {};
|
|
57501
|
-
this.actor = actor;
|
|
57502
|
-
this.repository = repository;
|
|
57503
|
-
this.pullRequest = pullRequest;
|
|
57504
|
-
}
|
|
57505
|
-
/** Resolve which roles apply to the current actor. */
|
|
57506
|
-
resolveRoles() {
|
|
57507
|
-
const matched = [];
|
|
57508
|
-
for (const [roleName, roleConfig] of Object.entries(this.roles)) {
|
|
57509
|
-
let identityMatch = false;
|
|
57510
|
-
if (roleConfig.author_association && this.actor.authorAssociation && roleConfig.author_association.includes(this.actor.authorAssociation)) {
|
|
57511
|
-
identityMatch = true;
|
|
57512
|
-
}
|
|
57513
|
-
if (!identityMatch && roleConfig.users && this.actor.login && roleConfig.users.includes(this.actor.login)) {
|
|
57514
|
-
identityMatch = true;
|
|
57515
|
-
}
|
|
57516
|
-
if (!identityMatch && roleConfig.slack_users && this.actor.slack?.userId && roleConfig.slack_users.includes(this.actor.slack.userId)) {
|
|
57517
|
-
identityMatch = true;
|
|
57518
|
-
}
|
|
57519
|
-
if (!identityMatch && roleConfig.emails && this.actor.slack?.email) {
|
|
57520
|
-
const actorEmail = this.actor.slack.email.toLowerCase();
|
|
57521
|
-
if (roleConfig.emails.some((e) => e.toLowerCase() === actorEmail)) {
|
|
57522
|
-
identityMatch = true;
|
|
57523
|
-
}
|
|
57524
|
-
}
|
|
57525
|
-
if (!identityMatch) continue;
|
|
57526
|
-
if (roleConfig.slack_channels && roleConfig.slack_channels.length > 0) {
|
|
57527
|
-
if (!this.actor.slack?.channelId || !roleConfig.slack_channels.includes(this.actor.slack.channelId)) {
|
|
57528
|
-
continue;
|
|
57529
|
-
}
|
|
57530
|
-
}
|
|
57531
|
-
matched.push(roleName);
|
|
57532
|
-
}
|
|
57533
|
-
return matched;
|
|
57534
|
-
}
|
|
57535
|
-
buildActor() {
|
|
57536
|
-
return {
|
|
57537
|
-
authorAssociation: this.actor.authorAssociation,
|
|
57538
|
-
login: this.actor.login,
|
|
57539
|
-
roles: this.resolveRoles(),
|
|
57540
|
-
isLocalMode: this.actor.isLocalMode,
|
|
57541
|
-
...this.actor.slack && { slack: this.actor.slack }
|
|
57542
|
-
};
|
|
57543
|
-
}
|
|
57544
|
-
forCheckExecution(check) {
|
|
57545
|
-
return {
|
|
57546
|
-
scope: "check.execute",
|
|
57547
|
-
check: {
|
|
57548
|
-
id: check.id,
|
|
57549
|
-
type: check.type,
|
|
57550
|
-
group: check.group,
|
|
57551
|
-
tags: check.tags,
|
|
57552
|
-
criticality: check.criticality,
|
|
57553
|
-
sandbox: check.sandbox,
|
|
57554
|
-
policy: check.policy
|
|
57555
|
-
},
|
|
57556
|
-
actor: this.buildActor(),
|
|
57557
|
-
repository: this.repository,
|
|
57558
|
-
pullRequest: this.pullRequest
|
|
57559
|
-
};
|
|
57560
|
-
}
|
|
57561
|
-
forToolInvocation(serverName, methodName, transport) {
|
|
57562
|
-
return {
|
|
57563
|
-
scope: "tool.invoke",
|
|
57564
|
-
tool: { serverName, methodName, transport },
|
|
57565
|
-
actor: this.buildActor(),
|
|
57566
|
-
repository: this.repository,
|
|
57567
|
-
pullRequest: this.pullRequest
|
|
57568
|
-
};
|
|
57569
|
-
}
|
|
57570
|
-
forCapabilityResolve(checkId, capabilities) {
|
|
57571
|
-
return {
|
|
57572
|
-
scope: "capability.resolve",
|
|
57573
|
-
check: { id: checkId, type: "ai" },
|
|
57574
|
-
capability: capabilities,
|
|
57575
|
-
actor: this.buildActor(),
|
|
57576
|
-
repository: this.repository,
|
|
57577
|
-
pullRequest: this.pullRequest
|
|
57578
|
-
};
|
|
57579
|
-
}
|
|
57580
|
-
};
|
|
57581
|
-
}
|
|
57582
|
-
});
|
|
57583
|
-
|
|
57584
|
-
// src/enterprise/policy/opa-policy-engine.ts
|
|
57585
|
-
var opa_policy_engine_exports = {};
|
|
57586
|
-
__export(opa_policy_engine_exports, {
|
|
57587
|
-
OpaPolicyEngine: () => OpaPolicyEngine
|
|
57588
|
-
});
|
|
57589
|
-
var OpaPolicyEngine;
|
|
57590
|
-
var init_opa_policy_engine = __esm({
|
|
57591
|
-
"src/enterprise/policy/opa-policy-engine.ts"() {
|
|
57592
|
-
"use strict";
|
|
57593
|
-
init_opa_wasm_evaluator();
|
|
57594
|
-
init_opa_http_evaluator();
|
|
57595
|
-
init_policy_input_builder();
|
|
57596
|
-
OpaPolicyEngine = class {
|
|
57597
|
-
evaluator = null;
|
|
57598
|
-
fallback;
|
|
57599
|
-
timeout;
|
|
57600
|
-
config;
|
|
57601
|
-
inputBuilder = null;
|
|
57602
|
-
logger = null;
|
|
57603
|
-
constructor(config) {
|
|
57604
|
-
this.config = config;
|
|
57605
|
-
this.fallback = config.fallback || "deny";
|
|
57606
|
-
this.timeout = config.timeout || 5e3;
|
|
57607
|
-
}
|
|
57608
|
-
async initialize(config) {
|
|
57609
|
-
try {
|
|
57610
|
-
this.logger = (init_logger(), __toCommonJS(logger_exports)).logger;
|
|
57611
|
-
} catch {
|
|
57612
|
-
}
|
|
57613
|
-
const actor = {
|
|
57614
|
-
authorAssociation: process.env.VISOR_AUTHOR_ASSOCIATION,
|
|
57615
|
-
login: process.env.VISOR_AUTHOR_LOGIN || process.env.GITHUB_ACTOR,
|
|
57616
|
-
isLocalMode: !process.env.GITHUB_ACTIONS
|
|
57617
|
-
};
|
|
57618
|
-
const repo = {
|
|
57619
|
-
owner: process.env.GITHUB_REPOSITORY_OWNER,
|
|
57620
|
-
name: process.env.GITHUB_REPOSITORY?.split("/")[1],
|
|
57621
|
-
branch: process.env.GITHUB_HEAD_REF,
|
|
57622
|
-
baseBranch: process.env.GITHUB_BASE_REF,
|
|
57623
|
-
event: process.env.GITHUB_EVENT_NAME
|
|
57624
|
-
};
|
|
57625
|
-
const prNum = process.env.GITHUB_PR_NUMBER ? parseInt(process.env.GITHUB_PR_NUMBER, 10) : void 0;
|
|
57626
|
-
const pullRequest = {
|
|
57627
|
-
number: prNum !== void 0 && Number.isFinite(prNum) ? prNum : void 0
|
|
57628
|
-
};
|
|
57629
|
-
this.inputBuilder = new PolicyInputBuilder(config, actor, repo, pullRequest);
|
|
57630
|
-
if (config.engine === "local") {
|
|
57631
|
-
if (!config.rules) {
|
|
57632
|
-
throw new Error("OPA local mode requires `policy.rules` path to .wasm or .rego files");
|
|
57633
|
-
}
|
|
57634
|
-
const wasm = new OpaWasmEvaluator();
|
|
57635
|
-
await wasm.initialize(config.rules);
|
|
57636
|
-
if (config.data) {
|
|
57637
|
-
wasm.loadData(config.data);
|
|
57638
|
-
}
|
|
57639
|
-
this.evaluator = wasm;
|
|
57640
|
-
} else if (config.engine === "remote") {
|
|
57641
|
-
if (!config.url) {
|
|
57642
|
-
throw new Error("OPA remote mode requires `policy.url` pointing to OPA server");
|
|
57643
|
-
}
|
|
57644
|
-
this.evaluator = new OpaHttpEvaluator(config.url, this.timeout);
|
|
57645
|
-
} else {
|
|
57646
|
-
this.evaluator = null;
|
|
57647
|
-
}
|
|
57648
|
-
}
|
|
57649
|
-
/**
|
|
57650
|
-
* Update actor/repo/PR context (e.g., after PR info becomes available).
|
|
57651
|
-
* Called by the enterprise loader when engine context is enriched.
|
|
57652
|
-
*/
|
|
57653
|
-
setActorContext(actor, repo, pullRequest) {
|
|
57654
|
-
this.inputBuilder = new PolicyInputBuilder(this.config, actor, repo, pullRequest);
|
|
57655
|
-
}
|
|
57656
|
-
async evaluateCheckExecution(checkId, checkConfig) {
|
|
57657
|
-
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
57658
|
-
const cfg = checkConfig && typeof checkConfig === "object" ? checkConfig : {};
|
|
57659
|
-
const policyOverride = cfg.policy;
|
|
57660
|
-
const input = this.inputBuilder.forCheckExecution({
|
|
57661
|
-
id: checkId,
|
|
57662
|
-
type: cfg.type || "ai",
|
|
57663
|
-
group: cfg.group,
|
|
57664
|
-
tags: cfg.tags,
|
|
57665
|
-
criticality: cfg.criticality,
|
|
57666
|
-
sandbox: cfg.sandbox,
|
|
57667
|
-
policy: policyOverride
|
|
57668
|
-
});
|
|
57669
|
-
return this.doEvaluate(input, this.resolveRulePath("check.execute", policyOverride?.rule));
|
|
57670
|
-
}
|
|
57671
|
-
async evaluateToolInvocation(serverName, methodName, transport) {
|
|
57672
|
-
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
57673
|
-
const input = this.inputBuilder.forToolInvocation(serverName, methodName, transport);
|
|
57674
|
-
return this.doEvaluate(input, "visor/tool/invoke");
|
|
57675
|
-
}
|
|
57676
|
-
async evaluateCapabilities(checkId, capabilities) {
|
|
57677
|
-
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
57678
|
-
const input = this.inputBuilder.forCapabilityResolve(checkId, capabilities);
|
|
57679
|
-
return this.doEvaluate(input, "visor/capability/resolve");
|
|
57680
|
-
}
|
|
57681
|
-
async shutdown() {
|
|
57682
|
-
if (this.evaluator && "shutdown" in this.evaluator) {
|
|
57683
|
-
await this.evaluator.shutdown();
|
|
57684
|
-
}
|
|
57685
|
-
this.evaluator = null;
|
|
57686
|
-
this.inputBuilder = null;
|
|
57687
|
-
}
|
|
57688
|
-
resolveRulePath(defaultScope, override) {
|
|
57689
|
-
if (override) {
|
|
57690
|
-
return override.startsWith("visor/") ? override : `visor/${override}`;
|
|
57691
|
-
}
|
|
57692
|
-
return `visor/${defaultScope.replace(/\./g, "/")}`;
|
|
57693
|
-
}
|
|
57694
|
-
async doEvaluate(input, rulePath) {
|
|
57695
|
-
try {
|
|
57696
|
-
this.logger?.debug(`[PolicyEngine] Evaluating ${rulePath}`, JSON.stringify(input));
|
|
57697
|
-
let timer;
|
|
57698
|
-
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
57699
|
-
timer = setTimeout(() => reject(new Error("policy evaluation timeout")), this.timeout);
|
|
57700
|
-
});
|
|
57701
|
-
try {
|
|
57702
|
-
const result = await Promise.race([this.rawEvaluate(input, rulePath), timeoutPromise]);
|
|
57703
|
-
const decision = this.parseDecision(result);
|
|
57704
|
-
if (!decision.allowed && this.fallback === "warn") {
|
|
57705
|
-
decision.allowed = true;
|
|
57706
|
-
decision.warn = true;
|
|
57707
|
-
decision.reason = `audit: ${decision.reason || "policy denied"}`;
|
|
57708
|
-
}
|
|
57709
|
-
this.logger?.debug(
|
|
57710
|
-
`[PolicyEngine] Decision for ${rulePath}: allowed=${decision.allowed}, warn=${decision.warn || false}, reason=${decision.reason || "none"}`
|
|
57711
|
-
);
|
|
57712
|
-
return decision;
|
|
57713
|
-
} finally {
|
|
57714
|
-
if (timer) clearTimeout(timer);
|
|
57715
|
-
}
|
|
57716
|
-
} catch (err) {
|
|
57717
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
57718
|
-
this.logger?.warn(`[PolicyEngine] Evaluation failed for ${rulePath}: ${msg}`);
|
|
57719
|
-
return {
|
|
57720
|
-
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
57721
|
-
warn: this.fallback === "warn" ? true : void 0,
|
|
57722
|
-
reason: `policy evaluation failed, fallback=${this.fallback}`
|
|
57723
|
-
};
|
|
57724
|
-
}
|
|
57725
|
-
}
|
|
57726
|
-
async rawEvaluate(input, rulePath) {
|
|
57727
|
-
if (this.evaluator instanceof OpaWasmEvaluator) {
|
|
57728
|
-
const result = await this.evaluator.evaluate(input);
|
|
57729
|
-
return this.navigateWasmResult(result, rulePath);
|
|
57730
|
-
}
|
|
57731
|
-
return this.evaluator.evaluate(input, rulePath);
|
|
57732
|
-
}
|
|
57733
|
-
/**
|
|
57734
|
-
* Navigate nested OPA WASM result tree to reach the specific rule's output.
|
|
57735
|
-
* The WASM entrypoint `-e visor` means the result root IS the visor package,
|
|
57736
|
-
* so we strip the `visor/` prefix and walk the remaining segments.
|
|
57737
|
-
*/
|
|
57738
|
-
navigateWasmResult(result, rulePath) {
|
|
57739
|
-
if (!result || typeof result !== "object") return result;
|
|
57740
|
-
const segments = rulePath.replace(/^visor\//, "").split("/");
|
|
57741
|
-
let current = result;
|
|
57742
|
-
for (const seg of segments) {
|
|
57743
|
-
if (current && typeof current === "object" && seg in current) {
|
|
57744
|
-
current = current[seg];
|
|
57745
|
-
} else {
|
|
57746
|
-
return void 0;
|
|
57747
|
-
}
|
|
57748
|
-
}
|
|
57749
|
-
return current;
|
|
57750
|
-
}
|
|
57751
|
-
parseDecision(result) {
|
|
57752
|
-
if (result === void 0 || result === null) {
|
|
57753
|
-
return {
|
|
57754
|
-
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
57755
|
-
warn: this.fallback === "warn" ? true : void 0,
|
|
57756
|
-
reason: this.fallback === "warn" ? "audit: no policy result" : "no policy result"
|
|
57757
|
-
};
|
|
57758
|
-
}
|
|
57759
|
-
const allowed = result.allowed !== false;
|
|
57760
|
-
const decision = {
|
|
57761
|
-
allowed,
|
|
57762
|
-
reason: result.reason
|
|
57763
|
-
};
|
|
57764
|
-
if (result.capabilities) {
|
|
57765
|
-
decision.capabilities = result.capabilities;
|
|
57766
|
-
}
|
|
57767
|
-
return decision;
|
|
57768
|
-
}
|
|
57769
|
-
};
|
|
57770
|
-
}
|
|
57771
|
-
});
|
|
57772
|
-
|
|
57773
|
-
// src/enterprise/scheduler/knex-store.ts
|
|
57774
|
-
var knex_store_exports = {};
|
|
57775
|
-
__export(knex_store_exports, {
|
|
57776
|
-
KnexStoreBackend: () => KnexStoreBackend
|
|
57777
|
-
});
|
|
57778
|
-
function toNum(val) {
|
|
57779
|
-
if (val === null || val === void 0) return void 0;
|
|
57780
|
-
return typeof val === "string" ? parseInt(val, 10) : val;
|
|
57781
|
-
}
|
|
57782
|
-
function safeJsonParse2(value) {
|
|
57783
|
-
if (!value) return void 0;
|
|
57784
|
-
try {
|
|
57785
|
-
return JSON.parse(value);
|
|
57786
|
-
} catch {
|
|
57787
|
-
return void 0;
|
|
57788
|
-
}
|
|
57789
|
-
}
|
|
57790
|
-
function fromTriggerRow2(row) {
|
|
57791
|
-
return {
|
|
57792
|
-
id: row.id,
|
|
57793
|
-
creatorId: row.creator_id,
|
|
57794
|
-
creatorContext: row.creator_context ?? void 0,
|
|
57795
|
-
creatorName: row.creator_name ?? void 0,
|
|
57796
|
-
description: row.description ?? void 0,
|
|
57797
|
-
channels: safeJsonParse2(row.channels),
|
|
57798
|
-
fromUsers: safeJsonParse2(row.from_users),
|
|
57799
|
-
fromBots: row.from_bots === true || row.from_bots === 1,
|
|
57800
|
-
contains: safeJsonParse2(row.contains),
|
|
57801
|
-
matchPattern: row.match_pattern ?? void 0,
|
|
57802
|
-
threads: row.threads,
|
|
57803
|
-
workflow: row.workflow,
|
|
57804
|
-
inputs: safeJsonParse2(row.inputs),
|
|
57805
|
-
outputContext: safeJsonParse2(row.output_context),
|
|
57806
|
-
status: row.status,
|
|
57807
|
-
enabled: row.enabled === true || row.enabled === 1,
|
|
57808
|
-
createdAt: toNum(row.created_at)
|
|
57809
|
-
};
|
|
57810
|
-
}
|
|
57811
|
-
function toTriggerInsertRow(trigger) {
|
|
57812
|
-
return {
|
|
57813
|
-
id: trigger.id,
|
|
57814
|
-
creator_id: trigger.creatorId,
|
|
57815
|
-
creator_context: trigger.creatorContext ?? null,
|
|
57816
|
-
creator_name: trigger.creatorName ?? null,
|
|
57817
|
-
description: trigger.description ?? null,
|
|
57818
|
-
channels: trigger.channels ? JSON.stringify(trigger.channels) : null,
|
|
57819
|
-
from_users: trigger.fromUsers ? JSON.stringify(trigger.fromUsers) : null,
|
|
57820
|
-
from_bots: trigger.fromBots,
|
|
57821
|
-
contains: trigger.contains ? JSON.stringify(trigger.contains) : null,
|
|
57822
|
-
match_pattern: trigger.matchPattern ?? null,
|
|
57823
|
-
threads: trigger.threads,
|
|
57824
|
-
workflow: trigger.workflow,
|
|
57825
|
-
inputs: trigger.inputs ? JSON.stringify(trigger.inputs) : null,
|
|
57826
|
-
output_context: trigger.outputContext ? JSON.stringify(trigger.outputContext) : null,
|
|
57827
|
-
status: trigger.status,
|
|
57828
|
-
enabled: trigger.enabled,
|
|
57829
|
-
created_at: trigger.createdAt
|
|
57830
|
-
};
|
|
57831
|
-
}
|
|
57832
|
-
function fromDbRow2(row) {
|
|
57833
|
-
return {
|
|
57834
|
-
id: row.id,
|
|
57835
|
-
creatorId: row.creator_id,
|
|
57836
|
-
creatorContext: row.creator_context ?? void 0,
|
|
57837
|
-
creatorName: row.creator_name ?? void 0,
|
|
57838
|
-
timezone: row.timezone,
|
|
57839
|
-
schedule: row.schedule_expr,
|
|
57840
|
-
runAt: toNum(row.run_at),
|
|
57841
|
-
isRecurring: row.is_recurring === true || row.is_recurring === 1,
|
|
57842
|
-
originalExpression: row.original_expression,
|
|
57843
|
-
workflow: row.workflow ?? void 0,
|
|
57844
|
-
workflowInputs: safeJsonParse2(row.workflow_inputs),
|
|
57845
|
-
outputContext: safeJsonParse2(row.output_context),
|
|
57846
|
-
status: row.status,
|
|
57847
|
-
createdAt: toNum(row.created_at),
|
|
57848
|
-
lastRunAt: toNum(row.last_run_at),
|
|
57849
|
-
nextRunAt: toNum(row.next_run_at),
|
|
57850
|
-
runCount: row.run_count,
|
|
57851
|
-
failureCount: row.failure_count,
|
|
57852
|
-
lastError: row.last_error ?? void 0,
|
|
57853
|
-
previousResponse: row.previous_response ?? void 0
|
|
57854
|
-
};
|
|
57855
|
-
}
|
|
57856
|
-
function toInsertRow(schedule) {
|
|
57857
|
-
return {
|
|
57858
|
-
id: schedule.id,
|
|
57859
|
-
creator_id: schedule.creatorId,
|
|
57860
|
-
creator_context: schedule.creatorContext ?? null,
|
|
57861
|
-
creator_name: schedule.creatorName ?? null,
|
|
57862
|
-
timezone: schedule.timezone,
|
|
57863
|
-
schedule_expr: schedule.schedule,
|
|
57864
|
-
run_at: schedule.runAt ?? null,
|
|
57865
|
-
is_recurring: schedule.isRecurring,
|
|
57866
|
-
original_expression: schedule.originalExpression,
|
|
57867
|
-
workflow: schedule.workflow ?? null,
|
|
57868
|
-
workflow_inputs: schedule.workflowInputs ? JSON.stringify(schedule.workflowInputs) : null,
|
|
57869
|
-
output_context: schedule.outputContext ? JSON.stringify(schedule.outputContext) : null,
|
|
57870
|
-
status: schedule.status,
|
|
57871
|
-
created_at: schedule.createdAt,
|
|
57872
|
-
last_run_at: schedule.lastRunAt ?? null,
|
|
57873
|
-
next_run_at: schedule.nextRunAt ?? null,
|
|
57874
|
-
run_count: schedule.runCount,
|
|
57875
|
-
failure_count: schedule.failureCount,
|
|
57876
|
-
last_error: schedule.lastError ?? null,
|
|
57877
|
-
previous_response: schedule.previousResponse ?? null
|
|
57878
|
-
};
|
|
57879
|
-
}
|
|
57880
|
-
var fs24, path29, import_uuid2, KnexStoreBackend;
|
|
57881
|
-
var init_knex_store = __esm({
|
|
57882
|
-
"src/enterprise/scheduler/knex-store.ts"() {
|
|
57883
|
-
"use strict";
|
|
57884
|
-
fs24 = __toESM(require("fs"));
|
|
57885
|
-
path29 = __toESM(require("path"));
|
|
57886
|
-
import_uuid2 = require("uuid");
|
|
57887
|
-
init_logger();
|
|
57888
|
-
KnexStoreBackend = class {
|
|
57889
|
-
knex = null;
|
|
57890
|
-
driver;
|
|
57891
|
-
connection;
|
|
57892
|
-
constructor(driver, storageConfig, _haConfig) {
|
|
57893
|
-
this.driver = driver;
|
|
57894
|
-
this.connection = storageConfig.connection || {};
|
|
57895
|
-
}
|
|
57896
|
-
async initialize() {
|
|
57897
|
-
const { createRequire } = require("module");
|
|
57898
|
-
const runtimeRequire = createRequire(__filename);
|
|
57899
|
-
let knexFactory;
|
|
57900
|
-
try {
|
|
57901
|
-
knexFactory = runtimeRequire("knex");
|
|
57902
|
-
} catch (err) {
|
|
57903
|
-
const code = err?.code;
|
|
57904
|
-
if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
|
|
57905
|
-
throw new Error(
|
|
57906
|
-
"knex is required for PostgreSQL/MySQL/MSSQL schedule storage. Install it with: npm install knex"
|
|
57907
|
-
);
|
|
57908
|
-
}
|
|
57909
|
-
throw err;
|
|
57910
|
-
}
|
|
57911
|
-
const clientMap = {
|
|
57912
|
-
postgresql: "pg",
|
|
57913
|
-
mysql: "mysql2",
|
|
57914
|
-
mssql: "tedious"
|
|
57915
|
-
};
|
|
57916
|
-
const client = clientMap[this.driver];
|
|
57917
|
-
let connection;
|
|
57918
|
-
if (this.connection.connection_string) {
|
|
57919
|
-
connection = this.connection.connection_string;
|
|
57920
|
-
} else if (this.driver === "mssql") {
|
|
57921
|
-
connection = this.buildMssqlConnection();
|
|
57922
|
-
} else {
|
|
57923
|
-
connection = this.buildStandardConnection();
|
|
57924
|
-
}
|
|
57925
|
-
this.knex = knexFactory({
|
|
57926
|
-
client,
|
|
57927
|
-
connection,
|
|
57928
|
-
pool: {
|
|
57929
|
-
min: this.connection.pool?.min ?? 0,
|
|
57930
|
-
max: this.connection.pool?.max ?? 10
|
|
57931
|
-
}
|
|
57932
|
-
});
|
|
57933
|
-
await this.migrateSchema();
|
|
57934
|
-
logger.info(`[KnexStore] Initialized (${this.driver})`);
|
|
57935
|
-
}
|
|
57936
|
-
buildStandardConnection() {
|
|
57937
|
-
return {
|
|
57938
|
-
host: this.connection.host || "localhost",
|
|
57939
|
-
port: this.connection.port,
|
|
57940
|
-
database: this.connection.database || "visor",
|
|
57941
|
-
user: this.connection.user,
|
|
57942
|
-
password: this.connection.password,
|
|
57943
|
-
ssl: this.resolveSslConfig()
|
|
57944
|
-
};
|
|
57945
|
-
}
|
|
57946
|
-
buildMssqlConnection() {
|
|
57947
|
-
const ssl = this.connection.ssl;
|
|
57948
|
-
const sslEnabled = ssl === true || typeof ssl === "object" && ssl.enabled !== false;
|
|
57949
|
-
return {
|
|
57950
|
-
server: this.connection.host || "localhost",
|
|
57951
|
-
port: this.connection.port,
|
|
57952
|
-
database: this.connection.database || "visor",
|
|
57953
|
-
user: this.connection.user,
|
|
57954
|
-
password: this.connection.password,
|
|
57955
|
-
options: {
|
|
57956
|
-
encrypt: sslEnabled,
|
|
57957
|
-
trustServerCertificate: typeof ssl === "object" ? ssl.reject_unauthorized === false : !sslEnabled
|
|
57958
|
-
}
|
|
57959
|
-
};
|
|
57960
|
-
}
|
|
57961
|
-
resolveSslConfig() {
|
|
57962
|
-
const ssl = this.connection.ssl;
|
|
57963
|
-
if (ssl === false || ssl === void 0) return false;
|
|
57964
|
-
if (ssl === true) return { rejectUnauthorized: true };
|
|
57965
|
-
if (ssl.enabled === false) return false;
|
|
57966
|
-
const result = {
|
|
57967
|
-
rejectUnauthorized: ssl.reject_unauthorized !== false
|
|
57968
|
-
};
|
|
57969
|
-
if (ssl.ca) {
|
|
57970
|
-
const caPath = this.validateSslPath(ssl.ca, "CA certificate");
|
|
57971
|
-
result.ca = fs24.readFileSync(caPath, "utf8");
|
|
57972
|
-
}
|
|
57973
|
-
if (ssl.cert) {
|
|
57974
|
-
const certPath = this.validateSslPath(ssl.cert, "client certificate");
|
|
57975
|
-
result.cert = fs24.readFileSync(certPath, "utf8");
|
|
57976
|
-
}
|
|
57977
|
-
if (ssl.key) {
|
|
57978
|
-
const keyPath = this.validateSslPath(ssl.key, "client key");
|
|
57979
|
-
result.key = fs24.readFileSync(keyPath, "utf8");
|
|
57980
|
-
}
|
|
57981
|
-
return result;
|
|
57982
|
-
}
|
|
57983
|
-
validateSslPath(filePath, label) {
|
|
57984
|
-
const resolved = path29.resolve(filePath);
|
|
57985
|
-
if (resolved !== path29.normalize(resolved)) {
|
|
57986
|
-
throw new Error(`SSL ${label} path contains invalid sequences: ${filePath}`);
|
|
57987
|
-
}
|
|
57988
|
-
if (!fs24.existsSync(resolved)) {
|
|
57989
|
-
throw new Error(`SSL ${label} not found: ${filePath}`);
|
|
57990
|
-
}
|
|
57991
|
-
return resolved;
|
|
57992
|
-
}
|
|
57993
|
-
async shutdown() {
|
|
57994
|
-
if (this.knex) {
|
|
57995
|
-
await this.knex.destroy();
|
|
57996
|
-
this.knex = null;
|
|
57997
|
-
}
|
|
57998
|
-
}
|
|
57999
|
-
async migrateSchema() {
|
|
58000
|
-
const knex = this.getKnex();
|
|
58001
|
-
const exists = await knex.schema.hasTable("schedules");
|
|
58002
|
-
if (!exists) {
|
|
58003
|
-
await knex.schema.createTable("schedules", (table) => {
|
|
58004
|
-
table.string("id", 36).primary();
|
|
58005
|
-
table.string("creator_id", 255).notNullable().index();
|
|
58006
|
-
table.string("creator_context", 255);
|
|
58007
|
-
table.string("creator_name", 255);
|
|
58008
|
-
table.string("timezone", 64).notNullable().defaultTo("UTC");
|
|
58009
|
-
table.string("schedule_expr", 255);
|
|
58010
|
-
table.bigInteger("run_at");
|
|
58011
|
-
table.boolean("is_recurring").notNullable();
|
|
58012
|
-
table.text("original_expression");
|
|
58013
|
-
table.string("workflow", 255);
|
|
58014
|
-
table.text("workflow_inputs");
|
|
58015
|
-
table.text("output_context");
|
|
58016
|
-
table.string("status", 20).notNullable().index();
|
|
58017
|
-
table.bigInteger("created_at").notNullable();
|
|
58018
|
-
table.bigInteger("last_run_at");
|
|
58019
|
-
table.bigInteger("next_run_at");
|
|
58020
|
-
table.integer("run_count").notNullable().defaultTo(0);
|
|
58021
|
-
table.integer("failure_count").notNullable().defaultTo(0);
|
|
58022
|
-
table.text("last_error");
|
|
58023
|
-
table.text("previous_response");
|
|
58024
|
-
table.index(["status", "next_run_at"]);
|
|
58025
|
-
});
|
|
58026
|
-
}
|
|
58027
|
-
const triggersExist = await knex.schema.hasTable("message_triggers");
|
|
58028
|
-
if (!triggersExist) {
|
|
58029
|
-
await knex.schema.createTable("message_triggers", (table) => {
|
|
58030
|
-
table.string("id", 36).primary();
|
|
58031
|
-
table.string("creator_id", 255).notNullable().index();
|
|
58032
|
-
table.string("creator_context", 255);
|
|
58033
|
-
table.string("creator_name", 255);
|
|
58034
|
-
table.text("description");
|
|
58035
|
-
table.text("channels");
|
|
58036
|
-
table.text("from_users");
|
|
58037
|
-
table.boolean("from_bots").notNullable().defaultTo(false);
|
|
58038
|
-
table.text("contains");
|
|
58039
|
-
table.text("match_pattern");
|
|
58040
|
-
table.string("threads", 20).notNullable().defaultTo("any");
|
|
58041
|
-
table.string("workflow", 255).notNullable();
|
|
58042
|
-
table.text("inputs");
|
|
58043
|
-
table.text("output_context");
|
|
58044
|
-
table.string("status", 20).notNullable().defaultTo("active").index();
|
|
58045
|
-
table.boolean("enabled").notNullable().defaultTo(true);
|
|
58046
|
-
table.bigInteger("created_at").notNullable();
|
|
58047
|
-
});
|
|
58048
|
-
}
|
|
58049
|
-
const locksExist = await knex.schema.hasTable("scheduler_locks");
|
|
58050
|
-
if (!locksExist) {
|
|
58051
|
-
await knex.schema.createTable("scheduler_locks", (table) => {
|
|
58052
|
-
table.string("lock_id", 255).primary();
|
|
58053
|
-
table.string("node_id", 255).notNullable();
|
|
58054
|
-
table.string("lock_token", 36).notNullable();
|
|
58055
|
-
table.bigInteger("acquired_at").notNullable();
|
|
58056
|
-
table.bigInteger("expires_at").notNullable();
|
|
58057
|
-
});
|
|
58058
|
-
}
|
|
58059
|
-
}
|
|
58060
|
-
getKnex() {
|
|
58061
|
-
if (!this.knex) {
|
|
58062
|
-
throw new Error("[KnexStore] Not initialized. Call initialize() first.");
|
|
58063
|
-
}
|
|
58064
|
-
return this.knex;
|
|
58065
|
-
}
|
|
58066
|
-
// --- CRUD ---
|
|
58067
|
-
async create(schedule) {
|
|
58068
|
-
const knex = this.getKnex();
|
|
58069
|
-
const newSchedule = {
|
|
58070
|
-
...schedule,
|
|
58071
|
-
id: (0, import_uuid2.v4)(),
|
|
58072
|
-
createdAt: Date.now(),
|
|
58073
|
-
runCount: 0,
|
|
58074
|
-
failureCount: 0,
|
|
58075
|
-
status: "active"
|
|
58076
|
-
};
|
|
58077
|
-
await knex("schedules").insert(toInsertRow(newSchedule));
|
|
58078
|
-
logger.info(`[KnexStore] Created schedule ${newSchedule.id} for user ${newSchedule.creatorId}`);
|
|
58079
|
-
return newSchedule;
|
|
58080
|
-
}
|
|
58081
|
-
async importSchedule(schedule) {
|
|
58082
|
-
const knex = this.getKnex();
|
|
58083
|
-
const existing = await knex("schedules").where("id", schedule.id).first();
|
|
58084
|
-
if (existing) return;
|
|
58085
|
-
await knex("schedules").insert(toInsertRow(schedule));
|
|
58086
|
-
}
|
|
58087
|
-
async get(id) {
|
|
58088
|
-
const knex = this.getKnex();
|
|
58089
|
-
const row = await knex("schedules").where("id", id).first();
|
|
58090
|
-
return row ? fromDbRow2(row) : void 0;
|
|
58091
|
-
}
|
|
58092
|
-
async update(id, patch) {
|
|
58093
|
-
const knex = this.getKnex();
|
|
58094
|
-
const existing = await knex("schedules").where("id", id).first();
|
|
58095
|
-
if (!existing) return void 0;
|
|
58096
|
-
const current = fromDbRow2(existing);
|
|
58097
|
-
const updated = { ...current, ...patch, id: current.id };
|
|
58098
|
-
const row = toInsertRow(updated);
|
|
58099
|
-
delete row.id;
|
|
58100
|
-
await knex("schedules").where("id", id).update(row);
|
|
58101
|
-
return updated;
|
|
58102
|
-
}
|
|
58103
|
-
async delete(id) {
|
|
58104
|
-
const knex = this.getKnex();
|
|
58105
|
-
const deleted = await knex("schedules").where("id", id).del();
|
|
58106
|
-
if (deleted > 0) {
|
|
58107
|
-
logger.info(`[KnexStore] Deleted schedule ${id}`);
|
|
58108
|
-
return true;
|
|
58109
|
-
}
|
|
58110
|
-
return false;
|
|
58111
|
-
}
|
|
58112
|
-
// --- Queries ---
|
|
58113
|
-
async getByCreator(creatorId) {
|
|
58114
|
-
const knex = this.getKnex();
|
|
58115
|
-
const rows = await knex("schedules").where("creator_id", creatorId);
|
|
58116
|
-
return rows.map((r) => fromDbRow2(r));
|
|
58117
|
-
}
|
|
58118
|
-
async getActiveSchedules() {
|
|
58119
|
-
const knex = this.getKnex();
|
|
58120
|
-
const rows = await knex("schedules").where("status", "active");
|
|
58121
|
-
return rows.map((r) => fromDbRow2(r));
|
|
58122
|
-
}
|
|
58123
|
-
async getDueSchedules(now) {
|
|
58124
|
-
const ts = now ?? Date.now();
|
|
58125
|
-
const knex = this.getKnex();
|
|
58126
|
-
const bFalse = this.driver === "mssql" ? 0 : false;
|
|
58127
|
-
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
58128
|
-
const rows = await knex("schedules").where("status", "active").andWhere(function() {
|
|
58129
|
-
this.where(function() {
|
|
58130
|
-
this.where("is_recurring", bFalse).whereNotNull("run_at").where("run_at", "<=", ts);
|
|
58131
|
-
}).orWhere(function() {
|
|
58132
|
-
this.where("is_recurring", bTrue).whereNotNull("next_run_at").where("next_run_at", "<=", ts);
|
|
58133
|
-
});
|
|
58134
|
-
});
|
|
58135
|
-
return rows.map((r) => fromDbRow2(r));
|
|
58136
|
-
}
|
|
58137
|
-
async findByWorkflow(creatorId, workflowName) {
|
|
58138
|
-
const knex = this.getKnex();
|
|
58139
|
-
const escaped = workflowName.toLowerCase().replace(/[%_\\]/g, "\\$&");
|
|
58140
|
-
const pattern = `%${escaped}%`;
|
|
58141
|
-
const rows = await knex("schedules").where("creator_id", creatorId).where("status", "active").whereRaw("LOWER(workflow) LIKE ? ESCAPE '\\'", [pattern]);
|
|
58142
|
-
return rows.map((r) => fromDbRow2(r));
|
|
58143
|
-
}
|
|
58144
|
-
async getAll() {
|
|
58145
|
-
const knex = this.getKnex();
|
|
58146
|
-
const rows = await knex("schedules");
|
|
58147
|
-
return rows.map((r) => fromDbRow2(r));
|
|
58148
|
-
}
|
|
58149
|
-
async getStats() {
|
|
58150
|
-
const knex = this.getKnex();
|
|
58151
|
-
const boolTrue = this.driver === "mssql" ? "1" : "true";
|
|
58152
|
-
const boolFalse = this.driver === "mssql" ? "0" : "false";
|
|
58153
|
-
const result = await knex("schedules").select(
|
|
58154
|
-
knex.raw("COUNT(*) as total"),
|
|
58155
|
-
knex.raw("SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active"),
|
|
58156
|
-
knex.raw("SUM(CASE WHEN status = 'paused' THEN 1 ELSE 0 END) as paused"),
|
|
58157
|
-
knex.raw("SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed"),
|
|
58158
|
-
knex.raw("SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed"),
|
|
58159
|
-
knex.raw(`SUM(CASE WHEN is_recurring = ${boolTrue} THEN 1 ELSE 0 END) as recurring`),
|
|
58160
|
-
knex.raw(`SUM(CASE WHEN is_recurring = ${boolFalse} THEN 1 ELSE 0 END) as one_time`)
|
|
58161
|
-
).first();
|
|
58162
|
-
return {
|
|
58163
|
-
total: Number(result.total) || 0,
|
|
58164
|
-
active: Number(result.active) || 0,
|
|
58165
|
-
paused: Number(result.paused) || 0,
|
|
58166
|
-
completed: Number(result.completed) || 0,
|
|
58167
|
-
failed: Number(result.failed) || 0,
|
|
58168
|
-
recurring: Number(result.recurring) || 0,
|
|
58169
|
-
oneTime: Number(result.one_time) || 0
|
|
58170
|
-
};
|
|
58171
|
-
}
|
|
58172
|
-
async validateLimits(creatorId, isRecurring, limits) {
|
|
58173
|
-
const knex = this.getKnex();
|
|
58174
|
-
if (limits.maxGlobal) {
|
|
58175
|
-
const result = await knex("schedules").count("* as cnt").first();
|
|
58176
|
-
if (Number(result?.cnt) >= limits.maxGlobal) {
|
|
58177
|
-
throw new Error(`Global schedule limit reached (${limits.maxGlobal})`);
|
|
58178
|
-
}
|
|
58179
|
-
}
|
|
58180
|
-
if (limits.maxPerUser) {
|
|
58181
|
-
const result = await knex("schedules").where("creator_id", creatorId).count("* as cnt").first();
|
|
58182
|
-
if (Number(result?.cnt) >= limits.maxPerUser) {
|
|
58183
|
-
throw new Error(`You have reached the maximum number of schedules (${limits.maxPerUser})`);
|
|
58184
|
-
}
|
|
58185
|
-
}
|
|
58186
|
-
if (isRecurring && limits.maxRecurringPerUser) {
|
|
58187
|
-
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
58188
|
-
const result = await knex("schedules").where("creator_id", creatorId).where("is_recurring", bTrue).count("* as cnt").first();
|
|
58189
|
-
if (Number(result?.cnt) >= limits.maxRecurringPerUser) {
|
|
58190
|
-
throw new Error(
|
|
58191
|
-
`You have reached the maximum number of recurring schedules (${limits.maxRecurringPerUser})`
|
|
58192
|
-
);
|
|
58193
|
-
}
|
|
58194
|
-
}
|
|
58195
|
-
}
|
|
58196
|
-
// --- HA Distributed Locking (via scheduler_locks table) ---
|
|
58197
|
-
async tryAcquireLock(lockId, nodeId, ttlSeconds) {
|
|
58198
|
-
const knex = this.getKnex();
|
|
58199
|
-
const now = Date.now();
|
|
58200
|
-
const expiresAt = now + ttlSeconds * 1e3;
|
|
58201
|
-
const token = (0, import_uuid2.v4)();
|
|
58202
|
-
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("expires_at", "<", now).update({
|
|
58203
|
-
node_id: nodeId,
|
|
58204
|
-
lock_token: token,
|
|
58205
|
-
acquired_at: now,
|
|
58206
|
-
expires_at: expiresAt
|
|
58207
|
-
});
|
|
58208
|
-
if (updated > 0) return token;
|
|
58209
|
-
try {
|
|
58210
|
-
await knex("scheduler_locks").insert({
|
|
58211
|
-
lock_id: lockId,
|
|
58212
|
-
node_id: nodeId,
|
|
58213
|
-
lock_token: token,
|
|
58214
|
-
acquired_at: now,
|
|
58215
|
-
expires_at: expiresAt
|
|
58216
|
-
});
|
|
58217
|
-
return token;
|
|
58218
|
-
} catch {
|
|
58219
|
-
return null;
|
|
58220
|
-
}
|
|
58221
|
-
}
|
|
58222
|
-
async releaseLock(lockId, lockToken) {
|
|
58223
|
-
const knex = this.getKnex();
|
|
58224
|
-
await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).del();
|
|
58225
|
-
}
|
|
58226
|
-
async renewLock(lockId, lockToken, ttlSeconds) {
|
|
58227
|
-
const knex = this.getKnex();
|
|
58228
|
-
const now = Date.now();
|
|
58229
|
-
const expiresAt = now + ttlSeconds * 1e3;
|
|
58230
|
-
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).update({ acquired_at: now, expires_at: expiresAt });
|
|
58231
|
-
return updated > 0;
|
|
58232
|
-
}
|
|
58233
|
-
async flush() {
|
|
58234
|
-
}
|
|
58235
|
-
// --- Message Trigger CRUD ---
|
|
58236
|
-
async createTrigger(trigger) {
|
|
58237
|
-
const knex = this.getKnex();
|
|
58238
|
-
const newTrigger = {
|
|
58239
|
-
...trigger,
|
|
58240
|
-
id: (0, import_uuid2.v4)(),
|
|
58241
|
-
createdAt: Date.now()
|
|
58242
|
-
};
|
|
58243
|
-
await knex("message_triggers").insert(toTriggerInsertRow(newTrigger));
|
|
58244
|
-
logger.info(`[KnexStore] Created trigger ${newTrigger.id} for user ${newTrigger.creatorId}`);
|
|
58245
|
-
return newTrigger;
|
|
58246
|
-
}
|
|
58247
|
-
async getTrigger(id) {
|
|
58248
|
-
const knex = this.getKnex();
|
|
58249
|
-
const row = await knex("message_triggers").where("id", id).first();
|
|
58250
|
-
return row ? fromTriggerRow2(row) : void 0;
|
|
58251
|
-
}
|
|
58252
|
-
async updateTrigger(id, patch) {
|
|
58253
|
-
const knex = this.getKnex();
|
|
58254
|
-
const existing = await knex("message_triggers").where("id", id).first();
|
|
58255
|
-
if (!existing) return void 0;
|
|
58256
|
-
const current = fromTriggerRow2(existing);
|
|
58257
|
-
const updated = {
|
|
58258
|
-
...current,
|
|
58259
|
-
...patch,
|
|
58260
|
-
id: current.id,
|
|
58261
|
-
createdAt: current.createdAt
|
|
58262
|
-
};
|
|
58263
|
-
const row = toTriggerInsertRow(updated);
|
|
58264
|
-
delete row.id;
|
|
58265
|
-
await knex("message_triggers").where("id", id).update(row);
|
|
58266
|
-
return updated;
|
|
58267
|
-
}
|
|
58268
|
-
async deleteTrigger(id) {
|
|
58269
|
-
const knex = this.getKnex();
|
|
58270
|
-
const deleted = await knex("message_triggers").where("id", id).del();
|
|
58271
|
-
if (deleted > 0) {
|
|
58272
|
-
logger.info(`[KnexStore] Deleted trigger ${id}`);
|
|
58273
|
-
return true;
|
|
58274
|
-
}
|
|
58275
|
-
return false;
|
|
58276
|
-
}
|
|
58277
|
-
async getTriggersByCreator(creatorId) {
|
|
58278
|
-
const knex = this.getKnex();
|
|
58279
|
-
const rows = await knex("message_triggers").where("creator_id", creatorId);
|
|
58280
|
-
return rows.map((r) => fromTriggerRow2(r));
|
|
58281
|
-
}
|
|
58282
|
-
async getActiveTriggers() {
|
|
58283
|
-
const knex = this.getKnex();
|
|
58284
|
-
const rows = await knex("message_triggers").where("status", "active").where("enabled", this.driver === "mssql" ? 1 : true);
|
|
58285
|
-
return rows.map((r) => fromTriggerRow2(r));
|
|
58286
|
-
}
|
|
58287
|
-
};
|
|
58288
|
-
}
|
|
58289
|
-
});
|
|
58290
|
-
|
|
58291
|
-
// src/enterprise/loader.ts
|
|
58292
|
-
var loader_exports = {};
|
|
58293
|
-
__export(loader_exports, {
|
|
58294
|
-
loadEnterprisePolicyEngine: () => loadEnterprisePolicyEngine,
|
|
58295
|
-
loadEnterpriseStoreBackend: () => loadEnterpriseStoreBackend
|
|
58296
|
-
});
|
|
58297
|
-
async function loadEnterprisePolicyEngine(config) {
|
|
58298
|
-
try {
|
|
58299
|
-
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
58300
|
-
const validator = new LicenseValidator2();
|
|
58301
|
-
const license = await validator.loadAndValidate();
|
|
58302
|
-
if (!license || !validator.hasFeature("policy")) {
|
|
58303
|
-
return new DefaultPolicyEngine();
|
|
58304
|
-
}
|
|
58305
|
-
if (validator.isInGracePeriod()) {
|
|
58306
|
-
console.warn(
|
|
58307
|
-
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
58308
|
-
);
|
|
58309
|
-
}
|
|
58310
|
-
const { OpaPolicyEngine: OpaPolicyEngine2 } = await Promise.resolve().then(() => (init_opa_policy_engine(), opa_policy_engine_exports));
|
|
58311
|
-
const engine = new OpaPolicyEngine2(config);
|
|
58312
|
-
await engine.initialize(config);
|
|
58313
|
-
return engine;
|
|
58314
|
-
} catch (err) {
|
|
58315
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
58316
|
-
try {
|
|
58317
|
-
const { logger: logger2 } = (init_logger(), __toCommonJS(logger_exports));
|
|
58318
|
-
logger2.warn(`[PolicyEngine] Enterprise policy init failed, falling back to default: ${msg}`);
|
|
58319
|
-
} catch {
|
|
58320
|
-
}
|
|
58321
|
-
return new DefaultPolicyEngine();
|
|
58322
|
-
}
|
|
58323
|
-
}
|
|
58324
|
-
async function loadEnterpriseStoreBackend(driver, storageConfig, haConfig) {
|
|
58325
|
-
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
58326
|
-
const validator = new LicenseValidator2();
|
|
58327
|
-
const license = await validator.loadAndValidate();
|
|
58328
|
-
if (!license || !validator.hasFeature("scheduler-sql")) {
|
|
58329
|
-
throw new Error(
|
|
58330
|
-
`The ${driver} schedule storage driver requires a Visor Enterprise license with the 'scheduler-sql' feature. Please upgrade or use driver: 'sqlite' (default).`
|
|
58331
|
-
);
|
|
58332
|
-
}
|
|
58333
|
-
if (validator.isInGracePeriod()) {
|
|
58334
|
-
console.warn(
|
|
58335
|
-
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
58336
|
-
);
|
|
58337
|
-
}
|
|
58338
|
-
const { KnexStoreBackend: KnexStoreBackend2 } = await Promise.resolve().then(() => (init_knex_store(), knex_store_exports));
|
|
58339
|
-
return new KnexStoreBackend2(driver, storageConfig, haConfig);
|
|
58340
|
-
}
|
|
58341
|
-
var init_loader = __esm({
|
|
58342
|
-
"src/enterprise/loader.ts"() {
|
|
58343
|
-
"use strict";
|
|
58344
|
-
init_default_engine();
|
|
58345
|
-
}
|
|
58346
|
-
});
|
|
58347
|
-
|
|
58348
57134
|
// src/event-bus/event-bus.ts
|
|
58349
57135
|
var event_bus_exports = {};
|
|
58350
57136
|
__export(event_bus_exports, {
|
|
@@ -59251,8 +58037,8 @@ ${content}
|
|
|
59251
58037
|
* Sleep utility
|
|
59252
58038
|
*/
|
|
59253
58039
|
sleep(ms) {
|
|
59254
|
-
return new Promise((
|
|
59255
|
-
const t = setTimeout(
|
|
58040
|
+
return new Promise((resolve15) => {
|
|
58041
|
+
const t = setTimeout(resolve15, ms);
|
|
59256
58042
|
if (typeof t.unref === "function") {
|
|
59257
58043
|
try {
|
|
59258
58044
|
t.unref();
|
|
@@ -59537,8 +58323,8 @@ ${end}`);
|
|
|
59537
58323
|
async updateGroupedComment(ctx, comments, group, changedIds) {
|
|
59538
58324
|
const existingLock = this.updateLocks.get(group);
|
|
59539
58325
|
let resolveLock;
|
|
59540
|
-
const ourLock = new Promise((
|
|
59541
|
-
resolveLock =
|
|
58326
|
+
const ourLock = new Promise((resolve15) => {
|
|
58327
|
+
resolveLock = resolve15;
|
|
59542
58328
|
});
|
|
59543
58329
|
this.updateLocks.set(group, ourLock);
|
|
59544
58330
|
try {
|
|
@@ -59869,7 +58655,7 @@ ${blocks}
|
|
|
59869
58655
|
* Sleep utility for enforcing delays
|
|
59870
58656
|
*/
|
|
59871
58657
|
sleep(ms) {
|
|
59872
|
-
return new Promise((
|
|
58658
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
59873
58659
|
}
|
|
59874
58660
|
};
|
|
59875
58661
|
}
|
|
@@ -61716,11 +60502,11 @@ var require_request3 = __commonJS({
|
|
|
61716
60502
|
"use strict";
|
|
61717
60503
|
var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
61718
60504
|
function adopt(value) {
|
|
61719
|
-
return value instanceof P ? value : new P(function(
|
|
61720
|
-
|
|
60505
|
+
return value instanceof P ? value : new P(function(resolve15) {
|
|
60506
|
+
resolve15(value);
|
|
61721
60507
|
});
|
|
61722
60508
|
}
|
|
61723
|
-
return new (P || (P = Promise))(function(
|
|
60509
|
+
return new (P || (P = Promise))(function(resolve15, reject) {
|
|
61724
60510
|
function fulfilled(value) {
|
|
61725
60511
|
try {
|
|
61726
60512
|
step(generator.next(value));
|
|
@@ -61736,7 +60522,7 @@ var require_request3 = __commonJS({
|
|
|
61736
60522
|
}
|
|
61737
60523
|
}
|
|
61738
60524
|
function step(result) {
|
|
61739
|
-
result.done ?
|
|
60525
|
+
result.done ? resolve15(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
61740
60526
|
}
|
|
61741
60527
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
61742
60528
|
});
|
|
@@ -61760,9 +60546,9 @@ var require_request3 = __commonJS({
|
|
|
61760
60546
|
HttpMethod2["PATCH"] = "PATCH";
|
|
61761
60547
|
})(HttpMethod = exports2.HttpMethod || (exports2.HttpMethod = {}));
|
|
61762
60548
|
var SvixRequest = class {
|
|
61763
|
-
constructor(method,
|
|
60549
|
+
constructor(method, path29) {
|
|
61764
60550
|
this.method = method;
|
|
61765
|
-
this.path =
|
|
60551
|
+
this.path = path29;
|
|
61766
60552
|
this.queryParams = {};
|
|
61767
60553
|
this.headerParams = {};
|
|
61768
60554
|
}
|
|
@@ -61865,7 +60651,7 @@ var require_request3 = __commonJS({
|
|
|
61865
60651
|
}
|
|
61866
60652
|
function sendWithRetry(url, init, retryScheduleInMs, nextInterval = 50, triesLeft = 2, fetchImpl = fetch, retryCount = 1) {
|
|
61867
60653
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61868
|
-
const sleep = (interval) => new Promise((
|
|
60654
|
+
const sleep = (interval) => new Promise((resolve15) => setTimeout(resolve15, interval));
|
|
61869
60655
|
try {
|
|
61870
60656
|
const response = yield fetchImpl(url, init);
|
|
61871
60657
|
if (triesLeft <= 0 || response.status < 500) {
|
|
@@ -70939,7 +69725,7 @@ ${message}`;
|
|
|
70939
69725
|
});
|
|
70940
69726
|
|
|
70941
69727
|
// src/agent-protocol/task-store.ts
|
|
70942
|
-
function
|
|
69728
|
+
function safeJsonParse2(value) {
|
|
70943
69729
|
if (!value) return void 0;
|
|
70944
69730
|
try {
|
|
70945
69731
|
return JSON.parse(value);
|
|
@@ -70956,12 +69742,12 @@ function taskRowToAgentTask(row) {
|
|
|
70956
69742
|
context_id: row.context_id,
|
|
70957
69743
|
status: {
|
|
70958
69744
|
state: row.state,
|
|
70959
|
-
message:
|
|
69745
|
+
message: safeJsonParse2(row.status_message),
|
|
70960
69746
|
timestamp: row.updated_at
|
|
70961
69747
|
},
|
|
70962
|
-
artifacts:
|
|
70963
|
-
history:
|
|
70964
|
-
metadata:
|
|
69748
|
+
artifacts: safeJsonParse2(row.artifacts) ?? [],
|
|
69749
|
+
history: safeJsonParse2(row.history) ?? [],
|
|
69750
|
+
metadata: safeJsonParse2(row.request_metadata),
|
|
70965
69751
|
workflow_id: row.workflow_id ?? void 0
|
|
70966
69752
|
};
|
|
70967
69753
|
}
|
|
@@ -71198,7 +69984,7 @@ var init_task_store = __esm({
|
|
|
71198
69984
|
const db = this.getDb();
|
|
71199
69985
|
const row = db.prepare("SELECT artifacts FROM agent_tasks WHERE id = ?").get(taskId);
|
|
71200
69986
|
if (!row) throw new TaskNotFoundError(taskId);
|
|
71201
|
-
const artifacts =
|
|
69987
|
+
const artifacts = safeJsonParse2(row.artifacts) ?? [];
|
|
71202
69988
|
artifacts.push(artifact);
|
|
71203
69989
|
db.prepare("UPDATE agent_tasks SET artifacts = ?, updated_at = ? WHERE id = ?").run(
|
|
71204
69990
|
JSON.stringify(artifacts),
|
|
@@ -71210,7 +69996,7 @@ var init_task_store = __esm({
|
|
|
71210
69996
|
const db = this.getDb();
|
|
71211
69997
|
const row = db.prepare("SELECT history FROM agent_tasks WHERE id = ?").get(taskId);
|
|
71212
69998
|
if (!row) throw new TaskNotFoundError(taskId);
|
|
71213
|
-
const history =
|
|
69999
|
+
const history = safeJsonParse2(row.history) ?? [];
|
|
71214
70000
|
history.push(message);
|
|
71215
70001
|
db.prepare("UPDATE agent_tasks SET history = ?, updated_at = ? WHERE id = ?").run(
|
|
71216
70002
|
JSON.stringify(history),
|
|
@@ -71722,13 +70508,13 @@ __export(a2a_frontend_exports, {
|
|
|
71722
70508
|
resultToArtifacts: () => resultToArtifacts
|
|
71723
70509
|
});
|
|
71724
70510
|
function readJsonBody(req) {
|
|
71725
|
-
return new Promise((
|
|
70511
|
+
return new Promise((resolve15, reject) => {
|
|
71726
70512
|
const chunks = [];
|
|
71727
70513
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
71728
70514
|
req.on("end", () => {
|
|
71729
70515
|
try {
|
|
71730
70516
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
71731
|
-
|
|
70517
|
+
resolve15(body ? JSON.parse(body) : {});
|
|
71732
70518
|
} catch {
|
|
71733
70519
|
reject(new ParseError("Malformed JSON body"));
|
|
71734
70520
|
}
|
|
@@ -71971,12 +70757,12 @@ var init_a2a_frontend = __esm({
|
|
|
71971
70757
|
}
|
|
71972
70758
|
const port = this.config.port ?? 9e3;
|
|
71973
70759
|
const host = this.config.host ?? "0.0.0.0";
|
|
71974
|
-
await new Promise((
|
|
70760
|
+
await new Promise((resolve15) => {
|
|
71975
70761
|
this.server.listen(port, host, () => {
|
|
71976
70762
|
const addr = this.server.address();
|
|
71977
70763
|
this._boundPort = typeof addr === "object" && addr ? addr.port : port;
|
|
71978
70764
|
logger.info(`A2A server listening on ${host}:${this._boundPort}`);
|
|
71979
|
-
|
|
70765
|
+
resolve15();
|
|
71980
70766
|
});
|
|
71981
70767
|
});
|
|
71982
70768
|
if (this.agentCard) {
|
|
@@ -72000,8 +70786,8 @@ var init_a2a_frontend = __esm({
|
|
|
72000
70786
|
}
|
|
72001
70787
|
this.streamManager.shutdown();
|
|
72002
70788
|
if (this.server) {
|
|
72003
|
-
await new Promise((
|
|
72004
|
-
this.server.close((err) => err ? reject(err) :
|
|
70789
|
+
await new Promise((resolve15, reject) => {
|
|
70790
|
+
this.server.close((err) => err ? reject(err) : resolve15());
|
|
72005
70791
|
});
|
|
72006
70792
|
this.server = null;
|
|
72007
70793
|
}
|
|
@@ -72718,15 +71504,15 @@ function serializeRunState(state) {
|
|
|
72718
71504
|
])
|
|
72719
71505
|
};
|
|
72720
71506
|
}
|
|
72721
|
-
var
|
|
71507
|
+
var path28, fs24, StateMachineExecutionEngine;
|
|
72722
71508
|
var init_state_machine_execution_engine = __esm({
|
|
72723
71509
|
"src/state-machine-execution-engine.ts"() {
|
|
72724
71510
|
"use strict";
|
|
72725
71511
|
init_runner();
|
|
72726
71512
|
init_logger();
|
|
72727
71513
|
init_sandbox_manager();
|
|
72728
|
-
|
|
72729
|
-
|
|
71514
|
+
path28 = __toESM(require("path"));
|
|
71515
|
+
fs24 = __toESM(require("fs"));
|
|
72730
71516
|
StateMachineExecutionEngine = class _StateMachineExecutionEngine {
|
|
72731
71517
|
workingDirectory;
|
|
72732
71518
|
executionContext;
|
|
@@ -72958,8 +71744,8 @@ var init_state_machine_execution_engine = __esm({
|
|
|
72958
71744
|
logger.debug(
|
|
72959
71745
|
`[PolicyEngine] Loading enterprise policy engine (engine=${configWithTagFilter.policy.engine})`
|
|
72960
71746
|
);
|
|
72961
|
-
const { loadEnterprisePolicyEngine
|
|
72962
|
-
context2.policyEngine = await
|
|
71747
|
+
const { loadEnterprisePolicyEngine } = await import("./enterprise/loader");
|
|
71748
|
+
context2.policyEngine = await loadEnterprisePolicyEngine(configWithTagFilter.policy);
|
|
72963
71749
|
logger.debug(
|
|
72964
71750
|
`[PolicyEngine] Initialized: ${context2.policyEngine?.constructor?.name || "unknown"}`
|
|
72965
71751
|
);
|
|
@@ -73113,9 +71899,9 @@ var init_state_machine_execution_engine = __esm({
|
|
|
73113
71899
|
}
|
|
73114
71900
|
const checkId = String(ev?.checkId || "unknown");
|
|
73115
71901
|
const threadKey = ev?.threadKey || (channel && threadTs ? `${channel}:${threadTs}` : "session");
|
|
73116
|
-
const baseDir = process.env.VISOR_SNAPSHOT_DIR ||
|
|
73117
|
-
|
|
73118
|
-
const filePath =
|
|
71902
|
+
const baseDir = process.env.VISOR_SNAPSHOT_DIR || path28.resolve(process.cwd(), ".visor", "snapshots");
|
|
71903
|
+
fs24.mkdirSync(baseDir, { recursive: true });
|
|
71904
|
+
const filePath = path28.join(baseDir, `${threadKey}-${checkId}.json`);
|
|
73119
71905
|
await this.saveSnapshotToFile(filePath);
|
|
73120
71906
|
logger.info(`[Snapshot] Saved run snapshot: ${filePath}`);
|
|
73121
71907
|
try {
|
|
@@ -73256,7 +72042,7 @@ var init_state_machine_execution_engine = __esm({
|
|
|
73256
72042
|
* Does not include secrets. Intended for debugging and future resume support.
|
|
73257
72043
|
*/
|
|
73258
72044
|
async saveSnapshotToFile(filePath) {
|
|
73259
|
-
const
|
|
72045
|
+
const fs25 = await import("fs/promises");
|
|
73260
72046
|
const ctx = this._lastContext;
|
|
73261
72047
|
const runner = this._lastRunner;
|
|
73262
72048
|
if (!ctx || !runner) {
|
|
@@ -73276,14 +72062,14 @@ var init_state_machine_execution_engine = __esm({
|
|
|
73276
72062
|
journal: entries,
|
|
73277
72063
|
requestedChecks: ctx.requestedChecks || []
|
|
73278
72064
|
};
|
|
73279
|
-
await
|
|
72065
|
+
await fs25.writeFile(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
73280
72066
|
}
|
|
73281
72067
|
/**
|
|
73282
72068
|
* Load a snapshot JSON from file and return it. Resume support can build on this.
|
|
73283
72069
|
*/
|
|
73284
72070
|
async loadSnapshotFromFile(filePath) {
|
|
73285
|
-
const
|
|
73286
|
-
const raw = await
|
|
72071
|
+
const fs25 = await import("fs/promises");
|
|
72072
|
+
const raw = await fs25.readFile(filePath, "utf8");
|
|
73287
72073
|
return JSON.parse(raw);
|
|
73288
72074
|
}
|
|
73289
72075
|
/**
|