@entro314labs/ai-changelog-generator 3.2.1 → 3.3.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 (32) hide show
  1. package/ai-changelog-mcp.sh +0 -0
  2. package/ai-changelog.sh +0 -0
  3. package/bin/ai-changelog-dxt.js +0 -0
  4. package/package.json +72 -80
  5. package/src/ai-changelog-generator.js +5 -4
  6. package/src/application/orchestrators/changelog.orchestrator.js +12 -202
  7. package/src/cli.js +4 -5
  8. package/src/domains/ai/ai-analysis.service.js +2 -0
  9. package/src/domains/analysis/analysis.engine.js +714 -37
  10. package/src/domains/changelog/changelog.service.js +615 -30
  11. package/src/domains/changelog/workspace-changelog.service.js +418 -627
  12. package/src/domains/git/commit-tagger.js +552 -0
  13. package/src/domains/git/git-manager.js +357 -0
  14. package/src/domains/git/git.service.js +865 -16
  15. package/src/infrastructure/cli/cli.controller.js +14 -9
  16. package/src/infrastructure/config/configuration.manager.js +24 -2
  17. package/src/infrastructure/interactive/interactive-workflow.service.js +8 -1
  18. package/src/infrastructure/mcp/mcp-server.service.js +35 -11
  19. package/src/infrastructure/providers/core/base-provider.js +1 -1
  20. package/src/infrastructure/providers/implementations/anthropic.js +16 -173
  21. package/src/infrastructure/providers/implementations/azure.js +16 -63
  22. package/src/infrastructure/providers/implementations/dummy.js +13 -16
  23. package/src/infrastructure/providers/implementations/mock.js +13 -26
  24. package/src/infrastructure/providers/implementations/ollama.js +12 -4
  25. package/src/infrastructure/providers/implementations/openai.js +13 -165
  26. package/src/infrastructure/providers/provider-management.service.js +126 -412
  27. package/src/infrastructure/providers/utils/base-provider-helpers.js +11 -0
  28. package/src/shared/utils/cli-ui.js +1 -1
  29. package/src/shared/utils/diff-processor.js +21 -19
  30. package/src/shared/utils/error-classes.js +33 -0
  31. package/src/shared/utils/utils.js +65 -60
  32. package/src/domains/git/git-repository.analyzer.js +0 -678
