@probelabs/visor 0.1.173 → 0.1.174-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/docs/dashboards/README.md +73 -26
- package/dist/docs/dashboards/grafana-visor-overview.json +435 -15
- package/dist/docs/telemetry-reference.md +387 -0
- package/dist/docs/telemetry-setup.md +2 -0
- package/dist/generated/config-schema.d.ts +277 -7
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/generated/config-schema.json +3803 -0
- package/dist/index.js +2202 -51
- package/dist/sdk/{a2a-frontend-VHOQ45CR.mjs → a2a-frontend-FUJRKHJB.mjs} +3 -3
- package/dist/sdk/{check-provider-registry-65GO3SCO.mjs → check-provider-registry-53C2ZIXJ.mjs} +7 -7
- package/dist/sdk/{check-provider-registry-75O5XJMA.mjs → check-provider-registry-UPQNHHFF.mjs} +7 -7
- package/dist/sdk/{chunk-Y5MEQW2W.mjs → chunk-2PL2YH3B.mjs} +19 -19
- package/dist/sdk/{chunk-4TV2CVVI.mjs → chunk-34QX63WK.mjs} +16 -14
- package/dist/sdk/chunk-34QX63WK.mjs.map +1 -0
- package/dist/sdk/{chunk-2HXOGRAS.mjs → chunk-65SHRIQF.mjs} +3 -3
- package/dist/sdk/{chunk-2HXOGRAS.mjs.map → chunk-65SHRIQF.mjs.map} +1 -1
- package/dist/sdk/{chunk-VVHALCWV.mjs → chunk-EFNNJIMY.mjs} +3 -3
- package/dist/sdk/{chunk-7CWJNSL2.mjs → chunk-GKSSG5IM.mjs} +20 -20
- package/dist/sdk/{chunk-7CWJNSL2.mjs.map → chunk-GKSSG5IM.mjs.map} +1 -1
- package/dist/sdk/{chunk-HZEXCJGA.mjs → chunk-W4KCJM6J.mjs} +282 -8
- package/dist/sdk/chunk-W4KCJM6J.mjs.map +1 -0
- package/dist/sdk/{chunk-GVPMO6QD.mjs → chunk-WJIV7MKY.mjs} +3 -3
- package/dist/sdk/{config-UXRHADSE.mjs → config-BVL3KFMB.mjs} +2 -2
- package/dist/sdk/{failure-condition-evaluator-Q4KNMX6F.mjs → failure-condition-evaluator-DL6H57NX.mjs} +4 -4
- package/dist/sdk/{github-frontend-56UQTA47.mjs → github-frontend-F2YCPK6H.mjs} +4 -4
- package/dist/sdk/{host-QRGXXRDA.mjs → host-6TBS44ER.mjs} +3 -3
- package/dist/sdk/{host-VYPJ2UGQ.mjs → host-LRWIKURZ.mjs} +3 -3
- package/dist/sdk/knex-store-QCEW4I4R.mjs +527 -0
- package/dist/sdk/knex-store-QCEW4I4R.mjs.map +1 -0
- package/dist/sdk/loader-Q7K76ZIY.mjs +89 -0
- package/dist/sdk/loader-Q7K76ZIY.mjs.map +1 -0
- package/dist/sdk/{metrics-FU2G5SZ2.mjs → metrics-JTOG2HNO.mjs} +2 -2
- package/dist/sdk/opa-policy-engine-QCSSIMUF.mjs +655 -0
- package/dist/sdk/opa-policy-engine-QCSSIMUF.mjs.map +1 -0
- package/dist/sdk/{routing-DBQHPP2O.mjs → routing-GF2CF3JT.mjs} +5 -5
- package/dist/sdk/{schedule-tool-MHICRNCI.mjs → schedule-tool-5KDBDCFO.mjs} +7 -7
- package/dist/sdk/{schedule-tool-VRLX54J5.mjs → schedule-tool-UMDRCNO5.mjs} +7 -7
- package/dist/sdk/{schedule-tool-handler-3ES4WON7.mjs → schedule-tool-handler-5EPTHBLS.mjs} +7 -7
- package/dist/sdk/{schedule-tool-handler-FQGAWC5N.mjs → schedule-tool-handler-MUF5V36L.mjs} +7 -7
- package/dist/sdk/sdk.d.mts +137 -133
- package/dist/sdk/sdk.d.ts +137 -133
- package/dist/sdk/sdk.js +1952 -302
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +6 -6
- package/dist/sdk/{trace-helpers-UKMYHQIK.mjs → trace-helpers-FKM2MEDW.mjs} +3 -3
- package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
- package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-F5DTEX6E.mjs → workflow-check-provider-EWMZEEES.mjs} +7 -7
- package/dist/sdk/{workflow-check-provider-VEOVTCVU.mjs → workflow-check-provider-RQUCBAYY.mjs} +7 -7
- package/dist/telemetry/metrics.d.ts.map +1 -1
- package/dist/types/config.d.ts +5 -4
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/output/traces/run-2026-03-09T15-21-25-122Z.ndjson +0 -138
- package/dist/output/traces/run-2026-03-09T15-22-05-255Z.ndjson +0 -2280
- package/dist/sdk/a2a-frontend-7CYN3X7M.mjs +0 -1658
- package/dist/sdk/a2a-frontend-VHOQ45CR.mjs.map +0 -1
- package/dist/sdk/check-provider-registry-DBTS7OXY.mjs +0 -30
- package/dist/sdk/chunk-4TV2CVVI.mjs.map +0 -1
- package/dist/sdk/chunk-AV6KML52.mjs +0 -45016
- package/dist/sdk/chunk-AV6KML52.mjs.map +0 -1
- package/dist/sdk/chunk-HZEXCJGA.mjs.map +0 -1
- package/dist/sdk/chunk-LTHHE6Z5.mjs +0 -516
- package/dist/sdk/chunk-LTHHE6Z5.mjs.map +0 -1
- package/dist/sdk/chunk-VK7FUBBU.mjs +0 -739
- package/dist/sdk/chunk-VVHALCWV.mjs.map +0 -1
- package/dist/sdk/chunk-WYFQQ445.mjs +0 -1502
- package/dist/sdk/chunk-WYFQQ445.mjs.map +0 -1
- package/dist/sdk/failure-condition-evaluator-SNR5XLGN.mjs +0 -18
- package/dist/sdk/github-frontend-OOP26667.mjs +0 -1386
- package/dist/sdk/github-frontend-OOP26667.mjs.map +0 -1
- package/dist/sdk/routing-ZAUCS3HJ.mjs +0 -26
- package/dist/sdk/schedule-tool-2FIVKPVJ.mjs +0 -36
- package/dist/sdk/schedule-tool-handler-FQGAWC5N.mjs.map +0 -1
- package/dist/sdk/schedule-tool-handler-KYUHU4JR.mjs +0 -40
- package/dist/sdk/schedule-tool-handler-KYUHU4JR.mjs.map +0 -1
- package/dist/sdk/trace-helpers-UKMYHQIK.mjs.map +0 -1
- package/dist/sdk/trace-helpers-ZFDJ55SH.mjs +0 -29
- package/dist/sdk/trace-helpers-ZFDJ55SH.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-5KQTXKWS.mjs +0 -30
- package/dist/sdk/workflow-check-provider-5KQTXKWS.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-F5DTEX6E.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-VEOVTCVU.mjs.map +0 -1
- package/dist/traces/run-2026-03-09T15-21-25-122Z.ndjson +0 -138
- package/dist/traces/run-2026-03-09T15-22-05-255Z.ndjson +0 -2280
- /package/dist/sdk/{a2a-frontend-7CYN3X7M.mjs.map → a2a-frontend-FUJRKHJB.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-65GO3SCO.mjs.map → check-provider-registry-53C2ZIXJ.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-75O5XJMA.mjs.map → check-provider-registry-UPQNHHFF.mjs.map} +0 -0
- /package/dist/sdk/{chunk-Y5MEQW2W.mjs.map → chunk-2PL2YH3B.mjs.map} +0 -0
- /package/dist/sdk/{chunk-VK7FUBBU.mjs.map → chunk-EFNNJIMY.mjs.map} +0 -0
- /package/dist/sdk/{chunk-GVPMO6QD.mjs.map → chunk-WJIV7MKY.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-DBTS7OXY.mjs.map → config-BVL3KFMB.mjs.map} +0 -0
- /package/dist/sdk/{config-UXRHADSE.mjs.map → failure-condition-evaluator-DL6H57NX.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-56UQTA47.mjs.map → github-frontend-F2YCPK6H.mjs.map} +0 -0
- /package/dist/sdk/{host-QRGXXRDA.mjs.map → host-6TBS44ER.mjs.map} +0 -0
- /package/dist/sdk/{host-VYPJ2UGQ.mjs.map → host-LRWIKURZ.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-Q4KNMX6F.mjs.map → metrics-JTOG2HNO.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-SNR5XLGN.mjs.map → routing-GF2CF3JT.mjs.map} +0 -0
- /package/dist/sdk/{metrics-FU2G5SZ2.mjs.map → schedule-tool-5KDBDCFO.mjs.map} +0 -0
- /package/dist/sdk/{routing-DBQHPP2O.mjs.map → schedule-tool-UMDRCNO5.mjs.map} +0 -0
- /package/dist/sdk/{routing-ZAUCS3HJ.mjs.map → schedule-tool-handler-5EPTHBLS.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-2FIVKPVJ.mjs.map → schedule-tool-handler-MUF5V36L.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-MHICRNCI.mjs.map → trace-helpers-FKM2MEDW.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-VRLX54J5.mjs.map → workflow-check-provider-EWMZEEES.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-3ES4WON7.mjs.map → workflow-check-provider-RQUCBAYY.mjs.map} +0 -0
package/dist/sdk/sdk.js
CHANGED
|
@@ -704,7 +704,7 @@ var require_package = __commonJS({
|
|
|
704
704
|
"package.json"(exports2, module2) {
|
|
705
705
|
module2.exports = {
|
|
706
706
|
name: "@probelabs/visor",
|
|
707
|
-
version: "0.1.
|
|
707
|
+
version: "0.1.42",
|
|
708
708
|
main: "dist/index.js",
|
|
709
709
|
bin: {
|
|
710
710
|
visor: "./dist/index.js"
|
|
@@ -823,7 +823,7 @@ var require_package = __commonJS({
|
|
|
823
823
|
"@opentelemetry/sdk-node": "^0.203.0",
|
|
824
824
|
"@opentelemetry/sdk-trace-base": "^1.30.1",
|
|
825
825
|
"@opentelemetry/semantic-conventions": "^1.30.1",
|
|
826
|
-
"@probelabs/probe": "^0.6.0-
|
|
826
|
+
"@probelabs/probe": "^0.6.0-rc291",
|
|
827
827
|
"@types/commander": "^2.12.0",
|
|
828
828
|
"@types/uuid": "^10.0.0",
|
|
829
829
|
acorn: "^8.16.0",
|
|
@@ -939,50 +939,53 @@ __export(metrics_exports, {
|
|
|
939
939
|
resetRunAiCalls: () => resetRunAiCalls,
|
|
940
940
|
resetTestMetricsSnapshot: () => resetTestMetricsSnapshot
|
|
941
941
|
});
|
|
942
|
+
function getMeter() {
|
|
943
|
+
return metrics.getMeter("visor");
|
|
944
|
+
}
|
|
942
945
|
function ensureInstruments() {
|
|
943
946
|
if (initialized) return;
|
|
944
947
|
try {
|
|
945
|
-
checkDurationHist =
|
|
948
|
+
checkDurationHist = getMeter().createHistogram("visor.check.duration_ms", {
|
|
946
949
|
description: "Duration of a check execution in milliseconds",
|
|
947
950
|
unit: "ms"
|
|
948
951
|
});
|
|
949
|
-
providerDurationHist =
|
|
952
|
+
providerDurationHist = getMeter().createHistogram("visor.provider.duration_ms", {
|
|
950
953
|
description: "Duration of provider execution in milliseconds",
|
|
951
954
|
unit: "ms"
|
|
952
955
|
});
|
|
953
|
-
foreachDurationHist =
|
|
956
|
+
foreachDurationHist = getMeter().createHistogram("visor.foreach.item.duration_ms", {
|
|
954
957
|
description: "Duration of a forEach item execution in milliseconds",
|
|
955
958
|
unit: "ms"
|
|
956
959
|
});
|
|
957
|
-
issuesCounter =
|
|
960
|
+
issuesCounter = getMeter().createCounter("visor.check.issues", {
|
|
958
961
|
description: "Number of issues produced by checks",
|
|
959
962
|
unit: "1"
|
|
960
963
|
});
|
|
961
|
-
activeChecks =
|
|
964
|
+
activeChecks = getMeter().createUpDownCounter("visor.run.active_checks", {
|
|
962
965
|
description: "Number of checks actively running",
|
|
963
966
|
unit: "1"
|
|
964
967
|
});
|
|
965
|
-
failIfCounter =
|
|
968
|
+
failIfCounter = getMeter().createCounter("visor.fail_if.triggered", {
|
|
966
969
|
description: "Number of times fail_if condition triggered",
|
|
967
970
|
unit: "1"
|
|
968
971
|
});
|
|
969
|
-
diagramBlocks =
|
|
972
|
+
diagramBlocks = getMeter().createCounter("visor.diagram.blocks", {
|
|
970
973
|
description: "Number of Mermaid diagram blocks emitted",
|
|
971
974
|
unit: "1"
|
|
972
975
|
});
|
|
973
|
-
runCounter =
|
|
976
|
+
runCounter = getMeter().createCounter("visor.run.total", {
|
|
974
977
|
description: "Total number of visor runs (workflow executions)",
|
|
975
978
|
unit: "1"
|
|
976
979
|
});
|
|
977
|
-
runDurationHist =
|
|
980
|
+
runDurationHist = getMeter().createHistogram("visor.run.duration_ms", {
|
|
978
981
|
description: "Duration of a complete visor run in milliseconds",
|
|
979
982
|
unit: "ms"
|
|
980
983
|
});
|
|
981
|
-
aiCallCounter =
|
|
984
|
+
aiCallCounter = getMeter().createCounter("visor.ai_call.total", {
|
|
982
985
|
description: "Total number of AI provider calls",
|
|
983
986
|
unit: "1"
|
|
984
987
|
});
|
|
985
|
-
runAiCallsHist =
|
|
988
|
+
runAiCallsHist = getMeter().createHistogram("visor.run.ai_calls", {
|
|
986
989
|
description: "Number of AI calls per visor run",
|
|
987
990
|
unit: "1"
|
|
988
991
|
});
|
|
@@ -1119,13 +1122,12 @@ function getTestMetricsSnapshot() {
|
|
|
1119
1122
|
function resetTestMetricsSnapshot() {
|
|
1120
1123
|
Object.keys(TEST_SNAPSHOT).forEach((k) => TEST_SNAPSHOT[k] = 0);
|
|
1121
1124
|
}
|
|
1122
|
-
var initialized,
|
|
1125
|
+
var initialized, TEST_ENABLED, TEST_SNAPSHOT, checkDurationHist, providerDurationHist, foreachDurationHist, issuesCounter, activeChecks, failIfCounter, diagramBlocks, runCounter, runDurationHist, aiCallCounter, runAiCallsHist, _currentRunAiCalls;
|
|
1123
1126
|
var init_metrics = __esm({
|
|
1124
1127
|
"src/telemetry/metrics.ts"() {
|
|
1125
1128
|
"use strict";
|
|
1126
1129
|
init_lazy_otel();
|
|
1127
1130
|
initialized = false;
|
|
1128
|
-
meter = metrics.getMeter("visor");
|
|
1129
1131
|
TEST_ENABLED = process.env.VISOR_TEST_METRICS === "true";
|
|
1130
1132
|
TEST_SNAPSHOT = { fail_if_triggered: 0 };
|
|
1131
1133
|
_currentRunAiCalls = 0;
|
|
@@ -1150,11 +1152,11 @@ function getTracer() {
|
|
|
1150
1152
|
}
|
|
1151
1153
|
async function withActiveSpan(name, attrs, fn) {
|
|
1152
1154
|
const tracer = getTracer();
|
|
1153
|
-
return await new Promise((
|
|
1155
|
+
return await new Promise((resolve19, reject) => {
|
|
1154
1156
|
const callback = async (span) => {
|
|
1155
1157
|
try {
|
|
1156
1158
|
const res = await fn(span);
|
|
1157
|
-
|
|
1159
|
+
resolve19(res);
|
|
1158
1160
|
} catch (err) {
|
|
1159
1161
|
try {
|
|
1160
1162
|
if (err instanceof Error) span.recordException(err);
|
|
@@ -1279,19 +1281,19 @@ function __getOrCreateNdjsonPath() {
|
|
|
1279
1281
|
try {
|
|
1280
1282
|
if (process.env.VISOR_TELEMETRY_SINK && process.env.VISOR_TELEMETRY_SINK !== "file")
|
|
1281
1283
|
return null;
|
|
1282
|
-
const
|
|
1283
|
-
const
|
|
1284
|
+
const path33 = require("path");
|
|
1285
|
+
const fs29 = require("fs");
|
|
1284
1286
|
if (process.env.VISOR_FALLBACK_TRACE_FILE) {
|
|
1285
1287
|
__ndjsonPath = process.env.VISOR_FALLBACK_TRACE_FILE;
|
|
1286
|
-
const dir =
|
|
1287
|
-
if (!
|
|
1288
|
+
const dir = path33.dirname(__ndjsonPath);
|
|
1289
|
+
if (!fs29.existsSync(dir)) fs29.mkdirSync(dir, { recursive: true });
|
|
1288
1290
|
return __ndjsonPath;
|
|
1289
1291
|
}
|
|
1290
|
-
const outDir = process.env.VISOR_TRACE_DIR ||
|
|
1291
|
-
if (!
|
|
1292
|
+
const outDir = process.env.VISOR_TRACE_DIR || path33.join(process.cwd(), "output", "traces");
|
|
1293
|
+
if (!fs29.existsSync(outDir)) fs29.mkdirSync(outDir, { recursive: true });
|
|
1292
1294
|
if (!__ndjsonPath) {
|
|
1293
1295
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1294
|
-
__ndjsonPath =
|
|
1296
|
+
__ndjsonPath = path33.join(outDir, `${ts}.ndjson`);
|
|
1295
1297
|
}
|
|
1296
1298
|
return __ndjsonPath;
|
|
1297
1299
|
} catch {
|
|
@@ -1300,11 +1302,11 @@ function __getOrCreateNdjsonPath() {
|
|
|
1300
1302
|
}
|
|
1301
1303
|
function _appendRunMarker() {
|
|
1302
1304
|
try {
|
|
1303
|
-
const
|
|
1305
|
+
const fs29 = require("fs");
|
|
1304
1306
|
const p = __getOrCreateNdjsonPath();
|
|
1305
1307
|
if (!p) return;
|
|
1306
1308
|
const line = { name: "visor.run", attributes: { started: true } };
|
|
1307
|
-
|
|
1309
|
+
fs29.appendFileSync(p, JSON.stringify(line) + "\n", "utf8");
|
|
1308
1310
|
} catch {
|
|
1309
1311
|
}
|
|
1310
1312
|
}
|
|
@@ -3391,7 +3393,7 @@ var init_failure_condition_evaluator = __esm({
|
|
|
3391
3393
|
*/
|
|
3392
3394
|
evaluateExpression(condition, context2) {
|
|
3393
3395
|
try {
|
|
3394
|
-
const
|
|
3396
|
+
const normalize8 = (expr) => {
|
|
3395
3397
|
const trimmed = expr.trim();
|
|
3396
3398
|
if (!/[\n;]/.test(trimmed)) return trimmed;
|
|
3397
3399
|
const parts = trimmed.split(/[\n;]+/).map((s) => s.trim()).filter((s) => s.length > 0 && !s.startsWith("//"));
|
|
@@ -3549,7 +3551,7 @@ var init_failure_condition_evaluator = __esm({
|
|
|
3549
3551
|
try {
|
|
3550
3552
|
exec2 = this.sandbox.compile(`return (${raw});`);
|
|
3551
3553
|
} catch {
|
|
3552
|
-
const normalizedExpr =
|
|
3554
|
+
const normalizedExpr = normalize8(condition);
|
|
3553
3555
|
exec2 = this.sandbox.compile(`return (${normalizedExpr});`);
|
|
3554
3556
|
}
|
|
3555
3557
|
const result = exec2(scope).run();
|
|
@@ -3932,9 +3934,9 @@ function configureLiquidWithExtensions(liquid) {
|
|
|
3932
3934
|
});
|
|
3933
3935
|
liquid.registerFilter("get", (obj, pathExpr) => {
|
|
3934
3936
|
if (obj == null) return void 0;
|
|
3935
|
-
const
|
|
3936
|
-
if (!
|
|
3937
|
-
const parts =
|
|
3937
|
+
const path33 = typeof pathExpr === "string" ? pathExpr : String(pathExpr || "");
|
|
3938
|
+
if (!path33) return obj;
|
|
3939
|
+
const parts = path33.split(".");
|
|
3938
3940
|
let cur = obj;
|
|
3939
3941
|
for (const p of parts) {
|
|
3940
3942
|
if (cur == null) return void 0;
|
|
@@ -4053,9 +4055,9 @@ function configureLiquidWithExtensions(liquid) {
|
|
|
4053
4055
|
}
|
|
4054
4056
|
}
|
|
4055
4057
|
const defaultRole = typeof rolesCfg.default === "string" && rolesCfg.default.trim() ? rolesCfg.default.trim() : void 0;
|
|
4056
|
-
const getNested = (obj,
|
|
4057
|
-
if (!obj || !
|
|
4058
|
-
const parts =
|
|
4058
|
+
const getNested = (obj, path33) => {
|
|
4059
|
+
if (!obj || !path33) return void 0;
|
|
4060
|
+
const parts = path33.split(".");
|
|
4059
4061
|
let cur = obj;
|
|
4060
4062
|
for (const p of parts) {
|
|
4061
4063
|
if (cur == null) return void 0;
|
|
@@ -6607,8 +6609,8 @@ var init_dependency_gating = __esm({
|
|
|
6607
6609
|
async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
|
|
6608
6610
|
try {
|
|
6609
6611
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
6610
|
-
const
|
|
6611
|
-
const
|
|
6612
|
+
const fs29 = await import("fs/promises");
|
|
6613
|
+
const path33 = await import("path");
|
|
6612
6614
|
const schemaRaw = checkConfig.schema || "plain";
|
|
6613
6615
|
const schema = typeof schemaRaw === "string" ? schemaRaw : "code-review";
|
|
6614
6616
|
let templateContent;
|
|
@@ -6616,24 +6618,24 @@ async function renderTemplateContent(checkId, checkConfig, reviewSummary) {
|
|
|
6616
6618
|
templateContent = String(checkConfig.template.content);
|
|
6617
6619
|
} else if (checkConfig.template && checkConfig.template.file) {
|
|
6618
6620
|
const file = String(checkConfig.template.file);
|
|
6619
|
-
const resolved =
|
|
6620
|
-
templateContent = await
|
|
6621
|
+
const resolved = path33.resolve(process.cwd(), file);
|
|
6622
|
+
templateContent = await fs29.readFile(resolved, "utf-8");
|
|
6621
6623
|
} else if (schema && schema !== "plain") {
|
|
6622
6624
|
const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
|
|
6623
6625
|
if (sanitized) {
|
|
6624
6626
|
const candidatePaths = [
|
|
6625
|
-
|
|
6627
|
+
path33.join(__dirname, "output", sanitized, "template.liquid"),
|
|
6626
6628
|
// bundled: dist/output/
|
|
6627
|
-
|
|
6629
|
+
path33.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
6628
6630
|
// source: output/
|
|
6629
|
-
|
|
6631
|
+
path33.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
6630
6632
|
// fallback: cwd/output/
|
|
6631
|
-
|
|
6633
|
+
path33.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
|
|
6632
6634
|
// fallback: cwd/dist/output/
|
|
6633
6635
|
];
|
|
6634
6636
|
for (const p of candidatePaths) {
|
|
6635
6637
|
try {
|
|
6636
|
-
templateContent = await
|
|
6638
|
+
templateContent = await fs29.readFile(p, "utf-8");
|
|
6637
6639
|
if (templateContent) break;
|
|
6638
6640
|
} catch {
|
|
6639
6641
|
}
|
|
@@ -7038,7 +7040,7 @@ async function processDiffWithOutline(diffContent) {
|
|
|
7038
7040
|
}
|
|
7039
7041
|
try {
|
|
7040
7042
|
const originalProbePath = process.env.PROBE_PATH;
|
|
7041
|
-
const
|
|
7043
|
+
const fs29 = require("fs");
|
|
7042
7044
|
const possiblePaths = [
|
|
7043
7045
|
// Relative to current working directory (most common in production)
|
|
7044
7046
|
path6.join(process.cwd(), "node_modules/@probelabs/probe/bin/probe-binary"),
|
|
@@ -7049,7 +7051,7 @@ async function processDiffWithOutline(diffContent) {
|
|
|
7049
7051
|
];
|
|
7050
7052
|
let probeBinaryPath;
|
|
7051
7053
|
for (const candidatePath of possiblePaths) {
|
|
7052
|
-
if (
|
|
7054
|
+
if (fs29.existsSync(candidatePath)) {
|
|
7053
7055
|
probeBinaryPath = candidatePath;
|
|
7054
7056
|
break;
|
|
7055
7057
|
}
|
|
@@ -7156,7 +7158,7 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
7156
7158
|
if (chromiumPath) {
|
|
7157
7159
|
env.PUPPETEER_EXECUTABLE_PATH = chromiumPath;
|
|
7158
7160
|
}
|
|
7159
|
-
const result = await new Promise((
|
|
7161
|
+
const result = await new Promise((resolve19) => {
|
|
7160
7162
|
const proc = (0, import_child_process.spawn)(
|
|
7161
7163
|
"npx",
|
|
7162
7164
|
[
|
|
@@ -7186,13 +7188,13 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
7186
7188
|
});
|
|
7187
7189
|
proc.on("close", (code) => {
|
|
7188
7190
|
if (code === 0) {
|
|
7189
|
-
|
|
7191
|
+
resolve19({ success: true });
|
|
7190
7192
|
} else {
|
|
7191
|
-
|
|
7193
|
+
resolve19({ success: false, error: stderr || `Exit code ${code}` });
|
|
7192
7194
|
}
|
|
7193
7195
|
});
|
|
7194
7196
|
proc.on("error", (err) => {
|
|
7195
|
-
|
|
7197
|
+
resolve19({ success: false, error: err.message });
|
|
7196
7198
|
});
|
|
7197
7199
|
});
|
|
7198
7200
|
if (!result.success) {
|
|
@@ -8354,8 +8356,8 @@ ${schemaString}`);
|
|
|
8354
8356
|
}
|
|
8355
8357
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8356
8358
|
try {
|
|
8357
|
-
const
|
|
8358
|
-
const
|
|
8359
|
+
const fs29 = require("fs");
|
|
8360
|
+
const path33 = require("path");
|
|
8359
8361
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8360
8362
|
const provider = this.config.provider || "auto";
|
|
8361
8363
|
const model = this.config.model || "default";
|
|
@@ -8469,20 +8471,20 @@ ${"=".repeat(60)}
|
|
|
8469
8471
|
`;
|
|
8470
8472
|
readableVersion += `${"=".repeat(60)}
|
|
8471
8473
|
`;
|
|
8472
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8473
|
-
if (!
|
|
8474
|
-
|
|
8474
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
8475
|
+
if (!fs29.existsSync(debugArtifactsDir)) {
|
|
8476
|
+
fs29.mkdirSync(debugArtifactsDir, { recursive: true });
|
|
8475
8477
|
}
|
|
8476
|
-
const debugFile =
|
|
8478
|
+
const debugFile = path33.join(
|
|
8477
8479
|
debugArtifactsDir,
|
|
8478
8480
|
`prompt-${_checkName || "unknown"}-${timestamp}.json`
|
|
8479
8481
|
);
|
|
8480
|
-
|
|
8481
|
-
const readableFile =
|
|
8482
|
+
fs29.writeFileSync(debugFile, debugJson, "utf-8");
|
|
8483
|
+
const readableFile = path33.join(
|
|
8482
8484
|
debugArtifactsDir,
|
|
8483
8485
|
`prompt-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8484
8486
|
);
|
|
8485
|
-
|
|
8487
|
+
fs29.writeFileSync(readableFile, readableVersion, "utf-8");
|
|
8486
8488
|
log(`
|
|
8487
8489
|
\u{1F4BE} Full debug info saved to:`);
|
|
8488
8490
|
log(` JSON: ${debugFile}`);
|
|
@@ -8520,8 +8522,8 @@ ${"=".repeat(60)}
|
|
|
8520
8522
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8521
8523
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8522
8524
|
try {
|
|
8523
|
-
const
|
|
8524
|
-
const
|
|
8525
|
+
const fs29 = require("fs");
|
|
8526
|
+
const path33 = require("path");
|
|
8525
8527
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8526
8528
|
const agentAny2 = agent;
|
|
8527
8529
|
let fullHistory = [];
|
|
@@ -8532,8 +8534,8 @@ ${"=".repeat(60)}
|
|
|
8532
8534
|
} else if (agentAny2._messages) {
|
|
8533
8535
|
fullHistory = agentAny2._messages;
|
|
8534
8536
|
}
|
|
8535
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8536
|
-
const sessionBase =
|
|
8537
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
8538
|
+
const sessionBase = path33.join(
|
|
8537
8539
|
debugArtifactsDir,
|
|
8538
8540
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
8539
8541
|
);
|
|
@@ -8545,7 +8547,7 @@ ${"=".repeat(60)}
|
|
|
8545
8547
|
schema: effectiveSchema,
|
|
8546
8548
|
totalMessages: fullHistory.length
|
|
8547
8549
|
};
|
|
8548
|
-
|
|
8550
|
+
fs29.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
8549
8551
|
let readable = `=============================================================
|
|
8550
8552
|
`;
|
|
8551
8553
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -8572,7 +8574,7 @@ ${"=".repeat(60)}
|
|
|
8572
8574
|
`;
|
|
8573
8575
|
readable += content + "\n";
|
|
8574
8576
|
});
|
|
8575
|
-
|
|
8577
|
+
fs29.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
8576
8578
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
8577
8579
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
8578
8580
|
} catch (error) {
|
|
@@ -8581,11 +8583,11 @@ ${"=".repeat(60)}
|
|
|
8581
8583
|
}
|
|
8582
8584
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8583
8585
|
try {
|
|
8584
|
-
const
|
|
8585
|
-
const
|
|
8586
|
+
const fs29 = require("fs");
|
|
8587
|
+
const path33 = require("path");
|
|
8586
8588
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8587
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8588
|
-
const responseFile =
|
|
8589
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
8590
|
+
const responseFile = path33.join(
|
|
8589
8591
|
debugArtifactsDir,
|
|
8590
8592
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
8591
8593
|
);
|
|
@@ -8618,7 +8620,7 @@ ${"=".repeat(60)}
|
|
|
8618
8620
|
`;
|
|
8619
8621
|
responseContent += `${"=".repeat(60)}
|
|
8620
8622
|
`;
|
|
8621
|
-
|
|
8623
|
+
fs29.writeFileSync(responseFile, responseContent, "utf-8");
|
|
8622
8624
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
8623
8625
|
} catch (error) {
|
|
8624
8626
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -8634,9 +8636,9 @@ ${"=".repeat(60)}
|
|
|
8634
8636
|
await agentAny._telemetryConfig.shutdown();
|
|
8635
8637
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${agentAny._traceFilePath}`);
|
|
8636
8638
|
if (process.env.GITHUB_ACTIONS) {
|
|
8637
|
-
const
|
|
8638
|
-
if (
|
|
8639
|
-
const stats =
|
|
8639
|
+
const fs29 = require("fs");
|
|
8640
|
+
if (fs29.existsSync(agentAny._traceFilePath)) {
|
|
8641
|
+
const stats = fs29.statSync(agentAny._traceFilePath);
|
|
8640
8642
|
console.log(
|
|
8641
8643
|
`::notice title=AI Trace Saved::${agentAny._traceFilePath} (${stats.size} bytes)`
|
|
8642
8644
|
);
|
|
@@ -8849,9 +8851,9 @@ ${schemaString}`);
|
|
|
8849
8851
|
const model = this.config.model || "default";
|
|
8850
8852
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8851
8853
|
try {
|
|
8852
|
-
const
|
|
8853
|
-
const
|
|
8854
|
-
const
|
|
8854
|
+
const fs29 = require("fs");
|
|
8855
|
+
const path33 = require("path");
|
|
8856
|
+
const os3 = require("os");
|
|
8855
8857
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8856
8858
|
const debugData = {
|
|
8857
8859
|
timestamp,
|
|
@@ -8923,19 +8925,19 @@ ${"=".repeat(60)}
|
|
|
8923
8925
|
`;
|
|
8924
8926
|
readableVersion += `${"=".repeat(60)}
|
|
8925
8927
|
`;
|
|
8926
|
-
const tempDir =
|
|
8927
|
-
const promptFile =
|
|
8928
|
-
|
|
8928
|
+
const tempDir = os3.tmpdir();
|
|
8929
|
+
const promptFile = path33.join(tempDir, `visor-prompt-${timestamp}.txt`);
|
|
8930
|
+
fs29.writeFileSync(promptFile, prompt, "utf-8");
|
|
8929
8931
|
log(`
|
|
8930
8932
|
\u{1F4BE} Prompt saved to: ${promptFile}`);
|
|
8931
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
8933
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
8932
8934
|
try {
|
|
8933
|
-
const base =
|
|
8935
|
+
const base = path33.join(
|
|
8934
8936
|
debugArtifactsDir,
|
|
8935
8937
|
`prompt-${_checkName || "unknown"}-${timestamp}`
|
|
8936
8938
|
);
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
+
fs29.writeFileSync(base + ".json", debugJson, "utf-8");
|
|
8940
|
+
fs29.writeFileSync(base + ".summary.txt", readableVersion, "utf-8");
|
|
8939
8941
|
log(`
|
|
8940
8942
|
\u{1F4BE} Full debug info saved to directory: ${debugArtifactsDir}`);
|
|
8941
8943
|
} catch {
|
|
@@ -8985,8 +8987,8 @@ $ ${cliCommand}
|
|
|
8985
8987
|
log(`\u{1F4E4} Response length: ${response.length} characters`);
|
|
8986
8988
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
8987
8989
|
try {
|
|
8988
|
-
const
|
|
8989
|
-
const
|
|
8990
|
+
const fs29 = require("fs");
|
|
8991
|
+
const path33 = require("path");
|
|
8990
8992
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8991
8993
|
const agentAny = agent;
|
|
8992
8994
|
let fullHistory = [];
|
|
@@ -8997,8 +8999,8 @@ $ ${cliCommand}
|
|
|
8997
8999
|
} else if (agentAny._messages) {
|
|
8998
9000
|
fullHistory = agentAny._messages;
|
|
8999
9001
|
}
|
|
9000
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
9001
|
-
const sessionBase =
|
|
9002
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
9003
|
+
const sessionBase = path33.join(
|
|
9002
9004
|
debugArtifactsDir,
|
|
9003
9005
|
`session-${_checkName || "unknown"}-${timestamp}`
|
|
9004
9006
|
);
|
|
@@ -9010,7 +9012,7 @@ $ ${cliCommand}
|
|
|
9010
9012
|
schema: effectiveSchema,
|
|
9011
9013
|
totalMessages: fullHistory.length
|
|
9012
9014
|
};
|
|
9013
|
-
|
|
9015
|
+
fs29.writeFileSync(sessionBase + ".json", JSON.stringify(sessionData, null, 2), "utf-8");
|
|
9014
9016
|
let readable = `=============================================================
|
|
9015
9017
|
`;
|
|
9016
9018
|
readable += `COMPLETE AI SESSION HISTORY (AFTER RESPONSE)
|
|
@@ -9037,7 +9039,7 @@ ${"=".repeat(60)}
|
|
|
9037
9039
|
`;
|
|
9038
9040
|
readable += content + "\n";
|
|
9039
9041
|
});
|
|
9040
|
-
|
|
9042
|
+
fs29.writeFileSync(sessionBase + ".summary.txt", readable, "utf-8");
|
|
9041
9043
|
log(`\u{1F4BE} Complete session history saved:`);
|
|
9042
9044
|
log(` - Contains ALL ${fullHistory.length} messages (prompts + responses)`);
|
|
9043
9045
|
} catch (error) {
|
|
@@ -9046,11 +9048,11 @@ ${"=".repeat(60)}
|
|
|
9046
9048
|
}
|
|
9047
9049
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
9048
9050
|
try {
|
|
9049
|
-
const
|
|
9050
|
-
const
|
|
9051
|
+
const fs29 = require("fs");
|
|
9052
|
+
const path33 = require("path");
|
|
9051
9053
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
9052
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
9053
|
-
const responseFile =
|
|
9054
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path33.join(process.cwd(), "debug-artifacts");
|
|
9055
|
+
const responseFile = path33.join(
|
|
9054
9056
|
debugArtifactsDir,
|
|
9055
9057
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
9056
9058
|
);
|
|
@@ -9083,7 +9085,7 @@ ${"=".repeat(60)}
|
|
|
9083
9085
|
`;
|
|
9084
9086
|
responseContent += `${"=".repeat(60)}
|
|
9085
9087
|
`;
|
|
9086
|
-
|
|
9088
|
+
fs29.writeFileSync(responseFile, responseContent, "utf-8");
|
|
9087
9089
|
log(`\u{1F4BE} Response saved to: ${responseFile}`);
|
|
9088
9090
|
} catch (error) {
|
|
9089
9091
|
log(`\u26A0\uFE0F Could not save response file: ${error}`);
|
|
@@ -9101,9 +9103,9 @@ ${"=".repeat(60)}
|
|
|
9101
9103
|
await telemetry.shutdown();
|
|
9102
9104
|
log(`\u{1F4CA} OpenTelemetry trace saved to: ${traceFilePath}`);
|
|
9103
9105
|
if (process.env.GITHUB_ACTIONS) {
|
|
9104
|
-
const
|
|
9105
|
-
if (
|
|
9106
|
-
const stats =
|
|
9106
|
+
const fs29 = require("fs");
|
|
9107
|
+
if (fs29.existsSync(traceFilePath)) {
|
|
9108
|
+
const stats = fs29.statSync(traceFilePath);
|
|
9107
9109
|
console.log(
|
|
9108
9110
|
`::notice title=AI Trace Saved::OpenTelemetry trace file size: ${stats.size} bytes`
|
|
9109
9111
|
);
|
|
@@ -9141,8 +9143,8 @@ ${"=".repeat(60)}
|
|
|
9141
9143
|
* Load schema content from schema files or inline definitions
|
|
9142
9144
|
*/
|
|
9143
9145
|
async loadSchemaContent(schema) {
|
|
9144
|
-
const
|
|
9145
|
-
const
|
|
9146
|
+
const fs29 = require("fs").promises;
|
|
9147
|
+
const path33 = require("path");
|
|
9146
9148
|
if (typeof schema === "object" && schema !== null) {
|
|
9147
9149
|
log("\u{1F4CB} Using inline schema object from configuration");
|
|
9148
9150
|
return JSON.stringify(schema);
|
|
@@ -9155,14 +9157,14 @@ ${"=".repeat(60)}
|
|
|
9155
9157
|
}
|
|
9156
9158
|
} catch {
|
|
9157
9159
|
}
|
|
9158
|
-
if ((schema.startsWith("./") || schema.includes(".json")) && !
|
|
9160
|
+
if ((schema.startsWith("./") || schema.includes(".json")) && !path33.isAbsolute(schema)) {
|
|
9159
9161
|
if (schema.includes("..") || schema.includes("\0")) {
|
|
9160
9162
|
throw new Error("Invalid schema path: path traversal not allowed");
|
|
9161
9163
|
}
|
|
9162
9164
|
try {
|
|
9163
|
-
const schemaPath =
|
|
9165
|
+
const schemaPath = path33.resolve(process.cwd(), schema);
|
|
9164
9166
|
log(`\u{1F4CB} Loading custom schema from file: ${schemaPath}`);
|
|
9165
|
-
const schemaContent = await
|
|
9167
|
+
const schemaContent = await fs29.readFile(schemaPath, "utf-8");
|
|
9166
9168
|
return schemaContent.trim();
|
|
9167
9169
|
} catch (error) {
|
|
9168
9170
|
throw new Error(
|
|
@@ -9176,22 +9178,22 @@ ${"=".repeat(60)}
|
|
|
9176
9178
|
}
|
|
9177
9179
|
const candidatePaths = [
|
|
9178
9180
|
// GitHub Action bundle location
|
|
9179
|
-
|
|
9181
|
+
path33.join(__dirname, "output", sanitizedSchemaName, "schema.json"),
|
|
9180
9182
|
// Historical fallback when src/output was inadvertently bundled as output1/
|
|
9181
|
-
|
|
9183
|
+
path33.join(__dirname, "output1", sanitizedSchemaName, "schema.json"),
|
|
9182
9184
|
// Local dev (repo root)
|
|
9183
|
-
|
|
9185
|
+
path33.join(process.cwd(), "output", sanitizedSchemaName, "schema.json")
|
|
9184
9186
|
];
|
|
9185
9187
|
for (const schemaPath of candidatePaths) {
|
|
9186
9188
|
try {
|
|
9187
|
-
const schemaContent = await
|
|
9189
|
+
const schemaContent = await fs29.readFile(schemaPath, "utf-8");
|
|
9188
9190
|
return schemaContent.trim();
|
|
9189
9191
|
} catch {
|
|
9190
9192
|
}
|
|
9191
9193
|
}
|
|
9192
|
-
const distPath =
|
|
9193
|
-
const distAltPath =
|
|
9194
|
-
const cwdPath =
|
|
9194
|
+
const distPath = path33.join(__dirname, "output", sanitizedSchemaName, "schema.json");
|
|
9195
|
+
const distAltPath = path33.join(__dirname, "output1", sanitizedSchemaName, "schema.json");
|
|
9196
|
+
const cwdPath = path33.join(process.cwd(), "output", sanitizedSchemaName, "schema.json");
|
|
9195
9197
|
throw new Error(
|
|
9196
9198
|
`Failed to load schema '${sanitizedSchemaName}'. Tried: ${distPath}, ${distAltPath}, and ${cwdPath}. Ensure build copies 'output/' into dist (build:cli), or provide a custom schema file/path.`
|
|
9197
9199
|
);
|
|
@@ -9433,7 +9435,7 @@ ${"=".repeat(60)}
|
|
|
9433
9435
|
* Generate mock response for testing
|
|
9434
9436
|
*/
|
|
9435
9437
|
async generateMockResponse(_prompt, _checkName, _schema) {
|
|
9436
|
-
await new Promise((
|
|
9438
|
+
await new Promise((resolve19) => setTimeout(resolve19, 500));
|
|
9437
9439
|
const name = (_checkName || "").toLowerCase();
|
|
9438
9440
|
if (name.includes("extract-facts")) {
|
|
9439
9441
|
const arr = Array.from({ length: 6 }, (_, i) => ({
|
|
@@ -9794,7 +9796,7 @@ var init_command_executor = __esm({
|
|
|
9794
9796
|
* Execute command with stdin input
|
|
9795
9797
|
*/
|
|
9796
9798
|
executeWithStdin(command, options) {
|
|
9797
|
-
return new Promise((
|
|
9799
|
+
return new Promise((resolve19, reject) => {
|
|
9798
9800
|
const childProcess = (0, import_child_process2.exec)(
|
|
9799
9801
|
command,
|
|
9800
9802
|
{
|
|
@@ -9806,7 +9808,7 @@ var init_command_executor = __esm({
|
|
|
9806
9808
|
if (error && error.killed && (error.code === "ETIMEDOUT" || error.signal === "SIGTERM")) {
|
|
9807
9809
|
reject(new Error(`Command timed out after ${options.timeout || 3e4}ms`));
|
|
9808
9810
|
} else {
|
|
9809
|
-
|
|
9811
|
+
resolve19({
|
|
9810
9812
|
stdout: stdout || "",
|
|
9811
9813
|
stderr: stderr || "",
|
|
9812
9814
|
exitCode: error ? error.code || 1 : 0
|
|
@@ -12669,6 +12671,22 @@ var init_config_schema = __esm({
|
|
|
12669
12671
|
$ref: "#/definitions/SlackConfig",
|
|
12670
12672
|
description: "Slack configuration"
|
|
12671
12673
|
},
|
|
12674
|
+
telegram: {
|
|
12675
|
+
$ref: "#/definitions/TelegramConfig",
|
|
12676
|
+
description: "Telegram bot configuration"
|
|
12677
|
+
},
|
|
12678
|
+
email: {
|
|
12679
|
+
$ref: "#/definitions/EmailConfig",
|
|
12680
|
+
description: "Email integration configuration"
|
|
12681
|
+
},
|
|
12682
|
+
whatsapp: {
|
|
12683
|
+
$ref: "#/definitions/WhatsAppConfig",
|
|
12684
|
+
description: "WhatsApp bot configuration"
|
|
12685
|
+
},
|
|
12686
|
+
teams: {
|
|
12687
|
+
$ref: "#/definitions/TeamsConfig",
|
|
12688
|
+
description: "Microsoft Teams bot configuration"
|
|
12689
|
+
},
|
|
12672
12690
|
scheduler: {
|
|
12673
12691
|
$ref: "#/definitions/SchedulerConfig",
|
|
12674
12692
|
description: "Scheduler configuration for scheduled workflow execution"
|
|
@@ -13442,7 +13460,7 @@ var init_config_schema = __esm({
|
|
|
13442
13460
|
description: "Arguments/inputs for the workflow"
|
|
13443
13461
|
},
|
|
13444
13462
|
overrides: {
|
|
13445
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-
|
|
13463
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833%3E%3E",
|
|
13446
13464
|
description: "Override specific step configurations in the workflow"
|
|
13447
13465
|
},
|
|
13448
13466
|
output_mapping: {
|
|
@@ -13458,7 +13476,7 @@ var init_config_schema = __esm({
|
|
|
13458
13476
|
description: "Config file path - alternative to workflow ID (loads a Visor config file as workflow)"
|
|
13459
13477
|
},
|
|
13460
13478
|
workflow_overrides: {
|
|
13461
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-
|
|
13479
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833%3E%3E",
|
|
13462
13480
|
description: "Alias for overrides - workflow step overrides (backward compatibility)"
|
|
13463
13481
|
},
|
|
13464
13482
|
ref: {
|
|
@@ -13642,7 +13660,11 @@ var init_config_schema = __esm({
|
|
|
13642
13660
|
"manual",
|
|
13643
13661
|
"schedule",
|
|
13644
13662
|
"webhook_received",
|
|
13645
|
-
"slack_message"
|
|
13663
|
+
"slack_message",
|
|
13664
|
+
"telegram_message",
|
|
13665
|
+
"email_message",
|
|
13666
|
+
"whatsapp_message",
|
|
13667
|
+
"teams_message"
|
|
13646
13668
|
],
|
|
13647
13669
|
description: "Valid event triggers for checks"
|
|
13648
13670
|
},
|
|
@@ -14156,7 +14178,7 @@ var init_config_schema = __esm({
|
|
|
14156
14178
|
description: "Custom output name (defaults to workflow name)"
|
|
14157
14179
|
},
|
|
14158
14180
|
overrides: {
|
|
14159
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-
|
|
14181
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833%3E%3E",
|
|
14160
14182
|
description: "Step overrides"
|
|
14161
14183
|
},
|
|
14162
14184
|
output_mapping: {
|
|
@@ -14171,13 +14193,13 @@ var init_config_schema = __esm({
|
|
|
14171
14193
|
"^x-": {}
|
|
14172
14194
|
}
|
|
14173
14195
|
},
|
|
14174
|
-
"Record<string,Partial<interface-src_types_config.ts-
|
|
14196
|
+
"Record<string,Partial<interface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833>>": {
|
|
14175
14197
|
type: "object",
|
|
14176
14198
|
additionalProperties: {
|
|
14177
|
-
$ref: "#/definitions/Partial%3Cinterface-src_types_config.ts-
|
|
14199
|
+
$ref: "#/definitions/Partial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833%3E"
|
|
14178
14200
|
}
|
|
14179
14201
|
},
|
|
14180
|
-
"Partial<interface-src_types_config.ts-
|
|
14202
|
+
"Partial<interface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833>": {
|
|
14181
14203
|
type: "object",
|
|
14182
14204
|
additionalProperties: false
|
|
14183
14205
|
},
|
|
@@ -15036,6 +15058,260 @@ var init_config_schema = __esm({
|
|
|
15036
15058
|
"^x-": {}
|
|
15037
15059
|
}
|
|
15038
15060
|
},
|
|
15061
|
+
TelegramConfig: {
|
|
15062
|
+
type: "object",
|
|
15063
|
+
properties: {
|
|
15064
|
+
bot_token: {
|
|
15065
|
+
type: "string",
|
|
15066
|
+
description: "Bot token from"
|
|
15067
|
+
},
|
|
15068
|
+
polling_timeout: {
|
|
15069
|
+
type: "number",
|
|
15070
|
+
description: "Polling timeout in seconds for getUpdates (default: 30)"
|
|
15071
|
+
},
|
|
15072
|
+
chat_allowlist: {
|
|
15073
|
+
type: "array",
|
|
15074
|
+
items: {
|
|
15075
|
+
type: ["string", "number"]
|
|
15076
|
+
},
|
|
15077
|
+
description: "Chat/group allowlist - numeric chat IDs that the bot responds in"
|
|
15078
|
+
},
|
|
15079
|
+
require_mention: {
|
|
15080
|
+
type: "boolean",
|
|
15081
|
+
description: "In groups, only respond when"
|
|
15082
|
+
},
|
|
15083
|
+
workflow: {
|
|
15084
|
+
type: "string",
|
|
15085
|
+
description: "Workflow to run when a message is received"
|
|
15086
|
+
}
|
|
15087
|
+
},
|
|
15088
|
+
additionalProperties: false,
|
|
15089
|
+
patternProperties: {
|
|
15090
|
+
"^x-": {}
|
|
15091
|
+
}
|
|
15092
|
+
},
|
|
15093
|
+
EmailConfig: {
|
|
15094
|
+
type: "object",
|
|
15095
|
+
properties: {
|
|
15096
|
+
receive: {
|
|
15097
|
+
type: "object",
|
|
15098
|
+
properties: {
|
|
15099
|
+
type: {
|
|
15100
|
+
type: "string",
|
|
15101
|
+
enum: ["imap", "resend"],
|
|
15102
|
+
description: "Backend type: 'imap' (universal) or 'resend' (managed webhook)"
|
|
15103
|
+
},
|
|
15104
|
+
host: {
|
|
15105
|
+
type: "string",
|
|
15106
|
+
description: "IMAP server hostname"
|
|
15107
|
+
},
|
|
15108
|
+
port: {
|
|
15109
|
+
type: "number",
|
|
15110
|
+
description: "IMAP server port (default: 993)"
|
|
15111
|
+
},
|
|
15112
|
+
auth: {
|
|
15113
|
+
type: "object",
|
|
15114
|
+
properties: {
|
|
15115
|
+
user: {
|
|
15116
|
+
type: "string"
|
|
15117
|
+
},
|
|
15118
|
+
pass: {
|
|
15119
|
+
type: "string"
|
|
15120
|
+
}
|
|
15121
|
+
},
|
|
15122
|
+
additionalProperties: false,
|
|
15123
|
+
description: "IMAP auth credentials",
|
|
15124
|
+
patternProperties: {
|
|
15125
|
+
"^x-": {}
|
|
15126
|
+
}
|
|
15127
|
+
},
|
|
15128
|
+
secure: {
|
|
15129
|
+
type: "boolean",
|
|
15130
|
+
description: "Use TLS (default: true)"
|
|
15131
|
+
},
|
|
15132
|
+
poll_interval: {
|
|
15133
|
+
type: "number",
|
|
15134
|
+
description: "Polling interval in seconds when IDLE not available (default: 30)"
|
|
15135
|
+
},
|
|
15136
|
+
folder: {
|
|
15137
|
+
type: "string",
|
|
15138
|
+
description: "IMAP folder to monitor (default: 'INBOX')"
|
|
15139
|
+
},
|
|
15140
|
+
mark_read: {
|
|
15141
|
+
type: "boolean",
|
|
15142
|
+
description: "Mark processed messages as read (default: true)"
|
|
15143
|
+
},
|
|
15144
|
+
api_key: {
|
|
15145
|
+
type: "string",
|
|
15146
|
+
description: "Resend API key (for type: 'resend')"
|
|
15147
|
+
},
|
|
15148
|
+
webhook_secret: {
|
|
15149
|
+
type: "string",
|
|
15150
|
+
description: "Resend webhook secret for signature verification"
|
|
15151
|
+
}
|
|
15152
|
+
},
|
|
15153
|
+
additionalProperties: false,
|
|
15154
|
+
description: "Receive backend configuration",
|
|
15155
|
+
patternProperties: {
|
|
15156
|
+
"^x-": {}
|
|
15157
|
+
}
|
|
15158
|
+
},
|
|
15159
|
+
send: {
|
|
15160
|
+
type: "object",
|
|
15161
|
+
properties: {
|
|
15162
|
+
type: {
|
|
15163
|
+
type: "string",
|
|
15164
|
+
enum: ["smtp", "resend"],
|
|
15165
|
+
description: "Backend type: 'smtp' (universal) or 'resend' (managed API)"
|
|
15166
|
+
},
|
|
15167
|
+
host: {
|
|
15168
|
+
type: "string",
|
|
15169
|
+
description: "SMTP server hostname"
|
|
15170
|
+
},
|
|
15171
|
+
port: {
|
|
15172
|
+
type: "number",
|
|
15173
|
+
description: "SMTP server port (default: 587)"
|
|
15174
|
+
},
|
|
15175
|
+
auth: {
|
|
15176
|
+
type: "object",
|
|
15177
|
+
properties: {
|
|
15178
|
+
user: {
|
|
15179
|
+
type: "string"
|
|
15180
|
+
},
|
|
15181
|
+
pass: {
|
|
15182
|
+
type: "string"
|
|
15183
|
+
}
|
|
15184
|
+
},
|
|
15185
|
+
additionalProperties: false,
|
|
15186
|
+
description: "SMTP auth credentials",
|
|
15187
|
+
patternProperties: {
|
|
15188
|
+
"^x-": {}
|
|
15189
|
+
}
|
|
15190
|
+
},
|
|
15191
|
+
secure: {
|
|
15192
|
+
type: "boolean",
|
|
15193
|
+
description: "Use TLS (default: true)"
|
|
15194
|
+
},
|
|
15195
|
+
from: {
|
|
15196
|
+
type: "string",
|
|
15197
|
+
description: 'Default sender address (e.g., "Bot <bot@example.com>")'
|
|
15198
|
+
},
|
|
15199
|
+
api_key: {
|
|
15200
|
+
type: "string",
|
|
15201
|
+
description: "Resend API key (for type: 'resend')"
|
|
15202
|
+
}
|
|
15203
|
+
},
|
|
15204
|
+
additionalProperties: false,
|
|
15205
|
+
description: "Send backend configuration",
|
|
15206
|
+
patternProperties: {
|
|
15207
|
+
"^x-": {}
|
|
15208
|
+
}
|
|
15209
|
+
},
|
|
15210
|
+
allowlist: {
|
|
15211
|
+
type: "array",
|
|
15212
|
+
items: {
|
|
15213
|
+
type: "string"
|
|
15214
|
+
},
|
|
15215
|
+
description: "Only process emails from these senders"
|
|
15216
|
+
},
|
|
15217
|
+
workflow: {
|
|
15218
|
+
type: "string",
|
|
15219
|
+
description: "Workflow to run when an email is received"
|
|
15220
|
+
}
|
|
15221
|
+
},
|
|
15222
|
+
additionalProperties: false,
|
|
15223
|
+
patternProperties: {
|
|
15224
|
+
"^x-": {}
|
|
15225
|
+
}
|
|
15226
|
+
},
|
|
15227
|
+
WhatsAppConfig: {
|
|
15228
|
+
type: "object",
|
|
15229
|
+
properties: {
|
|
15230
|
+
access_token: {
|
|
15231
|
+
type: "string",
|
|
15232
|
+
description: "WhatsApp Cloud API access token (or WHATSAPP_ACCESS_TOKEN env var)"
|
|
15233
|
+
},
|
|
15234
|
+
phone_number_id: {
|
|
15235
|
+
type: "string",
|
|
15236
|
+
description: "Phone Number ID from Meta Business Suite (or WHATSAPP_PHONE_NUMBER_ID env var)"
|
|
15237
|
+
},
|
|
15238
|
+
app_secret: {
|
|
15239
|
+
type: "string",
|
|
15240
|
+
description: "Meta App Secret for webhook signature verification (or WHATSAPP_APP_SECRET env var)"
|
|
15241
|
+
},
|
|
15242
|
+
verify_token: {
|
|
15243
|
+
type: "string",
|
|
15244
|
+
description: "Verify token for webhook subscription challenge (or WHATSAPP_VERIFY_TOKEN env var)"
|
|
15245
|
+
},
|
|
15246
|
+
api_version: {
|
|
15247
|
+
type: "string",
|
|
15248
|
+
description: "Graph API version (default: 'v21.0')"
|
|
15249
|
+
},
|
|
15250
|
+
port: {
|
|
15251
|
+
type: "number",
|
|
15252
|
+
description: "Port for webhook HTTP server (default: 8443)"
|
|
15253
|
+
},
|
|
15254
|
+
host: {
|
|
15255
|
+
type: "string",
|
|
15256
|
+
description: "Host for webhook HTTP server (default: '0.0.0.0')"
|
|
15257
|
+
},
|
|
15258
|
+
phone_allowlist: {
|
|
15259
|
+
type: "array",
|
|
15260
|
+
items: {
|
|
15261
|
+
type: "string"
|
|
15262
|
+
},
|
|
15263
|
+
description: "Phone number allowlist \u2014 only respond to these numbers"
|
|
15264
|
+
},
|
|
15265
|
+
workflow: {
|
|
15266
|
+
type: "string",
|
|
15267
|
+
description: "Workflow to run when a message is received"
|
|
15268
|
+
}
|
|
15269
|
+
},
|
|
15270
|
+
additionalProperties: false,
|
|
15271
|
+
patternProperties: {
|
|
15272
|
+
"^x-": {}
|
|
15273
|
+
}
|
|
15274
|
+
},
|
|
15275
|
+
TeamsConfig: {
|
|
15276
|
+
type: "object",
|
|
15277
|
+
properties: {
|
|
15278
|
+
app_id: {
|
|
15279
|
+
type: "string",
|
|
15280
|
+
description: "Azure AD App (client) ID (or TEAMS_APP_ID env var)"
|
|
15281
|
+
},
|
|
15282
|
+
app_password: {
|
|
15283
|
+
type: "string",
|
|
15284
|
+
description: "Azure AD App client secret (or TEAMS_APP_PASSWORD env var)"
|
|
15285
|
+
},
|
|
15286
|
+
tenant_id: {
|
|
15287
|
+
type: "string",
|
|
15288
|
+
description: "Azure AD Tenant ID for single-tenant apps (or TEAMS_TENANT_ID env var)"
|
|
15289
|
+
},
|
|
15290
|
+
port: {
|
|
15291
|
+
type: "number",
|
|
15292
|
+
description: "Port for webhook HTTP server (default: 3978)"
|
|
15293
|
+
},
|
|
15294
|
+
host: {
|
|
15295
|
+
type: "string",
|
|
15296
|
+
description: "Host for webhook HTTP server (default: '0.0.0.0')"
|
|
15297
|
+
},
|
|
15298
|
+
user_allowlist: {
|
|
15299
|
+
type: "array",
|
|
15300
|
+
items: {
|
|
15301
|
+
type: "string"
|
|
15302
|
+
},
|
|
15303
|
+
description: "User ID allowlist \u2014 only respond to these AAD user IDs"
|
|
15304
|
+
},
|
|
15305
|
+
workflow: {
|
|
15306
|
+
type: "string",
|
|
15307
|
+
description: "Workflow to run when a message is received"
|
|
15308
|
+
}
|
|
15309
|
+
},
|
|
15310
|
+
additionalProperties: false,
|
|
15311
|
+
patternProperties: {
|
|
15312
|
+
"^x-": {}
|
|
15313
|
+
}
|
|
15314
|
+
},
|
|
15039
15315
|
SchedulerConfig: {
|
|
15040
15316
|
type: "object",
|
|
15041
15317
|
properties: {
|
|
@@ -18299,17 +18575,17 @@ var init_workflow_check_provider = __esm({
|
|
|
18299
18575
|
* so it can be executed by the state machine as a nested workflow.
|
|
18300
18576
|
*/
|
|
18301
18577
|
async loadWorkflowFromConfigPath(sourcePath, baseDir) {
|
|
18302
|
-
const
|
|
18303
|
-
const
|
|
18578
|
+
const path33 = require("path");
|
|
18579
|
+
const fs29 = require("fs");
|
|
18304
18580
|
const yaml5 = require("js-yaml");
|
|
18305
|
-
const resolved =
|
|
18306
|
-
if (!
|
|
18581
|
+
const resolved = path33.isAbsolute(sourcePath) ? sourcePath : path33.resolve(baseDir, sourcePath);
|
|
18582
|
+
if (!fs29.existsSync(resolved)) {
|
|
18307
18583
|
throw new Error(`Workflow config not found at: ${resolved}`);
|
|
18308
18584
|
}
|
|
18309
|
-
const rawContent =
|
|
18585
|
+
const rawContent = fs29.readFileSync(resolved, "utf8");
|
|
18310
18586
|
const rawData = yaml5.load(rawContent);
|
|
18311
18587
|
if (rawData.imports && Array.isArray(rawData.imports)) {
|
|
18312
|
-
const configDir =
|
|
18588
|
+
const configDir = path33.dirname(resolved);
|
|
18313
18589
|
for (const source of rawData.imports) {
|
|
18314
18590
|
const results = await this.registry.import(source, {
|
|
18315
18591
|
basePath: configDir,
|
|
@@ -18339,8 +18615,8 @@ ${errors}`);
|
|
|
18339
18615
|
if (!steps || Object.keys(steps).length === 0) {
|
|
18340
18616
|
throw new Error(`Config '${resolved}' does not contain any steps to execute as a workflow`);
|
|
18341
18617
|
}
|
|
18342
|
-
const id =
|
|
18343
|
-
const name = loaded.name || `Workflow from ${
|
|
18618
|
+
const id = path33.basename(resolved).replace(/\.(ya?ml)$/i, "");
|
|
18619
|
+
const name = loaded.name || `Workflow from ${path33.basename(resolved)}`;
|
|
18344
18620
|
const workflowDef = {
|
|
18345
18621
|
id,
|
|
18346
18622
|
name,
|
|
@@ -19149,8 +19425,8 @@ async function createStoreBackend(storageConfig, haConfig) {
|
|
|
19149
19425
|
case "mssql": {
|
|
19150
19426
|
try {
|
|
19151
19427
|
const loaderPath = "../../enterprise/loader";
|
|
19152
|
-
const { loadEnterpriseStoreBackend } = await import(loaderPath);
|
|
19153
|
-
return await
|
|
19428
|
+
const { loadEnterpriseStoreBackend: loadEnterpriseStoreBackend2 } = await import(loaderPath);
|
|
19429
|
+
return await loadEnterpriseStoreBackend2(driver, storageConfig, haConfig);
|
|
19154
19430
|
} catch (err) {
|
|
19155
19431
|
const msg = err instanceof Error ? err.message : String(err);
|
|
19156
19432
|
logger.error(`[StoreFactory] Failed to load enterprise ${driver} backend: ${msg}`);
|
|
@@ -21838,7 +22114,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21838
22114
|
* Returns the actual bound port number
|
|
21839
22115
|
*/
|
|
21840
22116
|
async start() {
|
|
21841
|
-
return new Promise((
|
|
22117
|
+
return new Promise((resolve19, reject) => {
|
|
21842
22118
|
try {
|
|
21843
22119
|
this.server = import_http.default.createServer((req, res) => {
|
|
21844
22120
|
this.handleRequest(req, res).catch((error) => {
|
|
@@ -21872,7 +22148,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21872
22148
|
);
|
|
21873
22149
|
}
|
|
21874
22150
|
this.startKeepalive();
|
|
21875
|
-
|
|
22151
|
+
resolve19(this.port);
|
|
21876
22152
|
});
|
|
21877
22153
|
} catch (error) {
|
|
21878
22154
|
reject(error);
|
|
@@ -21935,7 +22211,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21935
22211
|
logger.debug(
|
|
21936
22212
|
`[CustomToolsSSEServer:${this.sessionId}] Grace period before stop: ${waitMs}ms (activeToolCalls=${this.activeToolCalls})`
|
|
21937
22213
|
);
|
|
21938
|
-
await new Promise((
|
|
22214
|
+
await new Promise((resolve19) => setTimeout(resolve19, waitMs));
|
|
21939
22215
|
}
|
|
21940
22216
|
}
|
|
21941
22217
|
if (this.activeToolCalls > 0) {
|
|
@@ -21944,7 +22220,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21944
22220
|
`[CustomToolsSSEServer:${this.sessionId}] Waiting for ${this.activeToolCalls} active tool call(s) before stop`
|
|
21945
22221
|
);
|
|
21946
22222
|
while (this.activeToolCalls > 0 && Date.now() - startedAt < effectiveDrainTimeoutMs) {
|
|
21947
|
-
await new Promise((
|
|
22223
|
+
await new Promise((resolve19) => setTimeout(resolve19, 250));
|
|
21948
22224
|
}
|
|
21949
22225
|
if (this.activeToolCalls > 0) {
|
|
21950
22226
|
logger.warn(
|
|
@@ -21969,21 +22245,21 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
21969
22245
|
}
|
|
21970
22246
|
this.connections.clear();
|
|
21971
22247
|
if (this.server) {
|
|
21972
|
-
await new Promise((
|
|
22248
|
+
await new Promise((resolve19, reject) => {
|
|
21973
22249
|
const timeout = setTimeout(() => {
|
|
21974
22250
|
if (this.debug) {
|
|
21975
22251
|
logger.debug(
|
|
21976
22252
|
`[CustomToolsSSEServer:${this.sessionId}] Force closing server after timeout`
|
|
21977
22253
|
);
|
|
21978
22254
|
}
|
|
21979
|
-
this.server?.close(() =>
|
|
22255
|
+
this.server?.close(() => resolve19());
|
|
21980
22256
|
}, 5e3);
|
|
21981
22257
|
this.server.close((error) => {
|
|
21982
22258
|
clearTimeout(timeout);
|
|
21983
22259
|
if (error) {
|
|
21984
22260
|
reject(error);
|
|
21985
22261
|
} else {
|
|
21986
|
-
|
|
22262
|
+
resolve19();
|
|
21987
22263
|
}
|
|
21988
22264
|
});
|
|
21989
22265
|
});
|
|
@@ -22433,7 +22709,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
22433
22709
|
logger.warn(
|
|
22434
22710
|
`[CustomToolsSSEServer:${this.sessionId}] Tool ${toolName} failed (attempt ${attempt + 1}/${retryCount + 1}): ${errorMsg}. Retrying in ${delay}ms`
|
|
22435
22711
|
);
|
|
22436
|
-
await new Promise((
|
|
22712
|
+
await new Promise((resolve19) => setTimeout(resolve19, delay));
|
|
22437
22713
|
attempt++;
|
|
22438
22714
|
}
|
|
22439
22715
|
}
|
|
@@ -22825,9 +23101,9 @@ var init_ai_check_provider = __esm({
|
|
|
22825
23101
|
} else {
|
|
22826
23102
|
resolvedPath = import_path8.default.resolve(process.cwd(), str);
|
|
22827
23103
|
}
|
|
22828
|
-
const
|
|
23104
|
+
const fs29 = require("fs").promises;
|
|
22829
23105
|
try {
|
|
22830
|
-
const stat2 = await
|
|
23106
|
+
const stat2 = await fs29.stat(resolvedPath);
|
|
22831
23107
|
return stat2.isFile();
|
|
22832
23108
|
} catch {
|
|
22833
23109
|
return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);
|
|
@@ -28929,14 +29205,14 @@ var require_util = __commonJS({
|
|
|
28929
29205
|
}
|
|
28930
29206
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
28931
29207
|
let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`;
|
|
28932
|
-
let
|
|
29208
|
+
let path33 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
28933
29209
|
if (origin.endsWith("/")) {
|
|
28934
29210
|
origin = origin.substring(0, origin.length - 1);
|
|
28935
29211
|
}
|
|
28936
|
-
if (
|
|
28937
|
-
|
|
29212
|
+
if (path33 && !path33.startsWith("/")) {
|
|
29213
|
+
path33 = `/${path33}`;
|
|
28938
29214
|
}
|
|
28939
|
-
url = new URL(origin +
|
|
29215
|
+
url = new URL(origin + path33);
|
|
28940
29216
|
}
|
|
28941
29217
|
return url;
|
|
28942
29218
|
}
|
|
@@ -30550,20 +30826,20 @@ var require_parseParams = __commonJS({
|
|
|
30550
30826
|
var require_basename = __commonJS({
|
|
30551
30827
|
"node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) {
|
|
30552
30828
|
"use strict";
|
|
30553
|
-
module2.exports = function basename4(
|
|
30554
|
-
if (typeof
|
|
30829
|
+
module2.exports = function basename4(path33) {
|
|
30830
|
+
if (typeof path33 !== "string") {
|
|
30555
30831
|
return "";
|
|
30556
30832
|
}
|
|
30557
|
-
for (var i =
|
|
30558
|
-
switch (
|
|
30833
|
+
for (var i = path33.length - 1; i >= 0; --i) {
|
|
30834
|
+
switch (path33.charCodeAt(i)) {
|
|
30559
30835
|
case 47:
|
|
30560
30836
|
// '/'
|
|
30561
30837
|
case 92:
|
|
30562
|
-
|
|
30563
|
-
return
|
|
30838
|
+
path33 = path33.slice(i + 1);
|
|
30839
|
+
return path33 === ".." || path33 === "." ? "" : path33;
|
|
30564
30840
|
}
|
|
30565
30841
|
}
|
|
30566
|
-
return
|
|
30842
|
+
return path33 === ".." || path33 === "." ? "" : path33;
|
|
30567
30843
|
};
|
|
30568
30844
|
}
|
|
30569
30845
|
});
|
|
@@ -31567,11 +31843,11 @@ var require_util2 = __commonJS({
|
|
|
31567
31843
|
var assert = require("assert");
|
|
31568
31844
|
var { isUint8Array } = require("util/types");
|
|
31569
31845
|
var supportedHashes = [];
|
|
31570
|
-
var
|
|
31846
|
+
var crypto9;
|
|
31571
31847
|
try {
|
|
31572
|
-
|
|
31848
|
+
crypto9 = require("crypto");
|
|
31573
31849
|
const possibleRelevantHashes = ["sha256", "sha384", "sha512"];
|
|
31574
|
-
supportedHashes =
|
|
31850
|
+
supportedHashes = crypto9.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
|
|
31575
31851
|
} catch {
|
|
31576
31852
|
}
|
|
31577
31853
|
function responseURL(response) {
|
|
@@ -31848,7 +32124,7 @@ var require_util2 = __commonJS({
|
|
|
31848
32124
|
}
|
|
31849
32125
|
}
|
|
31850
32126
|
function bytesMatch(bytes, metadataList) {
|
|
31851
|
-
if (
|
|
32127
|
+
if (crypto9 === void 0) {
|
|
31852
32128
|
return true;
|
|
31853
32129
|
}
|
|
31854
32130
|
const parsedMetadata = parseMetadata(metadataList);
|
|
@@ -31863,7 +32139,7 @@ var require_util2 = __commonJS({
|
|
|
31863
32139
|
for (const item of metadata) {
|
|
31864
32140
|
const algorithm = item.algo;
|
|
31865
32141
|
const expectedValue = item.hash;
|
|
31866
|
-
let actualValue =
|
|
32142
|
+
let actualValue = crypto9.createHash(algorithm).update(bytes).digest("base64");
|
|
31867
32143
|
if (actualValue[actualValue.length - 1] === "=") {
|
|
31868
32144
|
if (actualValue[actualValue.length - 2] === "=") {
|
|
31869
32145
|
actualValue = actualValue.slice(0, -2);
|
|
@@ -31956,8 +32232,8 @@ var require_util2 = __commonJS({
|
|
|
31956
32232
|
function createDeferredPromise() {
|
|
31957
32233
|
let res;
|
|
31958
32234
|
let rej;
|
|
31959
|
-
const promise = new Promise((
|
|
31960
|
-
res =
|
|
32235
|
+
const promise = new Promise((resolve19, reject) => {
|
|
32236
|
+
res = resolve19;
|
|
31961
32237
|
rej = reject;
|
|
31962
32238
|
});
|
|
31963
32239
|
return { promise, resolve: res, reject: rej };
|
|
@@ -33210,8 +33486,8 @@ var require_body = __commonJS({
|
|
|
33210
33486
|
var { parseMIMEType, serializeAMimeType } = require_dataURL();
|
|
33211
33487
|
var random;
|
|
33212
33488
|
try {
|
|
33213
|
-
const
|
|
33214
|
-
random = (max) =>
|
|
33489
|
+
const crypto9 = require("crypto");
|
|
33490
|
+
random = (max) => crypto9.randomInt(0, max);
|
|
33215
33491
|
} catch {
|
|
33216
33492
|
random = (max) => Math.floor(Math.random(max));
|
|
33217
33493
|
}
|
|
@@ -33462,8 +33738,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r
|
|
|
33462
33738
|
});
|
|
33463
33739
|
}
|
|
33464
33740
|
});
|
|
33465
|
-
const busboyResolve = new Promise((
|
|
33466
|
-
busboy.on("finish",
|
|
33741
|
+
const busboyResolve = new Promise((resolve19, reject) => {
|
|
33742
|
+
busboy.on("finish", resolve19);
|
|
33467
33743
|
busboy.on("error", (err) => reject(new TypeError(err)));
|
|
33468
33744
|
});
|
|
33469
33745
|
if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk);
|
|
@@ -33594,7 +33870,7 @@ var require_request = __commonJS({
|
|
|
33594
33870
|
}
|
|
33595
33871
|
var Request2 = class _Request {
|
|
33596
33872
|
constructor(origin, {
|
|
33597
|
-
path:
|
|
33873
|
+
path: path33,
|
|
33598
33874
|
method,
|
|
33599
33875
|
body,
|
|
33600
33876
|
headers,
|
|
@@ -33608,11 +33884,11 @@ var require_request = __commonJS({
|
|
|
33608
33884
|
throwOnError,
|
|
33609
33885
|
expectContinue
|
|
33610
33886
|
}, handler) {
|
|
33611
|
-
if (typeof
|
|
33887
|
+
if (typeof path33 !== "string") {
|
|
33612
33888
|
throw new InvalidArgumentError("path must be a string");
|
|
33613
|
-
} else if (
|
|
33889
|
+
} else if (path33[0] !== "/" && !(path33.startsWith("http://") || path33.startsWith("https://")) && method !== "CONNECT") {
|
|
33614
33890
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
33615
|
-
} else if (invalidPathRegex.exec(
|
|
33891
|
+
} else if (invalidPathRegex.exec(path33) !== null) {
|
|
33616
33892
|
throw new InvalidArgumentError("invalid request path");
|
|
33617
33893
|
}
|
|
33618
33894
|
if (typeof method !== "string") {
|
|
@@ -33675,7 +33951,7 @@ var require_request = __commonJS({
|
|
|
33675
33951
|
this.completed = false;
|
|
33676
33952
|
this.aborted = false;
|
|
33677
33953
|
this.upgrade = upgrade || null;
|
|
33678
|
-
this.path = query ? util.buildURL(
|
|
33954
|
+
this.path = query ? util.buildURL(path33, query) : path33;
|
|
33679
33955
|
this.origin = origin;
|
|
33680
33956
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
33681
33957
|
this.blocking = blocking == null ? false : blocking;
|
|
@@ -33997,9 +34273,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
33997
34273
|
}
|
|
33998
34274
|
close(callback) {
|
|
33999
34275
|
if (callback === void 0) {
|
|
34000
|
-
return new Promise((
|
|
34276
|
+
return new Promise((resolve19, reject) => {
|
|
34001
34277
|
this.close((err, data) => {
|
|
34002
|
-
return err ? reject(err) :
|
|
34278
|
+
return err ? reject(err) : resolve19(data);
|
|
34003
34279
|
});
|
|
34004
34280
|
});
|
|
34005
34281
|
}
|
|
@@ -34037,12 +34313,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
34037
34313
|
err = null;
|
|
34038
34314
|
}
|
|
34039
34315
|
if (callback === void 0) {
|
|
34040
|
-
return new Promise((
|
|
34316
|
+
return new Promise((resolve19, reject) => {
|
|
34041
34317
|
this.destroy(err, (err2, data) => {
|
|
34042
34318
|
return err2 ? (
|
|
34043
34319
|
/* istanbul ignore next: should never error */
|
|
34044
34320
|
reject(err2)
|
|
34045
|
-
) :
|
|
34321
|
+
) : resolve19(data);
|
|
34046
34322
|
});
|
|
34047
34323
|
});
|
|
34048
34324
|
}
|
|
@@ -34683,9 +34959,9 @@ var require_RedirectHandler = __commonJS({
|
|
|
34683
34959
|
return this.handler.onHeaders(statusCode, headers, resume, statusText);
|
|
34684
34960
|
}
|
|
34685
34961
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
34686
|
-
const
|
|
34962
|
+
const path33 = search ? `${pathname}${search}` : pathname;
|
|
34687
34963
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
34688
|
-
this.opts.path =
|
|
34964
|
+
this.opts.path = path33;
|
|
34689
34965
|
this.opts.origin = origin;
|
|
34690
34966
|
this.opts.maxRedirections = 0;
|
|
34691
34967
|
this.opts.query = null;
|
|
@@ -35104,16 +35380,16 @@ var require_client = __commonJS({
|
|
|
35104
35380
|
return this[kNeedDrain] < 2;
|
|
35105
35381
|
}
|
|
35106
35382
|
async [kClose]() {
|
|
35107
|
-
return new Promise((
|
|
35383
|
+
return new Promise((resolve19) => {
|
|
35108
35384
|
if (!this[kSize]) {
|
|
35109
|
-
|
|
35385
|
+
resolve19(null);
|
|
35110
35386
|
} else {
|
|
35111
|
-
this[kClosedResolve] =
|
|
35387
|
+
this[kClosedResolve] = resolve19;
|
|
35112
35388
|
}
|
|
35113
35389
|
});
|
|
35114
35390
|
}
|
|
35115
35391
|
async [kDestroy](err) {
|
|
35116
|
-
return new Promise((
|
|
35392
|
+
return new Promise((resolve19) => {
|
|
35117
35393
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
35118
35394
|
for (let i = 0; i < requests.length; i++) {
|
|
35119
35395
|
const request = requests[i];
|
|
@@ -35124,7 +35400,7 @@ var require_client = __commonJS({
|
|
|
35124
35400
|
this[kClosedResolve]();
|
|
35125
35401
|
this[kClosedResolve] = null;
|
|
35126
35402
|
}
|
|
35127
|
-
|
|
35403
|
+
resolve19();
|
|
35128
35404
|
};
|
|
35129
35405
|
if (this[kHTTP2Session] != null) {
|
|
35130
35406
|
util.destroy(this[kHTTP2Session], err);
|
|
@@ -35704,7 +35980,7 @@ var require_client = __commonJS({
|
|
|
35704
35980
|
});
|
|
35705
35981
|
}
|
|
35706
35982
|
try {
|
|
35707
|
-
const socket = await new Promise((
|
|
35983
|
+
const socket = await new Promise((resolve19, reject) => {
|
|
35708
35984
|
client[kConnector]({
|
|
35709
35985
|
host,
|
|
35710
35986
|
hostname,
|
|
@@ -35716,7 +35992,7 @@ var require_client = __commonJS({
|
|
|
35716
35992
|
if (err) {
|
|
35717
35993
|
reject(err);
|
|
35718
35994
|
} else {
|
|
35719
|
-
|
|
35995
|
+
resolve19(socket2);
|
|
35720
35996
|
}
|
|
35721
35997
|
});
|
|
35722
35998
|
});
|
|
@@ -35927,7 +36203,7 @@ var require_client = __commonJS({
|
|
|
35927
36203
|
writeH2(client, client[kHTTP2Session], request);
|
|
35928
36204
|
return;
|
|
35929
36205
|
}
|
|
35930
|
-
const { body, method, path:
|
|
36206
|
+
const { body, method, path: path33, host, upgrade, headers, blocking, reset } = request;
|
|
35931
36207
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
35932
36208
|
if (body && typeof body.read === "function") {
|
|
35933
36209
|
body.read(0);
|
|
@@ -35977,7 +36253,7 @@ var require_client = __commonJS({
|
|
|
35977
36253
|
if (blocking) {
|
|
35978
36254
|
socket[kBlocking] = true;
|
|
35979
36255
|
}
|
|
35980
|
-
let header = `${method} ${
|
|
36256
|
+
let header = `${method} ${path33} HTTP/1.1\r
|
|
35981
36257
|
`;
|
|
35982
36258
|
if (typeof host === "string") {
|
|
35983
36259
|
header += `host: ${host}\r
|
|
@@ -36040,7 +36316,7 @@ upgrade: ${upgrade}\r
|
|
|
36040
36316
|
return true;
|
|
36041
36317
|
}
|
|
36042
36318
|
function writeH2(client, session, request) {
|
|
36043
|
-
const { body, method, path:
|
|
36319
|
+
const { body, method, path: path33, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
|
|
36044
36320
|
let headers;
|
|
36045
36321
|
if (typeof reqHeaders === "string") headers = Request2[kHTTP2CopyHeaders](reqHeaders.trim());
|
|
36046
36322
|
else headers = reqHeaders;
|
|
@@ -36083,7 +36359,7 @@ upgrade: ${upgrade}\r
|
|
|
36083
36359
|
});
|
|
36084
36360
|
return true;
|
|
36085
36361
|
}
|
|
36086
|
-
headers[HTTP2_HEADER_PATH] =
|
|
36362
|
+
headers[HTTP2_HEADER_PATH] = path33;
|
|
36087
36363
|
headers[HTTP2_HEADER_SCHEME] = "https";
|
|
36088
36364
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
36089
36365
|
if (body && typeof body.read === "function") {
|
|
@@ -36340,12 +36616,12 @@ upgrade: ${upgrade}\r
|
|
|
36340
36616
|
cb();
|
|
36341
36617
|
}
|
|
36342
36618
|
}
|
|
36343
|
-
const waitForDrain = () => new Promise((
|
|
36619
|
+
const waitForDrain = () => new Promise((resolve19, reject) => {
|
|
36344
36620
|
assert(callback === null);
|
|
36345
36621
|
if (socket[kError]) {
|
|
36346
36622
|
reject(socket[kError]);
|
|
36347
36623
|
} else {
|
|
36348
|
-
callback =
|
|
36624
|
+
callback = resolve19;
|
|
36349
36625
|
}
|
|
36350
36626
|
});
|
|
36351
36627
|
if (client[kHTTPConnVersion] === "h2") {
|
|
@@ -36691,8 +36967,8 @@ var require_pool_base = __commonJS({
|
|
|
36691
36967
|
if (this[kQueue].isEmpty()) {
|
|
36692
36968
|
return Promise.all(this[kClients].map((c) => c.close()));
|
|
36693
36969
|
} else {
|
|
36694
|
-
return new Promise((
|
|
36695
|
-
this[kClosedResolve] =
|
|
36970
|
+
return new Promise((resolve19) => {
|
|
36971
|
+
this[kClosedResolve] = resolve19;
|
|
36696
36972
|
});
|
|
36697
36973
|
}
|
|
36698
36974
|
}
|
|
@@ -37270,7 +37546,7 @@ var require_readable = __commonJS({
|
|
|
37270
37546
|
if (this.closed) {
|
|
37271
37547
|
return Promise.resolve(null);
|
|
37272
37548
|
}
|
|
37273
|
-
return new Promise((
|
|
37549
|
+
return new Promise((resolve19, reject) => {
|
|
37274
37550
|
const signalListenerCleanup = signal ? util.addAbortListener(signal, () => {
|
|
37275
37551
|
this.destroy();
|
|
37276
37552
|
}) : noop;
|
|
@@ -37279,7 +37555,7 @@ var require_readable = __commonJS({
|
|
|
37279
37555
|
if (signal && signal.aborted) {
|
|
37280
37556
|
reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" }));
|
|
37281
37557
|
} else {
|
|
37282
|
-
|
|
37558
|
+
resolve19(null);
|
|
37283
37559
|
}
|
|
37284
37560
|
}).on("error", noop).on("data", function(chunk) {
|
|
37285
37561
|
limit -= chunk.length;
|
|
@@ -37301,11 +37577,11 @@ var require_readable = __commonJS({
|
|
|
37301
37577
|
throw new TypeError("unusable");
|
|
37302
37578
|
}
|
|
37303
37579
|
assert(!stream[kConsume]);
|
|
37304
|
-
return new Promise((
|
|
37580
|
+
return new Promise((resolve19, reject) => {
|
|
37305
37581
|
stream[kConsume] = {
|
|
37306
37582
|
type,
|
|
37307
37583
|
stream,
|
|
37308
|
-
resolve:
|
|
37584
|
+
resolve: resolve19,
|
|
37309
37585
|
reject,
|
|
37310
37586
|
length: 0,
|
|
37311
37587
|
body: []
|
|
@@ -37340,12 +37616,12 @@ var require_readable = __commonJS({
|
|
|
37340
37616
|
}
|
|
37341
37617
|
}
|
|
37342
37618
|
function consumeEnd(consume2) {
|
|
37343
|
-
const { type, body, resolve:
|
|
37619
|
+
const { type, body, resolve: resolve19, stream, length } = consume2;
|
|
37344
37620
|
try {
|
|
37345
37621
|
if (type === "text") {
|
|
37346
|
-
|
|
37622
|
+
resolve19(toUSVString(Buffer.concat(body)));
|
|
37347
37623
|
} else if (type === "json") {
|
|
37348
|
-
|
|
37624
|
+
resolve19(JSON.parse(Buffer.concat(body)));
|
|
37349
37625
|
} else if (type === "arrayBuffer") {
|
|
37350
37626
|
const dst = new Uint8Array(length);
|
|
37351
37627
|
let pos = 0;
|
|
@@ -37353,12 +37629,12 @@ var require_readable = __commonJS({
|
|
|
37353
37629
|
dst.set(buf, pos);
|
|
37354
37630
|
pos += buf.byteLength;
|
|
37355
37631
|
}
|
|
37356
|
-
|
|
37632
|
+
resolve19(dst.buffer);
|
|
37357
37633
|
} else if (type === "blob") {
|
|
37358
37634
|
if (!Blob2) {
|
|
37359
37635
|
Blob2 = require("buffer").Blob;
|
|
37360
37636
|
}
|
|
37361
|
-
|
|
37637
|
+
resolve19(new Blob2(body, { type: stream[kContentType] }));
|
|
37362
37638
|
}
|
|
37363
37639
|
consumeFinish(consume2);
|
|
37364
37640
|
} catch (err) {
|
|
@@ -37615,9 +37891,9 @@ var require_api_request = __commonJS({
|
|
|
37615
37891
|
};
|
|
37616
37892
|
function request(opts, callback) {
|
|
37617
37893
|
if (callback === void 0) {
|
|
37618
|
-
return new Promise((
|
|
37894
|
+
return new Promise((resolve19, reject) => {
|
|
37619
37895
|
request.call(this, opts, (err, data) => {
|
|
37620
|
-
return err ? reject(err) :
|
|
37896
|
+
return err ? reject(err) : resolve19(data);
|
|
37621
37897
|
});
|
|
37622
37898
|
});
|
|
37623
37899
|
}
|
|
@@ -37790,9 +38066,9 @@ var require_api_stream = __commonJS({
|
|
|
37790
38066
|
};
|
|
37791
38067
|
function stream(opts, factory, callback) {
|
|
37792
38068
|
if (callback === void 0) {
|
|
37793
|
-
return new Promise((
|
|
38069
|
+
return new Promise((resolve19, reject) => {
|
|
37794
38070
|
stream.call(this, opts, factory, (err, data) => {
|
|
37795
|
-
return err ? reject(err) :
|
|
38071
|
+
return err ? reject(err) : resolve19(data);
|
|
37796
38072
|
});
|
|
37797
38073
|
});
|
|
37798
38074
|
}
|
|
@@ -38073,9 +38349,9 @@ var require_api_upgrade = __commonJS({
|
|
|
38073
38349
|
};
|
|
38074
38350
|
function upgrade(opts, callback) {
|
|
38075
38351
|
if (callback === void 0) {
|
|
38076
|
-
return new Promise((
|
|
38352
|
+
return new Promise((resolve19, reject) => {
|
|
38077
38353
|
upgrade.call(this, opts, (err, data) => {
|
|
38078
|
-
return err ? reject(err) :
|
|
38354
|
+
return err ? reject(err) : resolve19(data);
|
|
38079
38355
|
});
|
|
38080
38356
|
});
|
|
38081
38357
|
}
|
|
@@ -38164,9 +38440,9 @@ var require_api_connect = __commonJS({
|
|
|
38164
38440
|
};
|
|
38165
38441
|
function connect(opts, callback) {
|
|
38166
38442
|
if (callback === void 0) {
|
|
38167
|
-
return new Promise((
|
|
38443
|
+
return new Promise((resolve19, reject) => {
|
|
38168
38444
|
connect.call(this, opts, (err, data) => {
|
|
38169
|
-
return err ? reject(err) :
|
|
38445
|
+
return err ? reject(err) : resolve19(data);
|
|
38170
38446
|
});
|
|
38171
38447
|
});
|
|
38172
38448
|
}
|
|
@@ -38326,20 +38602,20 @@ var require_mock_utils = __commonJS({
|
|
|
38326
38602
|
}
|
|
38327
38603
|
return true;
|
|
38328
38604
|
}
|
|
38329
|
-
function safeUrl(
|
|
38330
|
-
if (typeof
|
|
38331
|
-
return
|
|
38605
|
+
function safeUrl(path33) {
|
|
38606
|
+
if (typeof path33 !== "string") {
|
|
38607
|
+
return path33;
|
|
38332
38608
|
}
|
|
38333
|
-
const pathSegments =
|
|
38609
|
+
const pathSegments = path33.split("?");
|
|
38334
38610
|
if (pathSegments.length !== 2) {
|
|
38335
|
-
return
|
|
38611
|
+
return path33;
|
|
38336
38612
|
}
|
|
38337
38613
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
38338
38614
|
qp.sort();
|
|
38339
38615
|
return [...pathSegments, qp.toString()].join("?");
|
|
38340
38616
|
}
|
|
38341
|
-
function matchKey(mockDispatch2, { path:
|
|
38342
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
38617
|
+
function matchKey(mockDispatch2, { path: path33, method, body, headers }) {
|
|
38618
|
+
const pathMatch = matchValue(mockDispatch2.path, path33);
|
|
38343
38619
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
38344
38620
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
38345
38621
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -38357,7 +38633,7 @@ var require_mock_utils = __commonJS({
|
|
|
38357
38633
|
function getMockDispatch(mockDispatches, key) {
|
|
38358
38634
|
const basePath = key.query ? buildURL(key.path, key.query) : key.path;
|
|
38359
38635
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
38360
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
38636
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path33 }) => matchValue(safeUrl(path33), resolvedPath));
|
|
38361
38637
|
if (matchedMockDispatches.length === 0) {
|
|
38362
38638
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
38363
38639
|
}
|
|
@@ -38394,9 +38670,9 @@ var require_mock_utils = __commonJS({
|
|
|
38394
38670
|
}
|
|
38395
38671
|
}
|
|
38396
38672
|
function buildKey(opts) {
|
|
38397
|
-
const { path:
|
|
38673
|
+
const { path: path33, method, body, headers, query } = opts;
|
|
38398
38674
|
return {
|
|
38399
|
-
path:
|
|
38675
|
+
path: path33,
|
|
38400
38676
|
method,
|
|
38401
38677
|
body,
|
|
38402
38678
|
headers,
|
|
@@ -38845,10 +39121,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
38845
39121
|
}
|
|
38846
39122
|
format(pendingInterceptors) {
|
|
38847
39123
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
38848
|
-
({ method, path:
|
|
39124
|
+
({ method, path: path33, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
38849
39125
|
Method: method,
|
|
38850
39126
|
Origin: origin,
|
|
38851
|
-
Path:
|
|
39127
|
+
Path: path33,
|
|
38852
39128
|
"Status code": statusCode,
|
|
38853
39129
|
Persistent: persist ? "\u2705" : "\u274C",
|
|
38854
39130
|
Invocations: timesInvoked,
|
|
@@ -41789,7 +42065,7 @@ var require_fetch = __commonJS({
|
|
|
41789
42065
|
async function dispatch({ body }) {
|
|
41790
42066
|
const url = requestCurrentURL(request);
|
|
41791
42067
|
const agent = fetchParams.controller.dispatcher;
|
|
41792
|
-
return new Promise((
|
|
42068
|
+
return new Promise((resolve19, reject) => agent.dispatch(
|
|
41793
42069
|
{
|
|
41794
42070
|
path: url.pathname + url.search,
|
|
41795
42071
|
origin: url.origin,
|
|
@@ -41865,7 +42141,7 @@ var require_fetch = __commonJS({
|
|
|
41865
42141
|
}
|
|
41866
42142
|
}
|
|
41867
42143
|
}
|
|
41868
|
-
|
|
42144
|
+
resolve19({
|
|
41869
42145
|
status,
|
|
41870
42146
|
statusText,
|
|
41871
42147
|
headersList: headers[kHeadersList],
|
|
@@ -41908,7 +42184,7 @@ var require_fetch = __commonJS({
|
|
|
41908
42184
|
const val = headersList[n + 1].toString("latin1");
|
|
41909
42185
|
headers[kHeadersList].append(key, val);
|
|
41910
42186
|
}
|
|
41911
|
-
|
|
42187
|
+
resolve19({
|
|
41912
42188
|
status,
|
|
41913
42189
|
statusText: STATUS_CODES[status],
|
|
41914
42190
|
headersList: headers[kHeadersList],
|
|
@@ -43469,8 +43745,8 @@ var require_util6 = __commonJS({
|
|
|
43469
43745
|
}
|
|
43470
43746
|
}
|
|
43471
43747
|
}
|
|
43472
|
-
function validateCookiePath(
|
|
43473
|
-
for (const char of
|
|
43748
|
+
function validateCookiePath(path33) {
|
|
43749
|
+
for (const char of path33) {
|
|
43474
43750
|
const code = char.charCodeAt(0);
|
|
43475
43751
|
if (code < 33 || char === ";") {
|
|
43476
43752
|
throw new Error("Invalid cookie path");
|
|
@@ -44267,9 +44543,9 @@ var require_connection = __commonJS({
|
|
|
44267
44543
|
channels.open = diagnosticsChannel.channel("undici:websocket:open");
|
|
44268
44544
|
channels.close = diagnosticsChannel.channel("undici:websocket:close");
|
|
44269
44545
|
channels.socketError = diagnosticsChannel.channel("undici:websocket:socket_error");
|
|
44270
|
-
var
|
|
44546
|
+
var crypto9;
|
|
44271
44547
|
try {
|
|
44272
|
-
|
|
44548
|
+
crypto9 = require("crypto");
|
|
44273
44549
|
} catch {
|
|
44274
44550
|
}
|
|
44275
44551
|
function establishWebSocketConnection(url, protocols, ws, onEstablish, options) {
|
|
@@ -44288,7 +44564,7 @@ var require_connection = __commonJS({
|
|
|
44288
44564
|
const headersList = new Headers(options.headers)[kHeadersList];
|
|
44289
44565
|
request.headersList = headersList;
|
|
44290
44566
|
}
|
|
44291
|
-
const keyValue =
|
|
44567
|
+
const keyValue = crypto9.randomBytes(16).toString("base64");
|
|
44292
44568
|
request.headersList.append("sec-websocket-key", keyValue);
|
|
44293
44569
|
request.headersList.append("sec-websocket-version", "13");
|
|
44294
44570
|
for (const protocol of protocols) {
|
|
@@ -44317,7 +44593,7 @@ var require_connection = __commonJS({
|
|
|
44317
44593
|
return;
|
|
44318
44594
|
}
|
|
44319
44595
|
const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
|
|
44320
|
-
const digest =
|
|
44596
|
+
const digest = crypto9.createHash("sha1").update(keyValue + uid).digest("base64");
|
|
44321
44597
|
if (secWSAccept !== digest) {
|
|
44322
44598
|
failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header.");
|
|
44323
44599
|
return;
|
|
@@ -44397,9 +44673,9 @@ var require_frame = __commonJS({
|
|
|
44397
44673
|
"node_modules/undici/lib/websocket/frame.js"(exports2, module2) {
|
|
44398
44674
|
"use strict";
|
|
44399
44675
|
var { maxUnsigned16Bit } = require_constants5();
|
|
44400
|
-
var
|
|
44676
|
+
var crypto9;
|
|
44401
44677
|
try {
|
|
44402
|
-
|
|
44678
|
+
crypto9 = require("crypto");
|
|
44403
44679
|
} catch {
|
|
44404
44680
|
}
|
|
44405
44681
|
var WebsocketFrameSend = class {
|
|
@@ -44408,7 +44684,7 @@ var require_frame = __commonJS({
|
|
|
44408
44684
|
*/
|
|
44409
44685
|
constructor(data) {
|
|
44410
44686
|
this.frameData = data;
|
|
44411
|
-
this.maskKey =
|
|
44687
|
+
this.maskKey = crypto9.randomBytes(4);
|
|
44412
44688
|
}
|
|
44413
44689
|
createFrame(opcode) {
|
|
44414
44690
|
const bodyLength = this.frameData?.byteLength ?? 0;
|
|
@@ -45150,11 +45426,11 @@ var require_undici = __commonJS({
|
|
|
45150
45426
|
if (typeof opts.path !== "string") {
|
|
45151
45427
|
throw new InvalidArgumentError("invalid opts.path");
|
|
45152
45428
|
}
|
|
45153
|
-
let
|
|
45429
|
+
let path33 = opts.path;
|
|
45154
45430
|
if (!opts.path.startsWith("/")) {
|
|
45155
|
-
|
|
45431
|
+
path33 = `/${path33}`;
|
|
45156
45432
|
}
|
|
45157
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
45433
|
+
url = new URL(util.parseOrigin(url).origin + path33);
|
|
45158
45434
|
} else {
|
|
45159
45435
|
if (!opts) {
|
|
45160
45436
|
opts = typeof url === "object" ? url : {};
|
|
@@ -45723,7 +45999,7 @@ var init_mcp_check_provider = __esm({
|
|
|
45723
45999
|
logger.warn(
|
|
45724
46000
|
`MCP ${transportName} failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`
|
|
45725
46001
|
);
|
|
45726
|
-
await new Promise((
|
|
46002
|
+
await new Promise((resolve19) => setTimeout(resolve19, delay));
|
|
45727
46003
|
attempt += 1;
|
|
45728
46004
|
} finally {
|
|
45729
46005
|
try {
|
|
@@ -46016,7 +46292,7 @@ async function acquirePromptLock() {
|
|
|
46016
46292
|
);
|
|
46017
46293
|
}, 1e4);
|
|
46018
46294
|
try {
|
|
46019
|
-
await new Promise((
|
|
46295
|
+
await new Promise((resolve19) => waiters.push(resolve19));
|
|
46020
46296
|
} finally {
|
|
46021
46297
|
clearInterval(reminder);
|
|
46022
46298
|
const waitedMs = Date.now() - queuedAt;
|
|
@@ -46035,7 +46311,7 @@ function releasePromptLock() {
|
|
|
46035
46311
|
}
|
|
46036
46312
|
async function interactivePrompt(options) {
|
|
46037
46313
|
await acquirePromptLock();
|
|
46038
|
-
return new Promise((
|
|
46314
|
+
return new Promise((resolve19, reject) => {
|
|
46039
46315
|
const dbg = process.env.VISOR_DEBUG === "true";
|
|
46040
46316
|
try {
|
|
46041
46317
|
if (dbg) {
|
|
@@ -46122,12 +46398,12 @@ async function interactivePrompt(options) {
|
|
|
46122
46398
|
};
|
|
46123
46399
|
const finish = (value) => {
|
|
46124
46400
|
cleanup();
|
|
46125
|
-
|
|
46401
|
+
resolve19(value);
|
|
46126
46402
|
};
|
|
46127
46403
|
if (options.timeout && options.timeout > 0) {
|
|
46128
46404
|
timeoutId = setTimeout(() => {
|
|
46129
46405
|
cleanup();
|
|
46130
|
-
if (defaultValue !== void 0) return
|
|
46406
|
+
if (defaultValue !== void 0) return resolve19(defaultValue);
|
|
46131
46407
|
return reject(new Error("Input timeout"));
|
|
46132
46408
|
}, options.timeout);
|
|
46133
46409
|
}
|
|
@@ -46259,7 +46535,7 @@ async function interactivePrompt(options) {
|
|
|
46259
46535
|
});
|
|
46260
46536
|
}
|
|
46261
46537
|
async function simplePrompt(prompt) {
|
|
46262
|
-
return new Promise((
|
|
46538
|
+
return new Promise((resolve19) => {
|
|
46263
46539
|
const rl = readline.createInterface({
|
|
46264
46540
|
input: process.stdin,
|
|
46265
46541
|
output: process.stdout
|
|
@@ -46275,7 +46551,7 @@ async function simplePrompt(prompt) {
|
|
|
46275
46551
|
rl.question(`${prompt}
|
|
46276
46552
|
> `, (answer) => {
|
|
46277
46553
|
rl.close();
|
|
46278
|
-
|
|
46554
|
+
resolve19(answer.trim());
|
|
46279
46555
|
});
|
|
46280
46556
|
});
|
|
46281
46557
|
}
|
|
@@ -46443,7 +46719,7 @@ function isStdinAvailable() {
|
|
|
46443
46719
|
return !process.stdin.isTTY;
|
|
46444
46720
|
}
|
|
46445
46721
|
async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
46446
|
-
return new Promise((
|
|
46722
|
+
return new Promise((resolve19, reject) => {
|
|
46447
46723
|
let data = "";
|
|
46448
46724
|
let timeoutId;
|
|
46449
46725
|
if (timeout) {
|
|
@@ -46470,7 +46746,7 @@ async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
|
46470
46746
|
};
|
|
46471
46747
|
const onEnd = () => {
|
|
46472
46748
|
cleanup();
|
|
46473
|
-
|
|
46749
|
+
resolve19(data.trim());
|
|
46474
46750
|
};
|
|
46475
46751
|
const onError = (err) => {
|
|
46476
46752
|
cleanup();
|
|
@@ -51170,23 +51446,23 @@ __export(renderer_schema_exports, {
|
|
|
51170
51446
|
});
|
|
51171
51447
|
async function loadRendererSchema(name) {
|
|
51172
51448
|
try {
|
|
51173
|
-
const
|
|
51174
|
-
const
|
|
51449
|
+
const fs29 = await import("fs/promises");
|
|
51450
|
+
const path33 = await import("path");
|
|
51175
51451
|
const sanitized = String(name).replace(/[^a-zA-Z0-9-]/g, "");
|
|
51176
51452
|
if (!sanitized) return void 0;
|
|
51177
51453
|
const candidates = [
|
|
51178
51454
|
// When bundled with ncc, __dirname is dist/ and output/ is at dist/output/
|
|
51179
|
-
|
|
51455
|
+
path33.join(__dirname, "output", sanitized, "schema.json"),
|
|
51180
51456
|
// When running from source, __dirname is src/state-machine/dispatch/ and output/ is at output/
|
|
51181
|
-
|
|
51457
|
+
path33.join(__dirname, "..", "..", "output", sanitized, "schema.json"),
|
|
51182
51458
|
// When running from a checkout with output/ folder copied to CWD
|
|
51183
|
-
|
|
51459
|
+
path33.join(process.cwd(), "output", sanitized, "schema.json"),
|
|
51184
51460
|
// Fallback: cwd/dist/output/
|
|
51185
|
-
|
|
51461
|
+
path33.join(process.cwd(), "dist", "output", sanitized, "schema.json")
|
|
51186
51462
|
];
|
|
51187
51463
|
for (const p of candidates) {
|
|
51188
51464
|
try {
|
|
51189
|
-
const raw = await
|
|
51465
|
+
const raw = await fs29.readFile(p, "utf-8");
|
|
51190
51466
|
return JSON.parse(raw);
|
|
51191
51467
|
} catch {
|
|
51192
51468
|
}
|
|
@@ -53631,8 +53907,8 @@ function updateStats2(results, state, isForEachIteration = false) {
|
|
|
53631
53907
|
async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
53632
53908
|
try {
|
|
53633
53909
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
53634
|
-
const
|
|
53635
|
-
const
|
|
53910
|
+
const fs29 = await import("fs/promises");
|
|
53911
|
+
const path33 = await import("path");
|
|
53636
53912
|
const schemaRaw = checkConfig.schema || "plain";
|
|
53637
53913
|
const schema = typeof schemaRaw === "string" && !schemaRaw.includes("{{") && !schemaRaw.includes("{%") ? schemaRaw : typeof schemaRaw === "object" ? "code-review" : "plain";
|
|
53638
53914
|
let templateContent;
|
|
@@ -53641,27 +53917,27 @@ async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
|
|
|
53641
53917
|
logger.debug(`[LevelDispatch] Using inline template for ${checkId}`);
|
|
53642
53918
|
} else if (checkConfig.template && checkConfig.template.file) {
|
|
53643
53919
|
const file = String(checkConfig.template.file);
|
|
53644
|
-
const resolved =
|
|
53645
|
-
templateContent = await
|
|
53920
|
+
const resolved = path33.resolve(process.cwd(), file);
|
|
53921
|
+
templateContent = await fs29.readFile(resolved, "utf-8");
|
|
53646
53922
|
logger.debug(`[LevelDispatch] Using template file for ${checkId}: ${resolved}`);
|
|
53647
53923
|
} else if (schema && schema !== "plain") {
|
|
53648
53924
|
const sanitized = String(schema).replace(/[^a-zA-Z0-9-]/g, "");
|
|
53649
53925
|
if (sanitized) {
|
|
53650
53926
|
const candidatePaths = [
|
|
53651
|
-
|
|
53927
|
+
path33.join(__dirname, "output", sanitized, "template.liquid"),
|
|
53652
53928
|
// bundled: dist/output/
|
|
53653
|
-
|
|
53929
|
+
path33.join(__dirname, "..", "..", "output", sanitized, "template.liquid"),
|
|
53654
53930
|
// source (from state-machine/states)
|
|
53655
|
-
|
|
53931
|
+
path33.join(__dirname, "..", "..", "..", "output", sanitized, "template.liquid"),
|
|
53656
53932
|
// source (alternate)
|
|
53657
|
-
|
|
53933
|
+
path33.join(process.cwd(), "output", sanitized, "template.liquid"),
|
|
53658
53934
|
// fallback: cwd/output/
|
|
53659
|
-
|
|
53935
|
+
path33.join(process.cwd(), "dist", "output", sanitized, "template.liquid")
|
|
53660
53936
|
// fallback: cwd/dist/output/
|
|
53661
53937
|
];
|
|
53662
53938
|
for (const p of candidatePaths) {
|
|
53663
53939
|
try {
|
|
53664
|
-
templateContent = await
|
|
53940
|
+
templateContent = await fs29.readFile(p, "utf-8");
|
|
53665
53941
|
if (templateContent) {
|
|
53666
53942
|
logger.debug(`[LevelDispatch] Using schema template for ${checkId}: ${p}`);
|
|
53667
53943
|
break;
|
|
@@ -55801,8 +56077,8 @@ var init_workspace_manager = __esm({
|
|
|
55801
56077
|
);
|
|
55802
56078
|
if (this.cleanupRequested && this.activeOperations === 0) {
|
|
55803
56079
|
logger.debug(`[Workspace] All references released, proceeding with deferred cleanup`);
|
|
55804
|
-
for (const
|
|
55805
|
-
|
|
56080
|
+
for (const resolve19 of this.cleanupResolvers) {
|
|
56081
|
+
resolve19();
|
|
55806
56082
|
}
|
|
55807
56083
|
this.cleanupResolvers = [];
|
|
55808
56084
|
}
|
|
@@ -55981,19 +56257,19 @@ var init_workspace_manager = __esm({
|
|
|
55981
56257
|
);
|
|
55982
56258
|
this.cleanupRequested = true;
|
|
55983
56259
|
await Promise.race([
|
|
55984
|
-
new Promise((
|
|
56260
|
+
new Promise((resolve19) => {
|
|
55985
56261
|
if (this.activeOperations === 0) {
|
|
55986
|
-
|
|
56262
|
+
resolve19();
|
|
55987
56263
|
} else {
|
|
55988
|
-
this.cleanupResolvers.push(
|
|
56264
|
+
this.cleanupResolvers.push(resolve19);
|
|
55989
56265
|
}
|
|
55990
56266
|
}),
|
|
55991
|
-
new Promise((
|
|
56267
|
+
new Promise((resolve19) => {
|
|
55992
56268
|
setTimeout(() => {
|
|
55993
56269
|
logger.warn(
|
|
55994
56270
|
`[Workspace] Cleanup timeout after ${timeout}ms, proceeding anyway (${this.activeOperations} operations still active)`
|
|
55995
56271
|
);
|
|
55996
|
-
|
|
56272
|
+
resolve19();
|
|
55997
56273
|
}, timeout);
|
|
55998
56274
|
})
|
|
55999
56275
|
]);
|
|
@@ -56387,8 +56663,8 @@ var init_fair_concurrency_limiter = __esm({
|
|
|
56387
56663
|
);
|
|
56388
56664
|
const queuedAt = Date.now();
|
|
56389
56665
|
const effectiveTimeout = queueTimeout ?? 12e4;
|
|
56390
|
-
return new Promise((
|
|
56391
|
-
const entry = { resolve:
|
|
56666
|
+
return new Promise((resolve19, reject) => {
|
|
56667
|
+
const entry = { resolve: resolve19, reject, queuedAt };
|
|
56392
56668
|
entry.reminder = setInterval(() => {
|
|
56393
56669
|
const waited = Math.round((Date.now() - queuedAt) / 1e3);
|
|
56394
56670
|
const curQueued = this._totalQueued();
|
|
@@ -56695,6 +56971,1380 @@ var init_build_engine_context = __esm({
|
|
|
56695
56971
|
}
|
|
56696
56972
|
});
|
|
56697
56973
|
|
|
56974
|
+
// src/policy/default-engine.ts
|
|
56975
|
+
var DefaultPolicyEngine;
|
|
56976
|
+
var init_default_engine = __esm({
|
|
56977
|
+
"src/policy/default-engine.ts"() {
|
|
56978
|
+
"use strict";
|
|
56979
|
+
DefaultPolicyEngine = class {
|
|
56980
|
+
async initialize(_config) {
|
|
56981
|
+
}
|
|
56982
|
+
async evaluateCheckExecution(_checkId, _checkConfig) {
|
|
56983
|
+
return { allowed: true };
|
|
56984
|
+
}
|
|
56985
|
+
async evaluateToolInvocation(_serverName, _methodName, _transport) {
|
|
56986
|
+
return { allowed: true };
|
|
56987
|
+
}
|
|
56988
|
+
async evaluateCapabilities(_checkId, _capabilities) {
|
|
56989
|
+
return { allowed: true };
|
|
56990
|
+
}
|
|
56991
|
+
async shutdown() {
|
|
56992
|
+
}
|
|
56993
|
+
};
|
|
56994
|
+
}
|
|
56995
|
+
});
|
|
56996
|
+
|
|
56997
|
+
// src/enterprise/license/validator.ts
|
|
56998
|
+
var validator_exports = {};
|
|
56999
|
+
__export(validator_exports, {
|
|
57000
|
+
LicenseValidator: () => LicenseValidator
|
|
57001
|
+
});
|
|
57002
|
+
var crypto3, fs21, path26, LicenseValidator;
|
|
57003
|
+
var init_validator = __esm({
|
|
57004
|
+
"src/enterprise/license/validator.ts"() {
|
|
57005
|
+
"use strict";
|
|
57006
|
+
crypto3 = __toESM(require("crypto"));
|
|
57007
|
+
fs21 = __toESM(require("fs"));
|
|
57008
|
+
path26 = __toESM(require("path"));
|
|
57009
|
+
LicenseValidator = class _LicenseValidator {
|
|
57010
|
+
/** Ed25519 public key for license verification (PEM format). */
|
|
57011
|
+
static PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAI/Zd08EFmgIdrDm/HXd0l3/5GBt7R1PrdvhdmEXhJlU=\n-----END PUBLIC KEY-----\n";
|
|
57012
|
+
cache = null;
|
|
57013
|
+
static CACHE_TTL = 5 * 60 * 1e3;
|
|
57014
|
+
// 5 minutes
|
|
57015
|
+
static GRACE_PERIOD = 72 * 3600 * 1e3;
|
|
57016
|
+
// 72 hours after expiry
|
|
57017
|
+
/**
|
|
57018
|
+
* Load and validate license from environment or file.
|
|
57019
|
+
*
|
|
57020
|
+
* Resolution order:
|
|
57021
|
+
* 1. VISOR_LICENSE env var (JWT string)
|
|
57022
|
+
* 2. VISOR_LICENSE_FILE env var (path to file)
|
|
57023
|
+
* 3. .visor-license in project root (cwd)
|
|
57024
|
+
* 4. .visor-license in ~/.config/visor/
|
|
57025
|
+
*/
|
|
57026
|
+
async loadAndValidate() {
|
|
57027
|
+
if (this.cache && Date.now() - this.cache.validatedAt < _LicenseValidator.CACHE_TTL) {
|
|
57028
|
+
return this.cache.payload;
|
|
57029
|
+
}
|
|
57030
|
+
const token = this.resolveToken();
|
|
57031
|
+
if (!token) return null;
|
|
57032
|
+
const payload = this.verifyAndDecode(token);
|
|
57033
|
+
if (!payload) return null;
|
|
57034
|
+
this.cache = { payload, validatedAt: Date.now() };
|
|
57035
|
+
return payload;
|
|
57036
|
+
}
|
|
57037
|
+
/** Check if a specific feature is licensed */
|
|
57038
|
+
hasFeature(feature) {
|
|
57039
|
+
if (!this.cache) return false;
|
|
57040
|
+
return this.cache.payload.features.includes(feature);
|
|
57041
|
+
}
|
|
57042
|
+
/** Check if license is valid (with grace period) */
|
|
57043
|
+
isValid() {
|
|
57044
|
+
if (!this.cache) return false;
|
|
57045
|
+
const now = Date.now();
|
|
57046
|
+
const expiryMs = this.cache.payload.exp * 1e3;
|
|
57047
|
+
return now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
57048
|
+
}
|
|
57049
|
+
/** Check if the license is within its grace period (expired but still valid) */
|
|
57050
|
+
isInGracePeriod() {
|
|
57051
|
+
if (!this.cache) return false;
|
|
57052
|
+
const now = Date.now();
|
|
57053
|
+
const expiryMs = this.cache.payload.exp * 1e3;
|
|
57054
|
+
return now >= expiryMs && now < expiryMs + _LicenseValidator.GRACE_PERIOD;
|
|
57055
|
+
}
|
|
57056
|
+
resolveToken() {
|
|
57057
|
+
if (process.env.VISOR_LICENSE) {
|
|
57058
|
+
return process.env.VISOR_LICENSE.trim();
|
|
57059
|
+
}
|
|
57060
|
+
if (process.env.VISOR_LICENSE_FILE) {
|
|
57061
|
+
const resolved = path26.resolve(process.env.VISOR_LICENSE_FILE);
|
|
57062
|
+
const home2 = process.env.HOME || process.env.USERPROFILE || "";
|
|
57063
|
+
const allowedPrefixes = [path26.normalize(process.cwd())];
|
|
57064
|
+
if (home2) allowedPrefixes.push(path26.normalize(path26.join(home2, ".config", "visor")));
|
|
57065
|
+
let realPath;
|
|
57066
|
+
try {
|
|
57067
|
+
realPath = fs21.realpathSync(resolved);
|
|
57068
|
+
} catch {
|
|
57069
|
+
return null;
|
|
57070
|
+
}
|
|
57071
|
+
const isSafe = allowedPrefixes.some(
|
|
57072
|
+
(prefix) => realPath === prefix || realPath.startsWith(prefix + path26.sep)
|
|
57073
|
+
);
|
|
57074
|
+
if (!isSafe) return null;
|
|
57075
|
+
return this.readFile(realPath);
|
|
57076
|
+
}
|
|
57077
|
+
const cwdPath = path26.join(process.cwd(), ".visor-license");
|
|
57078
|
+
const cwdToken = this.readFile(cwdPath);
|
|
57079
|
+
if (cwdToken) return cwdToken;
|
|
57080
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
57081
|
+
if (home) {
|
|
57082
|
+
const configPath = path26.join(home, ".config", "visor", ".visor-license");
|
|
57083
|
+
const configToken = this.readFile(configPath);
|
|
57084
|
+
if (configToken) return configToken;
|
|
57085
|
+
}
|
|
57086
|
+
return null;
|
|
57087
|
+
}
|
|
57088
|
+
readFile(filePath) {
|
|
57089
|
+
try {
|
|
57090
|
+
return fs21.readFileSync(filePath, "utf-8").trim();
|
|
57091
|
+
} catch {
|
|
57092
|
+
return null;
|
|
57093
|
+
}
|
|
57094
|
+
}
|
|
57095
|
+
verifyAndDecode(token) {
|
|
57096
|
+
try {
|
|
57097
|
+
const parts = token.split(".");
|
|
57098
|
+
if (parts.length !== 3) return null;
|
|
57099
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
57100
|
+
const header = JSON.parse(Buffer.from(headerB64, "base64url").toString());
|
|
57101
|
+
if (header.alg !== "EdDSA") return null;
|
|
57102
|
+
const data = `${headerB64}.${payloadB64}`;
|
|
57103
|
+
const signature = Buffer.from(signatureB64, "base64url");
|
|
57104
|
+
const publicKey = crypto3.createPublicKey(_LicenseValidator.PUBLIC_KEY);
|
|
57105
|
+
if (publicKey.asymmetricKeyType !== "ed25519") {
|
|
57106
|
+
return null;
|
|
57107
|
+
}
|
|
57108
|
+
const isValid = crypto3.verify(null, Buffer.from(data), publicKey, signature);
|
|
57109
|
+
if (!isValid) return null;
|
|
57110
|
+
const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
|
|
57111
|
+
if (!payload.org || !Array.isArray(payload.features) || typeof payload.exp !== "number" || typeof payload.iat !== "number" || !payload.sub) {
|
|
57112
|
+
return null;
|
|
57113
|
+
}
|
|
57114
|
+
const now = Date.now();
|
|
57115
|
+
const expiryMs = payload.exp * 1e3;
|
|
57116
|
+
if (now >= expiryMs + _LicenseValidator.GRACE_PERIOD) {
|
|
57117
|
+
return null;
|
|
57118
|
+
}
|
|
57119
|
+
return payload;
|
|
57120
|
+
} catch {
|
|
57121
|
+
return null;
|
|
57122
|
+
}
|
|
57123
|
+
}
|
|
57124
|
+
};
|
|
57125
|
+
}
|
|
57126
|
+
});
|
|
57127
|
+
|
|
57128
|
+
// src/enterprise/policy/opa-compiler.ts
|
|
57129
|
+
var fs22, path27, os2, crypto4, import_child_process8, OpaCompiler;
|
|
57130
|
+
var init_opa_compiler = __esm({
|
|
57131
|
+
"src/enterprise/policy/opa-compiler.ts"() {
|
|
57132
|
+
"use strict";
|
|
57133
|
+
fs22 = __toESM(require("fs"));
|
|
57134
|
+
path27 = __toESM(require("path"));
|
|
57135
|
+
os2 = __toESM(require("os"));
|
|
57136
|
+
crypto4 = __toESM(require("crypto"));
|
|
57137
|
+
import_child_process8 = require("child_process");
|
|
57138
|
+
OpaCompiler = class _OpaCompiler {
|
|
57139
|
+
static CACHE_DIR = path27.join(os2.tmpdir(), "visor-opa-cache");
|
|
57140
|
+
/**
|
|
57141
|
+
* Resolve the input paths to WASM bytes.
|
|
57142
|
+
*
|
|
57143
|
+
* Strategy:
|
|
57144
|
+
* 1. If any path is a .wasm file, read it directly
|
|
57145
|
+
* 2. If a directory contains policy.wasm, read it
|
|
57146
|
+
* 3. Otherwise, collect all .rego files and auto-compile via `opa build`
|
|
57147
|
+
*/
|
|
57148
|
+
async resolveWasmBytes(paths) {
|
|
57149
|
+
const regoFiles = [];
|
|
57150
|
+
for (const p of paths) {
|
|
57151
|
+
const resolved = path27.resolve(p);
|
|
57152
|
+
if (path27.normalize(resolved).includes("..")) {
|
|
57153
|
+
throw new Error(`Policy path contains traversal sequences: ${p}`);
|
|
57154
|
+
}
|
|
57155
|
+
if (resolved.endsWith(".wasm") && fs22.existsSync(resolved)) {
|
|
57156
|
+
return fs22.readFileSync(resolved);
|
|
57157
|
+
}
|
|
57158
|
+
if (!fs22.existsSync(resolved)) continue;
|
|
57159
|
+
const stat2 = fs22.statSync(resolved);
|
|
57160
|
+
if (stat2.isDirectory()) {
|
|
57161
|
+
const wasmCandidate = path27.join(resolved, "policy.wasm");
|
|
57162
|
+
if (fs22.existsSync(wasmCandidate)) {
|
|
57163
|
+
return fs22.readFileSync(wasmCandidate);
|
|
57164
|
+
}
|
|
57165
|
+
const files = fs22.readdirSync(resolved);
|
|
57166
|
+
for (const f of files) {
|
|
57167
|
+
if (f.endsWith(".rego")) {
|
|
57168
|
+
regoFiles.push(path27.join(resolved, f));
|
|
57169
|
+
}
|
|
57170
|
+
}
|
|
57171
|
+
} else if (resolved.endsWith(".rego")) {
|
|
57172
|
+
regoFiles.push(resolved);
|
|
57173
|
+
}
|
|
57174
|
+
}
|
|
57175
|
+
if (regoFiles.length === 0) {
|
|
57176
|
+
throw new Error(
|
|
57177
|
+
`OPA WASM evaluator: no .wasm bundle or .rego files found in: ${paths.join(", ")}`
|
|
57178
|
+
);
|
|
57179
|
+
}
|
|
57180
|
+
return this.compileRego(regoFiles);
|
|
57181
|
+
}
|
|
57182
|
+
/**
|
|
57183
|
+
* Auto-compile .rego files to a WASM bundle using the `opa` CLI.
|
|
57184
|
+
*
|
|
57185
|
+
* Caches the compiled bundle based on a content hash of all input .rego files
|
|
57186
|
+
* so subsequent runs skip compilation if policies haven't changed.
|
|
57187
|
+
*/
|
|
57188
|
+
compileRego(regoFiles) {
|
|
57189
|
+
try {
|
|
57190
|
+
(0, import_child_process8.execFileSync)("opa", ["version"], { stdio: "pipe" });
|
|
57191
|
+
} catch {
|
|
57192
|
+
throw new Error(
|
|
57193
|
+
"OPA CLI (`opa`) not found on PATH. Install it from https://www.openpolicyagent.org/docs/latest/#running-opa\nOr pre-compile your .rego files: opa build -t wasm -e visor -o bundle.tar.gz " + regoFiles.join(" ")
|
|
57194
|
+
);
|
|
57195
|
+
}
|
|
57196
|
+
const hash = crypto4.createHash("sha256");
|
|
57197
|
+
for (const f of regoFiles.sort()) {
|
|
57198
|
+
hash.update(fs22.readFileSync(f));
|
|
57199
|
+
hash.update(f);
|
|
57200
|
+
}
|
|
57201
|
+
const cacheKey = hash.digest("hex").slice(0, 16);
|
|
57202
|
+
const cacheDir = _OpaCompiler.CACHE_DIR;
|
|
57203
|
+
const cachedWasm = path27.join(cacheDir, `${cacheKey}.wasm`);
|
|
57204
|
+
if (fs22.existsSync(cachedWasm)) {
|
|
57205
|
+
return fs22.readFileSync(cachedWasm);
|
|
57206
|
+
}
|
|
57207
|
+
fs22.mkdirSync(cacheDir, { recursive: true });
|
|
57208
|
+
const bundleTar = path27.join(cacheDir, `${cacheKey}-bundle.tar.gz`);
|
|
57209
|
+
try {
|
|
57210
|
+
const args = [
|
|
57211
|
+
"build",
|
|
57212
|
+
"-t",
|
|
57213
|
+
"wasm",
|
|
57214
|
+
"-e",
|
|
57215
|
+
"visor",
|
|
57216
|
+
// entrypoint: the visor package tree
|
|
57217
|
+
"-o",
|
|
57218
|
+
bundleTar,
|
|
57219
|
+
...regoFiles
|
|
57220
|
+
];
|
|
57221
|
+
(0, import_child_process8.execFileSync)("opa", args, {
|
|
57222
|
+
stdio: "pipe",
|
|
57223
|
+
timeout: 3e4
|
|
57224
|
+
});
|
|
57225
|
+
} catch (err) {
|
|
57226
|
+
const stderr = err?.stderr?.toString() || "";
|
|
57227
|
+
throw new Error(
|
|
57228
|
+
`Failed to compile .rego files to WASM:
|
|
57229
|
+
${stderr}
|
|
57230
|
+
Ensure your .rego files are valid and the \`opa\` CLI is installed.`
|
|
57231
|
+
);
|
|
57232
|
+
}
|
|
57233
|
+
try {
|
|
57234
|
+
(0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "/policy.wasm"], {
|
|
57235
|
+
stdio: "pipe"
|
|
57236
|
+
});
|
|
57237
|
+
const extractedWasm = path27.join(cacheDir, "policy.wasm");
|
|
57238
|
+
if (fs22.existsSync(extractedWasm)) {
|
|
57239
|
+
fs22.renameSync(extractedWasm, cachedWasm);
|
|
57240
|
+
}
|
|
57241
|
+
} catch {
|
|
57242
|
+
try {
|
|
57243
|
+
(0, import_child_process8.execFileSync)("tar", ["-xzf", bundleTar, "-C", cacheDir, "policy.wasm"], {
|
|
57244
|
+
stdio: "pipe"
|
|
57245
|
+
});
|
|
57246
|
+
const extractedWasm = path27.join(cacheDir, "policy.wasm");
|
|
57247
|
+
if (fs22.existsSync(extractedWasm)) {
|
|
57248
|
+
fs22.renameSync(extractedWasm, cachedWasm);
|
|
57249
|
+
}
|
|
57250
|
+
} catch (err2) {
|
|
57251
|
+
throw new Error(`Failed to extract policy.wasm from OPA bundle: ${err2?.message || err2}`);
|
|
57252
|
+
}
|
|
57253
|
+
}
|
|
57254
|
+
try {
|
|
57255
|
+
fs22.unlinkSync(bundleTar);
|
|
57256
|
+
} catch {
|
|
57257
|
+
}
|
|
57258
|
+
if (!fs22.existsSync(cachedWasm)) {
|
|
57259
|
+
throw new Error("OPA build succeeded but policy.wasm was not found in the bundle");
|
|
57260
|
+
}
|
|
57261
|
+
return fs22.readFileSync(cachedWasm);
|
|
57262
|
+
}
|
|
57263
|
+
};
|
|
57264
|
+
}
|
|
57265
|
+
});
|
|
57266
|
+
|
|
57267
|
+
// src/enterprise/policy/opa-wasm-evaluator.ts
|
|
57268
|
+
var fs23, path28, OpaWasmEvaluator;
|
|
57269
|
+
var init_opa_wasm_evaluator = __esm({
|
|
57270
|
+
"src/enterprise/policy/opa-wasm-evaluator.ts"() {
|
|
57271
|
+
"use strict";
|
|
57272
|
+
fs23 = __toESM(require("fs"));
|
|
57273
|
+
path28 = __toESM(require("path"));
|
|
57274
|
+
init_opa_compiler();
|
|
57275
|
+
OpaWasmEvaluator = class {
|
|
57276
|
+
policy = null;
|
|
57277
|
+
dataDocument = {};
|
|
57278
|
+
compiler = new OpaCompiler();
|
|
57279
|
+
async initialize(rulesPath) {
|
|
57280
|
+
const paths = Array.isArray(rulesPath) ? rulesPath : [rulesPath];
|
|
57281
|
+
const wasmBytes = await this.compiler.resolveWasmBytes(paths);
|
|
57282
|
+
try {
|
|
57283
|
+
const { createRequire } = require("module");
|
|
57284
|
+
const runtimeRequire = createRequire(__filename);
|
|
57285
|
+
const opaWasm = runtimeRequire("@open-policy-agent/opa-wasm");
|
|
57286
|
+
const loadPolicy = opaWasm.loadPolicy || opaWasm.default?.loadPolicy;
|
|
57287
|
+
if (!loadPolicy) {
|
|
57288
|
+
throw new Error("loadPolicy not found in @open-policy-agent/opa-wasm");
|
|
57289
|
+
}
|
|
57290
|
+
this.policy = await loadPolicy(wasmBytes);
|
|
57291
|
+
} catch (err) {
|
|
57292
|
+
if (err?.code === "MODULE_NOT_FOUND" || err?.code === "ERR_MODULE_NOT_FOUND") {
|
|
57293
|
+
throw new Error(
|
|
57294
|
+
"OPA WASM evaluator requires @open-policy-agent/opa-wasm. Install it with: npm install @open-policy-agent/opa-wasm"
|
|
57295
|
+
);
|
|
57296
|
+
}
|
|
57297
|
+
throw err;
|
|
57298
|
+
}
|
|
57299
|
+
}
|
|
57300
|
+
/**
|
|
57301
|
+
* Load external data from a JSON file to use as the OPA data document.
|
|
57302
|
+
* The loaded data will be passed to `policy.setData()` during evaluation,
|
|
57303
|
+
* making it available in Rego via `data.<key>`.
|
|
57304
|
+
*/
|
|
57305
|
+
loadData(dataPath) {
|
|
57306
|
+
const resolved = path28.resolve(dataPath);
|
|
57307
|
+
if (path28.normalize(resolved).includes("..")) {
|
|
57308
|
+
throw new Error(`Data path contains traversal sequences: ${dataPath}`);
|
|
57309
|
+
}
|
|
57310
|
+
if (!fs23.existsSync(resolved)) {
|
|
57311
|
+
throw new Error(`OPA data file not found: ${resolved}`);
|
|
57312
|
+
}
|
|
57313
|
+
const stat2 = fs23.statSync(resolved);
|
|
57314
|
+
if (stat2.size > 10 * 1024 * 1024) {
|
|
57315
|
+
throw new Error(`OPA data file exceeds 10MB limit: ${resolved} (${stat2.size} bytes)`);
|
|
57316
|
+
}
|
|
57317
|
+
const raw = fs23.readFileSync(resolved, "utf-8");
|
|
57318
|
+
try {
|
|
57319
|
+
const parsed = JSON.parse(raw);
|
|
57320
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
57321
|
+
throw new Error("OPA data file must contain a JSON object (not an array or primitive)");
|
|
57322
|
+
}
|
|
57323
|
+
this.dataDocument = parsed;
|
|
57324
|
+
} catch (err) {
|
|
57325
|
+
if (err.message.startsWith("OPA data file must")) {
|
|
57326
|
+
throw err;
|
|
57327
|
+
}
|
|
57328
|
+
throw new Error(`Failed to parse OPA data file ${resolved}: ${err.message}`);
|
|
57329
|
+
}
|
|
57330
|
+
}
|
|
57331
|
+
async evaluate(input) {
|
|
57332
|
+
if (!this.policy) {
|
|
57333
|
+
throw new Error("OPA WASM evaluator not initialized");
|
|
57334
|
+
}
|
|
57335
|
+
this.policy.setData(this.dataDocument);
|
|
57336
|
+
const resultSet = this.policy.evaluate(input);
|
|
57337
|
+
if (Array.isArray(resultSet) && resultSet.length > 0) {
|
|
57338
|
+
return resultSet[0].result;
|
|
57339
|
+
}
|
|
57340
|
+
return void 0;
|
|
57341
|
+
}
|
|
57342
|
+
async shutdown() {
|
|
57343
|
+
if (this.policy) {
|
|
57344
|
+
if (typeof this.policy.close === "function") {
|
|
57345
|
+
try {
|
|
57346
|
+
this.policy.close();
|
|
57347
|
+
} catch {
|
|
57348
|
+
}
|
|
57349
|
+
} else if (typeof this.policy.free === "function") {
|
|
57350
|
+
try {
|
|
57351
|
+
this.policy.free();
|
|
57352
|
+
} catch {
|
|
57353
|
+
}
|
|
57354
|
+
}
|
|
57355
|
+
}
|
|
57356
|
+
this.policy = null;
|
|
57357
|
+
}
|
|
57358
|
+
};
|
|
57359
|
+
}
|
|
57360
|
+
});
|
|
57361
|
+
|
|
57362
|
+
// src/enterprise/policy/opa-http-evaluator.ts
|
|
57363
|
+
var OpaHttpEvaluator;
|
|
57364
|
+
var init_opa_http_evaluator = __esm({
|
|
57365
|
+
"src/enterprise/policy/opa-http-evaluator.ts"() {
|
|
57366
|
+
"use strict";
|
|
57367
|
+
OpaHttpEvaluator = class {
|
|
57368
|
+
baseUrl;
|
|
57369
|
+
timeout;
|
|
57370
|
+
constructor(baseUrl, timeout = 5e3) {
|
|
57371
|
+
let parsed;
|
|
57372
|
+
try {
|
|
57373
|
+
parsed = new URL(baseUrl);
|
|
57374
|
+
} catch {
|
|
57375
|
+
throw new Error(`OPA HTTP evaluator: invalid URL: ${baseUrl}`);
|
|
57376
|
+
}
|
|
57377
|
+
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
57378
|
+
throw new Error(
|
|
57379
|
+
`OPA HTTP evaluator: url must use http:// or https:// protocol, got: ${baseUrl}`
|
|
57380
|
+
);
|
|
57381
|
+
}
|
|
57382
|
+
const hostname = parsed.hostname;
|
|
57383
|
+
if (this.isBlockedHostname(hostname)) {
|
|
57384
|
+
throw new Error(
|
|
57385
|
+
`OPA HTTP evaluator: url must not point to internal, loopback, or private network addresses`
|
|
57386
|
+
);
|
|
57387
|
+
}
|
|
57388
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
57389
|
+
this.timeout = timeout;
|
|
57390
|
+
}
|
|
57391
|
+
/**
|
|
57392
|
+
* Check if a hostname is blocked due to SSRF concerns.
|
|
57393
|
+
*
|
|
57394
|
+
* Blocks:
|
|
57395
|
+
* - Loopback addresses (127.x.x.x, localhost, 0.0.0.0, ::1)
|
|
57396
|
+
* - Link-local addresses (169.254.x.x)
|
|
57397
|
+
* - Private networks (10.x.x.x, 172.16-31.x.x, 192.168.x.x)
|
|
57398
|
+
* - IPv6 unique local addresses (fd00::/8)
|
|
57399
|
+
* - Cloud metadata services (*.internal)
|
|
57400
|
+
*/
|
|
57401
|
+
isBlockedHostname(hostname) {
|
|
57402
|
+
if (!hostname) return true;
|
|
57403
|
+
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
57404
|
+
if (normalized === "metadata.google.internal" || normalized.endsWith(".internal")) {
|
|
57405
|
+
return true;
|
|
57406
|
+
}
|
|
57407
|
+
if (normalized === "localhost" || normalized === "localhost.localdomain") {
|
|
57408
|
+
return true;
|
|
57409
|
+
}
|
|
57410
|
+
if (normalized === "::1" || normalized === "0:0:0:0:0:0:0:1") {
|
|
57411
|
+
return true;
|
|
57412
|
+
}
|
|
57413
|
+
const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
57414
|
+
const ipv4Match = normalized.match(ipv4Pattern);
|
|
57415
|
+
if (ipv4Match) {
|
|
57416
|
+
const octets = ipv4Match.slice(1, 5).map(Number);
|
|
57417
|
+
if (octets.some((octet) => octet > 255)) {
|
|
57418
|
+
return false;
|
|
57419
|
+
}
|
|
57420
|
+
const [a, b] = octets;
|
|
57421
|
+
if (a === 127) {
|
|
57422
|
+
return true;
|
|
57423
|
+
}
|
|
57424
|
+
if (a === 0) {
|
|
57425
|
+
return true;
|
|
57426
|
+
}
|
|
57427
|
+
if (a === 169 && b === 254) {
|
|
57428
|
+
return true;
|
|
57429
|
+
}
|
|
57430
|
+
if (a === 10) {
|
|
57431
|
+
return true;
|
|
57432
|
+
}
|
|
57433
|
+
if (a === 172 && b >= 16 && b <= 31) {
|
|
57434
|
+
return true;
|
|
57435
|
+
}
|
|
57436
|
+
if (a === 192 && b === 168) {
|
|
57437
|
+
return true;
|
|
57438
|
+
}
|
|
57439
|
+
}
|
|
57440
|
+
if (normalized.startsWith("fd") || normalized.startsWith("fc")) {
|
|
57441
|
+
return true;
|
|
57442
|
+
}
|
|
57443
|
+
if (normalized.startsWith("fe80:")) {
|
|
57444
|
+
return true;
|
|
57445
|
+
}
|
|
57446
|
+
return false;
|
|
57447
|
+
}
|
|
57448
|
+
/**
|
|
57449
|
+
* Evaluate a policy rule against an input document via OPA REST API.
|
|
57450
|
+
*
|
|
57451
|
+
* @param input - The input document to evaluate
|
|
57452
|
+
* @param rulePath - OPA rule path (e.g., 'visor/check/execute')
|
|
57453
|
+
* @returns The result object from OPA, or undefined on error
|
|
57454
|
+
*/
|
|
57455
|
+
async evaluate(input, rulePath) {
|
|
57456
|
+
const encodedPath = rulePath.split("/").map((s) => encodeURIComponent(s)).join("/");
|
|
57457
|
+
const url = `${this.baseUrl}/v1/data/${encodedPath}`;
|
|
57458
|
+
const controller = new AbortController();
|
|
57459
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
57460
|
+
try {
|
|
57461
|
+
const response = await fetch(url, {
|
|
57462
|
+
method: "POST",
|
|
57463
|
+
headers: { "Content-Type": "application/json" },
|
|
57464
|
+
body: JSON.stringify({ input }),
|
|
57465
|
+
signal: controller.signal
|
|
57466
|
+
});
|
|
57467
|
+
if (!response.ok) {
|
|
57468
|
+
throw new Error(`OPA HTTP ${response.status}: ${response.statusText}`);
|
|
57469
|
+
}
|
|
57470
|
+
let body;
|
|
57471
|
+
try {
|
|
57472
|
+
body = await response.json();
|
|
57473
|
+
} catch (jsonErr) {
|
|
57474
|
+
throw new Error(
|
|
57475
|
+
`OPA HTTP evaluator: failed to parse JSON response: ${jsonErr instanceof Error ? jsonErr.message : String(jsonErr)}`
|
|
57476
|
+
);
|
|
57477
|
+
}
|
|
57478
|
+
return body?.result;
|
|
57479
|
+
} finally {
|
|
57480
|
+
clearTimeout(timer);
|
|
57481
|
+
}
|
|
57482
|
+
}
|
|
57483
|
+
async shutdown() {
|
|
57484
|
+
}
|
|
57485
|
+
};
|
|
57486
|
+
}
|
|
57487
|
+
});
|
|
57488
|
+
|
|
57489
|
+
// src/enterprise/policy/policy-input-builder.ts
|
|
57490
|
+
var PolicyInputBuilder;
|
|
57491
|
+
var init_policy_input_builder = __esm({
|
|
57492
|
+
"src/enterprise/policy/policy-input-builder.ts"() {
|
|
57493
|
+
"use strict";
|
|
57494
|
+
PolicyInputBuilder = class {
|
|
57495
|
+
roles;
|
|
57496
|
+
actor;
|
|
57497
|
+
repository;
|
|
57498
|
+
pullRequest;
|
|
57499
|
+
constructor(policyConfig, actor, repository, pullRequest) {
|
|
57500
|
+
this.roles = policyConfig.roles || {};
|
|
57501
|
+
this.actor = actor;
|
|
57502
|
+
this.repository = repository;
|
|
57503
|
+
this.pullRequest = pullRequest;
|
|
57504
|
+
}
|
|
57505
|
+
/** Resolve which roles apply to the current actor. */
|
|
57506
|
+
resolveRoles() {
|
|
57507
|
+
const matched = [];
|
|
57508
|
+
for (const [roleName, roleConfig] of Object.entries(this.roles)) {
|
|
57509
|
+
let identityMatch = false;
|
|
57510
|
+
if (roleConfig.author_association && this.actor.authorAssociation && roleConfig.author_association.includes(this.actor.authorAssociation)) {
|
|
57511
|
+
identityMatch = true;
|
|
57512
|
+
}
|
|
57513
|
+
if (!identityMatch && roleConfig.users && this.actor.login && roleConfig.users.includes(this.actor.login)) {
|
|
57514
|
+
identityMatch = true;
|
|
57515
|
+
}
|
|
57516
|
+
if (!identityMatch && roleConfig.slack_users && this.actor.slack?.userId && roleConfig.slack_users.includes(this.actor.slack.userId)) {
|
|
57517
|
+
identityMatch = true;
|
|
57518
|
+
}
|
|
57519
|
+
if (!identityMatch && roleConfig.emails && this.actor.slack?.email) {
|
|
57520
|
+
const actorEmail = this.actor.slack.email.toLowerCase();
|
|
57521
|
+
if (roleConfig.emails.some((e) => e.toLowerCase() === actorEmail)) {
|
|
57522
|
+
identityMatch = true;
|
|
57523
|
+
}
|
|
57524
|
+
}
|
|
57525
|
+
if (!identityMatch) continue;
|
|
57526
|
+
if (roleConfig.slack_channels && roleConfig.slack_channels.length > 0) {
|
|
57527
|
+
if (!this.actor.slack?.channelId || !roleConfig.slack_channels.includes(this.actor.slack.channelId)) {
|
|
57528
|
+
continue;
|
|
57529
|
+
}
|
|
57530
|
+
}
|
|
57531
|
+
matched.push(roleName);
|
|
57532
|
+
}
|
|
57533
|
+
return matched;
|
|
57534
|
+
}
|
|
57535
|
+
buildActor() {
|
|
57536
|
+
return {
|
|
57537
|
+
authorAssociation: this.actor.authorAssociation,
|
|
57538
|
+
login: this.actor.login,
|
|
57539
|
+
roles: this.resolveRoles(),
|
|
57540
|
+
isLocalMode: this.actor.isLocalMode,
|
|
57541
|
+
...this.actor.slack && { slack: this.actor.slack }
|
|
57542
|
+
};
|
|
57543
|
+
}
|
|
57544
|
+
forCheckExecution(check) {
|
|
57545
|
+
return {
|
|
57546
|
+
scope: "check.execute",
|
|
57547
|
+
check: {
|
|
57548
|
+
id: check.id,
|
|
57549
|
+
type: check.type,
|
|
57550
|
+
group: check.group,
|
|
57551
|
+
tags: check.tags,
|
|
57552
|
+
criticality: check.criticality,
|
|
57553
|
+
sandbox: check.sandbox,
|
|
57554
|
+
policy: check.policy
|
|
57555
|
+
},
|
|
57556
|
+
actor: this.buildActor(),
|
|
57557
|
+
repository: this.repository,
|
|
57558
|
+
pullRequest: this.pullRequest
|
|
57559
|
+
};
|
|
57560
|
+
}
|
|
57561
|
+
forToolInvocation(serverName, methodName, transport) {
|
|
57562
|
+
return {
|
|
57563
|
+
scope: "tool.invoke",
|
|
57564
|
+
tool: { serverName, methodName, transport },
|
|
57565
|
+
actor: this.buildActor(),
|
|
57566
|
+
repository: this.repository,
|
|
57567
|
+
pullRequest: this.pullRequest
|
|
57568
|
+
};
|
|
57569
|
+
}
|
|
57570
|
+
forCapabilityResolve(checkId, capabilities) {
|
|
57571
|
+
return {
|
|
57572
|
+
scope: "capability.resolve",
|
|
57573
|
+
check: { id: checkId, type: "ai" },
|
|
57574
|
+
capability: capabilities,
|
|
57575
|
+
actor: this.buildActor(),
|
|
57576
|
+
repository: this.repository,
|
|
57577
|
+
pullRequest: this.pullRequest
|
|
57578
|
+
};
|
|
57579
|
+
}
|
|
57580
|
+
};
|
|
57581
|
+
}
|
|
57582
|
+
});
|
|
57583
|
+
|
|
57584
|
+
// src/enterprise/policy/opa-policy-engine.ts
|
|
57585
|
+
var opa_policy_engine_exports = {};
|
|
57586
|
+
__export(opa_policy_engine_exports, {
|
|
57587
|
+
OpaPolicyEngine: () => OpaPolicyEngine
|
|
57588
|
+
});
|
|
57589
|
+
var OpaPolicyEngine;
|
|
57590
|
+
var init_opa_policy_engine = __esm({
|
|
57591
|
+
"src/enterprise/policy/opa-policy-engine.ts"() {
|
|
57592
|
+
"use strict";
|
|
57593
|
+
init_opa_wasm_evaluator();
|
|
57594
|
+
init_opa_http_evaluator();
|
|
57595
|
+
init_policy_input_builder();
|
|
57596
|
+
OpaPolicyEngine = class {
|
|
57597
|
+
evaluator = null;
|
|
57598
|
+
fallback;
|
|
57599
|
+
timeout;
|
|
57600
|
+
config;
|
|
57601
|
+
inputBuilder = null;
|
|
57602
|
+
logger = null;
|
|
57603
|
+
constructor(config) {
|
|
57604
|
+
this.config = config;
|
|
57605
|
+
this.fallback = config.fallback || "deny";
|
|
57606
|
+
this.timeout = config.timeout || 5e3;
|
|
57607
|
+
}
|
|
57608
|
+
async initialize(config) {
|
|
57609
|
+
try {
|
|
57610
|
+
this.logger = (init_logger(), __toCommonJS(logger_exports)).logger;
|
|
57611
|
+
} catch {
|
|
57612
|
+
}
|
|
57613
|
+
const actor = {
|
|
57614
|
+
authorAssociation: process.env.VISOR_AUTHOR_ASSOCIATION,
|
|
57615
|
+
login: process.env.VISOR_AUTHOR_LOGIN || process.env.GITHUB_ACTOR,
|
|
57616
|
+
isLocalMode: !process.env.GITHUB_ACTIONS
|
|
57617
|
+
};
|
|
57618
|
+
const repo = {
|
|
57619
|
+
owner: process.env.GITHUB_REPOSITORY_OWNER,
|
|
57620
|
+
name: process.env.GITHUB_REPOSITORY?.split("/")[1],
|
|
57621
|
+
branch: process.env.GITHUB_HEAD_REF,
|
|
57622
|
+
baseBranch: process.env.GITHUB_BASE_REF,
|
|
57623
|
+
event: process.env.GITHUB_EVENT_NAME
|
|
57624
|
+
};
|
|
57625
|
+
const prNum = process.env.GITHUB_PR_NUMBER ? parseInt(process.env.GITHUB_PR_NUMBER, 10) : void 0;
|
|
57626
|
+
const pullRequest = {
|
|
57627
|
+
number: prNum !== void 0 && Number.isFinite(prNum) ? prNum : void 0
|
|
57628
|
+
};
|
|
57629
|
+
this.inputBuilder = new PolicyInputBuilder(config, actor, repo, pullRequest);
|
|
57630
|
+
if (config.engine === "local") {
|
|
57631
|
+
if (!config.rules) {
|
|
57632
|
+
throw new Error("OPA local mode requires `policy.rules` path to .wasm or .rego files");
|
|
57633
|
+
}
|
|
57634
|
+
const wasm = new OpaWasmEvaluator();
|
|
57635
|
+
await wasm.initialize(config.rules);
|
|
57636
|
+
if (config.data) {
|
|
57637
|
+
wasm.loadData(config.data);
|
|
57638
|
+
}
|
|
57639
|
+
this.evaluator = wasm;
|
|
57640
|
+
} else if (config.engine === "remote") {
|
|
57641
|
+
if (!config.url) {
|
|
57642
|
+
throw new Error("OPA remote mode requires `policy.url` pointing to OPA server");
|
|
57643
|
+
}
|
|
57644
|
+
this.evaluator = new OpaHttpEvaluator(config.url, this.timeout);
|
|
57645
|
+
} else {
|
|
57646
|
+
this.evaluator = null;
|
|
57647
|
+
}
|
|
57648
|
+
}
|
|
57649
|
+
/**
|
|
57650
|
+
* Update actor/repo/PR context (e.g., after PR info becomes available).
|
|
57651
|
+
* Called by the enterprise loader when engine context is enriched.
|
|
57652
|
+
*/
|
|
57653
|
+
setActorContext(actor, repo, pullRequest) {
|
|
57654
|
+
this.inputBuilder = new PolicyInputBuilder(this.config, actor, repo, pullRequest);
|
|
57655
|
+
}
|
|
57656
|
+
async evaluateCheckExecution(checkId, checkConfig) {
|
|
57657
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
57658
|
+
const cfg = checkConfig && typeof checkConfig === "object" ? checkConfig : {};
|
|
57659
|
+
const policyOverride = cfg.policy;
|
|
57660
|
+
const input = this.inputBuilder.forCheckExecution({
|
|
57661
|
+
id: checkId,
|
|
57662
|
+
type: cfg.type || "ai",
|
|
57663
|
+
group: cfg.group,
|
|
57664
|
+
tags: cfg.tags,
|
|
57665
|
+
criticality: cfg.criticality,
|
|
57666
|
+
sandbox: cfg.sandbox,
|
|
57667
|
+
policy: policyOverride
|
|
57668
|
+
});
|
|
57669
|
+
return this.doEvaluate(input, this.resolveRulePath("check.execute", policyOverride?.rule));
|
|
57670
|
+
}
|
|
57671
|
+
async evaluateToolInvocation(serverName, methodName, transport) {
|
|
57672
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
57673
|
+
const input = this.inputBuilder.forToolInvocation(serverName, methodName, transport);
|
|
57674
|
+
return this.doEvaluate(input, "visor/tool/invoke");
|
|
57675
|
+
}
|
|
57676
|
+
async evaluateCapabilities(checkId, capabilities) {
|
|
57677
|
+
if (!this.evaluator || !this.inputBuilder) return { allowed: true };
|
|
57678
|
+
const input = this.inputBuilder.forCapabilityResolve(checkId, capabilities);
|
|
57679
|
+
return this.doEvaluate(input, "visor/capability/resolve");
|
|
57680
|
+
}
|
|
57681
|
+
async shutdown() {
|
|
57682
|
+
if (this.evaluator && "shutdown" in this.evaluator) {
|
|
57683
|
+
await this.evaluator.shutdown();
|
|
57684
|
+
}
|
|
57685
|
+
this.evaluator = null;
|
|
57686
|
+
this.inputBuilder = null;
|
|
57687
|
+
}
|
|
57688
|
+
resolveRulePath(defaultScope, override) {
|
|
57689
|
+
if (override) {
|
|
57690
|
+
return override.startsWith("visor/") ? override : `visor/${override}`;
|
|
57691
|
+
}
|
|
57692
|
+
return `visor/${defaultScope.replace(/\./g, "/")}`;
|
|
57693
|
+
}
|
|
57694
|
+
async doEvaluate(input, rulePath) {
|
|
57695
|
+
try {
|
|
57696
|
+
this.logger?.debug(`[PolicyEngine] Evaluating ${rulePath}`, JSON.stringify(input));
|
|
57697
|
+
let timer;
|
|
57698
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
57699
|
+
timer = setTimeout(() => reject(new Error("policy evaluation timeout")), this.timeout);
|
|
57700
|
+
});
|
|
57701
|
+
try {
|
|
57702
|
+
const result = await Promise.race([this.rawEvaluate(input, rulePath), timeoutPromise]);
|
|
57703
|
+
const decision = this.parseDecision(result);
|
|
57704
|
+
if (!decision.allowed && this.fallback === "warn") {
|
|
57705
|
+
decision.allowed = true;
|
|
57706
|
+
decision.warn = true;
|
|
57707
|
+
decision.reason = `audit: ${decision.reason || "policy denied"}`;
|
|
57708
|
+
}
|
|
57709
|
+
this.logger?.debug(
|
|
57710
|
+
`[PolicyEngine] Decision for ${rulePath}: allowed=${decision.allowed}, warn=${decision.warn || false}, reason=${decision.reason || "none"}`
|
|
57711
|
+
);
|
|
57712
|
+
return decision;
|
|
57713
|
+
} finally {
|
|
57714
|
+
if (timer) clearTimeout(timer);
|
|
57715
|
+
}
|
|
57716
|
+
} catch (err) {
|
|
57717
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
57718
|
+
this.logger?.warn(`[PolicyEngine] Evaluation failed for ${rulePath}: ${msg}`);
|
|
57719
|
+
return {
|
|
57720
|
+
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
57721
|
+
warn: this.fallback === "warn" ? true : void 0,
|
|
57722
|
+
reason: `policy evaluation failed, fallback=${this.fallback}`
|
|
57723
|
+
};
|
|
57724
|
+
}
|
|
57725
|
+
}
|
|
57726
|
+
async rawEvaluate(input, rulePath) {
|
|
57727
|
+
if (this.evaluator instanceof OpaWasmEvaluator) {
|
|
57728
|
+
const result = await this.evaluator.evaluate(input);
|
|
57729
|
+
return this.navigateWasmResult(result, rulePath);
|
|
57730
|
+
}
|
|
57731
|
+
return this.evaluator.evaluate(input, rulePath);
|
|
57732
|
+
}
|
|
57733
|
+
/**
|
|
57734
|
+
* Navigate nested OPA WASM result tree to reach the specific rule's output.
|
|
57735
|
+
* The WASM entrypoint `-e visor` means the result root IS the visor package,
|
|
57736
|
+
* so we strip the `visor/` prefix and walk the remaining segments.
|
|
57737
|
+
*/
|
|
57738
|
+
navigateWasmResult(result, rulePath) {
|
|
57739
|
+
if (!result || typeof result !== "object") return result;
|
|
57740
|
+
const segments = rulePath.replace(/^visor\//, "").split("/");
|
|
57741
|
+
let current = result;
|
|
57742
|
+
for (const seg of segments) {
|
|
57743
|
+
if (current && typeof current === "object" && seg in current) {
|
|
57744
|
+
current = current[seg];
|
|
57745
|
+
} else {
|
|
57746
|
+
return void 0;
|
|
57747
|
+
}
|
|
57748
|
+
}
|
|
57749
|
+
return current;
|
|
57750
|
+
}
|
|
57751
|
+
parseDecision(result) {
|
|
57752
|
+
if (result === void 0 || result === null) {
|
|
57753
|
+
return {
|
|
57754
|
+
allowed: this.fallback === "allow" || this.fallback === "warn",
|
|
57755
|
+
warn: this.fallback === "warn" ? true : void 0,
|
|
57756
|
+
reason: this.fallback === "warn" ? "audit: no policy result" : "no policy result"
|
|
57757
|
+
};
|
|
57758
|
+
}
|
|
57759
|
+
const allowed = result.allowed !== false;
|
|
57760
|
+
const decision = {
|
|
57761
|
+
allowed,
|
|
57762
|
+
reason: result.reason
|
|
57763
|
+
};
|
|
57764
|
+
if (result.capabilities) {
|
|
57765
|
+
decision.capabilities = result.capabilities;
|
|
57766
|
+
}
|
|
57767
|
+
return decision;
|
|
57768
|
+
}
|
|
57769
|
+
};
|
|
57770
|
+
}
|
|
57771
|
+
});
|
|
57772
|
+
|
|
57773
|
+
// src/enterprise/scheduler/knex-store.ts
|
|
57774
|
+
var knex_store_exports = {};
|
|
57775
|
+
__export(knex_store_exports, {
|
|
57776
|
+
KnexStoreBackend: () => KnexStoreBackend
|
|
57777
|
+
});
|
|
57778
|
+
function toNum(val) {
|
|
57779
|
+
if (val === null || val === void 0) return void 0;
|
|
57780
|
+
return typeof val === "string" ? parseInt(val, 10) : val;
|
|
57781
|
+
}
|
|
57782
|
+
function safeJsonParse2(value) {
|
|
57783
|
+
if (!value) return void 0;
|
|
57784
|
+
try {
|
|
57785
|
+
return JSON.parse(value);
|
|
57786
|
+
} catch {
|
|
57787
|
+
return void 0;
|
|
57788
|
+
}
|
|
57789
|
+
}
|
|
57790
|
+
function fromTriggerRow2(row) {
|
|
57791
|
+
return {
|
|
57792
|
+
id: row.id,
|
|
57793
|
+
creatorId: row.creator_id,
|
|
57794
|
+
creatorContext: row.creator_context ?? void 0,
|
|
57795
|
+
creatorName: row.creator_name ?? void 0,
|
|
57796
|
+
description: row.description ?? void 0,
|
|
57797
|
+
channels: safeJsonParse2(row.channels),
|
|
57798
|
+
fromUsers: safeJsonParse2(row.from_users),
|
|
57799
|
+
fromBots: row.from_bots === true || row.from_bots === 1,
|
|
57800
|
+
contains: safeJsonParse2(row.contains),
|
|
57801
|
+
matchPattern: row.match_pattern ?? void 0,
|
|
57802
|
+
threads: row.threads,
|
|
57803
|
+
workflow: row.workflow,
|
|
57804
|
+
inputs: safeJsonParse2(row.inputs),
|
|
57805
|
+
outputContext: safeJsonParse2(row.output_context),
|
|
57806
|
+
status: row.status,
|
|
57807
|
+
enabled: row.enabled === true || row.enabled === 1,
|
|
57808
|
+
createdAt: toNum(row.created_at)
|
|
57809
|
+
};
|
|
57810
|
+
}
|
|
57811
|
+
function toTriggerInsertRow(trigger) {
|
|
57812
|
+
return {
|
|
57813
|
+
id: trigger.id,
|
|
57814
|
+
creator_id: trigger.creatorId,
|
|
57815
|
+
creator_context: trigger.creatorContext ?? null,
|
|
57816
|
+
creator_name: trigger.creatorName ?? null,
|
|
57817
|
+
description: trigger.description ?? null,
|
|
57818
|
+
channels: trigger.channels ? JSON.stringify(trigger.channels) : null,
|
|
57819
|
+
from_users: trigger.fromUsers ? JSON.stringify(trigger.fromUsers) : null,
|
|
57820
|
+
from_bots: trigger.fromBots,
|
|
57821
|
+
contains: trigger.contains ? JSON.stringify(trigger.contains) : null,
|
|
57822
|
+
match_pattern: trigger.matchPattern ?? null,
|
|
57823
|
+
threads: trigger.threads,
|
|
57824
|
+
workflow: trigger.workflow,
|
|
57825
|
+
inputs: trigger.inputs ? JSON.stringify(trigger.inputs) : null,
|
|
57826
|
+
output_context: trigger.outputContext ? JSON.stringify(trigger.outputContext) : null,
|
|
57827
|
+
status: trigger.status,
|
|
57828
|
+
enabled: trigger.enabled,
|
|
57829
|
+
created_at: trigger.createdAt
|
|
57830
|
+
};
|
|
57831
|
+
}
|
|
57832
|
+
function fromDbRow2(row) {
|
|
57833
|
+
return {
|
|
57834
|
+
id: row.id,
|
|
57835
|
+
creatorId: row.creator_id,
|
|
57836
|
+
creatorContext: row.creator_context ?? void 0,
|
|
57837
|
+
creatorName: row.creator_name ?? void 0,
|
|
57838
|
+
timezone: row.timezone,
|
|
57839
|
+
schedule: row.schedule_expr,
|
|
57840
|
+
runAt: toNum(row.run_at),
|
|
57841
|
+
isRecurring: row.is_recurring === true || row.is_recurring === 1,
|
|
57842
|
+
originalExpression: row.original_expression,
|
|
57843
|
+
workflow: row.workflow ?? void 0,
|
|
57844
|
+
workflowInputs: safeJsonParse2(row.workflow_inputs),
|
|
57845
|
+
outputContext: safeJsonParse2(row.output_context),
|
|
57846
|
+
status: row.status,
|
|
57847
|
+
createdAt: toNum(row.created_at),
|
|
57848
|
+
lastRunAt: toNum(row.last_run_at),
|
|
57849
|
+
nextRunAt: toNum(row.next_run_at),
|
|
57850
|
+
runCount: row.run_count,
|
|
57851
|
+
failureCount: row.failure_count,
|
|
57852
|
+
lastError: row.last_error ?? void 0,
|
|
57853
|
+
previousResponse: row.previous_response ?? void 0
|
|
57854
|
+
};
|
|
57855
|
+
}
|
|
57856
|
+
function toInsertRow(schedule) {
|
|
57857
|
+
return {
|
|
57858
|
+
id: schedule.id,
|
|
57859
|
+
creator_id: schedule.creatorId,
|
|
57860
|
+
creator_context: schedule.creatorContext ?? null,
|
|
57861
|
+
creator_name: schedule.creatorName ?? null,
|
|
57862
|
+
timezone: schedule.timezone,
|
|
57863
|
+
schedule_expr: schedule.schedule,
|
|
57864
|
+
run_at: schedule.runAt ?? null,
|
|
57865
|
+
is_recurring: schedule.isRecurring,
|
|
57866
|
+
original_expression: schedule.originalExpression,
|
|
57867
|
+
workflow: schedule.workflow ?? null,
|
|
57868
|
+
workflow_inputs: schedule.workflowInputs ? JSON.stringify(schedule.workflowInputs) : null,
|
|
57869
|
+
output_context: schedule.outputContext ? JSON.stringify(schedule.outputContext) : null,
|
|
57870
|
+
status: schedule.status,
|
|
57871
|
+
created_at: schedule.createdAt,
|
|
57872
|
+
last_run_at: schedule.lastRunAt ?? null,
|
|
57873
|
+
next_run_at: schedule.nextRunAt ?? null,
|
|
57874
|
+
run_count: schedule.runCount,
|
|
57875
|
+
failure_count: schedule.failureCount,
|
|
57876
|
+
last_error: schedule.lastError ?? null,
|
|
57877
|
+
previous_response: schedule.previousResponse ?? null
|
|
57878
|
+
};
|
|
57879
|
+
}
|
|
57880
|
+
var fs24, path29, import_uuid2, KnexStoreBackend;
|
|
57881
|
+
var init_knex_store = __esm({
|
|
57882
|
+
"src/enterprise/scheduler/knex-store.ts"() {
|
|
57883
|
+
"use strict";
|
|
57884
|
+
fs24 = __toESM(require("fs"));
|
|
57885
|
+
path29 = __toESM(require("path"));
|
|
57886
|
+
import_uuid2 = require("uuid");
|
|
57887
|
+
init_logger();
|
|
57888
|
+
KnexStoreBackend = class {
|
|
57889
|
+
knex = null;
|
|
57890
|
+
driver;
|
|
57891
|
+
connection;
|
|
57892
|
+
constructor(driver, storageConfig, _haConfig) {
|
|
57893
|
+
this.driver = driver;
|
|
57894
|
+
this.connection = storageConfig.connection || {};
|
|
57895
|
+
}
|
|
57896
|
+
async initialize() {
|
|
57897
|
+
const { createRequire } = require("module");
|
|
57898
|
+
const runtimeRequire = createRequire(__filename);
|
|
57899
|
+
let knexFactory;
|
|
57900
|
+
try {
|
|
57901
|
+
knexFactory = runtimeRequire("knex");
|
|
57902
|
+
} catch (err) {
|
|
57903
|
+
const code = err?.code;
|
|
57904
|
+
if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
|
|
57905
|
+
throw new Error(
|
|
57906
|
+
"knex is required for PostgreSQL/MySQL/MSSQL schedule storage. Install it with: npm install knex"
|
|
57907
|
+
);
|
|
57908
|
+
}
|
|
57909
|
+
throw err;
|
|
57910
|
+
}
|
|
57911
|
+
const clientMap = {
|
|
57912
|
+
postgresql: "pg",
|
|
57913
|
+
mysql: "mysql2",
|
|
57914
|
+
mssql: "tedious"
|
|
57915
|
+
};
|
|
57916
|
+
const client = clientMap[this.driver];
|
|
57917
|
+
let connection;
|
|
57918
|
+
if (this.connection.connection_string) {
|
|
57919
|
+
connection = this.connection.connection_string;
|
|
57920
|
+
} else if (this.driver === "mssql") {
|
|
57921
|
+
connection = this.buildMssqlConnection();
|
|
57922
|
+
} else {
|
|
57923
|
+
connection = this.buildStandardConnection();
|
|
57924
|
+
}
|
|
57925
|
+
this.knex = knexFactory({
|
|
57926
|
+
client,
|
|
57927
|
+
connection,
|
|
57928
|
+
pool: {
|
|
57929
|
+
min: this.connection.pool?.min ?? 0,
|
|
57930
|
+
max: this.connection.pool?.max ?? 10
|
|
57931
|
+
}
|
|
57932
|
+
});
|
|
57933
|
+
await this.migrateSchema();
|
|
57934
|
+
logger.info(`[KnexStore] Initialized (${this.driver})`);
|
|
57935
|
+
}
|
|
57936
|
+
buildStandardConnection() {
|
|
57937
|
+
return {
|
|
57938
|
+
host: this.connection.host || "localhost",
|
|
57939
|
+
port: this.connection.port,
|
|
57940
|
+
database: this.connection.database || "visor",
|
|
57941
|
+
user: this.connection.user,
|
|
57942
|
+
password: this.connection.password,
|
|
57943
|
+
ssl: this.resolveSslConfig()
|
|
57944
|
+
};
|
|
57945
|
+
}
|
|
57946
|
+
buildMssqlConnection() {
|
|
57947
|
+
const ssl = this.connection.ssl;
|
|
57948
|
+
const sslEnabled = ssl === true || typeof ssl === "object" && ssl.enabled !== false;
|
|
57949
|
+
return {
|
|
57950
|
+
server: this.connection.host || "localhost",
|
|
57951
|
+
port: this.connection.port,
|
|
57952
|
+
database: this.connection.database || "visor",
|
|
57953
|
+
user: this.connection.user,
|
|
57954
|
+
password: this.connection.password,
|
|
57955
|
+
options: {
|
|
57956
|
+
encrypt: sslEnabled,
|
|
57957
|
+
trustServerCertificate: typeof ssl === "object" ? ssl.reject_unauthorized === false : !sslEnabled
|
|
57958
|
+
}
|
|
57959
|
+
};
|
|
57960
|
+
}
|
|
57961
|
+
resolveSslConfig() {
|
|
57962
|
+
const ssl = this.connection.ssl;
|
|
57963
|
+
if (ssl === false || ssl === void 0) return false;
|
|
57964
|
+
if (ssl === true) return { rejectUnauthorized: true };
|
|
57965
|
+
if (ssl.enabled === false) return false;
|
|
57966
|
+
const result = {
|
|
57967
|
+
rejectUnauthorized: ssl.reject_unauthorized !== false
|
|
57968
|
+
};
|
|
57969
|
+
if (ssl.ca) {
|
|
57970
|
+
const caPath = this.validateSslPath(ssl.ca, "CA certificate");
|
|
57971
|
+
result.ca = fs24.readFileSync(caPath, "utf8");
|
|
57972
|
+
}
|
|
57973
|
+
if (ssl.cert) {
|
|
57974
|
+
const certPath = this.validateSslPath(ssl.cert, "client certificate");
|
|
57975
|
+
result.cert = fs24.readFileSync(certPath, "utf8");
|
|
57976
|
+
}
|
|
57977
|
+
if (ssl.key) {
|
|
57978
|
+
const keyPath = this.validateSslPath(ssl.key, "client key");
|
|
57979
|
+
result.key = fs24.readFileSync(keyPath, "utf8");
|
|
57980
|
+
}
|
|
57981
|
+
return result;
|
|
57982
|
+
}
|
|
57983
|
+
validateSslPath(filePath, label) {
|
|
57984
|
+
const resolved = path29.resolve(filePath);
|
|
57985
|
+
if (resolved !== path29.normalize(resolved)) {
|
|
57986
|
+
throw new Error(`SSL ${label} path contains invalid sequences: ${filePath}`);
|
|
57987
|
+
}
|
|
57988
|
+
if (!fs24.existsSync(resolved)) {
|
|
57989
|
+
throw new Error(`SSL ${label} not found: ${filePath}`);
|
|
57990
|
+
}
|
|
57991
|
+
return resolved;
|
|
57992
|
+
}
|
|
57993
|
+
async shutdown() {
|
|
57994
|
+
if (this.knex) {
|
|
57995
|
+
await this.knex.destroy();
|
|
57996
|
+
this.knex = null;
|
|
57997
|
+
}
|
|
57998
|
+
}
|
|
57999
|
+
async migrateSchema() {
|
|
58000
|
+
const knex = this.getKnex();
|
|
58001
|
+
const exists = await knex.schema.hasTable("schedules");
|
|
58002
|
+
if (!exists) {
|
|
58003
|
+
await knex.schema.createTable("schedules", (table) => {
|
|
58004
|
+
table.string("id", 36).primary();
|
|
58005
|
+
table.string("creator_id", 255).notNullable().index();
|
|
58006
|
+
table.string("creator_context", 255);
|
|
58007
|
+
table.string("creator_name", 255);
|
|
58008
|
+
table.string("timezone", 64).notNullable().defaultTo("UTC");
|
|
58009
|
+
table.string("schedule_expr", 255);
|
|
58010
|
+
table.bigInteger("run_at");
|
|
58011
|
+
table.boolean("is_recurring").notNullable();
|
|
58012
|
+
table.text("original_expression");
|
|
58013
|
+
table.string("workflow", 255);
|
|
58014
|
+
table.text("workflow_inputs");
|
|
58015
|
+
table.text("output_context");
|
|
58016
|
+
table.string("status", 20).notNullable().index();
|
|
58017
|
+
table.bigInteger("created_at").notNullable();
|
|
58018
|
+
table.bigInteger("last_run_at");
|
|
58019
|
+
table.bigInteger("next_run_at");
|
|
58020
|
+
table.integer("run_count").notNullable().defaultTo(0);
|
|
58021
|
+
table.integer("failure_count").notNullable().defaultTo(0);
|
|
58022
|
+
table.text("last_error");
|
|
58023
|
+
table.text("previous_response");
|
|
58024
|
+
table.index(["status", "next_run_at"]);
|
|
58025
|
+
});
|
|
58026
|
+
}
|
|
58027
|
+
const triggersExist = await knex.schema.hasTable("message_triggers");
|
|
58028
|
+
if (!triggersExist) {
|
|
58029
|
+
await knex.schema.createTable("message_triggers", (table) => {
|
|
58030
|
+
table.string("id", 36).primary();
|
|
58031
|
+
table.string("creator_id", 255).notNullable().index();
|
|
58032
|
+
table.string("creator_context", 255);
|
|
58033
|
+
table.string("creator_name", 255);
|
|
58034
|
+
table.text("description");
|
|
58035
|
+
table.text("channels");
|
|
58036
|
+
table.text("from_users");
|
|
58037
|
+
table.boolean("from_bots").notNullable().defaultTo(false);
|
|
58038
|
+
table.text("contains");
|
|
58039
|
+
table.text("match_pattern");
|
|
58040
|
+
table.string("threads", 20).notNullable().defaultTo("any");
|
|
58041
|
+
table.string("workflow", 255).notNullable();
|
|
58042
|
+
table.text("inputs");
|
|
58043
|
+
table.text("output_context");
|
|
58044
|
+
table.string("status", 20).notNullable().defaultTo("active").index();
|
|
58045
|
+
table.boolean("enabled").notNullable().defaultTo(true);
|
|
58046
|
+
table.bigInteger("created_at").notNullable();
|
|
58047
|
+
});
|
|
58048
|
+
}
|
|
58049
|
+
const locksExist = await knex.schema.hasTable("scheduler_locks");
|
|
58050
|
+
if (!locksExist) {
|
|
58051
|
+
await knex.schema.createTable("scheduler_locks", (table) => {
|
|
58052
|
+
table.string("lock_id", 255).primary();
|
|
58053
|
+
table.string("node_id", 255).notNullable();
|
|
58054
|
+
table.string("lock_token", 36).notNullable();
|
|
58055
|
+
table.bigInteger("acquired_at").notNullable();
|
|
58056
|
+
table.bigInteger("expires_at").notNullable();
|
|
58057
|
+
});
|
|
58058
|
+
}
|
|
58059
|
+
}
|
|
58060
|
+
getKnex() {
|
|
58061
|
+
if (!this.knex) {
|
|
58062
|
+
throw new Error("[KnexStore] Not initialized. Call initialize() first.");
|
|
58063
|
+
}
|
|
58064
|
+
return this.knex;
|
|
58065
|
+
}
|
|
58066
|
+
// --- CRUD ---
|
|
58067
|
+
async create(schedule) {
|
|
58068
|
+
const knex = this.getKnex();
|
|
58069
|
+
const newSchedule = {
|
|
58070
|
+
...schedule,
|
|
58071
|
+
id: (0, import_uuid2.v4)(),
|
|
58072
|
+
createdAt: Date.now(),
|
|
58073
|
+
runCount: 0,
|
|
58074
|
+
failureCount: 0,
|
|
58075
|
+
status: "active"
|
|
58076
|
+
};
|
|
58077
|
+
await knex("schedules").insert(toInsertRow(newSchedule));
|
|
58078
|
+
logger.info(`[KnexStore] Created schedule ${newSchedule.id} for user ${newSchedule.creatorId}`);
|
|
58079
|
+
return newSchedule;
|
|
58080
|
+
}
|
|
58081
|
+
async importSchedule(schedule) {
|
|
58082
|
+
const knex = this.getKnex();
|
|
58083
|
+
const existing = await knex("schedules").where("id", schedule.id).first();
|
|
58084
|
+
if (existing) return;
|
|
58085
|
+
await knex("schedules").insert(toInsertRow(schedule));
|
|
58086
|
+
}
|
|
58087
|
+
async get(id) {
|
|
58088
|
+
const knex = this.getKnex();
|
|
58089
|
+
const row = await knex("schedules").where("id", id).first();
|
|
58090
|
+
return row ? fromDbRow2(row) : void 0;
|
|
58091
|
+
}
|
|
58092
|
+
async update(id, patch) {
|
|
58093
|
+
const knex = this.getKnex();
|
|
58094
|
+
const existing = await knex("schedules").where("id", id).first();
|
|
58095
|
+
if (!existing) return void 0;
|
|
58096
|
+
const current = fromDbRow2(existing);
|
|
58097
|
+
const updated = { ...current, ...patch, id: current.id };
|
|
58098
|
+
const row = toInsertRow(updated);
|
|
58099
|
+
delete row.id;
|
|
58100
|
+
await knex("schedules").where("id", id).update(row);
|
|
58101
|
+
return updated;
|
|
58102
|
+
}
|
|
58103
|
+
async delete(id) {
|
|
58104
|
+
const knex = this.getKnex();
|
|
58105
|
+
const deleted = await knex("schedules").where("id", id).del();
|
|
58106
|
+
if (deleted > 0) {
|
|
58107
|
+
logger.info(`[KnexStore] Deleted schedule ${id}`);
|
|
58108
|
+
return true;
|
|
58109
|
+
}
|
|
58110
|
+
return false;
|
|
58111
|
+
}
|
|
58112
|
+
// --- Queries ---
|
|
58113
|
+
async getByCreator(creatorId) {
|
|
58114
|
+
const knex = this.getKnex();
|
|
58115
|
+
const rows = await knex("schedules").where("creator_id", creatorId);
|
|
58116
|
+
return rows.map((r) => fromDbRow2(r));
|
|
58117
|
+
}
|
|
58118
|
+
async getActiveSchedules() {
|
|
58119
|
+
const knex = this.getKnex();
|
|
58120
|
+
const rows = await knex("schedules").where("status", "active");
|
|
58121
|
+
return rows.map((r) => fromDbRow2(r));
|
|
58122
|
+
}
|
|
58123
|
+
async getDueSchedules(now) {
|
|
58124
|
+
const ts = now ?? Date.now();
|
|
58125
|
+
const knex = this.getKnex();
|
|
58126
|
+
const bFalse = this.driver === "mssql" ? 0 : false;
|
|
58127
|
+
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
58128
|
+
const rows = await knex("schedules").where("status", "active").andWhere(function() {
|
|
58129
|
+
this.where(function() {
|
|
58130
|
+
this.where("is_recurring", bFalse).whereNotNull("run_at").where("run_at", "<=", ts);
|
|
58131
|
+
}).orWhere(function() {
|
|
58132
|
+
this.where("is_recurring", bTrue).whereNotNull("next_run_at").where("next_run_at", "<=", ts);
|
|
58133
|
+
});
|
|
58134
|
+
});
|
|
58135
|
+
return rows.map((r) => fromDbRow2(r));
|
|
58136
|
+
}
|
|
58137
|
+
async findByWorkflow(creatorId, workflowName) {
|
|
58138
|
+
const knex = this.getKnex();
|
|
58139
|
+
const escaped = workflowName.toLowerCase().replace(/[%_\\]/g, "\\$&");
|
|
58140
|
+
const pattern = `%${escaped}%`;
|
|
58141
|
+
const rows = await knex("schedules").where("creator_id", creatorId).where("status", "active").whereRaw("LOWER(workflow) LIKE ? ESCAPE '\\'", [pattern]);
|
|
58142
|
+
return rows.map((r) => fromDbRow2(r));
|
|
58143
|
+
}
|
|
58144
|
+
async getAll() {
|
|
58145
|
+
const knex = this.getKnex();
|
|
58146
|
+
const rows = await knex("schedules");
|
|
58147
|
+
return rows.map((r) => fromDbRow2(r));
|
|
58148
|
+
}
|
|
58149
|
+
async getStats() {
|
|
58150
|
+
const knex = this.getKnex();
|
|
58151
|
+
const boolTrue = this.driver === "mssql" ? "1" : "true";
|
|
58152
|
+
const boolFalse = this.driver === "mssql" ? "0" : "false";
|
|
58153
|
+
const result = await knex("schedules").select(
|
|
58154
|
+
knex.raw("COUNT(*) as total"),
|
|
58155
|
+
knex.raw("SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active"),
|
|
58156
|
+
knex.raw("SUM(CASE WHEN status = 'paused' THEN 1 ELSE 0 END) as paused"),
|
|
58157
|
+
knex.raw("SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed"),
|
|
58158
|
+
knex.raw("SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed"),
|
|
58159
|
+
knex.raw(`SUM(CASE WHEN is_recurring = ${boolTrue} THEN 1 ELSE 0 END) as recurring`),
|
|
58160
|
+
knex.raw(`SUM(CASE WHEN is_recurring = ${boolFalse} THEN 1 ELSE 0 END) as one_time`)
|
|
58161
|
+
).first();
|
|
58162
|
+
return {
|
|
58163
|
+
total: Number(result.total) || 0,
|
|
58164
|
+
active: Number(result.active) || 0,
|
|
58165
|
+
paused: Number(result.paused) || 0,
|
|
58166
|
+
completed: Number(result.completed) || 0,
|
|
58167
|
+
failed: Number(result.failed) || 0,
|
|
58168
|
+
recurring: Number(result.recurring) || 0,
|
|
58169
|
+
oneTime: Number(result.one_time) || 0
|
|
58170
|
+
};
|
|
58171
|
+
}
|
|
58172
|
+
async validateLimits(creatorId, isRecurring, limits) {
|
|
58173
|
+
const knex = this.getKnex();
|
|
58174
|
+
if (limits.maxGlobal) {
|
|
58175
|
+
const result = await knex("schedules").count("* as cnt").first();
|
|
58176
|
+
if (Number(result?.cnt) >= limits.maxGlobal) {
|
|
58177
|
+
throw new Error(`Global schedule limit reached (${limits.maxGlobal})`);
|
|
58178
|
+
}
|
|
58179
|
+
}
|
|
58180
|
+
if (limits.maxPerUser) {
|
|
58181
|
+
const result = await knex("schedules").where("creator_id", creatorId).count("* as cnt").first();
|
|
58182
|
+
if (Number(result?.cnt) >= limits.maxPerUser) {
|
|
58183
|
+
throw new Error(`You have reached the maximum number of schedules (${limits.maxPerUser})`);
|
|
58184
|
+
}
|
|
58185
|
+
}
|
|
58186
|
+
if (isRecurring && limits.maxRecurringPerUser) {
|
|
58187
|
+
const bTrue = this.driver === "mssql" ? 1 : true;
|
|
58188
|
+
const result = await knex("schedules").where("creator_id", creatorId).where("is_recurring", bTrue).count("* as cnt").first();
|
|
58189
|
+
if (Number(result?.cnt) >= limits.maxRecurringPerUser) {
|
|
58190
|
+
throw new Error(
|
|
58191
|
+
`You have reached the maximum number of recurring schedules (${limits.maxRecurringPerUser})`
|
|
58192
|
+
);
|
|
58193
|
+
}
|
|
58194
|
+
}
|
|
58195
|
+
}
|
|
58196
|
+
// --- HA Distributed Locking (via scheduler_locks table) ---
|
|
58197
|
+
async tryAcquireLock(lockId, nodeId, ttlSeconds) {
|
|
58198
|
+
const knex = this.getKnex();
|
|
58199
|
+
const now = Date.now();
|
|
58200
|
+
const expiresAt = now + ttlSeconds * 1e3;
|
|
58201
|
+
const token = (0, import_uuid2.v4)();
|
|
58202
|
+
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("expires_at", "<", now).update({
|
|
58203
|
+
node_id: nodeId,
|
|
58204
|
+
lock_token: token,
|
|
58205
|
+
acquired_at: now,
|
|
58206
|
+
expires_at: expiresAt
|
|
58207
|
+
});
|
|
58208
|
+
if (updated > 0) return token;
|
|
58209
|
+
try {
|
|
58210
|
+
await knex("scheduler_locks").insert({
|
|
58211
|
+
lock_id: lockId,
|
|
58212
|
+
node_id: nodeId,
|
|
58213
|
+
lock_token: token,
|
|
58214
|
+
acquired_at: now,
|
|
58215
|
+
expires_at: expiresAt
|
|
58216
|
+
});
|
|
58217
|
+
return token;
|
|
58218
|
+
} catch {
|
|
58219
|
+
return null;
|
|
58220
|
+
}
|
|
58221
|
+
}
|
|
58222
|
+
async releaseLock(lockId, lockToken) {
|
|
58223
|
+
const knex = this.getKnex();
|
|
58224
|
+
await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).del();
|
|
58225
|
+
}
|
|
58226
|
+
async renewLock(lockId, lockToken, ttlSeconds) {
|
|
58227
|
+
const knex = this.getKnex();
|
|
58228
|
+
const now = Date.now();
|
|
58229
|
+
const expiresAt = now + ttlSeconds * 1e3;
|
|
58230
|
+
const updated = await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).update({ acquired_at: now, expires_at: expiresAt });
|
|
58231
|
+
return updated > 0;
|
|
58232
|
+
}
|
|
58233
|
+
async flush() {
|
|
58234
|
+
}
|
|
58235
|
+
// --- Message Trigger CRUD ---
|
|
58236
|
+
async createTrigger(trigger) {
|
|
58237
|
+
const knex = this.getKnex();
|
|
58238
|
+
const newTrigger = {
|
|
58239
|
+
...trigger,
|
|
58240
|
+
id: (0, import_uuid2.v4)(),
|
|
58241
|
+
createdAt: Date.now()
|
|
58242
|
+
};
|
|
58243
|
+
await knex("message_triggers").insert(toTriggerInsertRow(newTrigger));
|
|
58244
|
+
logger.info(`[KnexStore] Created trigger ${newTrigger.id} for user ${newTrigger.creatorId}`);
|
|
58245
|
+
return newTrigger;
|
|
58246
|
+
}
|
|
58247
|
+
async getTrigger(id) {
|
|
58248
|
+
const knex = this.getKnex();
|
|
58249
|
+
const row = await knex("message_triggers").where("id", id).first();
|
|
58250
|
+
return row ? fromTriggerRow2(row) : void 0;
|
|
58251
|
+
}
|
|
58252
|
+
async updateTrigger(id, patch) {
|
|
58253
|
+
const knex = this.getKnex();
|
|
58254
|
+
const existing = await knex("message_triggers").where("id", id).first();
|
|
58255
|
+
if (!existing) return void 0;
|
|
58256
|
+
const current = fromTriggerRow2(existing);
|
|
58257
|
+
const updated = {
|
|
58258
|
+
...current,
|
|
58259
|
+
...patch,
|
|
58260
|
+
id: current.id,
|
|
58261
|
+
createdAt: current.createdAt
|
|
58262
|
+
};
|
|
58263
|
+
const row = toTriggerInsertRow(updated);
|
|
58264
|
+
delete row.id;
|
|
58265
|
+
await knex("message_triggers").where("id", id).update(row);
|
|
58266
|
+
return updated;
|
|
58267
|
+
}
|
|
58268
|
+
async deleteTrigger(id) {
|
|
58269
|
+
const knex = this.getKnex();
|
|
58270
|
+
const deleted = await knex("message_triggers").where("id", id).del();
|
|
58271
|
+
if (deleted > 0) {
|
|
58272
|
+
logger.info(`[KnexStore] Deleted trigger ${id}`);
|
|
58273
|
+
return true;
|
|
58274
|
+
}
|
|
58275
|
+
return false;
|
|
58276
|
+
}
|
|
58277
|
+
async getTriggersByCreator(creatorId) {
|
|
58278
|
+
const knex = this.getKnex();
|
|
58279
|
+
const rows = await knex("message_triggers").where("creator_id", creatorId);
|
|
58280
|
+
return rows.map((r) => fromTriggerRow2(r));
|
|
58281
|
+
}
|
|
58282
|
+
async getActiveTriggers() {
|
|
58283
|
+
const knex = this.getKnex();
|
|
58284
|
+
const rows = await knex("message_triggers").where("status", "active").where("enabled", this.driver === "mssql" ? 1 : true);
|
|
58285
|
+
return rows.map((r) => fromTriggerRow2(r));
|
|
58286
|
+
}
|
|
58287
|
+
};
|
|
58288
|
+
}
|
|
58289
|
+
});
|
|
58290
|
+
|
|
58291
|
+
// src/enterprise/loader.ts
|
|
58292
|
+
var loader_exports = {};
|
|
58293
|
+
__export(loader_exports, {
|
|
58294
|
+
loadEnterprisePolicyEngine: () => loadEnterprisePolicyEngine,
|
|
58295
|
+
loadEnterpriseStoreBackend: () => loadEnterpriseStoreBackend
|
|
58296
|
+
});
|
|
58297
|
+
async function loadEnterprisePolicyEngine(config) {
|
|
58298
|
+
try {
|
|
58299
|
+
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
58300
|
+
const validator = new LicenseValidator2();
|
|
58301
|
+
const license = await validator.loadAndValidate();
|
|
58302
|
+
if (!license || !validator.hasFeature("policy")) {
|
|
58303
|
+
return new DefaultPolicyEngine();
|
|
58304
|
+
}
|
|
58305
|
+
if (validator.isInGracePeriod()) {
|
|
58306
|
+
console.warn(
|
|
58307
|
+
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
58308
|
+
);
|
|
58309
|
+
}
|
|
58310
|
+
const { OpaPolicyEngine: OpaPolicyEngine2 } = await Promise.resolve().then(() => (init_opa_policy_engine(), opa_policy_engine_exports));
|
|
58311
|
+
const engine = new OpaPolicyEngine2(config);
|
|
58312
|
+
await engine.initialize(config);
|
|
58313
|
+
return engine;
|
|
58314
|
+
} catch (err) {
|
|
58315
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
58316
|
+
try {
|
|
58317
|
+
const { logger: logger2 } = (init_logger(), __toCommonJS(logger_exports));
|
|
58318
|
+
logger2.warn(`[PolicyEngine] Enterprise policy init failed, falling back to default: ${msg}`);
|
|
58319
|
+
} catch {
|
|
58320
|
+
}
|
|
58321
|
+
return new DefaultPolicyEngine();
|
|
58322
|
+
}
|
|
58323
|
+
}
|
|
58324
|
+
async function loadEnterpriseStoreBackend(driver, storageConfig, haConfig) {
|
|
58325
|
+
const { LicenseValidator: LicenseValidator2 } = await Promise.resolve().then(() => (init_validator(), validator_exports));
|
|
58326
|
+
const validator = new LicenseValidator2();
|
|
58327
|
+
const license = await validator.loadAndValidate();
|
|
58328
|
+
if (!license || !validator.hasFeature("scheduler-sql")) {
|
|
58329
|
+
throw new Error(
|
|
58330
|
+
`The ${driver} schedule storage driver requires a Visor Enterprise license with the 'scheduler-sql' feature. Please upgrade or use driver: 'sqlite' (default).`
|
|
58331
|
+
);
|
|
58332
|
+
}
|
|
58333
|
+
if (validator.isInGracePeriod()) {
|
|
58334
|
+
console.warn(
|
|
58335
|
+
"[visor:enterprise] License has expired but is within the 72-hour grace period. Please renew your license."
|
|
58336
|
+
);
|
|
58337
|
+
}
|
|
58338
|
+
const { KnexStoreBackend: KnexStoreBackend2 } = await Promise.resolve().then(() => (init_knex_store(), knex_store_exports));
|
|
58339
|
+
return new KnexStoreBackend2(driver, storageConfig, haConfig);
|
|
58340
|
+
}
|
|
58341
|
+
var init_loader = __esm({
|
|
58342
|
+
"src/enterprise/loader.ts"() {
|
|
58343
|
+
"use strict";
|
|
58344
|
+
init_default_engine();
|
|
58345
|
+
}
|
|
58346
|
+
});
|
|
58347
|
+
|
|
56698
58348
|
// src/event-bus/event-bus.ts
|
|
56699
58349
|
var event_bus_exports = {};
|
|
56700
58350
|
__export(event_bus_exports, {
|
|
@@ -57601,8 +59251,8 @@ ${content}
|
|
|
57601
59251
|
* Sleep utility
|
|
57602
59252
|
*/
|
|
57603
59253
|
sleep(ms) {
|
|
57604
|
-
return new Promise((
|
|
57605
|
-
const t = setTimeout(
|
|
59254
|
+
return new Promise((resolve19) => {
|
|
59255
|
+
const t = setTimeout(resolve19, ms);
|
|
57606
59256
|
if (typeof t.unref === "function") {
|
|
57607
59257
|
try {
|
|
57608
59258
|
t.unref();
|
|
@@ -57887,8 +59537,8 @@ ${end}`);
|
|
|
57887
59537
|
async updateGroupedComment(ctx, comments, group, changedIds) {
|
|
57888
59538
|
const existingLock = this.updateLocks.get(group);
|
|
57889
59539
|
let resolveLock;
|
|
57890
|
-
const ourLock = new Promise((
|
|
57891
|
-
resolveLock =
|
|
59540
|
+
const ourLock = new Promise((resolve19) => {
|
|
59541
|
+
resolveLock = resolve19;
|
|
57892
59542
|
});
|
|
57893
59543
|
this.updateLocks.set(group, ourLock);
|
|
57894
59544
|
try {
|
|
@@ -58219,7 +59869,7 @@ ${blocks}
|
|
|
58219
59869
|
* Sleep utility for enforcing delays
|
|
58220
59870
|
*/
|
|
58221
59871
|
sleep(ms) {
|
|
58222
|
-
return new Promise((
|
|
59872
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
58223
59873
|
}
|
|
58224
59874
|
};
|
|
58225
59875
|
}
|
|
@@ -60066,11 +61716,11 @@ var require_request3 = __commonJS({
|
|
|
60066
61716
|
"use strict";
|
|
60067
61717
|
var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
60068
61718
|
function adopt(value) {
|
|
60069
|
-
return value instanceof P ? value : new P(function(
|
|
60070
|
-
|
|
61719
|
+
return value instanceof P ? value : new P(function(resolve19) {
|
|
61720
|
+
resolve19(value);
|
|
60071
61721
|
});
|
|
60072
61722
|
}
|
|
60073
|
-
return new (P || (P = Promise))(function(
|
|
61723
|
+
return new (P || (P = Promise))(function(resolve19, reject) {
|
|
60074
61724
|
function fulfilled(value) {
|
|
60075
61725
|
try {
|
|
60076
61726
|
step(generator.next(value));
|
|
@@ -60086,7 +61736,7 @@ var require_request3 = __commonJS({
|
|
|
60086
61736
|
}
|
|
60087
61737
|
}
|
|
60088
61738
|
function step(result) {
|
|
60089
|
-
result.done ?
|
|
61739
|
+
result.done ? resolve19(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
60090
61740
|
}
|
|
60091
61741
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
60092
61742
|
});
|
|
@@ -60110,9 +61760,9 @@ var require_request3 = __commonJS({
|
|
|
60110
61760
|
HttpMethod2["PATCH"] = "PATCH";
|
|
60111
61761
|
})(HttpMethod = exports2.HttpMethod || (exports2.HttpMethod = {}));
|
|
60112
61762
|
var SvixRequest = class {
|
|
60113
|
-
constructor(method,
|
|
61763
|
+
constructor(method, path33) {
|
|
60114
61764
|
this.method = method;
|
|
60115
|
-
this.path =
|
|
61765
|
+
this.path = path33;
|
|
60116
61766
|
this.queryParams = {};
|
|
60117
61767
|
this.headerParams = {};
|
|
60118
61768
|
}
|
|
@@ -60215,7 +61865,7 @@ var require_request3 = __commonJS({
|
|
|
60215
61865
|
}
|
|
60216
61866
|
function sendWithRetry(url, init, retryScheduleInMs, nextInterval = 50, triesLeft = 2, fetchImpl = fetch, retryCount = 1) {
|
|
60217
61867
|
return __awaiter(this, void 0, void 0, function* () {
|
|
60218
|
-
const sleep = (interval) => new Promise((
|
|
61868
|
+
const sleep = (interval) => new Promise((resolve19) => setTimeout(resolve19, interval));
|
|
60219
61869
|
try {
|
|
60220
61870
|
const response = yield fetchImpl(url, init);
|
|
60221
61871
|
if (triesLeft <= 0 || response.status < 500) {
|
|
@@ -69289,7 +70939,7 @@ ${message}`;
|
|
|
69289
70939
|
});
|
|
69290
70940
|
|
|
69291
70941
|
// src/agent-protocol/task-store.ts
|
|
69292
|
-
function
|
|
70942
|
+
function safeJsonParse3(value) {
|
|
69293
70943
|
if (!value) return void 0;
|
|
69294
70944
|
try {
|
|
69295
70945
|
return JSON.parse(value);
|
|
@@ -69306,12 +70956,12 @@ function taskRowToAgentTask(row) {
|
|
|
69306
70956
|
context_id: row.context_id,
|
|
69307
70957
|
status: {
|
|
69308
70958
|
state: row.state,
|
|
69309
|
-
message:
|
|
70959
|
+
message: safeJsonParse3(row.status_message),
|
|
69310
70960
|
timestamp: row.updated_at
|
|
69311
70961
|
},
|
|
69312
|
-
artifacts:
|
|
69313
|
-
history:
|
|
69314
|
-
metadata:
|
|
70962
|
+
artifacts: safeJsonParse3(row.artifacts) ?? [],
|
|
70963
|
+
history: safeJsonParse3(row.history) ?? [],
|
|
70964
|
+
metadata: safeJsonParse3(row.request_metadata),
|
|
69315
70965
|
workflow_id: row.workflow_id ?? void 0
|
|
69316
70966
|
};
|
|
69317
70967
|
}
|
|
@@ -69548,7 +71198,7 @@ var init_task_store = __esm({
|
|
|
69548
71198
|
const db = this.getDb();
|
|
69549
71199
|
const row = db.prepare("SELECT artifacts FROM agent_tasks WHERE id = ?").get(taskId);
|
|
69550
71200
|
if (!row) throw new TaskNotFoundError(taskId);
|
|
69551
|
-
const artifacts =
|
|
71201
|
+
const artifacts = safeJsonParse3(row.artifacts) ?? [];
|
|
69552
71202
|
artifacts.push(artifact);
|
|
69553
71203
|
db.prepare("UPDATE agent_tasks SET artifacts = ?, updated_at = ? WHERE id = ?").run(
|
|
69554
71204
|
JSON.stringify(artifacts),
|
|
@@ -69560,7 +71210,7 @@ var init_task_store = __esm({
|
|
|
69560
71210
|
const db = this.getDb();
|
|
69561
71211
|
const row = db.prepare("SELECT history FROM agent_tasks WHERE id = ?").get(taskId);
|
|
69562
71212
|
if (!row) throw new TaskNotFoundError(taskId);
|
|
69563
|
-
const history =
|
|
71213
|
+
const history = safeJsonParse3(row.history) ?? [];
|
|
69564
71214
|
history.push(message);
|
|
69565
71215
|
db.prepare("UPDATE agent_tasks SET history = ?, updated_at = ? WHERE id = ?").run(
|
|
69566
71216
|
JSON.stringify(history),
|
|
@@ -70072,13 +71722,13 @@ __export(a2a_frontend_exports, {
|
|
|
70072
71722
|
resultToArtifacts: () => resultToArtifacts
|
|
70073
71723
|
});
|
|
70074
71724
|
function readJsonBody(req) {
|
|
70075
|
-
return new Promise((
|
|
71725
|
+
return new Promise((resolve19, reject) => {
|
|
70076
71726
|
const chunks = [];
|
|
70077
71727
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
70078
71728
|
req.on("end", () => {
|
|
70079
71729
|
try {
|
|
70080
71730
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
70081
|
-
|
|
71731
|
+
resolve19(body ? JSON.parse(body) : {});
|
|
70082
71732
|
} catch {
|
|
70083
71733
|
reject(new ParseError("Malformed JSON body"));
|
|
70084
71734
|
}
|
|
@@ -70321,12 +71971,12 @@ var init_a2a_frontend = __esm({
|
|
|
70321
71971
|
}
|
|
70322
71972
|
const port = this.config.port ?? 9e3;
|
|
70323
71973
|
const host = this.config.host ?? "0.0.0.0";
|
|
70324
|
-
await new Promise((
|
|
71974
|
+
await new Promise((resolve19) => {
|
|
70325
71975
|
this.server.listen(port, host, () => {
|
|
70326
71976
|
const addr = this.server.address();
|
|
70327
71977
|
this._boundPort = typeof addr === "object" && addr ? addr.port : port;
|
|
70328
71978
|
logger.info(`A2A server listening on ${host}:${this._boundPort}`);
|
|
70329
|
-
|
|
71979
|
+
resolve19();
|
|
70330
71980
|
});
|
|
70331
71981
|
});
|
|
70332
71982
|
if (this.agentCard) {
|
|
@@ -70350,8 +72000,8 @@ var init_a2a_frontend = __esm({
|
|
|
70350
72000
|
}
|
|
70351
72001
|
this.streamManager.shutdown();
|
|
70352
72002
|
if (this.server) {
|
|
70353
|
-
await new Promise((
|
|
70354
|
-
this.server.close((err) => err ? reject(err) :
|
|
72003
|
+
await new Promise((resolve19, reject) => {
|
|
72004
|
+
this.server.close((err) => err ? reject(err) : resolve19());
|
|
70355
72005
|
});
|
|
70356
72006
|
this.server = null;
|
|
70357
72007
|
}
|
|
@@ -71068,15 +72718,15 @@ function serializeRunState(state) {
|
|
|
71068
72718
|
])
|
|
71069
72719
|
};
|
|
71070
72720
|
}
|
|
71071
|
-
var
|
|
72721
|
+
var path32, fs28, StateMachineExecutionEngine;
|
|
71072
72722
|
var init_state_machine_execution_engine = __esm({
|
|
71073
72723
|
"src/state-machine-execution-engine.ts"() {
|
|
71074
72724
|
"use strict";
|
|
71075
72725
|
init_runner();
|
|
71076
72726
|
init_logger();
|
|
71077
72727
|
init_sandbox_manager();
|
|
71078
|
-
|
|
71079
|
-
|
|
72728
|
+
path32 = __toESM(require("path"));
|
|
72729
|
+
fs28 = __toESM(require("fs"));
|
|
71080
72730
|
StateMachineExecutionEngine = class _StateMachineExecutionEngine {
|
|
71081
72731
|
workingDirectory;
|
|
71082
72732
|
executionContext;
|
|
@@ -71308,8 +72958,8 @@ var init_state_machine_execution_engine = __esm({
|
|
|
71308
72958
|
logger.debug(
|
|
71309
72959
|
`[PolicyEngine] Loading enterprise policy engine (engine=${configWithTagFilter.policy.engine})`
|
|
71310
72960
|
);
|
|
71311
|
-
const { loadEnterprisePolicyEngine } = await
|
|
71312
|
-
context2.policyEngine = await
|
|
72961
|
+
const { loadEnterprisePolicyEngine: loadEnterprisePolicyEngine2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
72962
|
+
context2.policyEngine = await loadEnterprisePolicyEngine2(configWithTagFilter.policy);
|
|
71313
72963
|
logger.debug(
|
|
71314
72964
|
`[PolicyEngine] Initialized: ${context2.policyEngine?.constructor?.name || "unknown"}`
|
|
71315
72965
|
);
|
|
@@ -71463,9 +73113,9 @@ var init_state_machine_execution_engine = __esm({
|
|
|
71463
73113
|
}
|
|
71464
73114
|
const checkId = String(ev?.checkId || "unknown");
|
|
71465
73115
|
const threadKey = ev?.threadKey || (channel && threadTs ? `${channel}:${threadTs}` : "session");
|
|
71466
|
-
const baseDir = process.env.VISOR_SNAPSHOT_DIR ||
|
|
71467
|
-
|
|
71468
|
-
const filePath =
|
|
73116
|
+
const baseDir = process.env.VISOR_SNAPSHOT_DIR || path32.resolve(process.cwd(), ".visor", "snapshots");
|
|
73117
|
+
fs28.mkdirSync(baseDir, { recursive: true });
|
|
73118
|
+
const filePath = path32.join(baseDir, `${threadKey}-${checkId}.json`);
|
|
71469
73119
|
await this.saveSnapshotToFile(filePath);
|
|
71470
73120
|
logger.info(`[Snapshot] Saved run snapshot: ${filePath}`);
|
|
71471
73121
|
try {
|
|
@@ -71606,7 +73256,7 @@ var init_state_machine_execution_engine = __esm({
|
|
|
71606
73256
|
* Does not include secrets. Intended for debugging and future resume support.
|
|
71607
73257
|
*/
|
|
71608
73258
|
async saveSnapshotToFile(filePath) {
|
|
71609
|
-
const
|
|
73259
|
+
const fs29 = await import("fs/promises");
|
|
71610
73260
|
const ctx = this._lastContext;
|
|
71611
73261
|
const runner = this._lastRunner;
|
|
71612
73262
|
if (!ctx || !runner) {
|
|
@@ -71626,14 +73276,14 @@ var init_state_machine_execution_engine = __esm({
|
|
|
71626
73276
|
journal: entries,
|
|
71627
73277
|
requestedChecks: ctx.requestedChecks || []
|
|
71628
73278
|
};
|
|
71629
|
-
await
|
|
73279
|
+
await fs29.writeFile(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
71630
73280
|
}
|
|
71631
73281
|
/**
|
|
71632
73282
|
* Load a snapshot JSON from file and return it. Resume support can build on this.
|
|
71633
73283
|
*/
|
|
71634
73284
|
async loadSnapshotFromFile(filePath) {
|
|
71635
|
-
const
|
|
71636
|
-
const raw = await
|
|
73285
|
+
const fs29 = await import("fs/promises");
|
|
73286
|
+
const raw = await fs29.readFile(filePath, "utf8");
|
|
71637
73287
|
return JSON.parse(raw);
|
|
71638
73288
|
}
|
|
71639
73289
|
/**
|