@entro314labs/ai-changelog-generator 3.1.1 → 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 -877
- package/README.md +8 -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 +80 -48
- package/src/ai-changelog-generator.js +83 -81
- package/src/application/orchestrators/changelog.orchestrator.js +791 -516
- package/src/application/services/application.service.js +137 -128
- 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 +390 -274
- package/src/infrastructure/config/configuration.manager.js +220 -190
- package/src/infrastructure/interactive/interactive-staging.service.js +154 -135
- 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 +259 -161
- package/src/shared/constants/colors.js +453 -180
- 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 +1117 -945
- package/types/index.d.ts +353 -344
|
@@ -1,201 +1,297 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
import {
|
|
1
|
+
import { access } from 'node:fs/promises'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import process from 'node:process'
|
|
4
|
+
|
|
5
|
+
import { hideBin } from 'yargs/helpers'
|
|
6
|
+
import yargs from 'yargs/yargs'
|
|
7
|
+
|
|
8
|
+
import { ApplicationService } from '../../application/services/application.service.js'
|
|
9
|
+
import colors from '../../shared/constants/colors.js'
|
|
10
|
+
import { handleCLIError, setupProcessErrorHandlers } from '../../shared/utils/cli-entry-utils.js'
|
|
11
|
+
import { EnhancedConsole } from '../../shared/utils/cli-ui.js'
|
|
12
|
+
import { formatDuration, promptForConfig } from '../../shared/utils/utils.js'
|
|
9
13
|
|
|
10
14
|
export class CLIController {
|
|
11
15
|
constructor() {
|
|
12
|
-
this.commands = new Map()
|
|
13
|
-
this.appService = null
|
|
14
|
-
this.startTime = Date.now()
|
|
16
|
+
this.commands = new Map()
|
|
17
|
+
this.appService = null
|
|
18
|
+
this.startTime = Date.now()
|
|
15
19
|
|
|
16
20
|
// Setup enhanced error handling
|
|
17
21
|
setupProcessErrorHandlers('AI Changelog Generator', {
|
|
18
22
|
gracefulShutdown: true,
|
|
19
23
|
logErrors: true,
|
|
20
|
-
showStack: process.env.DEBUG === 'true'
|
|
21
|
-
})
|
|
24
|
+
showStack: process.env.DEBUG === 'true',
|
|
25
|
+
})
|
|
22
26
|
|
|
23
|
-
this.registerCommands()
|
|
27
|
+
this.registerCommands()
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
registerCommands() {
|
|
27
31
|
// Register all available commands
|
|
28
|
-
this.commands.set('default', new DefaultCommand())
|
|
29
|
-
this.commands.set('init', new InitCommand())
|
|
30
|
-
this.commands.set('validate', new ValidateCommand())
|
|
31
|
-
this.commands.set('analyze', new AnalyzeCommand())
|
|
32
|
-
this.commands.set('analyze-commits', new AnalyzeCommitsCommand())
|
|
33
|
-
this.commands.set('git-info', new GitInfoCommand())
|
|
34
|
-
this.commands.set('health', new HealthCommand())
|
|
35
|
-
this.commands.set('branches', new BranchesCommand())
|
|
36
|
-
this.commands.set('comprehensive', new ComprehensiveCommand())
|
|
37
|
-
this.commands.set('untracked', new UntrackedCommand())
|
|
38
|
-
this.commands.set('working-dir', new WorkingDirCommand())
|
|
39
|
-
this.commands.set('from-commits', new FromCommitsCommand())
|
|
40
|
-
this.commands.set('commit-message', new CommitMessageCommand())
|
|
41
|
-
this.commands.set('commit', new CommitCommand())
|
|
42
|
-
this.commands.set('providers', new ProvidersCommand())
|
|
32
|
+
this.commands.set('default', new DefaultCommand())
|
|
33
|
+
this.commands.set('init', new InitCommand())
|
|
34
|
+
this.commands.set('validate', new ValidateCommand())
|
|
35
|
+
this.commands.set('analyze', new AnalyzeCommand())
|
|
36
|
+
this.commands.set('analyze-commits', new AnalyzeCommitsCommand())
|
|
37
|
+
this.commands.set('git-info', new GitInfoCommand())
|
|
38
|
+
this.commands.set('health', new HealthCommand())
|
|
39
|
+
this.commands.set('branches', new BranchesCommand())
|
|
40
|
+
this.commands.set('comprehensive', new ComprehensiveCommand())
|
|
41
|
+
this.commands.set('untracked', new UntrackedCommand())
|
|
42
|
+
this.commands.set('working-dir', new WorkingDirCommand())
|
|
43
|
+
this.commands.set('from-commits', new FromCommitsCommand())
|
|
44
|
+
this.commands.set('commit-message', new CommitMessageCommand())
|
|
45
|
+
this.commands.set('commit', new CommitCommand())
|
|
46
|
+
this.commands.set('providers', new ProvidersCommand())
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
async runCLI() {
|
|
46
50
|
try {
|
|
47
51
|
// Ensure config exists
|
|
48
|
-
await this.ensureConfig()
|
|
52
|
+
await this.ensureConfig()
|
|
49
53
|
|
|
50
|
-
const argv = await this.setupYargs()
|
|
54
|
+
const argv = await this.setupYargs()
|
|
51
55
|
|
|
52
56
|
// Initialize application service with CLI options
|
|
53
57
|
this.appService = new ApplicationService({
|
|
54
58
|
dryRun: argv.dryRun,
|
|
55
59
|
noColor: argv.noColor,
|
|
56
|
-
silent: argv.silent
|
|
57
|
-
})
|
|
60
|
+
silent: argv.silent,
|
|
61
|
+
})
|
|
58
62
|
|
|
59
63
|
// Execute command
|
|
60
|
-
const commandName = argv._[0] || 'default'
|
|
61
|
-
const command = this.commands.get(commandName)
|
|
64
|
+
const commandName = argv._[0] || 'default'
|
|
65
|
+
const command = this.commands.get(commandName)
|
|
62
66
|
|
|
63
67
|
if (!command) {
|
|
64
|
-
throw new Error(`Unknown command: ${commandName}`)
|
|
68
|
+
throw new Error(`Unknown command: ${commandName}`)
|
|
65
69
|
}
|
|
66
70
|
|
|
67
|
-
await command.execute(argv, this.appService)
|
|
71
|
+
await command.execute(argv, this.appService)
|
|
68
72
|
|
|
69
73
|
// Show completion metrics
|
|
70
|
-
await this.showMetrics()
|
|
71
|
-
|
|
74
|
+
await this.showMetrics()
|
|
72
75
|
} catch (error) {
|
|
73
76
|
handleCLIError(error, 'run CLI application', {
|
|
74
77
|
exitOnError: false,
|
|
75
78
|
showTips: true,
|
|
76
|
-
showStack: process.env.DEBUG === 'true'
|
|
77
|
-
})
|
|
78
|
-
process.exitCode = 1
|
|
79
|
+
showStack: process.env.DEBUG === 'true',
|
|
80
|
+
})
|
|
81
|
+
process.exitCode = 1
|
|
79
82
|
}
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
async ensureConfig() {
|
|
83
|
-
const configPath = path.join(process.cwd(), '.env.local')
|
|
86
|
+
const configPath = path.join(process.cwd(), '.env.local')
|
|
84
87
|
try {
|
|
85
|
-
await access(configPath)
|
|
88
|
+
await access(configPath)
|
|
86
89
|
} catch {
|
|
87
|
-
await promptForConfig()
|
|
90
|
+
await promptForConfig()
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
setupYargs() {
|
|
92
|
-
return
|
|
93
|
-
.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
95
|
+
return (
|
|
96
|
+
yargs(hideBin(process.argv))
|
|
97
|
+
.scriptName('ai-changelog')
|
|
98
|
+
.usage(
|
|
99
|
+
`${colors.header('AI Changelog Generator')} - ${colors.secondary('Automatically generate changelogs from your git commits using AI.')}\n\n${colors.header('Usage:')} $0 [command] [options]`
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
// Default command
|
|
103
|
+
.command('$0', 'Generate a changelog from git commits (default command).', (yargs) => {
|
|
104
|
+
yargs
|
|
105
|
+
.option('interactive', {
|
|
106
|
+
alias: 'i',
|
|
107
|
+
type: 'boolean',
|
|
108
|
+
description: 'Choose commits interactively.',
|
|
109
|
+
})
|
|
110
|
+
.option('release-version', {
|
|
111
|
+
alias: 'v',
|
|
112
|
+
type: 'string',
|
|
113
|
+
description: 'Set the release version (e.g., 1.2.3).',
|
|
114
|
+
})
|
|
115
|
+
.option('since', {
|
|
116
|
+
alias: 's',
|
|
117
|
+
type: 'string',
|
|
118
|
+
description: 'Generate changelog since a specific git ref (tag/commit).',
|
|
119
|
+
})
|
|
120
|
+
.option('model', {
|
|
121
|
+
alias: 'm',
|
|
122
|
+
type: 'string',
|
|
123
|
+
description: 'Override the default model.',
|
|
124
|
+
})
|
|
125
|
+
.option('detailed', { type: 'boolean', description: 'Use detailed analysis mode.' })
|
|
126
|
+
.option('enterprise', { type: 'boolean', description: 'Use enterprise analysis mode.' })
|
|
127
|
+
.option('dry-run', {
|
|
128
|
+
type: 'boolean',
|
|
129
|
+
description: 'Preview changelog without writing to file.',
|
|
130
|
+
})
|
|
131
|
+
.option('no-attribution', {
|
|
132
|
+
type: 'boolean',
|
|
133
|
+
description: 'Disable the attribution footer.',
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
// Analysis commands
|
|
138
|
+
.command('init', 'Run interactive setup to configure the tool.')
|
|
139
|
+
.command('validate', 'Validate your configuration and connectivity.')
|
|
140
|
+
.command(
|
|
141
|
+
'analyze',
|
|
142
|
+
'Analyze current working directory changes.',
|
|
143
|
+
this.createStandardOptions
|
|
144
|
+
)
|
|
145
|
+
.command(
|
|
146
|
+
'analyze-commits <limit>',
|
|
147
|
+
'Analyze recent commits with detailed information.',
|
|
148
|
+
(yargs) => {
|
|
149
|
+
this.createStandardOptions(yargs).positional('limit', {
|
|
150
|
+
type: 'number',
|
|
151
|
+
default: 10,
|
|
152
|
+
description: 'Number of commits to analyze',
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
.command(
|
|
157
|
+
'git-info',
|
|
158
|
+
'Display comprehensive repository information and statistics.',
|
|
159
|
+
this.createStandardOptions
|
|
160
|
+
)
|
|
161
|
+
.command(
|
|
162
|
+
'health',
|
|
163
|
+
'Assess repository health and commit quality.',
|
|
164
|
+
this.createStandardOptions
|
|
165
|
+
)
|
|
166
|
+
.command(
|
|
167
|
+
'branches',
|
|
168
|
+
'Analyze all branches and unmerged commits.',
|
|
169
|
+
this.createStandardOptions
|
|
170
|
+
)
|
|
171
|
+
.command(
|
|
172
|
+
'comprehensive',
|
|
173
|
+
'Comprehensive analysis including dangling commits.',
|
|
174
|
+
this.createStandardOptions
|
|
175
|
+
)
|
|
176
|
+
.command('untracked', 'Include untracked files analysis.', this.createStandardOptions)
|
|
177
|
+
.command(
|
|
178
|
+
'working-dir',
|
|
179
|
+
'Generate changelog from working directory changes.',
|
|
180
|
+
this.createStandardOptions
|
|
181
|
+
)
|
|
182
|
+
.command(
|
|
183
|
+
'from-commits <commits...>',
|
|
184
|
+
'Generate changelog from specific commit hashes.',
|
|
185
|
+
(yargs) => {
|
|
186
|
+
yargs.positional('commits', { describe: 'Commit hashes to analyze', type: 'string' })
|
|
187
|
+
}
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
// Utility commands
|
|
191
|
+
.command('commit-message', 'Generate a commit message for current changes.')
|
|
192
|
+
.command('commit', 'Interactive commit workflow with AI-generated messages.', (yargs) => {
|
|
193
|
+
yargs
|
|
194
|
+
.option('interactive', {
|
|
195
|
+
alias: 'i',
|
|
196
|
+
type: 'boolean',
|
|
197
|
+
default: true,
|
|
198
|
+
description: 'Use interactive staging (default).',
|
|
199
|
+
})
|
|
200
|
+
.option('all', {
|
|
201
|
+
alias: 'a',
|
|
202
|
+
type: 'boolean',
|
|
203
|
+
description: 'Automatically stage all changes.',
|
|
204
|
+
})
|
|
205
|
+
.option('message', {
|
|
206
|
+
alias: 'm',
|
|
207
|
+
type: 'string',
|
|
208
|
+
description: 'Use provided commit message (skip AI generation).',
|
|
209
|
+
})
|
|
210
|
+
.option('dry-run', {
|
|
211
|
+
type: 'boolean',
|
|
212
|
+
description: 'Preview commit message without committing.',
|
|
213
|
+
})
|
|
214
|
+
.option('editor', {
|
|
215
|
+
alias: 'e',
|
|
216
|
+
type: 'boolean',
|
|
217
|
+
description: 'Open editor to review/edit commit message.',
|
|
218
|
+
})
|
|
219
|
+
.option('model', { type: 'string', description: 'Override the default AI model.' })
|
|
220
|
+
})
|
|
221
|
+
.command('providers', 'Manage AI providers.', (yargs) => {
|
|
222
|
+
yargs
|
|
223
|
+
.command('list', 'List available providers.')
|
|
224
|
+
.command('switch <provider>', 'Switch to a different provider.')
|
|
225
|
+
.command('configure [provider]', 'Configure AI provider settings.')
|
|
226
|
+
.command('validate [provider]', 'Validate provider models and capabilities.')
|
|
227
|
+
.demandCommand(1, 'Please specify a provider subcommand.')
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
// Global options
|
|
231
|
+
.option('no-color', { type: 'boolean', description: 'Disable colored output.' })
|
|
232
|
+
.option('silent', { type: 'boolean', description: 'Suppress non-essential output.' })
|
|
233
|
+
.help('h')
|
|
234
|
+
.alias('h', 'help')
|
|
235
|
+
.epilogue(
|
|
236
|
+
`For more information, visit ${colors.highlight('https://github.com/entro314-labs/ai-changelog-generator')}`
|
|
237
|
+
)
|
|
238
|
+
.demandCommand(0)
|
|
239
|
+
.strict()
|
|
240
|
+
.parse()
|
|
241
|
+
)
|
|
156
242
|
}
|
|
157
243
|
|
|
158
244
|
createStandardOptions(yargs) {
|
|
159
245
|
return yargs
|
|
160
|
-
.option('format', {
|
|
246
|
+
.option('format', {
|
|
247
|
+
alias: 'f',
|
|
248
|
+
type: 'string',
|
|
249
|
+
choices: ['markdown', 'json'],
|
|
250
|
+
default: 'markdown',
|
|
251
|
+
description: 'Output format',
|
|
252
|
+
})
|
|
161
253
|
.option('output', { alias: 'o', type: 'string', description: 'Output file path' })
|
|
162
254
|
.option('since', { type: 'string', description: 'Analyze changes since this git ref' })
|
|
163
255
|
.option('silent', { type: 'boolean', description: 'Suppress non-essential output' })
|
|
164
256
|
.option('dry-run', { type: 'boolean', description: 'Preview without writing files' })
|
|
165
257
|
.option('detailed', { type: 'boolean', description: 'Use detailed analysis mode' })
|
|
166
258
|
.option('enterprise', { type: 'boolean', description: 'Use enterprise analysis mode' })
|
|
167
|
-
.option('model', { alias: 'm', type: 'string', description: 'Override the default model' })
|
|
259
|
+
.option('model', { alias: 'm', type: 'string', description: 'Override the default model' })
|
|
168
260
|
}
|
|
169
261
|
|
|
170
262
|
async showMetrics() {
|
|
171
|
-
if (!this.appService || this.appService.options.silent)
|
|
263
|
+
if (!this.appService || this.appService.options.silent) {
|
|
264
|
+
return
|
|
265
|
+
}
|
|
172
266
|
|
|
173
|
-
const endTime = Date.now()
|
|
174
|
-
const metrics = this.appService.getMetrics()
|
|
267
|
+
const endTime = Date.now()
|
|
268
|
+
const metrics = this.appService.getMetrics()
|
|
175
269
|
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
270
|
+
const summaryData = {
|
|
271
|
+
'Total time': formatDuration(endTime - this.startTime),
|
|
272
|
+
'Commits processed': metrics.commitsProcessed || 0,
|
|
273
|
+
}
|
|
180
274
|
|
|
181
275
|
if (metrics.apiCalls > 0) {
|
|
182
|
-
|
|
183
|
-
|
|
276
|
+
summaryData['AI calls'] = metrics.apiCalls
|
|
277
|
+
summaryData['Total tokens'] = (metrics.totalTokens || 0).toLocaleString()
|
|
184
278
|
}
|
|
185
279
|
|
|
186
280
|
if (metrics.errors > 0) {
|
|
187
|
-
|
|
188
|
-
summaryLines.push(colors.error(`❌ Errors: ${metrics.errors}`));
|
|
281
|
+
summaryData.Errors = colors.error(`${metrics.errors}`)
|
|
189
282
|
}
|
|
190
283
|
|
|
191
|
-
|
|
284
|
+
EnhancedConsole.box('📊 Session Summary', colors.formatMetrics(summaryData), {
|
|
285
|
+
borderStyle: 'rounded',
|
|
286
|
+
borderColor: 'info',
|
|
287
|
+
})
|
|
192
288
|
}
|
|
193
289
|
}
|
|
194
290
|
|
|
195
291
|
// Base command class
|
|
196
292
|
class BaseCommand {
|
|
197
|
-
async execute(
|
|
198
|
-
throw new Error('Command execute method not implemented')
|
|
293
|
+
async execute(_argv, _appService) {
|
|
294
|
+
throw new Error('Command execute method not implemented')
|
|
199
295
|
}
|
|
200
296
|
|
|
201
297
|
processStandardFlags(argv, appService) {
|
|
@@ -203,58 +299,64 @@ class BaseCommand {
|
|
|
203
299
|
format: argv.format || 'markdown',
|
|
204
300
|
output: argv.output,
|
|
205
301
|
since: argv.since,
|
|
206
|
-
silent: argv.silent
|
|
207
|
-
dryRun: argv.dryRun
|
|
208
|
-
}
|
|
302
|
+
silent: argv.silent,
|
|
303
|
+
dryRun: argv.dryRun,
|
|
304
|
+
}
|
|
209
305
|
|
|
210
306
|
// Apply analysis mode
|
|
211
|
-
if (argv.detailed)
|
|
212
|
-
|
|
213
|
-
|
|
307
|
+
if (argv.detailed) {
|
|
308
|
+
appService.setAnalysisMode('detailed')
|
|
309
|
+
}
|
|
310
|
+
if (argv.enterprise) {
|
|
311
|
+
appService.setAnalysisMode('enterprise')
|
|
312
|
+
}
|
|
313
|
+
if (argv.model) {
|
|
314
|
+
appService.setModelOverride(argv.model)
|
|
315
|
+
}
|
|
214
316
|
|
|
215
|
-
return config
|
|
317
|
+
return config
|
|
216
318
|
}
|
|
217
319
|
}
|
|
218
320
|
|
|
219
321
|
// Command implementations
|
|
220
322
|
class DefaultCommand extends BaseCommand {
|
|
221
323
|
async execute(argv, appService) {
|
|
222
|
-
const
|
|
324
|
+
const _config = this.processStandardFlags(argv, appService)
|
|
223
325
|
|
|
224
326
|
if (argv.interactive) {
|
|
225
|
-
await appService.runInteractive()
|
|
327
|
+
await appService.runInteractive()
|
|
226
328
|
} else {
|
|
227
329
|
await appService.generateChangelog({
|
|
228
330
|
version: argv.releaseVersion,
|
|
229
|
-
since: argv.since
|
|
230
|
-
})
|
|
331
|
+
since: argv.since,
|
|
332
|
+
})
|
|
231
333
|
}
|
|
232
334
|
}
|
|
233
335
|
}
|
|
234
336
|
|
|
235
337
|
class InitCommand extends BaseCommand {
|
|
236
|
-
async execute(
|
|
237
|
-
await promptForConfig()
|
|
338
|
+
async execute(_argv, _appService) {
|
|
339
|
+
await promptForConfig()
|
|
238
340
|
}
|
|
239
341
|
}
|
|
240
342
|
|
|
241
343
|
class ValidateCommand extends BaseCommand {
|
|
242
|
-
async execute(
|
|
243
|
-
const validation = await appService.validateConfiguration()
|
|
344
|
+
async execute(_argv, appService) {
|
|
345
|
+
const validation = await appService.validateConfiguration()
|
|
244
346
|
|
|
245
347
|
if (validation.valid) {
|
|
246
|
-
console.log(colors.successMessage('✅ Configuration is valid'))
|
|
348
|
+
console.log(colors.successMessage('✅ Configuration is valid'))
|
|
247
349
|
} else {
|
|
248
|
-
console.log(colors.errorMessage('❌ Configuration has issues:'))
|
|
249
|
-
validation.issues.forEach(issue => {
|
|
250
|
-
console.log(` - ${issue}`)
|
|
251
|
-
})
|
|
350
|
+
console.log(colors.errorMessage('❌ Configuration has issues:'))
|
|
351
|
+
validation.issues.forEach((issue) => {
|
|
352
|
+
console.log(` - ${issue}`)
|
|
353
|
+
})
|
|
252
354
|
|
|
253
355
|
if (validation.recommendations.length > 0) {
|
|
254
|
-
console.log(colors.infoMessage('\n💡 Recommendations:'))
|
|
255
|
-
validation.recommendations.forEach(rec => {
|
|
256
|
-
console.log(` - ${rec}`)
|
|
257
|
-
})
|
|
356
|
+
console.log(colors.infoMessage('\n💡 Recommendations:'))
|
|
357
|
+
validation.recommendations.forEach((rec) => {
|
|
358
|
+
console.log(` - ${rec}`)
|
|
359
|
+
})
|
|
258
360
|
}
|
|
259
361
|
}
|
|
260
362
|
}
|
|
@@ -262,131 +364,141 @@ class ValidateCommand extends BaseCommand {
|
|
|
262
364
|
|
|
263
365
|
class AnalyzeCommand extends BaseCommand {
|
|
264
366
|
async execute(argv, appService) {
|
|
265
|
-
const
|
|
266
|
-
await appService.analyzeCurrentChanges()
|
|
367
|
+
const _config = this.processStandardFlags(argv, appService)
|
|
368
|
+
await appService.analyzeCurrentChanges()
|
|
267
369
|
}
|
|
268
370
|
}
|
|
269
371
|
|
|
270
372
|
class AnalyzeCommitsCommand extends BaseCommand {
|
|
271
373
|
async execute(argv, appService) {
|
|
272
|
-
const
|
|
273
|
-
await appService.analyzeRecentCommits(argv.limit || 10)
|
|
374
|
+
const _config = this.processStandardFlags(argv, appService)
|
|
375
|
+
await appService.analyzeRecentCommits(argv.limit || 10)
|
|
274
376
|
}
|
|
275
377
|
}
|
|
276
378
|
|
|
277
379
|
class GitInfoCommand extends BaseCommand {
|
|
278
380
|
async execute(argv, appService) {
|
|
279
|
-
const config = this.processStandardFlags(argv, appService)
|
|
280
|
-
await appService.analyzeRepository({ type: 'git-info', ...config })
|
|
381
|
+
const config = this.processStandardFlags(argv, appService)
|
|
382
|
+
await appService.analyzeRepository({ type: 'git-info', ...config })
|
|
281
383
|
}
|
|
282
384
|
}
|
|
283
385
|
|
|
284
386
|
class HealthCommand extends BaseCommand {
|
|
285
387
|
async execute(argv, appService) {
|
|
286
|
-
const config = this.processStandardFlags(argv, appService)
|
|
287
|
-
await appService.assessHealth(config)
|
|
388
|
+
const config = this.processStandardFlags(argv, appService)
|
|
389
|
+
await appService.assessHealth(config)
|
|
288
390
|
}
|
|
289
391
|
}
|
|
290
392
|
|
|
291
393
|
class BranchesCommand extends BaseCommand {
|
|
292
394
|
async execute(argv, appService) {
|
|
293
|
-
const config = this.processStandardFlags(argv, appService)
|
|
294
|
-
await appService.analyzeRepository({ type: 'branches', ...config })
|
|
395
|
+
const config = this.processStandardFlags(argv, appService)
|
|
396
|
+
await appService.analyzeRepository({ type: 'branches', ...config })
|
|
295
397
|
}
|
|
296
398
|
}
|
|
297
399
|
|
|
298
400
|
class ComprehensiveCommand extends BaseCommand {
|
|
299
401
|
async execute(argv, appService) {
|
|
300
|
-
const config = this.processStandardFlags(argv, appService)
|
|
301
|
-
await appService.analyzeRepository({ type: 'comprehensive', ...config })
|
|
402
|
+
const config = this.processStandardFlags(argv, appService)
|
|
403
|
+
await appService.analyzeRepository({ type: 'comprehensive', ...config })
|
|
302
404
|
}
|
|
303
405
|
}
|
|
304
406
|
|
|
305
407
|
class UntrackedCommand extends BaseCommand {
|
|
306
408
|
async execute(argv, appService) {
|
|
307
|
-
const config = this.processStandardFlags(argv, appService)
|
|
308
|
-
await appService.analyzeRepository({ type: 'untracked', ...config })
|
|
409
|
+
const config = this.processStandardFlags(argv, appService)
|
|
410
|
+
await appService.analyzeRepository({ type: 'untracked', ...config })
|
|
309
411
|
}
|
|
310
412
|
}
|
|
311
413
|
|
|
312
414
|
class WorkingDirCommand extends BaseCommand {
|
|
313
415
|
async execute(argv, appService) {
|
|
314
|
-
const
|
|
315
|
-
await appService.generateChangelogFromChanges(argv.releaseVersion)
|
|
416
|
+
const _config = this.processStandardFlags(argv, appService)
|
|
417
|
+
await appService.generateChangelogFromChanges(argv.releaseVersion)
|
|
316
418
|
}
|
|
317
419
|
}
|
|
318
420
|
|
|
319
421
|
class FromCommitsCommand extends BaseCommand {
|
|
320
422
|
async execute(argv, appService) {
|
|
321
|
-
const
|
|
423
|
+
const _config = this.processStandardFlags(argv, appService)
|
|
322
424
|
// Implementation would generate changelog from specific commits
|
|
323
|
-
console.log(colors.infoMessage(`Generating changelog from commits: ${argv.commits.join(', ')}`))
|
|
425
|
+
console.log(colors.infoMessage(`Generating changelog from commits: ${argv.commits.join(', ')}`))
|
|
324
426
|
}
|
|
325
427
|
}
|
|
326
428
|
|
|
327
429
|
class CommitMessageCommand extends BaseCommand {
|
|
328
|
-
async execute(
|
|
329
|
-
console.log(
|
|
430
|
+
async execute(_argv, appService) {
|
|
431
|
+
console.log(
|
|
432
|
+
colors.processingMessage('🤖 Analyzing current changes for commit message suggestions...')
|
|
433
|
+
)
|
|
330
434
|
|
|
331
435
|
try {
|
|
332
|
-
const result = await appService.generateCommitMessage()
|
|
436
|
+
const result = await appService.generateCommitMessage()
|
|
333
437
|
|
|
334
|
-
if (result
|
|
335
|
-
console.log(colors.successMessage('\n✅ Generated commit message suggestions:'))
|
|
438
|
+
if (result?.suggestions && result.suggestions.length > 0) {
|
|
439
|
+
console.log(colors.successMessage('\n✅ Generated commit message suggestions:'))
|
|
336
440
|
result.suggestions.forEach((suggestion, index) => {
|
|
337
|
-
console.log(`${colors.number(index + 1)}. ${colors.highlight(suggestion)}`)
|
|
338
|
-
})
|
|
441
|
+
console.log(`${colors.number(index + 1)}. ${colors.highlight(suggestion)}`)
|
|
442
|
+
})
|
|
339
443
|
|
|
340
444
|
if (result.context) {
|
|
341
|
-
console.log(colors.dim(`\nContext: ${result.context}`))
|
|
445
|
+
console.log(colors.dim(`\nContext: ${result.context}`))
|
|
342
446
|
}
|
|
343
447
|
} else {
|
|
344
|
-
console.log(colors.warningMessage('No commit message suggestions could be generated.'))
|
|
345
|
-
console.log(colors.infoMessage('Make sure you have uncommitted changes.'))
|
|
448
|
+
console.log(colors.warningMessage('No commit message suggestions could be generated.'))
|
|
449
|
+
console.log(colors.infoMessage('Make sure you have uncommitted changes.'))
|
|
346
450
|
}
|
|
347
451
|
} catch (error) {
|
|
348
|
-
console.error(colors.errorMessage(`Error generating commit message: ${error.message}`))
|
|
452
|
+
console.error(colors.errorMessage(`Error generating commit message: ${error.message}`))
|
|
349
453
|
}
|
|
350
454
|
}
|
|
351
455
|
}
|
|
352
456
|
|
|
353
457
|
class CommitCommand extends BaseCommand {
|
|
354
458
|
async execute(argv, appService) {
|
|
355
|
-
console.log(colors.processingMessage('🚀 Starting interactive commit workflow...'))
|
|
459
|
+
console.log(colors.processingMessage('🚀 Starting interactive commit workflow...'))
|
|
356
460
|
|
|
357
461
|
try {
|
|
358
462
|
// Process flags and model override
|
|
359
|
-
if (argv.model)
|
|
463
|
+
if (argv.model) {
|
|
464
|
+
appService.setModelOverride(argv.model)
|
|
465
|
+
}
|
|
360
466
|
|
|
361
467
|
// Execute the commit workflow
|
|
362
468
|
const result = await appService.executeCommitWorkflow({
|
|
363
469
|
interactive: argv.interactive !== false, // Default to true unless explicitly false
|
|
364
|
-
stageAll: argv.all
|
|
470
|
+
stageAll: argv.all,
|
|
365
471
|
customMessage: argv.message,
|
|
366
|
-
dryRun: argv.dryRun
|
|
367
|
-
useEditor: argv.editor
|
|
368
|
-
})
|
|
472
|
+
dryRun: argv.dryRun,
|
|
473
|
+
useEditor: argv.editor,
|
|
474
|
+
})
|
|
369
475
|
|
|
370
|
-
if (result
|
|
476
|
+
if (result?.success) {
|
|
371
477
|
if (argv.dryRun) {
|
|
372
|
-
console.log(colors.successMessage('✅ Commit workflow completed (dry-run mode)'))
|
|
373
|
-
console.log(colors.highlight(`Proposed commit message:\n${result.commitMessage}`))
|
|
478
|
+
console.log(colors.successMessage('✅ Commit workflow completed (dry-run mode)'))
|
|
479
|
+
console.log(colors.highlight(`Proposed commit message:\n${result.commitMessage}`))
|
|
374
480
|
} else {
|
|
375
|
-
console.log(colors.successMessage('✅ Changes committed successfully!'))
|
|
376
|
-
console.log(colors.highlight(`Commit: ${result.commitHash}`))
|
|
377
|
-
console.log(colors.dim(`Message: ${result.commitMessage}`))
|
|
481
|
+
console.log(colors.successMessage('✅ Changes committed successfully!'))
|
|
482
|
+
console.log(colors.highlight(`Commit: ${result.commitHash}`))
|
|
483
|
+
console.log(colors.dim(`Message: ${result.commitMessage}`))
|
|
378
484
|
}
|
|
379
485
|
} else {
|
|
380
|
-
console.log(colors.warningMessage('Commit workflow cancelled or no changes to commit.'))
|
|
486
|
+
console.log(colors.warningMessage('Commit workflow cancelled or no changes to commit.'))
|
|
381
487
|
}
|
|
382
488
|
} catch (error) {
|
|
383
|
-
console.error(colors.errorMessage(`Commit workflow failed: ${error.message}`))
|
|
384
|
-
|
|
489
|
+
console.error(colors.errorMessage(`Commit workflow failed: ${error.message}`))
|
|
490
|
+
|
|
385
491
|
// Provide helpful suggestions based on error type
|
|
386
492
|
if (error.message.includes('No changes')) {
|
|
387
|
-
console.log(
|
|
493
|
+
console.log(
|
|
494
|
+
colors.infoMessage('💡 Try making some changes first, then run the commit command.')
|
|
495
|
+
)
|
|
388
496
|
} else if (error.message.includes('git')) {
|
|
389
|
-
console.log(
|
|
497
|
+
console.log(
|
|
498
|
+
colors.infoMessage(
|
|
499
|
+
'💡 Make sure you are in a git repository and git is properly configured.'
|
|
500
|
+
)
|
|
501
|
+
)
|
|
390
502
|
}
|
|
391
503
|
}
|
|
392
504
|
}
|
|
@@ -394,176 +506,180 @@ class CommitCommand extends BaseCommand {
|
|
|
394
506
|
|
|
395
507
|
class ProvidersCommand extends BaseCommand {
|
|
396
508
|
async execute(argv, appService) {
|
|
397
|
-
const subcommand = argv._[1]
|
|
509
|
+
const subcommand = argv._[1]
|
|
398
510
|
|
|
399
511
|
switch (subcommand) {
|
|
400
512
|
case 'list':
|
|
401
|
-
await this.listProviders(appService)
|
|
402
|
-
break
|
|
513
|
+
await this.listProviders(appService)
|
|
514
|
+
break
|
|
403
515
|
case 'switch':
|
|
404
|
-
await this.switchProvider(appService, argv.provider)
|
|
405
|
-
break
|
|
516
|
+
await this.switchProvider(appService, argv.provider)
|
|
517
|
+
break
|
|
406
518
|
case 'configure':
|
|
407
|
-
await this.configureProvider(appService, argv.provider)
|
|
408
|
-
break
|
|
519
|
+
await this.configureProvider(appService, argv.provider)
|
|
520
|
+
break
|
|
409
521
|
case 'validate':
|
|
410
|
-
await this.validateProvider(appService, argv.provider)
|
|
411
|
-
break
|
|
522
|
+
await this.validateProvider(appService, argv.provider)
|
|
523
|
+
break
|
|
412
524
|
default:
|
|
413
|
-
console.log(colors.errorMessage('Unknown provider subcommand'))
|
|
414
|
-
console.log(colors.infoMessage('Available subcommands: list, switch, configure, validate'))
|
|
525
|
+
console.log(colors.errorMessage('Unknown provider subcommand'))
|
|
526
|
+
console.log(colors.infoMessage('Available subcommands: list, switch, configure, validate'))
|
|
415
527
|
}
|
|
416
528
|
}
|
|
417
529
|
|
|
418
530
|
async listProviders(appService) {
|
|
419
531
|
try {
|
|
420
|
-
const providers = await appService.listProviders()
|
|
532
|
+
const providers = await appService.listProviders()
|
|
421
533
|
|
|
422
|
-
console.log(colors.header('\n🤖 Available AI Providers:'))
|
|
534
|
+
console.log(colors.header('\n🤖 Available AI Providers:'))
|
|
423
535
|
|
|
424
|
-
providers.forEach(provider => {
|
|
425
|
-
const status = provider.available ? '✅ Available' : '⚠️ Needs configuration'
|
|
426
|
-
const activeIndicator = provider.active ? ' 🎯 (Active)' : ''
|
|
536
|
+
providers.forEach((provider) => {
|
|
537
|
+
const status = provider.available ? '✅ Available' : '⚠️ Needs configuration'
|
|
538
|
+
const activeIndicator = provider.active ? ' 🎯 (Active)' : ''
|
|
427
539
|
|
|
428
|
-
console.log(` ${colors.highlight(provider.name)} - ${status}${activeIndicator}`)
|
|
540
|
+
console.log(` ${colors.highlight(provider.name)} - ${status}${activeIndicator}`)
|
|
429
541
|
|
|
430
542
|
if (provider.capabilities && Object.keys(provider.capabilities).length > 0) {
|
|
431
543
|
const caps = Object.entries(provider.capabilities)
|
|
432
|
-
.filter(([
|
|
544
|
+
.filter(([_key, value]) => value === true)
|
|
433
545
|
.map(([key]) => key)
|
|
434
|
-
.join(', ')
|
|
546
|
+
.join(', ')
|
|
435
547
|
if (caps) {
|
|
436
|
-
console.log(` ${colors.dim(`Capabilities: ${caps}`)}`)
|
|
548
|
+
console.log(` ${colors.dim(`Capabilities: ${caps}`)}`)
|
|
437
549
|
}
|
|
438
550
|
}
|
|
439
|
-
})
|
|
440
|
-
|
|
441
|
-
console.log(colors.dim('\nUse "ai-changelog providers configure <provider>" to set up a provider'));
|
|
551
|
+
})
|
|
442
552
|
|
|
553
|
+
console.log(
|
|
554
|
+
colors.dim('\nUse "ai-changelog providers configure <provider>" to set up a provider')
|
|
555
|
+
)
|
|
443
556
|
} catch (error) {
|
|
444
|
-
console.error(colors.errorMessage(`Error listing providers: ${error.message}`))
|
|
557
|
+
console.error(colors.errorMessage(`Error listing providers: ${error.message}`))
|
|
445
558
|
}
|
|
446
559
|
}
|
|
447
560
|
|
|
448
561
|
async switchProvider(appService, providerName) {
|
|
449
562
|
if (!providerName) {
|
|
450
|
-
console.log(colors.errorMessage('Please specify a provider name'))
|
|
451
|
-
console.log(colors.infoMessage('Usage: ai-changelog providers switch <provider>'))
|
|
452
|
-
return
|
|
563
|
+
console.log(colors.errorMessage('Please specify a provider name'))
|
|
564
|
+
console.log(colors.infoMessage('Usage: ai-changelog providers switch <provider>'))
|
|
565
|
+
return
|
|
453
566
|
}
|
|
454
567
|
|
|
455
568
|
try {
|
|
456
|
-
const result = await appService.switchProvider(providerName)
|
|
569
|
+
const result = await appService.switchProvider(providerName)
|
|
457
570
|
|
|
458
571
|
if (result.success) {
|
|
459
|
-
console.log(colors.successMessage(`✅ Switched to ${providerName} provider`))
|
|
572
|
+
console.log(colors.successMessage(`✅ Switched to ${providerName} provider`))
|
|
460
573
|
} else {
|
|
461
|
-
console.log(colors.errorMessage(`❌ Failed to switch provider: ${result.error}`))
|
|
462
|
-
console.log(
|
|
574
|
+
console.log(colors.errorMessage(`❌ Failed to switch provider: ${result.error}`))
|
|
575
|
+
console.log(
|
|
576
|
+
colors.infoMessage('Use "ai-changelog providers list" to see available providers')
|
|
577
|
+
)
|
|
463
578
|
}
|
|
464
579
|
} catch (error) {
|
|
465
|
-
console.error(colors.errorMessage(`Error switching provider: ${error.message}`))
|
|
580
|
+
console.error(colors.errorMessage(`Error switching provider: ${error.message}`))
|
|
466
581
|
}
|
|
467
582
|
}
|
|
468
583
|
|
|
469
584
|
async configureProvider(appService, providerName) {
|
|
470
|
-
const { select } = await import('@clack/prompts')
|
|
585
|
+
const { select } = await import('@clack/prompts')
|
|
471
586
|
|
|
472
587
|
try {
|
|
473
588
|
// If no provider specified, let user choose
|
|
474
589
|
if (!providerName) {
|
|
475
|
-
const providers = await appService.listProviders()
|
|
590
|
+
const providers = await appService.listProviders()
|
|
476
591
|
|
|
477
|
-
const choices = providers.map(p => ({
|
|
592
|
+
const choices = providers.map((p) => ({
|
|
478
593
|
value: p.name,
|
|
479
|
-
label: `${p.name} ${p.available ? '✅' : '⚠️ (needs configuration)'}
|
|
480
|
-
}))
|
|
594
|
+
label: `${p.name} ${p.available ? '✅' : '⚠️ (needs configuration)'}`,
|
|
595
|
+
}))
|
|
481
596
|
|
|
482
597
|
providerName = await select({
|
|
483
598
|
message: 'Select provider to configure:',
|
|
484
|
-
options: choices
|
|
485
|
-
})
|
|
599
|
+
options: choices,
|
|
600
|
+
})
|
|
486
601
|
}
|
|
487
602
|
|
|
488
|
-
console.log(colors.header(`\n🔧 Configuring ${providerName.toUpperCase()} Provider`))
|
|
489
|
-
console.log(colors.infoMessage('Please add the following to your .env.local file:\n'))
|
|
603
|
+
console.log(colors.header(`\n🔧 Configuring ${providerName.toUpperCase()} Provider`))
|
|
604
|
+
console.log(colors.infoMessage('Please add the following to your .env.local file:\n'))
|
|
490
605
|
|
|
491
606
|
switch (providerName.toLowerCase()) {
|
|
492
607
|
case 'openai':
|
|
493
|
-
console.log(colors.code('OPENAI_API_KEY=your_openai_api_key_here'))
|
|
494
|
-
console.log(colors.dim('Get your API key from: https://platform.openai.com/api-keys'))
|
|
495
|
-
break
|
|
608
|
+
console.log(colors.code('OPENAI_API_KEY=your_openai_api_key_here'))
|
|
609
|
+
console.log(colors.dim('Get your API key from: https://platform.openai.com/api-keys'))
|
|
610
|
+
break
|
|
496
611
|
|
|
497
612
|
case 'anthropic':
|
|
498
|
-
console.log(colors.code('ANTHROPIC_API_KEY=your_anthropic_api_key_here'))
|
|
499
|
-
console.log(colors.dim('Get your API key from: https://console.anthropic.com/'))
|
|
500
|
-
break
|
|
613
|
+
console.log(colors.code('ANTHROPIC_API_KEY=your_anthropic_api_key_here'))
|
|
614
|
+
console.log(colors.dim('Get your API key from: https://console.anthropic.com/'))
|
|
615
|
+
break
|
|
501
616
|
|
|
502
617
|
case 'azure':
|
|
503
|
-
console.log(colors.code('AZURE_OPENAI_API_KEY=your_azure_api_key_here'))
|
|
504
|
-
console.log(colors.code('AZURE_OPENAI_ENDPOINT=your_azure_endpoint_here'))
|
|
505
|
-
console.log(colors.dim('Get from your Azure OpenAI resource in Azure portal'))
|
|
506
|
-
break
|
|
618
|
+
console.log(colors.code('AZURE_OPENAI_API_KEY=your_azure_api_key_here'))
|
|
619
|
+
console.log(colors.code('AZURE_OPENAI_ENDPOINT=your_azure_endpoint_here'))
|
|
620
|
+
console.log(colors.dim('Get from your Azure OpenAI resource in Azure portal'))
|
|
621
|
+
break
|
|
507
622
|
|
|
508
623
|
case 'google':
|
|
509
|
-
console.log(colors.code('GOOGLE_API_KEY=your_google_api_key_here'))
|
|
510
|
-
console.log(colors.dim('Get your API key from: https://aistudio.google.com/app/apikey'))
|
|
511
|
-
break
|
|
624
|
+
console.log(colors.code('GOOGLE_API_KEY=your_google_api_key_here'))
|
|
625
|
+
console.log(colors.dim('Get your API key from: https://aistudio.google.com/app/apikey'))
|
|
626
|
+
break
|
|
512
627
|
|
|
513
628
|
case 'ollama':
|
|
514
|
-
console.log(colors.code('OLLAMA_HOST=http://localhost:11434'))
|
|
515
|
-
console.log(colors.dim('Make sure Ollama is running: ollama serve'))
|
|
516
|
-
break
|
|
629
|
+
console.log(colors.code('OLLAMA_HOST=http://localhost:11434'))
|
|
630
|
+
console.log(colors.dim('Make sure Ollama is running: ollama serve'))
|
|
631
|
+
break
|
|
517
632
|
|
|
518
633
|
default:
|
|
519
|
-
console.log(colors.code(`${providerName.toUpperCase()}_API_KEY=your_api_key_here`))
|
|
634
|
+
console.log(colors.code(`${providerName.toUpperCase()}_API_KEY=your_api_key_here`))
|
|
520
635
|
}
|
|
521
636
|
|
|
522
|
-
console.log(colors.infoMessage('\nAfter adding the configuration, run:'))
|
|
523
|
-
console.log(colors.highlight(`ai-changelog providers validate ${providerName}`))
|
|
524
|
-
|
|
637
|
+
console.log(colors.infoMessage('\nAfter adding the configuration, run:'))
|
|
638
|
+
console.log(colors.highlight(`ai-changelog providers validate ${providerName}`))
|
|
525
639
|
} catch (error) {
|
|
526
|
-
console.error(colors.errorMessage(`Error configuring provider: ${error.message}`))
|
|
640
|
+
console.error(colors.errorMessage(`Error configuring provider: ${error.message}`))
|
|
527
641
|
}
|
|
528
642
|
}
|
|
529
643
|
|
|
530
644
|
async validateProvider(appService, providerName) {
|
|
531
645
|
try {
|
|
532
646
|
if (!providerName) {
|
|
533
|
-
console.log(colors.processingMessage('🔍 Validating all configured providers...'))
|
|
534
|
-
const result = await appService.validateAllProviders()
|
|
647
|
+
console.log(colors.processingMessage('🔍 Validating all configured providers...'))
|
|
648
|
+
const result = await appService.validateAllProviders()
|
|
535
649
|
|
|
536
|
-
console.log(colors.header('\n📊 Provider Validation Results:'))
|
|
650
|
+
console.log(colors.header('\n📊 Provider Validation Results:'))
|
|
537
651
|
|
|
538
652
|
Object.entries(result).forEach(([name, validation]) => {
|
|
539
|
-
const status = validation.success ? '✅ Valid' : '❌ Invalid'
|
|
540
|
-
console.log(` ${colors.highlight(name)}: ${status}`)
|
|
653
|
+
const status = validation.success ? '✅ Valid' : '❌ Invalid'
|
|
654
|
+
console.log(` ${colors.highlight(name)}: ${status}`)
|
|
541
655
|
|
|
542
656
|
if (!validation.success) {
|
|
543
|
-
console.log(` ${colors.errorMessage(validation.error)}`)
|
|
657
|
+
console.log(` ${colors.errorMessage(validation.error)}`)
|
|
544
658
|
}
|
|
545
|
-
})
|
|
546
|
-
|
|
659
|
+
})
|
|
547
660
|
} else {
|
|
548
|
-
console.log(colors.processingMessage(`🔍 Validating ${providerName} provider...`))
|
|
549
|
-
const result = await appService.validateProvider(providerName)
|
|
661
|
+
console.log(colors.processingMessage(`🔍 Validating ${providerName} provider...`))
|
|
662
|
+
const result = await appService.validateProvider(providerName)
|
|
550
663
|
|
|
551
664
|
if (result.success) {
|
|
552
|
-
console.log(colors.successMessage(`✅ ${providerName} provider is configured correctly`))
|
|
665
|
+
console.log(colors.successMessage(`✅ ${providerName} provider is configured correctly`))
|
|
553
666
|
if (result.model) {
|
|
554
|
-
console.log(colors.dim(` Default model: ${result.model}`))
|
|
667
|
+
console.log(colors.dim(` Default model: ${result.model}`))
|
|
555
668
|
}
|
|
556
669
|
} else {
|
|
557
|
-
console.log(colors.errorMessage(`❌ ${providerName} validation failed: ${result.error}`))
|
|
558
|
-
console.log(
|
|
670
|
+
console.log(colors.errorMessage(`❌ ${providerName} validation failed: ${result.error}`))
|
|
671
|
+
console.log(
|
|
672
|
+
colors.infoMessage(
|
|
673
|
+
`Use "ai-changelog providers configure ${providerName}" for setup instructions`
|
|
674
|
+
)
|
|
675
|
+
)
|
|
559
676
|
}
|
|
560
677
|
}
|
|
561
|
-
|
|
562
678
|
} catch (error) {
|
|
563
|
-
console.error(colors.errorMessage(`Error validating provider: ${error.message}`))
|
|
679
|
+
console.error(colors.errorMessage(`Error validating provider: ${error.message}`))
|
|
564
680
|
}
|
|
565
681
|
}
|
|
566
682
|
}
|
|
567
683
|
|
|
568
684
|
// Export the controller
|
|
569
|
-
export default CLIController
|
|
685
|
+
export default CLIController
|