@entro314labs/ai-changelog-generator 3.0.5 → 3.2.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 +383 -785
- package/README.md +30 -3
- package/ai-changelog-mcp.sh +0 -0
- package/ai-changelog.sh +0 -0
- package/bin/ai-changelog-dxt.js +9 -9
- package/bin/ai-changelog-mcp.js +19 -17
- package/bin/ai-changelog.js +6 -6
- package/package.json +84 -52
- package/src/ai-changelog-generator.js +83 -81
- package/src/application/orchestrators/changelog.orchestrator.js +1040 -296
- package/src/application/services/application.service.js +145 -123
- package/src/cli.js +76 -57
- package/src/domains/ai/ai-analysis.service.js +289 -209
- package/src/domains/analysis/analysis.engine.js +253 -193
- package/src/domains/changelog/changelog.service.js +1062 -784
- package/src/domains/changelog/workspace-changelog.service.js +420 -249
- package/src/domains/git/git-repository.analyzer.js +348 -258
- package/src/domains/git/git.service.js +132 -112
- package/src/infrastructure/cli/cli.controller.js +415 -247
- package/src/infrastructure/config/configuration.manager.js +220 -190
- package/src/infrastructure/interactive/interactive-staging.service.js +332 -0
- package/src/infrastructure/interactive/interactive-workflow.service.js +200 -159
- package/src/infrastructure/mcp/mcp-server.service.js +208 -207
- package/src/infrastructure/metrics/metrics.collector.js +140 -123
- package/src/infrastructure/providers/core/base-provider.js +87 -40
- package/src/infrastructure/providers/implementations/anthropic.js +101 -99
- package/src/infrastructure/providers/implementations/azure.js +124 -101
- package/src/infrastructure/providers/implementations/bedrock.js +136 -126
- package/src/infrastructure/providers/implementations/dummy.js +23 -23
- package/src/infrastructure/providers/implementations/google.js +123 -114
- package/src/infrastructure/providers/implementations/huggingface.js +94 -87
- package/src/infrastructure/providers/implementations/lmstudio.js +75 -60
- package/src/infrastructure/providers/implementations/mock.js +69 -73
- package/src/infrastructure/providers/implementations/ollama.js +89 -66
- package/src/infrastructure/providers/implementations/openai.js +88 -89
- package/src/infrastructure/providers/implementations/vertex.js +227 -197
- package/src/infrastructure/providers/provider-management.service.js +245 -207
- package/src/infrastructure/providers/provider-manager.service.js +145 -125
- package/src/infrastructure/providers/utils/base-provider-helpers.js +308 -302
- package/src/infrastructure/providers/utils/model-config.js +220 -195
- package/src/infrastructure/providers/utils/provider-utils.js +105 -100
- package/src/infrastructure/validation/commit-message-validation.service.js +556 -0
- package/src/shared/constants/colors.js +467 -172
- package/src/shared/utils/cli-demo.js +285 -0
- package/src/shared/utils/cli-entry-utils.js +257 -249
- package/src/shared/utils/cli-ui.js +447 -0
- package/src/shared/utils/diff-processor.js +513 -0
- package/src/shared/utils/error-classes.js +125 -156
- package/src/shared/utils/json-utils.js +93 -89
- package/src/shared/utils/utils.js +1299 -775
- package/types/index.d.ts +353 -344
|
@@ -1,201 +1,205 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import
|
|
1
|
+
import process from 'node:process'
|
|
2
|
+
|
|
3
|
+
import { ConfigurationManager } from '../../infrastructure/config/configuration.manager.js'
|
|
4
|
+
import colors from '../../shared/constants/colors.js'
|
|
5
|
+
import { ChangelogOrchestrator } from '../orchestrators/changelog.orchestrator.js'
|
|
4
6
|
|
|
5
7
|
export class ApplicationService {
|
|
6
8
|
constructor(options = {}) {
|
|
7
|
-
this.options = options
|
|
8
|
-
this.configManager = new ConfigurationManager()
|
|
9
|
-
this.orchestrator = new ChangelogOrchestrator(this.configManager, options)
|
|
10
|
-
this.initialized = false
|
|
11
|
-
|
|
9
|
+
this.options = options
|
|
10
|
+
this.configManager = new ConfigurationManager()
|
|
11
|
+
this.orchestrator = new ChangelogOrchestrator(this.configManager, options)
|
|
12
|
+
this.initialized = false
|
|
13
|
+
|
|
12
14
|
// Apply options
|
|
13
15
|
if (options.noColor || process.env.NO_COLOR) {
|
|
14
|
-
colors.disable()
|
|
16
|
+
colors.disable()
|
|
15
17
|
}
|
|
16
|
-
|
|
18
|
+
|
|
17
19
|
// Wait for orchestrator to initialize
|
|
18
|
-
this.initializeAsync()
|
|
20
|
+
this.initializeAsync()
|
|
19
21
|
}
|
|
20
|
-
|
|
22
|
+
|
|
21
23
|
async initializeAsync() {
|
|
22
24
|
try {
|
|
23
25
|
// Wait for orchestrator services to be ready
|
|
24
|
-
await this.orchestrator.ensureInitialized()
|
|
25
|
-
this.initialized = true
|
|
26
|
+
await this.orchestrator.ensureInitialized()
|
|
27
|
+
this.initialized = true
|
|
26
28
|
} catch (error) {
|
|
27
|
-
console.error(
|
|
29
|
+
console.error(
|
|
30
|
+
colors.errorMessage('Application service initialization failed:'),
|
|
31
|
+
error.message
|
|
32
|
+
)
|
|
28
33
|
}
|
|
29
34
|
}
|
|
30
|
-
|
|
35
|
+
|
|
31
36
|
async ensureInitialized() {
|
|
32
37
|
if (!this.initialized) {
|
|
33
|
-
await this.initializeAsync()
|
|
38
|
+
await this.initializeAsync()
|
|
34
39
|
}
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
async generateChangelog(options = {}) {
|
|
38
43
|
try {
|
|
39
|
-
const { version, since } = options
|
|
40
|
-
return await this.orchestrator.generateChangelog(version, since)
|
|
44
|
+
const { version, since } = options
|
|
45
|
+
return await this.orchestrator.generateChangelog(version, since)
|
|
41
46
|
} catch (error) {
|
|
42
|
-
console.error(colors.errorMessage('Application service error:'), error.message)
|
|
43
|
-
throw error
|
|
47
|
+
console.error(colors.errorMessage('Application service error:'), error.message)
|
|
48
|
+
throw error
|
|
44
49
|
}
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
async analyzeRepository(options = {}) {
|
|
48
53
|
try {
|
|
49
|
-
return await this.orchestrator.analyzeRepository(options)
|
|
54
|
+
return await this.orchestrator.analyzeRepository(options)
|
|
50
55
|
} catch (error) {
|
|
51
|
-
console.error(colors.errorMessage('Repository analysis error:'), error.message)
|
|
52
|
-
throw error
|
|
56
|
+
console.error(colors.errorMessage('Repository analysis error:'), error.message)
|
|
57
|
+
throw error
|
|
53
58
|
}
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
async analyzeCurrentChanges() {
|
|
57
62
|
try {
|
|
58
|
-
await this.ensureInitialized()
|
|
59
|
-
return await this.orchestrator.analyzeRepository({ type: 'changes' })
|
|
63
|
+
await this.ensureInitialized()
|
|
64
|
+
return await this.orchestrator.analyzeRepository({ type: 'changes' })
|
|
60
65
|
} catch (error) {
|
|
61
|
-
console.error(colors.errorMessage('Changes analysis error:'), error.message)
|
|
62
|
-
throw error
|
|
66
|
+
console.error(colors.errorMessage('Changes analysis error:'), error.message)
|
|
67
|
+
throw error
|
|
63
68
|
}
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
async analyzeRecentCommits(limit = 10) {
|
|
67
72
|
try {
|
|
68
|
-
return await this.orchestrator.analyzeRepository({
|
|
69
|
-
type: 'commits',
|
|
70
|
-
limit
|
|
71
|
-
})
|
|
73
|
+
return await this.orchestrator.analyzeRepository({
|
|
74
|
+
type: 'commits',
|
|
75
|
+
limit,
|
|
76
|
+
})
|
|
72
77
|
} catch (error) {
|
|
73
|
-
console.error(colors.errorMessage('Commits analysis error:'), error.message)
|
|
74
|
-
throw error
|
|
78
|
+
console.error(colors.errorMessage('Commits analysis error:'), error.message)
|
|
79
|
+
throw error
|
|
75
80
|
}
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
async assessHealth(options = {}) {
|
|
79
84
|
try {
|
|
80
|
-
return await this.orchestrator.analyzeRepository({
|
|
85
|
+
return await this.orchestrator.analyzeRepository({
|
|
81
86
|
type: 'health',
|
|
82
|
-
...options
|
|
83
|
-
})
|
|
87
|
+
...options,
|
|
88
|
+
})
|
|
84
89
|
} catch (error) {
|
|
85
|
-
console.error(colors.errorMessage('Health assessment error:'), error.message)
|
|
86
|
-
throw error
|
|
90
|
+
console.error(colors.errorMessage('Health assessment error:'), error.message)
|
|
91
|
+
throw error
|
|
87
92
|
}
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
async generateChangelogFromChanges(version) {
|
|
91
96
|
try {
|
|
92
|
-
return await this.orchestrator.generateChangelogFromChanges(version)
|
|
97
|
+
return await this.orchestrator.generateChangelogFromChanges(version)
|
|
93
98
|
} catch (error) {
|
|
94
|
-
console.error(colors.errorMessage('Working directory changelog error:'), error.message)
|
|
95
|
-
throw error
|
|
99
|
+
console.error(colors.errorMessage('Working directory changelog error:'), error.message)
|
|
100
|
+
throw error
|
|
96
101
|
}
|
|
97
102
|
}
|
|
98
103
|
|
|
99
104
|
async runInteractive() {
|
|
100
105
|
try {
|
|
101
|
-
return await this.orchestrator.runInteractive()
|
|
106
|
+
return await this.orchestrator.runInteractive()
|
|
102
107
|
} catch (error) {
|
|
103
|
-
console.error(colors.errorMessage('Interactive mode error:'), error.message)
|
|
104
|
-
throw error
|
|
108
|
+
console.error(colors.errorMessage('Interactive mode error:'), error.message)
|
|
109
|
+
throw error
|
|
105
110
|
}
|
|
106
111
|
}
|
|
107
112
|
|
|
108
113
|
// Configuration delegation
|
|
109
114
|
setAnalysisMode(mode) {
|
|
110
|
-
this.orchestrator.setAnalysisMode(mode)
|
|
115
|
+
this.orchestrator.setAnalysisMode(mode)
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
setModelOverride(model) {
|
|
114
|
-
this.orchestrator.setModelOverride(model)
|
|
119
|
+
this.orchestrator.setModelOverride(model)
|
|
115
120
|
}
|
|
116
121
|
|
|
117
122
|
// Metrics delegation
|
|
118
123
|
getMetrics() {
|
|
119
|
-
return this.orchestrator.getMetrics()
|
|
124
|
+
return this.orchestrator.getMetrics()
|
|
120
125
|
}
|
|
121
126
|
|
|
122
127
|
resetMetrics() {
|
|
123
|
-
this.orchestrator.resetMetrics()
|
|
128
|
+
this.orchestrator.resetMetrics()
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
// Provider management
|
|
127
132
|
async listProviders() {
|
|
128
133
|
try {
|
|
129
|
-
return await this.orchestrator.providerManager.listProviders()
|
|
134
|
+
return await this.orchestrator.providerManager.listProviders()
|
|
130
135
|
} catch (error) {
|
|
131
|
-
console.error(colors.errorMessage('Provider listing error:'), error.message)
|
|
132
|
-
throw error
|
|
136
|
+
console.error(colors.errorMessage('Provider listing error:'), error.message)
|
|
137
|
+
throw error
|
|
133
138
|
}
|
|
134
139
|
}
|
|
135
140
|
|
|
136
|
-
|
|
141
|
+
switchProvider(providerName) {
|
|
137
142
|
try {
|
|
138
|
-
const result = this.orchestrator.providerManager.switchProvider(providerName)
|
|
143
|
+
const result = this.orchestrator.providerManager.switchProvider(providerName)
|
|
139
144
|
if (result.success) {
|
|
140
145
|
// Reinitialize services with new provider
|
|
141
|
-
this.orchestrator.initializeServices()
|
|
142
|
-
console.log(colors.successMessage(`✅ Switched to provider: ${providerName}`))
|
|
146
|
+
this.orchestrator.initializeServices()
|
|
147
|
+
console.log(colors.successMessage(`✅ Switched to provider: ${providerName}`))
|
|
143
148
|
}
|
|
144
|
-
return result
|
|
149
|
+
return result
|
|
145
150
|
} catch (error) {
|
|
146
|
-
console.error(colors.errorMessage('Provider switch error:'), error.message)
|
|
147
|
-
return { success: false, error: error.message }
|
|
151
|
+
console.error(colors.errorMessage('Provider switch error:'), error.message)
|
|
152
|
+
return { success: false, error: error.message }
|
|
148
153
|
}
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
// Validation methods
|
|
152
|
-
|
|
157
|
+
validateConfiguration() {
|
|
153
158
|
try {
|
|
154
159
|
// Basic validation
|
|
155
|
-
const config = this.configManager.getAll()
|
|
156
|
-
const issues = []
|
|
157
|
-
|
|
158
|
-
if (!config.GIT_PATH
|
|
159
|
-
issues.push('No git path configured')
|
|
160
|
+
const config = this.configManager.getAll()
|
|
161
|
+
const issues = []
|
|
162
|
+
|
|
163
|
+
if (!(config.GIT_PATH || process.cwd())) {
|
|
164
|
+
issues.push('No git path configured')
|
|
160
165
|
}
|
|
161
|
-
|
|
166
|
+
|
|
162
167
|
// Validate AI provider if available
|
|
163
168
|
if (this.orchestrator.aiProvider) {
|
|
164
|
-
const isAvailable = this.orchestrator.aiProvider.isAvailable()
|
|
169
|
+
const isAvailable = this.orchestrator.aiProvider.isAvailable()
|
|
165
170
|
if (!isAvailable) {
|
|
166
|
-
issues.push('AI provider not properly configured')
|
|
171
|
+
issues.push('AI provider not properly configured')
|
|
167
172
|
}
|
|
168
173
|
}
|
|
169
|
-
|
|
174
|
+
|
|
170
175
|
return {
|
|
171
176
|
valid: issues.length === 0,
|
|
172
177
|
issues,
|
|
173
|
-
recommendations: this.generateRecommendations(issues)
|
|
174
|
-
}
|
|
175
|
-
|
|
178
|
+
recommendations: this.generateRecommendations(issues),
|
|
179
|
+
}
|
|
176
180
|
} catch (error) {
|
|
177
|
-
console.error(colors.errorMessage('Configuration validation error:'), error.message)
|
|
181
|
+
console.error(colors.errorMessage('Configuration validation error:'), error.message)
|
|
178
182
|
return {
|
|
179
183
|
valid: false,
|
|
180
184
|
issues: [error.message],
|
|
181
|
-
recommendations: []
|
|
182
|
-
}
|
|
185
|
+
recommendations: [],
|
|
186
|
+
}
|
|
183
187
|
}
|
|
184
188
|
}
|
|
185
189
|
|
|
186
190
|
generateRecommendations(issues) {
|
|
187
|
-
const recommendations = []
|
|
188
|
-
|
|
189
|
-
issues.forEach(issue => {
|
|
191
|
+
const recommendations = []
|
|
192
|
+
|
|
193
|
+
issues.forEach((issue) => {
|
|
190
194
|
if (issue.includes('git path')) {
|
|
191
|
-
recommendations.push('Set GIT_PATH environment variable or run from git repository')
|
|
195
|
+
recommendations.push('Set GIT_PATH environment variable or run from git repository')
|
|
192
196
|
}
|
|
193
197
|
if (issue.includes('AI provider')) {
|
|
194
|
-
recommendations.push('Configure AI provider credentials in .env.local file')
|
|
198
|
+
recommendations.push('Configure AI provider credentials in .env.local file')
|
|
195
199
|
}
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
return recommendations
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
return recommendations
|
|
199
203
|
}
|
|
200
204
|
|
|
201
205
|
// Health check
|
|
@@ -204,98 +208,116 @@ export class ApplicationService {
|
|
|
204
208
|
const health = {
|
|
205
209
|
status: 'healthy',
|
|
206
210
|
checks: {},
|
|
207
|
-
timestamp: new Date().toISOString()
|
|
208
|
-
}
|
|
209
|
-
|
|
211
|
+
timestamp: new Date().toISOString(),
|
|
212
|
+
}
|
|
213
|
+
|
|
210
214
|
// Git check
|
|
211
215
|
try {
|
|
212
216
|
health.checks.git = {
|
|
213
217
|
status: this.orchestrator.gitManager.isGitRepo ? 'ok' : 'error',
|
|
214
|
-
message: this.orchestrator.gitManager.isGitRepo
|
|
215
|
-
|
|
218
|
+
message: this.orchestrator.gitManager.isGitRepo
|
|
219
|
+
? 'Git repository detected'
|
|
220
|
+
: 'Not a git repository',
|
|
221
|
+
}
|
|
216
222
|
} catch (error) {
|
|
217
|
-
health.checks.git = { status: 'error', message: error.message }
|
|
223
|
+
health.checks.git = { status: 'error', message: error.message }
|
|
218
224
|
}
|
|
219
|
-
|
|
225
|
+
|
|
220
226
|
// AI provider check
|
|
221
227
|
try {
|
|
222
228
|
health.checks.ai = {
|
|
223
229
|
status: this.orchestrator.aiProvider?.isAvailable() ? 'ok' : 'warning',
|
|
224
|
-
message: this.orchestrator.aiProvider?.isAvailable()
|
|
225
|
-
|
|
230
|
+
message: this.orchestrator.aiProvider?.isAvailable()
|
|
231
|
+
? 'AI provider available'
|
|
232
|
+
: 'AI provider not configured',
|
|
233
|
+
}
|
|
226
234
|
} catch (error) {
|
|
227
|
-
health.checks.ai = { status: 'error', message: error.message }
|
|
235
|
+
health.checks.ai = { status: 'error', message: error.message }
|
|
228
236
|
}
|
|
229
|
-
|
|
237
|
+
|
|
230
238
|
// Configuration check
|
|
231
239
|
try {
|
|
232
|
-
const configValidation = await this.validateConfiguration()
|
|
240
|
+
const configValidation = await this.validateConfiguration()
|
|
233
241
|
health.checks.config = {
|
|
234
242
|
status: configValidation.valid ? 'ok' : 'warning',
|
|
235
|
-
message: configValidation.valid
|
|
236
|
-
|
|
243
|
+
message: configValidation.valid
|
|
244
|
+
? 'Configuration valid'
|
|
245
|
+
: `${configValidation.issues.length} issues found`,
|
|
246
|
+
}
|
|
237
247
|
} catch (error) {
|
|
238
|
-
health.checks.config = { status: 'error', message: error.message }
|
|
248
|
+
health.checks.config = { status: 'error', message: error.message }
|
|
239
249
|
}
|
|
240
|
-
|
|
250
|
+
|
|
241
251
|
// Overall status
|
|
242
|
-
const hasErrors = Object.values(health.checks).some(check => check.status === 'error')
|
|
243
|
-
const hasWarnings = Object.values(health.checks).some(check => check.status === 'warning')
|
|
244
|
-
|
|
252
|
+
const hasErrors = Object.values(health.checks).some((check) => check.status === 'error')
|
|
253
|
+
const hasWarnings = Object.values(health.checks).some((check) => check.status === 'warning')
|
|
254
|
+
|
|
245
255
|
if (hasErrors) {
|
|
246
|
-
health.status = 'unhealthy'
|
|
256
|
+
health.status = 'unhealthy'
|
|
247
257
|
} else if (hasWarnings) {
|
|
248
|
-
health.status = 'degraded'
|
|
258
|
+
health.status = 'degraded'
|
|
249
259
|
}
|
|
250
|
-
|
|
251
|
-
return health
|
|
252
|
-
|
|
260
|
+
|
|
261
|
+
return health
|
|
253
262
|
} catch (error) {
|
|
254
263
|
return {
|
|
255
264
|
status: 'unhealthy',
|
|
256
265
|
error: error.message,
|
|
257
|
-
timestamp: new Date().toISOString()
|
|
258
|
-
}
|
|
266
|
+
timestamp: new Date().toISOString(),
|
|
267
|
+
}
|
|
259
268
|
}
|
|
260
269
|
}
|
|
261
270
|
|
|
262
271
|
// Commit message generation
|
|
263
272
|
async generateCommitMessage() {
|
|
264
273
|
try {
|
|
265
|
-
await this.ensureInitialized()
|
|
266
|
-
return await this.orchestrator.interactiveService.generateCommitSuggestion()
|
|
274
|
+
await this.ensureInitialized()
|
|
275
|
+
return await this.orchestrator.interactiveService.generateCommitSuggestion()
|
|
267
276
|
} catch (error) {
|
|
268
|
-
console.error(colors.errorMessage('Commit message generation error:'), error.message)
|
|
269
|
-
throw error
|
|
277
|
+
console.error(colors.errorMessage('Commit message generation error:'), error.message)
|
|
278
|
+
throw error
|
|
270
279
|
}
|
|
271
280
|
}
|
|
272
281
|
|
|
273
282
|
// Provider validation methods
|
|
274
283
|
async validateProvider(providerName) {
|
|
275
284
|
try {
|
|
276
|
-
return await this.orchestrator.providerManager.testProvider(providerName)
|
|
285
|
+
return await this.orchestrator.providerManager.testProvider(providerName)
|
|
277
286
|
} catch (error) {
|
|
278
|
-
console.error(colors.errorMessage('Provider validation error:'), error.message)
|
|
279
|
-
throw error
|
|
287
|
+
console.error(colors.errorMessage('Provider validation error:'), error.message)
|
|
288
|
+
throw error
|
|
280
289
|
}
|
|
281
290
|
}
|
|
282
291
|
|
|
283
292
|
async validateAllProviders() {
|
|
284
293
|
try {
|
|
285
|
-
return await this.orchestrator.providerManager.validateAll()
|
|
294
|
+
return await this.orchestrator.providerManager.validateAll()
|
|
286
295
|
} catch (error) {
|
|
287
|
-
console.error(colors.errorMessage('All providers validation error:'), error.message)
|
|
288
|
-
throw error
|
|
296
|
+
console.error(colors.errorMessage('All providers validation error:'), error.message)
|
|
297
|
+
throw error
|
|
289
298
|
}
|
|
290
299
|
}
|
|
291
300
|
|
|
292
301
|
// Additional helper methods
|
|
293
302
|
async generateChangelogFromCommits(commitHashes) {
|
|
294
303
|
try {
|
|
295
|
-
return await this.orchestrator.interactiveService.generateChangelogForCommits(commitHashes)
|
|
304
|
+
return await this.orchestrator.interactiveService.generateChangelogForCommits(commitHashes)
|
|
305
|
+
} catch (error) {
|
|
306
|
+
console.error(colors.errorMessage('Changelog from commits error:'), error.message)
|
|
307
|
+
throw error
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Interactive commit workflow
|
|
312
|
+
async executeCommitWorkflow(options = {}) {
|
|
313
|
+
try {
|
|
314
|
+
await this.ensureInitialized()
|
|
315
|
+
|
|
316
|
+
// Delegate to orchestrator for the commit workflow
|
|
317
|
+
return await this.orchestrator.executeCommitWorkflow(options)
|
|
296
318
|
} catch (error) {
|
|
297
|
-
console.error(colors.errorMessage('
|
|
298
|
-
throw error
|
|
319
|
+
console.error(colors.errorMessage('Commit workflow error:'), error.message)
|
|
320
|
+
throw error
|
|
299
321
|
}
|
|
300
322
|
}
|
|
301
|
-
}
|
|
323
|
+
}
|
package/src/cli.js
CHANGED
|
@@ -5,10 +5,14 @@
|
|
|
5
5
|
* Provides command-line interface for changelog generation functionality
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
8
|
+
import process from 'node:process'
|
|
9
|
+
|
|
10
|
+
import { hideBin } from 'yargs/helpers'
|
|
11
|
+
import yargs from 'yargs/yargs'
|
|
12
|
+
|
|
13
|
+
import { AIChangelogGenerator } from './ai-changelog-generator.js'
|
|
14
|
+
import colors from './shared/constants/colors.js'
|
|
15
|
+
import { EnhancedConsole, SimpleSpinner } from './shared/utils/cli-ui.js'
|
|
12
16
|
|
|
13
17
|
async function runCLI() {
|
|
14
18
|
const argv = await yargs(hideBin(process.argv))
|
|
@@ -17,141 +21,156 @@ async function runCLI() {
|
|
|
17
21
|
.option('tag', {
|
|
18
22
|
alias: ['v', 'version'],
|
|
19
23
|
type: 'string',
|
|
20
|
-
description: 'Version tag for changelog'
|
|
24
|
+
description: 'Version tag for changelog',
|
|
21
25
|
})
|
|
22
26
|
.option('since', {
|
|
23
27
|
alias: 's',
|
|
24
28
|
type: 'string',
|
|
25
|
-
description: 'Generate changelog since commit/tag'
|
|
29
|
+
description: 'Generate changelog since commit/tag',
|
|
26
30
|
})
|
|
27
31
|
.option('detailed', {
|
|
28
32
|
type: 'boolean',
|
|
29
|
-
description: 'Generate detailed technical analysis'
|
|
33
|
+
description: 'Generate detailed technical analysis',
|
|
30
34
|
})
|
|
31
35
|
.option('enterprise', {
|
|
32
36
|
type: 'boolean',
|
|
33
|
-
description: 'Generate enterprise-ready documentation'
|
|
37
|
+
description: 'Generate enterprise-ready documentation',
|
|
34
38
|
})
|
|
35
39
|
.option('interactive', {
|
|
36
40
|
alias: 'i',
|
|
37
41
|
type: 'boolean',
|
|
38
|
-
description: 'Run in interactive mode'
|
|
42
|
+
description: 'Run in interactive mode',
|
|
39
43
|
})
|
|
40
44
|
.option('analyze', {
|
|
41
45
|
type: 'boolean',
|
|
42
|
-
description: 'Analyze current working directory changes'
|
|
46
|
+
description: 'Analyze current working directory changes',
|
|
43
47
|
})
|
|
44
48
|
.option('health', {
|
|
45
49
|
type: 'boolean',
|
|
46
|
-
description: 'Assess repository health'
|
|
50
|
+
description: 'Assess repository health',
|
|
47
51
|
})
|
|
48
52
|
.option('branches', {
|
|
49
53
|
type: 'boolean',
|
|
50
|
-
description: 'Analyze all branches'
|
|
54
|
+
description: 'Analyze all branches',
|
|
51
55
|
})
|
|
52
56
|
.option('comprehensive', {
|
|
53
57
|
type: 'boolean',
|
|
54
|
-
description: 'Comprehensive repository analysis'
|
|
58
|
+
description: 'Comprehensive repository analysis',
|
|
55
59
|
})
|
|
56
60
|
.option('model', {
|
|
57
61
|
type: 'string',
|
|
58
|
-
description: 'Override AI model selection'
|
|
62
|
+
description: 'Override AI model selection',
|
|
59
63
|
})
|
|
60
64
|
.option('no-attribution', {
|
|
61
65
|
type: 'boolean',
|
|
62
|
-
description: 'Disable attribution footer'
|
|
66
|
+
description: 'Disable attribution footer',
|
|
63
67
|
})
|
|
64
68
|
.option('validate', {
|
|
65
69
|
type: 'boolean',
|
|
66
|
-
description: 'Validate configuration'
|
|
70
|
+
description: 'Validate configuration',
|
|
67
71
|
})
|
|
68
72
|
.help()
|
|
69
73
|
.alias('help', 'h')
|
|
70
|
-
.parse()
|
|
74
|
+
.parse()
|
|
71
75
|
|
|
72
76
|
try {
|
|
73
77
|
const generator = new AIChangelogGenerator({
|
|
74
78
|
analysisMode: argv.detailed ? 'detailed' : argv.enterprise ? 'enterprise' : 'standard',
|
|
75
79
|
modelOverride: argv.model,
|
|
76
|
-
includeAttribution: !argv.noAttribution
|
|
77
|
-
})
|
|
80
|
+
includeAttribution: !argv.noAttribution,
|
|
81
|
+
})
|
|
78
82
|
|
|
79
83
|
if (argv.model) {
|
|
80
|
-
generator.setModelOverride(argv.model)
|
|
84
|
+
generator.setModelOverride(argv.model)
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
if (argv.detailed) {
|
|
84
|
-
generator.setAnalysisMode('detailed')
|
|
88
|
+
generator.setAnalysisMode('detailed')
|
|
85
89
|
} else if (argv.enterprise) {
|
|
86
|
-
generator.setAnalysisMode('enterprise')
|
|
90
|
+
generator.setAnalysisMode('enterprise')
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
if (argv.validate) {
|
|
90
|
-
console.log(colors.infoMessage('🔧 Validating configuration...'))
|
|
91
|
-
await generator.validateConfiguration()
|
|
92
|
-
console.log(colors.successMessage('✅ Configuration is valid'))
|
|
93
|
-
return
|
|
94
|
+
console.log(colors.infoMessage('🔧 Validating configuration...'))
|
|
95
|
+
await generator.validateConfiguration()
|
|
96
|
+
console.log(colors.successMessage('✅ Configuration is valid'))
|
|
97
|
+
return
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
if (argv.interactive) {
|
|
97
|
-
console.log(colors.infoMessage('🎮 Starting interactive mode...'))
|
|
98
|
-
await generator.runInteractive()
|
|
99
|
-
return
|
|
101
|
+
console.log(colors.infoMessage('🎮 Starting interactive mode...'))
|
|
102
|
+
await generator.runInteractive()
|
|
103
|
+
return
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
if (argv.health) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
const healthSpinner = new SimpleSpinner('Assessing repository health...')
|
|
108
|
+
healthSpinner.start()
|
|
109
|
+
await generator.assessRepositoryHealth()
|
|
110
|
+
healthSpinner.succeed('Repository health assessment complete')
|
|
111
|
+
return
|
|
106
112
|
}
|
|
107
113
|
|
|
108
114
|
if (argv.analyze) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
const analyzeSpinner = new SimpleSpinner('Analyzing current changes...')
|
|
116
|
+
analyzeSpinner.start()
|
|
117
|
+
await generator.analyzeCurrentChanges()
|
|
118
|
+
analyzeSpinner.succeed('Current changes analysis complete')
|
|
119
|
+
return
|
|
112
120
|
}
|
|
113
121
|
|
|
114
122
|
if (argv.branches) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
123
|
+
const branchSpinner = new SimpleSpinner('Analyzing branches...')
|
|
124
|
+
branchSpinner.start()
|
|
125
|
+
await generator.analyzeRepository({ type: 'branches' })
|
|
126
|
+
branchSpinner.succeed('Branch analysis complete')
|
|
127
|
+
return
|
|
118
128
|
}
|
|
119
129
|
|
|
120
130
|
if (argv.comprehensive) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
131
|
+
const compSpinner = new SimpleSpinner('Running comprehensive analysis...')
|
|
132
|
+
compSpinner.start()
|
|
133
|
+
await generator.analyzeRepository({ type: 'comprehensive' })
|
|
134
|
+
compSpinner.succeed('Comprehensive analysis complete')
|
|
135
|
+
return
|
|
124
136
|
}
|
|
125
137
|
|
|
126
138
|
// Default: Generate changelog
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
139
|
+
const changelogSpinner = new SimpleSpinner('Generating changelog...')
|
|
140
|
+
changelogSpinner.start()
|
|
141
|
+
const result = await generator.generateChangelog(argv.tag || argv.version, argv.since)
|
|
142
|
+
|
|
130
143
|
if (result) {
|
|
131
|
-
|
|
132
|
-
|
|
144
|
+
changelogSpinner.succeed('Changelog generated successfully!')
|
|
145
|
+
|
|
133
146
|
// Show metrics
|
|
134
|
-
const metrics = generator.getMetrics()
|
|
135
|
-
|
|
147
|
+
const metrics = generator.getMetrics()
|
|
148
|
+
EnhancedConsole.metrics(
|
|
149
|
+
`Processed ${metrics.commitsProcessed} commits in ${formatDuration(Date.now() - metrics.startTime)}`
|
|
150
|
+
)
|
|
151
|
+
} else {
|
|
152
|
+
changelogSpinner.fail('Failed to generate changelog')
|
|
136
153
|
}
|
|
137
|
-
|
|
138
154
|
} catch (error) {
|
|
139
|
-
|
|
155
|
+
EnhancedConsole.error(`Error: ${error.message}`)
|
|
140
156
|
if (process.env.DEBUG) {
|
|
141
|
-
|
|
157
|
+
EnhancedConsole.error(error.stack)
|
|
142
158
|
}
|
|
143
|
-
process.exit(1)
|
|
159
|
+
process.exit(1)
|
|
144
160
|
}
|
|
145
161
|
}
|
|
146
162
|
|
|
147
163
|
function formatDuration(ms) {
|
|
148
|
-
const seconds = Math.round(ms / 1000)
|
|
149
|
-
return seconds > 0 ? `${seconds}s` : `${ms}ms
|
|
164
|
+
const seconds = Math.round(ms / 1000)
|
|
165
|
+
return seconds > 0 ? `${seconds}s` : `${ms}ms`
|
|
150
166
|
}
|
|
151
167
|
|
|
152
|
-
export { runCLI }
|
|
168
|
+
export { runCLI }
|
|
153
169
|
|
|
154
170
|
// If this file is run directly, execute CLI
|
|
155
171
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
156
|
-
runCLI()
|
|
157
|
-
|
|
172
|
+
runCLI().catch((error) => {
|
|
173
|
+
console.error('CLI Error:', error.message)
|
|
174
|
+
process.exit(1)
|
|
175
|
+
})
|
|
176
|
+
}
|