@probelabs/visor 0.1.33 → 0.1.35
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 +221 -7
- package/defaults/.visor.yaml +13 -22
- package/dist/ai-review-service.d.ts +1 -1
- package/dist/ai-review-service.d.ts.map +1 -1
- package/dist/check-execution-engine.d.ts +2 -0
- package/dist/check-execution-engine.d.ts.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/defaults/.visor.yaml +13 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +676 -130
- package/dist/issue-filter.d.ts +28 -0
- package/dist/issue-filter.d.ts.map +1 -0
- package/dist/pr-analyzer.d.ts.map +1 -1
- package/dist/providers/ai-check-provider.d.ts.map +1 -1
- package/dist/providers/tool-check-provider.d.ts.map +1 -1
- package/dist/providers/webhook-check-provider.d.ts.map +1 -1
- package/dist/reviewer.d.ts.map +1 -1
- package/dist/types/config.d.ts +2 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -80893,45 +80893,168 @@ class AIReviewService {
|
|
|
80893
80893
|
*/
|
|
80894
80894
|
async buildCustomPrompt(prInfo, customInstructions, _schema) {
|
|
80895
80895
|
const prContext = this.formatPRContext(prInfo);
|
|
80896
|
+
const isIssue = prInfo.isIssue === true;
|
|
80897
|
+
if (isIssue) {
|
|
80898
|
+
// Issue context - no code analysis needed
|
|
80899
|
+
return `<review_request>
|
|
80900
|
+
<instructions>
|
|
80901
|
+
${customInstructions}
|
|
80902
|
+
</instructions>
|
|
80903
|
+
|
|
80904
|
+
<context>
|
|
80905
|
+
${prContext}
|
|
80906
|
+
</context>
|
|
80907
|
+
|
|
80908
|
+
<rules>
|
|
80909
|
+
<rule>Understand the issue context and requirements from the XML data structure</rule>
|
|
80910
|
+
<rule>Provide helpful, actionable guidance based on the issue details</rule>
|
|
80911
|
+
<rule>Be constructive and supportive in your analysis</rule>
|
|
80912
|
+
<rule>Consider project conventions and patterns when making recommendations</rule>
|
|
80913
|
+
<rule>Suggest practical solutions or next steps that address the specific concern</rule>
|
|
80914
|
+
<rule>Focus on addressing the specific concern raised in the issue</rule>
|
|
80915
|
+
<rule>Reference relevant XML elements like metadata, description, labels, assignees when providing context</rule>
|
|
80916
|
+
</rules>
|
|
80917
|
+
</review_request>`;
|
|
80918
|
+
}
|
|
80919
|
+
// PR context - structured XML format
|
|
80896
80920
|
const analysisType = prInfo.isIncremental ? 'INCREMENTAL' : 'FULL';
|
|
80897
|
-
return
|
|
80921
|
+
return `<review_request>
|
|
80922
|
+
<analysis_type>${analysisType}</analysis_type>
|
|
80898
80923
|
|
|
80899
|
-
|
|
80900
|
-
${analysisType === 'INCREMENTAL'
|
|
80901
|
-
? '
|
|
80902
|
-
: '
|
|
80924
|
+
<analysis_focus>
|
|
80925
|
+
${analysisType === 'INCREMENTAL'
|
|
80926
|
+
? 'You are analyzing a NEW COMMIT added to an existing PR. Focus on the changes in the commit_diff section for this specific commit.'
|
|
80927
|
+
: 'You are analyzing the COMPLETE PR. Review all changes in the full_diff section.'}
|
|
80928
|
+
</analysis_focus>
|
|
80903
80929
|
|
|
80904
|
-
|
|
80930
|
+
<instructions>
|
|
80905
80931
|
${customInstructions}
|
|
80932
|
+
</instructions>
|
|
80906
80933
|
|
|
80907
|
-
|
|
80908
|
-
|
|
80934
|
+
<context>
|
|
80909
80935
|
${prContext}
|
|
80910
|
-
|
|
80911
|
-
|
|
80912
|
-
|
|
80913
|
-
|
|
80914
|
-
|
|
80915
|
-
|
|
80916
|
-
|
|
80917
|
-
|
|
80918
|
-
|
|
80919
|
-
|
|
80920
|
-
|
|
80921
|
-
|
|
80922
|
-
|
|
80923
|
-
4. Focus on real issues, not nitpicks
|
|
80924
|
-
5. Provide actionable, specific feedback
|
|
80925
|
-
6. For INCREMENTAL analysis, ONLY review changes in <commit_diff>
|
|
80926
|
-
7. For FULL analysis, review all changes in <full_diff>`;
|
|
80936
|
+
</context>
|
|
80937
|
+
|
|
80938
|
+
<rules>
|
|
80939
|
+
<rule>Only analyze code that appears with + (additions) or - (deletions) in the diff sections</rule>
|
|
80940
|
+
<rule>Ignore unchanged code unless directly relevant to understanding a change</rule>
|
|
80941
|
+
<rule>Line numbers in your response should match actual file line numbers from the diff</rule>
|
|
80942
|
+
<rule>Focus on real issues, not nitpicks or cosmetic concerns</rule>
|
|
80943
|
+
<rule>Provide actionable, specific feedback with clear remediation steps</rule>
|
|
80944
|
+
<rule>For INCREMENTAL analysis, ONLY review changes in commit_diff section</rule>
|
|
80945
|
+
<rule>For FULL analysis, review all changes in full_diff section</rule>
|
|
80946
|
+
<rule>Reference specific XML elements like files_summary, metadata when providing context</rule>
|
|
80947
|
+
</rules>
|
|
80948
|
+
</review_request>`;
|
|
80927
80949
|
}
|
|
80928
80950
|
// REMOVED: Built-in prompts - only use custom prompts from .visor.yaml
|
|
80929
80951
|
// REMOVED: getFocusInstructions - only use custom prompts from .visor.yaml
|
|
80930
80952
|
/**
|
|
80931
|
-
* Format PR context for the AI using XML structure
|
|
80953
|
+
* Format PR or Issue context for the AI using XML structure
|
|
80932
80954
|
*/
|
|
80933
80955
|
formatPRContext(prInfo) {
|
|
80956
|
+
// Check if this is an issue (not a PR)
|
|
80957
|
+
const isIssue = prInfo.isIssue === true;
|
|
80958
|
+
if (isIssue) {
|
|
80959
|
+
// Format as issue context
|
|
80960
|
+
let context = `<issue>
|
|
80961
|
+
<!-- Core issue metadata including identification, status, and timeline information -->
|
|
80962
|
+
<metadata>
|
|
80963
|
+
<number>${prInfo.number}</number>
|
|
80964
|
+
<title>${this.escapeXml(prInfo.title)}</title>
|
|
80965
|
+
<author>${prInfo.author}</author>
|
|
80966
|
+
<state>${prInfo.eventContext?.issue?.state || 'open'}</state>
|
|
80967
|
+
<created_at>${prInfo.eventContext?.issue?.created_at || ''}</created_at>
|
|
80968
|
+
<updated_at>${prInfo.eventContext?.issue?.updated_at || ''}</updated_at>
|
|
80969
|
+
<comments_count>${prInfo.eventContext?.issue?.comments || 0}</comments_count>
|
|
80970
|
+
</metadata>`;
|
|
80971
|
+
// Add issue body/description if available
|
|
80972
|
+
if (prInfo.body) {
|
|
80973
|
+
context += `
|
|
80974
|
+
<!-- Full issue description and body text provided by the issue author -->
|
|
80975
|
+
<description>
|
|
80976
|
+
${this.escapeXml(prInfo.body)}
|
|
80977
|
+
</description>`;
|
|
80978
|
+
}
|
|
80979
|
+
// Add labels if available
|
|
80980
|
+
const labels = prInfo.eventContext?.issue?.labels;
|
|
80981
|
+
if (labels && labels.length > 0) {
|
|
80982
|
+
context += `
|
|
80983
|
+
<!-- Applied labels for issue categorization and organization -->
|
|
80984
|
+
<labels>`;
|
|
80985
|
+
labels.forEach((label) => {
|
|
80986
|
+
context += `
|
|
80987
|
+
<label>${this.escapeXml(label.name || label)}</label>`;
|
|
80988
|
+
});
|
|
80989
|
+
context += `
|
|
80990
|
+
</labels>`;
|
|
80991
|
+
}
|
|
80992
|
+
// Add assignees if available
|
|
80993
|
+
const assignees = prInfo.eventContext?.issue?.assignees;
|
|
80994
|
+
if (assignees && assignees.length > 0) {
|
|
80995
|
+
context += `
|
|
80996
|
+
<!-- Users assigned to work on this issue -->
|
|
80997
|
+
<assignees>`;
|
|
80998
|
+
assignees.forEach((assignee) => {
|
|
80999
|
+
context += `
|
|
81000
|
+
<assignee>${this.escapeXml(assignee.login || assignee)}</assignee>`;
|
|
81001
|
+
});
|
|
81002
|
+
context += `
|
|
81003
|
+
</assignees>`;
|
|
81004
|
+
}
|
|
81005
|
+
// Add milestone if available
|
|
81006
|
+
const milestone = prInfo.eventContext?.issue?.milestone;
|
|
81007
|
+
if (milestone) {
|
|
81008
|
+
context += `
|
|
81009
|
+
<!-- Associated project milestone information -->
|
|
81010
|
+
<milestone>
|
|
81011
|
+
<title>${this.escapeXml(milestone.title || '')}</title>
|
|
81012
|
+
<state>${milestone.state || 'open'}</state>
|
|
81013
|
+
<due_on>${milestone.due_on || ''}</due_on>
|
|
81014
|
+
</milestone>`;
|
|
81015
|
+
}
|
|
81016
|
+
// Add current/triggering comment if this is a comment event
|
|
81017
|
+
const triggeringComment = prInfo.eventContext?.comment;
|
|
81018
|
+
if (triggeringComment) {
|
|
81019
|
+
context += `
|
|
81020
|
+
<!-- The comment that triggered this analysis -->
|
|
81021
|
+
<triggering_comment>
|
|
81022
|
+
<author>${this.escapeXml(triggeringComment.user?.login || 'unknown')}</author>
|
|
81023
|
+
<created_at>${triggeringComment.created_at || ''}</created_at>
|
|
81024
|
+
<body>${this.escapeXml(triggeringComment.body || '')}</body>
|
|
81025
|
+
</triggering_comment>`;
|
|
81026
|
+
}
|
|
81027
|
+
// Add comment history (excluding the current comment if it exists)
|
|
81028
|
+
const issueComments = prInfo.comments;
|
|
81029
|
+
if (issueComments && issueComments.length > 0) {
|
|
81030
|
+
// Filter out the triggering comment from history if present
|
|
81031
|
+
const historicalComments = triggeringComment
|
|
81032
|
+
? issueComments.filter((c) => c.id !== triggeringComment.id)
|
|
81033
|
+
: issueComments;
|
|
81034
|
+
if (historicalComments.length > 0) {
|
|
81035
|
+
context += `
|
|
81036
|
+
<!-- Previous comments in chronological order (excluding triggering comment) -->
|
|
81037
|
+
<comment_history>`;
|
|
81038
|
+
historicalComments.forEach((comment) => {
|
|
81039
|
+
context += `
|
|
81040
|
+
<comment>
|
|
81041
|
+
<author>${this.escapeXml(comment.author || 'unknown')}</author>
|
|
81042
|
+
<created_at>${comment.createdAt || ''}</created_at>
|
|
81043
|
+
<body>${this.escapeXml(comment.body || '')}</body>
|
|
81044
|
+
</comment>`;
|
|
81045
|
+
});
|
|
81046
|
+
context += `
|
|
81047
|
+
</comment_history>`;
|
|
81048
|
+
}
|
|
81049
|
+
}
|
|
81050
|
+
// Close the issue tag
|
|
81051
|
+
context += `
|
|
81052
|
+
</issue>`;
|
|
81053
|
+
return context;
|
|
81054
|
+
}
|
|
81055
|
+
// Original PR context formatting
|
|
80934
81056
|
let context = `<pull_request>
|
|
81057
|
+
<!-- Core pull request metadata including identification, branches, and change statistics -->
|
|
80935
81058
|
<metadata>
|
|
80936
81059
|
<number>${prInfo.number}</number>
|
|
80937
81060
|
<title>${this.escapeXml(prInfo.title)}</title>
|
|
@@ -80945,6 +81068,7 @@ IMPORTANT RULES:
|
|
|
80945
81068
|
// Add PR description if available
|
|
80946
81069
|
if (prInfo.body) {
|
|
80947
81070
|
context += `
|
|
81071
|
+
<!-- Full pull request description provided by the author -->
|
|
80948
81072
|
<description>
|
|
80949
81073
|
${this.escapeXml(prInfo.body)}
|
|
80950
81074
|
</description>`;
|
|
@@ -80952,6 +81076,7 @@ ${this.escapeXml(prInfo.body)}
|
|
|
80952
81076
|
// Add full diff if available (for complete PR review)
|
|
80953
81077
|
if (prInfo.fullDiff) {
|
|
80954
81078
|
context += `
|
|
81079
|
+
<!-- Complete unified diff showing all changes in the pull request -->
|
|
80955
81080
|
<full_diff>
|
|
80956
81081
|
${this.escapeXml(prInfo.fullDiff)}
|
|
80957
81082
|
</full_diff>`;
|
|
@@ -80960,14 +81085,15 @@ ${this.escapeXml(prInfo.fullDiff)}
|
|
|
80960
81085
|
if (prInfo.isIncremental) {
|
|
80961
81086
|
if (prInfo.commitDiff && prInfo.commitDiff.length > 0) {
|
|
80962
81087
|
context += `
|
|
81088
|
+
<!-- Diff of only the latest commit for incremental analysis -->
|
|
80963
81089
|
<commit_diff>
|
|
80964
81090
|
${this.escapeXml(prInfo.commitDiff)}
|
|
80965
81091
|
</commit_diff>`;
|
|
80966
81092
|
}
|
|
80967
81093
|
else {
|
|
80968
81094
|
context += `
|
|
81095
|
+
<!-- Commit diff could not be retrieved - falling back to full diff analysis -->
|
|
80969
81096
|
<commit_diff>
|
|
80970
|
-
<!-- Commit diff could not be retrieved - falling back to full diff analysis -->
|
|
80971
81097
|
${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
|
|
80972
81098
|
</commit_diff>`;
|
|
80973
81099
|
}
|
|
@@ -80975,10 +81101,11 @@ ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
|
|
|
80975
81101
|
// Add file summary for context
|
|
80976
81102
|
if (prInfo.files.length > 0) {
|
|
80977
81103
|
context += `
|
|
81104
|
+
<!-- Summary of all files changed with statistics -->
|
|
80978
81105
|
<files_summary>`;
|
|
80979
|
-
prInfo.files.forEach(
|
|
81106
|
+
prInfo.files.forEach(file => {
|
|
80980
81107
|
context += `
|
|
80981
|
-
<file
|
|
81108
|
+
<file>
|
|
80982
81109
|
<filename>${this.escapeXml(file.filename)}</filename>
|
|
80983
81110
|
<status>${file.status}</status>
|
|
80984
81111
|
<additions>${file.additions}</additions>
|
|
@@ -80988,6 +81115,40 @@ ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
|
|
|
80988
81115
|
context += `
|
|
80989
81116
|
</files_summary>`;
|
|
80990
81117
|
}
|
|
81118
|
+
// Add current/triggering comment if this is a comment event
|
|
81119
|
+
const triggeringComment = prInfo.eventContext?.comment;
|
|
81120
|
+
if (triggeringComment) {
|
|
81121
|
+
context += `
|
|
81122
|
+
<!-- The comment that triggered this analysis -->
|
|
81123
|
+
<triggering_comment>
|
|
81124
|
+
<author>${this.escapeXml(triggeringComment.user?.login || 'unknown')}</author>
|
|
81125
|
+
<created_at>${triggeringComment.created_at || ''}</created_at>
|
|
81126
|
+
<body>${this.escapeXml(triggeringComment.body || '')}</body>
|
|
81127
|
+
</triggering_comment>`;
|
|
81128
|
+
}
|
|
81129
|
+
// Add comment history (excluding the current comment if it exists)
|
|
81130
|
+
const prComments = prInfo.comments;
|
|
81131
|
+
if (prComments && prComments.length > 0) {
|
|
81132
|
+
// Filter out the triggering comment from history if present
|
|
81133
|
+
const historicalComments = triggeringComment
|
|
81134
|
+
? prComments.filter((c) => c.id !== triggeringComment.id)
|
|
81135
|
+
: prComments;
|
|
81136
|
+
if (historicalComments.length > 0) {
|
|
81137
|
+
context += `
|
|
81138
|
+
<!-- Previous PR comments in chronological order (excluding triggering comment) -->
|
|
81139
|
+
<comment_history>`;
|
|
81140
|
+
historicalComments.forEach((comment) => {
|
|
81141
|
+
context += `
|
|
81142
|
+
<comment>
|
|
81143
|
+
<author>${this.escapeXml(comment.author || 'unknown')}</author>
|
|
81144
|
+
<created_at>${comment.createdAt || ''}</created_at>
|
|
81145
|
+
<body>${this.escapeXml(comment.body || '')}</body>
|
|
81146
|
+
</comment>`;
|
|
81147
|
+
});
|
|
81148
|
+
context += `
|
|
81149
|
+
</comment_history>`;
|
|
81150
|
+
}
|
|
81151
|
+
}
|
|
80991
81152
|
context += `
|
|
80992
81153
|
</pull_request>`;
|
|
80993
81154
|
return context;
|
|
@@ -81563,6 +81724,7 @@ const check_provider_registry_1 = __nccwpck_require__(57140);
|
|
|
81563
81724
|
const dependency_resolver_1 = __nccwpck_require__(98645);
|
|
81564
81725
|
const failure_condition_evaluator_1 = __nccwpck_require__(54429);
|
|
81565
81726
|
const github_check_service_1 = __nccwpck_require__(21367);
|
|
81727
|
+
const issue_filter_1 = __nccwpck_require__(36879);
|
|
81566
81728
|
/**
|
|
81567
81729
|
* Filter environment variables to only include safe ones for sandbox evaluation
|
|
81568
81730
|
*/
|
|
@@ -81598,8 +81760,11 @@ class CheckExecutionEngine {
|
|
|
81598
81760
|
githubCheckService;
|
|
81599
81761
|
checkRunMap;
|
|
81600
81762
|
githubContext;
|
|
81763
|
+
workingDirectory;
|
|
81764
|
+
config;
|
|
81601
81765
|
constructor(workingDirectory) {
|
|
81602
|
-
this.
|
|
81766
|
+
this.workingDirectory = workingDirectory || process.cwd();
|
|
81767
|
+
this.gitAnalyzer = new git_repository_analyzer_1.GitRepositoryAnalyzer(this.workingDirectory);
|
|
81603
81768
|
this.providerRegistry = check_provider_registry_1.CheckProviderRegistry.getInstance();
|
|
81604
81769
|
this.failureEvaluator = new failure_condition_evaluator_1.FailureConditionEvaluator();
|
|
81605
81770
|
// Create a mock Octokit instance for local analysis
|
|
@@ -81743,6 +81908,8 @@ class CheckExecutionEngine {
|
|
|
81743
81908
|
* Execute review checks using parallel execution for multiple AI checks
|
|
81744
81909
|
*/
|
|
81745
81910
|
async executeReviewChecks(prInfo, checks, timeout, config, outputFormat, debug, maxParallelism, failFast) {
|
|
81911
|
+
// Store config for use in filtering
|
|
81912
|
+
this.config = config;
|
|
81746
81913
|
// Determine where to send log messages based on output format
|
|
81747
81914
|
const logFn = outputFormat === 'json' || outputFormat === 'sarif' ? console.error : console.log;
|
|
81748
81915
|
logFn(`🔧 Debug: executeReviewChecks called with checks: ${JSON.stringify(checks)}`);
|
|
@@ -82583,6 +82750,10 @@ class CheckExecutionEngine {
|
|
|
82583
82750
|
// Add summary information
|
|
82584
82751
|
aggregatedSuggestions.unshift(...debugInfo);
|
|
82585
82752
|
console.error(`🔧 Debug: Aggregated ${aggregatedIssues.length} issues from ${results.size} dependency-aware checks`);
|
|
82753
|
+
// Apply issue suppression filtering
|
|
82754
|
+
const suppressionEnabled = this.config?.output?.suppressionEnabled !== false;
|
|
82755
|
+
const issueFilter = new issue_filter_1.IssueFilter(suppressionEnabled);
|
|
82756
|
+
const filteredIssues = issueFilter.filterIssues(aggregatedIssues, this.workingDirectory);
|
|
82586
82757
|
// Collect debug information when debug mode is enabled
|
|
82587
82758
|
let aggregatedDebug;
|
|
82588
82759
|
if (debug) {
|
|
@@ -82621,7 +82792,7 @@ class CheckExecutionEngine {
|
|
|
82621
82792
|
}
|
|
82622
82793
|
}
|
|
82623
82794
|
return {
|
|
82624
|
-
issues:
|
|
82795
|
+
issues: filteredIssues,
|
|
82625
82796
|
suggestions: aggregatedSuggestions,
|
|
82626
82797
|
debug: aggregatedDebug,
|
|
82627
82798
|
};
|
|
@@ -82709,6 +82880,10 @@ class CheckExecutionEngine {
|
|
|
82709
82880
|
: `🔍 Parallel execution completed: ${successfulChecks} successful, ${failedChecks} failed`);
|
|
82710
82881
|
aggregatedSuggestions.unshift(...debugInfo);
|
|
82711
82882
|
console.error(`🔧 Debug: Aggregated ${aggregatedIssues.length} issues from ${results.length} checks`);
|
|
82883
|
+
// Apply issue suppression filtering
|
|
82884
|
+
const suppressionEnabled = this.config?.output?.suppressionEnabled !== false;
|
|
82885
|
+
const issueFilter = new issue_filter_1.IssueFilter(suppressionEnabled);
|
|
82886
|
+
const filteredIssues = issueFilter.filterIssues(aggregatedIssues, this.workingDirectory);
|
|
82712
82887
|
// Collect debug information when debug mode is enabled
|
|
82713
82888
|
let aggregatedDebug;
|
|
82714
82889
|
if (debug) {
|
|
@@ -82804,7 +82979,7 @@ class CheckExecutionEngine {
|
|
|
82804
82979
|
}
|
|
82805
82980
|
}
|
|
82806
82981
|
return {
|
|
82807
|
-
issues:
|
|
82982
|
+
issues: filteredIssues,
|
|
82808
82983
|
suggestions: aggregatedSuggestions,
|
|
82809
82984
|
debug: aggregatedDebug,
|
|
82810
82985
|
};
|
|
@@ -84023,13 +84198,31 @@ class ConfigManager {
|
|
|
84023
84198
|
*/
|
|
84024
84199
|
loadBundledDefaultConfig() {
|
|
84025
84200
|
try {
|
|
84026
|
-
//
|
|
84027
|
-
const
|
|
84028
|
-
|
|
84029
|
-
|
|
84201
|
+
// Try different paths to find the bundled default config
|
|
84202
|
+
const possiblePaths = [
|
|
84203
|
+
// When running as GitHub Action (bundled in dist/)
|
|
84204
|
+
path.join(__dirname, 'defaults', '.visor.yaml'),
|
|
84205
|
+
// When running from source
|
|
84206
|
+
path.join(__dirname, '..', 'defaults', '.visor.yaml'),
|
|
84207
|
+
// Try via package root
|
|
84208
|
+
this.findPackageRoot() ? path.join(this.findPackageRoot(), 'defaults', '.visor.yaml') : '',
|
|
84209
|
+
// GitHub Action environment variable
|
|
84210
|
+
process.env.GITHUB_ACTION_PATH
|
|
84211
|
+
? path.join(process.env.GITHUB_ACTION_PATH, 'defaults', '.visor.yaml')
|
|
84212
|
+
: '',
|
|
84213
|
+
process.env.GITHUB_ACTION_PATH
|
|
84214
|
+
? path.join(process.env.GITHUB_ACTION_PATH, 'dist', 'defaults', '.visor.yaml')
|
|
84215
|
+
: '',
|
|
84216
|
+
].filter(p => p); // Remove empty paths
|
|
84217
|
+
let bundledConfigPath;
|
|
84218
|
+
for (const possiblePath of possiblePaths) {
|
|
84219
|
+
if (fs.existsSync(possiblePath)) {
|
|
84220
|
+
bundledConfigPath = possiblePath;
|
|
84221
|
+
break;
|
|
84222
|
+
}
|
|
84030
84223
|
}
|
|
84031
|
-
|
|
84032
|
-
|
|
84224
|
+
if (bundledConfigPath && fs.existsSync(bundledConfigPath)) {
|
|
84225
|
+
console.log(`📦 Loading bundled default configuration from ${bundledConfigPath}`);
|
|
84033
84226
|
const configContent = fs.readFileSync(bundledConfigPath, 'utf8');
|
|
84034
84227
|
const parsedConfig = yaml.load(configContent);
|
|
84035
84228
|
if (!parsedConfig || typeof parsedConfig !== 'object') {
|
|
@@ -85983,7 +86176,6 @@ exports.run = run;
|
|
|
85983
86176
|
const rest_1 = __nccwpck_require__(47432);
|
|
85984
86177
|
const auth_app_1 = __nccwpck_require__(76479);
|
|
85985
86178
|
const core_1 = __nccwpck_require__(37484);
|
|
85986
|
-
const path = __importStar(__nccwpck_require__(16928));
|
|
85987
86179
|
const commands_1 = __nccwpck_require__(99153);
|
|
85988
86180
|
const pr_analyzer_1 = __nccwpck_require__(80100);
|
|
85989
86181
|
const reviewer_1 = __nccwpck_require__(532);
|
|
@@ -86147,12 +86339,12 @@ async function run() {
|
|
|
86147
86339
|
}
|
|
86148
86340
|
catch {
|
|
86149
86341
|
// Fall back to bundled default config
|
|
86150
|
-
|
|
86151
|
-
|
|
86152
|
-
config =
|
|
86153
|
-
console.log('📋 Using bundled default configuration
|
|
86342
|
+
const bundledConfig = configManager.loadBundledDefaultConfig();
|
|
86343
|
+
if (bundledConfig) {
|
|
86344
|
+
config = bundledConfig;
|
|
86345
|
+
console.log('📋 Using bundled default configuration');
|
|
86154
86346
|
}
|
|
86155
|
-
|
|
86347
|
+
else {
|
|
86156
86348
|
// Ultimate fallback if even defaults/.visor.yaml can't be loaded
|
|
86157
86349
|
config = {
|
|
86158
86350
|
version: '1.0',
|
|
@@ -86349,6 +86541,18 @@ async function handleIssueEvent(octokit, owner, repo, context, inputs, config, c
|
|
|
86349
86541
|
isIssue: true, // Flag to indicate this is an issue, not a PR
|
|
86350
86542
|
eventContext: context.event, // Pass the full event context for templates
|
|
86351
86543
|
};
|
|
86544
|
+
// Fetch comment history for issues
|
|
86545
|
+
try {
|
|
86546
|
+
console.log(`💬 Fetching comment history for issue #${issue.number}`);
|
|
86547
|
+
const analyzer = new pr_analyzer_1.PRAnalyzer(octokit);
|
|
86548
|
+
const comments = await analyzer.fetchPRComments(owner, repo, issue.number);
|
|
86549
|
+
prInfo.comments = comments;
|
|
86550
|
+
console.log(`✅ Retrieved ${comments.length} comments for issue`);
|
|
86551
|
+
}
|
|
86552
|
+
catch (error) {
|
|
86553
|
+
console.warn(`⚠️ Could not fetch issue comments: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
86554
|
+
prInfo.comments = [];
|
|
86555
|
+
}
|
|
86352
86556
|
// Run the checks using CheckExecutionEngine
|
|
86353
86557
|
const { CheckExecutionEngine } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(80299)));
|
|
86354
86558
|
const engine = new CheckExecutionEngine();
|
|
@@ -86520,7 +86724,7 @@ async function handleIssueComment(octokit, owner, repo, context, inputs, actionC
|
|
|
86520
86724
|
if (isPullRequest) {
|
|
86521
86725
|
// It's a PR comment - fetch the PR diff
|
|
86522
86726
|
prInfo = await analyzer.fetchPRDiff(owner, repo, prNumber, undefined, 'issue_comment');
|
|
86523
|
-
// Add event context for templates
|
|
86727
|
+
// Add event context for templates and XML generation
|
|
86524
86728
|
prInfo.eventContext = context.event;
|
|
86525
86729
|
}
|
|
86526
86730
|
else {
|
|
@@ -86538,8 +86742,19 @@ async function handleIssueComment(octokit, owner, repo, context, inputs, actionC
|
|
|
86538
86742
|
fullDiff: '',
|
|
86539
86743
|
eventType: 'issue_comment',
|
|
86540
86744
|
isIssue: true, // Flag to indicate this is an issue, not a PR
|
|
86541
|
-
eventContext: context.event, // Pass the full event context
|
|
86745
|
+
eventContext: context.event, // Pass the full event context
|
|
86542
86746
|
};
|
|
86747
|
+
// Fetch comment history for the issue
|
|
86748
|
+
try {
|
|
86749
|
+
console.log(`💬 Fetching comment history for issue #${issue.number}`);
|
|
86750
|
+
const comments = await analyzer.fetchPRComments(owner, repo, issue.number);
|
|
86751
|
+
prInfo.comments = comments;
|
|
86752
|
+
console.log(`✅ Retrieved ${comments.length} comments for issue`);
|
|
86753
|
+
}
|
|
86754
|
+
catch (error) {
|
|
86755
|
+
console.warn(`⚠️ Could not fetch issue comments: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
86756
|
+
prInfo.comments = [];
|
|
86757
|
+
}
|
|
86543
86758
|
}
|
|
86544
86759
|
// Extract common arguments
|
|
86545
86760
|
const focus = command.args?.find(arg => arg.startsWith('--focus='))?.split('=')[1];
|
|
@@ -86619,7 +86834,7 @@ async function handlePullRequestWithConfig(octokit, owner, repo, inputs, config,
|
|
|
86619
86834
|
let prInfo;
|
|
86620
86835
|
try {
|
|
86621
86836
|
prInfo = await analyzer.fetchPRDiff(owner, repo, prNumber, undefined, eventType);
|
|
86622
|
-
// Add event context for templates
|
|
86837
|
+
// Add event context for templates and XML generation
|
|
86623
86838
|
prInfo.eventContext = context.event;
|
|
86624
86839
|
}
|
|
86625
86840
|
catch (error) {
|
|
@@ -87094,6 +87309,159 @@ if (process.env.NODE_ENV !== 'test' && process.env.JEST_WORKER_ID === undefined)
|
|
|
87094
87309
|
}
|
|
87095
87310
|
|
|
87096
87311
|
|
|
87312
|
+
/***/ }),
|
|
87313
|
+
|
|
87314
|
+
/***/ 36879:
|
|
87315
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
87316
|
+
|
|
87317
|
+
"use strict";
|
|
87318
|
+
|
|
87319
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
87320
|
+
if (k2 === undefined) k2 = k;
|
|
87321
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
87322
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
87323
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
87324
|
+
}
|
|
87325
|
+
Object.defineProperty(o, k2, desc);
|
|
87326
|
+
}) : (function(o, m, k, k2) {
|
|
87327
|
+
if (k2 === undefined) k2 = k;
|
|
87328
|
+
o[k2] = m[k];
|
|
87329
|
+
}));
|
|
87330
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
87331
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
87332
|
+
}) : function(o, v) {
|
|
87333
|
+
o["default"] = v;
|
|
87334
|
+
});
|
|
87335
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
87336
|
+
var ownKeys = function(o) {
|
|
87337
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
87338
|
+
var ar = [];
|
|
87339
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
87340
|
+
return ar;
|
|
87341
|
+
};
|
|
87342
|
+
return ownKeys(o);
|
|
87343
|
+
};
|
|
87344
|
+
return function (mod) {
|
|
87345
|
+
if (mod && mod.__esModule) return mod;
|
|
87346
|
+
var result = {};
|
|
87347
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
87348
|
+
__setModuleDefault(result, mod);
|
|
87349
|
+
return result;
|
|
87350
|
+
};
|
|
87351
|
+
})();
|
|
87352
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
87353
|
+
exports.IssueFilter = void 0;
|
|
87354
|
+
const fs = __importStar(__nccwpck_require__(79896));
|
|
87355
|
+
const path = __importStar(__nccwpck_require__(16928));
|
|
87356
|
+
/**
|
|
87357
|
+
* Filter for suppressing Visor issues based on special comments in code
|
|
87358
|
+
*/
|
|
87359
|
+
class IssueFilter {
|
|
87360
|
+
fileCache = new Map();
|
|
87361
|
+
suppressionEnabled;
|
|
87362
|
+
constructor(suppressionEnabled = true) {
|
|
87363
|
+
this.suppressionEnabled = suppressionEnabled;
|
|
87364
|
+
}
|
|
87365
|
+
/**
|
|
87366
|
+
* Filter out issues that have suppression comments
|
|
87367
|
+
* @param issues Array of issues to filter
|
|
87368
|
+
* @param workingDir Working directory for resolving file paths
|
|
87369
|
+
* @returns Filtered array of issues with suppressed ones removed
|
|
87370
|
+
*/
|
|
87371
|
+
filterIssues(issues, workingDir = process.cwd()) {
|
|
87372
|
+
if (!this.suppressionEnabled || !issues || issues.length === 0) {
|
|
87373
|
+
return issues;
|
|
87374
|
+
}
|
|
87375
|
+
const filteredIssues = [];
|
|
87376
|
+
const suppressedCount = {};
|
|
87377
|
+
for (const issue of issues) {
|
|
87378
|
+
if (this.shouldSuppressIssue(issue, workingDir)) {
|
|
87379
|
+
// Track suppressed issues for logging
|
|
87380
|
+
suppressedCount[issue.file] = (suppressedCount[issue.file] || 0) + 1;
|
|
87381
|
+
}
|
|
87382
|
+
else {
|
|
87383
|
+
filteredIssues.push(issue);
|
|
87384
|
+
}
|
|
87385
|
+
}
|
|
87386
|
+
// Log suppression summary if any issues were suppressed
|
|
87387
|
+
const totalSuppressed = Object.values(suppressedCount).reduce((sum, count) => sum + count, 0);
|
|
87388
|
+
if (totalSuppressed > 0) {
|
|
87389
|
+
console.log(`🔇 Suppressed ${totalSuppressed} issue(s) via visor-disable comments:`);
|
|
87390
|
+
for (const [file, count] of Object.entries(suppressedCount)) {
|
|
87391
|
+
console.log(` - ${file}: ${count} issue(s)`);
|
|
87392
|
+
}
|
|
87393
|
+
}
|
|
87394
|
+
return filteredIssues;
|
|
87395
|
+
}
|
|
87396
|
+
/**
|
|
87397
|
+
* Check if an issue should be suppressed based on comments in the file
|
|
87398
|
+
*/
|
|
87399
|
+
shouldSuppressIssue(issue, workingDir) {
|
|
87400
|
+
// Skip system-level issues or issues without file/line info
|
|
87401
|
+
if (!issue.file || issue.file === 'system' || issue.file === 'webhook' || issue.line === 0) {
|
|
87402
|
+
return false;
|
|
87403
|
+
}
|
|
87404
|
+
const lines = this.getFileLines(issue.file, workingDir);
|
|
87405
|
+
if (!lines || lines.length === 0) {
|
|
87406
|
+
return false;
|
|
87407
|
+
}
|
|
87408
|
+
// Check for file-level suppression (visor-disable-file in first 5 lines)
|
|
87409
|
+
const firstFiveLines = lines.slice(0, 5).join('\n').toLowerCase();
|
|
87410
|
+
if (firstFiveLines.includes('visor-disable-file')) {
|
|
87411
|
+
return true;
|
|
87412
|
+
}
|
|
87413
|
+
// Check for line-level suppression (visor-disable within ±2 lines)
|
|
87414
|
+
const lineIndex = issue.line - 1; // Convert to 0-based index
|
|
87415
|
+
const startLine = Math.max(0, lineIndex - 2);
|
|
87416
|
+
const endLine = Math.min(lines.length - 1, lineIndex + 2);
|
|
87417
|
+
for (let i = startLine; i <= endLine; i++) {
|
|
87418
|
+
if (lines[i].toLowerCase().includes('visor-disable')) {
|
|
87419
|
+
return true;
|
|
87420
|
+
}
|
|
87421
|
+
}
|
|
87422
|
+
return false;
|
|
87423
|
+
}
|
|
87424
|
+
/**
|
|
87425
|
+
* Get file lines from cache or read from disk
|
|
87426
|
+
*/
|
|
87427
|
+
getFileLines(filePath, workingDir) {
|
|
87428
|
+
// Check cache first
|
|
87429
|
+
if (this.fileCache.has(filePath)) {
|
|
87430
|
+
return this.fileCache.get(filePath);
|
|
87431
|
+
}
|
|
87432
|
+
try {
|
|
87433
|
+
// Resolve the file path
|
|
87434
|
+
const resolvedPath = path.isAbsolute(filePath) ? filePath : path.join(workingDir, filePath);
|
|
87435
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
87436
|
+
// Try without working directory if the file doesn't exist
|
|
87437
|
+
if (fs.existsSync(filePath)) {
|
|
87438
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
87439
|
+
const lines = content.split('\n');
|
|
87440
|
+
this.fileCache.set(filePath, lines);
|
|
87441
|
+
return lines;
|
|
87442
|
+
}
|
|
87443
|
+
return null;
|
|
87444
|
+
}
|
|
87445
|
+
const content = fs.readFileSync(resolvedPath, 'utf8');
|
|
87446
|
+
const lines = content.split('\n');
|
|
87447
|
+
this.fileCache.set(filePath, lines);
|
|
87448
|
+
return lines;
|
|
87449
|
+
}
|
|
87450
|
+
catch {
|
|
87451
|
+
// Silently skip files that can't be read
|
|
87452
|
+
return null;
|
|
87453
|
+
}
|
|
87454
|
+
}
|
|
87455
|
+
/**
|
|
87456
|
+
* Clear the file cache (useful for testing or long-running processes)
|
|
87457
|
+
*/
|
|
87458
|
+
clearCache() {
|
|
87459
|
+
this.fileCache.clear();
|
|
87460
|
+
}
|
|
87461
|
+
}
|
|
87462
|
+
exports.IssueFilter = IssueFilter;
|
|
87463
|
+
|
|
87464
|
+
|
|
87097
87465
|
/***/ }),
|
|
87098
87466
|
|
|
87099
87467
|
/***/ 25508:
|
|
@@ -87840,6 +88208,17 @@ class PRAnalyzer {
|
|
|
87840
88208
|
fullDiff: this.generateFullDiff(validFiles),
|
|
87841
88209
|
eventType,
|
|
87842
88210
|
};
|
|
88211
|
+
// Fetch comment history for better context
|
|
88212
|
+
try {
|
|
88213
|
+
console.log(`💬 Fetching comment history for PR #${prInfo.number}`);
|
|
88214
|
+
const comments = await this.fetchPRComments(owner, repo, prInfo.number);
|
|
88215
|
+
prInfo.comments = comments;
|
|
88216
|
+
console.log(`✅ Retrieved ${comments.length} comments`);
|
|
88217
|
+
}
|
|
88218
|
+
catch (error) {
|
|
88219
|
+
console.warn(`⚠️ Could not fetch comments: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
88220
|
+
prInfo.comments = [];
|
|
88221
|
+
}
|
|
87843
88222
|
// Add commit diff for incremental analysis
|
|
87844
88223
|
if (commitSha) {
|
|
87845
88224
|
console.log(`🔧 Fetching incremental diff for commit: ${commitSha}`);
|
|
@@ -87942,6 +88321,7 @@ exports.AICheckProvider = void 0;
|
|
|
87942
88321
|
const check_provider_interface_1 = __nccwpck_require__(14131);
|
|
87943
88322
|
const ai_review_service_1 = __nccwpck_require__(51796);
|
|
87944
88323
|
const env_resolver_1 = __nccwpck_require__(58749);
|
|
88324
|
+
const issue_filter_1 = __nccwpck_require__(36879);
|
|
87945
88325
|
const liquidjs_1 = __nccwpck_require__(48694);
|
|
87946
88326
|
const promises_1 = __importDefault(__nccwpck_require__(91943));
|
|
87947
88327
|
const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
@@ -88311,15 +88691,24 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
|
|
|
88311
88691
|
console.error(`🔧 Debug: AICheckProvider full config: ${JSON.stringify(config, null, 2)}`);
|
|
88312
88692
|
try {
|
|
88313
88693
|
console.error(`🔧 Debug: AICheckProvider passing checkName: ${config.checkName} to service`);
|
|
88694
|
+
let result;
|
|
88314
88695
|
// Check if we should use session reuse
|
|
88315
88696
|
if (sessionInfo?.reuseSession && sessionInfo.parentSessionId) {
|
|
88316
88697
|
console.error(`🔄 Debug: Using session reuse with parent session: ${sessionInfo.parentSessionId}`);
|
|
88317
|
-
|
|
88698
|
+
result = await service.executeReviewWithSessionReuse(prInfo, processedPrompt, sessionInfo.parentSessionId, schema, config.checkName);
|
|
88318
88699
|
}
|
|
88319
88700
|
else {
|
|
88320
88701
|
console.error(`🆕 Debug: Creating new AI session for check: ${config.checkName}`);
|
|
88321
|
-
|
|
88702
|
+
result = await service.executeReview(prInfo, processedPrompt, schema, config.checkName, config.sessionId);
|
|
88322
88703
|
}
|
|
88704
|
+
// Apply issue suppression filtering
|
|
88705
|
+
const suppressionEnabled = config.suppressionEnabled !== false;
|
|
88706
|
+
const issueFilter = new issue_filter_1.IssueFilter(suppressionEnabled);
|
|
88707
|
+
const filteredIssues = issueFilter.filterIssues(result.issues || [], process.cwd());
|
|
88708
|
+
return {
|
|
88709
|
+
...result,
|
|
88710
|
+
issues: filteredIssues,
|
|
88711
|
+
};
|
|
88323
88712
|
}
|
|
88324
88713
|
catch (error) {
|
|
88325
88714
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -88607,6 +88996,7 @@ exports.NoopCheckProvider = NoopCheckProvider;
|
|
|
88607
88996
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
88608
88997
|
exports.ToolCheckProvider = void 0;
|
|
88609
88998
|
const check_provider_interface_1 = __nccwpck_require__(14131);
|
|
88999
|
+
const issue_filter_1 = __nccwpck_require__(36879);
|
|
88610
89000
|
const child_process_1 = __nccwpck_require__(35317);
|
|
88611
89001
|
const liquidjs_1 = __nccwpck_require__(48694);
|
|
88612
89002
|
/**
|
|
@@ -88692,8 +89082,12 @@ class ToolCheckProvider extends check_provider_interface_1.CheckProvider {
|
|
|
88692
89082
|
suggestion: undefined,
|
|
88693
89083
|
replacement: undefined,
|
|
88694
89084
|
}));
|
|
89085
|
+
// Apply issue suppression filtering
|
|
89086
|
+
const suppressionEnabled = config.suppressionEnabled !== false;
|
|
89087
|
+
const issueFilter = new issue_filter_1.IssueFilter(suppressionEnabled);
|
|
89088
|
+
const filteredIssues = issueFilter.filterIssues(issues, process.cwd());
|
|
88695
89089
|
return {
|
|
88696
|
-
issues,
|
|
89090
|
+
issues: filteredIssues,
|
|
88697
89091
|
suggestions: this.generateSuggestions(comments, renderedCommand),
|
|
88698
89092
|
};
|
|
88699
89093
|
}
|
|
@@ -88788,6 +89182,7 @@ exports.ToolCheckProvider = ToolCheckProvider;
|
|
|
88788
89182
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
88789
89183
|
exports.WebhookCheckProvider = void 0;
|
|
88790
89184
|
const check_provider_interface_1 = __nccwpck_require__(14131);
|
|
89185
|
+
const issue_filter_1 = __nccwpck_require__(36879);
|
|
88791
89186
|
/**
|
|
88792
89187
|
* Check provider that sends PR info to a webhook for external analysis
|
|
88793
89188
|
*/
|
|
@@ -88848,7 +89243,15 @@ class WebhookCheckProvider extends check_provider_interface_1.CheckProvider {
|
|
|
88848
89243
|
// Send webhook request
|
|
88849
89244
|
const response = await this.sendWebhookRequest(url, method, headers, payload, timeout);
|
|
88850
89245
|
// Parse webhook response
|
|
88851
|
-
|
|
89246
|
+
const result = this.parseWebhookResponse(response, url);
|
|
89247
|
+
// Apply issue suppression filtering
|
|
89248
|
+
const suppressionEnabled = config.suppressionEnabled !== false;
|
|
89249
|
+
const issueFilter = new issue_filter_1.IssueFilter(suppressionEnabled);
|
|
89250
|
+
const filteredIssues = issueFilter.filterIssues(result.issues || [], process.cwd());
|
|
89251
|
+
return {
|
|
89252
|
+
...result,
|
|
89253
|
+
issues: filteredIssues,
|
|
89254
|
+
};
|
|
88852
89255
|
}
|
|
88853
89256
|
catch (error) {
|
|
88854
89257
|
return this.createErrorResult(url, error);
|
|
@@ -89088,9 +89491,19 @@ class PRReviewer {
|
|
|
89088
89491
|
prNumber,
|
|
89089
89492
|
commitSha: options.commitSha,
|
|
89090
89493
|
});
|
|
89091
|
-
|
|
89092
|
-
|
|
89093
|
-
|
|
89494
|
+
// Generate comment ID - use unique ID for "dynamic" group
|
|
89495
|
+
let commentId;
|
|
89496
|
+
if (groupName === 'dynamic') {
|
|
89497
|
+
// Dynamic group creates a new comment each time with timestamp-based ID
|
|
89498
|
+
const timestamp = Date.now();
|
|
89499
|
+
commentId = `visor-dynamic-${timestamp}`;
|
|
89500
|
+
}
|
|
89501
|
+
else {
|
|
89502
|
+
// Regular groups use static IDs that get updated
|
|
89503
|
+
commentId = options.commentId
|
|
89504
|
+
? `${options.commentId}-${groupName}`
|
|
89505
|
+
: `visor-review-${groupName}`;
|
|
89506
|
+
}
|
|
89094
89507
|
await this.commentManager.updateOrCreateComment(owner, repo, prNumber, comment, {
|
|
89095
89508
|
commentId,
|
|
89096
89509
|
triggeredBy: options.triggeredBy || 'unknown',
|
|
@@ -89536,15 +89949,31 @@ class ConfigLoader {
|
|
|
89536
89949
|
* Load bundled default configuration
|
|
89537
89950
|
*/
|
|
89538
89951
|
async fetchDefaultConfig() {
|
|
89539
|
-
//
|
|
89540
|
-
|
|
89541
|
-
|
|
89542
|
-
|
|
89543
|
-
|
|
89544
|
-
|
|
89545
|
-
|
|
89546
|
-
|
|
89547
|
-
|
|
89952
|
+
// Try different paths to find the bundled default config
|
|
89953
|
+
const possiblePaths = [
|
|
89954
|
+
// When running as GitHub Action (bundled in dist/)
|
|
89955
|
+
path.join(__dirname, 'defaults', '.visor.yaml'),
|
|
89956
|
+
// When running from source
|
|
89957
|
+
path.join(__dirname, '..', '..', 'defaults', '.visor.yaml'),
|
|
89958
|
+
// Try via package root
|
|
89959
|
+
this.findPackageRoot() ? path.join(this.findPackageRoot(), 'defaults', '.visor.yaml') : '',
|
|
89960
|
+
// GitHub Action environment variable
|
|
89961
|
+
process.env.GITHUB_ACTION_PATH
|
|
89962
|
+
? path.join(process.env.GITHUB_ACTION_PATH, 'defaults', '.visor.yaml')
|
|
89963
|
+
: '',
|
|
89964
|
+
process.env.GITHUB_ACTION_PATH
|
|
89965
|
+
? path.join(process.env.GITHUB_ACTION_PATH, 'dist', 'defaults', '.visor.yaml')
|
|
89966
|
+
: '',
|
|
89967
|
+
].filter(p => p); // Remove empty paths
|
|
89968
|
+
let defaultConfigPath;
|
|
89969
|
+
for (const possiblePath of possiblePaths) {
|
|
89970
|
+
if (fs.existsSync(possiblePath)) {
|
|
89971
|
+
defaultConfigPath = possiblePath;
|
|
89972
|
+
break;
|
|
89973
|
+
}
|
|
89974
|
+
}
|
|
89975
|
+
if (defaultConfigPath && fs.existsSync(defaultConfigPath)) {
|
|
89976
|
+
console.log(`📦 Loading bundled default configuration from ${defaultConfigPath}`);
|
|
89548
89977
|
const content = fs.readFileSync(defaultConfigPath, 'utf8');
|
|
89549
89978
|
const config = yaml.load(content);
|
|
89550
89979
|
if (!config || typeof config !== 'object') {
|
|
@@ -110291,6 +110720,103 @@ ${decodedContent}
|
|
|
110291
110720
|
};
|
|
110292
110721
|
}
|
|
110293
110722
|
}
|
|
110723
|
+
let proactiveFixesApplied = false;
|
|
110724
|
+
const { diagrams: currentDiagrams } = extractMermaidFromMarkdown(fixedResponse);
|
|
110725
|
+
for (let diagramIndex = currentDiagrams.length - 1; diagramIndex >= 0; diagramIndex--) {
|
|
110726
|
+
const diagram = currentDiagrams[diagramIndex];
|
|
110727
|
+
const originalContent = diagram.content;
|
|
110728
|
+
const lines = originalContent.split("\n");
|
|
110729
|
+
let wasFixed = false;
|
|
110730
|
+
const fixedLines = lines.map((line) => {
|
|
110731
|
+
const trimmedLine = line.trim();
|
|
110732
|
+
let modifiedLine = line;
|
|
110733
|
+
if (trimmedLine.match(/\[[^\]]*\]/)) {
|
|
110734
|
+
modifiedLine = modifiedLine.replace(/\[([^\]]*)\]/g, (match, content) => {
|
|
110735
|
+
if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
|
|
110736
|
+
return match;
|
|
110737
|
+
}
|
|
110738
|
+
const needsQuoting = /[()'"<>&]/.test(content) || // Core problematic characters
|
|
110739
|
+
content.includes("e.g.") || content.includes("i.e.") || content.includes("src/") || content.includes("defaults/") || content.includes(".ts") || content.includes(".js") || content.includes(".yaml") || content.includes(".json") || content.includes(".md") || content.includes(".html") || content.includes(".css");
|
|
110740
|
+
if (needsQuoting) {
|
|
110741
|
+
wasFixed = true;
|
|
110742
|
+
const safeContent = content.replace(/"/g, "'");
|
|
110743
|
+
return `["${safeContent}"]`;
|
|
110744
|
+
}
|
|
110745
|
+
return match;
|
|
110746
|
+
});
|
|
110747
|
+
}
|
|
110748
|
+
if (trimmedLine.match(/\{[^{}]*\}/)) {
|
|
110749
|
+
modifiedLine = modifiedLine.replace(/\{([^{}]*)\}/g, (match, content) => {
|
|
110750
|
+
if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
|
|
110751
|
+
return match;
|
|
110752
|
+
}
|
|
110753
|
+
const needsQuoting = /[()'"<>&]/.test(content) || // Core problematic characters
|
|
110754
|
+
content.includes("e.g.") || content.includes("i.e.") || content.includes("src/") || content.includes("defaults/") || content.includes(".ts") || content.includes(".js") || content.includes(".yaml") || content.includes(".json") || content.includes(".md") || content.includes(".html") || content.includes(".css");
|
|
110755
|
+
if (needsQuoting) {
|
|
110756
|
+
wasFixed = true;
|
|
110757
|
+
const safeContent = content.replace(/"/g, "'");
|
|
110758
|
+
return `{"${safeContent}"}`;
|
|
110759
|
+
}
|
|
110760
|
+
return match;
|
|
110761
|
+
});
|
|
110762
|
+
}
|
|
110763
|
+
return modifiedLine;
|
|
110764
|
+
});
|
|
110765
|
+
if (wasFixed) {
|
|
110766
|
+
const fixedContent = fixedLines.join("\n");
|
|
110767
|
+
const attributesStr = diagram.attributes ? ` ${diagram.attributes}` : "";
|
|
110768
|
+
const newCodeBlock = `\`\`\`mermaid${attributesStr}
|
|
110769
|
+
${fixedContent}
|
|
110770
|
+
\`\`\``;
|
|
110771
|
+
fixedResponse = fixedResponse.slice(0, diagram.startIndex) + newCodeBlock + fixedResponse.slice(diagram.endIndex);
|
|
110772
|
+
fixingResults.push({
|
|
110773
|
+
diagramIndex,
|
|
110774
|
+
wasFixed: true,
|
|
110775
|
+
originalContent,
|
|
110776
|
+
fixedContent,
|
|
110777
|
+
originalError: "Proactive node label quoting",
|
|
110778
|
+
fixMethod: "node_label_quote_wrapping",
|
|
110779
|
+
fixedWithProactiveQuoting: true
|
|
110780
|
+
});
|
|
110781
|
+
proactiveFixesApplied = true;
|
|
110782
|
+
if (debug) {
|
|
110783
|
+
console.log(`[DEBUG] Mermaid validation: Proactively fixed diagram ${diagramIndex + 1} with node label quoting`);
|
|
110784
|
+
console.log(`[DEBUG] Mermaid validation: Applied automatic quoting to special characters`);
|
|
110785
|
+
}
|
|
110786
|
+
}
|
|
110787
|
+
}
|
|
110788
|
+
if (proactiveFixesApplied) {
|
|
110789
|
+
const revalidation = await validateMermaidResponse(fixedResponse);
|
|
110790
|
+
if (revalidation.isValid) {
|
|
110791
|
+
const totalTime2 = Date.now() - startTime;
|
|
110792
|
+
if (debug) {
|
|
110793
|
+
console.log(`[DEBUG] Mermaid validation: All diagrams fixed with proactive quoting in ${totalTime2}ms, no AI needed`);
|
|
110794
|
+
console.log(`[DEBUG] Mermaid validation: Applied ${fixingResults.length} proactive fixes`);
|
|
110795
|
+
}
|
|
110796
|
+
if (tracer) {
|
|
110797
|
+
tracer.recordMermaidValidationEvent("proactive_fix_completed", {
|
|
110798
|
+
"mermaid_validation.success": true,
|
|
110799
|
+
"mermaid_validation.fix_method": "node_label_quote_wrapping",
|
|
110800
|
+
"mermaid_validation.diagrams_fixed": fixingResults.length,
|
|
110801
|
+
"mermaid_validation.duration_ms": totalTime2
|
|
110802
|
+
});
|
|
110803
|
+
}
|
|
110804
|
+
return {
|
|
110805
|
+
...revalidation,
|
|
110806
|
+
wasFixed: true,
|
|
110807
|
+
originalResponse: response,
|
|
110808
|
+
fixedResponse,
|
|
110809
|
+
fixingResults,
|
|
110810
|
+
performanceMetrics: {
|
|
110811
|
+
totalTimeMs: totalTime2,
|
|
110812
|
+
aiFixingTimeMs: 0,
|
|
110813
|
+
finalValidationTimeMs: 0,
|
|
110814
|
+
diagramsProcessed: fixingResults.length,
|
|
110815
|
+
diagramsFixed: fixingResults.length
|
|
110816
|
+
}
|
|
110817
|
+
};
|
|
110818
|
+
}
|
|
110819
|
+
}
|
|
110294
110820
|
let subgraphFixesApplied = false;
|
|
110295
110821
|
const { diagrams: postHtmlDiagrams } = extractMermaidFromMarkdown(fixedResponse);
|
|
110296
110822
|
const postHtmlValidation = await validateMermaidResponse(fixedResponse);
|
|
@@ -110384,16 +110910,21 @@ ${fixedContent}
|
|
|
110384
110910
|
const postSubgraphValidation = await validateMermaidResponse(fixedResponse);
|
|
110385
110911
|
const stillInvalidAfterSubgraph = postSubgraphValidation.diagrams.map((result, index) => ({ ...result, originalIndex: index })).filter((result) => !result.isValid).reverse();
|
|
110386
110912
|
for (const invalidDiagram of stillInvalidAfterSubgraph) {
|
|
110387
|
-
if (invalidDiagram.error && (invalidDiagram.error.includes("Parentheses in node label") || invalidDiagram.error.includes("Complex expression in diamond node"))) {
|
|
110913
|
+
if (invalidDiagram.error && (invalidDiagram.error.includes("Parentheses in node label") || invalidDiagram.error.includes("Complex expression in diamond node") || invalidDiagram.error.includes("Single quotes in node label"))) {
|
|
110388
110914
|
const originalContent = invalidDiagram.content;
|
|
110389
110915
|
const lines = originalContent.split("\n");
|
|
110390
110916
|
let wasFixed = false;
|
|
110391
110917
|
const fixedLines = lines.map((line) => {
|
|
110392
110918
|
const trimmedLine = line.trim();
|
|
110393
110919
|
let modifiedLine = line;
|
|
110394
|
-
if (trimmedLine.match(/\[[^\]
|
|
110395
|
-
modifiedLine = modifiedLine.replace(/\[([^\]
|
|
110396
|
-
if (
|
|
110920
|
+
if (trimmedLine.match(/\[[^\]]*\]/)) {
|
|
110921
|
+
modifiedLine = modifiedLine.replace(/\[([^\]]*)\]/g, (match, content) => {
|
|
110922
|
+
if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
|
|
110923
|
+
return match;
|
|
110924
|
+
}
|
|
110925
|
+
const needsQuoting = /[()'"<>&]/.test(content) || // Core problematic characters
|
|
110926
|
+
content.includes("e.g.") || content.includes("i.e.") || content.includes("src/") || content.includes("defaults/") || content.includes(".ts") || content.includes(".js") || content.includes(".yaml") || content.includes(".json");
|
|
110927
|
+
if (needsQuoting) {
|
|
110397
110928
|
wasFixed = true;
|
|
110398
110929
|
const safeContent = content.replace(/"/g, "'");
|
|
110399
110930
|
return `["${safeContent}"]`;
|
|
@@ -110401,9 +110932,14 @@ ${fixedContent}
|
|
|
110401
110932
|
return match;
|
|
110402
110933
|
});
|
|
110403
110934
|
}
|
|
110404
|
-
if (trimmedLine.match(/\{[^{}
|
|
110405
|
-
modifiedLine = modifiedLine.replace(/\{([^{}
|
|
110406
|
-
if (
|
|
110935
|
+
if (trimmedLine.match(/\{[^{}]*\}/)) {
|
|
110936
|
+
modifiedLine = modifiedLine.replace(/\{([^{}]*)\}/g, (match, content) => {
|
|
110937
|
+
if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
|
|
110938
|
+
return match;
|
|
110939
|
+
}
|
|
110940
|
+
const needsQuoting = /[()'"<>&]/.test(content) || // Core problematic characters
|
|
110941
|
+
content.includes("e.g.") || content.includes("i.e.") || content.includes("src/") || content.includes("defaults/") || content.includes(".ts") || content.includes(".js") || content.includes(".yaml") || content.includes(".json");
|
|
110942
|
+
if (needsQuoting) {
|
|
110407
110943
|
wasFixed = true;
|
|
110408
110944
|
const safeContent = content.replace(/"/g, "'");
|
|
110409
110945
|
return `{"${safeContent}"}`;
|
|
@@ -110837,6 +111373,7 @@ var init_ProbeAgent = __esm({
|
|
|
110837
111373
|
* @param {boolean} [options.debug] - Enable debug mode
|
|
110838
111374
|
* @param {boolean} [options.outline] - Enable outline-xml format for search results
|
|
110839
111375
|
* @param {number} [options.maxResponseTokens] - Maximum tokens for AI responses
|
|
111376
|
+
* @param {boolean} [options.disableMermaidValidation=false] - Disable automatic mermaid diagram validation and fixing
|
|
110840
111377
|
*/
|
|
110841
111378
|
constructor(options = {}) {
|
|
110842
111379
|
this.sessionId = options.sessionId || (0, import_crypto5.randomUUID)();
|
|
@@ -110848,6 +111385,7 @@ var init_ProbeAgent = __esm({
|
|
|
110848
111385
|
this.tracer = options.tracer || null;
|
|
110849
111386
|
this.outline = !!options.outline;
|
|
110850
111387
|
this.maxResponseTokens = options.maxResponseTokens || parseInt(process.env.MAX_RESPONSE_TOKENS || "0", 10) || null;
|
|
111388
|
+
this.disableMermaidValidation = !!options.disableMermaidValidation;
|
|
110851
111389
|
this.allowedFolders = options.path ? [options.path] : [process.cwd()];
|
|
110852
111390
|
this.clientApiProvider = options.provider || null;
|
|
110853
111391
|
this.clientApiKey = null;
|
|
@@ -111541,56 +112079,60 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
111541
112079
|
_schemaFormatted: true
|
|
111542
112080
|
});
|
|
111543
112081
|
finalResult = cleanSchemaResponse(finalResult);
|
|
111544
|
-
|
|
111545
|
-
|
|
111546
|
-
console.log(`[DEBUG] Mermaid validation: Starting enhanced mermaid validation...`);
|
|
111547
|
-
}
|
|
111548
|
-
if (this.tracer) {
|
|
111549
|
-
this.tracer.recordMermaidValidationEvent("schema_processing_started", {
|
|
111550
|
-
"mermaid_validation.context": "schema_processing",
|
|
111551
|
-
"mermaid_validation.response_length": finalResult.length
|
|
111552
|
-
});
|
|
111553
|
-
}
|
|
111554
|
-
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
111555
|
-
debug: this.debug,
|
|
111556
|
-
path: this.allowedFolders[0],
|
|
111557
|
-
provider: this.clientApiProvider,
|
|
111558
|
-
model: this.model,
|
|
111559
|
-
tracer: this.tracer
|
|
111560
|
-
});
|
|
111561
|
-
if (mermaidValidation.wasFixed) {
|
|
111562
|
-
finalResult = mermaidValidation.fixedResponse;
|
|
112082
|
+
if (!this.disableMermaidValidation) {
|
|
112083
|
+
try {
|
|
111563
112084
|
if (this.debug) {
|
|
111564
|
-
console.log(`[DEBUG] Mermaid validation:
|
|
111565
|
-
|
|
111566
|
-
|
|
111567
|
-
|
|
111568
|
-
|
|
112085
|
+
console.log(`[DEBUG] Mermaid validation: Starting enhanced mermaid validation...`);
|
|
112086
|
+
}
|
|
112087
|
+
if (this.tracer) {
|
|
112088
|
+
this.tracer.recordMermaidValidationEvent("schema_processing_started", {
|
|
112089
|
+
"mermaid_validation.context": "schema_processing",
|
|
112090
|
+
"mermaid_validation.response_length": finalResult.length
|
|
112091
|
+
});
|
|
112092
|
+
}
|
|
112093
|
+
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
112094
|
+
debug: this.debug,
|
|
112095
|
+
path: this.allowedFolders[0],
|
|
112096
|
+
provider: this.clientApiProvider,
|
|
112097
|
+
model: this.model,
|
|
112098
|
+
tracer: this.tracer
|
|
112099
|
+
});
|
|
112100
|
+
if (mermaidValidation.wasFixed) {
|
|
112101
|
+
finalResult = mermaidValidation.fixedResponse;
|
|
112102
|
+
if (this.debug) {
|
|
112103
|
+
console.log(`[DEBUG] Mermaid validation: Diagrams successfully fixed`);
|
|
112104
|
+
if (mermaidValidation.performanceMetrics) {
|
|
112105
|
+
const metrics = mermaidValidation.performanceMetrics;
|
|
112106
|
+
console.log(`[DEBUG] Mermaid validation: Performance - total: ${metrics.totalTimeMs}ms, AI fixing: ${metrics.aiFixingTimeMs}ms`);
|
|
112107
|
+
console.log(`[DEBUG] Mermaid validation: Results - ${metrics.diagramsFixed}/${metrics.diagramsProcessed} diagrams fixed`);
|
|
112108
|
+
}
|
|
112109
|
+
if (mermaidValidation.fixingResults) {
|
|
112110
|
+
mermaidValidation.fixingResults.forEach((fixResult, index) => {
|
|
112111
|
+
if (fixResult.wasFixed) {
|
|
112112
|
+
const method = fixResult.fixedWithHtmlDecoding ? "HTML entity decoding" : "AI correction";
|
|
112113
|
+
const time = fixResult.aiFixingTimeMs ? ` in ${fixResult.aiFixingTimeMs}ms` : "";
|
|
112114
|
+
console.log(`[DEBUG] Mermaid validation: Fixed diagram ${fixResult.diagramIndex + 1} with ${method}${time}`);
|
|
112115
|
+
console.log(`[DEBUG] Mermaid validation: Original error: ${fixResult.originalError}`);
|
|
112116
|
+
} else {
|
|
112117
|
+
console.log(`[DEBUG] Mermaid validation: Failed to fix diagram ${fixResult.diagramIndex + 1}: ${fixResult.fixingError}`);
|
|
112118
|
+
}
|
|
112119
|
+
});
|
|
112120
|
+
}
|
|
111569
112121
|
}
|
|
111570
|
-
|
|
111571
|
-
|
|
111572
|
-
|
|
111573
|
-
|
|
111574
|
-
const time = fixResult.aiFixingTimeMs ? ` in ${fixResult.aiFixingTimeMs}ms` : "";
|
|
111575
|
-
console.log(`[DEBUG] Mermaid validation: Fixed diagram ${fixResult.diagramIndex + 1} with ${method}${time}`);
|
|
111576
|
-
console.log(`[DEBUG] Mermaid validation: Original error: ${fixResult.originalError}`);
|
|
111577
|
-
} else {
|
|
111578
|
-
console.log(`[DEBUG] Mermaid validation: Failed to fix diagram ${fixResult.diagramIndex + 1}: ${fixResult.fixingError}`);
|
|
111579
|
-
}
|
|
111580
|
-
});
|
|
112122
|
+
} else if (this.debug) {
|
|
112123
|
+
console.log(`[DEBUG] Mermaid validation: No fixes needed or fixes unsuccessful`);
|
|
112124
|
+
if (mermaidValidation.diagrams?.length > 0) {
|
|
112125
|
+
console.log(`[DEBUG] Mermaid validation: Found ${mermaidValidation.diagrams.length} diagrams, all valid: ${mermaidValidation.isValid}`);
|
|
111581
112126
|
}
|
|
111582
112127
|
}
|
|
111583
|
-
}
|
|
111584
|
-
|
|
111585
|
-
|
|
111586
|
-
console.log(`[DEBUG] Mermaid validation:
|
|
112128
|
+
} catch (error) {
|
|
112129
|
+
if (this.debug) {
|
|
112130
|
+
console.log(`[DEBUG] Mermaid validation: Process failed with error: ${error.message}`);
|
|
112131
|
+
console.log(`[DEBUG] Mermaid validation: Stack trace: ${error.stack}`);
|
|
111587
112132
|
}
|
|
111588
112133
|
}
|
|
111589
|
-
}
|
|
111590
|
-
|
|
111591
|
-
console.log(`[DEBUG] Mermaid validation: Process failed with error: ${error.message}`);
|
|
111592
|
-
console.log(`[DEBUG] Mermaid validation: Stack trace: ${error.stack}`);
|
|
111593
|
-
}
|
|
112134
|
+
} else if (this.debug) {
|
|
112135
|
+
console.log(`[DEBUG] Mermaid validation: Skipped due to disableMermaidValidation option`);
|
|
111594
112136
|
}
|
|
111595
112137
|
if (isJsonSchema(options.schema)) {
|
|
111596
112138
|
if (this.debug) {
|
|
@@ -111695,26 +112237,30 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
111695
112237
|
} else if (completionAttempted && options.schema) {
|
|
111696
112238
|
try {
|
|
111697
112239
|
finalResult = cleanSchemaResponse(finalResult);
|
|
111698
|
-
if (this.
|
|
111699
|
-
console.log(`[DEBUG] Mermaid validation: Validating attempt_completion result...`);
|
|
111700
|
-
}
|
|
111701
|
-
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
111702
|
-
debug: this.debug,
|
|
111703
|
-
path: this.allowedFolders[0],
|
|
111704
|
-
provider: this.clientApiProvider,
|
|
111705
|
-
model: this.model,
|
|
111706
|
-
tracer: this.tracer
|
|
111707
|
-
});
|
|
111708
|
-
if (mermaidValidation.wasFixed) {
|
|
111709
|
-
finalResult = mermaidValidation.fixedResponse;
|
|
112240
|
+
if (!this.disableMermaidValidation) {
|
|
111710
112241
|
if (this.debug) {
|
|
111711
|
-
console.log(`[DEBUG] Mermaid validation: attempt_completion
|
|
111712
|
-
|
|
111713
|
-
|
|
112242
|
+
console.log(`[DEBUG] Mermaid validation: Validating attempt_completion result...`);
|
|
112243
|
+
}
|
|
112244
|
+
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
112245
|
+
debug: this.debug,
|
|
112246
|
+
path: this.allowedFolders[0],
|
|
112247
|
+
provider: this.clientApiProvider,
|
|
112248
|
+
model: this.model,
|
|
112249
|
+
tracer: this.tracer
|
|
112250
|
+
});
|
|
112251
|
+
if (mermaidValidation.wasFixed) {
|
|
112252
|
+
finalResult = mermaidValidation.fixedResponse;
|
|
112253
|
+
if (this.debug) {
|
|
112254
|
+
console.log(`[DEBUG] Mermaid validation: attempt_completion diagrams fixed`);
|
|
112255
|
+
if (mermaidValidation.performanceMetrics) {
|
|
112256
|
+
console.log(`[DEBUG] Mermaid validation: Fixed in ${mermaidValidation.performanceMetrics.totalTimeMs}ms`);
|
|
112257
|
+
}
|
|
111714
112258
|
}
|
|
112259
|
+
} else if (this.debug) {
|
|
112260
|
+
console.log(`[DEBUG] Mermaid validation: attempt_completion result validation completed (no fixes needed)`);
|
|
111715
112261
|
}
|
|
111716
112262
|
} else if (this.debug) {
|
|
111717
|
-
console.log(`[DEBUG] Mermaid validation: attempt_completion result
|
|
112263
|
+
console.log(`[DEBUG] Mermaid validation: Skipped for attempt_completion result due to disableMermaidValidation option`);
|
|
111718
112264
|
}
|
|
111719
112265
|
if (isJsonSchema(options.schema)) {
|
|
111720
112266
|
if (this.debug) {
|