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