@probelabs/visor 0.1.94 → 0.1.95
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/README.md +4 -4
- package/defaults/.visor.yaml +86 -6
- package/dist/ai-review-service.d.ts +1 -1
- package/dist/ai-review-service.d.ts.map +1 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/config.d.ts +6 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/defaults/.visor.yaml +86 -6
- package/dist/failure-condition-evaluator.d.ts.map +1 -1
- package/dist/footer.d.ts +25 -0
- package/dist/footer.d.ts.map +1 -0
- package/dist/github-check-service.d.ts.map +1 -1
- package/dist/github-comments.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +926 -476
- package/dist/output/code-review/schema.json +0 -23
- package/dist/reviewer.d.ts +5 -2
- package/dist/reviewer.d.ts.map +1 -1
- package/dist/sdk/{check-execution-engine-YBRPVUWD.mjs → check-execution-engine-NMPXJ7FQ.mjs} +2 -2
- package/dist/sdk/{chunk-DQRFOQAP.mjs → chunk-Q4S5A5TO.mjs} +199 -113
- package/dist/sdk/chunk-Q4S5A5TO.mjs.map +1 -0
- package/dist/sdk/sdk.js +249 -149
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +23 -19
- package/dist/sdk/sdk.mjs.map +1 -1
- package/dist/traces/{run-2025-10-16T11-33-32-682Z.ndjson → run-2025-10-18T18-27-25-085Z.ndjson} +8 -1
- package/dist/traces/{run-2025-10-16T11-33-43-618Z.ndjson → run-2025-10-18T18-27-35-400Z.ndjson} +8 -1
- package/dist/traces/{run-2025-10-16T11-33-44-157Z.ndjson → run-2025-10-18T18-27-35-937Z.ndjson} +8 -1
- package/dist/traces/{run-2025-10-16T11-33-44-647Z.ndjson → run-2025-10-18T18-27-36-428Z.ndjson} +8 -1
- package/dist/types/cli.d.ts +3 -2
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts +0 -2
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/diff-processor.d.ts +6 -0
- package/dist/utils/diff-processor.d.ts.map +1 -0
- package/package.json +2 -2
- package/dist/sdk/chunk-DQRFOQAP.mjs.map +0 -1
- /package/dist/sdk/{check-execution-engine-YBRPVUWD.mjs.map → check-execution-engine-NMPXJ7FQ.mjs.map} +0 -0
- /package/dist/traces/{run-2025-10-16T11-33-45-128Z.ndjson → run-2025-10-18T18-27-36-917Z.ndjson} +0 -0
package/dist/sdk/sdk.js
CHANGED
|
@@ -136,6 +136,33 @@ var init_logger = __esm({
|
|
|
136
136
|
}
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
+
// src/footer.ts
|
|
140
|
+
function generateFooter(options = {}) {
|
|
141
|
+
const { includeMetadata, includeSeparator = true } = options;
|
|
142
|
+
const parts = [];
|
|
143
|
+
if (includeSeparator) {
|
|
144
|
+
parts.push("---");
|
|
145
|
+
parts.push("");
|
|
146
|
+
}
|
|
147
|
+
parts.push(
|
|
148
|
+
"*Powered by [Visor](https://probelabs.com/visor) from [Probelabs](https://probelabs.com)*"
|
|
149
|
+
);
|
|
150
|
+
if (includeMetadata) {
|
|
151
|
+
const { lastUpdated, triggeredBy, commitSha } = includeMetadata;
|
|
152
|
+
const commitInfo = commitSha ? ` | Commit: ${commitSha.substring(0, 7)}` : "";
|
|
153
|
+
parts.push("");
|
|
154
|
+
parts.push(`*Last updated: ${lastUpdated} | Triggered by: ${triggeredBy}${commitInfo}*`);
|
|
155
|
+
}
|
|
156
|
+
parts.push("");
|
|
157
|
+
parts.push("\u{1F4A1} **TIP:** You can chat with Visor using `/visor ask <your question>`");
|
|
158
|
+
return parts.join("\n");
|
|
159
|
+
}
|
|
160
|
+
var init_footer = __esm({
|
|
161
|
+
"src/footer.ts"() {
|
|
162
|
+
"use strict";
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
139
166
|
// src/github-comments.ts
|
|
140
167
|
var import_uuid, CommentManager;
|
|
141
168
|
var init_github_comments = __esm({
|
|
@@ -143,6 +170,7 @@ var init_github_comments = __esm({
|
|
|
143
170
|
"use strict";
|
|
144
171
|
import_uuid = require("uuid");
|
|
145
172
|
init_logger();
|
|
173
|
+
init_footer();
|
|
146
174
|
CommentManager = class {
|
|
147
175
|
octokit;
|
|
148
176
|
retryConfig;
|
|
@@ -244,15 +272,17 @@ var init_github_comments = __esm({
|
|
|
244
272
|
*/
|
|
245
273
|
formatCommentWithMetadata(content, metadata) {
|
|
246
274
|
const { commentId, lastUpdated, triggeredBy, commitSha } = metadata;
|
|
247
|
-
const
|
|
275
|
+
const footer = generateFooter({
|
|
276
|
+
includeMetadata: {
|
|
277
|
+
lastUpdated,
|
|
278
|
+
triggeredBy,
|
|
279
|
+
commitSha
|
|
280
|
+
}
|
|
281
|
+
});
|
|
248
282
|
return `<!-- visor-comment-id:${commentId} -->
|
|
249
283
|
${content}
|
|
250
284
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
*Powered by [Visor](https://probelabs.com/visor) from [Probelabs](https://probelabs.com)*
|
|
254
|
-
|
|
255
|
-
*Last updated: ${lastUpdated} | Triggered by: ${triggeredBy}${commitInfo}*
|
|
285
|
+
${footer}
|
|
256
286
|
<!-- /visor-comment-id:${commentId} -->`;
|
|
257
287
|
}
|
|
258
288
|
/**
|
|
@@ -718,18 +748,81 @@ var init_session_registry = __esm({
|
|
|
718
748
|
}
|
|
719
749
|
});
|
|
720
750
|
|
|
751
|
+
// src/utils/diff-processor.ts
|
|
752
|
+
async function processDiffWithOutline(diffContent) {
|
|
753
|
+
if (!diffContent || diffContent.trim().length === 0) {
|
|
754
|
+
return diffContent;
|
|
755
|
+
}
|
|
756
|
+
try {
|
|
757
|
+
const originalProbePath = process.env.PROBE_PATH;
|
|
758
|
+
const fs12 = require("fs");
|
|
759
|
+
const possiblePaths = [
|
|
760
|
+
// Relative to current working directory (most common in production)
|
|
761
|
+
path2.join(process.cwd(), "node_modules/@probelabs/probe/bin/probe-binary"),
|
|
762
|
+
// Relative to __dirname (for unbundled development)
|
|
763
|
+
path2.join(__dirname, "../..", "node_modules/@probelabs/probe/bin/probe-binary"),
|
|
764
|
+
// Relative to dist directory (for bundled CLI)
|
|
765
|
+
path2.join(__dirname, "node_modules/@probelabs/probe/bin/probe-binary")
|
|
766
|
+
];
|
|
767
|
+
let probeBinaryPath;
|
|
768
|
+
for (const candidatePath of possiblePaths) {
|
|
769
|
+
if (fs12.existsSync(candidatePath)) {
|
|
770
|
+
probeBinaryPath = candidatePath;
|
|
771
|
+
break;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
if (!probeBinaryPath) {
|
|
775
|
+
if (process.env.DEBUG === "1" || process.env.VERBOSE === "1") {
|
|
776
|
+
console.error("Probe binary not found. Tried:", possiblePaths);
|
|
777
|
+
}
|
|
778
|
+
return diffContent;
|
|
779
|
+
}
|
|
780
|
+
process.env.PROBE_PATH = probeBinaryPath;
|
|
781
|
+
const extractPromise = (0, import_probe2.extract)({
|
|
782
|
+
content: diffContent,
|
|
783
|
+
format: "outline-diff",
|
|
784
|
+
allowTests: true
|
|
785
|
+
// Allow test files and test code blocks in extraction results
|
|
786
|
+
});
|
|
787
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
788
|
+
setTimeout(() => reject(new Error("Extract timeout after 30s")), 3e4);
|
|
789
|
+
});
|
|
790
|
+
const result = await Promise.race([extractPromise, timeoutPromise]);
|
|
791
|
+
if (originalProbePath !== void 0) {
|
|
792
|
+
process.env.PROBE_PATH = originalProbePath;
|
|
793
|
+
} else {
|
|
794
|
+
delete process.env.PROBE_PATH;
|
|
795
|
+
}
|
|
796
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
797
|
+
} catch (error) {
|
|
798
|
+
if (process.env.DEBUG === "1" || process.env.VERBOSE === "1") {
|
|
799
|
+
console.error("Failed to process diff with outline-diff format:", error);
|
|
800
|
+
}
|
|
801
|
+
return diffContent;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
var import_probe2, path2;
|
|
805
|
+
var init_diff_processor = __esm({
|
|
806
|
+
"src/utils/diff-processor.ts"() {
|
|
807
|
+
"use strict";
|
|
808
|
+
import_probe2 = require("@probelabs/probe");
|
|
809
|
+
path2 = __toESM(require("path"));
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
|
|
721
813
|
// src/ai-review-service.ts
|
|
722
814
|
function log(...args) {
|
|
723
815
|
logger.debug(args.join(" "));
|
|
724
816
|
}
|
|
725
|
-
var
|
|
817
|
+
var import_probe3, AIReviewService;
|
|
726
818
|
var init_ai_review_service = __esm({
|
|
727
819
|
"src/ai-review-service.ts"() {
|
|
728
820
|
"use strict";
|
|
729
|
-
|
|
821
|
+
import_probe3 = require("@probelabs/probe");
|
|
730
822
|
init_session_registry();
|
|
731
823
|
init_logger();
|
|
732
824
|
init_tracer_init();
|
|
825
|
+
init_diff_processor();
|
|
733
826
|
AIReviewService = class {
|
|
734
827
|
config;
|
|
735
828
|
sessionRegistry;
|
|
@@ -768,7 +861,7 @@ var init_ai_review_service = __esm({
|
|
|
768
861
|
/**
|
|
769
862
|
* Execute AI review using probe agent
|
|
770
863
|
*/
|
|
771
|
-
async executeReview(prInfo, customPrompt, schema,
|
|
864
|
+
async executeReview(prInfo, customPrompt, schema, checkName, sessionId) {
|
|
772
865
|
const startTime = Date.now();
|
|
773
866
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
774
867
|
const prompt = await this.buildCustomPrompt(prInfo, customPrompt, schema);
|
|
@@ -825,7 +918,7 @@ var init_ai_review_service = __esm({
|
|
|
825
918
|
prompt,
|
|
826
919
|
schema,
|
|
827
920
|
debugInfo,
|
|
828
|
-
|
|
921
|
+
checkName,
|
|
829
922
|
sessionId
|
|
830
923
|
);
|
|
831
924
|
const processingTime = Date.now() - startTime;
|
|
@@ -985,9 +1078,9 @@ var init_ai_review_service = __esm({
|
|
|
985
1078
|
*/
|
|
986
1079
|
async buildCustomPrompt(prInfo, customInstructions, schema, options) {
|
|
987
1080
|
const skipPRContext = options?.skipPRContext === true;
|
|
988
|
-
const prContext = skipPRContext ? "" : this.formatPRContext(prInfo);
|
|
989
|
-
const isIssue = prInfo.isIssue === true;
|
|
990
1081
|
const isCodeReviewSchema = schema === "code-review";
|
|
1082
|
+
const prContext = skipPRContext ? "" : await this.formatPRContext(prInfo, isCodeReviewSchema);
|
|
1083
|
+
const isIssue = prInfo.isIssue === true;
|
|
991
1084
|
if (isIssue) {
|
|
992
1085
|
if (skipPRContext) {
|
|
993
1086
|
return `<instructions>
|
|
@@ -1076,7 +1169,7 @@ ${prContext}
|
|
|
1076
1169
|
/**
|
|
1077
1170
|
* Format PR or Issue context for the AI using XML structure
|
|
1078
1171
|
*/
|
|
1079
|
-
formatPRContext(prInfo) {
|
|
1172
|
+
async formatPRContext(prInfo, isCodeReviewSchema) {
|
|
1080
1173
|
const prContextInfo = prInfo;
|
|
1081
1174
|
const isIssue = prContextInfo.isIssue === true;
|
|
1082
1175
|
const isPRContext = prContextInfo.isPRContext === true;
|
|
@@ -1158,7 +1251,12 @@ ${this.escapeXml(prInfo.body)}
|
|
|
1158
1251
|
}
|
|
1159
1252
|
const issueComments = prInfo.comments;
|
|
1160
1253
|
if (issueComments && issueComments.length > 0) {
|
|
1161
|
-
|
|
1254
|
+
let historicalComments = triggeringComment2 ? issueComments.filter((c) => c.id !== triggeringComment2.id) : issueComments;
|
|
1255
|
+
if (isCodeReviewSchema) {
|
|
1256
|
+
historicalComments = historicalComments.filter(
|
|
1257
|
+
(c) => !c.body || !c.body.includes("visor-comment-id:pr-review-")
|
|
1258
|
+
);
|
|
1259
|
+
}
|
|
1162
1260
|
if (historicalComments.length > 0) {
|
|
1163
1261
|
context3 += `
|
|
1164
1262
|
<!-- Previous comments in chronological order (excluding triggering comment) -->
|
|
@@ -1200,24 +1298,27 @@ ${this.escapeXml(prInfo.body)}
|
|
|
1200
1298
|
}
|
|
1201
1299
|
if (includeCodeContext) {
|
|
1202
1300
|
if (prInfo.fullDiff) {
|
|
1301
|
+
const processedFullDiff = await processDiffWithOutline(prInfo.fullDiff);
|
|
1203
1302
|
context2 += `
|
|
1204
|
-
<!-- Complete unified diff showing all changes in the pull request -->
|
|
1303
|
+
<!-- Complete unified diff showing all changes in the pull request (processed with outline-diff) -->
|
|
1205
1304
|
<full_diff>
|
|
1206
|
-
${this.escapeXml(
|
|
1305
|
+
${this.escapeXml(processedFullDiff)}
|
|
1207
1306
|
</full_diff>`;
|
|
1208
1307
|
}
|
|
1209
1308
|
if (prInfo.isIncremental) {
|
|
1210
1309
|
if (prInfo.commitDiff && prInfo.commitDiff.length > 0) {
|
|
1310
|
+
const processedCommitDiff = await processDiffWithOutline(prInfo.commitDiff);
|
|
1211
1311
|
context2 += `
|
|
1212
|
-
<!-- Diff of only the latest commit for incremental analysis -->
|
|
1312
|
+
<!-- Diff of only the latest commit for incremental analysis (processed with outline-diff) -->
|
|
1213
1313
|
<commit_diff>
|
|
1214
|
-
${this.escapeXml(
|
|
1314
|
+
${this.escapeXml(processedCommitDiff)}
|
|
1215
1315
|
</commit_diff>`;
|
|
1216
1316
|
} else {
|
|
1317
|
+
const processedFallbackDiff = prInfo.fullDiff ? await processDiffWithOutline(prInfo.fullDiff) : "";
|
|
1217
1318
|
context2 += `
|
|
1218
|
-
<!-- Commit diff could not be retrieved - falling back to full diff analysis -->
|
|
1319
|
+
<!-- Commit diff could not be retrieved - falling back to full diff analysis (processed with outline-diff) -->
|
|
1219
1320
|
<commit_diff>
|
|
1220
|
-
${
|
|
1321
|
+
${this.escapeXml(processedFallbackDiff)}
|
|
1221
1322
|
</commit_diff>`;
|
|
1222
1323
|
}
|
|
1223
1324
|
}
|
|
@@ -1253,7 +1354,12 @@ ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ""}
|
|
|
1253
1354
|
}
|
|
1254
1355
|
const prComments = prInfo.comments;
|
|
1255
1356
|
if (prComments && prComments.length > 0) {
|
|
1256
|
-
|
|
1357
|
+
let historicalComments = triggeringComment ? prComments.filter((c) => c.id !== triggeringComment.id) : prComments;
|
|
1358
|
+
if (isCodeReviewSchema) {
|
|
1359
|
+
historicalComments = historicalComments.filter(
|
|
1360
|
+
(c) => !c.body || !c.body.includes("visor-comment-id:pr-review-")
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1257
1363
|
if (historicalComments.length > 0) {
|
|
1258
1364
|
context2 += `
|
|
1259
1365
|
<!-- Previous PR comments in chronological order (excluding triggering comment) -->
|
|
@@ -1324,7 +1430,7 @@ ${schemaString}`);
|
|
|
1324
1430
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
1325
1431
|
try {
|
|
1326
1432
|
const fs12 = require("fs");
|
|
1327
|
-
const
|
|
1433
|
+
const path13 = require("path");
|
|
1328
1434
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1329
1435
|
const provider = this.config.provider || "auto";
|
|
1330
1436
|
const model = this.config.model || "default";
|
|
@@ -1438,16 +1544,16 @@ ${"=".repeat(60)}
|
|
|
1438
1544
|
`;
|
|
1439
1545
|
readableVersion += `${"=".repeat(60)}
|
|
1440
1546
|
`;
|
|
1441
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
1547
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path13.join(process.cwd(), "debug-artifacts");
|
|
1442
1548
|
if (!fs12.existsSync(debugArtifactsDir)) {
|
|
1443
1549
|
fs12.mkdirSync(debugArtifactsDir, { recursive: true });
|
|
1444
1550
|
}
|
|
1445
|
-
const debugFile =
|
|
1551
|
+
const debugFile = path13.join(
|
|
1446
1552
|
debugArtifactsDir,
|
|
1447
1553
|
`prompt-${_checkName || "unknown"}-${timestamp}.json`
|
|
1448
1554
|
);
|
|
1449
1555
|
fs12.writeFileSync(debugFile, debugJson, "utf-8");
|
|
1450
|
-
const readableFile =
|
|
1556
|
+
const readableFile = path13.join(
|
|
1451
1557
|
debugArtifactsDir,
|
|
1452
1558
|
`prompt-${_checkName || "unknown"}-${timestamp}.txt`
|
|
1453
1559
|
);
|
|
@@ -1484,7 +1590,7 @@ ${"=".repeat(60)}
|
|
|
1484
1590
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
1485
1591
|
try {
|
|
1486
1592
|
const fs12 = require("fs");
|
|
1487
|
-
const
|
|
1593
|
+
const path13 = require("path");
|
|
1488
1594
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1489
1595
|
const agentAny2 = agent;
|
|
1490
1596
|
let fullHistory = [];
|
|
@@ -1495,8 +1601,8 @@ ${"=".repeat(60)}
|
|
|
1495
1601
|
} else if (agentAny2._messages) {
|
|
1496
1602
|
fullHistory = agentAny2._messages;
|
|
1497
1603
|
}
|
|
1498
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
1499
|
-
const sessionFile =
|
|
1604
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path13.join(process.cwd(), "debug-artifacts");
|
|
1605
|
+
const sessionFile = path13.join(
|
|
1500
1606
|
debugArtifactsDir,
|
|
1501
1607
|
`session-${_checkName || "unknown"}-${timestamp}.json`
|
|
1502
1608
|
);
|
|
@@ -1511,7 +1617,7 @@ ${"=".repeat(60)}
|
|
|
1511
1617
|
latestResponse: response
|
|
1512
1618
|
};
|
|
1513
1619
|
fs12.writeFileSync(sessionFile, JSON.stringify(sessionData, null, 2), "utf-8");
|
|
1514
|
-
const sessionTxtFile =
|
|
1620
|
+
const sessionTxtFile = path13.join(
|
|
1515
1621
|
debugArtifactsDir,
|
|
1516
1622
|
`session-${_checkName || "unknown"}-${timestamp}.txt`
|
|
1517
1623
|
);
|
|
@@ -1555,10 +1661,10 @@ ${"=".repeat(60)}
|
|
|
1555
1661
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
1556
1662
|
try {
|
|
1557
1663
|
const fs12 = require("fs");
|
|
1558
|
-
const
|
|
1664
|
+
const path13 = require("path");
|
|
1559
1665
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1560
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
1561
|
-
const responseFile =
|
|
1666
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path13.join(process.cwd(), "debug-artifacts");
|
|
1667
|
+
const responseFile = path13.join(
|
|
1562
1668
|
debugArtifactsDir,
|
|
1563
1669
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
1564
1670
|
);
|
|
@@ -1696,7 +1802,7 @@ ${"=".repeat(60)}
|
|
|
1696
1802
|
if (this.config.model) {
|
|
1697
1803
|
options.model = this.config.model;
|
|
1698
1804
|
}
|
|
1699
|
-
const agent = new
|
|
1805
|
+
const agent = new import_probe3.ProbeAgent(options);
|
|
1700
1806
|
log("\u{1F680} Calling ProbeAgent...");
|
|
1701
1807
|
let schemaString = void 0;
|
|
1702
1808
|
let effectiveSchema = typeof schema === "object" ? "custom" : schema;
|
|
@@ -1730,7 +1836,7 @@ ${schemaString}`);
|
|
|
1730
1836
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
1731
1837
|
try {
|
|
1732
1838
|
const fs12 = require("fs");
|
|
1733
|
-
const
|
|
1839
|
+
const path13 = require("path");
|
|
1734
1840
|
const os = require("os");
|
|
1735
1841
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1736
1842
|
const debugData = {
|
|
@@ -1804,21 +1910,21 @@ ${"=".repeat(60)}
|
|
|
1804
1910
|
readableVersion += `${"=".repeat(60)}
|
|
1805
1911
|
`;
|
|
1806
1912
|
const tempDir = os.tmpdir();
|
|
1807
|
-
const promptFile =
|
|
1913
|
+
const promptFile = path13.join(tempDir, `visor-prompt-${timestamp}.txt`);
|
|
1808
1914
|
fs12.writeFileSync(promptFile, prompt, "utf-8");
|
|
1809
1915
|
log(`
|
|
1810
1916
|
\u{1F4BE} Prompt saved to: ${promptFile}`);
|
|
1811
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
1917
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path13.join(process.cwd(), "debug-artifacts");
|
|
1812
1918
|
try {
|
|
1813
1919
|
if (!fs12.existsSync(debugArtifactsDir)) {
|
|
1814
1920
|
fs12.mkdirSync(debugArtifactsDir, { recursive: true });
|
|
1815
1921
|
}
|
|
1816
|
-
const debugFile =
|
|
1922
|
+
const debugFile = path13.join(
|
|
1817
1923
|
debugArtifactsDir,
|
|
1818
1924
|
`prompt-${_checkName || "unknown"}-${timestamp}.json`
|
|
1819
1925
|
);
|
|
1820
1926
|
fs12.writeFileSync(debugFile, debugJson, "utf-8");
|
|
1821
|
-
const readableFile =
|
|
1927
|
+
const readableFile = path13.join(
|
|
1822
1928
|
debugArtifactsDir,
|
|
1823
1929
|
`prompt-${_checkName || "unknown"}-${timestamp}.txt`
|
|
1824
1930
|
);
|
|
@@ -1871,7 +1977,7 @@ $ ${cliCommand}
|
|
|
1871
1977
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
1872
1978
|
try {
|
|
1873
1979
|
const fs12 = require("fs");
|
|
1874
|
-
const
|
|
1980
|
+
const path13 = require("path");
|
|
1875
1981
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1876
1982
|
const agentAny = agent;
|
|
1877
1983
|
let fullHistory = [];
|
|
@@ -1882,8 +1988,8 @@ $ ${cliCommand}
|
|
|
1882
1988
|
} else if (agentAny._messages) {
|
|
1883
1989
|
fullHistory = agentAny._messages;
|
|
1884
1990
|
}
|
|
1885
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
1886
|
-
const sessionFile =
|
|
1991
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path13.join(process.cwd(), "debug-artifacts");
|
|
1992
|
+
const sessionFile = path13.join(
|
|
1887
1993
|
debugArtifactsDir,
|
|
1888
1994
|
`session-${_checkName || "unknown"}-${timestamp}.json`
|
|
1889
1995
|
);
|
|
@@ -1898,7 +2004,7 @@ $ ${cliCommand}
|
|
|
1898
2004
|
latestResponse: response
|
|
1899
2005
|
};
|
|
1900
2006
|
fs12.writeFileSync(sessionFile, JSON.stringify(sessionData, null, 2), "utf-8");
|
|
1901
|
-
const sessionTxtFile =
|
|
2007
|
+
const sessionTxtFile = path13.join(
|
|
1902
2008
|
debugArtifactsDir,
|
|
1903
2009
|
`session-${_checkName || "unknown"}-${timestamp}.txt`
|
|
1904
2010
|
);
|
|
@@ -1942,10 +2048,10 @@ ${"=".repeat(60)}
|
|
|
1942
2048
|
if (process.env.VISOR_DEBUG_AI_SESSIONS === "true") {
|
|
1943
2049
|
try {
|
|
1944
2050
|
const fs12 = require("fs");
|
|
1945
|
-
const
|
|
2051
|
+
const path13 = require("path");
|
|
1946
2052
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1947
|
-
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS ||
|
|
1948
|
-
const responseFile =
|
|
2053
|
+
const debugArtifactsDir = process.env.VISOR_DEBUG_ARTIFACTS || path13.join(process.cwd(), "debug-artifacts");
|
|
2054
|
+
const responseFile = path13.join(
|
|
1949
2055
|
debugArtifactsDir,
|
|
1950
2056
|
`response-${_checkName || "unknown"}-${timestamp}.txt`
|
|
1951
2057
|
);
|
|
@@ -2035,7 +2141,7 @@ ${"=".repeat(60)}
|
|
|
2035
2141
|
*/
|
|
2036
2142
|
async loadSchemaContent(schema) {
|
|
2037
2143
|
const fs12 = require("fs").promises;
|
|
2038
|
-
const
|
|
2144
|
+
const path13 = require("path");
|
|
2039
2145
|
if (typeof schema === "object" && schema !== null) {
|
|
2040
2146
|
log("\u{1F4CB} Using inline schema object from configuration");
|
|
2041
2147
|
return JSON.stringify(schema);
|
|
@@ -2048,12 +2154,12 @@ ${"=".repeat(60)}
|
|
|
2048
2154
|
}
|
|
2049
2155
|
} catch {
|
|
2050
2156
|
}
|
|
2051
|
-
if ((schema.startsWith("./") || schema.includes(".json")) && !
|
|
2157
|
+
if ((schema.startsWith("./") || schema.includes(".json")) && !path13.isAbsolute(schema)) {
|
|
2052
2158
|
if (schema.includes("..") || schema.includes("\0")) {
|
|
2053
2159
|
throw new Error("Invalid schema path: path traversal not allowed");
|
|
2054
2160
|
}
|
|
2055
2161
|
try {
|
|
2056
|
-
const schemaPath2 =
|
|
2162
|
+
const schemaPath2 = path13.resolve(process.cwd(), schema);
|
|
2057
2163
|
log(`\u{1F4CB} Loading custom schema from file: ${schemaPath2}`);
|
|
2058
2164
|
const schemaContent = await fs12.readFile(schemaPath2, "utf-8");
|
|
2059
2165
|
return schemaContent.trim();
|
|
@@ -2067,7 +2173,7 @@ ${"=".repeat(60)}
|
|
|
2067
2173
|
if (!sanitizedSchemaName || sanitizedSchemaName !== schema) {
|
|
2068
2174
|
throw new Error("Invalid schema name");
|
|
2069
2175
|
}
|
|
2070
|
-
const schemaPath =
|
|
2176
|
+
const schemaPath = path13.join(process.cwd(), "output", sanitizedSchemaName, "schema.json");
|
|
2071
2177
|
try {
|
|
2072
2178
|
const schemaContent = await fs12.readFile(schemaPath, "utf-8");
|
|
2073
2179
|
return schemaContent.trim();
|
|
@@ -2425,30 +2531,36 @@ var init_reviewer = __esm({
|
|
|
2425
2531
|
);
|
|
2426
2532
|
}
|
|
2427
2533
|
/**
|
|
2428
|
-
* Helper to check if a schema
|
|
2534
|
+
* Helper to check if a schema is comment-generating
|
|
2535
|
+
* Comment-generating schemas include:
|
|
2536
|
+
* - Built-in schemas: code-review, overview, plain, text
|
|
2537
|
+
* - Custom schemas with a "text" field in properties
|
|
2429
2538
|
*/
|
|
2430
|
-
async
|
|
2539
|
+
async isCommentGeneratingSchema(schema) {
|
|
2431
2540
|
try {
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2541
|
+
if (typeof schema === "string") {
|
|
2542
|
+
if (["code-review", "overview", "plain", "text"].includes(schema)) {
|
|
2543
|
+
return true;
|
|
2544
|
+
}
|
|
2436
2545
|
const fs12 = require("fs").promises;
|
|
2437
|
-
const
|
|
2546
|
+
const path13 = require("path");
|
|
2438
2547
|
const sanitizedSchemaName = schema.replace(/[^a-zA-Z0-9-]/g, "");
|
|
2439
2548
|
if (!sanitizedSchemaName || sanitizedSchemaName !== schema) {
|
|
2440
2549
|
return false;
|
|
2441
2550
|
}
|
|
2442
|
-
const schemaPath =
|
|
2551
|
+
const schemaPath = path13.join(process.cwd(), "output", sanitizedSchemaName, "schema.json");
|
|
2443
2552
|
try {
|
|
2444
2553
|
const schemaContent = await fs12.readFile(schemaPath, "utf-8");
|
|
2445
|
-
schemaObj = JSON.parse(schemaContent);
|
|
2554
|
+
const schemaObj = JSON.parse(schemaContent);
|
|
2555
|
+
const properties = schemaObj.properties;
|
|
2556
|
+
return !!(properties && "text" in properties);
|
|
2446
2557
|
} catch {
|
|
2447
2558
|
return false;
|
|
2448
2559
|
}
|
|
2560
|
+
} else {
|
|
2561
|
+
const properties = schema.properties;
|
|
2562
|
+
return !!(properties && "text" in properties);
|
|
2449
2563
|
}
|
|
2450
|
-
const properties = schemaObj.properties;
|
|
2451
|
-
return !!(properties && "text" in properties);
|
|
2452
2564
|
} catch {
|
|
2453
2565
|
return false;
|
|
2454
2566
|
}
|
|
@@ -2466,14 +2578,8 @@ var init_reviewer = __esm({
|
|
|
2466
2578
|
const isAICheck = type === "ai" || type === "claude-code";
|
|
2467
2579
|
if (!schema || schema === "") {
|
|
2468
2580
|
shouldPostComment = isAICheck;
|
|
2469
|
-
} else
|
|
2470
|
-
|
|
2471
|
-
shouldPostComment = true;
|
|
2472
|
-
} else {
|
|
2473
|
-
shouldPostComment = await this.schemaHasTextField(schema);
|
|
2474
|
-
}
|
|
2475
|
-
} else if (typeof schema === "object") {
|
|
2476
|
-
shouldPostComment = await this.schemaHasTextField(schema);
|
|
2581
|
+
} else {
|
|
2582
|
+
shouldPostComment = await this.isCommentGeneratingSchema(schema);
|
|
2477
2583
|
}
|
|
2478
2584
|
if (shouldPostComment) {
|
|
2479
2585
|
filtered.push(r);
|
|
@@ -2616,14 +2722,14 @@ var init_reviewer = __esm({
|
|
|
2616
2722
|
saveDebugArtifact(debug) {
|
|
2617
2723
|
try {
|
|
2618
2724
|
const fs12 = require("fs");
|
|
2619
|
-
const
|
|
2620
|
-
const debugDir =
|
|
2725
|
+
const path13 = require("path");
|
|
2726
|
+
const debugDir = path13.join(process.cwd(), "debug-artifacts");
|
|
2621
2727
|
if (!fs12.existsSync(debugDir)) {
|
|
2622
2728
|
fs12.mkdirSync(debugDir, { recursive: true });
|
|
2623
2729
|
}
|
|
2624
2730
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2625
2731
|
const filename = `visor-debug-${timestamp}.md`;
|
|
2626
|
-
const filepath =
|
|
2732
|
+
const filepath = path13.join(debugDir, filename);
|
|
2627
2733
|
const content = [
|
|
2628
2734
|
`# Visor Debug Information`,
|
|
2629
2735
|
``,
|
|
@@ -2656,12 +2762,12 @@ var init_reviewer = __esm({
|
|
|
2656
2762
|
});
|
|
2657
2763
|
|
|
2658
2764
|
// src/git-repository-analyzer.ts
|
|
2659
|
-
var import_simple_git,
|
|
2765
|
+
var import_simple_git, path3, fs2, MAX_PATCH_SIZE, GitRepositoryAnalyzer;
|
|
2660
2766
|
var init_git_repository_analyzer = __esm({
|
|
2661
2767
|
"src/git-repository-analyzer.ts"() {
|
|
2662
2768
|
"use strict";
|
|
2663
2769
|
import_simple_git = require("simple-git");
|
|
2664
|
-
|
|
2770
|
+
path3 = __toESM(require("path"));
|
|
2665
2771
|
fs2 = __toESM(require("fs"));
|
|
2666
2772
|
MAX_PATCH_SIZE = 50 * 1024;
|
|
2667
2773
|
GitRepositoryAnalyzer = class {
|
|
@@ -2876,7 +2982,7 @@ ${file.patch}`).join("\n\n");
|
|
|
2876
2982
|
console.error(`\u23ED\uFE0F Skipping excluded file: ${file}`);
|
|
2877
2983
|
continue;
|
|
2878
2984
|
}
|
|
2879
|
-
const filePath =
|
|
2985
|
+
const filePath = path3.join(this.cwd, file);
|
|
2880
2986
|
const fileChange = await this.analyzeFileChange(file, status2, filePath, includeContext);
|
|
2881
2987
|
changes.push(fileChange);
|
|
2882
2988
|
}
|
|
@@ -3356,12 +3462,12 @@ var init_env_resolver = __esm({
|
|
|
3356
3462
|
});
|
|
3357
3463
|
|
|
3358
3464
|
// src/issue-filter.ts
|
|
3359
|
-
var fs3,
|
|
3465
|
+
var fs3, path4, IssueFilter;
|
|
3360
3466
|
var init_issue_filter = __esm({
|
|
3361
3467
|
"src/issue-filter.ts"() {
|
|
3362
3468
|
"use strict";
|
|
3363
3469
|
fs3 = __toESM(require("fs"));
|
|
3364
|
-
|
|
3470
|
+
path4 = __toESM(require("path"));
|
|
3365
3471
|
IssueFilter = class {
|
|
3366
3472
|
fileCache = /* @__PURE__ */ new Map();
|
|
3367
3473
|
suppressionEnabled;
|
|
@@ -3429,7 +3535,7 @@ var init_issue_filter = __esm({
|
|
|
3429
3535
|
return this.fileCache.get(filePath);
|
|
3430
3536
|
}
|
|
3431
3537
|
try {
|
|
3432
|
-
const resolvedPath =
|
|
3538
|
+
const resolvedPath = path4.isAbsolute(filePath) ? filePath : path4.join(workingDir, filePath);
|
|
3433
3539
|
if (!fs3.existsSync(resolvedPath)) {
|
|
3434
3540
|
if (fs3.existsSync(filePath)) {
|
|
3435
3541
|
const content2 = fs3.readFileSync(filePath, "utf8");
|
|
@@ -9306,7 +9412,7 @@ function resolveTargetPath(outDir) {
|
|
|
9306
9412
|
}
|
|
9307
9413
|
if (CURRENT_FILE) return CURRENT_FILE;
|
|
9308
9414
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
9309
|
-
CURRENT_FILE =
|
|
9415
|
+
CURRENT_FILE = path9.join(outDir, `${ts}.ndjson`);
|
|
9310
9416
|
return CURRENT_FILE;
|
|
9311
9417
|
}
|
|
9312
9418
|
function isEnabled() {
|
|
@@ -9336,7 +9442,7 @@ async function flushNdjson() {
|
|
|
9336
9442
|
function emitNdjsonFallback(name, attrs) {
|
|
9337
9443
|
try {
|
|
9338
9444
|
if (!isEnabled()) return;
|
|
9339
|
-
const outDir = process.env.VISOR_TRACE_DIR ||
|
|
9445
|
+
const outDir = process.env.VISOR_TRACE_DIR || path9.join(process.cwd(), "output", "traces");
|
|
9340
9446
|
const line = JSON.stringify({ name, attributes: attrs }) + "\n";
|
|
9341
9447
|
appendAsync(outDir, line);
|
|
9342
9448
|
} catch {
|
|
@@ -9345,18 +9451,18 @@ function emitNdjsonFallback(name, attrs) {
|
|
|
9345
9451
|
function emitNdjsonSpanWithEvents(name, attrs, events) {
|
|
9346
9452
|
try {
|
|
9347
9453
|
if (!isEnabled()) return;
|
|
9348
|
-
const outDir = process.env.VISOR_TRACE_DIR ||
|
|
9454
|
+
const outDir = process.env.VISOR_TRACE_DIR || path9.join(process.cwd(), "output", "traces");
|
|
9349
9455
|
const line = JSON.stringify({ name, attributes: attrs, events }) + "\n";
|
|
9350
9456
|
appendAsync(outDir, line);
|
|
9351
9457
|
} catch {
|
|
9352
9458
|
}
|
|
9353
9459
|
}
|
|
9354
|
-
var fs8,
|
|
9460
|
+
var fs8, path9, CURRENT_FILE, dirReady, writeChain;
|
|
9355
9461
|
var init_fallback_ndjson = __esm({
|
|
9356
9462
|
"src/telemetry/fallback-ndjson.ts"() {
|
|
9357
9463
|
"use strict";
|
|
9358
9464
|
fs8 = __toESM(require("fs"));
|
|
9359
|
-
|
|
9465
|
+
path9 = __toESM(require("path"));
|
|
9360
9466
|
CURRENT_FILE = null;
|
|
9361
9467
|
dirReady = false;
|
|
9362
9468
|
writeChain = Promise.resolve();
|
|
@@ -9832,10 +9938,6 @@ var init_failure_condition_evaluator = __esm({
|
|
|
9832
9938
|
if (!Array.isArray(issues2)) return false;
|
|
9833
9939
|
return issues2.some((issue) => issue.file?.includes(pattern));
|
|
9834
9940
|
};
|
|
9835
|
-
const hasSuggestion = (suggestions2, text) => {
|
|
9836
|
-
if (!Array.isArray(suggestions2)) return false;
|
|
9837
|
-
return suggestions2.some((s) => s.toLowerCase().includes(text.toLowerCase()));
|
|
9838
|
-
};
|
|
9839
9941
|
const hasIssueWith = hasIssue;
|
|
9840
9942
|
const hasFileWith = hasFileMatching;
|
|
9841
9943
|
const permissionHelpers = createPermissionHelpers(
|
|
@@ -9850,7 +9952,6 @@ var init_failure_condition_evaluator = __esm({
|
|
|
9850
9952
|
const isFirstTimer2 = permissionHelpers.isFirstTimer;
|
|
9851
9953
|
const output = context2.output || {};
|
|
9852
9954
|
const issues = output.issues || [];
|
|
9853
|
-
const suggestions = [];
|
|
9854
9955
|
const metadata = context2.metadata || {
|
|
9855
9956
|
checkName: context2.checkName || "",
|
|
9856
9957
|
schema: context2.schema || "",
|
|
@@ -9894,7 +9995,6 @@ var init_failure_condition_evaluator = __esm({
|
|
|
9894
9995
|
memory: memoryAccessor,
|
|
9895
9996
|
// Legacy compatibility variables
|
|
9896
9997
|
issues,
|
|
9897
|
-
suggestions,
|
|
9898
9998
|
metadata,
|
|
9899
9999
|
criticalIssues,
|
|
9900
10000
|
errorIssues,
|
|
@@ -9923,7 +10023,6 @@ var init_failure_condition_evaluator = __esm({
|
|
|
9923
10023
|
hasIssue,
|
|
9924
10024
|
countIssues,
|
|
9925
10025
|
hasFileMatching,
|
|
9926
|
-
hasSuggestion,
|
|
9927
10026
|
hasIssueWith,
|
|
9928
10027
|
hasFileWith,
|
|
9929
10028
|
// Permission helpers
|
|
@@ -10193,6 +10292,7 @@ var GitHubCheckService;
|
|
|
10193
10292
|
var init_github_check_service = __esm({
|
|
10194
10293
|
"src/github-check-service.ts"() {
|
|
10195
10294
|
"use strict";
|
|
10295
|
+
init_footer();
|
|
10196
10296
|
GitHubCheckService = class {
|
|
10197
10297
|
octokit;
|
|
10198
10298
|
maxAnnotations = 50;
|
|
@@ -10433,11 +10533,7 @@ Please check your configuration and try again.`
|
|
|
10433
10533
|
});
|
|
10434
10534
|
}
|
|
10435
10535
|
sections.push("");
|
|
10436
|
-
sections.push(
|
|
10437
|
-
sections.push("");
|
|
10438
|
-
sections.push(
|
|
10439
|
-
"*Powered by [Visor](https://probelabs.com/visor) from [Probelabs](https://probelabs.com)*"
|
|
10440
|
-
);
|
|
10536
|
+
sections.push(generateFooter());
|
|
10441
10537
|
return sections.join("\n");
|
|
10442
10538
|
}
|
|
10443
10539
|
/**
|
|
@@ -10655,12 +10751,12 @@ function emitMermaidFromMarkdown(checkName, markdown, origin) {
|
|
|
10655
10751
|
addEvent("diagram.block", { check: checkName, origin, code });
|
|
10656
10752
|
addDiagramBlock(origin);
|
|
10657
10753
|
if (process.env.VISOR_TRACE_REPORT === "true") {
|
|
10658
|
-
const outDir = process.env.VISOR_TRACE_DIR ||
|
|
10754
|
+
const outDir = process.env.VISOR_TRACE_DIR || path10.join(process.cwd(), "output", "traces");
|
|
10659
10755
|
try {
|
|
10660
10756
|
if (!fs9.existsSync(outDir)) fs9.mkdirSync(outDir, { recursive: true });
|
|
10661
10757
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
10662
|
-
const jsonPath =
|
|
10663
|
-
const htmlPath =
|
|
10758
|
+
const jsonPath = path10.join(outDir, `${ts}.trace.json`);
|
|
10759
|
+
const htmlPath = path10.join(outDir, `${ts}.report.html`);
|
|
10664
10760
|
let data = { spans: [] };
|
|
10665
10761
|
if (fs9.existsSync(jsonPath)) {
|
|
10666
10762
|
try {
|
|
@@ -10690,14 +10786,14 @@ function emitMermaidFromMarkdown(checkName, markdown, origin) {
|
|
|
10690
10786
|
}
|
|
10691
10787
|
return count;
|
|
10692
10788
|
}
|
|
10693
|
-
var fs9,
|
|
10789
|
+
var fs9, path10, MERMAID_RE;
|
|
10694
10790
|
var init_mermaid_telemetry = __esm({
|
|
10695
10791
|
"src/utils/mermaid-telemetry.ts"() {
|
|
10696
10792
|
"use strict";
|
|
10697
10793
|
init_trace_helpers();
|
|
10698
10794
|
init_metrics2();
|
|
10699
10795
|
fs9 = __toESM(require("fs"));
|
|
10700
|
-
|
|
10796
|
+
path10 = __toESM(require("path"));
|
|
10701
10797
|
MERMAID_RE = /```mermaid\s*\n([\s\S]*?)\n```/gi;
|
|
10702
10798
|
}
|
|
10703
10799
|
});
|
|
@@ -12063,7 +12159,7 @@ ${expr}
|
|
|
12063
12159
|
* - Enforcing .liquid file extension
|
|
12064
12160
|
*/
|
|
12065
12161
|
async validateTemplatePath(templatePath) {
|
|
12066
|
-
const
|
|
12162
|
+
const path13 = await import("path");
|
|
12067
12163
|
if (!templatePath || typeof templatePath !== "string" || templatePath.trim() === "") {
|
|
12068
12164
|
throw new Error("Template path must be a non-empty string");
|
|
12069
12165
|
}
|
|
@@ -12073,7 +12169,7 @@ ${expr}
|
|
|
12073
12169
|
if (!templatePath.endsWith(".liquid")) {
|
|
12074
12170
|
throw new Error("Template file must have .liquid extension");
|
|
12075
12171
|
}
|
|
12076
|
-
if (
|
|
12172
|
+
if (path13.isAbsolute(templatePath)) {
|
|
12077
12173
|
throw new Error("Template path must be relative to project directory");
|
|
12078
12174
|
}
|
|
12079
12175
|
if (templatePath.includes("..")) {
|
|
@@ -12087,14 +12183,14 @@ ${expr}
|
|
|
12087
12183
|
if (!projectRoot || typeof projectRoot !== "string") {
|
|
12088
12184
|
throw new Error("Unable to determine project root directory");
|
|
12089
12185
|
}
|
|
12090
|
-
const resolvedPath =
|
|
12091
|
-
const resolvedProjectRoot =
|
|
12186
|
+
const resolvedPath = path13.resolve(projectRoot, templatePath);
|
|
12187
|
+
const resolvedProjectRoot = path13.resolve(projectRoot);
|
|
12092
12188
|
if (!resolvedPath || !resolvedProjectRoot || resolvedPath === "" || resolvedProjectRoot === "") {
|
|
12093
12189
|
throw new Error(
|
|
12094
12190
|
`Unable to resolve template path: projectRoot="${projectRoot}", templatePath="${templatePath}", resolvedPath="${resolvedPath}", resolvedProjectRoot="${resolvedProjectRoot}"`
|
|
12095
12191
|
);
|
|
12096
12192
|
}
|
|
12097
|
-
if (!resolvedPath.startsWith(resolvedProjectRoot +
|
|
12193
|
+
if (!resolvedPath.startsWith(resolvedProjectRoot + path13.sep) && resolvedPath !== resolvedProjectRoot) {
|
|
12098
12194
|
throw new Error("Template path escapes project directory");
|
|
12099
12195
|
}
|
|
12100
12196
|
return resolvedPath;
|
|
@@ -12139,7 +12235,7 @@ ${expr}
|
|
|
12139
12235
|
}
|
|
12140
12236
|
const { createExtendedLiquid: createExtendedLiquid2 } = await Promise.resolve().then(() => (init_liquid_extensions(), liquid_extensions_exports));
|
|
12141
12237
|
const fs12 = await import("fs/promises");
|
|
12142
|
-
const
|
|
12238
|
+
const path13 = await import("path");
|
|
12143
12239
|
const liquid = createExtendedLiquid2({
|
|
12144
12240
|
trimTagLeft: false,
|
|
12145
12241
|
trimTagRight: false,
|
|
@@ -12173,7 +12269,7 @@ ${expr}
|
|
|
12173
12269
|
if (!sanitizedSchema) {
|
|
12174
12270
|
throw new Error("Invalid schema name");
|
|
12175
12271
|
}
|
|
12176
|
-
const templatePath =
|
|
12272
|
+
const templatePath = path13.join(__dirname, `../output/${sanitizedSchema}/template.liquid`);
|
|
12177
12273
|
templateContent = await fs12.readFile(templatePath, "utf-8");
|
|
12178
12274
|
if (sanitizedSchema === "issue-assistant") {
|
|
12179
12275
|
enrichAssistantContext = true;
|
|
@@ -16342,13 +16438,13 @@ init_check_execution_engine();
|
|
|
16342
16438
|
// src/config.ts
|
|
16343
16439
|
var yaml2 = __toESM(require("js-yaml"));
|
|
16344
16440
|
var fs11 = __toESM(require("fs"));
|
|
16345
|
-
var
|
|
16441
|
+
var path12 = __toESM(require("path"));
|
|
16346
16442
|
init_logger();
|
|
16347
16443
|
var import_simple_git2 = __toESM(require("simple-git"));
|
|
16348
16444
|
|
|
16349
16445
|
// src/utils/config-loader.ts
|
|
16350
16446
|
var fs10 = __toESM(require("fs"));
|
|
16351
|
-
var
|
|
16447
|
+
var path11 = __toESM(require("path"));
|
|
16352
16448
|
var yaml = __toESM(require("js-yaml"));
|
|
16353
16449
|
var ConfigLoader = class {
|
|
16354
16450
|
constructor(options = {}) {
|
|
@@ -16429,7 +16525,7 @@ var ConfigLoader = class {
|
|
|
16429
16525
|
return source.toLowerCase();
|
|
16430
16526
|
case "local" /* LOCAL */:
|
|
16431
16527
|
const basePath = this.options.baseDir || process.cwd();
|
|
16432
|
-
return
|
|
16528
|
+
return path11.resolve(basePath, source);
|
|
16433
16529
|
default:
|
|
16434
16530
|
return source;
|
|
16435
16531
|
}
|
|
@@ -16439,7 +16535,7 @@ var ConfigLoader = class {
|
|
|
16439
16535
|
*/
|
|
16440
16536
|
async fetchLocalConfig(filePath) {
|
|
16441
16537
|
const basePath = this.options.baseDir || process.cwd();
|
|
16442
|
-
const resolvedPath =
|
|
16538
|
+
const resolvedPath = path11.resolve(basePath, filePath);
|
|
16443
16539
|
this.validateLocalPath(resolvedPath);
|
|
16444
16540
|
if (!fs10.existsSync(resolvedPath)) {
|
|
16445
16541
|
throw new Error(`Configuration file not found: ${resolvedPath}`);
|
|
@@ -16451,7 +16547,7 @@ var ConfigLoader = class {
|
|
|
16451
16547
|
throw new Error(`Invalid YAML in configuration file: ${resolvedPath}`);
|
|
16452
16548
|
}
|
|
16453
16549
|
const previousBaseDir = this.options.baseDir;
|
|
16454
|
-
this.options.baseDir =
|
|
16550
|
+
this.options.baseDir = path11.dirname(resolvedPath);
|
|
16455
16551
|
try {
|
|
16456
16552
|
if (config.extends) {
|
|
16457
16553
|
const processedConfig = await this.processExtends(config);
|
|
@@ -16531,14 +16627,14 @@ var ConfigLoader = class {
|
|
|
16531
16627
|
async fetchDefaultConfig() {
|
|
16532
16628
|
const possiblePaths = [
|
|
16533
16629
|
// When running as GitHub Action (bundled in dist/)
|
|
16534
|
-
|
|
16630
|
+
path11.join(__dirname, "defaults", ".visor.yaml"),
|
|
16535
16631
|
// When running from source
|
|
16536
|
-
|
|
16632
|
+
path11.join(__dirname, "..", "..", "defaults", ".visor.yaml"),
|
|
16537
16633
|
// Try via package root
|
|
16538
|
-
this.findPackageRoot() ?
|
|
16634
|
+
this.findPackageRoot() ? path11.join(this.findPackageRoot(), "defaults", ".visor.yaml") : "",
|
|
16539
16635
|
// GitHub Action environment variable
|
|
16540
|
-
process.env.GITHUB_ACTION_PATH ?
|
|
16541
|
-
process.env.GITHUB_ACTION_PATH ?
|
|
16636
|
+
process.env.GITHUB_ACTION_PATH ? path11.join(process.env.GITHUB_ACTION_PATH, "defaults", ".visor.yaml") : "",
|
|
16637
|
+
process.env.GITHUB_ACTION_PATH ? path11.join(process.env.GITHUB_ACTION_PATH, "dist", "defaults", ".visor.yaml") : ""
|
|
16542
16638
|
].filter((p) => p);
|
|
16543
16639
|
let defaultConfigPath;
|
|
16544
16640
|
for (const possiblePath of possiblePaths) {
|
|
@@ -16628,8 +16724,8 @@ var ConfigLoader = class {
|
|
|
16628
16724
|
*/
|
|
16629
16725
|
validateLocalPath(resolvedPath) {
|
|
16630
16726
|
const projectRoot = this.options.projectRoot || process.cwd();
|
|
16631
|
-
const normalizedPath =
|
|
16632
|
-
const normalizedRoot =
|
|
16727
|
+
const normalizedPath = path11.normalize(resolvedPath);
|
|
16728
|
+
const normalizedRoot = path11.normalize(projectRoot);
|
|
16633
16729
|
if (!normalizedPath.startsWith(normalizedRoot)) {
|
|
16634
16730
|
throw new Error(
|
|
16635
16731
|
`Security error: Path traversal detected. Cannot access files outside project root: ${projectRoot}`
|
|
@@ -16655,9 +16751,9 @@ var ConfigLoader = class {
|
|
|
16655
16751
|
*/
|
|
16656
16752
|
findPackageRoot() {
|
|
16657
16753
|
let currentDir = __dirname;
|
|
16658
|
-
const root =
|
|
16754
|
+
const root = path11.parse(currentDir).root;
|
|
16659
16755
|
while (currentDir !== root) {
|
|
16660
|
-
const packageJsonPath =
|
|
16756
|
+
const packageJsonPath = path11.join(currentDir, "package.json");
|
|
16661
16757
|
if (fs10.existsSync(packageJsonPath)) {
|
|
16662
16758
|
try {
|
|
16663
16759
|
const packageJson = JSON.parse(fs10.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -16667,7 +16763,7 @@ var ConfigLoader = class {
|
|
|
16667
16763
|
} catch {
|
|
16668
16764
|
}
|
|
16669
16765
|
}
|
|
16670
|
-
currentDir =
|
|
16766
|
+
currentDir = path11.dirname(currentDir);
|
|
16671
16767
|
}
|
|
16672
16768
|
return null;
|
|
16673
16769
|
}
|
|
@@ -16690,6 +16786,16 @@ var ConfigLoader = class {
|
|
|
16690
16786
|
init_config_merger();
|
|
16691
16787
|
var import_ajv = __toESM(require("ajv"));
|
|
16692
16788
|
var import_ajv_formats = __toESM(require("ajv-formats"));
|
|
16789
|
+
var VALID_EVENT_TRIGGERS = [
|
|
16790
|
+
"pr_opened",
|
|
16791
|
+
"pr_updated",
|
|
16792
|
+
"pr_closed",
|
|
16793
|
+
"issue_opened",
|
|
16794
|
+
"issue_comment",
|
|
16795
|
+
"manual",
|
|
16796
|
+
"schedule",
|
|
16797
|
+
"webhook_received"
|
|
16798
|
+
];
|
|
16693
16799
|
var ConfigManager = class {
|
|
16694
16800
|
validCheckTypes = [
|
|
16695
16801
|
"ai",
|
|
@@ -16698,20 +16804,13 @@ var ConfigManager = class {
|
|
|
16698
16804
|
"http",
|
|
16699
16805
|
"http_input",
|
|
16700
16806
|
"http_client",
|
|
16807
|
+
"memory",
|
|
16701
16808
|
"noop",
|
|
16702
16809
|
"log",
|
|
16810
|
+
"memory",
|
|
16703
16811
|
"github"
|
|
16704
16812
|
];
|
|
16705
|
-
validEventTriggers = [
|
|
16706
|
-
"pr_opened",
|
|
16707
|
-
"pr_updated",
|
|
16708
|
-
"pr_closed",
|
|
16709
|
-
"issue_opened",
|
|
16710
|
-
"issue_comment",
|
|
16711
|
-
"manual",
|
|
16712
|
-
"schedule",
|
|
16713
|
-
"webhook_received"
|
|
16714
|
-
];
|
|
16813
|
+
validEventTriggers = [...VALID_EVENT_TRIGGERS];
|
|
16715
16814
|
validOutputFormats = ["table", "json", "markdown", "sarif"];
|
|
16716
16815
|
validGroupByOptions = ["check", "file", "severity", "group"];
|
|
16717
16816
|
/**
|
|
@@ -16719,24 +16818,25 @@ var ConfigManager = class {
|
|
|
16719
16818
|
*/
|
|
16720
16819
|
async loadConfig(configPath, options = {}) {
|
|
16721
16820
|
const { validate = true, mergeDefaults = true, allowedRemotePatterns } = options;
|
|
16821
|
+
const resolvedPath = path12.isAbsolute(configPath) ? configPath : path12.resolve(process.cwd(), configPath);
|
|
16722
16822
|
try {
|
|
16723
|
-
if (!fs11.existsSync(
|
|
16724
|
-
throw new Error(`Configuration file not found: ${
|
|
16823
|
+
if (!fs11.existsSync(resolvedPath)) {
|
|
16824
|
+
throw new Error(`Configuration file not found: ${resolvedPath}`);
|
|
16725
16825
|
}
|
|
16726
|
-
const configContent = fs11.readFileSync(
|
|
16826
|
+
const configContent = fs11.readFileSync(resolvedPath, "utf8");
|
|
16727
16827
|
let parsedConfig;
|
|
16728
16828
|
try {
|
|
16729
16829
|
parsedConfig = yaml2.load(configContent);
|
|
16730
16830
|
} catch (yamlError) {
|
|
16731
16831
|
const errorMessage = yamlError instanceof Error ? yamlError.message : String(yamlError);
|
|
16732
|
-
throw new Error(`Invalid YAML syntax in ${
|
|
16832
|
+
throw new Error(`Invalid YAML syntax in ${resolvedPath}: ${errorMessage}`);
|
|
16733
16833
|
}
|
|
16734
16834
|
if (!parsedConfig || typeof parsedConfig !== "object") {
|
|
16735
16835
|
throw new Error("Configuration file must contain a valid YAML object");
|
|
16736
16836
|
}
|
|
16737
16837
|
if (parsedConfig.extends) {
|
|
16738
16838
|
const loaderOptions = {
|
|
16739
|
-
baseDir:
|
|
16839
|
+
baseDir: path12.dirname(resolvedPath),
|
|
16740
16840
|
allowRemote: this.isRemoteExtendsAllowed(),
|
|
16741
16841
|
maxDepth: 10,
|
|
16742
16842
|
allowedRemotePatterns
|
|
@@ -16768,12 +16868,12 @@ var ConfigManager = class {
|
|
|
16768
16868
|
throw error;
|
|
16769
16869
|
}
|
|
16770
16870
|
if (error.message.includes("ENOENT")) {
|
|
16771
|
-
throw new Error(`Configuration file not found: ${
|
|
16871
|
+
throw new Error(`Configuration file not found: ${resolvedPath}`);
|
|
16772
16872
|
}
|
|
16773
16873
|
if (error.message.includes("EPERM")) {
|
|
16774
|
-
throw new Error(`Permission denied reading configuration file: ${
|
|
16874
|
+
throw new Error(`Permission denied reading configuration file: ${resolvedPath}`);
|
|
16775
16875
|
}
|
|
16776
|
-
throw new Error(`Failed to read configuration file ${
|
|
16876
|
+
throw new Error(`Failed to read configuration file ${resolvedPath}: ${error.message}`);
|
|
16777
16877
|
}
|
|
16778
16878
|
throw error;
|
|
16779
16879
|
}
|
|
@@ -16785,7 +16885,7 @@ var ConfigManager = class {
|
|
|
16785
16885
|
const gitRoot = await this.findGitRepositoryRoot();
|
|
16786
16886
|
const searchDirs = [gitRoot, process.cwd()].filter(Boolean);
|
|
16787
16887
|
for (const baseDir of searchDirs) {
|
|
16788
|
-
const possiblePaths = [
|
|
16888
|
+
const possiblePaths = [path12.join(baseDir, ".visor.yaml"), path12.join(baseDir, ".visor.yml")];
|
|
16789
16889
|
for (const configPath of possiblePaths) {
|
|
16790
16890
|
if (fs11.existsSync(configPath)) {
|
|
16791
16891
|
return this.loadConfig(configPath, options);
|
|
@@ -16839,18 +16939,18 @@ var ConfigManager = class {
|
|
|
16839
16939
|
const possiblePaths = [];
|
|
16840
16940
|
if (typeof __dirname !== "undefined") {
|
|
16841
16941
|
possiblePaths.push(
|
|
16842
|
-
|
|
16843
|
-
|
|
16942
|
+
path12.join(__dirname, "defaults", ".visor.yaml"),
|
|
16943
|
+
path12.join(__dirname, "..", "defaults", ".visor.yaml")
|
|
16844
16944
|
);
|
|
16845
16945
|
}
|
|
16846
16946
|
const pkgRoot = this.findPackageRoot();
|
|
16847
16947
|
if (pkgRoot) {
|
|
16848
|
-
possiblePaths.push(
|
|
16948
|
+
possiblePaths.push(path12.join(pkgRoot, "defaults", ".visor.yaml"));
|
|
16849
16949
|
}
|
|
16850
16950
|
if (process.env.GITHUB_ACTION_PATH) {
|
|
16851
16951
|
possiblePaths.push(
|
|
16852
|
-
|
|
16853
|
-
|
|
16952
|
+
path12.join(process.env.GITHUB_ACTION_PATH, "defaults", ".visor.yaml"),
|
|
16953
|
+
path12.join(process.env.GITHUB_ACTION_PATH, "dist", "defaults", ".visor.yaml")
|
|
16854
16954
|
);
|
|
16855
16955
|
}
|
|
16856
16956
|
let bundledConfigPath;
|
|
@@ -16883,8 +16983,8 @@ var ConfigManager = class {
|
|
|
16883
16983
|
*/
|
|
16884
16984
|
findPackageRoot() {
|
|
16885
16985
|
let currentDir = __dirname;
|
|
16886
|
-
while (currentDir !==
|
|
16887
|
-
const packageJsonPath =
|
|
16986
|
+
while (currentDir !== path12.dirname(currentDir)) {
|
|
16987
|
+
const packageJsonPath = path12.join(currentDir, "package.json");
|
|
16888
16988
|
if (fs11.existsSync(packageJsonPath)) {
|
|
16889
16989
|
try {
|
|
16890
16990
|
const packageJson = JSON.parse(fs11.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -16894,7 +16994,7 @@ var ConfigManager = class {
|
|
|
16894
16994
|
} catch {
|
|
16895
16995
|
}
|
|
16896
16996
|
}
|
|
16897
|
-
currentDir =
|
|
16997
|
+
currentDir = path12.dirname(currentDir);
|
|
16898
16998
|
}
|
|
16899
16999
|
return null;
|
|
16900
17000
|
}
|
|
@@ -17279,7 +17379,7 @@ var ConfigManager = class {
|
|
|
17279
17379
|
try {
|
|
17280
17380
|
if (!__ajvValidate) {
|
|
17281
17381
|
try {
|
|
17282
|
-
const jsonPath =
|
|
17382
|
+
const jsonPath = path12.resolve(__dirname, "generated", "config-schema.json");
|
|
17283
17383
|
const jsonSchema = require(jsonPath);
|
|
17284
17384
|
if (jsonSchema) {
|
|
17285
17385
|
const ajv = new import_ajv.default({ allErrors: true, allowUnionTypes: true, strict: false });
|