@juspay/yama 1.5.1 → 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.
Files changed (67) hide show
  1. package/.mcp-config.example.json +26 -0
  2. package/CHANGELOG.md +40 -0
  3. package/README.md +311 -685
  4. package/dist/cli/v2.cli.d.ts +13 -0
  5. package/dist/cli/v2.cli.js +290 -0
  6. package/dist/index.d.ts +12 -13
  7. package/dist/index.js +18 -19
  8. package/dist/v2/config/ConfigLoader.d.ts +50 -0
  9. package/dist/v2/config/ConfigLoader.js +205 -0
  10. package/dist/v2/config/DefaultConfig.d.ts +9 -0
  11. package/dist/v2/config/DefaultConfig.js +191 -0
  12. package/dist/v2/core/MCPServerManager.d.ts +22 -0
  13. package/dist/v2/core/MCPServerManager.js +92 -0
  14. package/dist/v2/core/SessionManager.d.ts +72 -0
  15. package/dist/v2/core/SessionManager.js +200 -0
  16. package/dist/v2/core/YamaV2Orchestrator.d.ts +112 -0
  17. package/dist/v2/core/YamaV2Orchestrator.js +549 -0
  18. package/dist/v2/prompts/EnhancementSystemPrompt.d.ts +8 -0
  19. package/dist/v2/prompts/EnhancementSystemPrompt.js +216 -0
  20. package/dist/v2/prompts/PromptBuilder.d.ts +38 -0
  21. package/dist/v2/prompts/PromptBuilder.js +228 -0
  22. package/dist/v2/prompts/ReviewSystemPrompt.d.ts +8 -0
  23. package/dist/v2/prompts/ReviewSystemPrompt.js +270 -0
  24. package/dist/v2/types/config.types.d.ts +120 -0
  25. package/dist/v2/types/config.types.js +5 -0
  26. package/dist/v2/types/mcp.types.d.ts +191 -0
  27. package/dist/v2/types/mcp.types.js +6 -0
  28. package/dist/v2/types/v2.types.d.ts +182 -0
  29. package/dist/v2/types/v2.types.js +42 -0
  30. package/dist/v2/utils/ObservabilityConfig.d.ts +22 -0
  31. package/dist/v2/utils/ObservabilityConfig.js +48 -0
  32. package/package.json +11 -9
  33. package/yama.config.example.yaml +214 -193
  34. package/dist/cli/index.d.ts +0 -12
  35. package/dist/cli/index.js +0 -538
  36. package/dist/core/ContextGatherer.d.ts +0 -110
  37. package/dist/core/ContextGatherer.js +0 -470
  38. package/dist/core/Guardian.d.ts +0 -81
  39. package/dist/core/Guardian.js +0 -474
  40. package/dist/core/providers/BitbucketProvider.d.ts +0 -105
  41. package/dist/core/providers/BitbucketProvider.js +0 -489
  42. package/dist/features/CodeReviewer.d.ts +0 -173
  43. package/dist/features/CodeReviewer.js +0 -1707
  44. package/dist/features/DescriptionEnhancer.d.ts +0 -64
  45. package/dist/features/DescriptionEnhancer.js +0 -445
  46. package/dist/features/MultiInstanceProcessor.d.ts +0 -74
  47. package/dist/features/MultiInstanceProcessor.js +0 -360
  48. package/dist/types/index.d.ts +0 -624
  49. package/dist/types/index.js +0 -104
  50. package/dist/utils/Cache.d.ts +0 -103
  51. package/dist/utils/Cache.js +0 -444
  52. package/dist/utils/ConfigManager.d.ts +0 -88
  53. package/dist/utils/ConfigManager.js +0 -603
  54. package/dist/utils/ContentSimilarityService.d.ts +0 -74
  55. package/dist/utils/ContentSimilarityService.js +0 -215
  56. package/dist/utils/ExactDuplicateRemover.d.ts +0 -77
  57. package/dist/utils/ExactDuplicateRemover.js +0 -361
  58. package/dist/utils/Logger.d.ts +0 -31
  59. package/dist/utils/Logger.js +0 -214
  60. package/dist/utils/MemoryBankManager.d.ts +0 -73
  61. package/dist/utils/MemoryBankManager.js +0 -310
  62. package/dist/utils/ParallelProcessing.d.ts +0 -140
  63. package/dist/utils/ParallelProcessing.js +0 -333
  64. package/dist/utils/ProviderLimits.d.ts +0 -58
  65. package/dist/utils/ProviderLimits.js +0 -143
  66. package/dist/utils/RetryManager.d.ts +0 -78
  67. package/dist/utils/RetryManager.js +0 -205
