@probelabs/visor 0.1.83 → 0.1.84
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 +4 -4
- package/dist/check-execution-engine.d.ts +5 -0
- package/dist/check-execution-engine.d.ts.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/defaults/.visor.yaml +4 -4
- package/dist/failure-condition-evaluator.d.ts.map +1 -1
- package/dist/generated/config-schema.d.ts +2 -2
- package/dist/generated/config-schema.json +5 -2
- package/dist/index.js +39741 -36629
- package/dist/output/code-review/schema.json +2 -2
- package/dist/providers/command-check-provider.d.ts.map +1 -1
- package/dist/sdk/{check-execution-engine-47X4MPHW.mjs → check-execution-engine-X7VCV6KI.mjs} +2 -2
- package/dist/sdk/{chunk-ROXFJUTY.mjs → chunk-Q55L5EPS.mjs} +123 -27
- package/dist/sdk/chunk-Q55L5EPS.mjs.map +1 -0
- package/dist/sdk/sdk.d.mts +2 -2
- package/dist/sdk/sdk.d.ts +2 -2
- package/dist/sdk/sdk.js +138 -31
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +18 -7
- package/dist/sdk/sdk.mjs.map +1 -1
- package/dist/types/config.d.ts +2 -2
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/sdk/chunk-ROXFJUTY.mjs.map +0 -1
- /package/dist/sdk/{check-execution-engine-47X4MPHW.mjs.map → check-execution-engine-X7VCV6KI.mjs.map} +0 -0
package/dist/sdk/sdk.d.mts
CHANGED
|
@@ -260,8 +260,8 @@ interface CheckConfig {
|
|
|
260
260
|
template?: CustomTemplateConfig;
|
|
261
261
|
/** Condition to determine if check should run - runs if expression evaluates to true */
|
|
262
262
|
if?: string;
|
|
263
|
-
/**
|
|
264
|
-
reuse_ai_session?: boolean;
|
|
263
|
+
/** Check name to reuse AI session from, or true to use first dependency (only works with depends_on) */
|
|
264
|
+
reuse_ai_session?: string | boolean;
|
|
265
265
|
/** Simple fail condition - fails check if expression evaluates to true */
|
|
266
266
|
fail_if?: string;
|
|
267
267
|
/** Check-specific failure conditions - optional (deprecated, use fail_if) */
|
package/dist/sdk/sdk.d.ts
CHANGED
|
@@ -260,8 +260,8 @@ interface CheckConfig {
|
|
|
260
260
|
template?: CustomTemplateConfig;
|
|
261
261
|
/** Condition to determine if check should run - runs if expression evaluates to true */
|
|
262
262
|
if?: string;
|
|
263
|
-
/**
|
|
264
|
-
reuse_ai_session?: boolean;
|
|
263
|
+
/** Check name to reuse AI session from, or true to use first dependency (only works with depends_on) */
|
|
264
|
+
reuse_ai_session?: string | boolean;
|
|
265
265
|
/** Simple fail condition - fails check if expression evaluates to true */
|
|
266
266
|
fail_if?: string;
|
|
267
267
|
/** Check-specific failure conditions - optional (deprecated, use fail_if) */
|
package/dist/sdk/sdk.js
CHANGED
|
@@ -4127,6 +4127,7 @@ var init_command_check_provider = __esm({
|
|
|
4127
4127
|
try {
|
|
4128
4128
|
const parsed = JSON.parse(rawOutput);
|
|
4129
4129
|
output = parsed;
|
|
4130
|
+
logger.debug(`\u{1F527} Debug: Parsed entire output as JSON successfully`);
|
|
4130
4131
|
} catch {
|
|
4131
4132
|
const extracted2 = this.extractJsonFromEnd(rawOutput);
|
|
4132
4133
|
if (extracted2) {
|
|
@@ -4135,13 +4136,28 @@ var init_command_check_provider = __esm({
|
|
|
4135
4136
|
logger.debug(
|
|
4136
4137
|
`\u{1F527} Debug: Extracted and parsed JSON from end of output (${extracted2.length} chars from ${rawOutput.length} total)`
|
|
4137
4138
|
);
|
|
4138
|
-
|
|
4139
|
+
logger.debug(`\u{1F527} Debug: Extracted JSON content: ${extracted2.slice(0, 200)}`);
|
|
4140
|
+
} catch (parseError) {
|
|
4141
|
+
logger.debug(
|
|
4142
|
+
`\u{1F527} Debug: Extracted text is not valid JSON: ${parseError instanceof Error ? parseError.message : "Unknown error"}`
|
|
4143
|
+
);
|
|
4139
4144
|
output = rawOutput;
|
|
4140
4145
|
}
|
|
4141
4146
|
} else {
|
|
4147
|
+
logger.debug(`\u{1F527} Debug: No JSON found in output, keeping as string`);
|
|
4142
4148
|
output = rawOutput;
|
|
4143
4149
|
}
|
|
4144
4150
|
}
|
|
4151
|
+
if (output !== rawOutput) {
|
|
4152
|
+
try {
|
|
4153
|
+
const outputType = Array.isArray(output) ? `array[${output.length}]` : typeof output;
|
|
4154
|
+
logger.debug(`\u{1F527} Debug: Parsed output type: ${outputType}`);
|
|
4155
|
+
if (typeof output === "object" && output !== null) {
|
|
4156
|
+
logger.debug(`\u{1F527} Debug: Parsed output keys: ${Object.keys(output).join(", ")}`);
|
|
4157
|
+
}
|
|
4158
|
+
} catch {
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4145
4161
|
let finalOutput = output;
|
|
4146
4162
|
if (transform) {
|
|
4147
4163
|
try {
|
|
@@ -5436,6 +5452,14 @@ var init_failure_condition_evaluator = __esm({
|
|
|
5436
5452
|
*/
|
|
5437
5453
|
buildEvaluationContext(checkName, checkSchema, checkGroup, reviewSummary, previousOutputs) {
|
|
5438
5454
|
const { issues, debug } = reviewSummary;
|
|
5455
|
+
const reviewSummaryWithOutput = reviewSummary;
|
|
5456
|
+
const {
|
|
5457
|
+
output: extractedOutput,
|
|
5458
|
+
// Exclude issues from otherFields since we handle it separately
|
|
5459
|
+
issues: _issues,
|
|
5460
|
+
// eslint-disable-line @typescript-eslint/no-unused-vars
|
|
5461
|
+
...otherFields
|
|
5462
|
+
} = reviewSummaryWithOutput;
|
|
5439
5463
|
const context = {
|
|
5440
5464
|
output: {
|
|
5441
5465
|
issues: (issues || []).map((issue) => ({
|
|
@@ -5452,9 +5476,9 @@ var init_failure_condition_evaluator = __esm({
|
|
|
5452
5476
|
replacement: issue.replacement
|
|
5453
5477
|
})),
|
|
5454
5478
|
// Include additional schema-specific data from reviewSummary
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5479
|
+
...otherFields,
|
|
5480
|
+
// Spread the extracted output directly (avoid output.output nesting)
|
|
5481
|
+
...extractedOutput && typeof extractedOutput === "object" ? extractedOutput : {}
|
|
5458
5482
|
},
|
|
5459
5483
|
outputs: (() => {
|
|
5460
5484
|
if (!previousOutputs) return {};
|
|
@@ -6894,6 +6918,31 @@ ${expr}
|
|
|
6894
6918
|
};
|
|
6895
6919
|
providerConfig.forEach = checkConfig.forEach;
|
|
6896
6920
|
const result = await provider.execute(prInfo, providerConfig);
|
|
6921
|
+
if (checkConfig.forEach && (!result.issues || result.issues.length === 0)) {
|
|
6922
|
+
const reviewSummaryWithOutput = result;
|
|
6923
|
+
const validation = this.validateAndNormalizeForEachOutput(
|
|
6924
|
+
checkName,
|
|
6925
|
+
reviewSummaryWithOutput.output,
|
|
6926
|
+
checkConfig.group
|
|
6927
|
+
);
|
|
6928
|
+
if (!validation.isValid) {
|
|
6929
|
+
return validation.error;
|
|
6930
|
+
}
|
|
6931
|
+
}
|
|
6932
|
+
if (config && (config.fail_if || checkConfig.fail_if)) {
|
|
6933
|
+
const failureResults = await this.evaluateFailureConditions(checkName, result, config);
|
|
6934
|
+
if (failureResults.length > 0) {
|
|
6935
|
+
const failureIssues = failureResults.filter((f) => f.failed).map((f) => ({
|
|
6936
|
+
file: "system",
|
|
6937
|
+
line: 0,
|
|
6938
|
+
ruleId: f.conditionName,
|
|
6939
|
+
message: f.message || `Failure condition met: ${f.expression}`,
|
|
6940
|
+
severity: f.severity || "error",
|
|
6941
|
+
category: "logic"
|
|
6942
|
+
}));
|
|
6943
|
+
result.issues = [...result.issues || [], ...failureIssues];
|
|
6944
|
+
}
|
|
6945
|
+
}
|
|
6897
6946
|
const content = await this.renderCheckContent(checkName, result, checkConfig, prInfo);
|
|
6898
6947
|
return {
|
|
6899
6948
|
checkName,
|
|
@@ -6904,6 +6953,53 @@ ${expr}
|
|
|
6904
6953
|
// Include structured issues
|
|
6905
6954
|
};
|
|
6906
6955
|
}
|
|
6956
|
+
/**
|
|
6957
|
+
* Validate and normalize forEach output
|
|
6958
|
+
* Returns normalized array or throws validation error result
|
|
6959
|
+
*/
|
|
6960
|
+
validateAndNormalizeForEachOutput(checkName, output, checkGroup) {
|
|
6961
|
+
if (output === void 0) {
|
|
6962
|
+
logger.error(`\u2717 forEach check "${checkName}" produced undefined output`);
|
|
6963
|
+
return {
|
|
6964
|
+
isValid: false,
|
|
6965
|
+
error: {
|
|
6966
|
+
checkName,
|
|
6967
|
+
content: "",
|
|
6968
|
+
group: checkGroup || "default",
|
|
6969
|
+
issues: [
|
|
6970
|
+
{
|
|
6971
|
+
file: "system",
|
|
6972
|
+
line: 0,
|
|
6973
|
+
ruleId: "forEach/undefined_output",
|
|
6974
|
+
message: `forEach check "${checkName}" produced undefined output. Verify your command outputs valid data and your transform_js returns a value.`,
|
|
6975
|
+
severity: "error",
|
|
6976
|
+
category: "logic"
|
|
6977
|
+
}
|
|
6978
|
+
]
|
|
6979
|
+
}
|
|
6980
|
+
};
|
|
6981
|
+
}
|
|
6982
|
+
let normalizedOutput;
|
|
6983
|
+
if (Array.isArray(output)) {
|
|
6984
|
+
normalizedOutput = output;
|
|
6985
|
+
} else if (typeof output === "string") {
|
|
6986
|
+
try {
|
|
6987
|
+
const parsed = JSON.parse(output);
|
|
6988
|
+
normalizedOutput = Array.isArray(parsed) ? parsed : [parsed];
|
|
6989
|
+
} catch {
|
|
6990
|
+
normalizedOutput = [output];
|
|
6991
|
+
}
|
|
6992
|
+
} else if (output === null) {
|
|
6993
|
+
normalizedOutput = [];
|
|
6994
|
+
} else {
|
|
6995
|
+
normalizedOutput = [output];
|
|
6996
|
+
}
|
|
6997
|
+
logger.info(` Found ${normalizedOutput.length} items for forEach iteration`);
|
|
6998
|
+
return {
|
|
6999
|
+
isValid: true,
|
|
7000
|
+
normalizedOutput
|
|
7001
|
+
};
|
|
7002
|
+
}
|
|
6907
7003
|
/**
|
|
6908
7004
|
* Execute multiple checks with dependency awareness - return grouped results with statistics
|
|
6909
7005
|
*/
|
|
@@ -7113,10 +7209,14 @@ ${expr}
|
|
|
7113
7209
|
const checkConfig = config.checks[checkName];
|
|
7114
7210
|
if (checkConfig) {
|
|
7115
7211
|
dependencies[checkName] = checkConfig.depends_on || [];
|
|
7116
|
-
if (checkConfig.reuse_ai_session
|
|
7212
|
+
if (checkConfig.reuse_ai_session) {
|
|
7117
7213
|
sessionReuseChecks.add(checkName);
|
|
7118
|
-
if (
|
|
7119
|
-
sessionProviders.set(checkName, checkConfig.
|
|
7214
|
+
if (typeof checkConfig.reuse_ai_session === "string") {
|
|
7215
|
+
sessionProviders.set(checkName, checkConfig.reuse_ai_session);
|
|
7216
|
+
} else if (checkConfig.reuse_ai_session === true) {
|
|
7217
|
+
if (checkConfig.depends_on && checkConfig.depends_on.length > 0) {
|
|
7218
|
+
sessionProviders.set(checkName, checkConfig.depends_on[0]);
|
|
7219
|
+
}
|
|
7120
7220
|
}
|
|
7121
7221
|
}
|
|
7122
7222
|
} else {
|
|
@@ -7679,27 +7779,23 @@ ${expr}
|
|
|
7679
7779
|
}
|
|
7680
7780
|
const reviewResult = result.value.result;
|
|
7681
7781
|
const reviewSummaryWithOutput = reviewResult;
|
|
7682
|
-
if (checkConfig?.forEach &&
|
|
7782
|
+
if (checkConfig?.forEach && (!reviewResult.issues || reviewResult.issues.length === 0)) {
|
|
7783
|
+
const validation2 = this.validateAndNormalizeForEachOutput(
|
|
7784
|
+
checkName,
|
|
7785
|
+
reviewSummaryWithOutput.output,
|
|
7786
|
+
checkConfig.group
|
|
7787
|
+
);
|
|
7788
|
+
if (!validation2.isValid) {
|
|
7789
|
+
results.set(
|
|
7790
|
+
checkName,
|
|
7791
|
+
validation2.error.issues ? { issues: validation2.error.issues } : {}
|
|
7792
|
+
);
|
|
7793
|
+
continue;
|
|
7794
|
+
}
|
|
7795
|
+
const normalizedOutput = validation2.normalizedOutput;
|
|
7683
7796
|
logger.debug(
|
|
7684
7797
|
`\u{1F527} Debug: Raw output for forEach check ${checkName}: ${Array.isArray(reviewSummaryWithOutput.output) ? `array(${reviewSummaryWithOutput.output.length})` : typeof reviewSummaryWithOutput.output}`
|
|
7685
7798
|
);
|
|
7686
|
-
const rawOutput = reviewSummaryWithOutput.output;
|
|
7687
|
-
let normalizedOutput;
|
|
7688
|
-
if (Array.isArray(rawOutput)) {
|
|
7689
|
-
normalizedOutput = rawOutput;
|
|
7690
|
-
} else if (typeof rawOutput === "string") {
|
|
7691
|
-
try {
|
|
7692
|
-
const parsed = JSON.parse(rawOutput);
|
|
7693
|
-
normalizedOutput = Array.isArray(parsed) ? parsed : [parsed];
|
|
7694
|
-
} catch {
|
|
7695
|
-
normalizedOutput = [rawOutput];
|
|
7696
|
-
}
|
|
7697
|
-
} else if (rawOutput === void 0 || rawOutput === null) {
|
|
7698
|
-
normalizedOutput = [];
|
|
7699
|
-
} else {
|
|
7700
|
-
normalizedOutput = [rawOutput];
|
|
7701
|
-
}
|
|
7702
|
-
logger.info(` Found ${normalizedOutput.length} items for forEach iteration`);
|
|
7703
7799
|
try {
|
|
7704
7800
|
const preview = JSON.stringify(normalizedOutput);
|
|
7705
7801
|
logger.debug(
|
|
@@ -9428,8 +9524,8 @@ var init_config_schema = __esm({
|
|
|
9428
9524
|
description: "Condition to determine if check should run - runs if expression evaluates to true"
|
|
9429
9525
|
},
|
|
9430
9526
|
reuse_ai_session: {
|
|
9431
|
-
type: "boolean",
|
|
9432
|
-
description: "
|
|
9527
|
+
type: ["string", "boolean"],
|
|
9528
|
+
description: "Check name to reuse AI session from, or true to use first dependency (only works with depends_on)"
|
|
9433
9529
|
},
|
|
9434
9530
|
fail_if: {
|
|
9435
9531
|
type: "string",
|
|
@@ -10766,7 +10862,7 @@ var ConfigManager = class {
|
|
|
10766
10862
|
if (!checkConfig.type) {
|
|
10767
10863
|
checkConfig.type = "ai";
|
|
10768
10864
|
}
|
|
10769
|
-
this.validateCheckConfig(checkName, checkConfig, errors);
|
|
10865
|
+
this.validateCheckConfig(checkName, checkConfig, errors, config);
|
|
10770
10866
|
if (checkConfig.ai_mcp_servers) {
|
|
10771
10867
|
this.validateMcpServersObject(
|
|
10772
10868
|
checkConfig.ai_mcp_servers,
|
|
@@ -10866,7 +10962,7 @@ var ConfigManager = class {
|
|
|
10866
10962
|
/**
|
|
10867
10963
|
* Validate individual check configuration
|
|
10868
10964
|
*/
|
|
10869
|
-
validateCheckConfig(checkName, checkConfig, errors) {
|
|
10965
|
+
validateCheckConfig(checkName, checkConfig, errors, config) {
|
|
10870
10966
|
if (!checkConfig.type) {
|
|
10871
10967
|
checkConfig.type = "ai";
|
|
10872
10968
|
}
|
|
@@ -10947,12 +11043,23 @@ var ConfigManager = class {
|
|
|
10947
11043
|
}
|
|
10948
11044
|
}
|
|
10949
11045
|
if (checkConfig.reuse_ai_session !== void 0) {
|
|
10950
|
-
|
|
11046
|
+
const isString = typeof checkConfig.reuse_ai_session === "string";
|
|
11047
|
+
const isBoolean = typeof checkConfig.reuse_ai_session === "boolean";
|
|
11048
|
+
if (!isString && !isBoolean) {
|
|
10951
11049
|
errors.push({
|
|
10952
11050
|
field: `checks.${checkName}.reuse_ai_session`,
|
|
10953
|
-
message: `Invalid reuse_ai_session value for "${checkName}": must be boolean`,
|
|
11051
|
+
message: `Invalid reuse_ai_session value for "${checkName}": must be string (check name) or boolean`,
|
|
10954
11052
|
value: checkConfig.reuse_ai_session
|
|
10955
11053
|
});
|
|
11054
|
+
} else if (isString) {
|
|
11055
|
+
const targetCheckName = checkConfig.reuse_ai_session;
|
|
11056
|
+
if (!config?.checks || !config.checks[targetCheckName]) {
|
|
11057
|
+
errors.push({
|
|
11058
|
+
field: `checks.${checkName}.reuse_ai_session`,
|
|
11059
|
+
message: `Check "${checkName}" references non-existent check "${targetCheckName}" for session reuse`,
|
|
11060
|
+
value: checkConfig.reuse_ai_session
|
|
11061
|
+
});
|
|
11062
|
+
}
|
|
10956
11063
|
} else if (checkConfig.reuse_ai_session === true) {
|
|
10957
11064
|
if (!checkConfig.depends_on || !Array.isArray(checkConfig.depends_on) || checkConfig.depends_on.length === 0) {
|
|
10958
11065
|
errors.push({
|