@juspay/yama 1.5.1 → 1.6.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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
# [1.6.0](https://github.com/juspay/yama/compare/v1.5.1...v1.6.0) (2025-10-24)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- added support for system prompt and fixed required section check in description enhancer ([c22d1ff](https://github.com/juspay/yama/commit/c22d1ff15a165379dece65145123433f7c1d6b98))
|
|
6
|
+
|
|
1
7
|
## [1.5.1](https://github.com/juspay/yama/compare/v1.5.0...v1.5.1) (2025-09-24)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
package/dist/core/Guardian.js
CHANGED
|
@@ -59,7 +59,13 @@ export class Guardian {
|
|
|
59
59
|
fallbackPaths: ["docs/memory-bank", ".memory-bank"],
|
|
60
60
|
});
|
|
61
61
|
this.codeReviewer = new CodeReviewer(this.bitbucketProvider, this.config.providers.ai, this.config.features.codeReview);
|
|
62
|
-
this.descriptionEnhancer = new DescriptionEnhancer(this.bitbucketProvider, this.config.providers.ai);
|
|
62
|
+
this.descriptionEnhancer = new DescriptionEnhancer(this.bitbucketProvider, this.config.providers.ai, this.config.features.descriptionEnhancement);
|
|
63
|
+
logger.debug("Description Enhancement Configuration:");
|
|
64
|
+
logger.debug(` - Enabled: ${this.config.features.descriptionEnhancement.enabled}`);
|
|
65
|
+
logger.debug(` - Required Sections: ${this.config.features.descriptionEnhancement.requiredSections.length} (${this.config.features.descriptionEnhancement.requiredSections.map((s) => s.key).join(", ")})`);
|
|
66
|
+
logger.debug(` - Custom systemPrompt: ${this.config.features.descriptionEnhancement.systemPrompt ? "Yes" : "No (using default)"}`);
|
|
67
|
+
logger.debug(` - Custom enhancementInstructions: ${this.config.features.descriptionEnhancement.enhancementInstructions ? "Yes" : "No (using default)"}`);
|
|
68
|
+
logger.debug(` - outputTemplate: ${this.config.features.descriptionEnhancement.outputTemplate ? "Provided" : "Not provided"}`);
|
|
63
69
|
this.initialized = true;
|
|
64
70
|
logger.success("✅ Yama initialized successfully");
|
|
65
71
|
}
|
|
@@ -2,15 +2,21 @@
|
|
|
2
2
|
* Enhanced Description Enhancer - Optimized to work with Unified Context
|
|
3
3
|
* Preserves all original functionality from pr-describe.js but optimized
|
|
4
4
|
*/
|
|
5
|
-
import { EnhancementOptions, EnhancementResult, AIProviderConfig } from "../types/index.js";
|
|
5
|
+
import { EnhancementOptions, EnhancementResult, AIProviderConfig, DescriptionEnhancementConfig } from "../types/index.js";
|
|
6
6
|
import { UnifiedContext } from "../core/ContextGatherer.js";
|
|
7
7
|
import { BitbucketProvider } from "../core/providers/BitbucketProvider.js";
|
|
8
8
|
export declare class DescriptionEnhancer {
|
|
9
9
|
private neurolink;
|
|
10
10
|
private bitbucketProvider;
|
|
11
11
|
private aiConfig;
|
|
12
|
+
private enhancementConfig;
|
|
12
13
|
private defaultRequiredSections;
|
|
13
|
-
constructor(bitbucketProvider: BitbucketProvider, aiConfig: AIProviderConfig);
|
|
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;
|
|
14
20
|
/**
|
|
15
21
|
* Enhance description using pre-gathered unified context (OPTIMIZED)
|
|
16
22
|
*/
|
|
@@ -60,5 +66,5 @@ export declare class DescriptionEnhancer {
|
|
|
60
66
|
*/
|
|
61
67
|
getStats(): any;
|
|
62
68
|
}
|
|
63
|
-
export declare function createDescriptionEnhancer(bitbucketProvider: BitbucketProvider, aiConfig: AIProviderConfig): DescriptionEnhancer;
|
|
69
|
+
export declare function createDescriptionEnhancer(bitbucketProvider: BitbucketProvider, aiConfig: AIProviderConfig, enhancementConfig: DescriptionEnhancementConfig): DescriptionEnhancer;
|
|
64
70
|
//# sourceMappingURL=DescriptionEnhancer.d.ts.map
|
|
@@ -8,6 +8,7 @@ export class DescriptionEnhancer {
|
|
|
8
8
|
neurolink;
|
|
9
9
|
bitbucketProvider;
|
|
10
10
|
aiConfig;
|
|
11
|
+
enhancementConfig;
|
|
11
12
|
defaultRequiredSections = [
|
|
12
13
|
{ key: "changelog", name: "Changelog (Modules Modified)", required: true },
|
|
13
14
|
{
|
|
@@ -21,9 +22,33 @@ export class DescriptionEnhancer {
|
|
|
21
22
|
required: true,
|
|
22
23
|
},
|
|
23
24
|
];
|
|
24
|
-
constructor(bitbucketProvider, aiConfig) {
|
|
25
|
+
constructor(bitbucketProvider, aiConfig, enhancementConfig) {
|
|
25
26
|
this.bitbucketProvider = bitbucketProvider;
|
|
26
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`);
|
|
27
52
|
}
|
|
28
53
|
/**
|
|
29
54
|
* Enhance description using pre-gathered unified context (OPTIMIZED)
|
|
@@ -34,7 +59,21 @@ export class DescriptionEnhancer {
|
|
|
34
59
|
logger.phase("📝 Enhancing PR description...");
|
|
35
60
|
logger.info(`Processing PR #${context.pr.id}: "${context.pr.title}"`);
|
|
36
61
|
// Step 1: Analyze existing content and identify what needs enhancement
|
|
37
|
-
const
|
|
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
|
+
}
|
|
38
77
|
logger.info(`Content analysis: ${analysisResult.preservedContent.media.length} media items, ` +
|
|
39
78
|
`${analysisResult.missingCount} missing sections`);
|
|
40
79
|
// Step 2: Generate enhanced description using AI
|
|
@@ -135,15 +174,21 @@ export class DescriptionEnhancer {
|
|
|
135
174
|
],
|
|
136
175
|
};
|
|
137
176
|
return requiredSections.map((section) => {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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));
|
|
142
187
|
return {
|
|
143
188
|
...section,
|
|
144
189
|
present: isPresent,
|
|
145
190
|
content: isPresent
|
|
146
|
-
? this.extractSectionContent(description, patterns
|
|
191
|
+
? this.extractSectionContent(description, patterns)
|
|
147
192
|
: "",
|
|
148
193
|
};
|
|
149
194
|
});
|
|
@@ -207,6 +252,7 @@ export class DescriptionEnhancer {
|
|
|
207
252
|
try {
|
|
208
253
|
const result = await this.neurolink.generate({
|
|
209
254
|
input: { text: enhancementPrompt },
|
|
255
|
+
systemPrompt: this.getSystemPrompt(), // Use config or default system prompt
|
|
210
256
|
provider: this.aiConfig.provider,
|
|
211
257
|
model: this.aiConfig.model,
|
|
212
258
|
temperature: this.aiConfig.temperature || 0.7,
|
|
@@ -224,6 +270,13 @@ export class DescriptionEnhancer {
|
|
|
224
270
|
.replace(/^```markdown\s*/, "")
|
|
225
271
|
.replace(/\s*```$/, "")
|
|
226
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();
|
|
227
280
|
if (!enhancedDescription) {
|
|
228
281
|
throw new Error("AI generated empty description");
|
|
229
282
|
}
|
|
@@ -231,7 +284,12 @@ export class DescriptionEnhancer {
|
|
|
231
284
|
const finalValidation = this.validateRequiredSections(enhancedDescription, options.customSections || this.defaultRequiredSections);
|
|
232
285
|
const stillMissing = finalValidation.filter((s) => !s.present);
|
|
233
286
|
if (stillMissing.length > 0) {
|
|
234
|
-
|
|
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`);
|
|
235
293
|
}
|
|
236
294
|
return enhancedDescription;
|
|
237
295
|
}
|
|
@@ -260,7 +318,15 @@ export class DescriptionEnhancer {
|
|
|
260
318
|
diffInfo = `**Diff Strategy**: File-by-file analysis (${context.diffStrategy.fileCount} files)
|
|
261
319
|
**Modified Files**: ${JSON.stringify(fileList, null, 2)}`;
|
|
262
320
|
}
|
|
263
|
-
|
|
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."}
|
|
264
330
|
|
|
265
331
|
## PR INFORMATION:
|
|
266
332
|
**Title**: ${context.pr.title}
|
|
@@ -439,7 +505,7 @@ Generate the enhanced description now, ensuring ALL preservation requirements ar
|
|
|
439
505
|
};
|
|
440
506
|
}
|
|
441
507
|
}
|
|
442
|
-
export function createDescriptionEnhancer(bitbucketProvider, aiConfig) {
|
|
443
|
-
return new DescriptionEnhancer(bitbucketProvider, aiConfig);
|
|
508
|
+
export function createDescriptionEnhancer(bitbucketProvider, aiConfig, enhancementConfig) {
|
|
509
|
+
return new DescriptionEnhancer(bitbucketProvider, aiConfig, enhancementConfig);
|
|
444
510
|
}
|
|
445
511
|
//# sourceMappingURL=DescriptionEnhancer.js.map
|
|
@@ -80,7 +80,7 @@ export class ConfigManager {
|
|
|
80
80
|
},
|
|
81
81
|
],
|
|
82
82
|
autoFormat: true,
|
|
83
|
-
systemPrompt: "You are an Expert Technical Writer specializing in pull request documentation. Your role is to:\n\n📝 CLARITY FIRST: Create clear, comprehensive PR descriptions that help reviewers understand the changes\n🎥 STORY TELLING: Explain the 'why' behind changes, not just the 'what'\n📈 STRUCTURED: Follow consistent formatting with required sections\n🔗 CONTEXTUAL: Link changes to business value and technical rationale\n\nCRITICAL INSTRUCTION: Return ONLY the enhanced PR description content as clean markdown
|
|
83
|
+
systemPrompt: "You are an Expert Technical Writer specializing in pull request documentation. Your role is to:\n\n📝 CLARITY FIRST: Create clear, comprehensive PR descriptions that help reviewers understand the changes\n🎥 STORY TELLING: Explain the 'why' behind changes, not just the 'what'\n📈 STRUCTURED: Follow consistent formatting with required sections\n🔗 CONTEXTUAL: Link changes to business value and technical rationale\n\nCRITICAL INSTRUCTION: Return ONLY the enhanced PR description content as clean markdown.\n- DO NOT add meta-commentary like \"No description provided\" or \"Here is the enhanced description\"\n- DO NOT add explanatory text about what you're doing\n- START directly with the actual PR content (sections, lists, explanations)\n- If there's no existing description, just write the new sections without mentioning it\n\nOutput the enhanced description directly without any wrapper text or explanations.",
|
|
84
84
|
outputTemplate: "# PR Title Enhancement (if needed)\n\n## Summary\n[Clear overview of what this PR accomplishes]\n\n## Changes Made\n[Specific technical changes - be precise]\n\n## Testing\n[How the changes were tested]\n\n## Impact\n[Business/technical impact and considerations]\n\n## Additional Notes\n[Any deployment notes, follow-ups, or special considerations]",
|
|
85
85
|
enhancementInstructions: 'Return ONLY the enhanced PR description as clean markdown. Do NOT include any explanatory text, meta-commentary, or phrases like "Here is the enhanced description:" or "I will enhance...".\n\nStart directly with the enhanced description content using this structure:',
|
|
86
86
|
},
|
|
@@ -244,11 +244,10 @@ export class ConfigManager {
|
|
|
244
244
|
* Apply provider-aware token limits using shared utility
|
|
245
245
|
*/
|
|
246
246
|
applyProviderTokenLimits(config) {
|
|
247
|
-
const provider = config.providers.ai.provider ||
|
|
247
|
+
const provider = config.providers.ai.provider || "auto";
|
|
248
248
|
const configuredTokens = config.providers.ai.maxTokens;
|
|
249
249
|
// Use the shared utility to validate and adjust token limits
|
|
250
|
-
const validatedTokens = validateProviderTokenLimit(provider, configuredTokens, false
|
|
251
|
-
);
|
|
250
|
+
const validatedTokens = validateProviderTokenLimit(provider, configuredTokens, false);
|
|
252
251
|
config.providers.ai.maxTokens = validatedTokens;
|
|
253
252
|
return config;
|
|
254
253
|
}
|
package/package.json
CHANGED
package/yama.config.example.yaml
CHANGED
|
@@ -109,6 +109,7 @@ features:
|
|
|
109
109
|
enabled: true
|
|
110
110
|
preserveContent: true # Always preserve existing content
|
|
111
111
|
autoFormat: true
|
|
112
|
+
|
|
112
113
|
requiredSections:
|
|
113
114
|
- key: "changelog"
|
|
114
115
|
name: "Changelog (Modules Modified)"
|
|
@@ -120,6 +121,16 @@ features:
|
|
|
120
121
|
name: "CAC Config Or Service Config Changes"
|
|
121
122
|
required: true
|
|
122
123
|
|
|
124
|
+
# Customize AI behavior:
|
|
125
|
+
systemPrompt: |
|
|
126
|
+
You are a Senior Staff Engineer writing comprehensive technical documentation.
|
|
127
|
+
Focus on architectural decisions, trade-offs, and long-term maintainability.
|
|
128
|
+
|
|
129
|
+
# Customize formatting:
|
|
130
|
+
enhancementInstructions: |
|
|
131
|
+
Keep descriptions under 300 words. Use bullet points, not paragraphs.
|
|
132
|
+
No emojis. Professional tone only. Include numbers and metrics.
|
|
133
|
+
|
|
123
134
|
# NEW: Diff Strategy Configuration
|
|
124
135
|
diffStrategy:
|
|
125
136
|
enabled: true
|