@probelabs/visor 0.1.171 → 0.1.172-ee
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-protocol/task-store.d.ts +8 -0
- package/dist/agent-protocol/task-store.d.ts.map +1 -1
- package/dist/agent-protocol/tasks-cli-handler.d.ts.map +1 -1
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/index.js +2033 -99
- package/dist/sdk/{a2a-frontend-GUEGI5SX.mjs → a2a-frontend-N4VU3PHW.mjs} +36 -1
- package/dist/sdk/a2a-frontend-N4VU3PHW.mjs.map +1 -0
- package/dist/sdk/{check-provider-registry-YTI4PU5F.mjs → check-provider-registry-4KW2YPZW.mjs} +3 -3
- package/dist/sdk/{check-provider-registry-ZUU7KSKR.mjs → check-provider-registry-H5GQGT2X.mjs} +3 -3
- package/dist/sdk/{chunk-CXA3WUOB.mjs → chunk-CNZ7XHLN.mjs} +9 -9
- package/dist/sdk/{chunk-2VDUNKIP.mjs → chunk-ONN7TBQM.mjs} +14 -14
- package/dist/sdk/{chunk-XUQSI5SR.mjs.map → chunk-ONN7TBQM.mjs.map} +1 -1
- package/dist/sdk/{chunk-AVMMKGLQ.mjs → chunk-PDQTEBOJ.mjs} +18 -18
- package/dist/sdk/chunk-PDQTEBOJ.mjs.map +1 -0
- package/dist/sdk/{host-A7UNRBQU.mjs → host-DOJQVREK.mjs} +3 -3
- package/dist/sdk/{host-A4GGQVEN.mjs → host-YATAT2B4.mjs} +4 -4
- package/dist/sdk/knex-store-CRORFJE6.mjs +527 -0
- package/dist/sdk/knex-store-CRORFJE6.mjs.map +1 -0
- package/dist/sdk/loader-QMJFFST6.mjs +89 -0
- package/dist/sdk/loader-QMJFFST6.mjs.map +1 -0
- package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs +655 -0
- package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
- package/dist/sdk/{schedule-tool-DGVJDHJM.mjs → schedule-tool-HCJUIF4H.mjs} +3 -3
- package/dist/sdk/{schedule-tool-4MTFIHCA.mjs → schedule-tool-KUGCECKZ.mjs} +3 -3
- package/dist/sdk/{schedule-tool-handler-LMXQ4BZQ.mjs → schedule-tool-handler-DCMMLWLB.mjs} +3 -3
- package/dist/sdk/{schedule-tool-handler-XLCSBU3E.mjs → schedule-tool-handler-IZU43FC2.mjs} +3 -3
- package/dist/sdk/sdk.js +1700 -291
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +5 -5
- package/dist/sdk/{slack-frontend-QO7LW5BH.mjs → slack-frontend-7T5UISCX.mjs} +2 -2
- package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
- package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-KQNLEQEY.mjs → workflow-check-provider-LO2X6XOJ.mjs} +3 -3
- package/dist/sdk/{workflow-check-provider-X5EMAJUZ.mjs → workflow-check-provider-O2SIH3PC.mjs} +3 -3
- package/dist/slack/markdown.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/output/traces/run-2026-03-08T07-55-35-120Z.ndjson +0 -138
- package/dist/output/traces/run-2026-03-08T07-56-13-035Z.ndjson +0 -2266
- package/dist/sdk/a2a-frontend-FGJ3UBHX.mjs +0 -1622
- package/dist/sdk/a2a-frontend-FGJ3UBHX.mjs.map +0 -1
- package/dist/sdk/a2a-frontend-GUEGI5SX.mjs.map +0 -1
- package/dist/sdk/check-provider-registry-PVTV5G5R.mjs +0 -30
- package/dist/sdk/chunk-2VDUNKIP.mjs.map +0 -1
- package/dist/sdk/chunk-6FDBLSGV.mjs +0 -739
- package/dist/sdk/chunk-6FDBLSGV.mjs.map +0 -1
- package/dist/sdk/chunk-AJK3FAA2.mjs +0 -1502
- package/dist/sdk/chunk-AJK3FAA2.mjs.map +0 -1
- package/dist/sdk/chunk-AVMMKGLQ.mjs.map +0 -1
- package/dist/sdk/chunk-O72J3ORS.mjs +0 -449
- package/dist/sdk/chunk-O72J3ORS.mjs.map +0 -1
- package/dist/sdk/chunk-XUQSI5SR.mjs +0 -44810
- package/dist/sdk/failure-condition-evaluator-EFMCQVAK.mjs +0 -18
- package/dist/sdk/github-frontend-XG55VJ4R.mjs +0 -1386
- package/dist/sdk/github-frontend-XG55VJ4R.mjs.map +0 -1
- package/dist/sdk/routing-BVEHVZHK.mjs +0 -26
- package/dist/sdk/schedule-tool-PHSF5U2B.mjs +0 -36
- package/dist/sdk/schedule-tool-handler-EFNCZNS7.mjs +0 -40
- package/dist/sdk/schedule-tool-handler-EFNCZNS7.mjs.map +0 -1
- package/dist/sdk/schedule-tool-handler-LMXQ4BZQ.mjs.map +0 -1
- package/dist/sdk/schedule-tool-handler-XLCSBU3E.mjs.map +0 -1
- package/dist/sdk/trace-helpers-P5L4COO4.mjs +0 -26
- package/dist/sdk/trace-helpers-P5L4COO4.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-KQNLEQEY.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-WLMTCFRA.mjs +0 -30
- package/dist/sdk/workflow-check-provider-WLMTCFRA.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-X5EMAJUZ.mjs.map +0 -1
- package/dist/traces/run-2026-03-08T07-55-35-120Z.ndjson +0 -138
- package/dist/traces/run-2026-03-08T07-56-13-035Z.ndjson +0 -2266
- /package/dist/sdk/{check-provider-registry-PVTV5G5R.mjs.map → check-provider-registry-4KW2YPZW.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-YTI4PU5F.mjs.map → check-provider-registry-H5GQGT2X.mjs.map} +0 -0
- /package/dist/sdk/{chunk-CXA3WUOB.mjs.map → chunk-CNZ7XHLN.mjs.map} +0 -0
- /package/dist/sdk/{host-A4GGQVEN.mjs.map → host-DOJQVREK.mjs.map} +0 -0
- /package/dist/sdk/{host-A7UNRBQU.mjs.map → host-YATAT2B4.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-ZUU7KSKR.mjs.map → schedule-tool-HCJUIF4H.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-EFMCQVAK.mjs.map → schedule-tool-KUGCECKZ.mjs.map} +0 -0
- /package/dist/sdk/{routing-BVEHVZHK.mjs.map → schedule-tool-handler-DCMMLWLB.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-4MTFIHCA.mjs.map → schedule-tool-handler-IZU43FC2.mjs.map} +0 -0
- /package/dist/sdk/{slack-frontend-QO7LW5BH.mjs.map → slack-frontend-7T5UISCX.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-DGVJDHJM.mjs.map → workflow-check-provider-LO2X6XOJ.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-PHSF5U2B.mjs.map → workflow-check-provider-O2SIH3PC.mjs.map} +0 -0
package/dist/sdk/sdk.js
CHANGED
|
@@ -661,7 +661,7 @@ var require_package = __commonJS({
|
|
|
661
661
|
"package.json"(exports2, module2) {
|
|
662
662
|
module2.exports = {
|
|
663
663
|
name: "@probelabs/visor",
|
|
664
|
-
version: "0.1.
|
|
664
|
+
version: "0.1.42",
|
|
665
665
|
main: "dist/index.js",
|
|
666
666
|
bin: {
|
|
667
667
|
visor: "./dist/index.js"
|
|
@@ -879,11 +879,11 @@ function getTracer() {
|
|
|
879
879
|
}
|
|
880
880
|
async function withActiveSpan(name, attrs, fn) {
|
|
881
881
|
const tracer = getTracer();
|
|
882
|
-
return await new Promise((
|
|
882
|
+
return await new Promise((resolve19, reject) => {
|
|
883
883
|
const callback = async (span) => {
|
|
884
884
|
try {
|
|
885
885
|
const res = await fn(span);
|
|
886
|
-
|
|
886
|
+
resolve19(res);
|
|
887
887
|
} catch (err) {
|
|
888
888
|
try {
|
|
889
889
|
if (err instanceof Error) span.recordException(err);
|
|
@@ -961,19 +961,19 @@ function __getOrCreateNdjsonPath() {
|
|
|
961
961
|
try {
|
|
962
962
|
if (process.env.VISOR_TELEMETRY_SINK && process.env.VISOR_TELEMETRY_SINK !== "file")
|
|
963
963
|
return null;
|
|
964
|
-
const
|
|
965
|
-
const
|
|
964
|
+
const path33 = require("path");
|
|
965
|
+
const fs29 = require("fs");
|
|
966
966
|
if (process.env.VISOR_FALLBACK_TRACE_FILE) {
|
|
967
967
|
__ndjsonPath = process.env.VISOR_FALLBACK_TRACE_FILE;
|
|
968
|
-
const dir =
|
|
969
|
-
if (!
|
|
968
|
+
const dir = path33.dirname(__ndjsonPath);
|
|
969
|
+
if (!fs29.existsSync(dir)) fs29.mkdirSync(dir, { recursive: true });
|
|
970
970
|
return __ndjsonPath;
|
|
971
971
|
}
|
|
972
|
-
const outDir = process.env.VISOR_TRACE_DIR ||
|
|
973
|
-
if (!
|
|
972
|
+
const outDir = process.env.VISOR_TRACE_DIR || path33.join(process.cwd(), "output", "traces");
|
|
973
|
+
if (!fs29.existsSync(outDir)) fs29.mkdirSync(outDir, { recursive: true });
|
|
974
974
|
if (!__ndjsonPath) {
|
|
975
975
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
976
|
-
__ndjsonPath =
|
|
976
|
+
__ndjsonPath = path33.join(outDir, `${ts}.ndjson`);
|
|
977
977
|
}
|
|
978
978
|
return __ndjsonPath;
|
|
979
979
|
} catch {
|
|
@@ -982,11 +982,11 @@ function __getOrCreateNdjsonPath() {
|
|
|
982
982
|
}
|
|
983
983
|
function _appendRunMarker() {
|
|
984
984
|
try {
|
|
985
|
-
const
|
|
985
|
+
const fs29 = require("fs");
|
|
986
986
|
const p = __getOrCreateNdjsonPath();
|
|
987
987
|
if (!p) return;
|
|
988
988
|
const line = { name: "visor.run", attributes: { started: true } };
|
|
989
|
-
|
|
989
|
+
fs29.appendFileSync(p, JSON.stringify(line) + "\n", "utf8");
|
|
990
990
|
} catch {
|
|
991
991
|
}
|
|
992
992
|
}
|
|
@@ -3210,7 +3210,7 @@ var init_failure_condition_evaluator = __esm({
|
|
|
3210
3210
|
*/
|
|
3211
3211
|
evaluateExpression(condition, context2) {
|
|
3212
3212
|
try {
|
|
3213
|
-
const
|
|
3213
|
+
const normalize8 = (expr) => {
|
|
3214
3214
|
const trimmed = expr.trim();
|
|
3215
3215
|
if (!/[\n;]/.test(trimmed)) return trimmed;
|
|
3216
3216
|
const parts = trimmed.split(/[\n;]+/).map((s) => s.trim()).filter((s) => s.length > 0 && !s.startsWith("//"));
|
|
@@ -3368,7 +3368,7 @@ var init_failure_condition_evaluator = __esm({
|
|
|
3368
3368
|
try {
|
|
3369
3369
|
exec2 = this.sandbox.compile(`return (${raw});`);
|
|
3370
3370
|
} catch {
|
|
3371
|
-
const normalizedExpr =
|
|
3371
|
+
const normalizedExpr = normalize8(condition);
|
|
3372
3372
|
exec2 = this.sandbox.compile(`return (${normalizedExpr});`);
|
|
3373
3373
|
}
|
|
3374
3374
|
const result = exec2(scope).run();
|
|
@@ -3751,9 +3751,9 @@ function configureLiquidWithExtensions(liquid) {
|
|
|
3751
3751
|
});
|
|
3752
3752
|
liquid.registerFilter("get", (obj, pathExpr) => {
|
|
3753
3753
|
if (obj == null) return void 0;
|
|
3754
|
-
const
|
|
3755
|
-
if (!
|
|
3756
|
-
const parts =
|
|
3754
|
+
const path33 = typeof pathExpr === "string" ? pathExpr : String(pathExpr || "");
|
|
3755
|
+
if (!path33) return obj;
|
|
3756
|
+
const parts = path33.split(".");
|
|
3757
3757
|
let cur = obj;
|
|
3758
3758
|
for (const p of parts) {
|
|
3759
3759
|
if (cur == null) return void 0;
|
|
@@ -3872,9 +3872,9 @@ function configureLiquidWithExtensions(liquid) {
|
|
|
3872
3872
|
}
|
|
3873
3873
|
}
|
|
3874
3874
|
const defaultRole = typeof rolesCfg.default === "string" && rolesCfg.default.trim() ? rolesCfg.default.trim() : void 0;
|
|
3875
|
-
const getNested = (obj,
|
|
3876
|
-
if (!obj || !
|
|
3877
|
-
const parts =
|
|
3875
|
+
const getNested = (obj, path33) => {
|
|
3876
|
+
if (!obj || !path33) return void 0;
|
|
3877
|
+
const parts = path33.split(".");
|
|
3878
3878
|
let cur = obj;
|
|
3879
3879
|
for (const p of parts) {
|
|
3880
3880
|
if (cur == null) return void 0;
|
|
@@ -6426,8 +6426,8 @@ var init_dependency_gating = __esm({
|
|
|
6426
6426
|
async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
|
|
6427
6427
|
try {
|
|
6428
6428
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
6429
|
-
const
|
|
6430
|
-
const
|
|
6429
|
+
const fs29 = await import("fs/promises");
|
|
6430
|
+
const path33 = await import("path");
|
|
6431
6431
|
const schemaRaw = checkConfig.schema || "plain";
|
|
6432
6432
|
const schema = typeof schemaRaw === "string" ? schemaRaw : "code-review";
|
|
6433
6433
|
let templateContent;
|
|
@@ -6435,24 +6435,24 @@ async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
|
|
|
6435
6435
|
templateContent = String(checkConfig.template.content);
|
|
6436
6436
|
} else if (checkConfig.template && checkConfig.template.file) {
|
|
6437
6437
|
const file = String(checkConfig.template.file);
|
|
6438
|
-
const resolved =
|
|
6439
|
-
templateContent = await
|
|
6438
|
+
const resolved = path33.resolve(process.cwd(), file);
|
|
6439
|
+
templateContent = await fs29.readFile(resolved, "utf-8");
|
|
6440
6440
|
} else if (schema && schema !== "plain") {
|
|
6441
6441
|
const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
|
|
6442
6442
|
if (sanitized) {
|
|
6443
6443
|
const candidatePaths = [
|
|
6444
|
-
|
|
6444
|
+
path33.join(__dirname, "output", sanitized, "template.liquid"),
|
|
6445
6445
|
// bundled: dist/output/
|
|
6446
|
-
|
|
6446
|
+
path33.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
6447
6447
|
// source: output/
|
|
6448
|
-
|
|
6448
|
+
path33.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
6449
6449
|
// fallback: cwd/output/
|
|
6450
|
-
|
|
6450
|
+
path33.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
|
|
6451
6451
|
// fallback: cwd/dist/output/
|
|
6452
6452
|
];
|
|
6453
6453
|
for (const p of candidatePaths) {
|
|
6454
6454
|
try {
|
|
6455
|
-
templateContent = await
|
|
6455
|
+
templateContent = await fs29.readFile(p, "utf-8");
|
|
6456
6456
|
if (templateContent) break;
|
|
6457
6457
|
} catch {
|
|
6458
6458
|
}
|
|
@@ -6857,7 +6857,7 @@ async function processDiffWithOutline(diffContent) {
|
|
|
6857
6857
|
}
|
|
6858
6858
|
try {
|
|
6859
6859
|
const originalProbePath = process.env.PROBE_PATH;
|
|
6860
|
-
const
|
|
6860
|
+
const fs29 = require("fs");
|
|
6861
6861
|
const possiblePaths = [
|
|
6862
6862
|
// Relative to current working directory (most common in production)
|
|
6863
6863
|
path6.join(process.cwd(), "node_modules/@probelabs/probe/bin/probe-binary"),
|
|
@@ -6868,7 +6868,7 @@ async function processDiffWithOutline(diffContent) {
|
|
|
6868
6868
|
];
|
|
6869
6869
|
let probeBinaryPath;
|
|
6870
6870
|
for (const candidatePath of possiblePaths) {
|
|
6871
|
-
if (
|
|
6871
|
+
if (fs29.existsSync(candidatePath)) {
|
|
6872
6872
|
probeBinaryPath = candidatePath;
|
|
6873
6873
|
break;
|
|
6874
6874
|
}
|
|
@@ -6975,7 +6975,7 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
6975
6975
|
if (chromiumPath) {
|
|
6976
6976
|
env.PUPPETEER_EXECUTABLE_PATH = chromiumPath;
|
|
6977
6977
|
}
|
|
6978
|
-
const result = await new Promise((
|
|
6978
|
+
const result = await new Promise((resolve19) => {
|
|
6979
6979
|
const proc = (0, import_child_process.spawn)(
|
|
6980
6980
|
"npx",
|
|
6981
6981
|
[
|
|
@@ -7005,13 +7005,13 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
7005
7005
|
});
|
|
7006
7006
|
proc.on("close", (code) => {
|
|
7007
7007
|
if (code === 0) {
|
|
7008
|
-
|
|
7008
|
+
resolve19({ success: true });
|
|
7009
7009
|
} else {
|
|
7010
|
-
|
|
7010
|
+
resolve19({ success: false, error: stderr || `Exit code ${code}` });
|
|
7011
7011
|
}
|
|
7012
7012
|
});
|
|
7013
7013
|
proc.on("error", (err) => {
|
|
7014
|
-
|
|
7014
|
+
resolve19({ success: false, error: err.message });
|
|
7015
7015
|
});
|
|
7016
7016
|
});
|
|
7017
7017
|
if (!result.success) {
|
|
@@ -7048,28 +7048,27 @@ function replaceMermaidBlocks(text, diagrams, replacement = "_(See diagram above
|
|
|
7048
7048
|
}
|
|
7049
7049
|
function markdownToSlack(text) {
|
|
7050
7050
|
if (!text || typeof text !== "string") return "";
|
|
7051
|
-
|
|
7052
|
-
out = out.replace(
|
|
7053
|
-
/!\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
|
|
7054
|
-
(_m, alt, url) => `<${url}|${alt || "image"}>`
|
|
7055
|
-
);
|
|
7056
|
-
out = out.replace(
|
|
7057
|
-
/\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
|
|
7058
|
-
(_m, label, url) => `<${url}|${label}>`
|
|
7059
|
-
);
|
|
7060
|
-
out = out.replace(/\*\*([^*]+)\*\*/g, (_m, inner) => `*${inner}*`);
|
|
7061
|
-
out = out.replace(/__([^_]+)__/g, (_m, inner) => `*${inner}*`);
|
|
7062
|
-
const lines = out.split(/\r?\n/);
|
|
7051
|
+
const lines = text.split(/\r?\n/);
|
|
7063
7052
|
let inCodeBlock = false;
|
|
7064
7053
|
for (let i = 0; i < lines.length; i++) {
|
|
7065
|
-
const
|
|
7066
|
-
const trimmed = line.trimStart();
|
|
7054
|
+
const trimmed = lines[i].trimStart();
|
|
7067
7055
|
if (/^```/.test(trimmed)) {
|
|
7068
7056
|
inCodeBlock = !inCodeBlock;
|
|
7069
7057
|
continue;
|
|
7070
7058
|
}
|
|
7071
7059
|
if (inCodeBlock) continue;
|
|
7072
|
-
|
|
7060
|
+
let line = lines[i];
|
|
7061
|
+
line = line.replace(
|
|
7062
|
+
/!\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
|
|
7063
|
+
(_m, alt, url) => `<${url}|${alt || "image"}>`
|
|
7064
|
+
);
|
|
7065
|
+
line = line.replace(
|
|
7066
|
+
/\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
|
|
7067
|
+
(_m, label, url) => `<${url}|${label}>`
|
|
7068
|
+
);
|
|
7069
|
+
line = line.replace(/\*\*([^*]+)\*\*/g, (_m, inner) => `*${inner}*`);
|
|
7070
|
+
line = line.replace(/__([^_]+)__/g, (_m, inner) => `*${inner}*`);
|
|
7071
|
+
const headerMatch = /^(#{1,6})\s+(.+)$/.exec(line.trimStart());
|
|
7073
7072
|
if (headerMatch) {
|
|
7074
7073
|
const [, hashes, headerText] = headerMatch;
|
|
7075
7074
|
const prevLine = i > 0 ? lines[i - 1].trim() : "";
|
|
@@ -7086,10 +7085,11 @@ function markdownToSlack(text) {
|
|
|
7086
7085
|
if (bulletMatch) {
|
|
7087
7086
|
const [, indent, , rest] = bulletMatch;
|
|
7088
7087
|
lines[i] = `${indent}\u2022 ${rest}`;
|
|
7088
|
+
continue;
|
|
7089
7089
|
}
|
|
7090
|
+
lines[i] = line;
|
|
7090
7091
|
}
|
|
7091
|
-
|
|
7092
|
-
return out;
|
|
7092
|
+
return lines.join("\n");
|
|
7093
7093
|
}
|
|
7094
7094
|
function extractFileSections(text) {
|
|
7095
7095
|
const sections = [];
|
|
@@ -8173,8 +8173,8 @@ ${schemaString}`);
|
|
|
8173
8173
|
}
|
|
8174
8174
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8175
8175
|
try {
|
|
8176
|
-
const
|
|
8177
|
-
const
|
|
8176
|
+
const fs29 = require("fs");
|
|
8177
|
+
const path33 = require("path");
|
|
8178
8178
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8179
8179
|
const provider = this.config.provider || "auto";
|
|
8180
8180
|
const model = this.config.model || "default";
|
|
@@ -8288,20 +8288,20 @@ ${"=".repeat(60)}
|
|
|
8288
8288
|
`;
|
|
8289
8289
|
readableVersion += `${"=".repeat(60)}
|
|
8290
8290
|
`;
|
|
8291
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8292
|
-
if (!
|
|
8293
|
-
|
|
8291
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
8292
|
+
if (!fs29.existsSync(debugArtifactsDir)) {
|
|
8293
|
+
fs29.mkdirSync(debugArtifactsDir, { recursive: true });
|
|
8294
8294
|
}
|
|
8295
|
-
const debugFile =
|
|
8295
|
+
const debugFile = path33.join(
|
|
8296
8296
|
debugArtifactsDir,
|
|
8297
8297
|
`prompt-${_checkName || "unknown"}-${timestamp}.json`
|
|
8298
8298
|
);
|
|
8299
|
-
|
|
8300
|
-
const readableFile =
|
|
8299
|
+
fs29.writeFileSync(debugFile, debugJson, "utf-8");
|
|
8300
|
+
const readableFile = path33.join(
|
|
8301
8301
|
debugArtifactsDir,
|
|
8302
8302
|
`prompt-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8303
8303
|
);
|
|
8304
|
-
|
|
8304
|
+
fs29.writeFileSync(readableFile, readableVersion, "utf-8");
|
|
8305
8305
|
log(`
|
|
8306
8306
|
\u{1F4BE} Full debug info saved to:`);
|
|
8307
8307
|
log(` JSON: ${debugFile}`);
|
|
@@ -8334,8 +8334,8 @@ ${"=".repeat(60)}
|
|
|
8334
8334
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8335
8335
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8336
8336
|
try {
|
|
8337
|
-
const
|
|
8338
|
-
const
|
|
8337
|
+
const fs29 = require("fs");
|
|
8338
|
+
const path33 = require("path");
|
|
8339
8339
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8340
8340
|
const agentAny2 = agent;
|
|
8341
8341
|
let fullHistory = [];
|
|
@@ -8346,8 +8346,8 @@ ${"=".repeat(60)}
|
|
|
8346
8346
|
} else if (agentAny2._messages) {
|
|
8347
8347
|
fullHistory = agentAny2._messages;
|
|
8348
8348
|
}
|
|
8349
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8350
|
-
const sessionBase =
|
|
8349
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
8350
|
+
const sessionBase = path33.join(
|
|
8351
8351
|
debugArtifactsDir,
|
|
8352
8352
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
8353
8353
|
);
|
|
@@ -8359,7 +8359,7 @@ ${"=".repeat(60)}
|
|
|
8359
8359
|
schema: effectiveSchema,
|
|
8360
8360
|
totalMessages: fullHistory.length
|
|
8361
8361
|
};
|
|
8362
|
-
|
|
8362
|
+
fs29.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
8363
8363
|
let readable = `=============================================================
|
|
8364
8364
|
`;
|
|
8365
8365
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -8386,7 +8386,7 @@ ${"=".repeat(60)}
|
|
|
8386
8386
|
`;
|
|
8387
8387
|
readable += content + "\n";
|
|
8388
8388
|
});
|
|
8389
|
-
|
|
8389
|
+
fs29.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
8390
8390
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
8391
8391
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
8392
8392
|
} catch (error) {
|
|
@@ -8395,11 +8395,11 @@ ${"=".repeat(60)}
|
|
|
8395
8395
|
}
|
|
8396
8396
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8397
8397
|
try {
|
|
8398
|
-
const
|
|
8399
|
-
const
|
|
8398
|
+
const fs29 = require("fs");
|
|
8399
|
+
const path33 = require("path");
|
|
8400
8400
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8401
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8402
|
-
const responseFile =
|
|
8401
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
8402
|
+
const responseFile = path33.join(
|
|
8403
8403
|
debugArtifactsDir,
|
|
8404
8404
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8405
8405
|
);
|
|
@@ -8432,7 +8432,7 @@ ${"=".repeat(60)}
|
|
|
8432
8432
|
`;
|
|
8433
8433
|
responseContent += `${"=".repeat(60)}
|
|
8434
8434
|
`;
|
|
8435
|
-
|
|
8435
|
+
fs29.writeFileSync(responseFile, responseContent, "utf-8");
|
|
8436
8436
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
8437
8437
|
} catch (error) {
|
|
8438
8438
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -8448,9 +8448,9 @@ ${"=".repeat(60)}
|
|
|
8448
8448
|
await agentAny._telemetryConfig.shutdown();
|
|
8449
8449
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${agentAny._traceFilePath}`);
|
|
8450
8450
|
if (process.env.GITHUB_ACTIONS) {
|
|
8451
|
-
const
|
|
8452
|
-
if (
|
|
8453
|
-
const stats =
|
|
8451
|
+
const fs29 = require("fs");
|
|
8452
|
+
if (fs29.existsSync(agentAny._traceFilePath)) {
|
|
8453
|
+
const stats = fs29.statSync(agentAny._traceFilePath);
|
|
8454
8454
|
console.log(
|
|
8455
8455
|
`::notice title=AI Trace Saved::${agentAny._traceFilePath} (${stats.size} bytes)`
|
|
8456
8456
|
);
|
|
@@ -8663,9 +8663,9 @@ ${schemaString}`);
|
|
|
8663
8663
|
const model = this.config.model || "default";
|
|
8664
8664
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8665
8665
|
try {
|
|
8666
|
-
const
|
|
8667
|
-
const
|
|
8668
|
-
const
|
|
8666
|
+
const fs29 = require("fs");
|
|
8667
|
+
const path33 = require("path");
|
|
8668
|
+
const os3 = require("os");
|
|
8669
8669
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8670
8670
|
const debugData = {
|
|
8671
8671
|
timestamp,
|
|
@@ -8737,19 +8737,19 @@ ${"=".repeat(60)}
|
|
|
8737
8737
|
`;
|
|
8738
8738
|
readableVersion += `${"=".repeat(60)}
|
|
8739
8739
|
`;
|
|
8740
|
-
const tempDir =
|
|
8741
|
-
const promptFile =
|
|
8742
|
-
|
|
8740
|
+
const tempDir = os3.tmpdir();
|
|
8741
|
+
const promptFile = path33.join(tempDir, `visor-prompt-${timestamp}.txt`);
|
|
8742
|
+
fs29.writeFileSync(promptFile, prompt, "utf-8");
|
|
8743
8743
|
log(`
|
|
8744
8744
|
\u{1F4BE} Prompt saved to: ${promptFile}`);
|
|
8745
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8745
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
8746
8746
|
try {
|
|
8747
|
-
const base =
|
|
8747
|
+
const base = path33.join(
|
|
8748
8748
|
debugArtifactsDir,
|
|
8749
8749
|
`prompt-${_checkName || "unknown"}-${timestamp}`
|
|
8750
8750
|
);
|
|
8751
|
-
|
|
8752
|
-
|
|
8751
|
+
fs29.writeFileSync(base + ".json", debugJson, "utf-8");
|
|
8752
|
+
fs29.writeFileSync(base + ".summary.txt", readableVersion, "utf-8");
|
|
8753
8753
|
log(`
|
|
8754
8754
|
\u{1F4BE} Full debug info saved to directory: ${debugArtifactsDir}`);
|
|
8755
8755
|
} catch {
|
|
@@ -8794,8 +8794,8 @@ $ ${cliCommand}
|
|
|
8794
8794
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8795
8795
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8796
8796
|
try {
|
|
8797
|
-
const
|
|
8798
|
-
const
|
|
8797
|
+
const fs29 = require("fs");
|
|
8798
|
+
const path33 = require("path");
|
|
8799
8799
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8800
8800
|
const agentAny = agent;
|
|
8801
8801
|
let fullHistory = [];
|
|
@@ -8806,8 +8806,8 @@ $ ${cliCommand}
|
|
|
8806
8806
|
} else if (agentAny._messages) {
|
|
8807
8807
|
fullHistory = agentAny._messages;
|
|
8808
8808
|
}
|
|
8809
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8810
|
-
const sessionBase =
|
|
8809
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
8810
|
+
const sessionBase = path33.join(
|
|
8811
8811
|
debugArtifactsDir,
|
|
8812
8812
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
8813
8813
|
);
|
|
@@ -8819,7 +8819,7 @@ $ ${cliCommand}
|
|
|
8819
8819
|
schema: effectiveSchema,
|
|
8820
8820
|
totalMessages: fullHistory.length
|
|
8821
8821
|
};
|
|
8822
|
-
|
|
8822
|
+
fs29.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
8823
8823
|
let readable = `=============================================================
|
|
8824
8824
|
`;
|
|
8825
8825
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -8846,7 +8846,7 @@ ${"=".repeat(60)}
|
|
|
8846
8846
|
`;
|
|
8847
8847
|
readable += content + "\n";
|
|
8848
8848
|
});
|
|
8849
|
-
|
|
8849
|
+
fs29.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
8850
8850
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
8851
8851
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
8852
8852
|
} catch (error) {
|
|
@@ -8855,11 +8855,11 @@ ${"=".repeat(60)}
|
|
|
8855
8855
|
}
|
|
8856
8856
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8857
8857
|
try {
|
|
8858
|
-
const
|
|
8859
|
-
const
|
|
8858
|
+
const fs29 = require("fs");
|
|
8859
|
+
const path33 = require("path");
|
|
8860
8860
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8861
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8862
|
-
const responseFile =
|
|
8861
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
8862
|
+
const responseFile = path33.join(
|
|
8863
8863
|
debugArtifactsDir,
|
|
8864
8864
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8865
8865
|
);
|
|
@@ -8892,7 +8892,7 @@ ${"=".repeat(60)}
|
|
|
8892
8892
|
`;
|
|
8893
8893
|
responseContent += `${"=".repeat(60)}
|
|
8894
8894
|
`;
|
|
8895
|
-
|
|
8895
|
+
fs29.writeFileSync(responseFile, responseContent, "utf-8");
|
|
8896
8896
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
8897
8897
|
} catch (error) {
|
|
8898
8898
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -8910,9 +8910,9 @@ ${"=".repeat(60)}
|
|
|
8910
8910
|
await telemetry.shutdown();
|
|
8911
8911
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${traceFilePath}`);
|
|
8912
8912
|
if (process.env.GITHUB_ACTIONS) {
|
|
8913
|
-
const
|
|
8914
|
-
if (
|
|
8915
|
-
const stats =
|
|
8913
|
+
const fs29 = require("fs");
|
|
8914
|
+
if (fs29.existsSync(traceFilePath)) {
|
|
8915
|
+
const stats = fs29.statSync(traceFilePath);
|
|
8916
8916
|
console.log(
|
|
8917
8917
|
`::notice title=AI Trace Saved::OpenTelemetry trace file size: ${stats.size} bytes`
|
|
8918
8918
|
);
|
|
@@ -8950,8 +8950,8 @@ ${"=".repeat(60)}
|
|
|
8950
8950
|
* Load schema content from schema files or inline definitions
|
|
8951
8951
|
*/
|
|
8952
8952
|
async loadSchemaContent(schema) {
|
|
8953
|
-
const
|
|
8954
|
-
const
|
|
8953
|
+
const fs29 = require("fs").promises;
|
|
8954
|
+
const path33 = require("path");
|
|
8955
8955
|
if (typeof schema === "object" && schema !== null) {
|
|
8956
8956
|
log("\u{1F4CB} Using inline schema object from configuration");
|
|
8957
8957
|
return JSON.stringify(schema);
|
|
@@ -8964,14 +8964,14 @@ ${"=".repeat(60)}
|
|
|
8964
8964
|
}
|
|
8965
8965
|
} catch {
|
|
8966
8966
|
}
|
|
8967
|
-
if ((schema.startsWith("./") || schema.includes(".json")) && !
|
|
8967
|
+
if ((schema.startsWith("./") || schema.includes(".json")) && !path33.isAbsolute(schema)) {
|
|
8968
8968
|
if (schema.includes("..") || schema.includes("\0")) {
|
|
8969
8969
|
throw new Error("Invalid schema path: path traversal not allowed");
|
|
8970
8970
|
}
|
|
8971
8971
|
try {
|
|
8972
|
-
const schemaPath =
|
|
8972
|
+
const schemaPath = path33.resolve(process.cwd(), schema);
|
|
8973
8973
|
log(`\u{1F4CB} Loading custom schema from file: ${schemaPath}`);
|
|
8974
|
-
const schemaContent = await
|
|
8974
|
+
const schemaContent = await fs29.readFile(schemaPath, "utf-8");
|
|
8975
8975
|
return schemaContent.trim();
|
|
8976
8976
|
} catch (error) {
|
|
8977
8977
|
throw new Error(
|
|
@@ -8985,22 +8985,22 @@ ${"=".repeat(60)}
|
|
|
8985
8985
|
}
|
|
8986
8986
|
const candidatePaths = [
|
|
8987
8987
|
// GitHub Action bundle location
|
|
8988
|
-
|
|
8988
|
+
path33.join(__dirname, "output", sanitizedSchemaName, "schema.json"),
|
|
8989
8989
|
// Historical fallback when src/output was inadvertently bundled as output1/
|
|
8990
|
-
|
|
8990
|
+
path33.join(__dirname, "output1", sanitizedSchemaName, "schema.json"),
|
|
8991
8991
|
// Local dev (repo root)
|
|
8992
|
-
|
|
8992
|
+
path33.join(process.cwd(), "output", sanitizedSchemaName, "schema.json")
|
|
8993
8993
|
];
|
|
8994
8994
|
for (const schemaPath of candidatePaths) {
|
|
8995
8995
|
try {
|
|
8996
|
-
const schemaContent = await
|
|
8996
|
+
const schemaContent = await fs29.readFile(schemaPath, "utf-8");
|
|
8997
8997
|
return schemaContent.trim();
|
|
8998
8998
|
} catch {
|
|
8999
8999
|
}
|
|
9000
9000
|
}
|
|
9001
|
-
const distPath =
|
|
9002
|
-
const distAltPath =
|
|
9003
|
-
const cwdPath =
|
|
9001
|
+
const distPath = path33.join(__dirname, "output", sanitizedSchemaName, "schema.json");
|
|
9002
|
+
const distAltPath = path33.join(__dirname, "output1", sanitizedSchemaName, "schema.json");
|
|
9003
|
+
const cwdPath = path33.join(process.cwd(), "output", sanitizedSchemaName, "schema.json");
|
|
9004
9004
|
throw new Error(
|
|
9005
9005
|
`Failed to load schema '${sanitizedSchemaName}'. Tried: ${distPath}, ${distAltPath}, and ${cwdPath}. Ensure build copies 'output/' into dist (build:cli), or provide a custom schema file/path.`
|
|
9006
9006
|
);
|
|
@@ -9245,7 +9245,7 @@ ${"=".repeat(60)}
|
|
|
9245
9245
|
* Generate mock response for testing
|
|
9246
9246
|
*/
|
|
9247
9247
|
async generateMockResponse(_prompt, _checkName, _schema) {
|
|
9248
|
-
await new Promise((
|
|
9248
|
+
await new Promise((resolve19) => setTimeout(resolve19, 500));
|
|
9249
9249
|
const name = (_checkName || "").toLowerCase();
|
|
9250
9250
|
if (name.includes("extract-facts")) {
|
|
9251
9251
|
const arr = Array.from({ length: 6 }, (_, i) => ({
|
|
@@ -9606,7 +9606,7 @@ var init_command_executor = __esm({
|
|
|
9606
9606
|
* Execute command with stdin input
|
|
9607
9607
|
*/
|
|
9608
9608
|
executeWithStdin(command, options) {
|
|
9609
|
-
return new Promise((
|
|
9609
|
+
return new Promise((resolve19, reject) => {
|
|
9610
9610
|
const childProcess = (0, import_child_process2.exec)(
|
|
9611
9611
|
command,
|
|
9612
9612
|
{
|
|
@@ -9618,7 +9618,7 @@ var init_command_executor = __esm({
|
|
|
9618
9618
|
if (error && error.killed && (error.code === "ETIMEDOUT" || error.signal === "SIGTERM")) {
|
|
9619
9619
|
reject(new Error(`Command timed out after ${options.timeout || 3e4}ms`));
|
|
9620
9620
|
} else {
|
|
9621
|
-
|
|
9621
|
+
resolve19({
|
|
9622
9622
|
stdout: stdout || "",
|
|
9623
9623
|
stderr: stderr || "",
|
|
9624
9624
|
exitCode: error ? error.code || 1 : 0
|
|
@@ -17998,17 +17998,17 @@ var init_workflow_check_provider = __esm({
|
|
|
17998
17998
|
* so it can be executed by the state machine as a nested workflow.
|
|
17999
17999
|
*/
|
|
18000
18000
|
async loadWorkflowFromConfigPath(sourcePath, baseDir) {
|
|
18001
|
-
const
|
|
18002
|
-
const
|
|
18001
|
+
const path33 = require("path");
|
|
18002
|
+
const fs29 = require("fs");
|
|
18003
18003
|
const yaml5 = require("js-yaml");
|
|
18004
|
-
const resolved =
|
|
18005
|
-
if (!
|
|
18004
|
+
const resolved = path33.isAbsolute(sourcePath) ? sourcePath : path33.resolve(baseDir, sourcePath);
|
|
18005
|
+
if (!fs29.existsSync(resolved)) {
|
|
18006
18006
|
throw new Error(`Workflow config not found at: ${resolved}`);
|
|
18007
18007
|
}
|
|
18008
|
-
const rawContent =
|
|
18008
|
+
const rawContent = fs29.readFileSync(resolved, "utf8");
|
|
18009
18009
|
const rawData = yaml5.load(rawContent);
|
|
18010
18010
|
if (rawData.imports && Array.isArray(rawData.imports)) {
|
|
18011
|
-
const configDir =
|
|
18011
|
+
const configDir = path33.dirname(resolved);
|
|
18012
18012
|
for (const source of rawData.imports) {
|
|
18013
18013
|
const results = await this.registry.import(source, {
|
|
18014
18014
|
basePath: configDir,
|
|
@@ -18038,8 +18038,8 @@ ${errors}`);
|
|
|
18038
18038
|
if (!steps || Object.keys(steps).length === 0) {
|
|
18039
18039
|
throw new Error(`Config '${resolved}' does not contain any steps to execute as a workflow`);
|
|
18040
18040
|
}
|
|
18041
|
-
const id =
|
|
18042
|
-
const name = loaded.name || `Workflow from ${
|
|
18041
|
+
const id = path33.basename(resolved).replace(/\.(ya?ml)$/i, "");
|
|
18042
|
+
const name = loaded.name || `Workflow from ${path33.basename(resolved)}`;
|
|
18043
18043
|
const workflowDef = {
|
|
18044
18044
|
id,
|
|
18045
18045
|
name,
|
|
@@ -18845,8 +18845,8 @@ async function createStoreBackend(storageConfig, haConfig) {
|
|
|
18845
18845
|
case "mssql": {
|
|
18846
18846
|
try {
|
|
18847
18847
|
const loaderPath = "../../enterprise/loader";
|
|
18848
|
-
const { loadEnterpriseStoreBackend } = await import(loaderPath);
|
|
18849
|
-
return await
|
|
18848
|
+
const { loadEnterpriseStoreBackend: loadEnterpriseStoreBackend2 } = await import(loaderPath);
|
|
18849
|
+
return await loadEnterpriseStoreBackend2(driver, storageConfig, haConfig);
|
|
18850
18850
|
} catch (err) {
|
|
18851
18851
|
const msg = err instanceof Error ? err.message : String(err);
|
|
18852
18852
|
logger.error(`[StoreFactory] Failed to load enterprise ${driver} backend: ${msg}`);
|
|
@@ -21524,7 +21524,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21524
21524
|
* Returns the actual bound port number
|
|
21525
21525
|
*/
|
|
21526
21526
|
async start() {
|
|
21527
|
-
return new Promise((
|
|
21527
|
+
return new Promise((resolve19, reject) => {
|
|
21528
21528
|
try {
|
|
21529
21529
|
this.server = import_http.default.createServer((req, res) => {
|
|
21530
21530
|
this.handleRequest(req, res).catch((error) => {
|
|
@@ -21558,7 +21558,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21558
21558
|
);
|
|
21559
21559
|
}
|
|
21560
21560
|
this.startKeepalive();
|
|
21561
|
-
|
|
21561
|
+
resolve19(this.port);
|
|
21562
21562
|
});
|
|
21563
21563
|
} catch (error) {
|
|
21564
21564
|
reject(error);
|
|
@@ -21621,7 +21621,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21621
21621
|
logger.debug(
|
|
21622
21622
|
`[CustomToolsSSEServer:${this.sessionId}] Grace period before stop: ${waitMs}ms (activeToolCalls=${this.activeToolCalls})`
|
|
21623
21623
|
);
|
|
21624
|
-
await new Promise((
|
|
21624
|
+
await new Promise((resolve19) => setTimeout(resolve19, waitMs));
|
|
21625
21625
|
}
|
|
21626
21626
|
}
|
|
21627
21627
|
if (this.activeToolCalls > 0) {
|
|
@@ -21630,7 +21630,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21630
21630
|
`[CustomToolsSSEServer:${this.sessionId}] Waiting for ${this.activeToolCalls} active tool call(s) before stop`
|
|
21631
21631
|
);
|
|
21632
21632
|
while (this.activeToolCalls > 0 && Date.now() - startedAt < effectiveDrainTimeoutMs) {
|
|
21633
|
-
await new Promise((
|
|
21633
|
+
await new Promise((resolve19) => setTimeout(resolve19, 250));
|
|
21634
21634
|
}
|
|
21635
21635
|
if (this.activeToolCalls > 0) {
|
|
21636
21636
|
logger.warn(
|
|
@@ -21655,21 +21655,21 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21655
21655
|
}
|
|
21656
21656
|
this.connections.clear();
|
|
21657
21657
|
if (this.server) {
|
|
21658
|
-
await new Promise((
|
|
21658
|
+
await new Promise((resolve19, reject) => {
|
|
21659
21659
|
const timeout = setTimeout(() => {
|
|
21660
21660
|
if (this.debug) {
|
|
21661
21661
|
logger.debug(
|
|
21662
21662
|
`[CustomToolsSSEServer:${this.sessionId}] Force closing server after timeout`
|
|
21663
21663
|
);
|
|
21664
21664
|
}
|
|
21665
|
-
this.server?.close(() =>
|
|
21665
|
+
this.server?.close(() => resolve19());
|
|
21666
21666
|
}, 5e3);
|
|
21667
21667
|
this.server.close((error) => {
|
|
21668
21668
|
clearTimeout(timeout);
|
|
21669
21669
|
if (error) {
|
|
21670
21670
|
reject(error);
|
|
21671
21671
|
} else {
|
|
21672
|
-
|
|
21672
|
+
resolve19();
|
|
21673
21673
|
}
|
|
21674
21674
|
});
|
|
21675
21675
|
});
|
|
@@ -22104,7 +22104,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22104
22104
|
logger.warn(
|
|
22105
22105
|
`[CustomToolsSSEServer:${this.sessionId}] Tool ${toolName} failed (attempt ${attempt + 1}/${retryCount + 1}): ${errorMsg}. Retrying in ${delay}ms`
|
|
22106
22106
|
);
|
|
22107
|
-
await new Promise((
|
|
22107
|
+
await new Promise((resolve19) => setTimeout(resolve19, delay));
|
|
22108
22108
|
attempt++;
|
|
22109
22109
|
}
|
|
22110
22110
|
}
|
|
@@ -22417,9 +22417,9 @@ var init_ai_check_provider = __esm({
|
|
|
22417
22417
|
} else {
|
|
22418
22418
|
resolvedPath = import_path8.default.resolve(process.cwd(), str);
|
|
22419
22419
|
}
|
|
22420
|
-
const
|
|
22420
|
+
const fs29 = require("fs").promises;
|
|
22421
22421
|
try {
|
|
22422
|
-
const stat2 = await
|
|
22422
|
+
const stat2 = await fs29.stat(resolvedPath);
|
|
22423
22423
|
return stat2.isFile();
|
|
22424
22424
|
} catch {
|
|
22425
22425
|
return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);
|
|
@@ -28521,14 +28521,14 @@ var require_util = __commonJS({
|
|
|
28521
28521
|
}
|
|
28522
28522
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
28523
28523
|
let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`;
|
|
28524
|
-
let
|
|
28524
|
+
let path33 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
28525
28525
|
if (origin.endsWith("/")) {
|
|
28526
28526
|
origin = origin.substring(0, origin.length - 1);
|
|
28527
28527
|
}
|
|
28528
|
-
if (
|
|
28529
|
-
|
|
28528
|
+
if (path33 && !path33.startsWith("/")) {
|
|
28529
|
+
path33 = `/${path33}`;
|
|
28530
28530
|
}
|
|
28531
|
-
url = new URL(origin +
|
|
28531
|
+
url = new URL(origin + path33);
|
|
28532
28532
|
}
|
|
28533
28533
|
return url;
|
|
28534
28534
|
}
|
|
@@ -30142,20 +30142,20 @@ var require_parseParams = __commonJS({
|
|
|
30142
30142
|
var require_basename = __commonJS({
|
|
30143
30143
|
"node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) {
|
|
30144
30144
|
"use strict";
|
|
30145
|
-
module2.exports = function basename4(
|
|
30146
|
-
if (typeof
|
|
30145
|
+
module2.exports = function basename4(path33) {
|
|
30146
|
+
if (typeof path33 !== "string") {
|
|
30147
30147
|
return "";
|
|
30148
30148
|
}
|
|
30149
|
-
for (var i =
|
|
30150
|
-
switch (
|
|
30149
|
+
for (var i = path33.length - 1; i >= 0; --i) {
|
|
30150
|
+
switch (path33.charCodeAt(i)) {
|
|
30151
30151
|
case 47:
|
|
30152
30152
|
// '/'
|
|
30153
30153
|
case 92:
|
|
30154
|
-
|
|
30155
|
-
return
|
|
30154
|
+
path33 = path33.slice(i + 1);
|
|
30155
|
+
return path33 === ".." || path33 === "." ? "" : path33;
|
|
30156
30156
|
}
|
|
30157
30157
|
}
|
|
30158
|
-
return
|
|
30158
|
+
return path33 === ".." || path33 === "." ? "" : path33;
|
|
30159
30159
|
};
|
|
30160
30160
|
}
|
|
30161
30161
|
});
|
|
@@ -31159,11 +31159,11 @@ var require_util2 = __commonJS({
|
|
|
31159
31159
|
var assert = require("assert");
|
|
31160
31160
|
var { isUint8Array } = require("util/types");
|
|
31161
31161
|
var supportedHashes = [];
|
|
31162
|
-
var
|
|
31162
|
+
var crypto9;
|
|
31163
31163
|
try {
|
|
31164
|
-
|
|
31164
|
+
crypto9 = require("crypto");
|
|
31165
31165
|
const possibleRelevantHashes = ["sha256", "sha384", "sha512"];
|
|
31166
|
-
supportedHashes =
|
|
31166
|
+
supportedHashes = crypto9.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
|
|
31167
31167
|
} catch {
|
|
31168
31168
|
}
|
|
31169
31169
|
function responseURL(response) {
|
|
@@ -31440,7 +31440,7 @@ var require_util2 = __commonJS({
|
|
|
31440
31440
|
}
|
|
31441
31441
|
}
|
|
31442
31442
|
function bytesMatch(bytes, metadataList) {
|
|
31443
|
-
if (
|
|
31443
|
+
if (crypto9 === void 0) {
|
|
31444
31444
|
return true;
|
|
31445
31445
|
}
|
|
31446
31446
|
const parsedMetadata = parseMetadata(metadataList);
|
|
@@ -31455,7 +31455,7 @@ var require_util2 = __commonJS({
|
|
|
31455
31455
|
for (const item of metadata) {
|
|
31456
31456
|
const algorithm = item.algo;
|
|
31457
31457
|
const expectedValue = item.hash;
|
|
31458
|
-
let actualValue =
|
|
31458
|
+
let actualValue = crypto9.createHash(algorithm).update(bytes).digest("base64");
|
|
31459
31459
|
if (actualValue[actualValue.length - 1] === "=") {
|
|
31460
31460
|
if (actualValue[actualValue.length - 2] === "=") {
|
|
31461
31461
|
actualValue = actualValue.slice(0, -2);
|
|
@@ -31548,8 +31548,8 @@ var require_util2 = __commonJS({
|
|
|
31548
31548
|
function createDeferredPromise() {
|
|
31549
31549
|
let res;
|
|
31550
31550
|
let rej;
|
|
31551
|
-
const promise = new Promise((
|
|
31552
|
-
res =
|
|
31551
|
+
const promise = new Promise((resolve19, reject) => {
|
|
31552
|
+
res = resolve19;
|
|
31553
31553
|
rej = reject;
|
|
31554
31554
|
});
|
|
31555
31555
|
return { promise, resolve: res, reject: rej };
|
|
@@ -32802,8 +32802,8 @@ var require_body = __commonJS({
|
|
|
32802
32802
|
var { parseMIMEType, serializeAMimeType } = require_dataURL();
|
|
32803
32803
|
var random;
|
|
32804
32804
|
try {
|
|
32805
|
-
const
|
|
32806
|
-
random = (max) =>
|
|
32805
|
+
const crypto9 = require("crypto");
|
|
32806
|
+
random = (max) => crypto9.randomInt(0, max);
|
|
32807
32807
|
} catch {
|
|
32808
32808
|
random = (max) => Math.floor(Math.random(max));
|
|
32809
32809
|
}
|
|
@@ -33054,8 +33054,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r
|
|
|
33054
33054
|
});
|
|
33055
33055
|
}
|
|
33056
33056
|
});
|
|
33057
|
-
const busboyResolve = new Promise((
|
|
33058
|
-
busboy.on("finish",
|
|
33057
|
+
const busboyResolve = new Promise((resolve19, reject) => {
|
|
33058
|
+
busboy.on("finish", resolve19);
|
|
33059
33059
|
busboy.on("error", (err) => reject(new TypeError(err)));
|
|
33060
33060
|
});
|
|
33061
33061
|
if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk);
|
|
@@ -33186,7 +33186,7 @@ var require_request = __commonJS({
|
|
|
33186
33186
|
}
|
|
33187
33187
|
var Request = class _Request {
|
|
33188
33188
|
constructor(origin, {
|
|
33189
|
-
path:
|
|
33189
|
+
path: path33,
|
|
33190
33190
|
method,
|
|
33191
33191
|
body,
|
|
33192
33192
|
headers,
|
|
@@ -33200,11 +33200,11 @@ var require_request = __commonJS({
|
|
|
33200
33200
|
throwOnError,
|
|
33201
33201
|
expectContinue
|
|
33202
33202
|
}, handler) {
|
|
33203
|
-
if (typeof
|
|
33203
|
+
if (typeof path33 !== "string") {
|
|
33204
33204
|
throw new InvalidArgumentError("path must be a string");
|
|
33205
|
-
} else if (
|
|
33205
|
+
} else if (path33[0] !== "/" && !(path33.startsWith("http://") || path33.startsWith("https://")) && method !== "CONNECT") {
|
|
33206
33206
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
33207
|
-
} else if (invalidPathRegex.exec(
|
|
33207
|
+
} else if (invalidPathRegex.exec(path33) !== null) {
|
|
33208
33208
|
throw new InvalidArgumentError("invalid request path");
|
|
33209
33209
|
}
|
|
33210
33210
|
if (typeof method !== "string") {
|
|
@@ -33267,7 +33267,7 @@ var require_request = __commonJS({
|
|
|
33267
33267
|
this.completed = false;
|
|
33268
33268
|
this.aborted = false;
|
|
33269
33269
|
this.upgrade = upgrade || null;
|
|
33270
|
-
this.path = query ? util.buildURL(
|
|
33270
|
+
this.path = query ? util.buildURL(path33, query) : path33;
|
|
33271
33271
|
this.origin = origin;
|
|
33272
33272
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
33273
33273
|
this.blocking = blocking == null ? false : blocking;
|
|
@@ -33589,9 +33589,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
33589
33589
|
}
|
|
33590
33590
|
close(callback) {
|
|
33591
33591
|
if (callback === void 0) {
|
|
33592
|
-
return new Promise((
|
|
33592
|
+
return new Promise((resolve19, reject) => {
|
|
33593
33593
|
this.close((err, data) => {
|
|
33594
|
-
return err ? reject(err) :
|
|
33594
|
+
return err ? reject(err) : resolve19(data);
|
|
33595
33595
|
});
|
|
33596
33596
|
});
|
|
33597
33597
|
}
|
|
@@ -33629,12 +33629,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
33629
33629
|
err = null;
|
|
33630
33630
|
}
|
|
33631
33631
|
if (callback === void 0) {
|
|
33632
|
-
return new Promise((
|
|
33632
|
+
return new Promise((resolve19, reject) => {
|
|
33633
33633
|
this.destroy(err, (err2, data) => {
|
|
33634
33634
|
return err2 ? (
|
|
33635
33635
|
/* istanbul ignore next: should never error */
|
|
33636
33636
|
reject(err2)
|
|
33637
|
-
) :
|
|
33637
|
+
) : resolve19(data);
|
|
33638
33638
|
});
|
|
33639
33639
|
});
|
|
33640
33640
|
}
|
|
@@ -34275,9 +34275,9 @@ var require_RedirectHandler = __commonJS({
|
|
|
34275
34275
|
return this.handler.onHeaders(statusCode, headers, resume, statusText);
|
|
34276
34276
|
}
|
|
34277
34277
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
34278
|
-
const
|
|
34278
|
+
const path33 = search ? `${pathname}${search}` : pathname;
|
|
34279
34279
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
34280
|
-
this.opts.path =
|
|
34280
|
+
this.opts.path = path33;
|
|
34281
34281
|
this.opts.origin = origin;
|
|
34282
34282
|
this.opts.maxRedirections = 0;
|
|
34283
34283
|
this.opts.query = null;
|
|
@@ -34696,16 +34696,16 @@ var require_client = __commonJS({
|
|
|
34696
34696
|
return this[kNeedDrain] < 2;
|
|
34697
34697
|
}
|
|
34698
34698
|
async [kClose]() {
|
|
34699
|
-
return new Promise((
|
|
34699
|
+
return new Promise((resolve19) => {
|
|
34700
34700
|
if (!this[kSize]) {
|
|
34701
|
-
|
|
34701
|
+
resolve19(null);
|
|
34702
34702
|
} else {
|
|
34703
|
-
this[kClosedResolve] =
|
|
34703
|
+
this[kClosedResolve] = resolve19;
|
|
34704
34704
|
}
|
|
34705
34705
|
});
|
|
34706
34706
|
}
|
|
34707
34707
|
async [kDestroy](err) {
|
|
34708
|
-
return new Promise((
|
|
34708
|
+
return new Promise((resolve19) => {
|
|
34709
34709
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
34710
34710
|
for (let i = 0; i < requests.length; i++) {
|
|
34711
34711
|
const request = requests[i];
|
|
@@ -34716,7 +34716,7 @@ var require_client = __commonJS({
|
|
|
34716
34716
|
this[kClosedResolve]();
|
|
34717
34717
|
this[kClosedResolve] = null;
|
|
34718
34718
|
}
|
|
34719
|
-
|
|
34719
|
+
resolve19();
|
|
34720
34720
|
};
|
|
34721
34721
|
if (this[kHTTP2Session] != null) {
|
|
34722
34722
|
util.destroy(this[kHTTP2Session], err);
|
|
@@ -35296,7 +35296,7 @@ var require_client = __commonJS({
|
|
|
35296
35296
|
});
|
|
35297
35297
|
}
|
|
35298
35298
|
try {
|
|
35299
|
-
const socket = await new Promise((
|
|
35299
|
+
const socket = await new Promise((resolve19, reject) => {
|
|
35300
35300
|
client[kConnector]({
|
|
35301
35301
|
host,
|
|
35302
35302
|
hostname,
|
|
@@ -35308,7 +35308,7 @@ var require_client = __commonJS({
|
|
|
35308
35308
|
if (err) {
|
|
35309
35309
|
reject(err);
|
|
35310
35310
|
} else {
|
|
35311
|
-
|
|
35311
|
+
resolve19(socket2);
|
|
35312
35312
|
}
|
|
35313
35313
|
});
|
|
35314
35314
|
});
|
|
@@ -35519,7 +35519,7 @@ var require_client = __commonJS({
|
|
|
35519
35519
|
writeH2(client, client[kHTTP2Session], request);
|
|
35520
35520
|
return;
|
|
35521
35521
|
}
|
|
35522
|
-
const { body, method, path:
|
|
35522
|
+
const { body, method, path: path33, host, upgrade, headers, blocking, reset } = request;
|
|
35523
35523
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
35524
35524
|
if (body && typeof body.read === "function") {
|
|
35525
35525
|
body.read(0);
|
|
@@ -35569,7 +35569,7 @@ var require_client = __commonJS({
|
|
|
35569
35569
|
if (blocking) {
|
|
35570
35570
|
socket[kBlocking] = true;
|
|
35571
35571
|
}
|
|
35572
|
-
let header = `${method} ${
|
|
35572
|
+
let header = `${method} ${path33} HTTP/1.1\r
|
|
35573
35573
|
`;
|
|
35574
35574
|
if (typeof host === "string") {
|
|
35575
35575
|
header += `host: ${host}\r
|
|
@@ -35632,7 +35632,7 @@ upgrade: ${upgrade}\r
|
|
|
35632
35632
|
return true;
|
|
35633
35633
|
}
|
|
35634
35634
|
function writeH2(client, session, request) {
|
|
35635
|
-
const { body, method, path:
|
|
35635
|
+
const { body, method, path: path33, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
|
|
35636
35636
|
let headers;
|
|
35637
35637
|
if (typeof reqHeaders === "string") headers = Request[kHTTP2CopyHeaders](reqHeaders.trim());
|
|
35638
35638
|
else headers = reqHeaders;
|
|
@@ -35675,7 +35675,7 @@ upgrade: ${upgrade}\r
|
|
|
35675
35675
|
});
|
|
35676
35676
|
return true;
|
|
35677
35677
|
}
|
|
35678
|
-
headers[HTTP2_HEADER_PATH] =
|
|
35678
|
+
headers[HTTP2_HEADER_PATH] = path33;
|
|
35679
35679
|
headers[HTTP2_HEADER_SCHEME] = "https";
|
|
35680
35680
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
35681
35681
|
if (body && typeof body.read === "function") {
|
|
@@ -35932,12 +35932,12 @@ upgrade: ${upgrade}\r
|
|
|
35932
35932
|
cb();
|
|
35933
35933
|
}
|
|
35934
35934
|
}
|
|
35935
|
-
const waitForDrain = () => new Promise((
|
|
35935
|
+
const waitForDrain = () => new Promise((resolve19, reject) => {
|
|
35936
35936
|
assert(callback === null);
|
|
35937
35937
|
if (socket[kError]) {
|
|
35938
35938
|
reject(socket[kError]);
|
|
35939
35939
|
} else {
|
|
35940
|
-
callback =
|
|
35940
|
+
callback = resolve19;
|
|
35941
35941
|
}
|
|
35942
35942
|
});
|
|
35943
35943
|
if (client[kHTTPConnVersion] === "h2") {
|
|
@@ -36283,8 +36283,8 @@ var require_pool_base = __commonJS({
|
|
|
36283
36283
|
if (this[kQueue].isEmpty()) {
|
|
36284
36284
|
return Promise.all(this[kClients].map((c) => c.close()));
|
|
36285
36285
|
} else {
|
|
36286
|
-
return new Promise((
|
|
36287
|
-
this[kClosedResolve] =
|
|
36286
|
+
return new Promise((resolve19) => {
|
|
36287
|
+
this[kClosedResolve] = resolve19;
|
|
36288
36288
|
});
|
|
36289
36289
|
}
|
|
36290
36290
|
}
|
|
@@ -36862,7 +36862,7 @@ var require_readable = __commonJS({
|
|
|
36862
36862
|
if (this.closed) {
|
|
36863
36863
|
return Promise.resolve(null);
|
|
36864
36864
|
}
|
|
36865
|
-
return new Promise((
|
|
36865
|
+
return new Promise((resolve19, reject) => {
|
|
36866
36866
|
const signalListenerCleanup = signal ? util.addAbortListener(signal, () => {
|
|
36867
36867
|
this.destroy();
|
|
36868
36868
|
}) : noop;
|
|
@@ -36871,7 +36871,7 @@ var require_readable = __commonJS({
|
|
|
36871
36871
|
if (signal && signal.aborted) {
|
|
36872
36872
|
reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" }));
|
|
36873
36873
|
} else {
|
|
36874
|
-
|
|
36874
|
+
resolve19(null);
|
|
36875
36875
|
}
|
|
36876
36876
|
}).on("error", noop).on("data", function(chunk) {
|
|
36877
36877
|
limit -= chunk.length;
|
|
@@ -36893,11 +36893,11 @@ var require_readable = __commonJS({
|
|
|
36893
36893
|
throw new TypeError("unusable");
|
|
36894
36894
|
}
|
|
36895
36895
|
assert(!stream[kConsume]);
|
|
36896
|
-
return new Promise((
|
|
36896
|
+
return new Promise((resolve19, reject) => {
|
|
36897
36897
|
stream[kConsume] = {
|
|
36898
36898
|
type,
|
|
36899
36899
|
stream,
|
|
36900
|
-
resolve:
|
|
36900
|
+
resolve: resolve19,
|
|
36901
36901
|
reject,
|
|
36902
36902
|
length: 0,
|
|
36903
36903
|
body: []
|
|
@@ -36932,12 +36932,12 @@ var require_readable = __commonJS({
|
|
|
36932
36932
|
}
|
|
36933
36933
|
}
|
|
36934
36934
|
function consumeEnd(consume2) {
|
|
36935
|
-
const { type, body, resolve:
|
|
36935
|
+
const { type, body, resolve: resolve19, stream, length } = consume2;
|
|
36936
36936
|
try {
|
|
36937
36937
|
if (type === "text") {
|
|
36938
|
-
|
|
36938
|
+
resolve19(toUSVString(Buffer.concat(body)));
|
|
36939
36939
|
} else if (type === "json") {
|
|
36940
|
-
|
|
36940
|
+
resolve19(JSON.parse(Buffer.concat(body)));
|
|
36941
36941
|
} else if (type === "arrayBuffer") {
|
|
36942
36942
|
const dst = new Uint8Array(length);
|
|
36943
36943
|
let pos = 0;
|
|
@@ -36945,12 +36945,12 @@ var require_readable = __commonJS({
|
|
|
36945
36945
|
dst.set(buf, pos);
|
|
36946
36946
|
pos += buf.byteLength;
|
|
36947
36947
|
}
|
|
36948
|
-
|
|
36948
|
+
resolve19(dst.buffer);
|
|
36949
36949
|
} else if (type === "blob") {
|
|
36950
36950
|
if (!Blob2) {
|
|
36951
36951
|
Blob2 = require("buffer").Blob;
|
|
36952
36952
|
}
|
|
36953
|
-
|
|
36953
|
+
resolve19(new Blob2(body, { type: stream[kContentType] }));
|
|
36954
36954
|
}
|
|
36955
36955
|
consumeFinish(consume2);
|
|
36956
36956
|
} catch (err) {
|
|
@@ -37207,9 +37207,9 @@ var require_api_request = __commonJS({
|
|
|
37207
37207
|
};
|
|
37208
37208
|
function request(opts, callback) {
|
|
37209
37209
|
if (callback === void 0) {
|
|
37210
|
-
return new Promise((
|
|
37210
|
+
return new Promise((resolve19, reject) => {
|
|
37211
37211
|
request.call(this, opts, (err, data) => {
|
|
37212
|
-
return err ? reject(err) :
|
|
37212
|
+
return err ? reject(err) : resolve19(data);
|
|
37213
37213
|
});
|
|
37214
37214
|
});
|
|
37215
37215
|
}
|
|
@@ -37382,9 +37382,9 @@ var require_api_stream = __commonJS({
|
|
|
37382
37382
|
};
|
|
37383
37383
|
function stream(opts, factory, callback) {
|
|
37384
37384
|
if (callback === void 0) {
|
|
37385
|
-
return new Promise((
|
|
37385
|
+
return new Promise((resolve19, reject) => {
|
|
37386
37386
|
stream.call(this, opts, factory, (err, data) => {
|
|
37387
|
-
return err ? reject(err) :
|
|
37387
|
+
return err ? reject(err) : resolve19(data);
|
|
37388
37388
|
});
|
|
37389
37389
|
});
|
|
37390
37390
|
}
|
|
@@ -37665,9 +37665,9 @@ var require_api_upgrade = __commonJS({
|
|
|
37665
37665
|
};
|
|
37666
37666
|
function upgrade(opts, callback) {
|
|
37667
37667
|
if (callback === void 0) {
|
|
37668
|
-
return new Promise((
|
|
37668
|
+
return new Promise((resolve19, reject) => {
|
|
37669
37669
|
upgrade.call(this, opts, (err, data) => {
|
|
37670
|
-
return err ? reject(err) :
|
|
37670
|
+
return err ? reject(err) : resolve19(data);
|
|
37671
37671
|
});
|
|
37672
37672
|
});
|
|
37673
37673
|
}
|
|
@@ -37756,9 +37756,9 @@ var require_api_connect = __commonJS({
|
|
|
37756
37756
|
};
|
|
37757
37757
|
function connect(opts, callback) {
|
|
37758
37758
|
if (callback === void 0) {
|
|
37759
|
-
return new Promise((
|
|
37759
|
+
return new Promise((resolve19, reject) => {
|
|
37760
37760
|
connect.call(this, opts, (err, data) => {
|
|
37761
|
-
return err ? reject(err) :
|
|
37761
|
+
return err ? reject(err) : resolve19(data);
|
|
37762
37762
|
});
|
|
37763
37763
|
});
|
|
37764
37764
|
}
|
|
@@ -37918,20 +37918,20 @@ var require_mock_utils = __commonJS({
|
|
|
37918
37918
|
}
|
|
37919
37919
|
return true;
|
|
37920
37920
|
}
|
|
37921
|
-
function safeUrl(
|
|
37922
|
-
if (typeof
|
|
37923
|
-
return
|
|
37921
|
+
function safeUrl(path33) {
|
|
37922
|
+
if (typeof path33 !== "string") {
|
|
37923
|
+
return path33;
|
|
37924
37924
|
}
|
|
37925
|
-
const pathSegments =
|
|
37925
|
+
const pathSegments = path33.split("?");
|
|
37926
37926
|
if (pathSegments.length !== 2) {
|
|
37927
|
-
return
|
|
37927
|
+
return path33;
|
|
37928
37928
|
}
|
|
37929
37929
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
37930
37930
|
qp.sort();
|
|
37931
37931
|
return [...pathSegments, qp.toString()].join("?");
|
|
37932
37932
|
}
|
|
37933
|
-
function matchKey(mockDispatch2, { path:
|
|
37934
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
37933
|
+
function matchKey(mockDispatch2, { path: path33, method, body, headers }) {
|
|
37934
|
+
const pathMatch = matchValue(mockDispatch2.path, path33);
|
|
37935
37935
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
37936
37936
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
37937
37937
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -37949,7 +37949,7 @@ var require_mock_utils = __commonJS({
|
|
|
37949
37949
|
function getMockDispatch(mockDispatches, key) {
|
|
37950
37950
|
const basePath = key.query ? buildURL(key.path, key.query) : key.path;
|
|
37951
37951
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
37952
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
37952
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path33 }) => matchValue(safeUrl(path33), resolvedPath));
|
|
37953
37953
|
if (matchedMockDispatches.length === 0) {
|
|
37954
37954
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
37955
37955
|
}
|
|
@@ -37986,9 +37986,9 @@ var require_mock_utils = __commonJS({
|
|
|
37986
37986
|
}
|
|
37987
37987
|
}
|
|
37988
37988
|
function buildKey(opts) {
|
|
37989
|
-
const { path:
|
|
37989
|
+
const { path: path33, method, body, headers, query } = opts;
|
|
37990
37990
|
return {
|
|
37991
|
-
path:
|
|
37991
|
+
path: path33,
|
|
37992
37992
|
method,
|
|
37993
37993
|
body,
|
|
37994
37994
|
headers,
|
|
@@ -38437,10 +38437,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
38437
38437
|
}
|
|
38438
38438
|
format(pendingInterceptors) {
|
|
38439
38439
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
38440
|
-
({ method, path:
|
|
38440
|
+
({ method, path: path33, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
38441
38441
|
Method: method,
|
|
38442
38442
|
Origin: origin,
|
|
38443
|
-
Path:
|
|
38443
|
+
Path: path33,
|
|
38444
38444
|
"Status code": statusCode,
|
|
38445
38445
|
Persistent: persist ? "\u2705" : "\u274C",
|
|
38446
38446
|
Invocations: timesInvoked,
|
|
@@ -41381,7 +41381,7 @@ var require_fetch = __commonJS({
|
|
|
41381
41381
|
async function dispatch({ body }) {
|
|
41382
41382
|
const url = requestCurrentURL(request);
|
|
41383
41383
|
const agent = fetchParams.controller.dispatcher;
|
|
41384
|
-
return new Promise((
|
|
41384
|
+
return new Promise((resolve19, reject) => agent.dispatch(
|
|
41385
41385
|
{
|
|
41386
41386
|
path: url.pathname + url.search,
|
|
41387
41387
|
origin: url.origin,
|
|
@@ -41457,7 +41457,7 @@ var require_fetch = __commonJS({
|
|
|
41457
41457
|
}
|
|
41458
41458
|
}
|
|
41459
41459
|
}
|
|
41460
|
-
|
|
41460
|
+
resolve19({
|
|
41461
41461
|
status,
|
|
41462
41462
|
statusText,
|
|
41463
41463
|
headersList: headers[kHeadersList],
|
|
@@ -41500,7 +41500,7 @@ var require_fetch = __commonJS({
|
|
|
41500
41500
|
const val = headersList[n + 1].toString("latin1");
|
|
41501
41501
|
headers[kHeadersList].append(key, val);
|
|
41502
41502
|
}
|
|
41503
|
-
|
|
41503
|
+
resolve19({
|
|
41504
41504
|
status,
|
|
41505
41505
|
statusText: STATUS_CODES[status],
|
|
41506
41506
|
headersList: headers[kHeadersList],
|
|
@@ -43061,8 +43061,8 @@ var require_util6 = __commonJS({
|
|
|
43061
43061
|
}
|
|
43062
43062
|
}
|
|
43063
43063
|
}
|
|
43064
|
-
function validateCookiePath(
|
|
43065
|
-
for (const char of
|
|
43064
|
+
function validateCookiePath(path33) {
|
|
43065
|
+
for (const char of path33) {
|
|
43066
43066
|
const code = char.charCodeAt(0);
|
|
43067
43067
|
if (code < 33 || char === ";") {
|
|
43068
43068
|
throw new Error("Invalid cookie path");
|
|
@@ -43859,9 +43859,9 @@ var require_connection = __commonJS({
|
|
|
43859
43859
|
channels.open = diagnosticsChannel.channel("undici:websocket:open");
|
|
43860
43860
|
channels.close = diagnosticsChannel.channel("undici:websocket:close");
|
|
43861
43861
|
channels.socketError = diagnosticsChannel.channel("undici:websocket:socket_error");
|
|
43862
|
-
var
|
|
43862
|
+
var crypto9;
|
|
43863
43863
|
try {
|
|
43864
|
-
|
|
43864
|
+
crypto9 = require("crypto");
|
|
43865
43865
|
} catch {
|
|
43866
43866
|
}
|
|
43867
43867
|
function establishWebSocketConnection(url, protocols, ws, onEstablish, options) {
|
|
@@ -43880,7 +43880,7 @@ var require_connection = __commonJS({
|
|
|
43880
43880
|
const headersList = new Headers(options.headers)[kHeadersList];
|
|
43881
43881
|
request.headersList = headersList;
|
|
43882
43882
|
}
|
|
43883
|
-
const keyValue =
|
|
43883
|
+
const keyValue = crypto9.randomBytes(16).toString("base64");
|
|
43884
43884
|
request.headersList.append("sec-websocket-key", keyValue);
|
|
43885
43885
|
request.headersList.append("sec-websocket-version", "13");
|
|
43886
43886
|
for (const protocol of protocols) {
|
|
@@ -43909,7 +43909,7 @@ var require_connection = __commonJS({
|
|
|
43909
43909
|
return;
|
|
43910
43910
|
}
|
|
43911
43911
|
const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
|
|
43912
|
-
const digest =
|
|
43912
|
+
const digest = crypto9.createHash("sha1").update(keyValue + uid).digest("base64");
|
|
43913
43913
|
if (secWSAccept !== digest) {
|
|
43914
43914
|
failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header.");
|
|
43915
43915
|
return;
|
|
@@ -43989,9 +43989,9 @@ var require_frame = __commonJS({
|
|
|
43989
43989
|
"node_modules/undici/lib/websocket/frame.js"(exports2, module2) {
|
|
43990
43990
|
"use strict";
|
|
43991
43991
|
var { maxUnsigned16Bit } = require_constants5();
|
|
43992
|
-
var
|
|
43992
|
+
var crypto9;
|
|
43993
43993
|
try {
|
|
43994
|
-
|
|
43994
|
+
crypto9 = require("crypto");
|
|
43995
43995
|
} catch {
|
|
43996
43996
|
}
|
|
43997
43997
|
var WebsocketFrameSend = class {
|
|
@@ -44000,7 +44000,7 @@ var require_frame = __commonJS({
|
|
|
44000
44000
|
*/
|
|
44001
44001
|
constructor(data) {
|
|
44002
44002
|
this.frameData = data;
|
|
44003
|
-
this.maskKey =
|
|
44003
|
+
this.maskKey = crypto9.randomBytes(4);
|
|
44004
44004
|
}
|
|
44005
44005
|
createFrame(opcode) {
|
|
44006
44006
|
const bodyLength = this.frameData?.byteLength ?? 0;
|
|
@@ -44742,11 +44742,11 @@ var require_undici = __commonJS({
|
|
|
44742
44742
|
if (typeof opts.path !== "string") {
|
|
44743
44743
|
throw new InvalidArgumentError("invalid opts.path");
|
|
44744
44744
|
}
|
|
44745
|
-
let
|
|
44745
|
+
let path33 = opts.path;
|
|
44746
44746
|
if (!opts.path.startsWith("/")) {
|
|
44747
|
-
|
|
44747
|
+
path33 = `/${path33}`;
|
|
44748
44748
|
}
|
|
44749
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
44749
|
+
url = new URL(util.parseOrigin(url).origin + path33);
|
|
44750
44750
|
} else {
|
|
44751
44751
|
if (!opts) {
|
|
44752
44752
|
opts = typeof url === "object" ? url : {};
|
|
@@ -45295,7 +45295,7 @@ var init_mcp_check_provider = __esm({
|
|
|
45295
45295
|
logger.warn(
|
|
45296
45296
|
`MCP ${transportName} failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`
|
|
45297
45297
|
);
|
|
45298
|
-
await new Promise((
|
|
45298
|
+
await new Promise((resolve19) => setTimeout(resolve19, delay));
|
|
45299
45299
|
attempt += 1;
|
|
45300
45300
|
} finally {
|
|
45301
45301
|
try {
|
|
@@ -45588,7 +45588,7 @@ async function acquirePromptLock() {
|
|
|
45588
45588
|
);
|
|
45589
45589
|
}, 1e4);
|
|
45590
45590
|
try {
|
|
45591
|
-
await new Promise((
|
|
45591
|
+
await new Promise((resolve19) => waiters.push(resolve19));
|
|
45592
45592
|
} finally {
|
|
45593
45593
|
clearInterval(reminder);
|
|
45594
45594
|
const waitedMs = Date.now() - queuedAt;
|
|
@@ -45607,7 +45607,7 @@ function releasePromptLock() {
|
|
|
45607
45607
|
}
|
|
45608
45608
|
async function interactivePrompt(options) {
|
|
45609
45609
|
await acquirePromptLock();
|
|
45610
|
-
return new Promise((
|
|
45610
|
+
return new Promise((resolve19, reject) => {
|
|
45611
45611
|
const dbg = process.env.VISOR_DEBUG === "true";
|
|
45612
45612
|
try {
|
|
45613
45613
|
if (dbg) {
|
|
@@ -45694,12 +45694,12 @@ async function interactivePrompt(options) {
|
|
|
45694
45694
|
};
|
|
45695
45695
|
const finish = (value) => {
|
|
45696
45696
|
cleanup();
|
|
45697
|
-
|
|
45697
|
+
resolve19(value);
|
|
45698
45698
|
};
|
|
45699
45699
|
if (options.timeout && options.timeout > 0) {
|
|
45700
45700
|
timeoutId = setTimeout(() => {
|
|
45701
45701
|
cleanup();
|
|
45702
|
-
if (defaultValue !== void 0) return
|
|
45702
|
+
if (defaultValue !== void 0) return resolve19(defaultValue);
|
|
45703
45703
|
return reject(new Error("Input timeout"));
|
|
45704
45704
|
}, options.timeout);
|
|
45705
45705
|
}
|
|
@@ -45831,7 +45831,7 @@ async function interactivePrompt(options) {
|
|
|
45831
45831
|
});
|
|
45832
45832
|
}
|
|
45833
45833
|
async function simplePrompt(prompt) {
|
|
45834
|
-
return new Promise((
|
|
45834
|
+
return new Promise((resolve19) => {
|
|
45835
45835
|
const rl = readline.createInterface({
|
|
45836
45836
|
input: process.stdin,
|
|
45837
45837
|
output: process.stdout
|
|
@@ -45847,7 +45847,7 @@ async function simplePrompt(prompt) {
|
|
|
45847
45847
|
rl.question(`${prompt}
|
|
45848
45848
|
> `, (answer) => {
|
|
45849
45849
|
rl.close();
|
|
45850
|
-
|
|
45850
|
+
resolve19(answer.trim());
|
|
45851
45851
|
});
|
|
45852
45852
|
});
|
|
45853
45853
|
}
|
|
@@ -46015,7 +46015,7 @@ function isStdinAvailable() {
|
|
|
46015
46015
|
return !process.stdin.isTTY;
|
|
46016
46016
|
}
|
|
46017
46017
|
async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
46018
|
-
return new Promise((
|
|
46018
|
+
return new Promise((resolve19, reject) => {
|
|
46019
46019
|
let data = "";
|
|
46020
46020
|
let timeoutId;
|
|
46021
46021
|
if (timeout) {
|
|
@@ -46042,7 +46042,7 @@ async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
|
46042
46042
|
};
|
|
46043
46043
|
const onEnd = () => {
|
|
46044
46044
|
cleanup();
|
|
46045
|
-
|
|
46045
|
+
resolve19(data.trim());
|
|
46046
46046
|
};
|
|
46047
46047
|
const onError = (err) => {
|
|
46048
46048
|
cleanup();
|
|
@@ -50733,23 +50733,23 @@ __export(renderer_schema_exports, {
|
|
|
50733
50733
|
});
|
|
50734
50734
|
async function loadRendererSchema(name) {
|
|
50735
50735
|
try {
|
|
50736
|
-
const
|
|
50737
|
-
const
|
|
50736
|
+
const fs29 = await import("fs/promises");
|
|
50737
|
+
const path33 = await import("path");
|
|
50738
50738
|
const sanitized = String(name).replace(/[^a-zA-Z0-9-]/g, "");
|
|
50739
50739
|
if (!sanitized) return void 0;
|
|
50740
50740
|
const candidates = [
|
|
50741
50741
|
// When bundled with ncc, __dirname is dist/ and output/ is at dist/output/
|
|
50742
|
-
|
|
50742
|
+
path33.join(__dirname, "output", sanitized, "schema.json"),
|
|
50743
50743
|
// When running from source, __dirname is src/state-machine/dispatch/ and output/ is at output/
|
|
50744
|
-
|
|
50744
|
+
path33.join(__dirname, "..", "..", "output", sanitized, "schema.json"),
|
|
50745
50745
|
// When running from a checkout with output/ folder copied to CWD
|
|
50746
|
-
|
|
50746
|
+
path33.join(process.cwd(), "output", sanitized, "schema.json"),
|
|
50747
50747
|
// Fallback: cwd/dist/output/
|
|
50748
|
-
|
|
50748
|
+
path33.join(process.cwd(), "dist", "output", sanitized, "schema.json")
|
|
50749
50749
|
];
|
|
50750
50750
|
for (const p of candidates) {
|
|
50751
50751
|
try {
|
|
50752
|
-
const raw = await
|
|
50752
|
+
const raw = await fs29.readFile(p, "utf-8");
|
|
50753
50753
|
return JSON.parse(raw);
|
|
50754
50754
|
} catch {
|
|
50755
50755
|
}
|
|
@@ -53190,8 +53190,8 @@ function updateStats2(results, state, isForEachIteration = false) {
|
|
|
53190
53190
|
async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
53191
53191
|
try {
|
|
53192
53192
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
53193
|
-
const
|
|
53194
|
-
const
|
|
53193
|
+
const fs29 = await import("fs/promises");
|
|
53194
|
+
const path33 = await import("path");
|
|
53195
53195
|
const schemaRaw = checkConfig.schema || "plain";
|
|
53196
53196
|
const schema = typeof schemaRaw === "string" && !schemaRaw.includes("{{") && !schemaRaw.includes("{%") ? schemaRaw : typeof schemaRaw === "object" ? "code-review" : "plain";
|
|
53197
53197
|
let templateContent;
|
|
@@ -53200,27 +53200,27 @@ async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
|
53200
53200
|
logger.debug(`[LevelDispatch] Using inline template for ${checkId}`);
|
|
53201
53201
|
} else if (checkConfig.template && checkConfig.template.file) {
|
|
53202
53202
|
const file = String(checkConfig.template.file);
|
|
53203
|
-
const resolved =
|
|
53204
|
-
templateContent = await
|
|
53203
|
+
const resolved = path33.resolve(process.cwd(), file);
|
|
53204
|
+
templateContent = await fs29.readFile(resolved, "utf-8");
|
|
53205
53205
|
logger.debug(`[LevelDispatch] Using template file for ${checkId}: ${resolved}`);
|
|
53206
53206
|
} else if (schema && schema !== "plain") {
|
|
53207
53207
|
const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
|
|
53208
53208
|
if (sanitized) {
|
|
53209
53209
|
const candidatePaths = [
|
|
53210
|
-
|
|
53210
|
+
path33.join(__dirname, "output", sanitized, "template.liquid"),
|
|
53211
53211
|
// bundled: dist/output/
|
|
53212
|
-
|
|
53212
|
+
path33.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
53213
53213
|
// source (from state-machine/states)
|
|
53214
|
-
|
|
53214
|
+
path33.join(__dirname, "..", "..", "..", "output", sanitized, "template.liquid"),
|
|
53215
53215
|
// source (alternate)
|
|
53216
|
-
|
|
53216
|
+
path33.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
53217
53217
|
// fallback: cwd/output/
|
|
53218
|
-
|
|
53218
|
+
path33.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
|
|
53219
53219
|
// fallback: cwd/dist/output/
|
|
53220
53220
|
];
|
|
53221
53221
|
for (const p of candidatePaths) {
|
|
53222
53222
|
try {
|
|
53223
|
-
templateContent = await
|
|
53223
|
+
templateContent = await fs29.readFile(p, "utf-8");
|
|
53224
53224
|
if (templateContent) {
|
|
53225
53225
|
logger.debug(`[LevelDispatch] Using schema template for ${checkId}: ${p}`);
|
|
53226
53226
|
break;
|
|
@@ -55360,8 +55360,8 @@ var init_workspace_manager = __esm({
|
|
|
55360
55360
|
);
|
|
55361
55361
|
if (this.cleanupRequested && this.activeOperations === 0) {
|
|
55362
55362
|
logger.debug(`[Workspace] All references released, proceeding with deferred cleanup`);
|
|
55363
|
-
for (const
|
|
55364
|
-
|
|
55363
|
+
for (const resolve19 of this.cleanupResolvers) {
|
|
55364
|
+
resolve19();
|
|
55365
55365
|
}
|
|
55366
55366
|
this.cleanupResolvers = [];
|
|
55367
55367
|
}
|
|
@@ -55540,19 +55540,19 @@ var init_workspace_manager = __esm({
|
|
|
55540
55540
|
);
|
|
55541
55541
|
this.cleanupRequested = true;
|
|
55542
55542
|
await Promise.race([
|
|
55543
|
-
new Promise((
|
|
55543
|
+
new Promise((resolve19) => {
|
|
55544
55544
|
if (this.activeOperations === 0) {
|
|
55545
|
-
|
|
55545
|
+
resolve19();
|
|
55546
55546
|
} else {
|
|
55547
|
-
this.cleanupResolvers.push(
|
|
55547
|
+
this.cleanupResolvers.push(resolve19);
|
|
55548
55548
|
}
|
|
55549
55549
|
}),
|
|
55550
|
-
new Promise((
|
|
55550
|
+
new Promise((resolve19) => {
|
|
55551
55551
|
setTimeout(() => {
|
|
55552
55552
|
logger.warn(
|
|
55553
55553
|
`[Workspace] Cleanup timeout after ${timeout}ms, proceeding anyway (${this.activeOperations} operations still active)`
|
|
55554
55554
|
);
|
|
55555
|
-
|
|
55555
|
+
resolve19();
|
|
55556
55556
|
}, timeout);
|
|
55557
55557
|
})
|
|
55558
55558
|
]);
|
|
@@ -55946,8 +55946,8 @@ var init_fair_concurrency_limiter = __esm({
|
|
|
55946
55946
|
);
|
|
55947
55947
|
const queuedAt = Date.now();
|
|
55948
55948
|
const effectiveTimeout = queueTimeout ?? 12e4;
|
|
55949
|
-
return new Promise((
|
|
55950
|
-
const entry = { resolve:
|
|
55949
|
+
return new Promise((resolve19, reject) => {
|
|
55950
|
+
const entry = { resolve: resolve19, reject, queuedAt };
|
|
55951
55951
|
entry.reminder = setInterval(() => {
|
|
55952
55952
|
const waited = Math.round((Date.now() - queuedAt) / 1e3);
|
|
55953
55953
|
const curQueued = this._totalQueued();
|
|
@@ -56254,6 +56254,1380 @@ var init_build_engine_context = __esm({
|
|
|
56254
56254
|
}
|
|
56255
56255
|
});
|
|
56256
56256
|
|
|
56257
|
+
// src/policy/default-engine.ts
|
|
56258
|
+
var DefaultPolicyEngine;
|
|
56259
|
+
var init_default_engine = __esm({
|
|
56260
|
+
"src/policy/default-engine.ts"() {
|
|
56261
|
+
"use strict";
|
|
56262
|
+
DefaultPolicyEngine = class {
|
|
56263
|
+
async initialize(_config) {
|
|
56264
|
+
}
|
|
56265
|
+
async evaluateCheckExecution(_checkId, _checkConfig) {
|
|
56266
|
+
return { allowed: true };
|
|
56267
|
+
}
|
|
56268
|
+
async evaluateToolInvocation(_serverName, _methodName, _transport) {
|
|
56269
|
+
return { allowed: true };
|
|
56270
|
+
}
|
|
56271
|
+
async evaluateCapabilities(_checkId, _capabilities) {
|
|
56272
|
+
return { allowed: true };
|
|
56273
|
+
}
|
|
56274
|
+
async shutdown() {
|
|
56275
|
+
}
|
|
56276
|
+
};
|
|
56277
|
+
}
|
|
56278
|
+
});
|
|
56279
|
+
|
|
56280
|
+
// src/enterprise/license/validator.ts
|
|
56281
|
+
var validator_exports = {};
|
|
56282
|
+
__export(validator_exports, {
|
|
56283
|
+
LicenseValidator: () => LicenseValidator
|
|
56284
|
+
});
|
|
56285
|
+
var crypto3, fs21, path26, LicenseValidator;
|
|
56286
|
+
var init_validator = __esm({
|
|
56287
|
+
"src/enterprise/license/validator.ts"() {
|
|
56288
|
+
"use strict";
|
|
56289
|
+
crypto3 = __toESM(require("crypto"));
|
|
56290
|
+
fs21 = __toESM(require("fs"));
|
|
56291
|
+
path26 = __toESM(require("path"));
|
|
56292
|
+
LicenseValidator = class _LicenseValidator {
|
|
56293
|
+
/** Ed25519 public key for license verification (PEM format). */
|
|
56294
|
+
static PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAI/Zd08EFmgIdrDm/HXd0l3/5GBt7R1PrdvhdmEXhJlU=\n-----END PUBLIC KEY-----\n";
|
|
56295
|
+
cache = null;
|
|
56296
|
+
static CACHE_TTL = 5 * 60 * 1e3;
|
|
56297
|
+
// 5 minutes
|
|
56298
|
+
static GRACE_PERIOD = 72 * 3600 * 1e3;
|
|
56299
|
+
// 72 hours after expiry
|
|
56300
|
+
/**
|
|
56301
|
+
* Load and validate license from environment or file.
|
|
56302
|
+
*
|
|
56303
|
+
* Resolution order:
|
|
56304
|
+
* 1. VISOR_LICENSE env var (JWT string)
|
|
56305
|
+
* 2. VISOR_LICENSE_FILE env var (path to file)
|
|
56306
|
+
* 3. .visor-license in project root (cwd)
|
|
56307
|
+
* 4. .visor-license in ~/.config/visor/
|
|
56308
|
+
*/
|
|
56309
|
+
async loadAndValidate() {
|
|
56310
|
+
if (this.cache && Date.now() - this.cache.validatedAt < _LicenseValidator.CACHE_TTL) {
|
|
56311
|
+
return this.cache.payload;
|
|
56312
|
+
}
|
|
56313
|
+
const token = this.resolveToken();
|
|
56314
|
+
if (!token) return null;
|
|
56315
|
+
const payload = this.verifyAndDecode(token);
|
|
56316
|
+
if (!payload) return null;
|
|
56317
|
+
this.cache = { payload, validatedAt: Date.now() };
|
|
56318
|
+
return payload;
|
|
56319
|
+
}
|
|
56320
|
+
/** Check if a specific feature is licensed */
|
|
56321
|
+
hasFeature(feature) {
|
|
56322
|
+
if (!this.cache) return false;
|
|
56323
|
+
return this.cache.payload.features.includes(feature);
|
|
56324
|
+
}
|
|
56325
|
+
/** Check if license is valid (with grace period) */
|
|
56326
|
+
isValid() {
|
|
56327
|
+
if (!this.cache) return false;
|
|
56328
|
+
const now = Date.now();
|
|
56329
|
+
const expiryMs = this.cache.payload.exp * 1e3;
|
|
56330
|
+
return now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
56331
|
+
}
|
|
56332
|
+
/** Check if the license is within its grace period (expired but still valid) */
|
|
56333
|
+
isInGracePeriod() {
|
|
56334
|
+
if (!this.cache) return false;
|
|
56335
|
+
const now = Date.now();
|
|
56336
|
+
const expiryMs = this.cache.payload.exp * 1e3;
|
|
56337
|
+
return now >= expiryMs && now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
56338
|
+
}
|
|
56339
|
+
resolveToken() {
|
|
56340
|
+
if (process.env.VISOR_LICENSE) {
|
|
56341
|
+
return process.env.VISOR_LICENSE.trim();
|
|
56342
|
+
}
|
|
56343
|
+
if (process.env.VISOR_LICENSE_FILE) {
|
|
56344
|
+
const resolved = path26.resolve(process.env.VISOR_LICENSE_FILE);
|
|
56345
|
+
const home2 = process.env.HOME || process.env.USERPROFILE || "";
|
|
56346
|
+
const allowedPrefixes = [path26.normalize(process.cwd())];
|
|
56347
|
+
if (home2) allowedPrefixes.push(path26.normalize(path26.join(home2, ".config", "visor")));
|
|
56348
|
+
let realPath;
|
|
56349
|
+
try {
|
|
56350
|
+
realPath = fs21.realpathSync(resolved);
|
|
56351
|
+
} catch {
|
|
56352
|
+
return null;
|
|
56353
|
+
}
|
|
56354
|
+
const isSafe = allowedPrefixes.some(
|
|
56355
|
+
(prefix) => realPath === prefix || realPath.startsWith(prefix + path26.sep)
|
|
56356
|
+
);
|
|
56357
|
+
if (!isSafe) return null;
|
|
56358
|
+
return this.readFile(realPath);
|
|
56359
|
+
}
|
|
56360
|
+
const cwdPath = path26.join(process.cwd(), ".visor-license");
|
|
56361
|
+
const cwdToken = this.readFile(cwdPath);
|
|
56362
|
+
if (cwdToken) return cwdToken;
|
|
56363
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
56364
|
+
if (home) {
|
|
56365
|
+
const configPath = path26.join(home, ".config", "visor", ".visor-license");
|
|
56366
|
+
const configToken = this.readFile(configPath);
|
|
56367
|
+
if (configToken) return configToken;
|
|
56368
|
+
}
|
|
56369
|
+
return null;
|
|
56370
|
+
}
|
|
56371
|
+
readFile(filePath) {
|
|
56372
|
+
try {
|
|
56373
|
+
return fs21.readFileSync(filePath, "utf-8").trim();
|
|
56374
|
+
} catch {
|
|
56375
|
+
return null;
|
|
56376
|
+
}
|
|
56377
|
+
}
|
|
56378
|
+
verifyAndDecode(token) {
|
|
56379
|
+
try {
|
|
56380
|
+
const parts = token.split(".");
|
|
56381
|
+
if (parts.length !== 3) return null;
|
|
56382
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
56383
|
+
const header = JSON.parse(Buffer.from(headerB64, "base64url").toString());
|
|
56384
|
+
if (header.alg !== "EdDSA") return null;
|
|
56385
|
+
const data = `${headerB64}.${payloadB64}`;
|
|
56386
|
+
const signature = Buffer.from(signatureB64, "base64url");
|
|
56387
|
+
const publicKey = crypto3.createPublicKey(_LicenseValidator.PUBLIC_KEY);
|
|
56388
|
+
if (publicKey.asymmetricKeyType !== "ed25519") {
|
|
56389
|
+
return null;
|
|
56390
|
+
}
|
|
56391
|
+
const isValid = crypto3.verify(null, Buffer.from(data), publicKey, signature);
|
|
56392
|
+
if (!isValid) return null;
|
|
56393
|
+
const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
|
|
56394
|
+
if (!payload.org || !Array.isArray(payload.features) || typeof payload.exp !== "number" || typeof payload.iat !== "number" || !payload.sub) {
|
|
56395
|
+
return null;
|
|
56396
|
+
}
|
|
56397
|
+
const now = Date.now();
|
|
56398
|
+
const expiryMs = payload.exp * 1e3;
|
|
56399
|
+
if (now >= expiryMs + _LicenseValidator.GRACE_PERIOD) {
|
|
56400
|
+
return null;
|
|
56401
|
+
}
|
|
56402
|
+
return payload;
|
|
56403
|
+
} catch {
|
|
56404
|
+
return null;
|
|
56405
|
+
}
|
|
56406
|
+
}
|
|
56407
|
+
};
|
|
56408
|
+
}
|
|
56409
|
+
});
|
|
56410
|
+
|
|
56411
|
+
// src/enterprise/policy/opa-compiler.ts
|
|
56412
|
+
var fs22, path27, os2, crypto4, import_child_process8, OpaCompiler;
|
|
56413
|
+
var init_opa_compiler = __esm({
|
|
56414
|
+
"src/enterprise/policy/opa-compiler.ts"() {
|
|
56415
|
+
"use strict";
|
|
56416
|
+
fs22 = __toESM(require("fs"));
|
|
56417
|
+
path27 = __toESM(require("path"));
|
|
56418
|
+
os2 = __toESM(require("os"));
|
|
56419
|
+
crypto4 = __toESM(require("crypto"));
|
|
56420
|
+
import_child_process8 = require("child_process");
|
|
56421
|
+
OpaCompiler = class _OpaCompiler {
|
|
56422
|
+
static CACHE_DIR = path27.join(os2.tmpdir(), "visor-opa-cache");
|
|
56423
|
+
/**
|
|
56424
|
+
* Resolve the input paths to WASM bytes.
|
|
56425
|
+
*
|
|
56426
|
+
* Strategy:
|
|
56427
|
+
* 1. If any path is a .wasm file, read it directly
|
|
56428
|
+
* 2. If a directory contains policy.wasm, read it
|
|
56429
|
+
* 3. Otherwise, collect all .rego files and auto-compile via `opa build`
|
|
56430
|
+
*/
|
|
56431
|
+
async resolveWasmBytes(paths) {
|
|
56432
|
+
const regoFiles = [];
|
|
56433
|
+
for (const p of paths) {
|
|
56434
|
+
const resolved = path27.resolve(p);
|
|
56435
|
+
if (path27.normalize(resolved).includes("..")) {
|
|
56436
|
+
throw new Error(`Policy path contains traversal sequences: ${p}`);
|
|
56437
|
+
}
|
|
56438
|
+
if (resolved.endsWith(".wasm") && fs22.existsSync(resolved)) {
|
|
56439
|
+
return fs22.readFileSync(resolved);
|
|
56440
|
+
}
|
|
56441
|
+
if (!fs22.existsSync(resolved)) continue;
|
|
56442
|
+
const stat2 = fs22.statSync(resolved);
|
|
56443
|
+
if (stat2.isDirectory()) {
|
|
56444
|
+
const wasmCandidate = path27.join(resolved, "policy.wasm");
|
|
56445
|
+
if (fs22.existsSync(wasmCandidate)) {
|
|
56446
|
+
return fs22.readFileSync(wasmCandidate);
|
|
56447
|
+
}
|
|
56448
|
+
const files = fs22.readdirSync(resolved);
|
|
56449
|
+
for (const f of files) {
|
|
56450
|
+
if (f.endsWith(".rego")) {
|
|
56451
|
+
regoFiles.push(path27.join(resolved, f));
|
|
56452
|
+
}
|
|
56453
|
+
}
|
|
56454
|
+
} else if (resolved.endsWith(".rego")) {
|
|
56455
|
+
regoFiles.push(resolved);
|
|
56456
|
+
}
|
|
56457
|
+
}
|
|
56458
|
+
if (regoFiles.length === 0) {
|
|
56459
|
+
throw new Error(
|
|
56460
|
+
`OPA WASM evaluator: no .wasm bundle or .rego files found in: ${paths.join(", ")}`
|
|
56461
|
+
);
|
|
56462
|
+
}
|
|
56463
|
+
return this.compileRego(regoFiles);
|
|
56464
|
+
}
|
|
56465
|
+
/**
|
|
56466
|
+
* Auto-compile .rego files to a WASM bundle using the `opa` CLI.
|
|
56467
|
+
*
|
|
56468
|
+
* Caches the compiled bundle based on a content hash of all input .rego files
|
|
56469
|
+
* so subsequent runs skip compilation if policies haven't changed.
|
|
56470
|
+
*/
|
|
56471
|
+
compileRego(regoFiles) {
|
|
56472
|
+
try {
|
|
56473
|
+
(0, import_child_process8.execFileSync)("opa", ["version"], { stdio: "pipe" });
|
|
56474
|
+
} catch {
|
|
56475
|
+
throw new Error(
|
|
56476
|
+
"OPA CLI (`opa`) not found on PATH. Install it from https://www.openpolicyagent.org/docs/latest/#running-opa\nOr pre-compile your .rego files: opa build -t wasm -e visor -o bundle.tar.gz " + regoFiles.join(" ")
|
|
56477
|
+
);
|
|
56478
|
+
}
|
|
56479
|
+
const hash = crypto4.createHash("sha256");
|
|
56480
|
+
for (const f of regoFiles.sort()) {
|
|
56481
|
+
hash.update(fs22.readFileSync(f));
|
|
56482
|
+
hash.update(f);
|
|
56483
|
+
}
|
|
56484
|
+
const cacheKey = hash.digest("hex").slice(0, 16);
|
|
56485
|
+
const cacheDir = _OpaCompiler.CACHE_DIR;
|
|
56486
|
+
const cachedWasm = path27.join(cacheDir, `${cacheKey}.wasm`);
|
|
56487
|
+
if (fs22.existsSync(cachedWasm)) {
|
|
56488
|
+
return fs22.readFileSync(cachedWasm);
|
|
56489
|
+
}
|
|
56490
|
+
fs22.mkdirSync(cacheDir, { recursive: true });
|
|
56491
|
+
const bundleTar = path27.join(cacheDir, `${cacheKey}-bundle.tar.gz`);
|
|
56492
|
+
try {
|
|
56493
|
+
const args = [
|
|
56494
|
+
"build",
|
|
56495
|
+
"-t",
|
|
56496
|
+
"wasm",
|
|
56497
|
+
"-e",
|
|
56498
|
+
"visor",
|
|
56499
|
+
// entrypoint: the visor package tree
|
|
56500
|
+
"-o",
|
|
56501
|
+
bundleTar,
|
|
56502
|
+
...regoFiles
|
|
56503
|
+
];
|
|
56504
|
+
(0, import_child_process8.execFileSync)("opa", args, {
|
|
56505
|
+
stdio: "pipe",
|
|
56506
|
+
timeout: 3e4
|
|
56507
|
+
});
|
|
56508
|
+
} catch (err) {
|
|
56509
|
+
const stderr = err?.stderr?.toString() || "";
|
|
56510
|
+
throw new Error(
|
|
56511
|
+
`Failed to compile .rego files to WASM:
|
|
56512
|
+
${stderr}
|
|
56513
|
+
Ensure your .rego files are valid and the \`opa\` CLI is installed.`
|
|
56514
|
+
);
|
|
56515
|
+
}
|
|
56516
|
+
try {
|
|
56517
|
+
(0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "/policy.wasm"], {
|
|
56518
|
+
stdio: "pipe"
|
|
56519
|
+
});
|
|
56520
|
+
const extractedWasm = path27.join(cacheDir, "policy.wasm");
|
|
56521
|
+
if (fs22.existsSync(extractedWasm)) {
|
|
56522
|
+
fs22.renameSync(extractedWasm, cachedWasm);
|
|
56523
|
+
}
|
|
56524
|
+
} catch {
|
|
56525
|
+
try {
|
|
56526
|
+
(0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "policy.wasm"], {
|
|
56527
|
+
stdio: "pipe"
|
|
56528
|
+
});
|
|
56529
|
+
const extractedWasm = path27.join(cacheDir, "policy.wasm");
|
|
56530
|
+
if (fs22.existsSync(extractedWasm)) {
|
|
56531
|
+
fs22.renameSync(extractedWasm, cachedWasm);
|
|
56532
|
+
}
|
|
56533
|
+
} catch (err2) {
|
|
56534
|
+
throw new Error(`Failed to extract policy.wasm from OPA bundle: ${err2?.message || err2}`);
|
|
56535
|
+
}
|
|
56536
|
+
}
|
|
56537
|
+
try {
|
|
56538
|
+
fs22.unlinkSync(bundleTar);
|
|
56539
|
+
} catch {
|
|
56540
|
+
}
|
|
56541
|
+
if (!fs22.existsSync(cachedWasm)) {
|
|
56542
|
+
throw new Error("OPA build succeeded but policy.wasm was not found in the bundle");
|
|
56543
|
+
}
|
|
56544
|
+
return fs22.readFileSync(cachedWasm);
|
|
56545
|
+
}
|
|
56546
|
+
};
|
|
56547
|
+
}
|
|
56548
|
+
});
|
|
56549
|
+
|
|
56550
|
+
// src/enterprise/policy/opa-wasm-evaluator.ts
|
|
56551
|
+
var fs23, path28, OpaWasmEvaluator;
|
|
56552
|
+
var init_opa_wasm_evaluator = __esm({
|
|
56553
|
+
"src/enterprise/policy/opa-wasm-evaluator.ts"() {
|
|
56554
|
+
"use strict";
|
|
56555
|
+
fs23 = __toESM(require("fs"));
|
|
56556
|
+
path28 = __toESM(require("path"));
|
|
56557
|
+
init_opa_compiler();
|
|
56558
|
+
OpaWasmEvaluator = class {
|
|
56559
|
+
policy = null;
|
|
56560
|
+
dataDocument = {};
|
|
56561
|
+
compiler = new OpaCompiler();
|
|
56562
|
+
async initialize(rulesPath) {
|
|
56563
|
+
const paths = Array.isArray(rulesPath) ? rulesPath : [rulesPath];
|
|
56564
|
+
const wasmBytes = await this.compiler.resolveWasmBytes(paths);
|
|
56565
|
+
try {
|
|
56566
|
+
const { createRequire } = require("module");
|
|
56567
|
+
const runtimeRequire = createRequire(__filename);
|
|
56568
|
+
const opaWasm = runtimeRequire("@open-policy-agent/opa-wasm");
|
|
56569
|
+
const loadPolicy = opaWasm.loadPolicy || opaWasm.default?.loadPolicy;
|
|
56570
|
+
if (!loadPolicy) {
|
|
56571
|
+
throw new Error("loadPolicy not found in @open-policy-agent/opa-wasm");
|
|
56572
|
+
}
|
|
56573
|
+
this.policy = await loadPolicy(wasmBytes);
|
|
56574
|
+
} catch (err) {
|
|
56575
|
+
if (err?.code === "MODULE_NOT_FOUND" || err?.code === "ERR_MODULE_NOT_FOUND") {
|
|
56576
|
+
throw new Error(
|
|
56577
|
+
"OPA WASM evaluator requires @open-policy-agent/opa-wasm. Install it with: npm install @open-policy-agent/opa-wasm"
|
|
56578
|
+
);
|
|
56579
|
+
}
|
|
56580
|
+
throw err;
|
|
56581
|
+
}
|
|
56582
|
+
}
|
|
56583
|
+
/**
|
|
56584
|
+
* Load external data from a JSON file to use as the OPA data document.
|
|
56585
|
+
* The loaded data will be passed to `policy.setData()` during evaluation,
|
|
56586
|
+
* making it available in Rego via `data.<key>`.
|
|
56587
|
+
*/
|
|
56588
|
+
loadData(dataPath) {
|
|
56589
|
+
const resolved = path28.resolve(dataPath);
|
|
56590
|
+
if (path28.normalize(resolved).includes("..")) {
|
|
56591
|
+
throw new Error(`Data path contains traversal sequences: ${dataPath}`);
|
|
56592
|
+
}
|
|
56593
|
+
if (!fs23.existsSync(resolved)) {
|
|
56594
|
+
throw new Error(`OPA data file not found: ${resolved}`);
|
|
56595
|
+
}
|
|
56596
|
+
const stat2 = fs23.statSync(resolved);
|
|
56597
|
+
if (stat2.size > 10 * 1024 * 1024) {
|
|
56598
|
+
throw new Error(`OPA data file exceeds 10MB limit: ${resolved} (${stat2.size} bytes)`);
|
|
56599
|
+
}
|
|
56600
|
+
const raw = fs23.readFileSync(resolved, "utf-8");
|
|
56601
|
+
try {
|
|
56602
|
+
const parsed = JSON.parse(raw);
|
|
56603
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
56604
|
+
throw new Error("OPA data file must contain a JSON object (not an array or primitive)");
|
|
56605
|
+
}
|
|
56606
|
+
this.dataDocument = parsed;
|
|
56607
|
+
} catch (err) {
|
|
56608
|
+
if (err.message.startsWith("OPA data file must")) {
|
|
56609
|
+
throw err;
|
|
56610
|
+
}
|
|
56611
|
+
throw new Error(`Failed to parse OPA data file ${resolved}: ${err.message}`);
|
|
56612
|
+
}
|
|
56613
|
+
}
|
|
56614
|
+
async evaluate(input) {
|
|
56615
|
+
if (!this.policy) {
|
|
56616
|
+
throw new Error("OPA WASM evaluator not initialized");
|
|
56617
|
+
}
|
|
56618
|
+
this.policy.setData(this.dataDocument);
|
|
56619
|
+
const resultSet = this.policy.evaluate(input);
|
|
56620
|
+
if (Array.isArray(resultSet) && resultSet.length > 0) {
|
|
56621
|
+
return resultSet[0].result;
|
|
56622
|
+
}
|
|
56623
|
+
return void 0;
|
|
56624
|
+
}
|
|
56625
|
+
async shutdown() {
|
|
56626
|
+
if (this.policy) {
|
|
56627
|
+
if (typeof this.policy.close === "function") {
|
|
56628
|
+
try {
|
|
56629
|
+
this.policy.close();
|
|
56630
|
+
} catch {
|
|
56631
|
+
}
|
|
56632
|
+
} else if (typeof this.policy.free === "function") {
|
|
56633
|
+
try {
|
|
56634
|
+
this.policy.free();
|
|
56635
|
+
} catch {
|
|
56636
|
+
}
|
|
56637
|
+
}
|
|
56638
|
+
}
|
|
56639
|
+
this.policy = null;
|
|
56640
|
+
}
|
|
56641
|
+
};
|
|
56642
|
+
}
|
|
56643
|
+
});
|
|
56644
|
+
|
|
56645
|
+
// src/enterprise/policy/opa-http-evaluator.ts
|
|
56646
|
+
var OpaHttpEvaluator;
|
|
56647
|
+
var init_opa_http_evaluator = __esm({
|
|
56648
|
+
"src/enterprise/policy/opa-http-evaluator.ts"() {
|
|
56649
|
+
"use strict";
|
|
56650
|
+
OpaHttpEvaluator = class {
|
|
56651
|
+
baseUrl;
|
|
56652
|
+
timeout;
|
|
56653
|
+
constructor(baseUrl, timeout = 5e3) {
|
|
56654
|
+
let parsed;
|
|
56655
|
+
try {
|
|
56656
|
+
parsed = new URL(baseUrl);
|
|
56657
|
+
} catch {
|
|
56658
|
+
throw new Error(`OPA HTTP evaluator: invalid URL: ${baseUrl}`);
|
|
56659
|
+
}
|
|
56660
|
+
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
56661
|
+
throw new Error(
|
|
56662
|
+
`OPA HTTP evaluator: url must use http:// or https:// protocol, got: ${baseUrl}`
|
|
56663
|
+
);
|
|
56664
|
+
}
|
|
56665
|
+
const hostname = parsed.hostname;
|
|
56666
|
+
if (this.isBlockedHostname(hostname)) {
|
|
56667
|
+
throw new Error(
|
|
56668
|
+
`OPA HTTP evaluator: url must not point to internal, loopback, or private network addresses`
|
|
56669
|
+
);
|
|
56670
|
+
}
|
|
56671
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
56672
|
+
this.timeout = timeout;
|
|
56673
|
+
}
|
|
56674
|
+
/**
|
|
56675
|
+
* Check if a hostname is blocked due to SSRF concerns.
|
|
56676
|
+
*
|
|
56677
|
+
* Blocks:
|
|
56678
|
+
* - Loopback addresses (127.x.x.x, localhost, 0.0.0.0, ::1)
|
|
56679
|
+
* - Link-local addresses (169.254.x.x)
|
|
56680
|
+
* - Private networks (10.x.x.x, 172.16-31.x.x, 192.168.x.x)
|
|
56681
|
+
* - IPv6 unique local addresses (fd00::/8)
|
|
56682
|
+
* - Cloud metadata services (*.internal)
|
|
56683
|
+
*/
|
|
56684
|
+
isBlockedHostname(hostname) {
|
|
56685
|
+
if (!hostname) return true;
|
|
56686
|
+
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
56687
|
+
if (normalized === "metadata.google.internal" || normalized.endsWith(".internal")) {
|
|
56688
|
+
return true;
|
|
56689
|
+
}
|
|
56690
|
+
if (normalized === "localhost" || normalized === "localhost.localdomain") {
|
|
56691
|
+
return true;
|
|
56692
|
+
}
|
|
56693
|
+
if (normalized === "::1" || normalized === "0:0:0:0:0:0:0:1") {
|
|
56694
|
+
return true;
|
|
56695
|
+
}
|
|
56696
|
+
const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
56697
|
+
const ipv4Match = normalized.match(ipv4Pattern);
|
|
56698
|
+
if (ipv4Match) {
|
|
56699
|
+
const octets = ipv4Match.slice(1, 5).map(Number);
|
|
56700
|
+
if (octets.some((octet) => octet > 255)) {
|
|
56701
|
+
return false;
|
|
56702
|
+
}
|
|
56703
|
+
const [a, b] = octets;
|
|
56704
|
+
if (a === 127) {
|
|
56705
|
+
return true;
|
|
56706
|
+
}
|
|
56707
|
+
if (a === 0) {
|
|
56708
|
+
return true;
|
|
56709
|
+
}
|
|
56710
|
+
if (a === 169 && b === 254) {
|
|
56711
|
+
return true;
|
|
56712
|
+
}
|
|
56713
|
+
if (a === 10) {
|
|
56714
|
+
return true;
|
|
56715
|
+
}
|
|
56716
|
+
if (a === 172 && b >= 16 && b <= 31) {
|
|
56717
|
+
return true;
|
|
56718
|
+
}
|
|
56719
|
+
if (a === 192 && b === 168) {
|
|
56720
|
+
return true;
|
|
56721
|
+
}
|
|
56722
|
+
}
|
|
56723
|
+
if (normalized.startsWith("fd") || normalized.startsWith("fc")) {
|
|
56724
|
+
return true;
|
|
56725
|
+
}
|
|
56726
|
+
if (normalized.startsWith("fe80:")) {
|
|
56727
|
+
return true;
|
|
56728
|
+
}
|
|
56729
|
+
return false;
|
|
56730
|
+
}
|
|
56731
|
+
/**
|
|
56732
|
+
* Evaluate a policy rule against an input document via OPA REST API.
|
|
56733
|
+
*
|
|
56734
|
+
* @param input - The input document to evaluate
|
|
56735
|
+
* @param rulePath - OPA rule path (e.g., 'visor/check/execute')
|
|
56736
|
+
* @returns The result object from OPA, or undefined on error
|
|
56737
|
+
*/
|
|
56738
|
+
async evaluate(input, rulePath) {
|
|
56739
|
+
const encodedPath = rulePath.split("/").map((s) => encodeURIComponent(s)).join("/");
|
|
56740
|
+
const url = `${this.baseUrl}/v1/data/${encodedPath}`;
|
|
56741
|
+
const controller = new AbortController();
|
|
56742
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
56743
|
+
try {
|
|
56744
|
+
const response = await fetch(url, {
|
|
56745
|
+
method: "POST",
|
|
56746
|
+
headers: { "Content-Type": "application/json" },
|
|
56747
|
+
body: JSON.stringify({ input }),
|
|
56748
|
+
signal: controller.signal
|
|
56749
|
+
});
|
|
56750
|
+
if (!response.ok) {
|
|
56751
|
+
throw new Error(`OPA HTTP ${response.status}: ${response.statusText}`);
|
|
56752
|
+
}
|
|
56753
|
+
let body;
|
|
56754
|
+
try {
|
|
56755
|
+
body = await response.json();
|
|
56756
|
+
} catch (jsonErr) {
|
|
56757
|
+
throw new Error(
|
|
56758
|
+
`OPA HTTP evaluator: failed to parse JSON response: ${jsonErr instanceof Error ? jsonErr.message : String(jsonErr)}`
|
|
56759
|
+
);
|
|
56760
|
+
}
|
|
56761
|
+
return body?.result;
|
|
56762
|
+
} finally {
|
|
56763
|
+
clearTimeout(timer);
|
|
56764
|
+
}
|
|
56765
|
+
}
|
|
56766
|
+
async shutdown() {
|
|
56767
|
+
}
|
|
56768
|
+
};
|
|
56769
|
+
}
|
|
56770
|
+
});
|
|
56771
|
+
|
|
56772
|
+
// src/enterprise/policy/policy-input-builder.ts
|
|
56773
|
+
var PolicyInputBuilder;
|
|
56774
|
+
var init_policy_input_builder = __esm({
|
|
56775
|
+
"src/enterprise/policy/policy-input-builder.ts"() {
|
|
56776
|
+
"use strict";
|
|
56777
|
+
PolicyInputBuilder = class {
|
|
56778
|
+
roles;
|
|
56779
|
+
actor;
|
|
56780
|
+
repository;
|
|
56781
|
+
pullRequest;
|
|
56782
|
+
constructor(policyConfig, actor, repository, pullRequest) {
|
|
56783
|
+
this.roles = policyConfig.roles || {};
|
|
56784
|
+
this.actor = actor;
|
|
56785
|
+
this.repository = repository;
|
|
56786
|
+
this.pullRequest = pullRequest;
|
|
56787
|
+
}
|
|
56788
|
+
/** Resolve which roles apply to the current actor. */
|
|
56789
|
+
resolveRoles() {
|
|
56790
|
+
const matched = [];
|
|
56791
|
+
for (const [roleName, roleConfig] of Object.entries(this.roles)) {
|
|
56792
|
+
let identityMatch = false;
|
|
56793
|
+
if (roleConfig.author_association && this.actor.authorAssociation && roleConfig.author_association.includes(this.actor.authorAssociation)) {
|
|
56794
|
+
identityMatch = true;
|
|
56795
|
+
}
|
|
56796
|
+
if (!identityMatch && roleConfig.users && this.actor.login && roleConfig.users.includes(this.actor.login)) {
|
|
56797
|
+
identityMatch = true;
|
|
56798
|
+
}
|
|
56799
|
+
if (!identityMatch && roleConfig.slack_users && this.actor.slack?.userId && roleConfig.slack_users.includes(this.actor.slack.userId)) {
|
|
56800
|
+
identityMatch = true;
|
|
56801
|
+
}
|
|
56802
|
+
if (!identityMatch && roleConfig.emails && this.actor.slack?.email) {
|
|
56803
|
+
const actorEmail = this.actor.slack.email.toLowerCase();
|
|
56804
|
+
if (roleConfig.emails.some((e) => e.toLowerCase() === actorEmail)) {
|
|
56805
|
+
identityMatch = true;
|
|
56806
|
+
}
|
|
56807
|
+
}
|
|
56808
|
+
if (!identityMatch) continue;
|
|
56809
|
+
if (roleConfig.slack_channels && roleConfig.slack_channels.length > 0) {
|
|
56810
|
+
if (!this.actor.slack?.channelId || !roleConfig.slack_channels.includes(this.actor.slack.channelId)) {
|
|
56811
|
+
continue;
|
|
56812
|
+
}
|
|
56813
|
+
}
|
|
56814
|
+
matched.push(roleName);
|
|
56815
|
+
}
|
|
56816
|
+
return matched;
|
|
56817
|
+
}
|
|
56818
|
+
buildActor() {
|
|
56819
|
+
return {
|
|
56820
|
+
authorAssociation: this.actor.authorAssociation,
|
|
56821
|
+
login: this.actor.login,
|
|
56822
|
+
roles: this.resolveRoles(),
|
|
56823
|
+
isLocalMode: this.actor.isLocalMode,
|
|
56824
|
+
...this.actor.slack && { slack: this.actor.slack }
|
|
56825
|
+
};
|
|
56826
|
+
}
|
|
56827
|
+
forCheckExecution(check) {
|
|
56828
|
+
return {
|
|
56829
|
+
scope: "check.execute",
|
|
56830
|
+
check: {
|
|
56831
|
+
id: check.id,
|
|
56832
|
+
type: check.type,
|
|
56833
|
+
group: check.group,
|
|
56834
|
+
tags: check.tags,
|
|
56835
|
+
criticality: check.criticality,
|
|
56836
|
+
sandbox: check.sandbox,
|
|
56837
|
+
policy: check.policy
|
|
56838
|
+
},
|
|
56839
|
+
actor: this.buildActor(),
|
|
56840
|
+
repository: this.repository,
|
|
56841
|
+
pullRequest: this.pullRequest
|
|
56842
|
+
};
|
|
56843
|
+
}
|
|
56844
|
+
forToolInvocation(serverName, methodName, transport) {
|
|
56845
|
+
return {
|
|
56846
|
+
scope: "tool.invoke",
|
|
56847
|
+
tool: { serverName, methodName, transport },
|
|
56848
|
+
actor: this.buildActor(),
|
|
56849
|
+
repository: this.repository,
|
|
56850
|
+
pullRequest: this.pullRequest
|
|
56851
|
+
};
|
|
56852
|
+
}
|
|
56853
|
+
forCapabilityResolve(checkId, capabilities) {
|
|
56854
|
+
return {
|
|
56855
|
+
scope: "capability.resolve",
|
|
56856
|
+
check: { id: checkId, type: "ai" },
|
|
56857
|
+
capability: capabilities,
|
|
56858
|
+
actor: this.buildActor(),
|
|
56859
|
+
repository: this.repository,
|
|
56860
|
+
pullRequest: this.pullRequest
|
|
56861
|
+
};
|
|
56862
|
+
}
|
|
56863
|
+
};
|
|
56864
|
+
}
|
|
56865
|
+
});
|
|
56866
|
+
|
|
56867
|
+
// src/enterprise/policy/opa-policy-engine.ts
|
|
56868
|
+
var opa_policy_engine_exports = {};
|
|
56869
|
+
__export(opa_policy_engine_exports, {
|
|
56870
|
+
OpaPolicyEngine: () => OpaPolicyEngine
|
|
56871
|
+
});
|
|
56872
|
+
var OpaPolicyEngine;
|
|
56873
|
+
var init_opa_policy_engine = __esm({
|
|
56874
|
+
"src/enterprise/policy/opa-policy-engine.ts"() {
|
|
56875
|
+
"use strict";
|
|
56876
|
+
init_opa_wasm_evaluator();
|
|
56877
|
+
init_opa_http_evaluator();
|
|
56878
|
+
init_policy_input_builder();
|
|
56879
|
+
OpaPolicyEngine = class {
|
|
56880
|
+
evaluator = null;
|
|
56881
|
+
fallback;
|
|
56882
|
+
timeout;
|
|
56883
|
+
config;
|
|
56884
|
+
inputBuilder = null;
|
|
56885
|
+
logger = null;
|
|
56886
|
+
constructor(config) {
|
|
56887
|
+
this.config = config;
|
|
56888
|
+
this.fallback = config.fallback || "deny";
|
|
56889
|
+
this.timeout = config.timeout || 5e3;
|
|
56890
|
+
}
|
|
56891
|
+
async initialize(config) {
|
|
56892
|
+
try {
|
|
56893
|
+
this.logger = (init_logger(), __toCommonJS(logger_exports)).logger;
|
|
56894
|
+
} catch {
|
|
56895
|
+
}
|
|
56896
|
+
const actor = {
|
|
56897
|
+
authorAssociation: process.env.VISOR_AUTHOR_ASSOCIATION,
|
|
56898
|
+
login: process.env.VISOR_AUTHOR_LOGIN || process.env.GITHUB_ACTOR,
|
|
56899
|
+
isLocalMode: !process.env.GITHUB_ACTIONS
|
|
56900
|
+
};
|
|
56901
|
+
const repo = {
|
|
56902
|
+
owner: process.env.GITHUB_REPOSITORY_OWNER,
|
|
56903
|
+
name: process.env.GITHUB_REPOSITORY?.split("/")[1],
|
|
56904
|
+
branch: process.env.GITHUB_HEAD_REF,
|
|
56905
|
+
baseBranch: process.env.GITHUB_BASE_REF,
|
|
56906
|
+
event: process.env.GITHUB_EVENT_NAME
|
|
56907
|
+
};
|
|
56908
|
+
const prNum = process.env.GITHUB_PR_NUMBER ? parseInt(process.env.GITHUB_PR_NUMBER, 10) : void 0;
|
|
56909
|
+
const pullRequest = {
|
|
56910
|
+
number: prNum !== void 0 && Number.isFinite(prNum) ? prNum : void 0
|
|
56911
|
+
};
|
|
56912
|
+
this.inputBuilder = new PolicyInputBuilder(config, actor, repo, pullRequest);
|
|
56913
|
+
if (config.engine === "local") {
|
|
56914
|
+
if (!config.rules) {
|
|
56915
|
+
throw new Error("OPA local mode requires `policy.rules` path to .wasm or .rego files");
|
|
56916
|
+
}
|
|
56917
|
+
const wasm = new OpaWasmEvaluator();
|
|
56918
|
+
await wasm.initialize(config.rules);
|
|
56919
|
+
if (config.data) {
|
|
56920
|
+
wasm.loadData(config.data);
|
|
56921
|
+
}
|
|
56922
|
+
this.evaluator = wasm;
|
|
56923
|
+
} else if (config.engine === "remote") {
|
|
56924
|
+
if (!config.url) {
|
|
56925
|
+
throw new Error("OPA remote mode requires `policy.url` pointing to OPA server");
|
|
56926
|
+
}
|
|
56927
|
+
this.evaluator = new OpaHttpEvaluator(config.url, this.timeout);
|
|
56928
|
+
} else {
|
|
56929
|
+
this.evaluator = null;
|
|
56930
|
+
}
|
|
56931
|
+
}
|
|
56932
|
+
/**
|
|
56933
|
+
* Update actor/repo/PR context (e.g., after PR info becomes available).
|
|
56934
|
+
* Called by the enterprise loader when engine context is enriched.
|
|
56935
|
+
*/
|
|
56936
|
+
setActorContext(actor, repo, pullRequest) {
|
|
56937
|
+
this.inputBuilder = new PolicyInputBuilder(this.config, actor, repo, pullRequest);
|
|
56938
|
+
}
|
|
56939
|
+
async evaluateCheckExecution(checkId, checkConfig) {
|
|
56940
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
56941
|
+
const cfg = checkConfig && typeof checkConfig === "object" ? checkConfig : {};
|
|
56942
|
+
const policyOverride = cfg.policy;
|
|
56943
|
+
const input = this.inputBuilder.forCheckExecution({
|
|
56944
|
+
id: checkId,
|
|
56945
|
+
type: cfg.type || "ai",
|
|
56946
|
+
group: cfg.group,
|
|
56947
|
+
tags: cfg.tags,
|
|
56948
|
+
criticality: cfg.criticality,
|
|
56949
|
+
sandbox: cfg.sandbox,
|
|
56950
|
+
policy: policyOverride
|
|
56951
|
+
});
|
|
56952
|
+
return this.doEvaluate(input, this.resolveRulePath("check.execute", policyOverride?.rule));
|
|
56953
|
+
}
|
|
56954
|
+
async evaluateToolInvocation(serverName, methodName, transport) {
|
|
56955
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
56956
|
+
const input = this.inputBuilder.forToolInvocation(serverName, methodName, transport);
|
|
56957
|
+
return this.doEvaluate(input, "visor/tool/invoke");
|
|
56958
|
+
}
|
|
56959
|
+
async evaluateCapabilities(checkId, capabilities) {
|
|
56960
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
56961
|
+
const input = this.inputBuilder.forCapabilityResolve(checkId, capabilities);
|
|
56962
|
+
return this.doEvaluate(input, "visor/capability/resolve");
|
|
56963
|
+
}
|
|
56964
|
+
async shutdown() {
|
|
56965
|
+
if (this.evaluator && "shutdown" in this.evaluator) {
|
|
56966
|
+
await this.evaluator.shutdown();
|
|
56967
|
+
}
|
|
56968
|
+
this.evaluator = null;
|
|
56969
|
+
this.inputBuilder = null;
|
|
56970
|
+
}
|
|
56971
|
+
resolveRulePath(defaultScope, override) {
|
|
56972
|
+
if (override) {
|
|
56973
|
+
return override.startsWith("visor/") ? override : `visor/${override}`;
|
|
56974
|
+
}
|
|
56975
|
+
return `visor/${defaultScope.replace(/\./g, "/")}`;
|
|
56976
|
+
}
|
|
56977
|
+
async doEvaluate(input, rulePath) {
|
|
56978
|
+
try {
|
|
56979
|
+
this.logger?.debug(`[PolicyEngine] Evaluating ${rulePath}`, JSON.stringify(input));
|
|
56980
|
+
let timer;
|
|
56981
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
56982
|
+
timer = setTimeout(() => reject(new Error("policy evaluation timeout")), this.timeout);
|
|
56983
|
+
});
|
|
56984
|
+
try {
|
|
56985
|
+
const result = await Promise.race([this.rawEvaluate(input, rulePath), timeoutPromise]);
|
|
56986
|
+
const decision = this.parseDecision(result);
|
|
56987
|
+
if (!decision.allowed && this.fallback === "warn") {
|
|
56988
|
+
decision.allowed = true;
|
|
56989
|
+
decision.warn = true;
|
|
56990
|
+
decision.reason = `audit: ${decision.reason || "policy denied"}`;
|
|
56991
|
+
}
|
|
56992
|
+
this.logger?.debug(
|
|
56993
|
+
`[PolicyEngine] Decision for ${rulePath}: allowed=${decision.allowed}, warn=${decision.warn || false}, reason=${decision.reason || "none"}`
|
|
56994
|
+
);
|
|
56995
|
+
return decision;
|
|
56996
|
+
} finally {
|
|
56997
|
+
if (timer) clearTimeout(timer);
|
|
56998
|
+
}
|
|
56999
|
+
} catch (err) {
|
|
57000
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
57001
|
+
this.logger?.warn(`[PolicyEngine] Evaluation failed for ${rulePath}: ${msg}`);
|
|
57002
|
+
return {
|
|
57003
|
+
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
57004
|
+
warn: this.fallback === "warn" ? true : void 0,
|
|
57005
|
+
reason: `policy evaluation failed, fallback=${this.fallback}`
|
|
57006
|
+
};
|
|
57007
|
+
}
|
|
57008
|
+
}
|
|
57009
|
+
async rawEvaluate(input, rulePath) {
|
|
57010
|
+
if (this.evaluator instanceof OpaWasmEvaluator) {
|
|
57011
|
+
const result = await this.evaluator.evaluate(input);
|
|
57012
|
+
return this.navigateWasmResult(result, rulePath);
|
|
57013
|
+
}
|
|
57014
|
+
return this.evaluator.evaluate(input, rulePath);
|
|
57015
|
+
}
|
|
57016
|
+
/**
|
|
57017
|
+
* Navigate nested OPA WASM result tree to reach the specific rule's output.
|
|
57018
|
+
* The WASM entrypoint `-e visor` means the result root IS the visor package,
|
|
57019
|
+
* so we strip the `visor/` prefix and walk the remaining segments.
|
|
57020
|
+
*/
|
|
57021
|
+
navigateWasmResult(result, rulePath) {
|
|
57022
|
+
if (!result || typeof result !== "object") return result;
|
|
57023
|
+
const segments = rulePath.replace(/^visor\//, "").split("/");
|
|
57024
|
+
let current = result;
|
|
57025
|
+
for (const seg of segments) {
|
|
57026
|
+
if (current && typeof current === "object" && seg in current) {
|
|
57027
|
+
current = current[seg];
|
|
57028
|
+
} else {
|
|
57029
|
+
return void 0;
|
|
57030
|
+
}
|
|
57031
|
+
}
|
|
57032
|
+
return current;
|
|
57033
|
+
}
|
|
57034
|
+
parseDecision(result) {
|
|
57035
|
+
if (result === void 0 || result === null) {
|
|
57036
|
+
return {
|
|
57037
|
+
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
57038
|
+
warn: this.fallback === "warn" ? true : void 0,
|
|
57039
|
+
reason: this.fallback === "warn" ? "audit: no policy result" : "no policy result"
|
|
57040
|
+
};
|
|
57041
|
+
}
|
|
57042
|
+
const allowed = result.allowed !== false;
|
|
57043
|
+
const decision = {
|
|
57044
|
+
allowed,
|
|
57045
|
+
reason: result.reason
|
|
57046
|
+
};
|
|
57047
|
+
if (result.capabilities) {
|
|
57048
|
+
decision.capabilities = result.capabilities;
|
|
57049
|
+
}
|
|
57050
|
+
return decision;
|
|
57051
|
+
}
|
|
57052
|
+
};
|
|
57053
|
+
}
|
|
57054
|
+
});
|
|
57055
|
+
|
|
57056
|
+
// src/enterprise/scheduler/knex-store.ts
|
|
57057
|
+
var knex_store_exports = {};
|
|
57058
|
+
__export(knex_store_exports, {
|
|
57059
|
+
KnexStoreBackend: () => KnexStoreBackend
|
|
57060
|
+
});
|
|
57061
|
+
function toNum(val) {
|
|
57062
|
+
if (val === null || val === void 0) return void 0;
|
|
57063
|
+
return typeof val === "string" ? parseInt(val, 10) : val;
|
|
57064
|
+
}
|
|
57065
|
+
function safeJsonParse2(value) {
|
|
57066
|
+
if (!value) return void 0;
|
|
57067
|
+
try {
|
|
57068
|
+
return JSON.parse(value);
|
|
57069
|
+
} catch {
|
|
57070
|
+
return void 0;
|
|
57071
|
+
}
|
|
57072
|
+
}
|
|
57073
|
+
function fromTriggerRow2(row) {
|
|
57074
|
+
return {
|
|
57075
|
+
id: row.id,
|
|
57076
|
+
creatorId: row.creator_id,
|
|
57077
|
+
creatorContext: row.creator_context ?? void 0,
|
|
57078
|
+
creatorName: row.creator_name ?? void 0,
|
|
57079
|
+
description: row.description ?? void 0,
|
|
57080
|
+
channels: safeJsonParse2(row.channels),
|
|
57081
|
+
fromUsers: safeJsonParse2(row.from_users),
|
|
57082
|
+
fromBots: row.from_bots === true || row.from_bots === 1,
|
|
57083
|
+
contains: safeJsonParse2(row.contains),
|
|
57084
|
+
matchPattern: row.match_pattern ?? void 0,
|
|
57085
|
+
threads: row.threads,
|
|
57086
|
+
workflow: row.workflow,
|
|
57087
|
+
inputs: safeJsonParse2(row.inputs),
|
|
57088
|
+
outputContext: safeJsonParse2(row.output_context),
|
|
57089
|
+
status: row.status,
|
|
57090
|
+
enabled: row.enabled === true || row.enabled === 1,
|
|
57091
|
+
createdAt: toNum(row.created_at)
|
|
57092
|
+
};
|
|
57093
|
+
}
|
|
57094
|
+
function toTriggerInsertRow(trigger) {
|
|
57095
|
+
return {
|
|
57096
|
+
id: trigger.id,
|
|
57097
|
+
creator_id: trigger.creatorId,
|
|
57098
|
+
creator_context: trigger.creatorContext ?? null,
|
|
57099
|
+
creator_name: trigger.creatorName ?? null,
|
|
57100
|
+
description: trigger.description ?? null,
|
|
57101
|
+
channels: trigger.channels ? JSON.stringify(trigger.channels) : null,
|
|
57102
|
+
from_users: trigger.fromUsers ? JSON.stringify(trigger.fromUsers) : null,
|
|
57103
|
+
from_bots: trigger.fromBots,
|
|
57104
|
+
contains: trigger.contains ? JSON.stringify(trigger.contains) : null,
|
|
57105
|
+
match_pattern: trigger.matchPattern ?? null,
|
|
57106
|
+
threads: trigger.threads,
|
|
57107
|
+
workflow: trigger.workflow,
|
|
57108
|
+
inputs: trigger.inputs ? JSON.stringify(trigger.inputs) : null,
|
|
57109
|
+
output_context: trigger.outputContext ? JSON.stringify(trigger.outputContext) : null,
|
|
57110
|
+
status: trigger.status,
|
|
57111
|
+
enabled: trigger.enabled,
|
|
57112
|
+
created_at: trigger.createdAt
|
|
57113
|
+
};
|
|
57114
|
+
}
|
|
57115
|
+
function fromDbRow2(row) {
|
|
57116
|
+
return {
|
|
57117
|
+
id: row.id,
|
|
57118
|
+
creatorId: row.creator_id,
|
|
57119
|
+
creatorContext: row.creator_context ?? void 0,
|
|
57120
|
+
creatorName: row.creator_name ?? void 0,
|
|
57121
|
+
timezone: row.timezone,
|
|
57122
|
+
schedule: row.schedule_expr,
|
|
57123
|
+
runAt: toNum(row.run_at),
|
|
57124
|
+
isRecurring: row.is_recurring === true || row.is_recurring === 1,
|
|
57125
|
+
originalExpression: row.original_expression,
|
|
57126
|
+
workflow: row.workflow ?? void 0,
|
|
57127
|
+
workflowInputs: safeJsonParse2(row.workflow_inputs),
|
|
57128
|
+
outputContext: safeJsonParse2(row.output_context),
|
|
57129
|
+
status: row.status,
|
|
57130
|
+
createdAt: toNum(row.created_at),
|
|
57131
|
+
lastRunAt: toNum(row.last_run_at),
|
|
57132
|
+
nextRunAt: toNum(row.next_run_at),
|
|
57133
|
+
runCount: row.run_count,
|
|
57134
|
+
failureCount: row.failure_count,
|
|
57135
|
+
lastError: row.last_error ?? void 0,
|
|
57136
|
+
previousResponse: row.previous_response ?? void 0
|
|
57137
|
+
};
|
|
57138
|
+
}
|
|
57139
|
+
function toInsertRow(schedule) {
|
|
57140
|
+
return {
|
|
57141
|
+
id: schedule.id,
|
|
57142
|
+
creator_id: schedule.creatorId,
|
|
57143
|
+
creator_context: schedule.creatorContext ?? null,
|
|
57144
|
+
creator_name: schedule.creatorName ?? null,
|
|
57145
|
+
timezone: schedule.timezone,
|
|
57146
|
+
schedule_expr: schedule.schedule,
|
|
57147
|
+
run_at: schedule.runAt ?? null,
|
|
57148
|
+
is_recurring: schedule.isRecurring,
|
|
57149
|
+
original_expression: schedule.originalExpression,
|
|
57150
|
+
workflow: schedule.workflow ?? null,
|
|
57151
|
+
workflow_inputs: schedule.workflowInputs ? JSON.stringify(schedule.workflowInputs) : null,
|
|
57152
|
+
output_context: schedule.outputContext ? JSON.stringify(schedule.outputContext) : null,
|
|
57153
|
+
status: schedule.status,
|
|
57154
|
+
created_at: schedule.createdAt,
|
|
57155
|
+
last_run_at: schedule.lastRunAt ?? null,
|
|
57156
|
+
next_run_at: schedule.nextRunAt ?? null,
|
|
57157
|
+
run_count: schedule.runCount,
|
|
57158
|
+
failure_count: schedule.failureCount,
|
|
57159
|
+
last_error: schedule.lastError ?? null,
|
|
57160
|
+
previous_response: schedule.previousResponse ?? null
|
|
57161
|
+
};
|
|
57162
|
+
}
|
|
57163
|
+
var fs24, path29, import_uuid2, KnexStoreBackend;
|
|
57164
|
+
var init_knex_store = __esm({
|
|
57165
|
+
"src/enterprise/scheduler/knex-store.ts"() {
|
|
57166
|
+
"use strict";
|
|
57167
|
+
fs24 = __toESM(require("fs"));
|
|
57168
|
+
path29 = __toESM(require("path"));
|
|
57169
|
+
import_uuid2 = require("uuid");
|
|
57170
|
+
init_logger();
|
|
57171
|
+
KnexStoreBackend = class {
|
|
57172
|
+
knex = null;
|
|
57173
|
+
driver;
|
|
57174
|
+
connection;
|
|
57175
|
+
constructor(driver, storageConfig, _haConfig) {
|
|
57176
|
+
this.driver = driver;
|
|
57177
|
+
this.connection = storageConfig.connection || {};
|
|
57178
|
+
}
|
|
57179
|
+
async initialize() {
|
|
57180
|
+
const { createRequire } = require("module");
|
|
57181
|
+
const runtimeRequire = createRequire(__filename);
|
|
57182
|
+
let knexFactory;
|
|
57183
|
+
try {
|
|
57184
|
+
knexFactory = runtimeRequire("knex");
|
|
57185
|
+
} catch (err) {
|
|
57186
|
+
const code = err?.code;
|
|
57187
|
+
if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
|
|
57188
|
+
throw new Error(
|
|
57189
|
+
"knex is required for PostgreSQL/MySQL/MSSQL schedule storage. Install it with: npm install knex"
|
|
57190
|
+
);
|
|
57191
|
+
}
|
|
57192
|
+
throw err;
|
|
57193
|
+
}
|
|
57194
|
+
const clientMap = {
|
|
57195
|
+
postgresql: "pg",
|
|
57196
|
+
mysql: "mysql2",
|
|
57197
|
+
mssql: "tedious"
|
|
57198
|
+
};
|
|
57199
|
+
const client = clientMap[this.driver];
|
|
57200
|
+
let connection;
|
|
57201
|
+
if (this.connection.connection_string) {
|
|
57202
|
+
connection = this.connection.connection_string;
|
|
57203
|
+
} else if (this.driver === "mssql") {
|
|
57204
|
+
connection = this.buildMssqlConnection();
|
|
57205
|
+
} else {
|
|
57206
|
+
connection = this.buildStandardConnection();
|
|
57207
|
+
}
|
|
57208
|
+
this.knex = knexFactory({
|
|
57209
|
+
client,
|
|
57210
|
+
connection,
|
|
57211
|
+
pool: {
|
|
57212
|
+
min: this.connection.pool?.min ?? 0,
|
|
57213
|
+
max: this.connection.pool?.max ?? 10
|
|
57214
|
+
}
|
|
57215
|
+
});
|
|
57216
|
+
await this.migrateSchema();
|
|
57217
|
+
logger.info(`[KnexStore] Initialized (${this.driver})`);
|
|
57218
|
+
}
|
|
57219
|
+
buildStandardConnection() {
|
|
57220
|
+
return {
|
|
57221
|
+
host: this.connection.host || "localhost",
|
|
57222
|
+
port: this.connection.port,
|
|
57223
|
+
database: this.connection.database || "visor",
|
|
57224
|
+
user: this.connection.user,
|
|
57225
|
+
password: this.connection.password,
|
|
57226
|
+
ssl: this.resolveSslConfig()
|
|
57227
|
+
};
|
|
57228
|
+
}
|
|
57229
|
+
buildMssqlConnection() {
|
|
57230
|
+
const ssl = this.connection.ssl;
|
|
57231
|
+
const sslEnabled = ssl === true || typeof ssl === "object" && ssl.enabled !== false;
|
|
57232
|
+
return {
|
|
57233
|
+
server: this.connection.host || "localhost",
|
|
57234
|
+
port: this.connection.port,
|
|
57235
|
+
database: this.connection.database || "visor",
|
|
57236
|
+
user: this.connection.user,
|
|
57237
|
+
password: this.connection.password,
|
|
57238
|
+
options: {
|
|
57239
|
+
encrypt: sslEnabled,
|
|
57240
|
+
trustServerCertificate: typeof ssl === "object" ? ssl.reject_unauthorized === false : !sslEnabled
|
|
57241
|
+
}
|
|
57242
|
+
};
|
|
57243
|
+
}
|
|
57244
|
+
resolveSslConfig() {
|
|
57245
|
+
const ssl = this.connection.ssl;
|
|
57246
|
+
if (ssl === false || ssl === void 0) return false;
|
|
57247
|
+
if (ssl === true) return { rejectUnauthorized: true };
|
|
57248
|
+
if (ssl.enabled === false) return false;
|
|
57249
|
+
const result = {
|
|
57250
|
+
rejectUnauthorized: ssl.reject_unauthorized !== false
|
|
57251
|
+
};
|
|
57252
|
+
if (ssl.ca) {
|
|
57253
|
+
const caPath = this.validateSslPath(ssl.ca, "CA certificate");
|
|
57254
|
+
result.ca = fs24.readFileSync(caPath, "utf8");
|
|
57255
|
+
}
|
|
57256
|
+
if (ssl.cert) {
|
|
57257
|
+
const certPath = this.validateSslPath(ssl.cert, "client certificate");
|
|
57258
|
+
result.cert = fs24.readFileSync(certPath, "utf8");
|
|
57259
|
+
}
|
|
57260
|
+
if (ssl.key) {
|
|
57261
|
+
const keyPath = this.validateSslPath(ssl.key, "client key");
|
|
57262
|
+
result.key = fs24.readFileSync(keyPath, "utf8");
|
|
57263
|
+
}
|
|
57264
|
+
return result;
|
|
57265
|
+
}
|
|
57266
|
+
validateSslPath(filePath, label) {
|
|
57267
|
+
const resolved = path29.resolve(filePath);
|
|
57268
|
+
if (resolved !== path29.normalize(resolved)) {
|
|
57269
|
+
throw new Error(`SSL ${label} path contains invalid sequences: ${filePath}`);
|
|
57270
|
+
}
|
|
57271
|
+
if (!fs24.existsSync(resolved)) {
|
|
57272
|
+
throw new Error(`SSL ${label} not found: ${filePath}`);
|
|
57273
|
+
}
|
|
57274
|
+
return resolved;
|
|
57275
|
+
}
|
|
57276
|
+
async shutdown() {
|
|
57277
|
+
if (this.knex) {
|
|
57278
|
+
await this.knex.destroy();
|
|
57279
|
+
this.knex = null;
|
|
57280
|
+
}
|
|
57281
|
+
}
|
|
57282
|
+
async migrateSchema() {
|
|
57283
|
+
const knex = this.getKnex();
|
|
57284
|
+
const exists = await knex.schema.hasTable("schedules");
|
|
57285
|
+
if (!exists) {
|
|
57286
|
+
await knex.schema.createTable("schedules", (table) => {
|
|
57287
|
+
table.string("id", 36).primary();
|
|
57288
|
+
table.string("creator_id", 255).notNullable().index();
|
|
57289
|
+
table.string("creator_context", 255);
|
|
57290
|
+
table.string("creator_name", 255);
|
|
57291
|
+
table.string("timezone", 64).notNullable().defaultTo("UTC");
|
|
57292
|
+
table.string("schedule_expr", 255);
|
|
57293
|
+
table.bigInteger("run_at");
|
|
57294
|
+
table.boolean("is_recurring").notNullable();
|
|
57295
|
+
table.text("original_expression");
|
|
57296
|
+
table.string("workflow", 255);
|
|
57297
|
+
table.text("workflow_inputs");
|
|
57298
|
+
table.text("output_context");
|
|
57299
|
+
table.string("status", 20).notNullable().index();
|
|
57300
|
+
table.bigInteger("created_at").notNullable();
|
|
57301
|
+
table.bigInteger("last_run_at");
|
|
57302
|
+
table.bigInteger("next_run_at");
|
|
57303
|
+
table.integer("run_count").notNullable().defaultTo(0);
|
|
57304
|
+
table.integer("failure_count").notNullable().defaultTo(0);
|
|
57305
|
+
table.text("last_error");
|
|
57306
|
+
table.text("previous_response");
|
|
57307
|
+
table.index(["status", "next_run_at"]);
|
|
57308
|
+
});
|
|
57309
|
+
}
|
|
57310
|
+
const triggersExist = await knex.schema.hasTable("message_triggers");
|
|
57311
|
+
if (!triggersExist) {
|
|
57312
|
+
await knex.schema.createTable("message_triggers", (table) => {
|
|
57313
|
+
table.string("id", 36).primary();
|
|
57314
|
+
table.string("creator_id", 255).notNullable().index();
|
|
57315
|
+
table.string("creator_context", 255);
|
|
57316
|
+
table.string("creator_name", 255);
|
|
57317
|
+
table.text("description");
|
|
57318
|
+
table.text("channels");
|
|
57319
|
+
table.text("from_users");
|
|
57320
|
+
table.boolean("from_bots").notNullable().defaultTo(false);
|
|
57321
|
+
table.text("contains");
|
|
57322
|
+
table.text("match_pattern");
|
|
57323
|
+
table.string("threads", 20).notNullable().defaultTo("any");
|
|
57324
|
+
table.string("workflow", 255).notNullable();
|
|
57325
|
+
table.text("inputs");
|
|
57326
|
+
table.text("output_context");
|
|
57327
|
+
table.string("status", 20).notNullable().defaultTo("active").index();
|
|
57328
|
+
table.boolean("enabled").notNullable().defaultTo(true);
|
|
57329
|
+
table.bigInteger("created_at").notNullable();
|
|
57330
|
+
});
|
|
57331
|
+
}
|
|
57332
|
+
const locksExist = await knex.schema.hasTable("scheduler_locks");
|
|
57333
|
+
if (!locksExist) {
|
|
57334
|
+
await knex.schema.createTable("scheduler_locks", (table) => {
|
|
57335
|
+
table.string("lock_id", 255).primary();
|
|
57336
|
+
table.string("node_id", 255).notNullable();
|
|
57337
|
+
table.string("lock_token", 36).notNullable();
|
|
57338
|
+
table.bigInteger("acquired_at").notNullable();
|
|
57339
|
+
table.bigInteger("expires_at").notNullable();
|
|
57340
|
+
});
|
|
57341
|
+
}
|
|
57342
|
+
}
|
|
57343
|
+
getKnex() {
|
|
57344
|
+
if (!this.knex) {
|
|
57345
|
+
throw new Error("[KnexStore] Not initialized. Call initialize() first.");
|
|
57346
|
+
}
|
|
57347
|
+
return this.knex;
|
|
57348
|
+
}
|
|
57349
|
+
// --- CRUD ---
|
|
57350
|
+
async create(schedule) {
|
|
57351
|
+
const knex = this.getKnex();
|
|
57352
|
+
const newSchedule = {
|
|
57353
|
+
...schedule,
|
|
57354
|
+
id: (0, import_uuid2.v4)(),
|
|
57355
|
+
createdAt: Date.now(),
|
|
57356
|
+
runCount: 0,
|
|
57357
|
+
failureCount: 0,
|
|
57358
|
+
status: "active"
|
|
57359
|
+
};
|
|
57360
|
+
await knex("schedules").insert(toInsertRow(newSchedule));
|
|
57361
|
+
logger.info(`[KnexStore] Created schedule ${newSchedule.id} for user ${newSchedule.creatorId}`);
|
|
57362
|
+
return newSchedule;
|
|
57363
|
+
}
|
|
57364
|
+
async importSchedule(schedule) {
|
|
57365
|
+
const knex = this.getKnex();
|
|
57366
|
+
const existing = await knex("schedules").where("id", schedule.id).first();
|
|
57367
|
+
if (existing) return;
|
|
57368
|
+
await knex("schedules").insert(toInsertRow(schedule));
|
|
57369
|
+
}
|
|
57370
|
+
async get(id) {
|
|
57371
|
+
const knex = this.getKnex();
|
|
57372
|
+
const row = await knex("schedules").where("id", id).first();
|
|
57373
|
+
return row ? fromDbRow2(row) : void 0;
|
|
57374
|
+
}
|
|
57375
|
+
async update(id, patch) {
|
|
57376
|
+
const knex = this.getKnex();
|
|
57377
|
+
const existing = await knex("schedules").where("id", id).first();
|
|
57378
|
+
if (!existing) return void 0;
|
|
57379
|
+
const current = fromDbRow2(existing);
|
|
57380
|
+
const updated = { ...current, ...patch, id: current.id };
|
|
57381
|
+
const row = toInsertRow(updated);
|
|
57382
|
+
delete row.id;
|
|
57383
|
+
await knex("schedules").where("id", id).update(row);
|
|
57384
|
+
return updated;
|
|
57385
|
+
}
|
|
57386
|
+
async delete(id) {
|
|
57387
|
+
const knex = this.getKnex();
|
|
57388
|
+
const deleted = await knex("schedules").where("id", id).del();
|
|
57389
|
+
if (deleted > 0) {
|
|
57390
|
+
logger.info(`[KnexStore] Deleted schedule ${id}`);
|
|
57391
|
+
return true;
|
|
57392
|
+
}
|
|
57393
|
+
return false;
|
|
57394
|
+
}
|
|
57395
|
+
// --- Queries ---
|
|
57396
|
+
async getByCreator(creatorId) {
|
|
57397
|
+
const knex = this.getKnex();
|
|
57398
|
+
const rows = await knex("schedules").where("creator_id", creatorId);
|
|
57399
|
+
return rows.map((r) => fromDbRow2(r));
|
|
57400
|
+
}
|
|
57401
|
+
async getActiveSchedules() {
|
|
57402
|
+
const knex = this.getKnex();
|
|
57403
|
+
const rows = await knex("schedules").where("status", "active");
|
|
57404
|
+
return rows.map((r) => fromDbRow2(r));
|
|
57405
|
+
}
|
|
57406
|
+
async getDueSchedules(now) {
|
|
57407
|
+
const ts = now ?? Date.now();
|
|
57408
|
+
const knex = this.getKnex();
|
|
57409
|
+
const bFalse = this.driver === "mssql" ? 0 : false;
|
|
57410
|
+
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
57411
|
+
const rows = await knex("schedules").where("status", "active").andWhere(function() {
|
|
57412
|
+
this.where(function() {
|
|
57413
|
+
this.where("is_recurring", bFalse).whereNotNull("run_at").where("run_at", "<=", ts);
|
|
57414
|
+
}).orWhere(function() {
|
|
57415
|
+
this.where("is_recurring", bTrue).whereNotNull("next_run_at").where("next_run_at", "<=", ts);
|
|
57416
|
+
});
|
|
57417
|
+
});
|
|
57418
|
+
return rows.map((r) => fromDbRow2(r));
|
|
57419
|
+
}
|
|
57420
|
+
async findByWorkflow(creatorId, workflowName) {
|
|
57421
|
+
const knex = this.getKnex();
|
|
57422
|
+
const escaped = workflowName.toLowerCase().replace(/[%_\\]/g, "\\$&");
|
|
57423
|
+
const pattern = `%${escaped}%`;
|
|
57424
|
+
const rows = await knex("schedules").where("creator_id", creatorId).where("status", "active").whereRaw("LOWER(workflow) LIKE ? ESCAPE '\\'", [pattern]);
|
|
57425
|
+
return rows.map((r) => fromDbRow2(r));
|
|
57426
|
+
}
|
|
57427
|
+
async getAll() {
|
|
57428
|
+
const knex = this.getKnex();
|
|
57429
|
+
const rows = await knex("schedules");
|
|
57430
|
+
return rows.map((r) => fromDbRow2(r));
|
|
57431
|
+
}
|
|
57432
|
+
async getStats() {
|
|
57433
|
+
const knex = this.getKnex();
|
|
57434
|
+
const boolTrue = this.driver === "mssql" ? "1" : "true";
|
|
57435
|
+
const boolFalse = this.driver === "mssql" ? "0" : "false";
|
|
57436
|
+
const result = await knex("schedules").select(
|
|
57437
|
+
knex.raw("COUNT(*) as total"),
|
|
57438
|
+
knex.raw("SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active"),
|
|
57439
|
+
knex.raw("SUM(CASE WHEN status = 'paused' THEN 1 ELSE 0 END) as paused"),
|
|
57440
|
+
knex.raw("SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed"),
|
|
57441
|
+
knex.raw("SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed"),
|
|
57442
|
+
knex.raw(`SUM(CASE WHEN is_recurring = ${boolTrue} THEN 1 ELSE 0 END) as recurring`),
|
|
57443
|
+
knex.raw(`SUM(CASE WHEN is_recurring = ${boolFalse} THEN 1 ELSE 0 END) as one_time`)
|
|
57444
|
+
).first();
|
|
57445
|
+
return {
|
|
57446
|
+
total: Number(result.total) || 0,
|
|
57447
|
+
active: Number(result.active) || 0,
|
|
57448
|
+
paused: Number(result.paused) || 0,
|
|
57449
|
+
completed: Number(result.completed) || 0,
|
|
57450
|
+
failed: Number(result.failed) || 0,
|
|
57451
|
+
recurring: Number(result.recurring) || 0,
|
|
57452
|
+
oneTime: Number(result.one_time) || 0
|
|
57453
|
+
};
|
|
57454
|
+
}
|
|
57455
|
+
async validateLimits(creatorId, isRecurring, limits) {
|
|
57456
|
+
const knex = this.getKnex();
|
|
57457
|
+
if (limits.maxGlobal) {
|
|
57458
|
+
const result = await knex("schedules").count("* as cnt").first();
|
|
57459
|
+
if (Number(result?.cnt) >= limits.maxGlobal) {
|
|
57460
|
+
throw new Error(`Global schedule limit reached (${limits.maxGlobal})`);
|
|
57461
|
+
}
|
|
57462
|
+
}
|
|
57463
|
+
if (limits.maxPerUser) {
|
|
57464
|
+
const result = await knex("schedules").where("creator_id", creatorId).count("* as cnt").first();
|
|
57465
|
+
if (Number(result?.cnt) >= limits.maxPerUser) {
|
|
57466
|
+
throw new Error(`You have reached the maximum number of schedules (${limits.maxPerUser})`);
|
|
57467
|
+
}
|
|
57468
|
+
}
|
|
57469
|
+
if (isRecurring && limits.maxRecurringPerUser) {
|
|
57470
|
+
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
57471
|
+
const result = await knex("schedules").where("creator_id", creatorId).where("is_recurring", bTrue).count("* as cnt").first();
|
|
57472
|
+
if (Number(result?.cnt) >= limits.maxRecurringPerUser) {
|
|
57473
|
+
throw new Error(
|
|
57474
|
+
`You have reached the maximum number of recurring schedules (${limits.maxRecurringPerUser})`
|
|
57475
|
+
);
|
|
57476
|
+
}
|
|
57477
|
+
}
|
|
57478
|
+
}
|
|
57479
|
+
// --- HA Distributed Locking (via scheduler_locks table) ---
|
|
57480
|
+
async tryAcquireLock(lockId, nodeId, ttlSeconds) {
|
|
57481
|
+
const knex = this.getKnex();
|
|
57482
|
+
const now = Date.now();
|
|
57483
|
+
const expiresAt = now + ttlSeconds * 1e3;
|
|
57484
|
+
const token = (0, import_uuid2.v4)();
|
|
57485
|
+
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("expires_at", "<", now).update({
|
|
57486
|
+
node_id: nodeId,
|
|
57487
|
+
lock_token: token,
|
|
57488
|
+
acquired_at: now,
|
|
57489
|
+
expires_at: expiresAt
|
|
57490
|
+
});
|
|
57491
|
+
if (updated > 0) return token;
|
|
57492
|
+
try {
|
|
57493
|
+
await knex("scheduler_locks").insert({
|
|
57494
|
+
lock_id: lockId,
|
|
57495
|
+
node_id: nodeId,
|
|
57496
|
+
lock_token: token,
|
|
57497
|
+
acquired_at: now,
|
|
57498
|
+
expires_at: expiresAt
|
|
57499
|
+
});
|
|
57500
|
+
return token;
|
|
57501
|
+
} catch {
|
|
57502
|
+
return null;
|
|
57503
|
+
}
|
|
57504
|
+
}
|
|
57505
|
+
async releaseLock(lockId, lockToken) {
|
|
57506
|
+
const knex = this.getKnex();
|
|
57507
|
+
await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).del();
|
|
57508
|
+
}
|
|
57509
|
+
async renewLock(lockId, lockToken, ttlSeconds) {
|
|
57510
|
+
const knex = this.getKnex();
|
|
57511
|
+
const now = Date.now();
|
|
57512
|
+
const expiresAt = now + ttlSeconds * 1e3;
|
|
57513
|
+
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).update({ acquired_at: now, expires_at: expiresAt });
|
|
57514
|
+
return updated > 0;
|
|
57515
|
+
}
|
|
57516
|
+
async flush() {
|
|
57517
|
+
}
|
|
57518
|
+
// --- Message Trigger CRUD ---
|
|
57519
|
+
async createTrigger(trigger) {
|
|
57520
|
+
const knex = this.getKnex();
|
|
57521
|
+
const newTrigger = {
|
|
57522
|
+
...trigger,
|
|
57523
|
+
id: (0, import_uuid2.v4)(),
|
|
57524
|
+
createdAt: Date.now()
|
|
57525
|
+
};
|
|
57526
|
+
await knex("message_triggers").insert(toTriggerInsertRow(newTrigger));
|
|
57527
|
+
logger.info(`[KnexStore] Created trigger ${newTrigger.id} for user ${newTrigger.creatorId}`);
|
|
57528
|
+
return newTrigger;
|
|
57529
|
+
}
|
|
57530
|
+
async getTrigger(id) {
|
|
57531
|
+
const knex = this.getKnex();
|
|
57532
|
+
const row = await knex("message_triggers").where("id", id).first();
|
|
57533
|
+
return row ? fromTriggerRow2(row) : void 0;
|
|
57534
|
+
}
|
|
57535
|
+
async updateTrigger(id, patch) {
|
|
57536
|
+
const knex = this.getKnex();
|
|
57537
|
+
const existing = await knex("message_triggers").where("id", id).first();
|
|
57538
|
+
if (!existing) return void 0;
|
|
57539
|
+
const current = fromTriggerRow2(existing);
|
|
57540
|
+
const updated = {
|
|
57541
|
+
...current,
|
|
57542
|
+
...patch,
|
|
57543
|
+
id: current.id,
|
|
57544
|
+
createdAt: current.createdAt
|
|
57545
|
+
};
|
|
57546
|
+
const row = toTriggerInsertRow(updated);
|
|
57547
|
+
delete row.id;
|
|
57548
|
+
await knex("message_triggers").where("id", id).update(row);
|
|
57549
|
+
return updated;
|
|
57550
|
+
}
|
|
57551
|
+
async deleteTrigger(id) {
|
|
57552
|
+
const knex = this.getKnex();
|
|
57553
|
+
const deleted = await knex("message_triggers").where("id", id).del();
|
|
57554
|
+
if (deleted > 0) {
|
|
57555
|
+
logger.info(`[KnexStore] Deleted trigger ${id}`);
|
|
57556
|
+
return true;
|
|
57557
|
+
}
|
|
57558
|
+
return false;
|
|
57559
|
+
}
|
|
57560
|
+
async getTriggersByCreator(creatorId) {
|
|
57561
|
+
const knex = this.getKnex();
|
|
57562
|
+
const rows = await knex("message_triggers").where("creator_id", creatorId);
|
|
57563
|
+
return rows.map((r) => fromTriggerRow2(r));
|
|
57564
|
+
}
|
|
57565
|
+
async getActiveTriggers() {
|
|
57566
|
+
const knex = this.getKnex();
|
|
57567
|
+
const rows = await knex("message_triggers").where("status", "active").where("enabled", this.driver === "mssql" ? 1 : true);
|
|
57568
|
+
return rows.map((r) => fromTriggerRow2(r));
|
|
57569
|
+
}
|
|
57570
|
+
};
|
|
57571
|
+
}
|
|
57572
|
+
});
|
|
57573
|
+
|
|
57574
|
+
// src/enterprise/loader.ts
|
|
57575
|
+
var loader_exports = {};
|
|
57576
|
+
__export(loader_exports, {
|
|
57577
|
+
loadEnterprisePolicyEngine: () => loadEnterprisePolicyEngine,
|
|
57578
|
+
loadEnterpriseStoreBackend: () => loadEnterpriseStoreBackend
|
|
57579
|
+
});
|
|
57580
|
+
async function loadEnterprisePolicyEngine(config) {
|
|
57581
|
+
try {
|
|
57582
|
+
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
57583
|
+
const validator = new LicenseValidator2();
|
|
57584
|
+
const license = await validator.loadAndValidate();
|
|
57585
|
+
if (!license || !validator.hasFeature("policy")) {
|
|
57586
|
+
return new DefaultPolicyEngine();
|
|
57587
|
+
}
|
|
57588
|
+
if (validator.isInGracePeriod()) {
|
|
57589
|
+
console.warn(
|
|
57590
|
+
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
57591
|
+
);
|
|
57592
|
+
}
|
|
57593
|
+
const { OpaPolicyEngine: OpaPolicyEngine2 } = await Promise.resolve().then(() => (init_opa_policy_engine(), opa_policy_engine_exports));
|
|
57594
|
+
const engine = new OpaPolicyEngine2(config);
|
|
57595
|
+
await engine.initialize(config);
|
|
57596
|
+
return engine;
|
|
57597
|
+
} catch (err) {
|
|
57598
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
57599
|
+
try {
|
|
57600
|
+
const { logger: logger2 } = (init_logger(), __toCommonJS(logger_exports));
|
|
57601
|
+
logger2.warn(`[PolicyEngine] Enterprise policy init failed, falling back to default: ${msg}`);
|
|
57602
|
+
} catch {
|
|
57603
|
+
}
|
|
57604
|
+
return new DefaultPolicyEngine();
|
|
57605
|
+
}
|
|
57606
|
+
}
|
|
57607
|
+
async function loadEnterpriseStoreBackend(driver, storageConfig, haConfig) {
|
|
57608
|
+
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
57609
|
+
const validator = new LicenseValidator2();
|
|
57610
|
+
const license = await validator.loadAndValidate();
|
|
57611
|
+
if (!license || !validator.hasFeature("scheduler-sql")) {
|
|
57612
|
+
throw new Error(
|
|
57613
|
+
`The ${driver} schedule storage driver requires a Visor Enterprise license with the 'scheduler-sql' feature. Please upgrade or use driver: 'sqlite' (default).`
|
|
57614
|
+
);
|
|
57615
|
+
}
|
|
57616
|
+
if (validator.isInGracePeriod()) {
|
|
57617
|
+
console.warn(
|
|
57618
|
+
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
57619
|
+
);
|
|
57620
|
+
}
|
|
57621
|
+
const { KnexStoreBackend: KnexStoreBackend2 } = await Promise.resolve().then(() => (init_knex_store(), knex_store_exports));
|
|
57622
|
+
return new KnexStoreBackend2(driver, storageConfig, haConfig);
|
|
57623
|
+
}
|
|
57624
|
+
var init_loader = __esm({
|
|
57625
|
+
"src/enterprise/loader.ts"() {
|
|
57626
|
+
"use strict";
|
|
57627
|
+
init_default_engine();
|
|
57628
|
+
}
|
|
57629
|
+
});
|
|
57630
|
+
|
|
56257
57631
|
// src/event-bus/event-bus.ts
|
|
56258
57632
|
var event_bus_exports = {};
|
|
56259
57633
|
__export(event_bus_exports, {
|
|
@@ -57160,8 +58534,8 @@ ${content}
|
|
|
57160
58534
|
* Sleep utility
|
|
57161
58535
|
*/
|
|
57162
58536
|
sleep(ms) {
|
|
57163
|
-
return new Promise((
|
|
57164
|
-
const t = setTimeout(
|
|
58537
|
+
return new Promise((resolve19) => {
|
|
58538
|
+
const t = setTimeout(resolve19, ms);
|
|
57165
58539
|
if (typeof t.unref === "function") {
|
|
57166
58540
|
try {
|
|
57167
58541
|
t.unref();
|
|
@@ -57446,8 +58820,8 @@ ${end}`);
|
|
|
57446
58820
|
async updateGroupedComment(ctx, comments, group, changedIds) {
|
|
57447
58821
|
const existingLock = this.updateLocks.get(group);
|
|
57448
58822
|
let resolveLock;
|
|
57449
|
-
const ourLock = new Promise((
|
|
57450
|
-
resolveLock =
|
|
58823
|
+
const ourLock = new Promise((resolve19) => {
|
|
58824
|
+
resolveLock = resolve19;
|
|
57451
58825
|
});
|
|
57452
58826
|
this.updateLocks.set(group, ourLock);
|
|
57453
58827
|
try {
|
|
@@ -57778,7 +59152,7 @@ ${blocks}
|
|
|
57778
59152
|
* Sleep utility for enforcing delays
|
|
57779
59153
|
*/
|
|
57780
59154
|
sleep(ms) {
|
|
57781
|
-
return new Promise((
|
|
59155
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
57782
59156
|
}
|
|
57783
59157
|
};
|
|
57784
59158
|
}
|
|
@@ -58947,7 +60321,7 @@ var init_tui_frontend = __esm({
|
|
|
58947
60321
|
});
|
|
58948
60322
|
|
|
58949
60323
|
// src/agent-protocol/task-store.ts
|
|
58950
|
-
function
|
|
60324
|
+
function safeJsonParse3(value) {
|
|
58951
60325
|
if (!value) return void 0;
|
|
58952
60326
|
try {
|
|
58953
60327
|
return JSON.parse(value);
|
|
@@ -58964,12 +60338,12 @@ function taskRowToAgentTask(row) {
|
|
|
58964
60338
|
context_id: row.context_id,
|
|
58965
60339
|
status: {
|
|
58966
60340
|
state: row.state,
|
|
58967
|
-
message:
|
|
60341
|
+
message: safeJsonParse3(row.status_message),
|
|
58968
60342
|
timestamp: row.updated_at
|
|
58969
60343
|
},
|
|
58970
|
-
artifacts:
|
|
58971
|
-
history:
|
|
58972
|
-
metadata:
|
|
60344
|
+
artifacts: safeJsonParse3(row.artifacts) ?? [],
|
|
60345
|
+
history: safeJsonParse3(row.history) ?? [],
|
|
60346
|
+
metadata: safeJsonParse3(row.request_metadata),
|
|
58973
60347
|
workflow_id: row.workflow_id ?? void 0
|
|
58974
60348
|
};
|
|
58975
60349
|
}
|
|
@@ -59114,6 +60488,15 @@ var init_task_store = __esm({
|
|
|
59114
60488
|
conditions.push("workflow_id = ?");
|
|
59115
60489
|
params.push(filter.workflowId);
|
|
59116
60490
|
}
|
|
60491
|
+
if (filter.search) {
|
|
60492
|
+
const escaped = filter.search.replace(/[%_\\]/g, "\\$&");
|
|
60493
|
+
conditions.push("request_message LIKE ? ESCAPE '\\'");
|
|
60494
|
+
params.push(`%${escaped}%`);
|
|
60495
|
+
}
|
|
60496
|
+
if (filter.claimedBy) {
|
|
60497
|
+
conditions.push("claimed_by = ?");
|
|
60498
|
+
params.push(filter.claimedBy);
|
|
60499
|
+
}
|
|
59117
60500
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
59118
60501
|
return { where, params };
|
|
59119
60502
|
}
|
|
@@ -59197,7 +60580,7 @@ var init_task_store = __esm({
|
|
|
59197
60580
|
const db = this.getDb();
|
|
59198
60581
|
const row = db.prepare("SELECT artifacts FROM agent_tasks WHERE id = ?").get(taskId);
|
|
59199
60582
|
if (!row) throw new TaskNotFoundError(taskId);
|
|
59200
|
-
const artifacts =
|
|
60583
|
+
const artifacts = safeJsonParse3(row.artifacts) ?? [];
|
|
59201
60584
|
artifacts.push(artifact);
|
|
59202
60585
|
db.prepare("UPDATE agent_tasks SET artifacts = ?, updated_at = ? WHERE id = ?").run(
|
|
59203
60586
|
JSON.stringify(artifacts),
|
|
@@ -59209,7 +60592,7 @@ var init_task_store = __esm({
|
|
|
59209
60592
|
const db = this.getDb();
|
|
59210
60593
|
const row = db.prepare("SELECT history FROM agent_tasks WHERE id = ?").get(taskId);
|
|
59211
60594
|
if (!row) throw new TaskNotFoundError(taskId);
|
|
59212
|
-
const history =
|
|
60595
|
+
const history = safeJsonParse3(row.history) ?? [];
|
|
59213
60596
|
history.push(message);
|
|
59214
60597
|
db.prepare("UPDATE agent_tasks SET history = ?, updated_at = ? WHERE id = ?").run(
|
|
59215
60598
|
JSON.stringify(history),
|
|
@@ -59267,6 +60650,32 @@ var init_task_store = __esm({
|
|
|
59267
60650
|
// -------------------------------------------------------------------------
|
|
59268
60651
|
// Cleanup
|
|
59269
60652
|
// -------------------------------------------------------------------------
|
|
60653
|
+
failStaleTasks(reason) {
|
|
60654
|
+
const db = this.getDb();
|
|
60655
|
+
const now = nowISO();
|
|
60656
|
+
const msg = reason || "Process terminated while task was running";
|
|
60657
|
+
const statusMessage = JSON.stringify({
|
|
60658
|
+
message_id: import_crypto6.default.randomUUID(),
|
|
60659
|
+
role: "agent",
|
|
60660
|
+
parts: [{ text: msg }]
|
|
60661
|
+
});
|
|
60662
|
+
const result = db.prepare(
|
|
60663
|
+
`UPDATE agent_tasks
|
|
60664
|
+
SET state = 'failed', updated_at = ?, status_message = ?
|
|
60665
|
+
WHERE state = 'working'`
|
|
60666
|
+
).run(now, statusMessage);
|
|
60667
|
+
return result.changes;
|
|
60668
|
+
}
|
|
60669
|
+
purgeOldTasks(olderThanMs) {
|
|
60670
|
+
const db = this.getDb();
|
|
60671
|
+
const cutoff = new Date(Date.now() - olderThanMs).toISOString();
|
|
60672
|
+
const result = db.prepare(
|
|
60673
|
+
`DELETE FROM agent_tasks
|
|
60674
|
+
WHERE state IN ('completed', 'failed', 'canceled', 'rejected')
|
|
60675
|
+
AND updated_at <= ?`
|
|
60676
|
+
).run(cutoff);
|
|
60677
|
+
return result.changes;
|
|
60678
|
+
}
|
|
59270
60679
|
deleteExpiredTasks() {
|
|
59271
60680
|
const db = this.getDb();
|
|
59272
60681
|
const now = nowISO();
|
|
@@ -59695,13 +61104,13 @@ __export(a2a_frontend_exports, {
|
|
|
59695
61104
|
resultToArtifacts: () => resultToArtifacts
|
|
59696
61105
|
});
|
|
59697
61106
|
function readJsonBody(req) {
|
|
59698
|
-
return new Promise((
|
|
61107
|
+
return new Promise((resolve19, reject) => {
|
|
59699
61108
|
const chunks = [];
|
|
59700
61109
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
59701
61110
|
req.on("end", () => {
|
|
59702
61111
|
try {
|
|
59703
61112
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
59704
|
-
|
|
61113
|
+
resolve19(body ? JSON.parse(body) : {});
|
|
59705
61114
|
} catch {
|
|
59706
61115
|
reject(new ParseError("Malformed JSON body"));
|
|
59707
61116
|
}
|
|
@@ -59944,12 +61353,12 @@ var init_a2a_frontend = __esm({
|
|
|
59944
61353
|
}
|
|
59945
61354
|
const port = this.config.port ?? 9e3;
|
|
59946
61355
|
const host = this.config.host ?? "0.0.0.0";
|
|
59947
|
-
await new Promise((
|
|
61356
|
+
await new Promise((resolve19) => {
|
|
59948
61357
|
this.server.listen(port, host, () => {
|
|
59949
61358
|
const addr = this.server.address();
|
|
59950
61359
|
this._boundPort = typeof addr === "object" && addr ? addr.port : port;
|
|
59951
61360
|
logger.info(`A2A server listening on ${host}:${this._boundPort}`);
|
|
59952
|
-
|
|
61361
|
+
resolve19();
|
|
59953
61362
|
});
|
|
59954
61363
|
});
|
|
59955
61364
|
if (this.agentCard) {
|
|
@@ -59973,8 +61382,8 @@ var init_a2a_frontend = __esm({
|
|
|
59973
61382
|
}
|
|
59974
61383
|
this.streamManager.shutdown();
|
|
59975
61384
|
if (this.server) {
|
|
59976
|
-
await new Promise((
|
|
59977
|
-
this.server.close((err) => err ? reject(err) :
|
|
61385
|
+
await new Promise((resolve19, reject) => {
|
|
61386
|
+
this.server.close((err) => err ? reject(err) : resolve19());
|
|
59978
61387
|
});
|
|
59979
61388
|
this.server = null;
|
|
59980
61389
|
}
|
|
@@ -60679,15 +62088,15 @@ function serializeRunState(state) {
|
|
|
60679
62088
|
])
|
|
60680
62089
|
};
|
|
60681
62090
|
}
|
|
60682
|
-
var
|
|
62091
|
+
var path32, fs28, StateMachineExecutionEngine;
|
|
60683
62092
|
var init_state_machine_execution_engine = __esm({
|
|
60684
62093
|
"src/state-machine-execution-engine.ts"() {
|
|
60685
62094
|
"use strict";
|
|
60686
62095
|
init_runner();
|
|
60687
62096
|
init_logger();
|
|
60688
62097
|
init_sandbox_manager();
|
|
60689
|
-
|
|
60690
|
-
|
|
62098
|
+
path32 = __toESM(require("path"));
|
|
62099
|
+
fs28 = __toESM(require("fs"));
|
|
60691
62100
|
StateMachineExecutionEngine = class _StateMachineExecutionEngine {
|
|
60692
62101
|
workingDirectory;
|
|
60693
62102
|
executionContext;
|
|
@@ -60919,8 +62328,8 @@ var init_state_machine_execution_engine = __esm({
|
|
|
60919
62328
|
logger.debug(
|
|
60920
62329
|
`[PolicyEngine] Loading enterprise policy engine (engine=${configWithTagFilter.policy.engine})`
|
|
60921
62330
|
);
|
|
60922
|
-
const { loadEnterprisePolicyEngine } = await
|
|
60923
|
-
context2.policyEngine = await
|
|
62331
|
+
const { loadEnterprisePolicyEngine: loadEnterprisePolicyEngine2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
62332
|
+
context2.policyEngine = await loadEnterprisePolicyEngine2(configWithTagFilter.policy);
|
|
60924
62333
|
logger.debug(
|
|
60925
62334
|
`[PolicyEngine] Initialized: ${context2.policyEngine?.constructor?.name || "unknown"}`
|
|
60926
62335
|
);
|
|
@@ -61074,9 +62483,9 @@ var init_state_machine_execution_engine = __esm({
|
|
|
61074
62483
|
}
|
|
61075
62484
|
const checkId = String(ev?.checkId || "unknown");
|
|
61076
62485
|
const threadKey = ev?.threadKey || (channel && threadTs ? `${channel}:${threadTs}` : "session");
|
|
61077
|
-
const baseDir = process.env.VISOR_SNAPSHOT_DIR ||
|
|
61078
|
-
|
|
61079
|
-
const filePath =
|
|
62486
|
+
const baseDir = process.env.VISOR_SNAPSHOT_DIR || path32.resolve(process.cwd(), ".visor", "snapshots");
|
|
62487
|
+
fs28.mkdirSync(baseDir, { recursive: true });
|
|
62488
|
+
const filePath = path32.join(baseDir, `${threadKey}-${checkId}.json`);
|
|
61080
62489
|
await this.saveSnapshotToFile(filePath);
|
|
61081
62490
|
logger.info(`[Snapshot] Saved run snapshot: ${filePath}`);
|
|
61082
62491
|
try {
|
|
@@ -61217,7 +62626,7 @@ var init_state_machine_execution_engine = __esm({
|
|
|
61217
62626
|
* Does not include secrets. Intended for debugging and future resume support.
|
|
61218
62627
|
*/
|
|
61219
62628
|
async saveSnapshotToFile(filePath) {
|
|
61220
|
-
const
|
|
62629
|
+
const fs29 = await import("fs/promises");
|
|
61221
62630
|
const ctx = this._lastContext;
|
|
61222
62631
|
const runner = this._lastRunner;
|
|
61223
62632
|
if (!ctx || !runner) {
|
|
@@ -61237,14 +62646,14 @@ var init_state_machine_execution_engine = __esm({
|
|
|
61237
62646
|
journal: entries,
|
|
61238
62647
|
requestedChecks: ctx.requestedChecks || []
|
|
61239
62648
|
};
|
|
61240
|
-
await
|
|
62649
|
+
await fs29.writeFile(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
61241
62650
|
}
|
|
61242
62651
|
/**
|
|
61243
62652
|
* Load a snapshot JSON from file and return it. Resume support can build on this.
|
|
61244
62653
|
*/
|
|
61245
62654
|
async loadSnapshotFromFile(filePath) {
|
|
61246
|
-
const
|
|
61247
|
-
const raw = await
|
|
62655
|
+
const fs29 = await import("fs/promises");
|
|
62656
|
+
const raw = await fs29.readFile(filePath, "utf8");
|
|
61248
62657
|
return JSON.parse(raw);
|
|
61249
62658
|
}
|
|
61250
62659
|
/**
|