@probelabs/visor 0.1.113 → 0.1.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/defaults/workflow-builder.tests.yaml +363 -0
- package/defaults/workflow-builder.yaml +720 -0
- package/dist/ai-review-service.d.ts.map +1 -1
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/defaults/workflow-builder.tests.yaml +363 -0
- package/dist/defaults/workflow-builder.yaml +720 -0
- package/dist/docs/workflow-creation-guide.md +1274 -0
- package/dist/frontends/slack-frontend.d.ts +3 -0
- package/dist/frontends/slack-frontend.d.ts.map +1 -1
- package/dist/generated/config-schema.d.ts +14 -6
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/generated/config-schema.json +14 -6
- package/dist/index.js +36879 -13895
- package/dist/logger.d.ts +9 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/mcp-server.d.ts +4 -4
- package/dist/output/traces/{run-2026-01-21T12-31-10-108Z.ndjson → run-2026-01-28T13-56-32-263Z.ndjson} +84 -84
- package/dist/output/traces/run-2026-01-28T13-57-13-140Z.ndjson +1357 -0
- package/dist/providers/ai-check-provider.d.ts.map +1 -1
- package/dist/providers/check-provider.interface.d.ts +15 -1
- package/dist/providers/check-provider.interface.d.ts.map +1 -1
- package/dist/providers/command-check-provider.d.ts.map +1 -1
- package/dist/providers/git-checkout-provider.d.ts.map +1 -1
- package/dist/sdk/{check-provider-registry-534KL5HT.mjs → check-provider-registry-JMNLGIMJ.mjs} +11 -11
- package/dist/sdk/{chunk-AIVFBIS4.mjs → chunk-35NT3725.mjs} +30 -10
- package/dist/sdk/chunk-35NT3725.mjs.map +1 -0
- package/dist/sdk/{chunk-AGIZJ4UZ.mjs → chunk-3NMLT3YS.mjs} +42 -8
- package/dist/sdk/chunk-3NMLT3YS.mjs.map +1 -0
- package/dist/sdk/{chunk-AK6BVWIT.mjs → chunk-7GUAFV6L.mjs} +2 -2
- package/dist/sdk/{chunk-QY2XYPEV.mjs → chunk-CUNPH6TR.mjs} +18 -10
- package/dist/sdk/chunk-CUNPH6TR.mjs.map +1 -0
- package/dist/sdk/{chunk-HTOKWMPO.mjs → chunk-HQL734ZI.mjs} +2 -2
- package/dist/sdk/{chunk-7UK3NIIT.mjs → chunk-IHZOSIF4.mjs} +2 -2
- package/dist/sdk/{chunk-AUT26LHW.mjs → chunk-J2QWVDXK.mjs} +2 -2
- package/dist/sdk/{chunk-QR7MOMJH.mjs → chunk-J6EVEXC2.mjs} +2 -2
- package/dist/sdk/{chunk-SIWNBRTK.mjs → chunk-SWEEZ5D5.mjs} +3 -3
- package/dist/sdk/{chunk-23L3QRYX.mjs → chunk-VPEQOQ7G.mjs} +279 -70
- package/dist/sdk/chunk-VPEQOQ7G.mjs.map +1 -0
- package/dist/sdk/{command-executor-TYUV6HUS.mjs → command-executor-Q7MHJKZJ.mjs} +3 -3
- package/dist/sdk/{config-YNC2EOOT.mjs → config-MK4XTU45.mjs} +3 -3
- package/dist/sdk/{failure-condition-evaluator-YGTF2GHG.mjs → failure-condition-evaluator-HB35XRLZ.mjs} +4 -4
- package/dist/sdk/{github-frontend-SIAEOCON.mjs → github-frontend-6Q4BISZX.mjs} +4 -4
- package/dist/sdk/{host-DXUYTNMU.mjs → host-P5NQICP7.mjs} +3 -3
- package/dist/sdk/{liquid-extensions-PKWCKK7E.mjs → liquid-extensions-DFDEBMUI.mjs} +4 -4
- package/dist/sdk/{memory-store-XGBB7LX7.mjs → memory-store-RW5N2NGJ.mjs} +3 -3
- package/dist/sdk/{prompt-state-YRJY6QAL.mjs → prompt-state-EZYOUG75.mjs} +3 -3
- package/dist/sdk/{renderer-schema-LPKN5UJS.mjs → renderer-schema-CKFB5NDB.mjs} +2 -2
- package/dist/sdk/{routing-6N45MJ4F.mjs → routing-KZ345OFG.mjs} +5 -5
- package/dist/sdk/sdk.d.mts +19 -1
- package/dist/sdk/sdk.d.ts +19 -1
- package/dist/sdk/sdk.js +421 -75
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +35 -18
- package/dist/sdk/sdk.mjs.map +1 -1
- package/dist/sdk/{slack-frontend-BVKW3GD5.mjs → slack-frontend-J442FJWZ.mjs} +61 -3
- package/dist/sdk/slack-frontend-J442FJWZ.mjs.map +1 -0
- package/dist/sdk/{workflow-registry-R6KSACFR.mjs → workflow-registry-6LZKCWHP.mjs} +3 -3
- package/dist/state-machine/context/build-engine-context.d.ts.map +1 -1
- package/dist/state-machine/dispatch/history-snapshot.d.ts.map +1 -1
- package/dist/state-machine/runner.d.ts.map +1 -1
- package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
- package/dist/state-machine/states/routing.d.ts.map +1 -1
- package/dist/state-machine/states/wave-planning.d.ts.map +1 -1
- package/dist/ter-u14b.json +17826 -0
- package/dist/ter-u14n.json +17826 -0
- package/dist/test-runner/index.d.ts.map +1 -1
- package/dist/traces/{run-2026-01-21T12-31-10-108Z.ndjson → run-2026-01-28T13-56-32-263Z.ndjson} +84 -84
- package/dist/traces/run-2026-01-28T13-57-13-140Z.ndjson +1357 -0
- package/dist/tui.d.ts +51 -0
- package/dist/tui.d.ts.map +1 -0
- package/dist/types/cli.d.ts +10 -0
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts +4 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/engine.d.ts +3 -0
- package/dist/types/engine.d.ts.map +1 -1
- package/dist/usr/fonts/AUTHORS +1 -0
- package/dist/usr/fonts/LICENSE +94 -0
- package/dist/usr/fonts/README +340 -0
- package/dist/usr/fonts/ter-u14b.json +17826 -0
- package/dist/usr/fonts/ter-u14n.json +17826 -0
- package/dist/usr/linux +0 -0
- package/dist/usr/windows-ansi +0 -0
- package/dist/usr/xterm +0 -0
- package/dist/usr/xterm-256color +0 -0
- package/dist/usr/xterm.termcap +243 -0
- package/dist/usr/xterm.terminfo +1977 -0
- package/dist/utils/workspace-manager.d.ts +2 -0
- package/dist/utils/workspace-manager.d.ts.map +1 -1
- package/dist/utils/worktree-manager.d.ts +5 -0
- package/dist/utils/worktree-manager.d.ts.map +1 -1
- package/dist/xterm +0 -0
- package/dist/xterm.termcap +243 -0
- package/package.json +9 -7
- package/dist/output/traces/run-2026-01-21T12-32-04-510Z.ndjson +0 -1067
- package/dist/sdk/chunk-23L3QRYX.mjs.map +0 -1
- package/dist/sdk/chunk-AGIZJ4UZ.mjs.map +0 -1
- package/dist/sdk/chunk-AIVFBIS4.mjs.map +0 -1
- package/dist/sdk/chunk-QY2XYPEV.mjs.map +0 -1
- package/dist/sdk/slack-frontend-BVKW3GD5.mjs.map +0 -1
- package/dist/traces/run-2026-01-21T12-32-04-510Z.ndjson +0 -1067
- /package/dist/sdk/{check-provider-registry-534KL5HT.mjs.map → check-provider-registry-JMNLGIMJ.mjs.map} +0 -0
- /package/dist/sdk/{chunk-AK6BVWIT.mjs.map → chunk-7GUAFV6L.mjs.map} +0 -0
- /package/dist/sdk/{chunk-HTOKWMPO.mjs.map → chunk-HQL734ZI.mjs.map} +0 -0
- /package/dist/sdk/{chunk-7UK3NIIT.mjs.map → chunk-IHZOSIF4.mjs.map} +0 -0
- /package/dist/sdk/{chunk-AUT26LHW.mjs.map → chunk-J2QWVDXK.mjs.map} +0 -0
- /package/dist/sdk/{chunk-QR7MOMJH.mjs.map → chunk-J6EVEXC2.mjs.map} +0 -0
- /package/dist/sdk/{chunk-SIWNBRTK.mjs.map → chunk-SWEEZ5D5.mjs.map} +0 -0
- /package/dist/sdk/{command-executor-TYUV6HUS.mjs.map → command-executor-Q7MHJKZJ.mjs.map} +0 -0
- /package/dist/sdk/{config-YNC2EOOT.mjs.map → config-MK4XTU45.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-YGTF2GHG.mjs.map → failure-condition-evaluator-HB35XRLZ.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-SIAEOCON.mjs.map → github-frontend-6Q4BISZX.mjs.map} +0 -0
- /package/dist/sdk/{host-DXUYTNMU.mjs.map → host-P5NQICP7.mjs.map} +0 -0
- /package/dist/sdk/{liquid-extensions-PKWCKK7E.mjs.map → liquid-extensions-DFDEBMUI.mjs.map} +0 -0
- /package/dist/sdk/{memory-store-XGBB7LX7.mjs.map → memory-store-RW5N2NGJ.mjs.map} +0 -0
- /package/dist/sdk/{prompt-state-YRJY6QAL.mjs.map → prompt-state-EZYOUG75.mjs.map} +0 -0
- /package/dist/sdk/{renderer-schema-LPKN5UJS.mjs.map → renderer-schema-CKFB5NDB.mjs.map} +0 -0
- /package/dist/sdk/{routing-6N45MJ4F.mjs.map → routing-KZ345OFG.mjs.map} +0 -0
- /package/dist/sdk/{workflow-registry-R6KSACFR.mjs.map → workflow-registry-6LZKCWHP.mjs.map} +0 -0
package/dist/sdk/sdk.js
CHANGED
|
@@ -211,6 +211,10 @@ var init_logger = __esm({
|
|
|
211
211
|
isTTY = typeof process !== "undefined" ? !!process.stderr.isTTY : false;
|
|
212
212
|
showTimestamps = true;
|
|
213
213
|
// default: always show timestamps
|
|
214
|
+
sink;
|
|
215
|
+
sinkPassthrough = true;
|
|
216
|
+
sinkErrorMode = "throw";
|
|
217
|
+
sinkErrorHandler;
|
|
214
218
|
configure(opts = {}) {
|
|
215
219
|
let lvl = "info";
|
|
216
220
|
if (opts.debug || process.env.VISOR_DEBUG === "true") {
|
|
@@ -231,6 +235,12 @@ var init_logger = __esm({
|
|
|
231
235
|
const output = opts.outputFormat || process.env.VISOR_OUTPUT_FORMAT || "table";
|
|
232
236
|
this.isJsonLike = output === "json" || output === "sarif";
|
|
233
237
|
}
|
|
238
|
+
setSink(sink, opts = {}) {
|
|
239
|
+
this.sink = sink;
|
|
240
|
+
this.sinkPassthrough = opts.passthrough !== void 0 ? opts.passthrough : true;
|
|
241
|
+
this.sinkErrorMode = opts.errorMode || "throw";
|
|
242
|
+
this.sinkErrorHandler = opts.onError;
|
|
243
|
+
}
|
|
234
244
|
shouldLog(level) {
|
|
235
245
|
const desired = levelToNumber(level);
|
|
236
246
|
const current = levelToNumber(this.level);
|
|
@@ -253,14 +263,38 @@ var init_logger = __esm({
|
|
|
253
263
|
}
|
|
254
264
|
}
|
|
255
265
|
write(msg, level) {
|
|
266
|
+
const suffix = this.getTraceSuffix(msg);
|
|
267
|
+
const decoratedMsg = suffix ? `${msg}${suffix}` : msg;
|
|
268
|
+
const lvl = level || "info";
|
|
269
|
+
if (this.sink) {
|
|
270
|
+
try {
|
|
271
|
+
this.sink(decoratedMsg, lvl);
|
|
272
|
+
} catch (error) {
|
|
273
|
+
if (this.sinkErrorMode === "warn") {
|
|
274
|
+
try {
|
|
275
|
+
if (this.sinkErrorHandler) {
|
|
276
|
+
this.sinkErrorHandler(error);
|
|
277
|
+
} else {
|
|
278
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
279
|
+
process.stderr.write(`[logger] sink failed: ${errMsg}
|
|
280
|
+
`);
|
|
281
|
+
}
|
|
282
|
+
} catch {
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (this.sinkErrorMode === "throw") {
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (!this.sinkPassthrough) return;
|
|
291
|
+
}
|
|
256
292
|
try {
|
|
257
|
-
const suffix = this.getTraceSuffix(msg);
|
|
258
|
-
const decoratedMsg = suffix ? `${msg}${suffix}` : msg;
|
|
259
293
|
if (this.showTimestamps) {
|
|
260
294
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
261
|
-
const
|
|
295
|
+
const lvl2 = level ? level : void 0;
|
|
262
296
|
let tsToken = `[${ts}]`;
|
|
263
|
-
let lvlToken =
|
|
297
|
+
let lvlToken = lvl2 ? `[${lvl2}]` : "";
|
|
264
298
|
if (this.isTTY && !this.isJsonLike) {
|
|
265
299
|
const reset = "\x1B[0m";
|
|
266
300
|
const dim = "\x1B[2m";
|
|
@@ -278,14 +312,14 @@ var init_logger = __esm({
|
|
|
278
312
|
// bright black / gray
|
|
279
313
|
};
|
|
280
314
|
tsToken = `${dim}${tsToken}${reset}`;
|
|
281
|
-
if (
|
|
282
|
-
const colour = colours[
|
|
315
|
+
if (lvl2) {
|
|
316
|
+
const colour = colours[lvl2] || "";
|
|
283
317
|
if (colour) {
|
|
284
318
|
lvlToken = `${colour}${lvlToken}${reset}`;
|
|
285
319
|
}
|
|
286
320
|
}
|
|
287
321
|
}
|
|
288
|
-
const prefix =
|
|
322
|
+
const prefix = lvl2 ? `${tsToken} ${lvlToken}` : tsToken;
|
|
289
323
|
process.stderr.write(`${prefix} ${decoratedMsg}
|
|
290
324
|
`);
|
|
291
325
|
} else {
|
|
@@ -1163,22 +1197,41 @@ async function handleWavePlanning(context2, state, transition) {
|
|
|
1163
1197
|
if (gotoEvent) {
|
|
1164
1198
|
eventOverrides.set(target, gotoEvent);
|
|
1165
1199
|
}
|
|
1200
|
+
const sourceCheck = request.sourceCheck;
|
|
1201
|
+
if (sourceCheck && request.origin === "run") {
|
|
1202
|
+
if (!state.allowedFailedDeps) {
|
|
1203
|
+
state.allowedFailedDeps = /* @__PURE__ */ new Map();
|
|
1204
|
+
}
|
|
1205
|
+
const allowedSet = state.allowedFailedDeps.get(target) || /* @__PURE__ */ new Set();
|
|
1206
|
+
allowedSet.add(sourceCheck);
|
|
1207
|
+
state.allowedFailedDeps.set(target, allowedSet);
|
|
1208
|
+
if (context2.debug) {
|
|
1209
|
+
logger.info(
|
|
1210
|
+
`[WavePlanning] Allowing ${target} to run despite failed dependency ${sourceCheck}`
|
|
1211
|
+
);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
const origin = request.origin;
|
|
1166
1215
|
const dependencies = findTransitiveDependencies(target, context2);
|
|
1167
1216
|
for (const dep of dependencies) {
|
|
1168
1217
|
const stats = state.stats.get(dep);
|
|
1169
1218
|
const hasSucceeded = !!stats && (stats.successfulRuns || 0) > 0;
|
|
1219
|
+
const hasRun = !!stats && (stats.totalRuns || 0) > 0;
|
|
1220
|
+
if (origin === "run" && hasRun) {
|
|
1221
|
+
continue;
|
|
1222
|
+
}
|
|
1170
1223
|
if (!hasSucceeded) {
|
|
1171
1224
|
checksToRun.add(dep);
|
|
1172
1225
|
}
|
|
1173
1226
|
}
|
|
1174
1227
|
let shouldIncludeDependents = true;
|
|
1175
1228
|
try {
|
|
1176
|
-
const
|
|
1229
|
+
const origin2 = request.origin;
|
|
1177
1230
|
const cfg = context2.config.checks?.[target];
|
|
1178
1231
|
const targetType = String(cfg?.type || "").toLowerCase();
|
|
1179
1232
|
const execCtx = context2.executionContext || {};
|
|
1180
1233
|
const hasWebhook = !!execCtx.webhookContext;
|
|
1181
|
-
if (hasWebhook && (
|
|
1234
|
+
if (hasWebhook && (origin2 === "goto" || origin2 === "goto_js") && targetType === "human-input") {
|
|
1182
1235
|
shouldIncludeDependents = false;
|
|
1183
1236
|
}
|
|
1184
1237
|
} catch {
|
|
@@ -3302,6 +3355,12 @@ function createMemoryHelpers() {
|
|
|
3302
3355
|
}
|
|
3303
3356
|
};
|
|
3304
3357
|
}
|
|
3358
|
+
function getHistoryLimit() {
|
|
3359
|
+
const raw = process.env.VISOR_TEST_HISTORY_LIMIT || process.env.VISOR_OUTPUT_HISTORY_LIMIT;
|
|
3360
|
+
if (!raw) return void 0;
|
|
3361
|
+
const n = parseInt(raw, 10);
|
|
3362
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
3363
|
+
}
|
|
3305
3364
|
function formatScopeLabel(scope) {
|
|
3306
3365
|
if (!scope || scope.length === 0) return "";
|
|
3307
3366
|
return scope.map((item) => `${item.check}:${item.index}`).join("|");
|
|
@@ -3902,7 +3961,9 @@ async function processOnFail(checkId, scope, result, checkConfig, context2, stat
|
|
|
3902
3961
|
type: "ForwardRunRequested",
|
|
3903
3962
|
target: targetCheck,
|
|
3904
3963
|
scope: itemScope,
|
|
3905
|
-
origin: "run"
|
|
3964
|
+
origin: "run",
|
|
3965
|
+
sourceCheck: checkId
|
|
3966
|
+
// The failed check that triggered on_fail.run
|
|
3906
3967
|
});
|
|
3907
3968
|
}
|
|
3908
3969
|
} else {
|
|
@@ -3919,7 +3980,9 @@ async function processOnFail(checkId, scope, result, checkConfig, context2, stat
|
|
|
3919
3980
|
type: "ForwardRunRequested",
|
|
3920
3981
|
target: targetCheck,
|
|
3921
3982
|
scope,
|
|
3922
|
-
origin: "run"
|
|
3983
|
+
origin: "run",
|
|
3984
|
+
sourceCheck: checkId
|
|
3985
|
+
// The failed check that triggered on_fail.run
|
|
3923
3986
|
});
|
|
3924
3987
|
}
|
|
3925
3988
|
}
|
|
@@ -3962,7 +4025,9 @@ async function processOnFail(checkId, scope, result, checkConfig, context2, stat
|
|
|
3962
4025
|
type: "ForwardRunRequested",
|
|
3963
4026
|
target: targetCheck,
|
|
3964
4027
|
scope,
|
|
3965
|
-
origin: "run_js"
|
|
4028
|
+
origin: "run_js",
|
|
4029
|
+
sourceCheck: checkId
|
|
4030
|
+
// The failed check that triggered on_fail.run_js
|
|
3966
4031
|
});
|
|
3967
4032
|
}
|
|
3968
4033
|
}
|
|
@@ -4109,6 +4174,7 @@ async function processOnFail(checkId, scope, result, checkConfig, context2, stat
|
|
|
4109
4174
|
async function evaluateRunJs(runJs, checkId, checkConfig, result, context2, _state) {
|
|
4110
4175
|
try {
|
|
4111
4176
|
const sandbox = createSecureSandbox();
|
|
4177
|
+
const historyLimit = getHistoryLimit();
|
|
4112
4178
|
const snapshotId = context2.journal.beginSnapshot();
|
|
4113
4179
|
const contextView = new (init_snapshot_store(), __toCommonJS(snapshot_store_exports)).ContextView(
|
|
4114
4180
|
context2.journal,
|
|
@@ -4133,7 +4199,8 @@ async function evaluateRunJs(runJs, checkId, checkConfig, result, context2, _sta
|
|
|
4133
4199
|
try {
|
|
4134
4200
|
const history = contextView.getHistory(checkIdFromJournal);
|
|
4135
4201
|
if (history && history.length > 0) {
|
|
4136
|
-
|
|
4202
|
+
const trimmed = historyLimit && history.length > historyLimit ? history.slice(history.length - historyLimit) : history;
|
|
4203
|
+
outputsHistory[checkIdFromJournal] = trimmed.map(
|
|
4137
4204
|
(r) => r.output !== void 0 ? r.output : r
|
|
4138
4205
|
);
|
|
4139
4206
|
}
|
|
@@ -4215,6 +4282,7 @@ async function evaluateGoto(gotoJs, gotoStatic, checkId, checkConfig, result, co
|
|
|
4215
4282
|
if (gotoJs) {
|
|
4216
4283
|
try {
|
|
4217
4284
|
const sandbox = createSecureSandbox();
|
|
4285
|
+
const historyLimit = getHistoryLimit();
|
|
4218
4286
|
const snapshotId = context2.journal.beginSnapshot();
|
|
4219
4287
|
const contextView = new (init_snapshot_store(), __toCommonJS(snapshot_store_exports)).ContextView(
|
|
4220
4288
|
context2.journal,
|
|
@@ -4239,7 +4307,8 @@ async function evaluateGoto(gotoJs, gotoStatic, checkId, checkConfig, result, co
|
|
|
4239
4307
|
try {
|
|
4240
4308
|
const history = contextView.getHistory(checkIdFromJournal);
|
|
4241
4309
|
if (history && history.length > 0) {
|
|
4242
|
-
|
|
4310
|
+
const trimmed = historyLimit && history.length > historyLimit ? history.slice(history.length - historyLimit) : history;
|
|
4311
|
+
outputsHistory[checkIdFromJournal] = trimmed.map(
|
|
4243
4312
|
(r) => r.output !== void 0 ? r.output : r
|
|
4244
4313
|
);
|
|
4245
4314
|
}
|
|
@@ -4342,6 +4411,7 @@ async function evaluateTransitions(transitions, checkId, checkConfig, result, co
|
|
|
4342
4411
|
if (!transitions || transitions.length === 0) return void 0;
|
|
4343
4412
|
try {
|
|
4344
4413
|
const sandbox = createSecureSandbox();
|
|
4414
|
+
const historyLimit = getHistoryLimit();
|
|
4345
4415
|
const snapshotId = context2.journal.beginSnapshot();
|
|
4346
4416
|
const ContextView2 = (init_snapshot_store(), __toCommonJS(snapshot_store_exports)).ContextView;
|
|
4347
4417
|
const view = new ContextView2(context2.journal, context2.sessionId, snapshotId, [], void 0);
|
|
@@ -4358,7 +4428,10 @@ async function evaluateTransitions(transitions, checkId, checkConfig, result, co
|
|
|
4358
4428
|
try {
|
|
4359
4429
|
const hist = view.getHistory(cid);
|
|
4360
4430
|
if (hist && hist.length > 0) {
|
|
4361
|
-
|
|
4431
|
+
const trimmed = historyLimit && hist.length > historyLimit ? hist.slice(hist.length - historyLimit) : hist;
|
|
4432
|
+
outputsHistory[cid] = trimmed.map(
|
|
4433
|
+
(r) => r.output !== void 0 ? r.output : r
|
|
4434
|
+
);
|
|
4362
4435
|
}
|
|
4363
4436
|
} catch {
|
|
4364
4437
|
}
|
|
@@ -4516,8 +4589,15 @@ var history_snapshot_exports = {};
|
|
|
4516
4589
|
__export(history_snapshot_exports, {
|
|
4517
4590
|
buildOutputHistoryFromJournal: () => buildOutputHistoryFromJournal
|
|
4518
4591
|
});
|
|
4592
|
+
function getHistoryLimit2() {
|
|
4593
|
+
const raw = process.env.VISOR_TEST_HISTORY_LIMIT || process.env.VISOR_OUTPUT_HISTORY_LIMIT;
|
|
4594
|
+
if (!raw) return void 0;
|
|
4595
|
+
const n = parseInt(raw, 10);
|
|
4596
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
4597
|
+
}
|
|
4519
4598
|
function buildOutputHistoryFromJournal(context2) {
|
|
4520
4599
|
const outputHistory = /* @__PURE__ */ new Map();
|
|
4600
|
+
const limit = getHistoryLimit2();
|
|
4521
4601
|
try {
|
|
4522
4602
|
const snapshot = context2.journal.beginSnapshot();
|
|
4523
4603
|
const allEntries = context2.journal.readVisible(context2.sessionId, snapshot, void 0);
|
|
@@ -4539,7 +4619,13 @@ function buildOutputHistoryFromJournal(context2) {
|
|
|
4539
4619
|
}
|
|
4540
4620
|
} catch {
|
|
4541
4621
|
}
|
|
4542
|
-
if (payload !== void 0)
|
|
4622
|
+
if (payload !== void 0) {
|
|
4623
|
+
const arr = outputHistory.get(checkId);
|
|
4624
|
+
arr.push(payload);
|
|
4625
|
+
if (limit && arr.length > limit) {
|
|
4626
|
+
arr.splice(0, arr.length - limit);
|
|
4627
|
+
}
|
|
4628
|
+
}
|
|
4543
4629
|
}
|
|
4544
4630
|
} catch (error) {
|
|
4545
4631
|
logger.debug(`[LevelDispatch] Error building output history: ${error}`);
|
|
@@ -5757,8 +5843,8 @@ var init_ai_review_service = __esm({
|
|
|
5757
5843
|
sessionRegistry;
|
|
5758
5844
|
constructor(config = {}) {
|
|
5759
5845
|
this.config = {
|
|
5760
|
-
timeout:
|
|
5761
|
-
// Increased timeout to
|
|
5846
|
+
timeout: 12e5,
|
|
5847
|
+
// Increased timeout to 20 minutes for AI responses
|
|
5762
5848
|
...config
|
|
5763
5849
|
};
|
|
5764
5850
|
this.sessionRegistry = SessionRegistry.getInstance();
|
|
@@ -5853,12 +5939,10 @@ var init_ai_review_service = __esm({
|
|
|
5853
5939
|
}
|
|
5854
5940
|
}
|
|
5855
5941
|
if (!this.config.apiKey) {
|
|
5856
|
-
|
|
5942
|
+
log("\u26A0\uFE0F No API key configured - ProbeAgent will attempt CLI fallback (claude-code/codex)");
|
|
5857
5943
|
if (debugInfo) {
|
|
5858
|
-
debugInfo.errors = [
|
|
5859
|
-
debugInfo.
|
|
5860
|
-
} else {
|
|
5861
|
-
throw new Error(errorMessage);
|
|
5944
|
+
debugInfo.errors = debugInfo.errors || [];
|
|
5945
|
+
debugInfo.errors.push("No API key configured - attempting CLI fallback");
|
|
5862
5946
|
}
|
|
5863
5947
|
}
|
|
5864
5948
|
}
|
|
@@ -7010,6 +7094,9 @@ ${"=".repeat(60)}
|
|
|
7010
7094
|
options.model = this.config.model;
|
|
7011
7095
|
}
|
|
7012
7096
|
const agent = new import_probe2.ProbeAgent(options);
|
|
7097
|
+
if (typeof agent.initialize === "function") {
|
|
7098
|
+
await agent.initialize();
|
|
7099
|
+
}
|
|
7013
7100
|
log("\u{1F680} Calling ProbeAgent...");
|
|
7014
7101
|
let schemaString = void 0;
|
|
7015
7102
|
let effectiveSchema = typeof schema === "object" ? "custom" : schema;
|
|
@@ -9299,10 +9386,18 @@ var init_ai_check_provider = __esm({
|
|
|
9299
9386
|
if (info && typeof info.workspacePath === "string") {
|
|
9300
9387
|
workspaceRoot = info.workspacePath;
|
|
9301
9388
|
mainProjectPath = info.mainProjectPath;
|
|
9302
|
-
folders.push(info.workspacePath);
|
|
9303
9389
|
}
|
|
9304
9390
|
} catch {
|
|
9305
9391
|
}
|
|
9392
|
+
if (mainProjectPath) {
|
|
9393
|
+
folders.push(mainProjectPath);
|
|
9394
|
+
logger.debug(
|
|
9395
|
+
`[AI Provider] Including main project FIRST in allowedFolders: ${mainProjectPath}`
|
|
9396
|
+
);
|
|
9397
|
+
}
|
|
9398
|
+
if (workspaceRoot) {
|
|
9399
|
+
folders.push(workspaceRoot);
|
|
9400
|
+
}
|
|
9306
9401
|
const projectPaths = [];
|
|
9307
9402
|
try {
|
|
9308
9403
|
const projects = workspace.listProjects?.() || [];
|
|
@@ -9314,27 +9409,16 @@ var init_ai_check_provider = __esm({
|
|
|
9314
9409
|
}
|
|
9315
9410
|
} catch {
|
|
9316
9411
|
}
|
|
9317
|
-
if (projectPaths.length === 0 && mainProjectPath) {
|
|
9318
|
-
folders.push(mainProjectPath);
|
|
9319
|
-
logger.debug(
|
|
9320
|
-
`[AI Provider] No external projects - including main project as fallback: ${mainProjectPath}`
|
|
9321
|
-
);
|
|
9322
|
-
} else if (mainProjectPath) {
|
|
9323
|
-
logger.debug(
|
|
9324
|
-
`[AI Provider] Excluding main project (visor) from allowedFolders: ${mainProjectPath}`
|
|
9325
|
-
);
|
|
9326
|
-
}
|
|
9327
9412
|
const unique = Array.from(new Set(folders.filter((p) => typeof p === "string" && p)));
|
|
9328
9413
|
if (unique.length > 0 && workspaceRoot) {
|
|
9329
9414
|
aiConfig.allowedFolders = unique;
|
|
9330
|
-
|
|
9331
|
-
aiConfig.
|
|
9332
|
-
aiConfig.
|
|
9415
|
+
const aiCwd = mainProjectPath || workspaceRoot;
|
|
9416
|
+
aiConfig.path = aiCwd;
|
|
9417
|
+
aiConfig.cwd = aiCwd;
|
|
9418
|
+
aiConfig.workspacePath = aiCwd;
|
|
9333
9419
|
logger.debug(`[AI Provider] Workspace isolation enabled:`);
|
|
9334
|
-
logger.debug(`[AI Provider]
|
|
9335
|
-
logger.debug(
|
|
9336
|
-
`[AI Provider] mainProjectPath (excluded unless fallback): ${mainProjectPath || "N/A"}`
|
|
9337
|
-
);
|
|
9420
|
+
logger.debug(`[AI Provider] cwd (mainProjectPath): ${aiCwd}`);
|
|
9421
|
+
logger.debug(`[AI Provider] workspaceRoot: ${workspaceRoot}`);
|
|
9338
9422
|
logger.debug(`[AI Provider] allowedFolders: ${JSON.stringify(unique)}`);
|
|
9339
9423
|
}
|
|
9340
9424
|
} else if (parentCtx && typeof parentCtx.workingDirectory === "string") {
|
|
@@ -9502,10 +9586,15 @@ ${processedPrompt}` : processedPrompt;
|
|
|
9502
9586
|
const stepName = config.checkName || "unknown";
|
|
9503
9587
|
const mock = sessionInfo?.hooks?.mockForStep?.(String(stepName));
|
|
9504
9588
|
if (mock !== void 0) {
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9589
|
+
const ms = mock;
|
|
9590
|
+
const issuesArr = Array.isArray(ms?.issues) ? ms.issues : [];
|
|
9591
|
+
const out = ms && typeof ms === "object" && "output" in ms ? ms.output : ms;
|
|
9592
|
+
const summary = {
|
|
9593
|
+
issues: issuesArr,
|
|
9594
|
+
output: out,
|
|
9595
|
+
...typeof ms?.content === "string" ? { content: String(ms.content) } : {}
|
|
9596
|
+
};
|
|
9597
|
+
return summary;
|
|
9509
9598
|
}
|
|
9510
9599
|
} catch {
|
|
9511
9600
|
}
|
|
@@ -11964,7 +12053,17 @@ var init_command_check_provider = __esm({
|
|
|
11964
12053
|
}
|
|
11965
12054
|
try {
|
|
11966
12055
|
const stepName = config.checkName || "unknown";
|
|
12056
|
+
if (process.env.VISOR_DEBUG === "true") {
|
|
12057
|
+
logger.debug(
|
|
12058
|
+
`[Command] Mock check: stepName=${stepName}, context=${!!context2}, hooks=${!!context2?.hooks}, mockForStep=${!!context2?.hooks?.mockForStep}`
|
|
12059
|
+
);
|
|
12060
|
+
}
|
|
11967
12061
|
const rawMock = context2?.hooks?.mockForStep?.(String(stepName));
|
|
12062
|
+
if (process.env.VISOR_DEBUG === "true") {
|
|
12063
|
+
logger.debug(
|
|
12064
|
+
`[Command] Mock result: ${rawMock !== void 0 ? "found" : "not found"}, value=${JSON.stringify(rawMock)?.slice(0, 200)}`
|
|
12065
|
+
);
|
|
12066
|
+
}
|
|
11968
12067
|
if (rawMock !== void 0) {
|
|
11969
12068
|
let mock;
|
|
11970
12069
|
if (typeof rawMock === "number") {
|
|
@@ -11989,6 +12088,16 @@ var init_command_check_provider = __esm({
|
|
|
11989
12088
|
out = mock;
|
|
11990
12089
|
}
|
|
11991
12090
|
const code = isCommandMock ? typeof m.exit_code === "number" ? m.exit_code : typeof m.exit === "number" ? m.exit : 0 : 0;
|
|
12091
|
+
let outputWithMeta;
|
|
12092
|
+
if (isCommandMock) {
|
|
12093
|
+
if (out && typeof out === "object" && !Array.isArray(out)) {
|
|
12094
|
+
outputWithMeta = { ...out, exit_code: code };
|
|
12095
|
+
} else {
|
|
12096
|
+
outputWithMeta = { value: out, exit_code: code };
|
|
12097
|
+
}
|
|
12098
|
+
} else {
|
|
12099
|
+
outputWithMeta = out;
|
|
12100
|
+
}
|
|
11992
12101
|
if (code !== 0) {
|
|
11993
12102
|
return {
|
|
11994
12103
|
issues: [
|
|
@@ -12001,10 +12110,10 @@ var init_command_check_provider = __esm({
|
|
|
12001
12110
|
category: "logic"
|
|
12002
12111
|
}
|
|
12003
12112
|
],
|
|
12004
|
-
output:
|
|
12113
|
+
output: outputWithMeta
|
|
12005
12114
|
};
|
|
12006
12115
|
}
|
|
12007
|
-
return { issues: [], output:
|
|
12116
|
+
return { issues: [], output: outputWithMeta };
|
|
12008
12117
|
}
|
|
12009
12118
|
} catch {
|
|
12010
12119
|
}
|
|
@@ -17417,7 +17526,7 @@ var init_config_schema = __esm({
|
|
|
17417
17526
|
description: "Arguments/inputs for the workflow"
|
|
17418
17527
|
},
|
|
17419
17528
|
overrides: {
|
|
17420
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-11359-23556-src_types_config.ts-0-
|
|
17529
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-11359-23556-src_types_config.ts-0-41044%3E%3E",
|
|
17421
17530
|
description: "Override specific step configurations in the workflow"
|
|
17422
17531
|
},
|
|
17423
17532
|
output_mapping: {
|
|
@@ -17433,7 +17542,7 @@ var init_config_schema = __esm({
|
|
|
17433
17542
|
description: "Config file path - alternative to workflow ID (loads a Visor config file as workflow)"
|
|
17434
17543
|
},
|
|
17435
17544
|
workflow_overrides: {
|
|
17436
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-11359-23556-src_types_config.ts-0-
|
|
17545
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-11359-23556-src_types_config.ts-0-41044%3E%3E",
|
|
17437
17546
|
description: "Alias for overrides - workflow step overrides (backward compatibility)"
|
|
17438
17547
|
},
|
|
17439
17548
|
ref: {
|
|
@@ -18063,7 +18172,7 @@ var init_config_schema = __esm({
|
|
|
18063
18172
|
description: "Custom output name (defaults to workflow name)"
|
|
18064
18173
|
},
|
|
18065
18174
|
overrides: {
|
|
18066
|
-
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-11359-23556-src_types_config.ts-0-
|
|
18175
|
+
$ref: "#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-11359-23556-src_types_config.ts-0-41044%3E%3E",
|
|
18067
18176
|
description: "Step overrides"
|
|
18068
18177
|
},
|
|
18069
18178
|
output_mapping: {
|
|
@@ -18078,13 +18187,13 @@ var init_config_schema = __esm({
|
|
|
18078
18187
|
"^x-": {}
|
|
18079
18188
|
}
|
|
18080
18189
|
},
|
|
18081
|
-
"Record<string,Partial<interface-src_types_config.ts-11359-23556-src_types_config.ts-0-
|
|
18190
|
+
"Record<string,Partial<interface-src_types_config.ts-11359-23556-src_types_config.ts-0-41044>>": {
|
|
18082
18191
|
type: "object",
|
|
18083
18192
|
additionalProperties: {
|
|
18084
|
-
$ref: "#/definitions/Partial%3Cinterface-src_types_config.ts-11359-23556-src_types_config.ts-0-
|
|
18193
|
+
$ref: "#/definitions/Partial%3Cinterface-src_types_config.ts-11359-23556-src_types_config.ts-0-41044%3E"
|
|
18085
18194
|
}
|
|
18086
18195
|
},
|
|
18087
|
-
"Partial<interface-src_types_config.ts-11359-23556-src_types_config.ts-0-
|
|
18196
|
+
"Partial<interface-src_types_config.ts-11359-23556-src_types_config.ts-0-41044>": {
|
|
18088
18197
|
type: "object",
|
|
18089
18198
|
additionalProperties: false
|
|
18090
18199
|
},
|
|
@@ -18655,6 +18764,14 @@ var init_config_schema = __esm({
|
|
|
18655
18764
|
type: "string",
|
|
18656
18765
|
description: "Base path for workspaces (default: /tmp/visor-workspaces)"
|
|
18657
18766
|
},
|
|
18767
|
+
name: {
|
|
18768
|
+
type: "string",
|
|
18769
|
+
description: "Workspace directory name (defaults to session id)"
|
|
18770
|
+
},
|
|
18771
|
+
main_project_name: {
|
|
18772
|
+
type: "string",
|
|
18773
|
+
description: "Main project folder name inside the workspace (defaults to original directory name)"
|
|
18774
|
+
},
|
|
18658
18775
|
cleanup_on_exit: {
|
|
18659
18776
|
type: "boolean",
|
|
18660
18777
|
description: "Clean up workspace on exit (default: true)"
|
|
@@ -20635,25 +20752,76 @@ var init_worktree_manager = __esm({
|
|
|
20635
20752
|
}
|
|
20636
20753
|
if (fs14.existsSync(worktreePath)) {
|
|
20637
20754
|
logger.debug(`Worktree already exists: ${worktreePath}`);
|
|
20638
|
-
if (options.clean) {
|
|
20639
|
-
logger.debug(`Cleaning existing worktree`);
|
|
20640
|
-
await this.cleanWorktree(worktreePath);
|
|
20641
|
-
}
|
|
20642
20755
|
const metadata2 = await this.loadMetadata(worktreePath);
|
|
20643
20756
|
if (metadata2) {
|
|
20644
|
-
|
|
20645
|
-
|
|
20646
|
-
|
|
20647
|
-
|
|
20648
|
-
|
|
20649
|
-
|
|
20650
|
-
|
|
20651
|
-
|
|
20652
|
-
|
|
20757
|
+
if (metadata2.ref === ref) {
|
|
20758
|
+
if (options.clean) {
|
|
20759
|
+
logger.debug(`Cleaning existing worktree`);
|
|
20760
|
+
await this.cleanWorktree(worktreePath);
|
|
20761
|
+
}
|
|
20762
|
+
this.activeWorktrees.set(worktreeId, metadata2);
|
|
20763
|
+
return {
|
|
20764
|
+
id: worktreeId,
|
|
20765
|
+
path: worktreePath,
|
|
20766
|
+
ref: metadata2.ref,
|
|
20767
|
+
commit: metadata2.commit,
|
|
20768
|
+
metadata: metadata2,
|
|
20769
|
+
locked: false
|
|
20770
|
+
};
|
|
20771
|
+
} else {
|
|
20772
|
+
logger.info(
|
|
20773
|
+
`Worktree exists with different ref (${metadata2.ref} -> ${ref}), updating...`
|
|
20774
|
+
);
|
|
20775
|
+
try {
|
|
20776
|
+
const bareRepoPath2 = metadata2.bare_repo_path || await this.getOrCreateBareRepo(
|
|
20777
|
+
repository,
|
|
20778
|
+
repoUrl,
|
|
20779
|
+
options.token,
|
|
20780
|
+
options.fetchDepth,
|
|
20781
|
+
options.cloneTimeoutMs
|
|
20782
|
+
);
|
|
20783
|
+
await this.fetchRef(bareRepoPath2, ref);
|
|
20784
|
+
const newCommit = await this.getCommitShaForRef(bareRepoPath2, ref);
|
|
20785
|
+
const checkoutCmd = `git -C ${this.escapeShellArg(worktreePath)} checkout --detach ${this.escapeShellArg(newCommit)}`;
|
|
20786
|
+
const checkoutResult = await this.executeGitCommand(checkoutCmd, { timeout: 6e4 });
|
|
20787
|
+
if (checkoutResult.exitCode !== 0) {
|
|
20788
|
+
throw new Error(`Failed to checkout new ref: ${checkoutResult.stderr}`);
|
|
20789
|
+
}
|
|
20790
|
+
const updatedMetadata = {
|
|
20791
|
+
...metadata2,
|
|
20792
|
+
ref,
|
|
20793
|
+
commit: newCommit,
|
|
20794
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
20795
|
+
};
|
|
20796
|
+
await this.saveMetadata(worktreePath, updatedMetadata);
|
|
20797
|
+
if (options.clean) {
|
|
20798
|
+
logger.debug(`Cleaning updated worktree`);
|
|
20799
|
+
await this.cleanWorktree(worktreePath);
|
|
20800
|
+
}
|
|
20801
|
+
this.activeWorktrees.set(worktreeId, updatedMetadata);
|
|
20802
|
+
logger.info(`Successfully updated worktree to ${ref} (${newCommit})`);
|
|
20803
|
+
return {
|
|
20804
|
+
id: worktreeId,
|
|
20805
|
+
path: worktreePath,
|
|
20806
|
+
ref,
|
|
20807
|
+
commit: newCommit,
|
|
20808
|
+
metadata: updatedMetadata,
|
|
20809
|
+
locked: false
|
|
20810
|
+
};
|
|
20811
|
+
} catch (error) {
|
|
20812
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
20813
|
+
logger.warn(`Failed to update worktree, will recreate: ${errorMessage}`);
|
|
20814
|
+
await fsp.rm(worktreePath, { recursive: true, force: true });
|
|
20815
|
+
}
|
|
20816
|
+
}
|
|
20817
|
+
} else {
|
|
20818
|
+
logger.info(`Removing stale directory (no metadata): ${worktreePath}`);
|
|
20819
|
+
await fsp.rm(worktreePath, { recursive: true, force: true });
|
|
20653
20820
|
}
|
|
20654
20821
|
}
|
|
20655
20822
|
await this.fetchRef(bareRepoPath, ref);
|
|
20656
20823
|
const commit = await this.getCommitShaForRef(bareRepoPath, ref);
|
|
20824
|
+
await this.pruneWorktrees(bareRepoPath);
|
|
20657
20825
|
logger.info(`Creating worktree for ${repository}@${ref} (${commit})`);
|
|
20658
20826
|
const createCmd = `git -C ${this.escapeShellArg(
|
|
20659
20827
|
bareRepoPath
|
|
@@ -20686,6 +20854,20 @@ var init_worktree_manager = __esm({
|
|
|
20686
20854
|
locked: false
|
|
20687
20855
|
};
|
|
20688
20856
|
}
|
|
20857
|
+
/**
|
|
20858
|
+
* Prune stale worktree entries from a bare repository.
|
|
20859
|
+
* This removes entries for worktrees whose directories no longer exist.
|
|
20860
|
+
*/
|
|
20861
|
+
async pruneWorktrees(bareRepoPath) {
|
|
20862
|
+
logger.debug(`Pruning stale worktrees for ${bareRepoPath}`);
|
|
20863
|
+
const pruneCmd = `git -C ${this.escapeShellArg(bareRepoPath)} worktree prune`;
|
|
20864
|
+
const result = await this.executeGitCommand(pruneCmd, { timeout: 1e4 });
|
|
20865
|
+
if (result.exitCode !== 0) {
|
|
20866
|
+
logger.warn(`Failed to prune worktrees: ${result.stderr}`);
|
|
20867
|
+
} else {
|
|
20868
|
+
logger.debug(`Successfully pruned stale worktrees`);
|
|
20869
|
+
}
|
|
20870
|
+
}
|
|
20689
20871
|
/**
|
|
20690
20872
|
* Fetch a specific ref in bare repository
|
|
20691
20873
|
*/
|
|
@@ -21046,6 +21228,53 @@ var init_git_checkout_provider = __esm({
|
|
|
21046
21228
|
async execute(prInfo, config, dependencyResults, context2) {
|
|
21047
21229
|
const checkoutConfig = config;
|
|
21048
21230
|
const issues = [];
|
|
21231
|
+
try {
|
|
21232
|
+
const stepName = config.checkName || "git-checkout";
|
|
21233
|
+
if (process.env.VISOR_DEBUG === "true") {
|
|
21234
|
+
logger.debug(
|
|
21235
|
+
`[GitCheckout] Mock check: stepName=${stepName}, context=${!!context2}, hooks=${!!context2?.hooks}, mockForStep=${!!context2?.hooks?.mockForStep}`
|
|
21236
|
+
);
|
|
21237
|
+
}
|
|
21238
|
+
const mock = context2?.hooks?.mockForStep?.(String(stepName));
|
|
21239
|
+
if (process.env.VISOR_DEBUG === "true") {
|
|
21240
|
+
logger.debug(
|
|
21241
|
+
`[GitCheckout] Mock result: ${mock !== void 0 ? "found" : "not found"}, value=${JSON.stringify(mock)}`
|
|
21242
|
+
);
|
|
21243
|
+
}
|
|
21244
|
+
if (mock !== void 0) {
|
|
21245
|
+
if (mock && typeof mock === "object") {
|
|
21246
|
+
const mockOutput = mock;
|
|
21247
|
+
if (mockOutput.success === false) {
|
|
21248
|
+
const errorMsg = String(mockOutput.error || "Mocked checkout failure");
|
|
21249
|
+
if (process.env.VISOR_DEBUG === "true") {
|
|
21250
|
+
logger.debug(`[GitCheckout] Returning mock failure: ${errorMsg}`);
|
|
21251
|
+
}
|
|
21252
|
+
return {
|
|
21253
|
+
issues: [
|
|
21254
|
+
{
|
|
21255
|
+
file: "git-checkout",
|
|
21256
|
+
line: 0,
|
|
21257
|
+
ruleId: "git-checkout/error",
|
|
21258
|
+
message: `Failed to checkout code: ${errorMsg}`,
|
|
21259
|
+
severity: "error",
|
|
21260
|
+
category: "logic"
|
|
21261
|
+
}
|
|
21262
|
+
],
|
|
21263
|
+
output: mockOutput
|
|
21264
|
+
};
|
|
21265
|
+
}
|
|
21266
|
+
if (process.env.VISOR_DEBUG === "true") {
|
|
21267
|
+
logger.debug(`[GitCheckout] Returning mock success: ${JSON.stringify(mockOutput)}`);
|
|
21268
|
+
}
|
|
21269
|
+
return { issues: [], output: mockOutput };
|
|
21270
|
+
}
|
|
21271
|
+
if (process.env.VISOR_DEBUG === "true") {
|
|
21272
|
+
logger.debug(`[GitCheckout] Returning primitive mock: ${String(mock)}`);
|
|
21273
|
+
}
|
|
21274
|
+
return { issues: [], output: { success: true, path: String(mock) } };
|
|
21275
|
+
}
|
|
21276
|
+
} catch {
|
|
21277
|
+
}
|
|
21049
21278
|
try {
|
|
21050
21279
|
const templateContext = this.buildTemplateContext(
|
|
21051
21280
|
prInfo,
|
|
@@ -21548,7 +21777,7 @@ async function executeCheckWithForEachItems(checkId, forEachParent, forEachItems
|
|
|
21548
21777
|
__outputHistory: outputHistory,
|
|
21549
21778
|
ai: {
|
|
21550
21779
|
...checkConfig.ai || {},
|
|
21551
|
-
timeout: checkConfig.ai?.timeout ||
|
|
21780
|
+
timeout: checkConfig.ai?.timeout || 12e5,
|
|
21552
21781
|
debug: !!context2.debug
|
|
21553
21782
|
}
|
|
21554
21783
|
};
|
|
@@ -22028,7 +22257,7 @@ async function executeInvocation(item, context2, scope, prInfo, dependencyResult
|
|
|
22028
22257
|
__outputHistory: outputHistory,
|
|
22029
22258
|
ai: {
|
|
22030
22259
|
...stepConfig.ai || {},
|
|
22031
|
-
timeout: stepConfig.ai?.timeout ||
|
|
22260
|
+
timeout: stepConfig.ai?.timeout || 12e5,
|
|
22032
22261
|
debug: !!context2.debug
|
|
22033
22262
|
}
|
|
22034
22263
|
};
|
|
@@ -22504,7 +22733,7 @@ async function executeSingleCheck(checkId, context2, state, emitEvent, transitio
|
|
|
22504
22733
|
__outputHistory: outputHistory,
|
|
22505
22734
|
ai: {
|
|
22506
22735
|
...checkConfig.ai || {},
|
|
22507
|
-
timeout: checkConfig.ai?.timeout ||
|
|
22736
|
+
timeout: checkConfig.ai?.timeout || 12e5,
|
|
22508
22737
|
debug: !!context2.debug
|
|
22509
22738
|
}
|
|
22510
22739
|
};
|
|
@@ -22857,8 +23086,15 @@ function recordOnFinishRoutingEvent(args) {
|
|
|
22857
23086
|
if (args.gotoEvent) attrs.goto_event = args.gotoEvent;
|
|
22858
23087
|
addEvent("visor.routing", attrs);
|
|
22859
23088
|
}
|
|
23089
|
+
function getHistoryLimit3() {
|
|
23090
|
+
const raw = process.env.VISOR_TEST_HISTORY_LIMIT || process.env.VISOR_OUTPUT_HISTORY_LIMIT;
|
|
23091
|
+
if (!raw) return void 0;
|
|
23092
|
+
const n = parseInt(raw, 10);
|
|
23093
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
23094
|
+
}
|
|
22860
23095
|
function buildOutputHistoryFromJournal2(context2) {
|
|
22861
23096
|
const outputHistory = /* @__PURE__ */ new Map();
|
|
23097
|
+
const limit = getHistoryLimit3();
|
|
22862
23098
|
try {
|
|
22863
23099
|
const snapshot = context2.journal.beginSnapshot();
|
|
22864
23100
|
const allEntries = context2.journal.readVisible(context2.sessionId, snapshot, void 0);
|
|
@@ -22868,7 +23104,13 @@ function buildOutputHistoryFromJournal2(context2) {
|
|
|
22868
23104
|
outputHistory.set(checkId, []);
|
|
22869
23105
|
}
|
|
22870
23106
|
const payload = entry.result.output !== void 0 ? entry.result.output : entry.result;
|
|
22871
|
-
if (payload !== void 0)
|
|
23107
|
+
if (payload !== void 0) {
|
|
23108
|
+
const arr = outputHistory.get(checkId);
|
|
23109
|
+
arr.push(payload);
|
|
23110
|
+
if (limit && arr.length > limit) {
|
|
23111
|
+
arr.splice(0, arr.length - limit);
|
|
23112
|
+
}
|
|
23113
|
+
}
|
|
22872
23114
|
}
|
|
22873
23115
|
} catch (error) {
|
|
22874
23116
|
logger.debug(`[LevelDispatch] Error building output history: ${error}`);
|
|
@@ -23281,7 +23523,7 @@ async function executeCheckWithForEachItems2(checkId, forEachParent, forEachItem
|
|
|
23281
23523
|
__outputHistory: outputHistory,
|
|
23282
23524
|
ai: {
|
|
23283
23525
|
...checkConfig.ai || {},
|
|
23284
|
-
timeout: checkConfig.ai?.timeout ||
|
|
23526
|
+
timeout: checkConfig.ai?.timeout || 12e5,
|
|
23285
23527
|
debug: !!context2.debug
|
|
23286
23528
|
}
|
|
23287
23529
|
};
|
|
@@ -24057,10 +24299,20 @@ async function executeSingleCheck2(checkId, context2, state, emitEvent, transiti
|
|
|
24057
24299
|
const dependencies = checkConfig?.depends_on || [];
|
|
24058
24300
|
const depList = Array.isArray(dependencies) ? dependencies : [dependencies];
|
|
24059
24301
|
const failedChecks = state.failedChecks;
|
|
24302
|
+
const allowedFailedDeps = state.allowedFailedDeps?.get(checkId);
|
|
24060
24303
|
const tokens = depList.filter(Boolean);
|
|
24061
24304
|
const groupSatisfied = (token) => {
|
|
24062
24305
|
const options = token.includes("|") ? token.split("|").map((s) => s.trim()).filter(Boolean) : [token];
|
|
24063
24306
|
for (const opt of options) {
|
|
24307
|
+
const isAllowedFailedDep = !!(allowedFailedDeps && allowedFailedDeps.has(opt));
|
|
24308
|
+
if (isAllowedFailedDep) {
|
|
24309
|
+
if (context2.debug) {
|
|
24310
|
+
logger.info(
|
|
24311
|
+
`[LevelDispatch] Allowing ${checkId} to run despite failed dependency ${opt} (on_fail.run)`
|
|
24312
|
+
);
|
|
24313
|
+
}
|
|
24314
|
+
return true;
|
|
24315
|
+
}
|
|
24064
24316
|
const depCfg = context2.config.checks?.[opt];
|
|
24065
24317
|
const cont = !!(depCfg && depCfg.continue_on_failure === true);
|
|
24066
24318
|
const st = state.stats.get(opt);
|
|
@@ -24299,7 +24551,7 @@ async function executeSingleCheck2(checkId, context2, state, emitEvent, transiti
|
|
|
24299
24551
|
checksMeta,
|
|
24300
24552
|
ai: {
|
|
24301
24553
|
...checkConfig2.ai || {},
|
|
24302
|
-
timeout: checkConfig2.ai?.timeout ||
|
|
24554
|
+
timeout: checkConfig2.ai?.timeout || 12e5,
|
|
24303
24555
|
debug: !!context2.debug
|
|
24304
24556
|
}
|
|
24305
24557
|
};
|
|
@@ -25373,6 +25625,25 @@ var init_runner = __esm({
|
|
|
25373
25625
|
}
|
|
25374
25626
|
} catch {
|
|
25375
25627
|
}
|
|
25628
|
+
if (event.type === "CheckCompleted") {
|
|
25629
|
+
try {
|
|
25630
|
+
const hook = this.context.executionContext?.hooks?.onCheckComplete;
|
|
25631
|
+
if (typeof hook === "function") {
|
|
25632
|
+
const checkConfig = this.context.config?.checks?.[event.checkId];
|
|
25633
|
+
hook({
|
|
25634
|
+
checkId: event.checkId,
|
|
25635
|
+
result: event.result,
|
|
25636
|
+
checkConfig: checkConfig ? {
|
|
25637
|
+
type: checkConfig.type,
|
|
25638
|
+
group: checkConfig.group,
|
|
25639
|
+
criticality: checkConfig.criticality,
|
|
25640
|
+
schema: checkConfig.schema
|
|
25641
|
+
} : void 0
|
|
25642
|
+
});
|
|
25643
|
+
}
|
|
25644
|
+
} catch {
|
|
25645
|
+
}
|
|
25646
|
+
}
|
|
25376
25647
|
if (this.context.debug && event.type !== "StateTransition") {
|
|
25377
25648
|
logger.debug(`[StateMachine] Event: ${event.type}`);
|
|
25378
25649
|
}
|
|
@@ -26122,14 +26393,19 @@ var init_workspace_manager = __esm({
|
|
|
26122
26393
|
constructor(sessionId, originalPath, config) {
|
|
26123
26394
|
this.sessionId = sessionId;
|
|
26124
26395
|
this.originalPath = originalPath;
|
|
26396
|
+
const configuredName = config?.name || process.env.VISOR_WORKSPACE_NAME;
|
|
26397
|
+
const configuredMainProjectName = config?.mainProjectName || process.env.VISOR_WORKSPACE_PROJECT;
|
|
26125
26398
|
this.config = {
|
|
26126
26399
|
enabled: true,
|
|
26127
26400
|
basePath: process.env.VISOR_WORKSPACE_PATH || "/tmp/visor-workspaces",
|
|
26128
26401
|
cleanupOnExit: true,
|
|
26402
|
+
name: configuredName,
|
|
26403
|
+
mainProjectName: configuredMainProjectName,
|
|
26129
26404
|
...config
|
|
26130
26405
|
};
|
|
26131
26406
|
this.basePath = this.config.basePath;
|
|
26132
|
-
|
|
26407
|
+
const workspaceDirName = sanitizePathComponent(this.config.name || this.sessionId);
|
|
26408
|
+
this.workspacePath = path18.join(this.basePath, workspaceDirName);
|
|
26133
26409
|
}
|
|
26134
26410
|
/**
|
|
26135
26411
|
* Get or create a WorkspaceManager instance for a session
|
|
@@ -26186,7 +26462,10 @@ var init_workspace_manager = __esm({
|
|
|
26186
26462
|
logger.info(`Initializing workspace: ${this.workspacePath}`);
|
|
26187
26463
|
await fsp2.mkdir(this.workspacePath, { recursive: true });
|
|
26188
26464
|
logger.debug(`Created workspace directory: ${this.workspacePath}`);
|
|
26189
|
-
const
|
|
26465
|
+
const configuredMainProjectName = this.config.mainProjectName;
|
|
26466
|
+
const mainProjectName = sanitizePathComponent(
|
|
26467
|
+
configuredMainProjectName || this.extractProjectName(this.originalPath)
|
|
26468
|
+
);
|
|
26190
26469
|
this.usedNames.add(mainProjectName);
|
|
26191
26470
|
const mainProjectPath = path18.join(this.workspacePath, mainProjectName);
|
|
26192
26471
|
const isGitRepo = await this.isGitRepository(this.originalPath);
|
|
@@ -26462,12 +26741,21 @@ async function initializeWorkspace(context2) {
|
|
|
26462
26741
|
const workspace = WorkspaceManager.getInstance(context2.sessionId, originalPath, {
|
|
26463
26742
|
enabled: true,
|
|
26464
26743
|
basePath: workspaceConfig?.base_path || process.env.VISOR_WORKSPACE_PATH || "/tmp/visor-workspaces",
|
|
26465
|
-
cleanupOnExit: keepWorkspace ? false : workspaceConfig?.cleanup_on_exit !== false
|
|
26744
|
+
cleanupOnExit: keepWorkspace ? false : workspaceConfig?.cleanup_on_exit !== false,
|
|
26745
|
+
name: workspaceConfig?.name || process.env.VISOR_WORKSPACE_NAME,
|
|
26746
|
+
mainProjectName: workspaceConfig?.main_project_name || process.env.VISOR_WORKSPACE_PROJECT
|
|
26466
26747
|
});
|
|
26467
26748
|
const info = await workspace.initialize();
|
|
26468
26749
|
context2.workspace = workspace;
|
|
26469
26750
|
context2.workingDirectory = info.mainProjectPath;
|
|
26470
26751
|
context2.originalWorkingDirectory = originalPath;
|
|
26752
|
+
try {
|
|
26753
|
+
process.env.VISOR_WORKSPACE_ROOT = info.workspacePath;
|
|
26754
|
+
process.env.VISOR_WORKSPACE_MAIN_PROJECT = info.mainProjectPath;
|
|
26755
|
+
process.env.VISOR_WORKSPACE_MAIN_PROJECT_NAME = info.mainProjectName;
|
|
26756
|
+
process.env.VISOR_ORIGINAL_WORKDIR = originalPath;
|
|
26757
|
+
} catch {
|
|
26758
|
+
}
|
|
26471
26759
|
logger.info(`[Workspace] Initialized workspace: ${info.workspacePath}`);
|
|
26472
26760
|
logger.debug(`[Workspace] Main project at: ${info.mainProjectPath}`);
|
|
26473
26761
|
if (keepWorkspace) {
|
|
@@ -28381,6 +28669,7 @@ var init_slack_frontend = __esm({
|
|
|
28381
28669
|
ackRef = null;
|
|
28382
28670
|
ackName = "eyes";
|
|
28383
28671
|
doneName = "thumbsup";
|
|
28672
|
+
errorNotified = false;
|
|
28384
28673
|
constructor(config) {
|
|
28385
28674
|
this.cfg = config || {};
|
|
28386
28675
|
}
|
|
@@ -28413,6 +28702,14 @@ var init_slack_frontend = __esm({
|
|
|
28413
28702
|
});
|
|
28414
28703
|
})
|
|
28415
28704
|
);
|
|
28705
|
+
this.subs.push(
|
|
28706
|
+
bus.on("CheckErrored", async (env) => {
|
|
28707
|
+
const ev = env && env.payload || env;
|
|
28708
|
+
const message = ev?.error?.message || "Execution error";
|
|
28709
|
+
await this.maybePostError(ctx, "Check failed", message, ev?.checkId).catch(() => {
|
|
28710
|
+
});
|
|
28711
|
+
})
|
|
28712
|
+
);
|
|
28416
28713
|
this.subs.push(
|
|
28417
28714
|
bus.on("StateTransition", async (env) => {
|
|
28418
28715
|
const ev = env && env.payload || env;
|
|
@@ -28422,6 +28719,14 @@ var init_slack_frontend = __esm({
|
|
|
28422
28719
|
}
|
|
28423
28720
|
})
|
|
28424
28721
|
);
|
|
28722
|
+
this.subs.push(
|
|
28723
|
+
bus.on("Shutdown", async (env) => {
|
|
28724
|
+
const ev = env && env.payload || env;
|
|
28725
|
+
const message = ev?.error?.message || "Fatal error";
|
|
28726
|
+
await this.maybePostError(ctx, "Run failed", message).catch(() => {
|
|
28727
|
+
});
|
|
28728
|
+
})
|
|
28729
|
+
);
|
|
28425
28730
|
this.subs.push(
|
|
28426
28731
|
bus.on("CheckScheduled", async () => {
|
|
28427
28732
|
await this.ensureAcknowledgement(ctx).catch(() => {
|
|
@@ -28532,6 +28837,47 @@ var init_slack_frontend = __esm({
|
|
|
28532
28837
|
}
|
|
28533
28838
|
return null;
|
|
28534
28839
|
}
|
|
28840
|
+
isTelemetryEnabled(ctx) {
|
|
28841
|
+
try {
|
|
28842
|
+
const anyCfg = ctx.config || {};
|
|
28843
|
+
const slackCfg = anyCfg.slack || {};
|
|
28844
|
+
const telemetryCfg = slackCfg.telemetry ?? this.cfg?.telemetry;
|
|
28845
|
+
return telemetryCfg === true || telemetryCfg && typeof telemetryCfg === "object" && telemetryCfg.enabled === true;
|
|
28846
|
+
} catch {
|
|
28847
|
+
return false;
|
|
28848
|
+
}
|
|
28849
|
+
}
|
|
28850
|
+
async maybePostError(ctx, title, message, checkId) {
|
|
28851
|
+
if (this.errorNotified) return;
|
|
28852
|
+
if (!this.isTelemetryEnabled(ctx)) return;
|
|
28853
|
+
const slack = this.getSlack(ctx);
|
|
28854
|
+
if (!slack) return;
|
|
28855
|
+
const payload = this.getInboundSlackPayload(ctx);
|
|
28856
|
+
const ev = payload?.event;
|
|
28857
|
+
const channel = String(ev?.channel || "");
|
|
28858
|
+
const threadTs = String(ev?.thread_ts || ev?.ts || ev?.event_ts || "");
|
|
28859
|
+
if (!channel || !threadTs) return;
|
|
28860
|
+
let text = `\u274C ${title}`;
|
|
28861
|
+
if (checkId) text += `
|
|
28862
|
+
Check: ${checkId}`;
|
|
28863
|
+
if (message) text += `
|
|
28864
|
+
${message}`;
|
|
28865
|
+
const traceInfo = this.getTraceInfo();
|
|
28866
|
+
if (traceInfo?.traceId) {
|
|
28867
|
+
text += `
|
|
28868
|
+
|
|
28869
|
+
\`trace_id: ${traceInfo.traceId}\``;
|
|
28870
|
+
}
|
|
28871
|
+
const formattedText = formatSlackText(text);
|
|
28872
|
+
await slack.chat.postMessage({ channel, text: formattedText, thread_ts: threadTs });
|
|
28873
|
+
try {
|
|
28874
|
+
ctx.logger.info(
|
|
28875
|
+
`[slack-frontend] posted error notice to ${channel} thread=${threadTs} check=${checkId || "run"}`
|
|
28876
|
+
);
|
|
28877
|
+
} catch {
|
|
28878
|
+
}
|
|
28879
|
+
this.errorNotified = true;
|
|
28880
|
+
}
|
|
28535
28881
|
async ensureAcknowledgement(ctx) {
|
|
28536
28882
|
if (this.acked) return;
|
|
28537
28883
|
const ref = this.getInboundSlackEvent(ctx);
|