@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,9 +1,10 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import process from 'node:process'
|
|
4
|
+
|
|
5
|
+
import yaml from 'js-yaml'
|
|
6
|
+
|
|
7
|
+
import colors from '../../shared/constants/colors.js'
|
|
7
8
|
|
|
8
9
|
// Model configurations - moved from lib/utils/model-config.js
|
|
9
10
|
const MODEL_CONFIGS = {
|
|
@@ -11,14 +12,14 @@ const MODEL_CONFIGS = {
|
|
|
11
12
|
'gpt-3.5-turbo': { maxTokens: 4096, cost: 0.002 },
|
|
12
13
|
'claude-3-opus': { maxTokens: 200000, cost: 0.015 },
|
|
13
14
|
'claude-3-sonnet': { maxTokens: 200000, cost: 0.003 },
|
|
14
|
-
'claude-3-haiku': { maxTokens: 200000, cost: 0.00025 }
|
|
15
|
-
}
|
|
15
|
+
'claude-3-haiku': { maxTokens: 200000, cost: 0.00025 },
|
|
16
|
+
}
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Unified Configuration Manager
|
|
19
20
|
* Consolidates config.js, model-config.js, and interactive-config.js logic
|
|
20
21
|
* Enhanced with YAML changelog configuration support
|
|
21
|
-
*
|
|
22
|
+
*
|
|
22
23
|
* Responsibilities:
|
|
23
24
|
* - Environment configuration loading
|
|
24
25
|
* - Model configuration management
|
|
@@ -28,12 +29,12 @@ const MODEL_CONFIGS = {
|
|
|
28
29
|
*/
|
|
29
30
|
export class ConfigurationManager {
|
|
30
31
|
constructor(configPath = null, changelogConfigPath = null) {
|
|
31
|
-
this.configPath = configPath || this.findConfigFile()
|
|
32
|
-
this.changelogConfigPath = changelogConfigPath || this.findChangelogConfigFile()
|
|
33
|
-
this.config = this.loadConfig()
|
|
34
|
-
this.changelogConfig = this.loadChangelogConfig()
|
|
35
|
-
this.modelConfigs = MODEL_CONFIGS
|
|
36
|
-
this.validate()
|
|
32
|
+
this.configPath = configPath || this.findConfigFile()
|
|
33
|
+
this.changelogConfigPath = changelogConfigPath || this.findChangelogConfigFile()
|
|
34
|
+
this.config = this.loadConfig()
|
|
35
|
+
this.changelogConfig = this.loadChangelogConfig()
|
|
36
|
+
this.modelConfigs = MODEL_CONFIGS
|
|
37
|
+
this.validate()
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
findConfigFile() {
|
|
@@ -41,16 +42,16 @@ export class ConfigurationManager {
|
|
|
41
42
|
'.env.local',
|
|
42
43
|
'.changelog.config.js',
|
|
43
44
|
'changelog.config.json',
|
|
44
|
-
path.join(process.cwd(), '.env.local')
|
|
45
|
-
]
|
|
45
|
+
path.join(process.cwd(), '.env.local'),
|
|
46
|
+
]
|
|
46
47
|
|
|
47
48
|
for (const configPath of possiblePaths) {
|
|
48
49
|
if (fs.existsSync(configPath)) {
|
|
49
|
-
return configPath
|
|
50
|
+
return configPath
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
return '.env.local'
|
|
54
|
+
return '.env.local' // Default
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
findChangelogConfigFile() {
|
|
@@ -60,16 +61,16 @@ export class ConfigurationManager {
|
|
|
60
61
|
'.ai-changelog.yaml',
|
|
61
62
|
'.ai-changelog.yml',
|
|
62
63
|
'changelog.config.yaml',
|
|
63
|
-
'changelog.config.yml'
|
|
64
|
-
]
|
|
64
|
+
'changelog.config.yml',
|
|
65
|
+
]
|
|
65
66
|
|
|
66
67
|
for (const configPath of possiblePaths) {
|
|
67
68
|
if (fs.existsSync(configPath)) {
|
|
68
|
-
return configPath
|
|
69
|
+
return configPath
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
return null
|
|
73
|
+
return null // No changelog config found
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
loadConfig() {
|
|
@@ -100,30 +101,32 @@ export class ConfigurationManager {
|
|
|
100
101
|
// General Settings
|
|
101
102
|
GIT_PATH: process.env.GIT_PATH || process.cwd(),
|
|
102
103
|
DEFAULT_ANALYSIS_MODE: process.env.DEFAULT_ANALYSIS_MODE || 'standard',
|
|
103
|
-
RATE_LIMIT_DELAY: parseInt(process.env.RATE_LIMIT_DELAY || '1000'),
|
|
104
|
-
MAX_RETRIES: parseInt(process.env.MAX_RETRIES || '3'),
|
|
104
|
+
RATE_LIMIT_DELAY: Number.parseInt(process.env.RATE_LIMIT_DELAY || '1000', 10),
|
|
105
|
+
MAX_RETRIES: Number.parseInt(process.env.MAX_RETRIES || '3', 10),
|
|
105
106
|
|
|
106
107
|
// Output Settings
|
|
107
108
|
OUTPUT_FORMAT: process.env.OUTPUT_FORMAT || 'markdown',
|
|
108
109
|
INCLUDE_ATTRIBUTION: process.env.INCLUDE_ATTRIBUTION !== 'false',
|
|
109
|
-
|
|
110
|
+
|
|
110
111
|
// Debug Settings
|
|
111
112
|
DEBUG: process.env.DEBUG === 'true',
|
|
112
|
-
VERBOSE: process.env.VERBOSE === 'true'
|
|
113
|
-
}
|
|
113
|
+
VERBOSE: process.env.VERBOSE === 'true',
|
|
114
|
+
}
|
|
114
115
|
|
|
115
116
|
// Load from .env.local if it exists
|
|
116
117
|
if (fs.existsSync(this.configPath)) {
|
|
117
118
|
try {
|
|
118
|
-
const content = fs.readFileSync(this.configPath, 'utf8')
|
|
119
|
-
const envVars = this.parseEnvFile(content)
|
|
120
|
-
Object.assign(defaults, envVars)
|
|
121
|
-
} catch (
|
|
122
|
-
console.warn(
|
|
119
|
+
const content = fs.readFileSync(this.configPath, 'utf8')
|
|
120
|
+
const envVars = this.parseEnvFile(content)
|
|
121
|
+
Object.assign(defaults, envVars)
|
|
122
|
+
} catch (_error) {
|
|
123
|
+
console.warn(
|
|
124
|
+
colors.warningMessage(`Warning: Could not load config from ${this.configPath}`)
|
|
125
|
+
)
|
|
123
126
|
}
|
|
124
127
|
}
|
|
125
128
|
|
|
126
|
-
return defaults
|
|
129
|
+
return defaults
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
loadChangelogConfig() {
|
|
@@ -131,21 +134,21 @@ export class ConfigurationManager {
|
|
|
131
134
|
const defaultConfig = {
|
|
132
135
|
convention: {
|
|
133
136
|
commitTypes: [
|
|
134
|
-
'feat',
|
|
135
|
-
'fix',
|
|
136
|
-
'docs',
|
|
137
|
-
'style',
|
|
137
|
+
'feat', // Features
|
|
138
|
+
'fix', // Bug fixes
|
|
139
|
+
'docs', // Documentation
|
|
140
|
+
'style', // Code style (formatting, missing semicolons, etc)
|
|
138
141
|
'refactor', // Code refactoring
|
|
139
|
-
'perf',
|
|
140
|
-
'test',
|
|
141
|
-
'build',
|
|
142
|
-
'ci',
|
|
143
|
-
'chore',
|
|
144
|
-
'revert',
|
|
145
|
-
'merge'
|
|
142
|
+
'perf', // Performance improvements
|
|
143
|
+
'test', // Tests
|
|
144
|
+
'build', // Build system or external dependencies
|
|
145
|
+
'ci', // CI/CD changes
|
|
146
|
+
'chore', // Maintenance tasks
|
|
147
|
+
'revert', // Reverting commits
|
|
148
|
+
'merge', // Merge commits
|
|
146
149
|
],
|
|
147
150
|
commitScopes: [],
|
|
148
|
-
releaseTagGlobPattern: 'v[0-9]*.[0-9]*.[0-9]*'
|
|
151
|
+
releaseTagGlobPattern: 'v[0-9]*.[0-9]*.[0-9]*',
|
|
149
152
|
},
|
|
150
153
|
changelog: {
|
|
151
154
|
commitTypes: ['feat', 'fix', 'perf', 'refactor', 'docs'],
|
|
@@ -164,212 +167,237 @@ export class ConfigurationManager {
|
|
|
164
167
|
style: '💄 Code Style',
|
|
165
168
|
revert: '⏪ Reverts',
|
|
166
169
|
merge: '🔀 Merges',
|
|
167
|
-
breakingChange: '🚨 BREAKING CHANGES'
|
|
170
|
+
breakingChange: '🚨 BREAKING CHANGES',
|
|
168
171
|
},
|
|
169
172
|
// Link generation support
|
|
170
173
|
commitUrl: null,
|
|
171
174
|
commitRangeUrl: null,
|
|
172
175
|
issueUrl: null,
|
|
173
|
-
issueRegexPattern: '#[0-9]+'
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
+
issueRegexPattern: '#[0-9]+',
|
|
177
|
+
},
|
|
178
|
+
}
|
|
176
179
|
|
|
177
180
|
if (!this.changelogConfigPath) {
|
|
178
|
-
return defaultConfig
|
|
181
|
+
return defaultConfig
|
|
179
182
|
}
|
|
180
183
|
|
|
181
184
|
try {
|
|
182
|
-
const content = fs.readFileSync(this.changelogConfigPath, 'utf8')
|
|
183
|
-
const yamlConfig = yaml.load(content)
|
|
184
|
-
|
|
185
|
+
const content = fs.readFileSync(this.changelogConfigPath, 'utf8')
|
|
186
|
+
const yamlConfig = yaml.load(content)
|
|
187
|
+
|
|
185
188
|
// Deep merge with defaults
|
|
186
|
-
return this.deepMergeConfig(defaultConfig, yamlConfig)
|
|
187
|
-
} catch (
|
|
188
|
-
console.warn(
|
|
189
|
-
|
|
189
|
+
return this.deepMergeConfig(defaultConfig, yamlConfig)
|
|
190
|
+
} catch (_error) {
|
|
191
|
+
console.warn(
|
|
192
|
+
colors.warningMessage(
|
|
193
|
+
`Warning: Could not load changelog config from ${this.changelogConfigPath}, using defaults`
|
|
194
|
+
)
|
|
195
|
+
)
|
|
196
|
+
return defaultConfig
|
|
190
197
|
}
|
|
191
198
|
}
|
|
192
199
|
|
|
193
200
|
deepMergeConfig(defaults, override) {
|
|
194
|
-
const result = JSON.parse(JSON.stringify(defaults))
|
|
195
|
-
|
|
201
|
+
const result = JSON.parse(JSON.stringify(defaults))
|
|
202
|
+
|
|
196
203
|
if (!override || typeof override !== 'object') {
|
|
197
|
-
return result
|
|
204
|
+
return result
|
|
198
205
|
}
|
|
199
206
|
|
|
200
207
|
for (const key in override) {
|
|
201
208
|
if (override[key] && typeof override[key] === 'object' && !Array.isArray(override[key])) {
|
|
202
|
-
result[key] = this.deepMergeConfig(result[key] || {}, override[key])
|
|
209
|
+
result[key] = this.deepMergeConfig(result[key] || {}, override[key])
|
|
203
210
|
} else {
|
|
204
|
-
result[key] = override[key]
|
|
211
|
+
result[key] = override[key]
|
|
205
212
|
}
|
|
206
213
|
}
|
|
207
214
|
|
|
208
|
-
return result
|
|
215
|
+
return result
|
|
209
216
|
}
|
|
210
217
|
|
|
211
218
|
parseEnvFile(content) {
|
|
212
|
-
const envVars = {}
|
|
213
|
-
const lines = content.split('\n')
|
|
214
|
-
|
|
219
|
+
const envVars = {}
|
|
220
|
+
const lines = content.split('\n')
|
|
221
|
+
|
|
215
222
|
for (const line of lines) {
|
|
216
|
-
const trimmed = line.trim()
|
|
223
|
+
const trimmed = line.trim()
|
|
217
224
|
if (trimmed && !trimmed.startsWith('#')) {
|
|
218
|
-
const [key, ...valueParts] = trimmed.split('=')
|
|
225
|
+
const [key, ...valueParts] = trimmed.split('=')
|
|
219
226
|
if (key && valueParts.length > 0) {
|
|
220
|
-
const value = valueParts.join('=').replace(/^["']|["']$/g, '')
|
|
221
|
-
envVars[key.trim()] = value
|
|
227
|
+
const value = valueParts.join('=').replace(/^["']|["']$/g, '')
|
|
228
|
+
envVars[key.trim()] = value
|
|
222
229
|
}
|
|
223
230
|
}
|
|
224
231
|
}
|
|
225
|
-
|
|
226
|
-
return envVars
|
|
232
|
+
|
|
233
|
+
return envVars
|
|
227
234
|
}
|
|
228
235
|
|
|
229
236
|
validate() {
|
|
230
|
-
const issues = []
|
|
231
|
-
const recommendations = []
|
|
237
|
+
const issues = []
|
|
238
|
+
const recommendations = []
|
|
232
239
|
|
|
233
240
|
// Check for AI provider configuration
|
|
234
|
-
const hasAnyProvider =
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
241
|
+
const hasAnyProvider =
|
|
242
|
+
this.hasOpenAI() ||
|
|
243
|
+
this.hasAnthropic() ||
|
|
244
|
+
this.hasGoogle() ||
|
|
245
|
+
this.hasHuggingFace() ||
|
|
246
|
+
this.hasOllama() ||
|
|
247
|
+
this.hasAzureOpenAI() ||
|
|
248
|
+
this.hasVertexAI() ||
|
|
249
|
+
this.hasLMStudio()
|
|
238
250
|
|
|
239
251
|
if (!hasAnyProvider) {
|
|
240
|
-
issues.push('No AI provider configured')
|
|
241
|
-
recommendations.push('Configure at least one AI provider (OpenAI, Anthropic, Google, etc.)')
|
|
252
|
+
issues.push('No AI provider configured')
|
|
253
|
+
recommendations.push('Configure at least one AI provider (OpenAI, Anthropic, Google, etc.)')
|
|
242
254
|
}
|
|
243
255
|
|
|
244
256
|
// Git path validation
|
|
245
257
|
if (!fs.existsSync(this.config.GIT_PATH)) {
|
|
246
|
-
issues.push('Git path does not exist')
|
|
247
|
-
recommendations.push('Set GIT_PATH to a valid git repository')
|
|
258
|
+
issues.push('Git path does not exist')
|
|
259
|
+
recommendations.push('Set GIT_PATH to a valid git repository')
|
|
248
260
|
}
|
|
249
261
|
|
|
250
262
|
// Provider-specific validations
|
|
251
263
|
if (this.config.AI_PROVIDER === 'azure' && !this.hasAzureOpenAI()) {
|
|
252
|
-
issues.push('Azure OpenAI selected but not properly configured')
|
|
253
|
-
recommendations.push('Set AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_KEY')
|
|
264
|
+
issues.push('Azure OpenAI selected but not properly configured')
|
|
265
|
+
recommendations.push('Set AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_KEY')
|
|
254
266
|
}
|
|
255
267
|
|
|
256
268
|
if (this.config.AI_PROVIDER === 'vertex' && !this.hasVertexAI()) {
|
|
257
|
-
issues.push('Vertex AI selected but not properly configured')
|
|
258
|
-
recommendations.push('Set VERTEX_PROJECT_ID and GOOGLE_APPLICATION_CREDENTIALS')
|
|
269
|
+
issues.push('Vertex AI selected but not properly configured')
|
|
270
|
+
recommendations.push('Set VERTEX_PROJECT_ID and GOOGLE_APPLICATION_CREDENTIALS')
|
|
259
271
|
}
|
|
260
272
|
|
|
261
|
-
this.validationResult = { issues, recommendations }
|
|
273
|
+
this.validationResult = { issues, recommendations }
|
|
262
274
|
}
|
|
263
275
|
|
|
264
276
|
// Provider availability checks
|
|
265
277
|
hasOpenAI() {
|
|
266
|
-
return !!this.config.OPENAI_API_KEY
|
|
278
|
+
return !!this.config.OPENAI_API_KEY
|
|
267
279
|
}
|
|
268
280
|
|
|
269
281
|
hasAnthropic() {
|
|
270
|
-
return !!this.config.ANTHROPIC_API_KEY
|
|
282
|
+
return !!this.config.ANTHROPIC_API_KEY
|
|
271
283
|
}
|
|
272
284
|
|
|
273
285
|
hasGoogle() {
|
|
274
|
-
return !!this.config.GOOGLE_API_KEY
|
|
286
|
+
return !!this.config.GOOGLE_API_KEY
|
|
275
287
|
}
|
|
276
288
|
|
|
277
289
|
hasHuggingFace() {
|
|
278
|
-
return !!this.config.HUGGINGFACE_API_KEY
|
|
290
|
+
return !!this.config.HUGGINGFACE_API_KEY
|
|
279
291
|
}
|
|
280
292
|
|
|
281
293
|
hasOllama() {
|
|
282
|
-
return !!this.config.OLLAMA_HOST
|
|
294
|
+
return !!this.config.OLLAMA_HOST
|
|
283
295
|
}
|
|
284
296
|
|
|
285
297
|
hasAzureOpenAI() {
|
|
286
|
-
return !!(this.config.AZURE_OPENAI_ENDPOINT && this.config.AZURE_OPENAI_KEY)
|
|
298
|
+
return !!(this.config.AZURE_OPENAI_ENDPOINT && this.config.AZURE_OPENAI_KEY)
|
|
287
299
|
}
|
|
288
300
|
|
|
289
301
|
hasVertexAI() {
|
|
290
|
-
return !!(this.config.VERTEX_PROJECT_ID && this.config.GOOGLE_APPLICATION_CREDENTIALS)
|
|
302
|
+
return !!(this.config.VERTEX_PROJECT_ID && this.config.GOOGLE_APPLICATION_CREDENTIALS)
|
|
291
303
|
}
|
|
292
304
|
|
|
293
305
|
hasLMStudio() {
|
|
294
|
-
return !!this.config.LMSTUDIO_BASE_URL
|
|
306
|
+
return !!this.config.LMSTUDIO_BASE_URL
|
|
295
307
|
}
|
|
296
308
|
|
|
297
309
|
// Model configuration methods
|
|
298
|
-
getOptimalModelConfig(analysisMode = 'standard',
|
|
310
|
+
getOptimalModelConfig(analysisMode = 'standard', _complexity = 'medium') {
|
|
299
311
|
const modes = {
|
|
300
312
|
simple: 'simple',
|
|
301
|
-
standard: 'standard',
|
|
313
|
+
standard: 'standard',
|
|
302
314
|
detailed: 'complex',
|
|
303
|
-
enterprise: 'complex'
|
|
304
|
-
}
|
|
315
|
+
enterprise: 'complex',
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const modelType = modes[analysisMode] || 'standard'
|
|
305
319
|
|
|
306
|
-
const modelType = modes[analysisMode] || 'standard';
|
|
307
|
-
|
|
308
320
|
// Return configuration for the active provider
|
|
309
|
-
const provider = this.getActiveProvider()
|
|
310
|
-
const providerConfig = this.modelConfigs[provider]
|
|
311
|
-
|
|
321
|
+
const provider = this.getActiveProvider()
|
|
322
|
+
const providerConfig = this.modelConfigs[provider]
|
|
323
|
+
|
|
312
324
|
if (!providerConfig) {
|
|
313
|
-
return { model: 'auto', capabilities: {} }
|
|
325
|
+
return { model: 'auto', capabilities: {} }
|
|
314
326
|
}
|
|
315
327
|
|
|
316
|
-
const modelKey = `${modelType}Model
|
|
317
|
-
const model = providerConfig[modelKey] || providerConfig.standardModel
|
|
318
|
-
|
|
328
|
+
const modelKey = `${modelType}Model`
|
|
329
|
+
const model = providerConfig[modelKey] || providerConfig.standardModel
|
|
330
|
+
|
|
319
331
|
return {
|
|
320
332
|
model,
|
|
321
333
|
capabilities: providerConfig.capabilities || {},
|
|
322
334
|
contextWindow: providerConfig.contextWindow || 8192,
|
|
323
|
-
maxTokens: providerConfig.maxTokens || 4096
|
|
324
|
-
}
|
|
335
|
+
maxTokens: providerConfig.maxTokens || 4096,
|
|
336
|
+
}
|
|
325
337
|
}
|
|
326
338
|
|
|
327
339
|
getModelRecommendation(commitInfo) {
|
|
328
|
-
const { files = 0, lines = 0, breaking = false, complex = false } = commitInfo
|
|
329
|
-
|
|
340
|
+
const { files = 0, lines = 0, breaking = false, complex = false } = commitInfo
|
|
341
|
+
|
|
330
342
|
// Determine complexity
|
|
331
|
-
let analysisMode = 'standard'
|
|
332
|
-
|
|
343
|
+
let analysisMode = 'standard'
|
|
344
|
+
|
|
333
345
|
if (breaking || complex || files > 20 || lines > 500) {
|
|
334
|
-
analysisMode = 'detailed'
|
|
346
|
+
analysisMode = 'detailed'
|
|
335
347
|
} else if (files > 5 || lines > 100) {
|
|
336
|
-
analysisMode = 'standard'
|
|
348
|
+
analysisMode = 'standard'
|
|
337
349
|
} else {
|
|
338
|
-
analysisMode = 'simple'
|
|
350
|
+
analysisMode = 'simple'
|
|
339
351
|
}
|
|
340
|
-
|
|
341
|
-
return this.getOptimalModelConfig(analysisMode)
|
|
352
|
+
|
|
353
|
+
return this.getOptimalModelConfig(analysisMode)
|
|
342
354
|
}
|
|
343
355
|
|
|
344
356
|
getActiveProvider() {
|
|
345
357
|
if (this.config.AI_PROVIDER !== 'auto') {
|
|
346
|
-
return this.config.AI_PROVIDER
|
|
358
|
+
return this.config.AI_PROVIDER
|
|
347
359
|
}
|
|
348
360
|
|
|
349
361
|
// Auto-detect available provider
|
|
350
|
-
if (this.hasOpenAI())
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
if (this.
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
if (this.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
362
|
+
if (this.hasOpenAI()) {
|
|
363
|
+
return 'openai'
|
|
364
|
+
}
|
|
365
|
+
if (this.hasAnthropic()) {
|
|
366
|
+
return 'anthropic'
|
|
367
|
+
}
|
|
368
|
+
if (this.hasGoogle()) {
|
|
369
|
+
return 'google'
|
|
370
|
+
}
|
|
371
|
+
if (this.hasAzureOpenAI()) {
|
|
372
|
+
return 'azure'
|
|
373
|
+
}
|
|
374
|
+
if (this.hasVertexAI()) {
|
|
375
|
+
return 'vertex'
|
|
376
|
+
}
|
|
377
|
+
if (this.hasOllama()) {
|
|
378
|
+
return 'ollama'
|
|
379
|
+
}
|
|
380
|
+
if (this.hasHuggingFace()) {
|
|
381
|
+
return 'huggingface'
|
|
382
|
+
}
|
|
383
|
+
if (this.hasLMStudio()) {
|
|
384
|
+
return 'lmstudio'
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return 'none'
|
|
360
388
|
}
|
|
361
389
|
|
|
362
390
|
// Configuration getters
|
|
363
391
|
get(key) {
|
|
364
|
-
return this.config[key]
|
|
392
|
+
return this.config[key]
|
|
365
393
|
}
|
|
366
394
|
|
|
367
395
|
getAll() {
|
|
368
|
-
return { ...this.config }
|
|
396
|
+
return { ...this.config }
|
|
369
397
|
}
|
|
370
398
|
|
|
371
399
|
set(key, value) {
|
|
372
|
-
this.config[key] = value
|
|
400
|
+
this.config[key] = value
|
|
373
401
|
}
|
|
374
402
|
|
|
375
403
|
// Provider configuration
|
|
@@ -377,41 +405,41 @@ export class ConfigurationManager {
|
|
|
377
405
|
const configs = {
|
|
378
406
|
openai: {
|
|
379
407
|
apiKey: this.config.OPENAI_API_KEY,
|
|
380
|
-
baseURL: 'https://api.openai.com/v1'
|
|
408
|
+
baseURL: 'https://api.openai.com/v1',
|
|
381
409
|
},
|
|
382
410
|
anthropic: {
|
|
383
411
|
apiKey: this.config.ANTHROPIC_API_KEY,
|
|
384
|
-
baseURL: 'https://api.anthropic.com/v1'
|
|
412
|
+
baseURL: 'https://api.anthropic.com/v1',
|
|
385
413
|
},
|
|
386
414
|
google: {
|
|
387
415
|
apiKey: this.config.GOOGLE_API_KEY,
|
|
388
|
-
baseURL: 'https://generativelanguage.googleapis.com/v1'
|
|
416
|
+
baseURL: 'https://generativelanguage.googleapis.com/v1',
|
|
389
417
|
},
|
|
390
418
|
azure: {
|
|
391
419
|
apiKey: this.config.AZURE_OPENAI_KEY,
|
|
392
420
|
endpoint: this.config.AZURE_OPENAI_ENDPOINT,
|
|
393
421
|
deploymentName: this.config.AZURE_OPENAI_DEPLOYMENT_NAME,
|
|
394
|
-
apiVersion: this.config.AZURE_OPENAI_API_VERSION
|
|
422
|
+
apiVersion: this.config.AZURE_OPENAI_API_VERSION,
|
|
395
423
|
},
|
|
396
424
|
vertex: {
|
|
397
425
|
projectId: this.config.VERTEX_PROJECT_ID,
|
|
398
426
|
location: this.config.VERTEX_LOCATION,
|
|
399
|
-
credentials: this.config.GOOGLE_APPLICATION_CREDENTIALS
|
|
427
|
+
credentials: this.config.GOOGLE_APPLICATION_CREDENTIALS,
|
|
400
428
|
},
|
|
401
429
|
ollama: {
|
|
402
430
|
host: this.config.OLLAMA_HOST,
|
|
403
|
-
model: this.config.OLLAMA_MODEL
|
|
431
|
+
model: this.config.OLLAMA_MODEL,
|
|
404
432
|
},
|
|
405
433
|
huggingface: {
|
|
406
434
|
apiKey: this.config.HUGGINGFACE_API_KEY,
|
|
407
|
-
baseURL: 'https://api-inference.huggingface.co'
|
|
435
|
+
baseURL: 'https://api-inference.huggingface.co',
|
|
408
436
|
},
|
|
409
437
|
lmstudio: {
|
|
410
|
-
baseURL: this.config.LMSTUDIO_BASE_URL
|
|
411
|
-
}
|
|
412
|
-
}
|
|
438
|
+
baseURL: this.config.LMSTUDIO_BASE_URL,
|
|
439
|
+
},
|
|
440
|
+
}
|
|
413
441
|
|
|
414
|
-
return configs[providerName] || {}
|
|
442
|
+
return configs[providerName] || {}
|
|
415
443
|
}
|
|
416
444
|
|
|
417
445
|
// Environment setup helpers
|
|
@@ -424,115 +452,117 @@ export class ConfigurationManager {
|
|
|
424
452
|
vertex: ['VERTEX_PROJECT_ID', 'GOOGLE_APPLICATION_CREDENTIALS'],
|
|
425
453
|
huggingface: ['HUGGINGFACE_API_KEY'],
|
|
426
454
|
ollama: ['OLLAMA_HOST'],
|
|
427
|
-
lmstudio: ['LMSTUDIO_BASE_URL']
|
|
428
|
-
}
|
|
455
|
+
lmstudio: ['LMSTUDIO_BASE_URL'],
|
|
456
|
+
}
|
|
429
457
|
|
|
430
|
-
return requirements[provider] || []
|
|
458
|
+
return requirements[provider] || []
|
|
431
459
|
}
|
|
432
460
|
|
|
433
461
|
validateProvider(providerName) {
|
|
434
|
-
const required = this.getRequiredEnvVars(providerName)
|
|
435
|
-
const missing = required.filter(key => !this.config[key])
|
|
436
|
-
|
|
462
|
+
const required = this.getRequiredEnvVars(providerName)
|
|
463
|
+
const missing = required.filter((key) => !this.config[key])
|
|
464
|
+
|
|
437
465
|
return {
|
|
438
466
|
valid: missing.length === 0,
|
|
439
467
|
missing,
|
|
440
|
-
configured: required.filter(key => !!this.config[key])
|
|
441
|
-
}
|
|
468
|
+
configured: required.filter((key) => !!this.config[key]),
|
|
469
|
+
}
|
|
442
470
|
}
|
|
443
471
|
|
|
444
472
|
// Configuration update methods
|
|
445
473
|
async updateConfig(updates) {
|
|
446
|
-
Object.assign(this.config, updates)
|
|
447
|
-
await this.saveConfig()
|
|
448
|
-
this.validate()
|
|
474
|
+
Object.assign(this.config, updates)
|
|
475
|
+
await this.saveConfig()
|
|
476
|
+
this.validate()
|
|
449
477
|
}
|
|
450
478
|
|
|
451
479
|
async saveConfig() {
|
|
452
480
|
try {
|
|
453
481
|
const envContent = Object.entries(this.config)
|
|
454
482
|
.map(([key, value]) => `${key}=${value || ''}`)
|
|
455
|
-
.join('\n')
|
|
456
|
-
|
|
457
|
-
await fs.promises.writeFile(this.configPath, envContent, 'utf8')
|
|
458
|
-
console.log(colors.successMessage(`✅ Configuration saved to ${this.configPath}`))
|
|
483
|
+
.join('\n')
|
|
484
|
+
|
|
485
|
+
await fs.promises.writeFile(this.configPath, envContent, 'utf8')
|
|
486
|
+
console.log(colors.successMessage(`✅ Configuration saved to ${this.configPath}`))
|
|
459
487
|
} catch (error) {
|
|
460
|
-
console.error(colors.errorMessage(`Failed to save configuration: ${error.message}`))
|
|
461
|
-
throw error
|
|
488
|
+
console.error(colors.errorMessage(`Failed to save configuration: ${error.message}`))
|
|
489
|
+
throw error
|
|
462
490
|
}
|
|
463
491
|
}
|
|
464
492
|
|
|
465
493
|
// Validation results
|
|
466
494
|
getValidationResult() {
|
|
467
|
-
return this.validationResult
|
|
495
|
+
return this.validationResult
|
|
468
496
|
}
|
|
469
497
|
|
|
470
498
|
isValid() {
|
|
471
|
-
return this.validationResult.issues.length === 0
|
|
499
|
+
return this.validationResult.issues.length === 0
|
|
472
500
|
}
|
|
473
501
|
|
|
474
502
|
// Debug and logging
|
|
475
503
|
logConfiguration() {
|
|
476
|
-
if (!this.config.DEBUG)
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
console.log(
|
|
481
|
-
console.log(`
|
|
482
|
-
console.log(`
|
|
483
|
-
|
|
504
|
+
if (!this.config.DEBUG) {
|
|
505
|
+
return
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
console.log(colors.header('🔧 Configuration Debug:'))
|
|
509
|
+
console.log(`Config path: ${colors.file(this.configPath)}`)
|
|
510
|
+
console.log(`Changelog config path: ${colors.file(this.changelogConfigPath || 'default')}`)
|
|
511
|
+
console.log(`Active provider: ${colors.highlight(this.getActiveProvider())}`)
|
|
512
|
+
console.log(`Git path: ${colors.file(this.config.GIT_PATH)}`)
|
|
513
|
+
|
|
484
514
|
if (this.validationResult.issues.length > 0) {
|
|
485
|
-
console.log(colors.warningMessage('Issues:'))
|
|
486
|
-
this.validationResult.issues.forEach(issue => {
|
|
487
|
-
console.log(` - ${issue}`)
|
|
488
|
-
})
|
|
515
|
+
console.log(colors.warningMessage('Issues:'))
|
|
516
|
+
this.validationResult.issues.forEach((issue) => {
|
|
517
|
+
console.log(` - ${issue}`)
|
|
518
|
+
})
|
|
489
519
|
}
|
|
490
520
|
}
|
|
491
521
|
|
|
492
522
|
// Changelog configuration getters
|
|
493
523
|
getChangelogConfig() {
|
|
494
|
-
return this.changelogConfig
|
|
524
|
+
return this.changelogConfig
|
|
495
525
|
}
|
|
496
526
|
|
|
497
527
|
getConventionConfig() {
|
|
498
|
-
return this.changelogConfig
|
|
528
|
+
return this.changelogConfig?.convention || {}
|
|
499
529
|
}
|
|
500
530
|
|
|
501
531
|
getCommitTypes() {
|
|
502
|
-
return this.changelogConfig
|
|
532
|
+
return this.changelogConfig?.convention?.commitTypes || ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert']
|
|
503
533
|
}
|
|
504
534
|
|
|
505
535
|
getChangelogCommitTypes() {
|
|
506
|
-
return this.changelogConfig
|
|
536
|
+
return this.changelogConfig?.changelog?.commitTypes || this.getCommitTypes()
|
|
507
537
|
}
|
|
508
538
|
|
|
509
539
|
getHeadlines() {
|
|
510
|
-
return this.changelogConfig.changelog.headlines
|
|
540
|
+
return this.changelogConfig.changelog.headlines
|
|
511
541
|
}
|
|
512
542
|
|
|
513
543
|
getCommitUrl() {
|
|
514
|
-
return this.changelogConfig.changelog.commitUrl
|
|
544
|
+
return this.changelogConfig.changelog.commitUrl
|
|
515
545
|
}
|
|
516
546
|
|
|
517
547
|
getCommitRangeUrl() {
|
|
518
|
-
return this.changelogConfig.changelog.commitRangeUrl
|
|
548
|
+
return this.changelogConfig.changelog.commitRangeUrl
|
|
519
549
|
}
|
|
520
550
|
|
|
521
551
|
getIssueUrl() {
|
|
522
|
-
return this.changelogConfig.changelog.issueUrl
|
|
552
|
+
return this.changelogConfig.changelog.issueUrl
|
|
523
553
|
}
|
|
524
554
|
|
|
525
555
|
getIssueRegexPattern() {
|
|
526
|
-
const pattern = this.changelogConfig.changelog.issueRegexPattern
|
|
527
|
-
return pattern ? new RegExp(pattern, 'g') : /#[0-9]+/g
|
|
556
|
+
const pattern = this.changelogConfig.changelog.issueRegexPattern
|
|
557
|
+
return pattern ? new RegExp(pattern, 'g') : /#[0-9]+/g
|
|
528
558
|
}
|
|
529
559
|
|
|
530
560
|
shouldIncludeInvalidCommits() {
|
|
531
|
-
return this.changelogConfig.changelog.includeInvalidCommits
|
|
561
|
+
return this.changelogConfig.changelog.includeInvalidCommits
|
|
532
562
|
}
|
|
533
563
|
|
|
534
564
|
getCommitIgnoreRegex() {
|
|
535
|
-
const pattern = this.changelogConfig.changelog.commitIgnoreRegexPattern
|
|
536
|
-
return pattern ? new RegExp(pattern) : /^WIP
|
|
565
|
+
const pattern = this.changelogConfig.changelog.commitIgnoreRegexPattern
|
|
566
|
+
return pattern ? new RegExp(pattern) : /^WIP /
|
|
537
567
|
}
|
|
538
|
-
}
|
|
568
|
+
}
|