@@ -16,18 +16,18 @@ export class DiffProcessor {
16
16
 
17
17
  getDefaultMaxSize() {
18
18
  const sizes = {
19
- standard: 12000,
20
- detailed: 20000,
21
- enterprise: 30000,
19
+ standard: 50000, // Increased from 12000 - modern LLMs can handle more
20
+ detailed: 80000, // Increased from 20000
21
+ enterprise: 120000, // Increased from 30000
22
22
  }
23
23
  return sizes[this.analysisMode] || sizes.standard
24
24
  }
25
25
 
26
26
  getDefaultPriorityFiles() {
27
27
  const counts = {
28
- standard: 15,
29
- detailed: 25,
30
- enterprise: 40,
28
+ standard: 30, // Increased from 15 - analyze more files in detail
29
+ detailed: 50, // Increased from 25
30
+ enterprise: 80, // Increased from 40
31
31
  }
32
32
  return counts[this.analysisMode] || counts.standard
33
33
  }
@@ -101,7 +101,7 @@ export class DiffProcessor {
101
101
  * Process a single file's diff with intelligent compression
102
102
  */
103
103
  processFileDiff(file, options = {}) {
104
- const { budget = 1500, patterns = {}, isHighPriority = false } = options
104
+ const { budget = 4000, patterns = {}, isHighPriority = false } = options // Increased from 1500
105
105
 
106
106
  if (!file.diff || file.diff === 'No diff available') {
107
107
  return {
@@ -119,17 +119,18 @@ export class DiffProcessor {
119
119
  processedDiff = this.applyDiffFiltering(processedDiff, file)
120
120
  }
121
121
 
122
- // Check if file matches bulk patterns
123
- const patternMatch = this.matchesBulkPattern(file, patterns)
124
- if (patternMatch) {
125
- return {
126
- ...file,
127
- diff: `[Bulk ${patternMatch.type}]: ${patternMatch.description}`,
128
- processed: true,
129
- compressionApplied: true,
130
- bulkPattern: patternMatch.type,
131
- }
132
- }
122
+ // Temporarily disable bulk pattern matching to preserve more detail
123
+ // TODO: Make this smarter - only apply to truly repetitive patterns
124
+ // const patternMatch = this.matchesBulkPattern(file, patterns)
125
+ // if (patternMatch) {
126
+ // return {
127
+ // ...file,
128
+ // diff: `[Bulk ${patternMatch.type}]: ${patternMatch.description}`,
129
+ // processed: true,
130
+ // compressionApplied: true,
131
+ // bulkPattern: patternMatch.type,
132
+ // }
133
+ // }
133
134
 
134
135
  // Apply intelligent truncation if still too large
135
136
  if (processedDiff.length > budget) {
@@ -313,7 +314,8 @@ export class DiffProcessor {
313
314
  return trimmed.match(/^(import|require|from\s+['"])/)
314
315
  })
315
316
 
316
- if (importLines.length > 10) {
317
+ if (importLines.length > 25) {
318
+ // Increased threshold from 10 to 25
317
319
  // If many import changes, summarize them
318
320
  filteredDiff = filteredDiff.replace(/^[+-]\s*(import|require|from\s+['"]).*$/gm, '')
319
321
  filteredDiff = `[${importLines.length} import/require changes summarized]\n${filteredDiff}`
@@ -355,6 +355,39 @@ export class NetworkError extends AIChangelogError {
355
355
  }
356
356
  }
357
357
 
358
+ /**
359
+ * Parse error for malformed data/responses
360
+ */
361
+ export class ParseError extends Error {
362
+ constructor(message, data = null, originalError = null) {
363
+ super(message)
364
+ this.name = 'ParseError'
365
+ this.data = data
366
+ this.originalError = originalError
367
+
368
+ if (Error.captureStackTrace) {
369
+ Error.captureStackTrace(this, ParseError)
370
+ }
371
+ }
372
+ }
373
+
374
+ /**
375
+ * Concurrency limit error for resource management
376
+ */
377
+ export class ConcurrencyLimitError extends Error {
378
+ constructor(message, limit, active, originalError = null) {
379
+ super(message)
380
+ this.name = 'ConcurrencyLimitError'
381
+ this.limit = limit
382
+ this.active = active
383
+ this.originalError = originalError
384
+
385
+ if (Error.captureStackTrace) {
386
+ Error.captureStackTrace(this, ConcurrencyLimitError)
387
+ }
388
+ }
389
+ }
390
+
358
391
  /**
359
392
  * Error context builder utility
360
393
  */
@@ -17,57 +17,12 @@ import fs from 'node:fs'
17
17
 
18
18
  import colors from '../constants/colors.js'
19
19
  import { DiffProcessor } from './diff-processor.js'
20
+ import { AbstractMethodError, AIChangelogError, ProviderError } from './error-classes.js'
20
21
  import JsonUtils from './json-utils.js'
21
22
 
22
- // ========================================
23
- // ERROR HANDLING UTILITIES
24
- // ========================================
25
-
26
- /**
27
- * Base error class for domain-specific errors
28
- */
29
- export class AIChangelogError extends Error {
30
- constructor(message, type, context = {}, originalError = null) {
31
- super(message)
32
- this.name = this.constructor.name
33
- this.type = type
34
- this.context = context
35
- this.originalError = originalError
36
- this.timestamp = new Date().toISOString()
37
- }
38
-
39
- toJSON() {
40
- return {
41
- name: this.name,
42
- message: this.message,
43
- type: this.type,
44
- context: this.context,
45
- timestamp: this.timestamp,
46
- stack: this.stack,
47
- }
48
- }
49
- }
50
-
51
- /**
52
- * Abstract method error for base classes
53
- */
54
- export class AbstractMethodError extends AIChangelogError {
55
- constructor(message, className, methodName, context = {}) {
56
- super(message, 'abstract', { className, methodName, ...context })
57
- this.className = className
58
- this.methodName = methodName
59
- }
60
- }
61
-
62
- /**
63
- * Provider-specific error
64
- */
65
- export class ProviderError extends AIChangelogError {
66
- constructor(message, providerName, context = {}, originalError = null) {
67
- super(message, 'provider', { providerName, ...context }, originalError)
68
- this.providerName = providerName
69
- }
70
- }
23
+ // Note: Error classes have been moved to './error-classes.js' to avoid duplication
24
+ // and provide better organization. Import them from there instead of defining here.
25
+ export { AbstractMethodError, AIChangelogError, ProviderError }
71
26
 
72
27
  // ========================================
73
28
  // DATA MANIPULATION UTILITIES
@@ -1110,9 +1065,22 @@ export function buildEnhancedPrompt(commitAnalysis, analysisMode = 'standard') {
1110
1065
  riskAssessment = {},
1111
1066
  } = commitAnalysis
1112
1067
 
1113
- // Initialize DiffProcessor with analysis mode
1068
+ // Detect merge commits and upgrade analysis mode for better specificity
1069
+ const isMergeCommit = subject && subject.toLowerCase().includes('merge')
1070
+ const effectiveAnalysisMode = isMergeCommit && files.length > 10 ? 'detailed' : analysisMode
1071
+
1072
+ // Debug logging for merge commits (disabled)
1073
+ // if (isMergeCommit) {
1074
+ // console.log('\n=== MERGE COMMIT DEBUG (EARLY) ===')
1075
+ // console.log('Subject:', subject)
1076
+ // console.log('Files count:', files.length)
1077
+ // console.log('Effective analysis mode:', effectiveAnalysisMode)
1078
+ // console.log('=== END EARLY DEBUG ===\n')
1079
+ // }
1080
+
1081
+ // Initialize DiffProcessor with effective analysis mode
1114
1082
  const diffProcessor = new DiffProcessor({
1115
- analysisMode,
1083
+ analysisMode: effectiveAnalysisMode,
1116
1084
  enableFiltering: true,
1117
1085
  enablePatternDetection: true,
1118
1086
  })
@@ -1148,10 +1116,41 @@ export function buildEnhancedPrompt(commitAnalysis, analysisMode = 'standard') {
1148
1116
  })
1149
1117
  .join('')
1150
1118
 
1119
+ // Check if we have enhanced merge summary from GitService (isMergeCommit already detected above)
1120
+ const enhancedMergeSummary =
1121
+ files.length > 0 && files[0].enhancedMergeSummary ? files[0].enhancedMergeSummary : null
1122
+
1151
1123
  const prompt = `Analyze this git commit for changelog generation.
1152
1124
 
1153
- **COMMIT:** ${subject}
1154
- **FILES:** ${files.length} files (${filesProcessed} analyzed, ${filesSkipped} summarized), ${insertions + deletions} lines changed${patternSummary}
1125
+ **COMMIT:** ${subject}${isMergeCommit ? ' (MERGE COMMIT - categorize as "merge")' : ''}
1126
+ **FILES:** ${files.length} files (${filesProcessed} analyzed, ${filesSkipped} summarized), ${insertions + deletions} lines changed${patternSummary}${
1127
+ enhancedMergeSummary
1128
+ ? `
1129
+
1130
+ **ENHANCED MERGE SUMMARY:**
1131
+ ${enhancedMergeSummary}
1132
+
1133
+ **IMPORTANT FOR MERGE COMMITS:** Use the above enhanced summary as your description. Do NOT create a generic summary. Instead, convert the bullet points above into a flowing description that includes the specific file names, numbers, and technical details provided.`
1134
+ : ''
1135
+ }
1136
+
1137
+ // Debug logging for merge commits with "pull request"
1138
+ if (isMergeCommit && subject.includes('pull request')) {
1139
+ try {
1140
+ const fs = require('fs')
1141
+ const debugContent = '=== EXACT AI INPUT FOR fd97ab7 ===\n' +
1142
+ 'SUBJECT: ' + subject + '\n' +
1143
+ 'FILES COUNT: ' + files.length + '\n' +
1144
+ 'ENHANCED MERGE SUMMARY:\n' + (enhancedMergeSummary || 'None') + '\n\n' +
1145
+ 'FILES SECTION (first 3000 chars):\n' + filesSection.substring(0, 3000) + '\n\n' +
1146
+ 'FULL PROMPT PREVIEW:\n' + prompt.substring(0, 2000) + '\n=== END DEBUG ==='
1147
+
1148
+ fs.writeFileSync('AI_INPUT_DEBUG.txt', debugContent)
1149
+ console.log('*** AI INPUT SAVED TO AI_INPUT_DEBUG.txt ***')
1150
+ } catch (error) {
1151
+ console.log('DEBUG ERROR:', error.message)
1152
+ }
1153
+ }
1155
1154
 
1156
1155
  **TARGET AUDIENCE:** End users and project stakeholders who need to understand what changed and why it matters.
1157
1156
 
@@ -1161,30 +1160,36 @@ export function buildEnhancedPrompt(commitAnalysis, analysisMode = 'standard') {
1161
1160
  1. **First, categorize correctly** using the rules below
1162
1161
  2. **Then, focus on user impact** - what can they do now that they couldn't before?
1163
1162
  3. **Keep technical details minimal** - only what's necessary for understanding
1163
+ 4. **Be definitive and factual** - never use uncertain language like "likely", "probably", "appears to", "seems to", or "possibly"
1164
+ 5. **Base analysis on actual code changes** - only describe what you can verify from the diff content
1165
+ 6. **For merge commits** - ALWAYS categorize as "merge" regardless of content
1166
+ 7. **Use enhanced merge summary** - If an "ENHANCED MERGE SUMMARY" section is provided above, DO NOT analyze individual file diffs. Instead, directly incorporate the specific bullet points from the enhanced summary into your response. Use the exact technical details, file names, and numbers provided in the enhanced summary.
1164
1167
 
1165
1168
  **PROCESSED DIFFS:**${filesSection}
1166
1169
 
1167
1170
  **CATEGORIZATION RULES (STRICTLY ENFORCED):**
1171
+ - **merge**: Any commit with "Merge" in the subject line (branch merges, pull request merges)
1168
1172
  - **fix**: ONLY actual bug fixes - broken functionality now works correctly
1169
- - **feature**: New capabilities, tools, or major functionality additions
1173
+ - **feature**: New capabilities, tools, or major functionality additions (NOT merges)
1170
1174
  - **refactor**: Code restructuring without changing what users can do
1171
1175
  - **perf**: Performance improvements users will notice
1172
1176
  - **docs**: Documentation updates only
1173
1177
  - **build/chore**: Build system, dependencies, maintenance
1174
1178
 
1175
1179
  **CRITICAL VALIDATION:**
1176
- - Large additions (>10 files OR >1000 lines) = "feature" or "refactor", NEVER "fix"
1177
- - New modules/classes/tools = "feature"
1180
+ - Commits with "Merge" in subject = "merge" category ALWAYS
1181
+ - Large additions (>10 files OR >1000 lines) = "feature" or "refactor", NEVER "fix" (unless merge)
1182
+ - New modules/classes/tools = "feature" (unless merge)
1178
1183
  - Only actual bug repairs = "fix"
1179
1184
 
1180
- Provide a JSON response with ONLY these fields:
1185
+ Provide a JSON response with ONLY these fields (use definitive language - NO "likely", "probably", "appears", etc.):
1181
1186
  {
1182
1187
  "summary": "${subject}",
1183
1188
  "impact": "critical|high|medium|low|minimal",
1184
1189
  "category": "feature|fix|security|breaking|docs|style|refactor|perf|test|chore",
1185
- "description": "One clear sentence describing what users can now do (for features) or what now works correctly (for fixes)",
1186
- "technicalDetails": "Maximum 2 sentences about key technical changes - focus on the most important functions/modules/APIs added or modified",
1187
- "businessValue": "Brief user benefit in 1 sentence",
1190
+ "description": "One clear, factual sentence describing what users can now do (for features) or what now works correctly (for fixes)",
1191
+ "technicalDetails": "Maximum 2 factual sentences about key technical changes - focus on the most important functions/modules/APIs added or modified",
1192
+ "businessValue": "Brief, definitive user benefit in 1 sentence",
1188
1193
  "riskFactors": ["minimal", "list"],
1189
1194
  "recommendations": ["minimal", "list"],
1190
1195
  "breakingChanges": false,