@juspay/yama 1.6.0 → 2.0.0
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/.mcp-config.example.json +26 -0
- package/CHANGELOG.md +34 -0
- package/README.md +311 -685
- package/dist/cli/v2.cli.d.ts +13 -0
- package/dist/cli/v2.cli.js +290 -0
- package/dist/index.d.ts +12 -13
- package/dist/index.js +18 -19
- package/dist/v2/config/ConfigLoader.d.ts +50 -0
- package/dist/v2/config/ConfigLoader.js +205 -0
- package/dist/v2/config/DefaultConfig.d.ts +9 -0
- package/dist/v2/config/DefaultConfig.js +191 -0
- package/dist/v2/core/MCPServerManager.d.ts +22 -0
- package/dist/v2/core/MCPServerManager.js +92 -0
- package/dist/v2/core/SessionManager.d.ts +72 -0
- package/dist/v2/core/SessionManager.js +200 -0
- package/dist/v2/core/YamaV2Orchestrator.d.ts +112 -0
- package/dist/v2/core/YamaV2Orchestrator.js +549 -0
- package/dist/v2/prompts/EnhancementSystemPrompt.d.ts +8 -0
- package/dist/v2/prompts/EnhancementSystemPrompt.js +216 -0
- package/dist/v2/prompts/PromptBuilder.d.ts +38 -0
- package/dist/v2/prompts/PromptBuilder.js +228 -0
- package/dist/v2/prompts/ReviewSystemPrompt.d.ts +8 -0
- package/dist/v2/prompts/ReviewSystemPrompt.js +270 -0
- package/dist/v2/types/config.types.d.ts +120 -0
- package/dist/v2/types/config.types.js +5 -0
- package/dist/v2/types/mcp.types.d.ts +191 -0
- package/dist/v2/types/mcp.types.js +6 -0
- package/dist/v2/types/v2.types.d.ts +182 -0
- package/dist/v2/types/v2.types.js +42 -0
- package/dist/v2/utils/ObservabilityConfig.d.ts +22 -0
- package/dist/v2/utils/ObservabilityConfig.js +48 -0
- package/package.json +11 -9
- package/yama.config.example.yaml +214 -204
- package/dist/cli/index.d.ts +0 -12
- package/dist/cli/index.js +0 -538
- package/dist/core/ContextGatherer.d.ts +0 -110
- package/dist/core/ContextGatherer.js +0 -470
- package/dist/core/Guardian.d.ts +0 -81
- package/dist/core/Guardian.js +0 -480
- package/dist/core/providers/BitbucketProvider.d.ts +0 -105
- package/dist/core/providers/BitbucketProvider.js +0 -489
- package/dist/features/CodeReviewer.d.ts +0 -173
- package/dist/features/CodeReviewer.js +0 -1707
- package/dist/features/DescriptionEnhancer.d.ts +0 -70
- package/dist/features/DescriptionEnhancer.js +0 -511
- package/dist/features/MultiInstanceProcessor.d.ts +0 -74
- package/dist/features/MultiInstanceProcessor.js +0 -360
- package/dist/types/index.d.ts +0 -624
- package/dist/types/index.js +0 -104
- package/dist/utils/Cache.d.ts +0 -103
- package/dist/utils/Cache.js +0 -444
- package/dist/utils/ConfigManager.d.ts +0 -88
- package/dist/utils/ConfigManager.js +0 -602
- package/dist/utils/ContentSimilarityService.d.ts +0 -74
- package/dist/utils/ContentSimilarityService.js +0 -215
- package/dist/utils/ExactDuplicateRemover.d.ts +0 -77
- package/dist/utils/ExactDuplicateRemover.js +0 -361
- package/dist/utils/Logger.d.ts +0 -31
- package/dist/utils/Logger.js +0 -214
- package/dist/utils/MemoryBankManager.d.ts +0 -73
- package/dist/utils/MemoryBankManager.js +0 -310
- package/dist/utils/ParallelProcessing.d.ts +0 -140
- package/dist/utils/ParallelProcessing.js +0 -333
- package/dist/utils/ProviderLimits.d.ts +0 -58
- package/dist/utils/ProviderLimits.js +0 -143
- package/dist/utils/RetryManager.d.ts +0 -78
- package/dist/utils/RetryManager.js +0 -205
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enhanced Description Enhancer - Optimized to work with Unified Context
|
|
3
|
-
* Preserves all original functionality from pr-describe.js but optimized
|
|
4
|
-
*/
|
|
5
|
-
import { EnhancementOptions, EnhancementResult, AIProviderConfig, DescriptionEnhancementConfig } from "../types/index.js";
|
|
6
|
-
import { UnifiedContext } from "../core/ContextGatherer.js";
|
|
7
|
-
import { BitbucketProvider } from "../core/providers/BitbucketProvider.js";
|
|
8
|
-
export declare class DescriptionEnhancer {
|
|
9
|
-
private neurolink;
|
|
10
|
-
private bitbucketProvider;
|
|
11
|
-
private aiConfig;
|
|
12
|
-
private enhancementConfig;
|
|
13
|
-
private defaultRequiredSections;
|
|
14
|
-
constructor(bitbucketProvider: BitbucketProvider, aiConfig: AIProviderConfig, enhancementConfig: DescriptionEnhancementConfig);
|
|
15
|
-
/**
|
|
16
|
-
* Get system prompt for description enhancement
|
|
17
|
-
* Uses config.systemPrompt if provided, otherwise uses default
|
|
18
|
-
*/
|
|
19
|
-
private getSystemPrompt;
|
|
20
|
-
/**
|
|
21
|
-
* Enhance description using pre-gathered unified context (OPTIMIZED)
|
|
22
|
-
*/
|
|
23
|
-
enhanceWithContext(context: UnifiedContext, options: EnhancementOptions): Promise<EnhancementResult>;
|
|
24
|
-
/**
|
|
25
|
-
* Analyze existing PR description content
|
|
26
|
-
*/
|
|
27
|
-
private analyzeExistingContent;
|
|
28
|
-
/**
|
|
29
|
-
* Extract preservable content (media, files, links)
|
|
30
|
-
*/
|
|
31
|
-
private extractPreservableContent;
|
|
32
|
-
/**
|
|
33
|
-
* Validate presence of required sections
|
|
34
|
-
*/
|
|
35
|
-
private validateRequiredSections;
|
|
36
|
-
/**
|
|
37
|
-
* Extract content for a specific section
|
|
38
|
-
*/
|
|
39
|
-
private extractSectionContent;
|
|
40
|
-
/**
|
|
41
|
-
* Identify content gaps (TODOs, unanswered questions, etc.)
|
|
42
|
-
*/
|
|
43
|
-
private identifyContentGaps;
|
|
44
|
-
/**
|
|
45
|
-
* Generate enhanced description using AI and unified context
|
|
46
|
-
*/
|
|
47
|
-
private generateEnhancedDescription;
|
|
48
|
-
/**
|
|
49
|
-
* Build comprehensive enhancement prompt using unified context
|
|
50
|
-
*/
|
|
51
|
-
private buildEnhancementPrompt;
|
|
52
|
-
/**
|
|
53
|
-
* Update PR description in Bitbucket
|
|
54
|
-
*/
|
|
55
|
-
private updatePRDescription;
|
|
56
|
-
/**
|
|
57
|
-
* Show description preview for dry run
|
|
58
|
-
*/
|
|
59
|
-
private showDescriptionPreview;
|
|
60
|
-
/**
|
|
61
|
-
* Generate enhancement result summary
|
|
62
|
-
*/
|
|
63
|
-
private generateEnhancementResult;
|
|
64
|
-
/**
|
|
65
|
-
* Get enhancement statistics
|
|
66
|
-
*/
|
|
67
|
-
getStats(): any;
|
|
68
|
-
}
|
|
69
|
-
export declare function createDescriptionEnhancer(bitbucketProvider: BitbucketProvider, aiConfig: AIProviderConfig, enhancementConfig: DescriptionEnhancementConfig): DescriptionEnhancer;
|
|
70
|
-
//# sourceMappingURL=DescriptionEnhancer.d.ts.map
|
|
@@ -1,511 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enhanced Description Enhancer - Optimized to work with Unified Context
|
|
3
|
-
* Preserves all original functionality from pr-describe.js but optimized
|
|
4
|
-
*/
|
|
5
|
-
import { ProviderError, } from "../types/index.js";
|
|
6
|
-
import { logger } from "../utils/Logger.js";
|
|
7
|
-
export class DescriptionEnhancer {
|
|
8
|
-
neurolink;
|
|
9
|
-
bitbucketProvider;
|
|
10
|
-
aiConfig;
|
|
11
|
-
enhancementConfig;
|
|
12
|
-
defaultRequiredSections = [
|
|
13
|
-
{ key: "changelog", name: "Changelog (Modules Modified)", required: true },
|
|
14
|
-
{
|
|
15
|
-
key: "testcases",
|
|
16
|
-
name: "Test Cases (What to be tested)",
|
|
17
|
-
required: true,
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
key: "config_changes",
|
|
21
|
-
name: "CAC Config Or Service Config Changes",
|
|
22
|
-
required: true,
|
|
23
|
-
},
|
|
24
|
-
];
|
|
25
|
-
constructor(bitbucketProvider, aiConfig, enhancementConfig) {
|
|
26
|
-
this.bitbucketProvider = bitbucketProvider;
|
|
27
|
-
this.aiConfig = aiConfig;
|
|
28
|
-
this.enhancementConfig = enhancementConfig;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Get system prompt for description enhancement
|
|
32
|
-
* Uses config.systemPrompt if provided, otherwise uses default
|
|
33
|
-
*/
|
|
34
|
-
getSystemPrompt() {
|
|
35
|
-
const isCustomPrompt = !!this.enhancementConfig.systemPrompt;
|
|
36
|
-
if (isCustomPrompt) {
|
|
37
|
-
logger.debug("✓ Using custom systemPrompt from configuration");
|
|
38
|
-
logger.debug(`Custom prompt preview: ${this.enhancementConfig.systemPrompt?.substring(0, 100)}...`);
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
logger.debug("Using default systemPrompt (no custom prompt configured)");
|
|
42
|
-
}
|
|
43
|
-
return (this.enhancementConfig.systemPrompt ||
|
|
44
|
-
`You are an Expert Technical Writer specializing in pull request documentation.
|
|
45
|
-
Focus on clarity, completeness, and helping reviewers understand the changes.
|
|
46
|
-
|
|
47
|
-
CRITICAL INSTRUCTION: Return ONLY the enhanced PR description content.
|
|
48
|
-
- DO NOT add meta-commentary like "No description provided" or "Here is the enhanced description"
|
|
49
|
-
- DO NOT add explanatory text about what you're doing
|
|
50
|
-
- START directly with the actual PR content (title, sections, etc.)
|
|
51
|
-
- If there's no existing description, just write the new sections without mentioning it`);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Enhance description using pre-gathered unified context (OPTIMIZED)
|
|
55
|
-
*/
|
|
56
|
-
async enhanceWithContext(context, options) {
|
|
57
|
-
const startTime = Date.now();
|
|
58
|
-
try {
|
|
59
|
-
logger.phase("📝 Enhancing PR description...");
|
|
60
|
-
logger.info(`Processing PR #${context.pr.id}: "${context.pr.title}"`);
|
|
61
|
-
// Step 1: Analyze existing content and identify what needs enhancement
|
|
62
|
-
const sectionsToUse = options.customSections || this.defaultRequiredSections;
|
|
63
|
-
logger.debug(`Checking ${sectionsToUse.length} required sections: ${sectionsToUse.map((s) => s.key).join(", ")}`);
|
|
64
|
-
const analysisResult = this.analyzeExistingContent(context.pr.description, sectionsToUse);
|
|
65
|
-
const presentSections = analysisResult.requiredSections
|
|
66
|
-
.filter((s) => s.present)
|
|
67
|
-
.map((s) => s.key);
|
|
68
|
-
const missingSections = analysisResult.requiredSections
|
|
69
|
-
.filter((s) => !s.present)
|
|
70
|
-
.map((s) => s.key);
|
|
71
|
-
if (presentSections.length > 0) {
|
|
72
|
-
logger.debug(`✓ Present sections: ${presentSections.join(", ")}`);
|
|
73
|
-
}
|
|
74
|
-
if (missingSections.length > 0) {
|
|
75
|
-
logger.debug(`✗ Missing sections: ${missingSections.join(", ")}`);
|
|
76
|
-
}
|
|
77
|
-
logger.info(`Content analysis: ${analysisResult.preservedContent.media.length} media items, ` +
|
|
78
|
-
`${analysisResult.missingCount} missing sections`);
|
|
79
|
-
// Step 2: Generate enhanced description using AI
|
|
80
|
-
const enhancedDescription = await this.generateEnhancedDescription(context, analysisResult, options);
|
|
81
|
-
// Step 3: Update PR description if not dry run
|
|
82
|
-
if (!options.dryRun) {
|
|
83
|
-
await this.updatePRDescription(context, enhancedDescription);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
this.showDescriptionPreview(enhancedDescription, analysisResult);
|
|
87
|
-
}
|
|
88
|
-
const duration = Math.round((Date.now() - startTime) / 1000);
|
|
89
|
-
const result = this.generateEnhancementResult(context.pr.description, enhancedDescription, analysisResult, duration);
|
|
90
|
-
logger.success(`Description enhancement completed in ${duration}s: ` +
|
|
91
|
-
`${result.sectionsAdded.length} sections added, ${result.sectionsEnhanced.length} enhanced`);
|
|
92
|
-
return result;
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
logger.error(`Description enhancement failed: ${error.message}`);
|
|
96
|
-
throw new ProviderError(`Description enhancement failed: ${error.message}`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Analyze existing PR description content
|
|
101
|
-
*/
|
|
102
|
-
analyzeExistingContent(description, requiredSections) {
|
|
103
|
-
logger.debug("Analyzing existing PR description content...");
|
|
104
|
-
// Extract preservable content (media, files, links)
|
|
105
|
-
const preservedContent = this.extractPreservableContent(description);
|
|
106
|
-
// Validate required sections
|
|
107
|
-
const sectionsAnalysis = this.validateRequiredSections(description, requiredSections);
|
|
108
|
-
const missingCount = sectionsAnalysis.filter((s) => !s.present).length;
|
|
109
|
-
// Identify content gaps
|
|
110
|
-
const gaps = this.identifyContentGaps(description);
|
|
111
|
-
return {
|
|
112
|
-
requiredSections: sectionsAnalysis,
|
|
113
|
-
missingCount,
|
|
114
|
-
preservedContent,
|
|
115
|
-
gaps,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Extract preservable content (media, files, links)
|
|
120
|
-
*/
|
|
121
|
-
extractPreservableContent(description) {
|
|
122
|
-
const preservableContent = {
|
|
123
|
-
media: [],
|
|
124
|
-
files: [],
|
|
125
|
-
links: [],
|
|
126
|
-
originalText: description || "",
|
|
127
|
-
};
|
|
128
|
-
if (!description) {
|
|
129
|
-
return preservableContent;
|
|
130
|
-
}
|
|
131
|
-
// Extract images and media (screenshots, etc.)
|
|
132
|
-
const mediaRegex = /!\[.*?\]\(.*?\)|<img[^>]*>|<video[^>]*>|<audio[^>]*>/g;
|
|
133
|
-
preservableContent.media = description.match(mediaRegex) || [];
|
|
134
|
-
// Extract file attachments
|
|
135
|
-
const fileRegex = /\[.*?\]\([^)]*\.(pdf|doc|docx|xls|xlsx|ppt|pptx|zip|rar|tar|gz)[^)]*\)/gi;
|
|
136
|
-
preservableContent.files = description.match(fileRegex) || [];
|
|
137
|
-
// Extract links (excluding images and files)
|
|
138
|
-
const linkRegex = /\[[^\]]*\]\([^)]+\)/g;
|
|
139
|
-
const allLinks = description.match(linkRegex) || [];
|
|
140
|
-
preservableContent.links = allLinks.filter((link) => !mediaRegex.test(link) && !fileRegex.test(link));
|
|
141
|
-
logger.debug(`Preservable content: ${preservableContent.media.length} media, ` +
|
|
142
|
-
`${preservableContent.files.length} files, ${preservableContent.links.length} links`);
|
|
143
|
-
return preservableContent;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Validate presence of required sections
|
|
147
|
-
*/
|
|
148
|
-
validateRequiredSections(description, requiredSections) {
|
|
149
|
-
if (!description) {
|
|
150
|
-
return requiredSections.map((section) => ({
|
|
151
|
-
...section,
|
|
152
|
-
present: false,
|
|
153
|
-
content: "",
|
|
154
|
-
}));
|
|
155
|
-
}
|
|
156
|
-
const sectionPatterns = {
|
|
157
|
-
changelog: [
|
|
158
|
-
/##.*?[Cc]hangelog/i,
|
|
159
|
-
/##.*?[Mm]odules?\s+[Mm]odified/i,
|
|
160
|
-
/##.*?[Cc]hanges?\s+[Mm]ade/i,
|
|
161
|
-
/📋.*?[Cc]hangelog/i,
|
|
162
|
-
],
|
|
163
|
-
testcases: [
|
|
164
|
-
/##.*?[Tt]est\s+[Cc]ases?/i,
|
|
165
|
-
/##.*?[Tt]esting/i,
|
|
166
|
-
/🧪.*?[Tt]est/i,
|
|
167
|
-
/##.*?[Tt]est\s+[Pp]lan/i,
|
|
168
|
-
],
|
|
169
|
-
config_changes: [
|
|
170
|
-
/##.*?[Cc]onfig/i,
|
|
171
|
-
/##.*?CAC/i,
|
|
172
|
-
/##.*?[Ss]ervice\s+[Cc]onfig/i,
|
|
173
|
-
/⚙️.*?[Cc]onfig/i,
|
|
174
|
-
],
|
|
175
|
-
};
|
|
176
|
-
return requiredSections.map((section) => {
|
|
177
|
-
let patterns = sectionPatterns[section.key];
|
|
178
|
-
if (!patterns) {
|
|
179
|
-
logger.debug(`No predefined pattern for section "${section.key}", using dynamic pattern based on name`);
|
|
180
|
-
const nameWords = section.name.split(/\s+/).filter((w) => w.length > 2); // Filter out short words like "Or", "Of"
|
|
181
|
-
const namePattern = new RegExp(`##.*?${nameWords.join(".*?")}`, "i");
|
|
182
|
-
const keyWords = section.key.split("_").filter((w) => w.length > 2);
|
|
183
|
-
const keyPattern = new RegExp(`##.*?${keyWords.join(".*?")}`, "i");
|
|
184
|
-
patterns = [namePattern, keyPattern];
|
|
185
|
-
}
|
|
186
|
-
const isPresent = patterns.some((pattern) => pattern.test(description));
|
|
187
|
-
return {
|
|
188
|
-
...section,
|
|
189
|
-
present: isPresent,
|
|
190
|
-
content: isPresent
|
|
191
|
-
? this.extractSectionContent(description, patterns)
|
|
192
|
-
: "",
|
|
193
|
-
};
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Extract content for a specific section
|
|
198
|
-
*/
|
|
199
|
-
extractSectionContent(description, patterns) {
|
|
200
|
-
for (const pattern of patterns) {
|
|
201
|
-
const match = description.match(pattern);
|
|
202
|
-
if (match) {
|
|
203
|
-
const startIndex = match.index + match[0].length;
|
|
204
|
-
const nextHeaderIndex = description
|
|
205
|
-
.substring(startIndex)
|
|
206
|
-
.search(/\n##/);
|
|
207
|
-
const endIndex = nextHeaderIndex === -1
|
|
208
|
-
? description.length
|
|
209
|
-
: startIndex + nextHeaderIndex;
|
|
210
|
-
return description.substring(startIndex, endIndex).trim();
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
return "";
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Identify content gaps (TODOs, unanswered questions, etc.)
|
|
217
|
-
*/
|
|
218
|
-
identifyContentGaps(description) {
|
|
219
|
-
const gaps = [];
|
|
220
|
-
if (!description) {
|
|
221
|
-
gaps.push("No description provided");
|
|
222
|
-
return gaps;
|
|
223
|
-
}
|
|
224
|
-
// Check for unanswered questions and placeholders
|
|
225
|
-
const gapMarkers = [
|
|
226
|
-
{ pattern: /\?\s*$/gm, name: "unanswered questions" },
|
|
227
|
-
{ pattern: /TODO/gi, name: "TODO items" },
|
|
228
|
-
{ pattern: /FIXME/gi, name: "FIXME items" },
|
|
229
|
-
{ pattern: /\[TBD\]/gi, name: "TBD placeholders" },
|
|
230
|
-
{ pattern: /\[TO BE DETERMINED\]/gi, name: "TBD placeholders" },
|
|
231
|
-
{ pattern: /\[PENDING\]/gi, name: "pending items" },
|
|
232
|
-
];
|
|
233
|
-
gapMarkers.forEach((marker) => {
|
|
234
|
-
const matches = description.match(marker.pattern);
|
|
235
|
-
if (matches) {
|
|
236
|
-
gaps.push(`${matches.length} ${marker.name}`);
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
return gaps;
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* Generate enhanced description using AI and unified context
|
|
243
|
-
*/
|
|
244
|
-
async generateEnhancedDescription(context, analysisResult, options) {
|
|
245
|
-
logger.debug("Generating AI-enhanced description...");
|
|
246
|
-
// Initialize NeuroLink with eval-based dynamic import
|
|
247
|
-
if (!this.neurolink) {
|
|
248
|
-
const { NeuroLink } = await import("@juspay/neurolink");
|
|
249
|
-
this.neurolink = new NeuroLink();
|
|
250
|
-
}
|
|
251
|
-
const enhancementPrompt = this.buildEnhancementPrompt(context, analysisResult, options);
|
|
252
|
-
try {
|
|
253
|
-
const result = await this.neurolink.generate({
|
|
254
|
-
input: { text: enhancementPrompt },
|
|
255
|
-
systemPrompt: this.getSystemPrompt(), // Use config or default system prompt
|
|
256
|
-
provider: this.aiConfig.provider,
|
|
257
|
-
model: this.aiConfig.model,
|
|
258
|
-
temperature: this.aiConfig.temperature || 0.7,
|
|
259
|
-
maxTokens: this.aiConfig.maxTokens || 1000000,
|
|
260
|
-
timeout: "8m", // Longer timeout for description generation
|
|
261
|
-
enableAnalytics: this.aiConfig.enableAnalytics,
|
|
262
|
-
enableEvaluation: this.aiConfig.enableEvaluation,
|
|
263
|
-
});
|
|
264
|
-
let enhancedDescription = result.content ||
|
|
265
|
-
result.text ||
|
|
266
|
-
result.response ||
|
|
267
|
-
"";
|
|
268
|
-
// Clean up any markdown code blocks if AI wrapped the response
|
|
269
|
-
enhancedDescription = enhancedDescription
|
|
270
|
-
.replace(/^```markdown\s*/, "")
|
|
271
|
-
.replace(/\s*```$/, "")
|
|
272
|
-
.trim();
|
|
273
|
-
// Remove any meta-commentary that AI might have added
|
|
274
|
-
enhancedDescription = enhancedDescription
|
|
275
|
-
.replace(/^No description provided\.?\s*/i, "")
|
|
276
|
-
.replace(/^Here is the enhanced description:?\s*/i, "")
|
|
277
|
-
.replace(/^I will enhance.*?:\s*/i, "")
|
|
278
|
-
.replace(/^Enhanced description:?\s*/i, "")
|
|
279
|
-
.trim();
|
|
280
|
-
if (!enhancedDescription) {
|
|
281
|
-
throw new Error("AI generated empty description");
|
|
282
|
-
}
|
|
283
|
-
// Validate that required sections are present after enhancement
|
|
284
|
-
const finalValidation = this.validateRequiredSections(enhancedDescription, options.customSections || this.defaultRequiredSections);
|
|
285
|
-
const stillMissing = finalValidation.filter((s) => !s.present);
|
|
286
|
-
if (stillMissing.length > 0) {
|
|
287
|
-
const missingSectionNames = stillMissing.map((s) => s.key).join(", ");
|
|
288
|
-
logger.warn(`Warning: ${stillMissing.length} required sections still missing after AI enhancement: ${missingSectionNames}`);
|
|
289
|
-
logger.debug(`AI may not have added these sections or they don't match detection patterns`);
|
|
290
|
-
}
|
|
291
|
-
else {
|
|
292
|
-
logger.debug(`✓ All ${finalValidation.length} required sections are now present`);
|
|
293
|
-
}
|
|
294
|
-
return enhancedDescription;
|
|
295
|
-
}
|
|
296
|
-
catch (error) {
|
|
297
|
-
if (error.message?.includes("timeout")) {
|
|
298
|
-
logger.error("⏰ Description enhancement timed out after 8 minutes");
|
|
299
|
-
throw new Error("Enhancement timeout - try with smaller diff or adjust timeout");
|
|
300
|
-
}
|
|
301
|
-
logger.error(`AI description generation failed: ${error.message}`);
|
|
302
|
-
throw error;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Build comprehensive enhancement prompt using unified context
|
|
307
|
-
*/
|
|
308
|
-
buildEnhancementPrompt(context, analysisResult, _options) {
|
|
309
|
-
// Prepare diff information based on strategy
|
|
310
|
-
let diffInfo = "";
|
|
311
|
-
if (context.diffStrategy.strategy === "whole" && context.prDiff) {
|
|
312
|
-
diffInfo = `**Diff Strategy**: Whole PR diff (${context.diffStrategy.fileCount} files)
|
|
313
|
-
**Changes**: ${JSON.stringify(context.prDiff.fileChanges?.slice(0, 20) || [], null, 2)}`;
|
|
314
|
-
}
|
|
315
|
-
else if (context.diffStrategy.strategy === "file-by-file" &&
|
|
316
|
-
context.fileDiffs) {
|
|
317
|
-
const fileList = Array.from(context.fileDiffs.keys()).slice(0, 20);
|
|
318
|
-
diffInfo = `**Diff Strategy**: File-by-file analysis (${context.diffStrategy.fileCount} files)
|
|
319
|
-
**Modified Files**: ${JSON.stringify(fileList, null, 2)}`;
|
|
320
|
-
}
|
|
321
|
-
const customInstructions = this.enhancementConfig.enhancementInstructions || "";
|
|
322
|
-
if (customInstructions) {
|
|
323
|
-
logger.debug("✓ Using custom enhancementInstructions from configuration");
|
|
324
|
-
logger.debug(`Instructions preview: ${customInstructions.substring(0, 80)}...`);
|
|
325
|
-
}
|
|
326
|
-
else {
|
|
327
|
-
logger.debug("Using default enhancementInstructions");
|
|
328
|
-
}
|
|
329
|
-
return `${customInstructions || "You are an expert technical writer specializing in comprehensive PR descriptions."}
|
|
330
|
-
|
|
331
|
-
## PR INFORMATION:
|
|
332
|
-
**Title**: ${context.pr.title}
|
|
333
|
-
**Author**: ${context.pr.author}
|
|
334
|
-
**Current Description**:
|
|
335
|
-
${analysisResult.preservedContent.originalText || "[No existing description]"}
|
|
336
|
-
|
|
337
|
-
## CODE CHANGES ANALYSIS:
|
|
338
|
-
${diffInfo}
|
|
339
|
-
|
|
340
|
-
## PROJECT CONTEXT:
|
|
341
|
-
${context.projectContext.memoryBank.summary}
|
|
342
|
-
|
|
343
|
-
## PROJECT RULES:
|
|
344
|
-
${context.projectContext.clinerules || "No specific rules defined"}
|
|
345
|
-
|
|
346
|
-
## CONTENT PRESERVATION REQUIREMENTS:
|
|
347
|
-
**CRITICAL**: This is content ENHANCEMENT, not replacement!
|
|
348
|
-
|
|
349
|
-
### Preserved Content Analysis:
|
|
350
|
-
- **Media Items**: ${analysisResult.preservedContent.media.length} (${analysisResult.preservedContent.media.join(", ")})
|
|
351
|
-
- **File Attachments**: ${analysisResult.preservedContent.files.length} (${analysisResult.preservedContent.files.join(", ")})
|
|
352
|
-
- **Links**: ${analysisResult.preservedContent.links.length}
|
|
353
|
-
- **Content Gaps**: ${analysisResult.gaps.join(", ") || "None identified"}
|
|
354
|
-
|
|
355
|
-
### PRESERVATION RULES:
|
|
356
|
-
- **NEVER REMOVE**: Screenshots, images, file attachments, existing explanations, or links
|
|
357
|
-
- **PRESERVE EXACTLY**: All media links, file references, and existing valuable content
|
|
358
|
-
- **ONLY ADD**: Missing required sections or enhance clearly incomplete ones
|
|
359
|
-
- **MAINTAIN**: Original structure, tone, and author's explanations
|
|
360
|
-
|
|
361
|
-
## REQUIRED SECTIONS STATUS:
|
|
362
|
-
${analysisResult.requiredSections
|
|
363
|
-
.map((section) => `
|
|
364
|
-
**${section.name}**:
|
|
365
|
-
- Present: ${section.present ? "✅ Yes" : "❌ Missing"}
|
|
366
|
-
- Content: ${section.content ? `"${section.content.substring(0, 100)}..."` : "None"}
|
|
367
|
-
- Action Needed: ${section.present ? ((section.content?.length || 0) < 50 ? "Enhancement" : "None") : "Add Section"}`)
|
|
368
|
-
.join("")}
|
|
369
|
-
|
|
370
|
-
## REQUIRED SECTIONS TO IMPLEMENT:
|
|
371
|
-
|
|
372
|
-
### 1. 📋 CHANGELOG (Modules Modified)
|
|
373
|
-
**Purpose**: Clear documentation of what changed
|
|
374
|
-
**Content Requirements**:
|
|
375
|
-
- List specific files/modules modified, added, or removed
|
|
376
|
-
- Categorize changes (Features, Bug Fixes, Improvements, Breaking Changes)
|
|
377
|
-
- Mention key components affected
|
|
378
|
-
- Highlight any architectural changes
|
|
379
|
-
|
|
380
|
-
### 2. 🧪 TEST CASES (What to be tested)
|
|
381
|
-
**Purpose**: Comprehensive testing guidance
|
|
382
|
-
**Content Requirements**:
|
|
383
|
-
- Unit tests to run or add
|
|
384
|
-
- Integration test scenarios
|
|
385
|
-
- Manual testing steps for reviewers
|
|
386
|
-
- Edge cases to verify
|
|
387
|
-
- Regression testing considerations
|
|
388
|
-
- Performance testing if applicable
|
|
389
|
-
|
|
390
|
-
### 3. ⚙️ CAC CONFIG OR SERVICE CONFIG CHANGES
|
|
391
|
-
**Purpose**: Infrastructure and configuration impact
|
|
392
|
-
**Content Requirements**:
|
|
393
|
-
- Configuration files modified
|
|
394
|
-
- Environment variables added/changed/removed
|
|
395
|
-
- Service configuration updates
|
|
396
|
-
- Database schema changes
|
|
397
|
-
- Deployment considerations
|
|
398
|
-
- If no config changes: explicitly state "No configuration changes required"
|
|
399
|
-
|
|
400
|
-
## ENHANCEMENT STRATEGY:
|
|
401
|
-
|
|
402
|
-
### For Missing Sections:
|
|
403
|
-
1. **START** with the complete existing description
|
|
404
|
-
2. **ANALYZE** the code changes to understand the scope
|
|
405
|
-
3. **ADD** each missing required section with comprehensive content
|
|
406
|
-
4. **EXTRACT** relevant information from the diff to populate sections
|
|
407
|
-
|
|
408
|
-
### For Incomplete Sections:
|
|
409
|
-
1. **PRESERVE** all existing content in the section
|
|
410
|
-
2. **ENHANCE** with additional details based on code analysis
|
|
411
|
-
3. **MAINTAIN** the original structure and format
|
|
412
|
-
|
|
413
|
-
### Content Generation Guidelines:
|
|
414
|
-
- **Be Specific**: Use actual file names, function names, and module names from the changes
|
|
415
|
-
- **Be Actionable**: Provide clear, executable test instructions
|
|
416
|
-
- **Be Complete**: Cover all aspects of the change comprehensively
|
|
417
|
-
- **Be Professional**: Maintain technical accuracy and clear communication
|
|
418
|
-
|
|
419
|
-
## OUTPUT REQUIREMENTS:
|
|
420
|
-
Return the COMPLETE enhanced description as properly formatted markdown text (NOT JSON).
|
|
421
|
-
|
|
422
|
-
**CRITICAL INSTRUCTIONS**:
|
|
423
|
-
1. **START WITH**: The entire existing description as your foundation
|
|
424
|
-
2. **PRESERVE**: Every single piece of existing content (media, links, explanations)
|
|
425
|
-
3. **ADD ONLY**: Missing required sections at appropriate locations
|
|
426
|
-
4. **ENHANCE ONLY**: Clearly incomplete sections with additional details
|
|
427
|
-
5. **EXTRACT**: Specific details from the code changes for accuracy
|
|
428
|
-
6. **MAINTAIN**: Professional tone and clear markdown formatting
|
|
429
|
-
|
|
430
|
-
Generate the enhanced description now, ensuring ALL preservation requirements are met:`;
|
|
431
|
-
}
|
|
432
|
-
/**
|
|
433
|
-
* Update PR description in Bitbucket
|
|
434
|
-
*/
|
|
435
|
-
async updatePRDescription(context, enhancedDescription) {
|
|
436
|
-
logger.debug(`Updating PR description for #${context.pr.id}...`);
|
|
437
|
-
try {
|
|
438
|
-
await this.bitbucketProvider.updatePRDescription(context.identifier, enhancedDescription);
|
|
439
|
-
logger.success("✅ PR description updated successfully");
|
|
440
|
-
}
|
|
441
|
-
catch (error) {
|
|
442
|
-
logger.error(`Failed to update PR description: ${error.message}`);
|
|
443
|
-
throw new ProviderError(`Description update failed: ${error.message}`);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* Show description preview for dry run
|
|
448
|
-
*/
|
|
449
|
-
showDescriptionPreview(enhancedDescription, analysisResult) {
|
|
450
|
-
console.log("\n" + "═".repeat(80));
|
|
451
|
-
console.log("📝 ENHANCED PR DESCRIPTION PREVIEW");
|
|
452
|
-
console.log("═".repeat(80));
|
|
453
|
-
console.log(enhancedDescription);
|
|
454
|
-
console.log("═".repeat(80));
|
|
455
|
-
console.log("\n📊 ENHANCEMENT SUMMARY:");
|
|
456
|
-
console.log(`✅ Required sections completed: ${analysisResult.requiredSections.filter((s) => s.present).length}/${analysisResult.requiredSections.length}`);
|
|
457
|
-
console.log(`📎 Preserved content: ${analysisResult.preservedContent.media.length} media items, ${analysisResult.preservedContent.files.length} files`);
|
|
458
|
-
console.log(`📏 Enhanced description length: ${enhancedDescription.length} characters`);
|
|
459
|
-
if (analysisResult.gaps.length > 0) {
|
|
460
|
-
console.log(`🔍 Content gaps addressed: ${analysisResult.gaps.join(", ")}`);
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
/**
|
|
464
|
-
* Generate enhancement result summary
|
|
465
|
-
*/
|
|
466
|
-
generateEnhancementResult(originalDescription, enhancedDescription, analysisResult, _duration) {
|
|
467
|
-
// Determine what sections were added or enhanced
|
|
468
|
-
const originalSections = this.validateRequiredSections(originalDescription, analysisResult.requiredSections);
|
|
469
|
-
const enhancedSections = this.validateRequiredSections(enhancedDescription, analysisResult.requiredSections);
|
|
470
|
-
const sectionsAdded = enhancedSections
|
|
471
|
-
.filter((enhanced, i) => enhanced.present && !originalSections[i].present)
|
|
472
|
-
.map((s) => s.name);
|
|
473
|
-
const sectionsEnhanced = enhancedSections
|
|
474
|
-
.filter((enhanced, i) => enhanced.present &&
|
|
475
|
-
originalSections[i].present &&
|
|
476
|
-
(enhanced.content?.length || 0) >
|
|
477
|
-
(originalSections[i].content?.length || 0) + 50)
|
|
478
|
-
.map((s) => s.name);
|
|
479
|
-
const completedSections = enhancedSections.filter((s) => s.present).length;
|
|
480
|
-
return {
|
|
481
|
-
originalDescription: originalDescription || "",
|
|
482
|
-
enhancedDescription,
|
|
483
|
-
sectionsAdded,
|
|
484
|
-
sectionsEnhanced,
|
|
485
|
-
preservedItems: {
|
|
486
|
-
media: analysisResult.preservedContent.media.length,
|
|
487
|
-
files: analysisResult.preservedContent.files.length,
|
|
488
|
-
links: analysisResult.preservedContent.links.length,
|
|
489
|
-
},
|
|
490
|
-
statistics: {
|
|
491
|
-
originalLength: originalDescription?.length || 0,
|
|
492
|
-
enhancedLength: enhancedDescription.length,
|
|
493
|
-
completedSections,
|
|
494
|
-
totalSections: analysisResult.requiredSections.length,
|
|
495
|
-
},
|
|
496
|
-
};
|
|
497
|
-
}
|
|
498
|
-
/**
|
|
499
|
-
* Get enhancement statistics
|
|
500
|
-
*/
|
|
501
|
-
getStats() {
|
|
502
|
-
return {
|
|
503
|
-
defaultSections: this.defaultRequiredSections.length,
|
|
504
|
-
aiProvider: this.aiConfig.provider,
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
export function createDescriptionEnhancer(bitbucketProvider, aiConfig, enhancementConfig) {
|
|
509
|
-
return new DescriptionEnhancer(bitbucketProvider, aiConfig, enhancementConfig);
|
|
510
|
-
}
|
|
511
|
-
//# sourceMappingURL=DescriptionEnhancer.js.map
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Multi-Instance Processor for Parallel Code Review
|
|
3
|
-
* Orchestrates multiple Neurolink SDK instances for diverse code analysis
|
|
4
|
-
*/
|
|
5
|
-
import { MultiInstanceConfig, MultiInstanceResult, CodeReviewConfig, ReviewOptions } from "../types/index.js";
|
|
6
|
-
import { UnifiedContext } from "../core/ContextGatherer.js";
|
|
7
|
-
import { BitbucketProvider } from "../core/providers/BitbucketProvider.js";
|
|
8
|
-
/**
|
|
9
|
-
* Multi-Instance Processor
|
|
10
|
-
* Manages parallel execution of multiple CodeReviewer instances
|
|
11
|
-
*/
|
|
12
|
-
export declare class MultiInstanceProcessor {
|
|
13
|
-
private bitbucketProvider;
|
|
14
|
-
private baseReviewConfig;
|
|
15
|
-
private duplicateRemover;
|
|
16
|
-
constructor(bitbucketProvider: BitbucketProvider, baseReviewConfig: CodeReviewConfig);
|
|
17
|
-
/**
|
|
18
|
-
* Process code review using multiple instances
|
|
19
|
-
*/
|
|
20
|
-
processWithMultipleInstances(context: UnifiedContext, options: ReviewOptions, multiInstanceConfig: MultiInstanceConfig): Promise<MultiInstanceResult>;
|
|
21
|
-
/**
|
|
22
|
-
* Execute all instances in parallel with concurrency control
|
|
23
|
-
*/
|
|
24
|
-
private executeInstancesInParallel;
|
|
25
|
-
/**
|
|
26
|
-
* Execute a single instance with concurrency control
|
|
27
|
-
*/
|
|
28
|
-
private executeInstanceWithConcurrency;
|
|
29
|
-
/**
|
|
30
|
-
* Validate provider string against allowed provider types
|
|
31
|
-
*/
|
|
32
|
-
private validateProvider;
|
|
33
|
-
/**
|
|
34
|
-
* Execute a single instance
|
|
35
|
-
*/
|
|
36
|
-
private executeInstance;
|
|
37
|
-
/**
|
|
38
|
-
* Validate multi-instance configuration
|
|
39
|
-
*/
|
|
40
|
-
private validateMultiInstanceConfig;
|
|
41
|
-
/**
|
|
42
|
-
* Estimate tokens per instance based on context
|
|
43
|
-
*/
|
|
44
|
-
private estimateTokensPerInstance;
|
|
45
|
-
/**
|
|
46
|
-
* Calculate total token budget for all instances
|
|
47
|
-
*/
|
|
48
|
-
private calculateTotalTokenBudget;
|
|
49
|
-
/**
|
|
50
|
-
* Extract token usage from review result (if available)
|
|
51
|
-
*/
|
|
52
|
-
private extractTokenUsage;
|
|
53
|
-
/**
|
|
54
|
-
* Create non-deduplicated result (when deduplication is disabled)
|
|
55
|
-
*/
|
|
56
|
-
private createNonDeduplicatedResult;
|
|
57
|
-
/**
|
|
58
|
-
* Apply final filtering based on configuration
|
|
59
|
-
*/
|
|
60
|
-
private applyFinalFiltering;
|
|
61
|
-
/**
|
|
62
|
-
* Prioritize violations based on strategy
|
|
63
|
-
*/
|
|
64
|
-
private prioritizeViolations;
|
|
65
|
-
/**
|
|
66
|
-
* Create summary of multi-instance processing
|
|
67
|
-
*/
|
|
68
|
-
private createSummary;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Factory function to create MultiInstanceProcessor
|
|
72
|
-
*/
|
|
73
|
-
export declare function createMultiInstanceProcessor(bitbucketProvider: BitbucketProvider, baseReviewConfig: CodeReviewConfig): MultiInstanceProcessor;
|
|
74
|
-
//# sourceMappingURL=MultiInstanceProcessor.d.ts.map
|