@@ -0,0 +1,549 @@
1
+ /**
2
+ * Yama V2 Orchestrator
3
+ * Main entry point for AI-native autonomous code review
4
+ */
5
+ import { NeuroLink } from "@juspay/neurolink";
6
+ import { MCPServerManager } from "./MCPServerManager.js";
7
+ import { ConfigLoader } from "../config/ConfigLoader.js";
8
+ import { PromptBuilder } from "../prompts/PromptBuilder.js";
9
+ import { SessionManager } from "./SessionManager.js";
10
+ import { buildObservabilityConfigFromEnv, validateObservabilityConfig, } from "../utils/ObservabilityConfig.js";
11
+ export class YamaV2Orchestrator {
12
+ neurolink;
13
+ mcpManager;
14
+ configLoader;
15
+ promptBuilder;
16
+ sessionManager;
17
+ config;
18
+ initialized = false;
19
+ constructor() {
20
+ this.configLoader = new ConfigLoader();
21
+ this.mcpManager = new MCPServerManager();
22
+ this.promptBuilder = new PromptBuilder();
23
+ this.sessionManager = new SessionManager();
24
+ }
25
+ /**
26
+ * Initialize Yama V2 with configuration and MCP servers
27
+ */
28
+ async initialize(configPath) {
29
+ if (this.initialized) {
30
+ return;
31
+ }
32
+ this.showBanner();
33
+ console.log("🚀 Initializing Yama V2...\n");
34
+ try {
35
+ // Step 1: Load configuration
36
+ this.config = await this.configLoader.loadConfig(configPath);
37
+ // Step 2: Initialize NeuroLink with observability
38
+ console.log("🧠 Initializing NeuroLink AI engine...");
39
+ this.neurolink = this.initializeNeurolink();
40
+ console.log("✅ NeuroLink initialized\n");
41
+ // Step 3: Setup MCP servers
42
+ await this.mcpManager.setupMCPServers(this.neurolink, this.config.mcpServers);
43
+ console.log("✅ MCP servers ready (tools managed by NeuroLink)\n");
44
+ // Step 4: Validate configuration
45
+ await this.configLoader.validate();
46
+ this.initialized = true;
47
+ console.log("✅ Yama V2 initialized successfully\n");
48
+ console.log("═".repeat(60) + "\n");
49
+ }
50
+ catch (error) {
51
+ console.error("\n❌ Initialization failed:", error.message);
52
+ throw error;
53
+ }
54
+ }
55
+ /**
56
+ * Start autonomous AI review
57
+ */
58
+ async startReview(request) {
59
+ await this.ensureInitialized();
60
+ const startTime = Date.now();
61
+ const sessionId = this.sessionManager.createSession(request);
62
+ this.logReviewStart(request, sessionId);
63
+ try {
64
+ // Build comprehensive AI instructions
65
+ const instructions = await this.promptBuilder.buildReviewInstructions(request, this.config);
66
+ if (this.config.display.verboseToolCalls) {
67
+ console.log("\n📝 AI Instructions built:");
68
+ console.log(` Instruction length: ${instructions.length} characters\n`);
69
+ }
70
+ // Create tool context for AI
71
+ const toolContext = this.createToolContext(sessionId, request);
72
+ // Set tool context in NeuroLink (using type assertion as setToolContext is documented but may not be in type definitions)
73
+ this.neurolink.setToolContext(toolContext);
74
+ // Update session metadata
75
+ this.sessionManager.updateMetadata(sessionId, {
76
+ aiProvider: this.config.ai.provider,
77
+ aiModel: this.config.ai.model,
78
+ });
79
+ // Execute autonomous AI review
80
+ console.log("🤖 Starting autonomous AI review...");
81
+ console.log(" AI will now make decisions and execute actions autonomously\n");
82
+ const aiResponse = await this.neurolink.generate({
83
+ input: { text: instructions },
84
+ provider: this.config.ai.provider,
85
+ model: this.config.ai.model,
86
+ temperature: this.config.ai.temperature,
87
+ maxTokens: this.config.ai.maxTokens,
88
+ timeout: this.config.ai.timeout,
89
+ context: {
90
+ sessionId,
91
+ userId: this.generateUserId(request),
92
+ operation: "code-review",
93
+ metadata: toolContext.metadata,
94
+ },
95
+ enableAnalytics: this.config.ai.enableAnalytics,
96
+ enableEvaluation: this.config.ai.enableEvaluation,
97
+ });
98
+ // Extract and parse results
99
+ const result = this.parseReviewResult(aiResponse, startTime, sessionId);
100
+ // Update session with results
101
+ this.sessionManager.completeSession(sessionId, result);
102
+ this.logReviewComplete(result);
103
+ return result;
104
+ }
105
+ catch (error) {
106
+ this.sessionManager.failSession(sessionId, error);
107
+ console.error("\n❌ Review failed:", error.message);
108
+ throw error;
109
+ }
110
+ }
111
+ /**
112
+ * Stream review with real-time updates (for verbose mode)
113
+ */
114
+ async *streamReview(request) {
115
+ await this.ensureInitialized();
116
+ const sessionId = this.sessionManager.createSession(request);
117
+ try {
118
+ // Build instructions
119
+ const instructions = await this.promptBuilder.buildReviewInstructions(request, this.config);
120
+ // Create tool context
121
+ const toolContext = this.createToolContext(sessionId, request);
122
+ this.neurolink.setToolContext(toolContext);
123
+ // Stream AI execution
124
+ yield {
125
+ type: "progress",
126
+ timestamp: new Date().toISOString(),
127
+ sessionId,
128
+ data: {
129
+ phase: "context_gathering",
130
+ progress: 0,
131
+ message: "Starting review...",
132
+ },
133
+ };
134
+ // Note: NeuroLink streaming implementation depends on version
135
+ // This is a placeholder for streaming functionality
136
+ const aiResponse = await this.neurolink.generate({
137
+ input: { text: instructions },
138
+ provider: this.config.ai.provider,
139
+ model: this.config.ai.model,
140
+ context: {
141
+ sessionId,
142
+ userId: this.generateUserId(request),
143
+ },
144
+ enableAnalytics: true,
145
+ });
146
+ yield {
147
+ type: "progress",
148
+ timestamp: new Date().toISOString(),
149
+ sessionId,
150
+ data: {
151
+ phase: "decision_making",
152
+ progress: 100,
153
+ message: "Review complete",
154
+ },
155
+ };
156
+ }
157
+ catch (error) {
158
+ this.sessionManager.failSession(sessionId, error);
159
+ throw error;
160
+ }
161
+ }
162
+ /**
163
+ * Start review and then enhance description in the same session
164
+ * This allows the AI to use knowledge gained during review to write better descriptions
165
+ */
166
+ async startReviewAndEnhance(request) {
167
+ await this.ensureInitialized();
168
+ const startTime = Date.now();
169
+ const sessionId = this.sessionManager.createSession(request);
170
+ this.logReviewStart(request, sessionId);
171
+ try {
172
+ // ========================================================================
173
+ // PHASE 1: Code Review
174
+ // ========================================================================
175
+ // Build review instructions
176
+ const reviewInstructions = await this.promptBuilder.buildReviewInstructions(request, this.config);
177
+ if (this.config.display.verboseToolCalls) {
178
+ console.log("\n📝 Review instructions built:");
179
+ console.log(` Instruction length: ${reviewInstructions.length} characters\n`);
180
+ }
181
+ // Create tool context
182
+ const toolContext = this.createToolContext(sessionId, request);
183
+ this.neurolink.setToolContext(toolContext);
184
+ // Update session metadata
185
+ this.sessionManager.updateMetadata(sessionId, {
186
+ aiProvider: this.config.ai.provider,
187
+ aiModel: this.config.ai.model,
188
+ });
189
+ // Execute review
190
+ console.log("🤖 Phase 1: Starting autonomous AI code review...");
191
+ console.log(" AI will analyze files and post comments\n");
192
+ const reviewResponse = await this.neurolink.generate({
193
+ input: { text: reviewInstructions },
194
+ provider: this.config.ai.provider,
195
+ model: this.config.ai.model,
196
+ temperature: this.config.ai.temperature,
197
+ maxTokens: this.config.ai.maxTokens,
198
+ timeout: this.config.ai.timeout,
199
+ context: {
200
+ sessionId,
201
+ userId: this.generateUserId(request),
202
+ operation: "code-review",
203
+ metadata: toolContext.metadata,
204
+ },
205
+ enableAnalytics: this.config.ai.enableAnalytics,
206
+ enableEvaluation: this.config.ai.enableEvaluation,
207
+ });
208
+ // Parse review results
209
+ const reviewResult = this.parseReviewResult(reviewResponse, startTime, sessionId);
210
+ console.log("\n✅ Phase 1 complete: Code review finished");
211
+ console.log(` Decision: ${reviewResult.decision}`);
212
+ console.log(` Comments: ${reviewResult.statistics.totalComments}\n`);
213
+ // ========================================================================
214
+ // PHASE 2: Description Enhancement (using same session)
215
+ // ========================================================================
216
+ if (this.config.descriptionEnhancement.enabled) {
217
+ console.log("📝 Phase 2: Enhancing PR description...");
218
+ console.log(" AI will use review insights to write description\n");
219
+ const enhanceInstructions = await this.promptBuilder.buildDescriptionEnhancementInstructions(request, this.config);
220
+ // Continue the SAME session - AI remembers everything from review
221
+ const enhanceResponse = await this.neurolink.generate({
222
+ input: { text: enhanceInstructions },
223
+ provider: this.config.ai.provider,
224
+ model: this.config.ai.model,
225
+ temperature: this.config.ai.temperature,
226
+ maxTokens: this.config.ai.maxTokens,
227
+ timeout: this.config.ai.timeout,
228
+ context: {
229
+ sessionId, // SAME sessionId = AI remembers review context
230
+ userId: this.generateUserId(request),
231
+ operation: "description-enhancement",
232
+ metadata: toolContext.metadata,
233
+ },
234
+ enableAnalytics: this.config.ai.enableAnalytics,
235
+ enableEvaluation: this.config.ai.enableEvaluation,
236
+ });
237
+ console.log("✅ Phase 2 complete: Description enhanced\n");
238
+ // Add enhancement status to result
239
+ reviewResult.descriptionEnhanced = true;
240
+ }
241
+ else {
242
+ console.log("⏭️ Skipping description enhancement (disabled in config)\n");
243
+ reviewResult.descriptionEnhanced = false;
244
+ }
245
+ // Update session with final results
246
+ this.sessionManager.completeSession(sessionId, reviewResult);
247
+ this.logReviewComplete(reviewResult);
248
+ return reviewResult;
249
+ }
250
+ catch (error) {
251
+ this.sessionManager.failSession(sessionId, error);
252
+ console.error("\n❌ Review failed:", error.message);
253
+ throw error;
254
+ }
255
+ }
256
+ /**
257
+ * Enhance PR description only (without full review)
258
+ */
259
+ async enhanceDescription(request) {
260
+ await this.ensureInitialized();
261
+ const sessionId = this.sessionManager.createSession(request);
262
+ try {
263
+ console.log("\n📝 Enhancing PR description...\n");
264
+ const instructions = await this.promptBuilder.buildDescriptionEnhancementInstructions(request, this.config);
265
+ const toolContext = this.createToolContext(sessionId, request);
266
+ this.neurolink.setToolContext(toolContext);
267
+ const aiResponse = await this.neurolink.generate({
268
+ input: { text: instructions },
269
+ provider: this.config.ai.provider,
270
+ model: this.config.ai.model,
271
+ context: {
272
+ sessionId,
273
+ userId: this.generateUserId(request),
274
+ operation: "description-enhancement",
275
+ },
276
+ enableAnalytics: true,
277
+ });
278
+ console.log("✅ Description enhanced successfully\n");
279
+ return {
280
+ success: true,
281
+ enhanced: true,
282
+ sessionId,
283
+ };
284
+ }
285
+ catch (error) {
286
+ this.sessionManager.failSession(sessionId, error);
287
+ throw error;
288
+ }
289
+ }
290
+ /**
291
+ * Get session information
292
+ */
293
+ getSession(sessionId) {
294
+ return this.sessionManager.getSession(sessionId);
295
+ }
296
+ /**
297
+ * Get session statistics
298
+ */
299
+ getSessionStats(sessionId) {
300
+ return this.sessionManager.getSessionStats(sessionId);
301
+ }
302
+ /**
303
+ * Export session data
304
+ */
305
+ exportSession(sessionId) {
306
+ return this.sessionManager.exportSession(sessionId);
307
+ }
308
+ /**
309
+ * Create tool context for AI
310
+ */
311
+ createToolContext(sessionId, request) {
312
+ return {
313
+ sessionId,
314
+ workspace: request.workspace,
315
+ repository: request.repository,
316
+ pullRequestId: request.pullRequestId,
317
+ branch: request.branch,
318
+ dryRun: request.dryRun || false,
319
+ metadata: {
320
+ yamaVersion: "2.0.0",
321
+ startTime: new Date().toISOString(),
322
+ },
323
+ };
324
+ }
325
+ /**
326
+ * Parse AI response into structured review result
327
+ */
328
+ parseReviewResult(aiResponse, startTime, sessionId) {
329
+ const session = this.sessionManager.getSession(sessionId);
330
+ const duration = Math.round((Date.now() - startTime) / 1000);
331
+ // Extract decision from AI response or tool calls
332
+ const decision = this.extractDecision(aiResponse, session);
333
+ // Calculate statistics from session tool calls
334
+ const statistics = this.calculateStatistics(session);
335
+ return {
336
+ prId: session.request.pullRequestId || 0,
337
+ decision,
338
+ statistics,
339
+ summary: this.extractSummary(aiResponse),
340
+ duration,
341
+ tokenUsage: {
342
+ input: aiResponse.usage?.inputTokens || 0,
343
+ output: aiResponse.usage?.outputTokens || 0,
344
+ total: aiResponse.usage?.totalTokens || 0,
345
+ },
346
+ costEstimate: this.calculateCost(aiResponse.usage),
347
+ sessionId,
348
+ };
349
+ }
350
+ /**
351
+ * Extract decision from AI response
352
+ */
353
+ extractDecision(aiResponse, session) {
354
+ // Check if AI called approve_pull_request or request_changes
355
+ const toolCalls = session.toolCalls || [];
356
+ const approveCall = toolCalls.find((tc) => tc.toolName === "approve_pull_request");
357
+ const requestChangesCall = toolCalls.find((tc) => tc.toolName === "request_changes");
358
+ if (approveCall) {
359
+ return "APPROVED";
360
+ }
361
+ if (requestChangesCall) {
362
+ return "BLOCKED";
363
+ }
364
+ // Default to changes requested if unclear
365
+ return "CHANGES_REQUESTED";
366
+ }
367
+ /**
368
+ * Calculate statistics from session
369
+ */
370
+ calculateStatistics(session) {
371
+ const toolCalls = session.toolCalls || [];
372
+ // Count file diffs read
373
+ const filesReviewed = toolCalls.filter((tc) => tc.toolName === "get_pull_request_diff").length;
374
+ // Try to extract issue counts from comments
375
+ const commentCalls = toolCalls.filter((tc) => tc.toolName === "add_comment");
376
+ const issuesFound = this.extractIssueCountsFromComments(commentCalls);
377
+ return {
378
+ filesReviewed,
379
+ issuesFound,
380
+ requirementCoverage: 0, // Would need to parse from Jira comparison
381
+ codeQualityScore: 0, // Would need AI to provide this
382
+ toolCallsMade: toolCalls.length,
383
+ cacheHits: 0,
384
+ totalComments: commentCalls.length,
385
+ };
386
+ }
387
+ /**
388
+ * Extract issue counts from comment tool calls
389
+ */
390
+ extractIssueCountsFromComments(commentCalls) {
391
+ const counts = {
392
+ critical: 0,
393
+ major: 0,
394
+ minor: 0,
395
+ suggestions: 0,
396
+ };
397
+ commentCalls.forEach((call) => {
398
+ const text = call.args?.comment_text || "";
399
+ if (text.includes("🔒 CRITICAL") || text.includes("CRITICAL:")) {
400
+ counts.critical++;
401
+ }
402
+ else if (text.includes("⚠️ MAJOR") || text.includes("MAJOR:")) {
403
+ counts.major++;
404
+ }
405
+ else if (text.includes("💡 MINOR") || text.includes("MINOR:")) {
406
+ counts.minor++;
407
+ }
408
+ else if (text.includes("💬 SUGGESTION") ||
409
+ text.includes("SUGGESTION:")) {
410
+ counts.suggestions++;
411
+ }
412
+ });
413
+ return counts;
414
+ }
415
+ /**
416
+ * Extract summary from AI response
417
+ */
418
+ extractSummary(aiResponse) {
419
+ return aiResponse.content || aiResponse.text || "Review completed";
420
+ }
421
+ /**
422
+ * Calculate cost estimate from token usage
423
+ */
424
+ calculateCost(usage) {
425
+ if (!usage) {
426
+ return 0;
427
+ }
428
+ // Rough estimates (update with actual pricing)
429
+ const inputCostPer1M = 0.25; // $0.25 per 1M input tokens (Gemini 2.0 Flash)
430
+ const outputCostPer1M = 1.0; // $1.00 per 1M output tokens
431
+ const inputCost = (usage.inputTokens / 1_000_000) * inputCostPer1M;
432
+ const outputCost = (usage.outputTokens / 1_000_000) * outputCostPer1M;
433
+ return Number((inputCost + outputCost).toFixed(4));
434
+ }
435
+ /**
436
+ * Generate userId for NeuroLink context from repository and branch/PR
437
+ */
438
+ generateUserId(request) {
439
+ const repo = request.repository;
440
+ const identifier = request.branch || `pr-${request.pullRequestId}`;
441
+ return `${repo}-${identifier}`;
442
+ }
443
+ /**
444
+ * Initialize NeuroLink with observability configuration
445
+ */
446
+ initializeNeurolink() {
447
+ try {
448
+ const observabilityConfig = buildObservabilityConfigFromEnv();
449
+ const neurolinkConfig = {
450
+ conversationMemory: this.config.ai.conversationMemory,
451
+ };
452
+ if (observabilityConfig) {
453
+ // Validate observability config
454
+ if (!validateObservabilityConfig(observabilityConfig)) {
455
+ throw new Error("Invalid observability configuration");
456
+ }
457
+ neurolinkConfig.observability = observabilityConfig;
458
+ console.log(" 📊 Observability enabled (Langfuse tracing active)");
459
+ }
460
+ else {
461
+ console.log(" 📊 Observability not configured (set LANGFUSE_* env vars to enable)");
462
+ }
463
+ const neurolink = new NeuroLink(neurolinkConfig);
464
+ return neurolink;
465
+ }
466
+ catch (error) {
467
+ console.error("❌ Failed to initialize NeuroLink:", error.message);
468
+ throw new Error(`NeuroLink initialization failed: ${error}`);
469
+ }
470
+ }
471
+ /**
472
+ * Ensure orchestrator is initialized
473
+ */
474
+ async ensureInitialized() {
475
+ if (!this.initialized) {
476
+ await this.initialize();
477
+ }
478
+ }
479
+ /**
480
+ * Show Yama V2 banner
481
+ */
482
+ showBanner() {
483
+ if (!this.config?.display?.showBanner) {
484
+ return;
485
+ }
486
+ console.log("\n" + "═".repeat(60));
487
+ console.log(`
488
+ ⚔️ YAMA V2 - AI-Native Code Review Guardian
489
+
490
+ Version: 2.0.0
491
+ Mode: Autonomous AI-Powered Review
492
+ Powered by: NeuroLink + MCP Tools
493
+ `);
494
+ console.log("═".repeat(60) + "\n");
495
+ }
496
+ /**
497
+ * Log review start
498
+ */
499
+ logReviewStart(request, sessionId) {
500
+ console.log("\n" + "─".repeat(60));
501
+ console.log(`📋 Review Session Started`);
502
+ console.log("─".repeat(60));
503
+ console.log(` Session ID: ${sessionId}`);
504
+ console.log(` Workspace: ${request.workspace}`);
505
+ console.log(` Repository: ${request.repository}`);
506
+ console.log(` PR: ${request.pullRequestId || request.branch}`);
507
+ console.log(` Mode: ${request.dryRun ? "🔵 DRY RUN" : "🔴 LIVE"}`);
508
+ console.log("─".repeat(60) + "\n");
509
+ }
510
+ /**
511
+ * Log review completion
512
+ */
513
+ logReviewComplete(result) {
514
+ console.log("\n" + "═".repeat(60));
515
+ console.log(`✅ Review Completed Successfully`);
516
+ console.log("═".repeat(60));
517
+ console.log(` Decision: ${this.formatDecision(result.decision)}`);
518
+ console.log(` Duration: ${result.duration}s`);
519
+ console.log(` Files Reviewed: ${result.statistics.filesReviewed}`);
520
+ console.log(` Issues Found:`);
521
+ console.log(` 🔒 CRITICAL: ${result.statistics.issuesFound.critical}`);
522
+ console.log(` ⚠️ MAJOR: ${result.statistics.issuesFound.major}`);
523
+ console.log(` 💡 MINOR: ${result.statistics.issuesFound.minor}`);
524
+ console.log(` 💬 SUGGESTIONS: ${result.statistics.issuesFound.suggestions}`);
525
+ console.log(` Token Usage: ${result.tokenUsage.total.toLocaleString()}`);
526
+ console.log(` Cost Estimate: $${result.costEstimate.toFixed(4)}`);
527
+ console.log("═".repeat(60) + "\n");
528
+ }
529
+ /**
530
+ * Format decision for display
531
+ */
532
+ formatDecision(decision) {
533
+ switch (decision) {
534
+ case "APPROVED":
535
+ return "✅ APPROVED";
536
+ case "BLOCKED":
537
+ return "🚫 BLOCKED";
538
+ case "CHANGES_REQUESTED":
539
+ return "⚠️ CHANGES REQUESTED";
540
+ default:
541
+ return decision;
542
+ }
543
+ }
544
+ }
545
+ // Export factory function
546
+ export function createYamaV2() {
547
+ return new YamaV2Orchestrator();
548
+ }
549
+ //# sourceMappingURL=YamaV2Orchestrator.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Base Enhancement System Prompt
3
+ * Generic, project-agnostic instructions for PR description enhancement
4
+ * Project-specific sections and requirements come from config
5
+ */
6
+ export declare const ENHANCEMENT_SYSTEM_PROMPT = "\n<yama-enhancement-system>\n <identity>\n <role>Technical Documentation Writer</role>\n <focus>Complete PR descriptions with comprehensive, accurate information</focus>\n </identity>\n\n <core-rules>\n <rule priority=\"CRITICAL\" id=\"complete-all-sections\">\n <title>Complete All Required Sections</title>\n <description>\n Fill every required section defined in project configuration.\n For sections that don't apply: explain why with \"Not applicable because {reason}\".\n Never leave sections empty or use generic \"N/A\".\n </description>\n </rule>\n\n <rule priority=\"CRITICAL\" id=\"extract-from-code\">\n <title>Extract Information from Code Changes</title>\n <description>\n Analyze the diff to find configuration changes, API modifications, dependencies.\n Use search_code() to find patterns in the codebase.\n Document what actually changed, not assumptions.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"structured-output\">\n <title>Follow Section Structure</title>\n <description>\n Use exact section headers from configuration.\n Maintain consistent formatting.\n Use markdown for readability.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"clean-output\">\n <title>Clean Output Only</title>\n <description>\n Return ONLY the enhanced PR description content.\n Do NOT include meta-commentary like \"Here is...\" or explanations.\n Start directly with the enhanced content.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"preserve-existing\">\n <title>Preserve User Content When Possible</title>\n <description>\n If preserveContent is enabled, merge existing description with enhancements.\n Don't overwrite manually written sections unless improving them.\n </description>\n </rule>\n </core-rules>\n\n <workflow>\n <phase name=\"analysis\">\n <step>Read PR diff to understand all changes</step>\n <step>Use search_code() to find configuration patterns</step>\n <step>Identify files modified, APIs changed, dependencies added</step>\n <step>Extract information for each required section</step>\n </phase>\n\n <phase name=\"extraction\">\n <step>For each required section from config:</step>\n <step>- Extract relevant information from diff and codebase</step>\n <step>- Use search_code() if patterns need to be found</step>\n <step>- If not applicable: write clear reason why</step>\n </phase>\n\n <phase name=\"composition\">\n <step>Build description with all sections in order</step>\n <step>Verify completeness against config requirements</step>\n <step>Format as clean markdown</step>\n <step>Ensure no meta-commentary included</step>\n </phase>\n\n <phase name=\"update\">\n <step>Call update_pull_request() with enhanced description</step>\n </phase>\n </workflow>\n\n <tools>\n <tool name=\"get_pull_request\">\n <purpose>Get current PR description and context</purpose>\n <usage>Read existing description to preserve user content</usage>\n </tool>\n\n <tool name=\"get_pull_request_diff\">\n <purpose>Analyze code changes to extract information</purpose>\n <usage>Find what files changed, what was modified</usage>\n </tool>\n\n <tool name=\"search_code\">\n <purpose>Find patterns, configurations, similar implementations</purpose>\n <examples>\n <example>Search for configuration getters to find config keys</example>\n <example>Search for API endpoint definitions</example>\n <example>Search for test file patterns</example>\n <example>Search for environment variable usage</example>\n <example>Search for database migration patterns</example>\n </examples>\n </tool>\n\n <tool name=\"list_directory_content\">\n <purpose>Understand project structure</purpose>\n <usage>Find related files, understand organization</usage>\n </tool>\n\n <tool name=\"get_file_content\">\n <purpose>Read specific files for context</purpose>\n <usage>Read config files, package.json, migration files</usage>\n </tool>\n\n <tool name=\"update_pull_request\">\n <purpose>Update PR description with enhanced content</purpose>\n <parameters>\n <param name=\"description\">Enhanced markdown description</param>\n </parameters>\n </tool>\n </tools>\n\n <section-completion-guide>\n <guideline>For applicable sections: Be specific and detailed</guideline>\n <guideline>For non-applicable sections: Write \"Not applicable for this PR because {specific reason}\"</guideline>\n <guideline>Never use generic \"N/A\" without explanation</guideline>\n <guideline>Link changes to business/technical value</guideline>\n <guideline>Include file references where relevant (e.g., \"Modified src/auth/Login.tsx\")</guideline>\n <guideline>Use lists and checkboxes for better readability</guideline>\n </section-completion-guide>\n\n <extraction-strategies>\n <strategy name=\"configuration-changes\">\n <description>How to find and document configuration changes</description>\n <steps>\n <step>Search diff for configuration file changes (config.yaml, .env.example, etc.)</step>\n <step>Use search_code() to find configuration getters in code</step>\n <step>Document key names and their purpose</step>\n <step>Explain impact of configuration changes</step>\n </steps>\n </strategy>\n\n <strategy name=\"api-modifications\">\n <description>How to identify API changes</description>\n <steps>\n <step>Look for route definitions, endpoint handlers in diff</step>\n <step>Search for API client calls, fetch/axios usage</step>\n <step>Document endpoints added/modified/removed</step>\n <step>Note request/response format changes</step>\n </steps>\n </strategy>\n\n <strategy name=\"database-changes\">\n <description>How to find database alterations</description>\n <steps>\n <step>Look for migration files in diff</step>\n <step>Search for schema definitions, model changes</step>\n <step>Document table/column changes</step>\n <step>Note any data migration requirements</step>\n </steps>\n </strategy>\n\n <strategy name=\"dependency-changes\">\n <description>How to document library updates</description>\n <steps>\n <step>Check package.json, requirements.txt, etc. in diff</step>\n <step>Document added/updated/removed dependencies</step>\n <step>Note version changes and breaking changes</step>\n <step>Explain why dependency was added/updated</step>\n </steps>\n </strategy>\n\n <strategy name=\"testing-coverage\">\n <description>How to document testing</description>\n <steps>\n <step>Look for test files in diff (*.test.*, *.spec.*)</step>\n <step>Document test scenarios covered</step>\n <step>Note integration/unit/e2e tests added</step>\n <step>Create testing checklist for reviewers</step>\n </steps>\n </strategy>\n </extraction-strategies>\n\n <output-format>\n <requirement>Return enhanced description as clean markdown</requirement>\n <requirement>No meta-commentary or wrapper text</requirement>\n <requirement>Start directly with section headers</requirement>\n <requirement>Use consistent formatting throughout</requirement>\n <requirement>Follow section order from configuration</requirement>\n </output-format>\n\n <formatting-guidelines>\n <guideline>Use ## for section headers</guideline>\n <guideline>Use - or * for bulleted lists</guideline>\n <guideline>Use - [ ] for checkboxes in test cases</guideline>\n <guideline>Use `code` for inline code references</guideline>\n <guideline>Use ```language for code blocks</guideline>\n <guideline>Use **bold** for emphasis on important items</guideline>\n <guideline>Use tables for structured data when appropriate</guideline>\n </formatting-guidelines>\n\n <anti-patterns>\n <dont>Start with \"Here is the enhanced description...\"</dont>\n <dont>Include explanatory wrapper text</dont>\n <dont>Use generic \"N/A\" without explanation</dont>\n <dont>Skip sections even if they seem not applicable</dont>\n <dont>Make assumptions - verify with code search</dont>\n <dont>Copy code changes verbatim - summarize meaningfully</dont>\n </anti-patterns>\n</yama-enhancement-system>\n";
7
+ export default ENHANCEMENT_SYSTEM_PROMPT;
8
+ //# sourceMappingURL=EnhancementSystemPrompt.d.ts.map