@probelabs/visor 0.1.92 → 0.1.94
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/.visor.yaml +15 -16
- package/dist/check-execution-engine.d.ts +11 -0
- package/dist/check-execution-engine.d.ts.map +1 -1
- package/dist/config.d.ts +3 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/defaults/.visor.yaml +15 -16
- package/dist/index.js +587 -646
- package/dist/liquid-extensions.d.ts +12 -0
- package/dist/liquid-extensions.d.ts.map +1 -1
- package/dist/output/issue-assistant/schema.json +14 -1
- package/dist/providers/command-check-provider.d.ts.map +1 -1
- package/dist/providers/log-check-provider.d.ts.map +1 -1
- package/dist/providers/memory-check-provider.d.ts.map +1 -1
- package/dist/reviewer.d.ts +8 -0
- package/dist/reviewer.d.ts.map +1 -1
- package/dist/sdk/{check-execution-engine-L73PFZQY.mjs → check-execution-engine-YBRPVUWD.mjs} +3 -3
- package/dist/sdk/{chunk-LJHRU3WQ.mjs → chunk-DQRFOQAP.mjs} +160 -41
- package/dist/sdk/chunk-DQRFOQAP.mjs.map +1 -0
- package/dist/sdk/{chunk-2U6BIWSY.mjs → chunk-I3GQJIR7.mjs} +14 -10
- package/dist/sdk/chunk-I3GQJIR7.mjs.map +1 -0
- package/dist/sdk/{liquid-extensions-AFKRYROF.mjs → liquid-extensions-GMEGEGC3.mjs} +6 -2
- package/dist/sdk/sdk.d.mts +11 -2
- package/dist/sdk/sdk.d.ts +11 -2
- package/dist/sdk/sdk.js +202 -50
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +36 -7
- package/dist/sdk/sdk.mjs.map +1 -1
- package/dist/sdk.d.ts +11 -2
- package/dist/sdk.d.ts.map +1 -1
- package/dist/traces/{run-2025-10-15T07-21-47-696Z.ndjson → run-2025-10-16T11-33-32-682Z.ndjson} +19 -3
- package/dist/traces/{run-2025-10-15T07-21-58-106Z.ndjson → run-2025-10-16T11-33-43-618Z.ndjson} +19 -3
- package/dist/traces/{run-2025-10-15T07-21-58-693Z.ndjson → run-2025-10-16T11-33-44-157Z.ndjson} +19 -3
- package/dist/traces/{run-2025-10-15T07-21-59-167Z.ndjson → run-2025-10-16T11-33-44-647Z.ndjson} +19 -3
- package/dist/traces/{run-2025-10-15T07-21-59-629Z.ndjson → run-2025-10-16T11-33-45-128Z.ndjson} +4 -0
- package/package.json +2 -2
- package/dist/sdk/chunk-2U6BIWSY.mjs.map +0 -1
- package/dist/sdk/chunk-LJHRU3WQ.mjs.map +0 -1
- /package/dist/sdk/{check-execution-engine-L73PFZQY.mjs.map → check-execution-engine-YBRPVUWD.mjs.map} +0 -0
- /package/dist/sdk/{liquid-extensions-AFKRYROF.mjs.map → liquid-extensions-GMEGEGC3.mjs.map} +0 -0
package/dist/sdk/sdk.js
CHANGED
|
@@ -2424,14 +2424,66 @@ var init_reviewer = __esm({
|
|
|
2424
2424
|
"No configuration provided. Please create a .visor.yaml file with check definitions. Built-in prompts have been removed - all checks must be explicitly configured."
|
|
2425
2425
|
);
|
|
2426
2426
|
}
|
|
2427
|
+
/**
|
|
2428
|
+
* Helper to check if a schema definition has a "text" field in its properties
|
|
2429
|
+
*/
|
|
2430
|
+
async schemaHasTextField(schema) {
|
|
2431
|
+
try {
|
|
2432
|
+
let schemaObj;
|
|
2433
|
+
if (typeof schema === "object") {
|
|
2434
|
+
schemaObj = schema;
|
|
2435
|
+
} else {
|
|
2436
|
+
const fs12 = require("fs").promises;
|
|
2437
|
+
const path12 = require("path");
|
|
2438
|
+
const sanitizedSchemaName = schema.replace(/[^a-zA-Z0-9-]/g, "");
|
|
2439
|
+
if (!sanitizedSchemaName || sanitizedSchemaName !== schema) {
|
|
2440
|
+
return false;
|
|
2441
|
+
}
|
|
2442
|
+
const schemaPath = path12.join(process.cwd(), "output", sanitizedSchemaName, "schema.json");
|
|
2443
|
+
try {
|
|
2444
|
+
const schemaContent = await fs12.readFile(schemaPath, "utf-8");
|
|
2445
|
+
schemaObj = JSON.parse(schemaContent);
|
|
2446
|
+
} catch {
|
|
2447
|
+
return false;
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
const properties = schemaObj.properties;
|
|
2451
|
+
return !!(properties && "text" in properties);
|
|
2452
|
+
} catch {
|
|
2453
|
+
return false;
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
/**
|
|
2457
|
+
* Filter check results to only include those that should post GitHub comments
|
|
2458
|
+
*/
|
|
2459
|
+
async filterCommentGeneratingChecks(checkResults, config) {
|
|
2460
|
+
const filtered = [];
|
|
2461
|
+
for (const r of checkResults) {
|
|
2462
|
+
const cfg = config.checks?.[r.checkName];
|
|
2463
|
+
const type = cfg?.type || "ai";
|
|
2464
|
+
const schema = cfg?.schema;
|
|
2465
|
+
let shouldPostComment = false;
|
|
2466
|
+
const isAICheck = type === "ai" || type === "claude-code";
|
|
2467
|
+
if (!schema || schema === "") {
|
|
2468
|
+
shouldPostComment = isAICheck;
|
|
2469
|
+
} else if (typeof schema === "string") {
|
|
2470
|
+
if (schema === "text" || schema === "plain") {
|
|
2471
|
+
shouldPostComment = true;
|
|
2472
|
+
} else {
|
|
2473
|
+
shouldPostComment = await this.schemaHasTextField(schema);
|
|
2474
|
+
}
|
|
2475
|
+
} else if (typeof schema === "object") {
|
|
2476
|
+
shouldPostComment = await this.schemaHasTextField(schema);
|
|
2477
|
+
}
|
|
2478
|
+
if (shouldPostComment) {
|
|
2479
|
+
filtered.push(r);
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
return filtered;
|
|
2483
|
+
}
|
|
2427
2484
|
async postReviewComment(owner, repo, prNumber, groupedResults, options = {}) {
|
|
2428
2485
|
for (const [groupName, checkResults] of Object.entries(groupedResults)) {
|
|
2429
|
-
const filteredResults = options.config ? checkResults.
|
|
2430
|
-
const cfg = options.config.checks?.[r.checkName];
|
|
2431
|
-
const t = cfg?.type || "";
|
|
2432
|
-
const isGitHubOps = t === "github" || r.group === "github" || t === "noop" || t === "command";
|
|
2433
|
-
return !isGitHubOps;
|
|
2434
|
-
}) : checkResults;
|
|
2486
|
+
const filteredResults = options.config ? await this.filterCommentGeneratingChecks(checkResults, options.config) : checkResults;
|
|
2435
2487
|
if (!filteredResults || filteredResults.length === 0) {
|
|
2436
2488
|
continue;
|
|
2437
2489
|
}
|
|
@@ -3923,8 +3975,19 @@ __export(liquid_extensions_exports, {
|
|
|
3923
3975
|
ReadFileTag: () => ReadFileTag,
|
|
3924
3976
|
configureLiquidWithExtensions: () => configureLiquidWithExtensions,
|
|
3925
3977
|
createExtendedLiquid: () => createExtendedLiquid,
|
|
3978
|
+
sanitizeLabel: () => sanitizeLabel,
|
|
3979
|
+
sanitizeLabelList: () => sanitizeLabelList,
|
|
3926
3980
|
withPermissionsContext: () => withPermissionsContext
|
|
3927
3981
|
});
|
|
3982
|
+
function sanitizeLabel(value) {
|
|
3983
|
+
if (value == null) return "";
|
|
3984
|
+
const s = String(value);
|
|
3985
|
+
return s.replace(/[^A-Za-z0-9:\/]/g, "").replace(/\/{2,}/g, "/");
|
|
3986
|
+
}
|
|
3987
|
+
function sanitizeLabelList(labels) {
|
|
3988
|
+
if (!Array.isArray(labels)) return [];
|
|
3989
|
+
return labels.map((v) => sanitizeLabel(v)).filter((s) => s.length > 0);
|
|
3990
|
+
}
|
|
3928
3991
|
async function withPermissionsContext(ctx, fn) {
|
|
3929
3992
|
return await permissionsALS.run(ctx, fn);
|
|
3930
3993
|
}
|
|
@@ -3947,15 +4010,8 @@ function configureLiquidWithExtensions(liquid) {
|
|
|
3947
4010
|
return "[Error: Unable to serialize to JSON]";
|
|
3948
4011
|
}
|
|
3949
4012
|
});
|
|
3950
|
-
liquid.registerFilter("safe_label", (value) =>
|
|
3951
|
-
|
|
3952
|
-
const s = String(value);
|
|
3953
|
-
return s.replace(/[^A-Za-z0-9:\/]/g, "").replace(/\/{2,}/g, "/");
|
|
3954
|
-
});
|
|
3955
|
-
liquid.registerFilter("safe_label_list", (value) => {
|
|
3956
|
-
if (!Array.isArray(value)) return [];
|
|
3957
|
-
return value.map((v) => v == null ? "" : String(v)).map((s) => s.replace(/[^A-Za-z0-9:\/]/g, "").replace(/\/{2,}/g, "/")).filter((s) => s.length > 0);
|
|
3958
|
-
});
|
|
4013
|
+
liquid.registerFilter("safe_label", (value) => sanitizeLabel(value));
|
|
4014
|
+
liquid.registerFilter("safe_label_list", (value) => sanitizeLabelList(value));
|
|
3959
4015
|
liquid.registerFilter("unescape_newlines", (value) => {
|
|
3960
4016
|
if (value == null) return "";
|
|
3961
4017
|
const s = String(value);
|
|
@@ -5123,7 +5179,8 @@ var init_log_check_provider = __esm({
|
|
|
5123
5179
|
dependencyResults,
|
|
5124
5180
|
includePrContext,
|
|
5125
5181
|
includeDependencies,
|
|
5126
|
-
includeMetadata
|
|
5182
|
+
includeMetadata,
|
|
5183
|
+
config.__outputHistory
|
|
5127
5184
|
);
|
|
5128
5185
|
const renderedMessage = await this.liquid.parseAndRender(message, templateContext);
|
|
5129
5186
|
const logOutput = this.formatLogOutput(
|
|
@@ -5144,7 +5201,7 @@ var init_log_check_provider = __esm({
|
|
|
5144
5201
|
logOutput
|
|
5145
5202
|
};
|
|
5146
5203
|
}
|
|
5147
|
-
buildTemplateContext(prInfo, dependencyResults, _includePrContext = true, _includeDependencies = true, includeMetadata = true) {
|
|
5204
|
+
buildTemplateContext(prInfo, dependencyResults, _includePrContext = true, _includeDependencies = true, includeMetadata = true, outputHistory) {
|
|
5148
5205
|
const context2 = {};
|
|
5149
5206
|
context2.pr = {
|
|
5150
5207
|
number: prInfo.number,
|
|
@@ -5168,6 +5225,7 @@ var init_log_check_provider = __esm({
|
|
|
5168
5225
|
if (dependencyResults) {
|
|
5169
5226
|
const dependencies = {};
|
|
5170
5227
|
const outputs = {};
|
|
5228
|
+
const history = {};
|
|
5171
5229
|
context2.dependencyCount = dependencyResults.size;
|
|
5172
5230
|
for (const [checkName, result] of dependencyResults.entries()) {
|
|
5173
5231
|
dependencies[checkName] = {
|
|
@@ -5178,6 +5236,12 @@ var init_log_check_provider = __esm({
|
|
|
5178
5236
|
const summary = result;
|
|
5179
5237
|
outputs[checkName] = summary.output !== void 0 ? summary.output : summary;
|
|
5180
5238
|
}
|
|
5239
|
+
if (outputHistory) {
|
|
5240
|
+
for (const [checkName, historyArray] of outputHistory) {
|
|
5241
|
+
history[checkName] = historyArray;
|
|
5242
|
+
}
|
|
5243
|
+
}
|
|
5244
|
+
outputs.history = history;
|
|
5181
5245
|
context2.dependencies = dependencies;
|
|
5182
5246
|
context2.outputs = outputs;
|
|
5183
5247
|
}
|
|
@@ -6080,7 +6144,10 @@ var init_command_check_provider = __esm({
|
|
|
6080
6144
|
},
|
|
6081
6145
|
files: prInfo.files,
|
|
6082
6146
|
fileCount: prInfo.files.length,
|
|
6083
|
-
outputs: this.buildOutputContext(
|
|
6147
|
+
outputs: this.buildOutputContext(
|
|
6148
|
+
dependencyResults,
|
|
6149
|
+
config.__outputHistory
|
|
6150
|
+
),
|
|
6084
6151
|
env: this.getSafeEnvironmentVariables()
|
|
6085
6152
|
};
|
|
6086
6153
|
logger.debug(
|
|
@@ -6806,16 +6873,23 @@ ${stderrOutput}` : `Command execution failed: ${errorMessage}`;
|
|
|
6806
6873
|
};
|
|
6807
6874
|
}
|
|
6808
6875
|
}
|
|
6809
|
-
buildOutputContext(dependencyResults) {
|
|
6876
|
+
buildOutputContext(dependencyResults, outputHistory) {
|
|
6810
6877
|
if (!dependencyResults) {
|
|
6811
6878
|
return {};
|
|
6812
6879
|
}
|
|
6813
6880
|
const outputs = {};
|
|
6881
|
+
const history = {};
|
|
6814
6882
|
for (const [checkName, result] of dependencyResults) {
|
|
6815
6883
|
const summary = result;
|
|
6816
6884
|
const value = summary.output !== void 0 ? summary.output : summary;
|
|
6817
6885
|
outputs[checkName] = this.makeJsonSmart(value);
|
|
6818
6886
|
}
|
|
6887
|
+
if (outputHistory) {
|
|
6888
|
+
for (const [checkName, historyArray] of outputHistory) {
|
|
6889
|
+
history[checkName] = historyArray.map((val) => this.makeJsonSmart(val));
|
|
6890
|
+
}
|
|
6891
|
+
}
|
|
6892
|
+
outputs.history = history;
|
|
6819
6893
|
return outputs;
|
|
6820
6894
|
}
|
|
6821
6895
|
/**
|
|
@@ -7373,7 +7447,12 @@ var init_memory_check_provider = __esm({
|
|
|
7373
7447
|
const key = config.key;
|
|
7374
7448
|
const namespace = config.namespace;
|
|
7375
7449
|
const memoryStore = MemoryStore.getInstance();
|
|
7376
|
-
const templateContext = this.buildTemplateContext(
|
|
7450
|
+
const templateContext = this.buildTemplateContext(
|
|
7451
|
+
prInfo,
|
|
7452
|
+
dependencyResults,
|
|
7453
|
+
memoryStore,
|
|
7454
|
+
config.__outputHistory
|
|
7455
|
+
);
|
|
7377
7456
|
let result;
|
|
7378
7457
|
try {
|
|
7379
7458
|
switch (operation) {
|
|
@@ -7656,7 +7735,7 @@ var init_memory_check_provider = __esm({
|
|
|
7656
7735
|
/**
|
|
7657
7736
|
* Build template context for Liquid and JS evaluation
|
|
7658
7737
|
*/
|
|
7659
|
-
buildTemplateContext(prInfo, dependencyResults, memoryStore) {
|
|
7738
|
+
buildTemplateContext(prInfo, dependencyResults, memoryStore, outputHistory) {
|
|
7660
7739
|
const context2 = {};
|
|
7661
7740
|
context2.pr = {
|
|
7662
7741
|
number: prInfo.number,
|
|
@@ -7675,14 +7754,21 @@ var init_memory_check_provider = __esm({
|
|
|
7675
7754
|
changes: f.changes
|
|
7676
7755
|
}))
|
|
7677
7756
|
};
|
|
7757
|
+
const outputs = {};
|
|
7758
|
+
const history = {};
|
|
7678
7759
|
if (dependencyResults) {
|
|
7679
|
-
const outputs = {};
|
|
7680
7760
|
for (const [checkName, result] of dependencyResults.entries()) {
|
|
7681
7761
|
const summary = result;
|
|
7682
7762
|
outputs[checkName] = summary.output !== void 0 ? summary.output : summary;
|
|
7683
7763
|
}
|
|
7684
|
-
context2.outputs = outputs;
|
|
7685
7764
|
}
|
|
7765
|
+
if (outputHistory) {
|
|
7766
|
+
for (const [checkName, historyArray] of outputHistory) {
|
|
7767
|
+
history[checkName] = historyArray;
|
|
7768
|
+
}
|
|
7769
|
+
}
|
|
7770
|
+
outputs.history = history;
|
|
7771
|
+
context2.outputs = outputs;
|
|
7686
7772
|
if (memoryStore) {
|
|
7687
7773
|
context2.memory = {
|
|
7688
7774
|
get: (key, ns) => memoryStore.get(key, ns),
|
|
@@ -10677,6 +10763,8 @@ var init_check_execution_engine = __esm({
|
|
|
10677
10763
|
webhookContext;
|
|
10678
10764
|
routingSandbox;
|
|
10679
10765
|
executionStats = /* @__PURE__ */ new Map();
|
|
10766
|
+
// Track history of all outputs for each check (useful for loops and goto)
|
|
10767
|
+
outputHistory = /* @__PURE__ */ new Map();
|
|
10680
10768
|
// Event override to simulate alternate event (used during routing goto)
|
|
10681
10769
|
routingEventOverride;
|
|
10682
10770
|
// Cached GitHub context for context elevation when running in Actions
|
|
@@ -10696,6 +10784,18 @@ var init_check_execution_engine = __esm({
|
|
|
10696
10784
|
this.mockOctokit = this.createMockOctokit();
|
|
10697
10785
|
this.reviewer = new PRReviewer(this.mockOctokit);
|
|
10698
10786
|
}
|
|
10787
|
+
/**
|
|
10788
|
+
* Enrich event context with authenticated octokit instance
|
|
10789
|
+
* @param eventContext - The event context to enrich
|
|
10790
|
+
* @returns Enriched event context with octokit if available
|
|
10791
|
+
*/
|
|
10792
|
+
enrichEventContext(eventContext) {
|
|
10793
|
+
const baseContext = eventContext || {};
|
|
10794
|
+
if (this.actionContext?.octokit) {
|
|
10795
|
+
return { ...baseContext, octokit: this.actionContext.octokit };
|
|
10796
|
+
}
|
|
10797
|
+
return baseContext;
|
|
10798
|
+
}
|
|
10699
10799
|
/**
|
|
10700
10800
|
* Lazily create a secure sandbox for routing JS (goto_js, run_js)
|
|
10701
10801
|
*/
|
|
@@ -10895,10 +10995,6 @@ ${expr}
|
|
|
10895
10995
|
const providerType = targetCfg.type || "ai";
|
|
10896
10996
|
const prov = this.providerRegistry.getProviderOrThrow(providerType);
|
|
10897
10997
|
this.setProviderWebhookContext(prov);
|
|
10898
|
-
const enrichedEventContext = {
|
|
10899
|
-
...prInfo.eventContext,
|
|
10900
|
-
...this.actionContext?.octokit ? { octokit: this.actionContext.octokit } : {}
|
|
10901
|
-
};
|
|
10902
10998
|
const provCfg = {
|
|
10903
10999
|
type: providerType,
|
|
10904
11000
|
prompt: targetCfg.prompt,
|
|
@@ -10907,11 +11003,13 @@ ${expr}
|
|
|
10907
11003
|
schema: targetCfg.schema,
|
|
10908
11004
|
group: targetCfg.group,
|
|
10909
11005
|
checkName: target,
|
|
10910
|
-
eventContext:
|
|
11006
|
+
eventContext: this.enrichEventContext(prInfo.eventContext),
|
|
10911
11007
|
transform: targetCfg.transform,
|
|
10912
11008
|
transform_js: targetCfg.transform_js,
|
|
10913
11009
|
env: targetCfg.env,
|
|
10914
11010
|
forEach: targetCfg.forEach,
|
|
11011
|
+
// Pass output history for loop/goto scenarios
|
|
11012
|
+
__outputHistory: this.outputHistory,
|
|
10915
11013
|
// Include provider-specific keys (e.g., op/values for github)
|
|
10916
11014
|
...targetCfg,
|
|
10917
11015
|
ai: {
|
|
@@ -10979,6 +11077,10 @@ ${expr}
|
|
|
10979
11077
|
timestamp: Date.now()
|
|
10980
11078
|
}));
|
|
10981
11079
|
const enriched = { ...r, issues: enrichedIssues };
|
|
11080
|
+
const enrichedWithOutput = enriched;
|
|
11081
|
+
if (enrichedWithOutput.output !== void 0) {
|
|
11082
|
+
this.trackOutputHistory(target, enrichedWithOutput.output);
|
|
11083
|
+
}
|
|
10982
11084
|
resultsMap?.set(target, enriched);
|
|
10983
11085
|
if (debug) log2(`\u{1F527} Debug: inline executed '${target}', issues: ${enrichedIssues.length}`);
|
|
10984
11086
|
return enriched;
|
|
@@ -11548,8 +11650,7 @@ ${expr}
|
|
|
11548
11650
|
const providerConfig = {
|
|
11549
11651
|
type: checks[0],
|
|
11550
11652
|
prompt: "all",
|
|
11551
|
-
eventContext: prInfo.eventContext,
|
|
11552
|
-
// Pass event context for templates
|
|
11653
|
+
eventContext: this.enrichEventContext(prInfo.eventContext),
|
|
11553
11654
|
ai: timeout ? { timeout } : void 0
|
|
11554
11655
|
};
|
|
11555
11656
|
const result = await provider.execute(prInfo, providerConfig);
|
|
@@ -11583,8 +11684,7 @@ ${expr}
|
|
|
11583
11684
|
type: "ai",
|
|
11584
11685
|
prompt: focus2,
|
|
11585
11686
|
focus: focus2,
|
|
11586
|
-
eventContext: prInfo.eventContext,
|
|
11587
|
-
// Pass event context for templates
|
|
11687
|
+
eventContext: this.enrichEventContext(prInfo.eventContext),
|
|
11588
11688
|
ai: timeout ? { timeout } : void 0,
|
|
11589
11689
|
// Inherit global AI provider and model settings if config is available
|
|
11590
11690
|
ai_provider: config?.ai_provider,
|
|
@@ -11739,8 +11839,7 @@ ${expr}
|
|
|
11739
11839
|
focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),
|
|
11740
11840
|
schema: checkConfig.schema,
|
|
11741
11841
|
group: checkConfig.group,
|
|
11742
|
-
eventContext: prInfo.eventContext,
|
|
11743
|
-
// Pass event context for templates
|
|
11842
|
+
eventContext: this.enrichEventContext(prInfo.eventContext),
|
|
11744
11843
|
ai: {
|
|
11745
11844
|
timeout: timeout || 6e5,
|
|
11746
11845
|
debug,
|
|
@@ -11750,6 +11849,8 @@ ${expr}
|
|
|
11750
11849
|
ai_model: checkConfig.ai_model || config.ai_model,
|
|
11751
11850
|
// Pass claude_code config if present
|
|
11752
11851
|
claude_code: checkConfig.claude_code,
|
|
11852
|
+
// Pass output history for loop/goto scenarios
|
|
11853
|
+
__outputHistory: this.outputHistory,
|
|
11753
11854
|
// Pass any provider-specific config
|
|
11754
11855
|
...checkConfig
|
|
11755
11856
|
};
|
|
@@ -11786,10 +11887,14 @@ ${expr}
|
|
|
11786
11887
|
}
|
|
11787
11888
|
}
|
|
11788
11889
|
const content = await this.renderCheckContent(checkName, result, checkConfig, prInfo);
|
|
11890
|
+
let group = checkConfig.group || "default";
|
|
11891
|
+
if (config?.output?.pr_comment?.group_by === "check" && !checkConfig.group) {
|
|
11892
|
+
group = checkName;
|
|
11893
|
+
}
|
|
11789
11894
|
return {
|
|
11790
11895
|
checkName,
|
|
11791
11896
|
content,
|
|
11792
|
-
group
|
|
11897
|
+
group,
|
|
11793
11898
|
output: result.output,
|
|
11794
11899
|
debug: result.debug,
|
|
11795
11900
|
issues: result.issues
|
|
@@ -11928,16 +12033,19 @@ ${expr}
|
|
|
11928
12033
|
}
|
|
11929
12034
|
];
|
|
11930
12035
|
}
|
|
12036
|
+
let group = checkConfig.group || "default";
|
|
12037
|
+
if (config?.output?.pr_comment?.group_by === "check" && !checkConfig.group) {
|
|
12038
|
+
group = checkName;
|
|
12039
|
+
}
|
|
11931
12040
|
const checkResult = {
|
|
11932
12041
|
checkName,
|
|
11933
12042
|
content,
|
|
11934
|
-
group
|
|
12043
|
+
group,
|
|
11935
12044
|
output: checkSummary.output,
|
|
11936
12045
|
debug: reviewSummary.debug,
|
|
11937
12046
|
issues: issuesForCheck
|
|
11938
12047
|
// Include structured issues + rendering error if any
|
|
11939
12048
|
};
|
|
11940
|
-
const group = checkResult.group;
|
|
11941
12049
|
if (!groupedResults[group]) {
|
|
11942
12050
|
groupedResults[group] = [];
|
|
11943
12051
|
}
|
|
@@ -12344,8 +12452,7 @@ ${expr}
|
|
|
12344
12452
|
group: checkConfig.group,
|
|
12345
12453
|
checkName,
|
|
12346
12454
|
// Add checkName for sessionID
|
|
12347
|
-
eventContext: prInfo.eventContext,
|
|
12348
|
-
// Pass event context for templates
|
|
12455
|
+
eventContext: this.enrichEventContext(prInfo.eventContext),
|
|
12349
12456
|
transform: checkConfig.transform,
|
|
12350
12457
|
transform_js: checkConfig.transform_js,
|
|
12351
12458
|
// Important: pass through provider-level timeout from check config
|
|
@@ -12532,7 +12639,7 @@ ${expr}
|
|
|
12532
12639
|
schema: childCfg.schema,
|
|
12533
12640
|
group: childCfg.group,
|
|
12534
12641
|
checkName: childName,
|
|
12535
|
-
eventContext: prInfo.eventContext,
|
|
12642
|
+
eventContext: this.enrichEventContext(prInfo.eventContext),
|
|
12536
12643
|
transform: childCfg.transform,
|
|
12537
12644
|
transform_js: childCfg.transform_js,
|
|
12538
12645
|
env: childCfg.env,
|
|
@@ -12839,6 +12946,10 @@ ${expr}
|
|
|
12839
12946
|
itemResult.issues || [],
|
|
12840
12947
|
itemResult.output
|
|
12841
12948
|
);
|
|
12949
|
+
const itemOutput = itemResult.output;
|
|
12950
|
+
if (itemOutput !== void 0) {
|
|
12951
|
+
this.trackOutputHistory(checkName, itemOutput);
|
|
12952
|
+
}
|
|
12842
12953
|
const descendantSet = (() => {
|
|
12843
12954
|
const visited = /* @__PURE__ */ new Set();
|
|
12844
12955
|
const stack = [checkName];
|
|
@@ -12926,7 +13037,7 @@ ${expr}
|
|
|
12926
13037
|
schema: nodeCfg.schema,
|
|
12927
13038
|
group: nodeCfg.group,
|
|
12928
13039
|
checkName: node,
|
|
12929
|
-
eventContext: prInfo.eventContext,
|
|
13040
|
+
eventContext: this.enrichEventContext(prInfo.eventContext),
|
|
12930
13041
|
transform: nodeCfg.transform,
|
|
12931
13042
|
transform_js: nodeCfg.transform_js,
|
|
12932
13043
|
env: nodeCfg.env,
|
|
@@ -13469,6 +13580,10 @@ ${error.stack || ""}` : String(error);
|
|
|
13469
13580
|
]);
|
|
13470
13581
|
} catch {
|
|
13471
13582
|
}
|
|
13583
|
+
const reviewResultWithOutput = reviewResult;
|
|
13584
|
+
if (reviewResultWithOutput.output !== void 0) {
|
|
13585
|
+
this.trackOutputHistory(checkName, reviewResultWithOutput.output);
|
|
13586
|
+
}
|
|
13472
13587
|
results.set(checkName, reviewResult);
|
|
13473
13588
|
} else {
|
|
13474
13589
|
const errorSummary = {
|
|
@@ -13622,8 +13737,7 @@ ${error.stack || ""}` : String(error);
|
|
|
13622
13737
|
focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),
|
|
13623
13738
|
schema: checkConfig.schema,
|
|
13624
13739
|
group: checkConfig.group,
|
|
13625
|
-
eventContext: prInfo.eventContext,
|
|
13626
|
-
// Pass event context for templates
|
|
13740
|
+
eventContext: this.enrichEventContext(prInfo.eventContext),
|
|
13627
13741
|
ai: {
|
|
13628
13742
|
timeout: timeout || 6e5,
|
|
13629
13743
|
debug,
|
|
@@ -13699,8 +13813,7 @@ ${error.stack || ""}` : String(error);
|
|
|
13699
13813
|
focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),
|
|
13700
13814
|
schema: checkConfig.schema,
|
|
13701
13815
|
group: checkConfig.group,
|
|
13702
|
-
eventContext: prInfo.eventContext,
|
|
13703
|
-
// Pass event context for templates
|
|
13816
|
+
eventContext: this.enrichEventContext(prInfo.eventContext),
|
|
13704
13817
|
ai: {
|
|
13705
13818
|
timeout: timeout || 6e5,
|
|
13706
13819
|
...checkConfig.ai || {}
|
|
@@ -14714,6 +14827,16 @@ ${result.value.result.debug.rawResponse}`;
|
|
|
14714
14827
|
stats.outputsProduced = (stats.outputsProduced || 0) + 1;
|
|
14715
14828
|
}
|
|
14716
14829
|
}
|
|
14830
|
+
/**
|
|
14831
|
+
* Track output in history for loop/goto scenarios
|
|
14832
|
+
*/
|
|
14833
|
+
trackOutputHistory(checkName, output) {
|
|
14834
|
+
if (output === void 0) return;
|
|
14835
|
+
if (!this.outputHistory.has(checkName)) {
|
|
14836
|
+
this.outputHistory.set(checkName, []);
|
|
14837
|
+
}
|
|
14838
|
+
this.outputHistory.get(checkName).push(output);
|
|
14839
|
+
}
|
|
14717
14840
|
/**
|
|
14718
14841
|
* Record that a check was skipped
|
|
14719
14842
|
*/
|
|
@@ -16817,8 +16940,10 @@ var ConfigManager = class {
|
|
|
16817
16940
|
}
|
|
16818
16941
|
/**
|
|
16819
16942
|
* Validate configuration against schema
|
|
16943
|
+
* @param config The config to validate
|
|
16944
|
+
* @param strict If true, treat warnings as errors (default: false)
|
|
16820
16945
|
*/
|
|
16821
|
-
validateConfig(config) {
|
|
16946
|
+
validateConfig(config, strict = false) {
|
|
16822
16947
|
const errors = [];
|
|
16823
16948
|
const warnings = [];
|
|
16824
16949
|
this.validateWithAjvSchema(config, errors, warnings);
|
|
@@ -16926,10 +17051,13 @@ var ConfigManager = class {
|
|
|
16926
17051
|
if (config.tag_filter) {
|
|
16927
17052
|
this.validateTagFilter(config.tag_filter, errors);
|
|
16928
17053
|
}
|
|
17054
|
+
if (strict && warnings.length > 0) {
|
|
17055
|
+
errors.push(...warnings);
|
|
17056
|
+
}
|
|
16929
17057
|
if (errors.length > 0) {
|
|
16930
17058
|
throw new Error(errors[0].message);
|
|
16931
17059
|
}
|
|
16932
|
-
if (warnings.length > 0) {
|
|
17060
|
+
if (!strict && warnings.length > 0) {
|
|
16933
17061
|
for (const w of warnings) {
|
|
16934
17062
|
logger.warn(`\u26A0\uFE0F Config warning [${w.field}]: ${w.message}`);
|
|
16935
17063
|
}
|
|
@@ -17385,9 +17513,25 @@ var __ajvValidate = null;
|
|
|
17385
17513
|
var __ajvErrors = null;
|
|
17386
17514
|
|
|
17387
17515
|
// src/sdk.ts
|
|
17388
|
-
async function loadConfig(
|
|
17516
|
+
async function loadConfig(configOrPath, options) {
|
|
17389
17517
|
const cm = new ConfigManager();
|
|
17390
|
-
if (
|
|
17518
|
+
if (typeof configOrPath === "object" && configOrPath !== null) {
|
|
17519
|
+
cm.validateConfig(configOrPath, options?.strict ?? false);
|
|
17520
|
+
const defaultConfig = {
|
|
17521
|
+
version: "1.0",
|
|
17522
|
+
checks: {},
|
|
17523
|
+
max_parallelism: 3,
|
|
17524
|
+
fail_fast: false
|
|
17525
|
+
};
|
|
17526
|
+
return {
|
|
17527
|
+
...defaultConfig,
|
|
17528
|
+
...configOrPath,
|
|
17529
|
+
checks: configOrPath.checks || {}
|
|
17530
|
+
};
|
|
17531
|
+
}
|
|
17532
|
+
if (typeof configOrPath === "string") {
|
|
17533
|
+
return cm.loadConfig(configOrPath);
|
|
17534
|
+
}
|
|
17391
17535
|
return cm.findAndLoadConfig();
|
|
17392
17536
|
}
|
|
17393
17537
|
function resolveChecks(checkIds, config) {
|
|
@@ -17413,7 +17557,15 @@ function resolveChecks(checkIds, config) {
|
|
|
17413
17557
|
}
|
|
17414
17558
|
async function runChecks(opts = {}) {
|
|
17415
17559
|
const cm = new ConfigManager();
|
|
17416
|
-
|
|
17560
|
+
let config;
|
|
17561
|
+
if (opts.config) {
|
|
17562
|
+
cm.validateConfig(opts.config, opts.strictValidation ?? false);
|
|
17563
|
+
config = opts.config;
|
|
17564
|
+
} else if (opts.configPath) {
|
|
17565
|
+
config = await cm.loadConfig(opts.configPath);
|
|
17566
|
+
} else {
|
|
17567
|
+
config = await cm.findAndLoadConfig();
|
|
17568
|
+
}
|
|
17417
17569
|
const checks = opts.checks && opts.checks.length > 0 ? resolveChecks(opts.checks, config) : Object.keys(config.checks || {});
|
|
17418
17570
|
const engine = new CheckExecutionEngine(opts.cwd);
|
|
17419
17571
|
const result = await engine.executeChecks({
|