@entro314labs/ai-changelog-generator 3.2.1 ā 3.6.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 +42 -2
- package/README.md +21 -1
- package/ai-changelog-mcp.sh +0 -0
- package/ai-changelog.sh +0 -0
- package/bin/ai-changelog-dxt.js +6 -3
- package/manifest.json +177 -0
- package/package.json +76 -81
- package/src/ai-changelog-generator.js +5 -4
- package/src/application/orchestrators/changelog.orchestrator.js +19 -203
- package/src/cli.js +16 -5
- package/src/domains/ai/ai-analysis.service.js +2 -0
- package/src/domains/analysis/analysis.engine.js +714 -37
- package/src/domains/changelog/changelog.service.js +623 -32
- package/src/domains/changelog/workspace-changelog.service.js +445 -622
- package/src/domains/git/commit-tagger.js +552 -0
- package/src/domains/git/git-manager.js +357 -0
- package/src/domains/git/git.service.js +865 -16
- package/src/infrastructure/cli/cli.controller.js +14 -9
- package/src/infrastructure/config/configuration.manager.js +25 -11
- package/src/infrastructure/interactive/interactive-workflow.service.js +8 -1
- package/src/infrastructure/mcp/mcp-server.service.js +105 -32
- package/src/infrastructure/providers/core/base-provider.js +1 -1
- package/src/infrastructure/providers/implementations/anthropic.js +16 -173
- package/src/infrastructure/providers/implementations/azure.js +16 -63
- package/src/infrastructure/providers/implementations/dummy.js +13 -16
- package/src/infrastructure/providers/implementations/mock.js +13 -26
- package/src/infrastructure/providers/implementations/ollama.js +12 -4
- package/src/infrastructure/providers/implementations/openai.js +13 -165
- package/src/infrastructure/providers/provider-management.service.js +126 -412
- package/src/infrastructure/providers/utils/base-provider-helpers.js +11 -0
- package/src/shared/utils/cli-ui.js +8 -10
- package/src/shared/utils/diff-processor.js +21 -19
- package/src/shared/utils/error-classes.js +33 -0
- package/src/shared/utils/utils.js +83 -63
- package/types/index.d.ts +61 -68
- package/src/domains/git/git-repository.analyzer.js +0 -678
|
@@ -1,453 +1,167 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import colors from '../../shared/constants/colors.js'
|
|
1
|
+
import { ProviderManagerService } from './provider-manager.service.js'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
|
-
*
|
|
4
|
+
* ProviderManagementService - Alias for ProviderManagerService
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* - switchProvider() (40 lines) - Provider switching functionality
|
|
11
|
-
* - configureProvider() (80 lines) - Provider configuration
|
|
12
|
-
* - validateModels() (95 lines) - Model validation functionality
|
|
6
|
+
* This service manages AI provider lifecycle, configuration, and operations
|
|
7
|
+
* including registration, activation, validation, and testing of providers.
|
|
13
8
|
*/
|
|
14
|
-
export class ProviderManagementService {
|
|
15
|
-
constructor(
|
|
16
|
-
|
|
9
|
+
export class ProviderManagementService extends ProviderManagerService {
|
|
10
|
+
constructor(config = {}, options = {}) {
|
|
11
|
+
super(config, options)
|
|
17
12
|
}
|
|
18
13
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const providers = this.providerManager.getAllProviders()
|
|
30
|
-
const activeProvider = this.providerManager.getActiveProvider()
|
|
31
|
-
|
|
32
|
-
providers.forEach((provider) => {
|
|
33
|
-
const isActive = activeProvider && provider.name === activeProvider.getName()
|
|
34
|
-
const status = provider.available ? 'ā
Available' : 'ā Not configured'
|
|
35
|
-
const activeIndicator = isActive ? colors.success(' (ACTIVE)') : ''
|
|
36
|
-
|
|
37
|
-
console.log(`${colors.highlight(provider.name.toUpperCase())}${activeIndicator}`)
|
|
38
|
-
console.log(` ${colors.label('Status')}: ${status}`)
|
|
39
|
-
|
|
40
|
-
if (includeCapabilities && provider.available && provider.capabilities) {
|
|
41
|
-
console.log(
|
|
42
|
-
` ${colors.label('Capabilities')}: ${
|
|
43
|
-
Object.entries(provider.capabilities)
|
|
44
|
-
.filter(([_key, value]) => value === true)
|
|
45
|
-
.map(([key]) => key)
|
|
46
|
-
.join(', ') || 'Basic completion'
|
|
47
|
-
}`
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
console.log('')
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
console.log(colors.infoMessage(`Total providers: ${colors.number(providers.length)}`))
|
|
54
|
-
console.log(
|
|
55
|
-
colors.infoMessage(
|
|
56
|
-
`Active provider: ${colors.highlight(activeProvider?.getName() || 'None')}`
|
|
57
|
-
)
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
providers,
|
|
62
|
-
activeProvider: activeProvider?.getName() || null,
|
|
63
|
-
total: providers.length,
|
|
64
|
-
}
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error(colors.errorMessage(`Error listing providers: ${error.message}`))
|
|
67
|
-
throw error
|
|
68
|
-
}
|
|
14
|
+
/**
|
|
15
|
+
* Initialize the provider management service
|
|
16
|
+
* @returns {Promise<void>}
|
|
17
|
+
*/
|
|
18
|
+
async initialize() {
|
|
19
|
+
await this.loadProviders()
|
|
20
|
+
await this.validateConfiguration()
|
|
69
21
|
}
|
|
70
22
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
if (!this.providerManager) {
|
|
80
|
-
console.log(colors.errorMessage('Provider manager not available'))
|
|
81
|
-
return { success: false, error: 'Provider manager not available' }
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Switch provider
|
|
85
|
-
const result = this.providerManager.switchProvider(providerName)
|
|
86
|
-
|
|
87
|
-
if (result.success) {
|
|
88
|
-
console.log(
|
|
89
|
-
colors.successMessage(
|
|
90
|
-
`ā
Successfully switched to ${colors.highlight(providerName.toUpperCase())}`
|
|
91
|
-
)
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
if (testConnection) {
|
|
95
|
-
console.log(colors.processingMessage('š§Ŗ Testing connection...'))
|
|
96
|
-
const newProvider = this.providerManager.getActiveProvider()
|
|
97
|
-
const testResult = await newProvider.testConnection()
|
|
98
|
-
|
|
99
|
-
if (testResult.success) {
|
|
100
|
-
console.log(colors.successMessage('ā
Connection test passed'))
|
|
101
|
-
if (testResult.model) {
|
|
102
|
-
console.log(
|
|
103
|
-
colors.infoMessage(
|
|
104
|
-
` ${colors.label('Model')}: ${colors.highlight(testResult.model)}`
|
|
105
|
-
)
|
|
106
|
-
)
|
|
107
|
-
}
|
|
108
|
-
return { success: true, provider: providerName, connectionTest: testResult }
|
|
109
|
-
}
|
|
110
|
-
console.log(colors.errorMessage(`ā Connection test failed: ${testResult.error}`))
|
|
111
|
-
return { success: true, provider: providerName, connectionTest: testResult }
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return { success: true, provider: providerName }
|
|
115
|
-
}
|
|
116
|
-
console.log(colors.errorMessage(`ā Failed to switch provider: ${result.error}`))
|
|
117
|
-
return { success: false, error: result.error }
|
|
118
|
-
} catch (error) {
|
|
119
|
-
console.error(colors.errorMessage(`Error switching provider: ${error.message}`))
|
|
120
|
-
return { success: false, error: error.message }
|
|
121
|
-
}
|
|
23
|
+
/**
|
|
24
|
+
* Get all available providers
|
|
25
|
+
* @returns {Array} Array of provider instances
|
|
26
|
+
*/
|
|
27
|
+
getAllProviders() {
|
|
28
|
+
return this.providers
|
|
122
29
|
}
|
|
123
30
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
console.log(
|
|
134
|
-
colors.header(`š§ Configuring ${colors.highlight(targetProvider.toUpperCase())} Provider:`)
|
|
135
|
-
)
|
|
136
|
-
console.log('')
|
|
31
|
+
/**
|
|
32
|
+
* Get provider by name
|
|
33
|
+
* @param {string} name - Provider name
|
|
34
|
+
* @returns {Object|null} Provider instance or null
|
|
35
|
+
*/
|
|
36
|
+
getProviderByName(name) {
|
|
37
|
+
return this.findProviderByName(name)
|
|
38
|
+
}
|
|
137
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Register a new provider
|
|
42
|
+
* @param {string} name - Provider name
|
|
43
|
+
* @param {Object} providerInstance - Provider instance
|
|
44
|
+
* @returns {boolean} Success status
|
|
45
|
+
*/
|
|
46
|
+
registerProvider(name, providerInstance) {
|
|
138
47
|
try {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const provider = this.providerManager.findProviderByName(targetProvider)
|
|
145
|
-
|
|
146
|
-
if (!provider) {
|
|
147
|
-
console.log(colors.errorMessage(`Provider '${targetProvider}' not found`))
|
|
148
|
-
return { success: false, error: `Provider '${targetProvider}' not found` }
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Display current configuration status
|
|
152
|
-
console.log(colors.subheader('š Current Configuration:'))
|
|
153
|
-
const config = provider.getConfiguration()
|
|
154
|
-
|
|
155
|
-
Object.entries(config).forEach(([key, value]) => {
|
|
156
|
-
const displayValue =
|
|
157
|
-
key.toLowerCase().includes('key') || key.toLowerCase().includes('secret')
|
|
158
|
-
? value
|
|
159
|
-
? '***CONFIGURED***'
|
|
160
|
-
: 'ā NOT SET'
|
|
161
|
-
: value || 'ā NOT SET'
|
|
162
|
-
console.log(` ${colors.label(key)}: ${displayValue}`)
|
|
48
|
+
this.providers.push({
|
|
49
|
+
name,
|
|
50
|
+
instance: providerInstance,
|
|
51
|
+
available: true,
|
|
163
52
|
})
|
|
164
|
-
|
|
165
|
-
// Show required environment variables
|
|
166
|
-
console.log(colors.subheader('\nš Required Environment Variables:'))
|
|
167
|
-
const requiredVars = provider.getRequiredEnvVars()
|
|
168
|
-
requiredVars.forEach((varName) => {
|
|
169
|
-
const isSet = !!process.env[varName]
|
|
170
|
-
const status = isSet ? 'ā
SET' : 'ā NOT SET'
|
|
171
|
-
console.log(` ${colors.label(varName)}: ${status}`)
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
// Configuration instructions
|
|
175
|
-
console.log(colors.infoMessage('\nš” Configuration Instructions:'))
|
|
176
|
-
console.log(' 1. Set the required environment variables in your .env.local file')
|
|
177
|
-
console.log(' 2. Or export them in your shell session')
|
|
178
|
-
console.log(' 3. Run the configuration test to verify setup')
|
|
179
|
-
|
|
180
|
-
// Test connection if requested
|
|
181
|
-
if (testConnection) {
|
|
182
|
-
console.log(colors.processingMessage('\nš§Ŗ Testing connection...'))
|
|
183
|
-
const testResult = await provider.testConnection()
|
|
184
|
-
|
|
185
|
-
if (testResult.success) {
|
|
186
|
-
console.log(colors.successMessage('ā
Configuration test passed'))
|
|
187
|
-
if (testResult.model) {
|
|
188
|
-
console.log(
|
|
189
|
-
colors.infoMessage(
|
|
190
|
-
` ${colors.label('Default model')}: ${colors.highlight(testResult.model)}`
|
|
191
|
-
)
|
|
192
|
-
)
|
|
193
|
-
}
|
|
194
|
-
} else {
|
|
195
|
-
console.log(colors.errorMessage(`ā Configuration test failed: ${testResult.error}`))
|
|
196
|
-
console.log(
|
|
197
|
-
colors.warningMessage(' Please check your environment variables and API keys')
|
|
198
|
-
)
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Show available models if requested
|
|
203
|
-
if (showModels) {
|
|
204
|
-
console.log(colors.processingMessage('\nš¤ Fetching available models...'))
|
|
205
|
-
try {
|
|
206
|
-
const models = await provider.getAvailableModels()
|
|
207
|
-
if (models && models.length > 0) {
|
|
208
|
-
console.log(colors.subheader('Available Models:'))
|
|
209
|
-
models.forEach((model) => {
|
|
210
|
-
console.log(` - ${colors.highlight(model.name || model)}`)
|
|
211
|
-
if (model.description) {
|
|
212
|
-
console.log(` ${colors.dim(model.description)}`)
|
|
213
|
-
}
|
|
214
|
-
})
|
|
215
|
-
} else {
|
|
216
|
-
console.log(colors.warningMessage('No models found or API error'))
|
|
217
|
-
}
|
|
218
|
-
} catch (error) {
|
|
219
|
-
console.log(colors.errorMessage(`Failed to fetch models: ${error.message}`))
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return {
|
|
224
|
-
success: true,
|
|
225
|
-
provider: targetProvider,
|
|
226
|
-
configuration: config,
|
|
227
|
-
testResult: testConnection ? await provider.testConnection() : null,
|
|
228
|
-
}
|
|
53
|
+
return true
|
|
229
54
|
} catch (error) {
|
|
230
|
-
console.error(
|
|
231
|
-
return
|
|
55
|
+
console.error(`Failed to register provider ${name}:`, error.message)
|
|
56
|
+
return false
|
|
232
57
|
}
|
|
233
58
|
}
|
|
234
59
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return { success: false, error: 'No provider specified' }
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
console.log(
|
|
245
|
-
colors.header(`š Validating Models for ${colors.highlight(targetProvider.toUpperCase())}:`)
|
|
246
|
-
)
|
|
247
|
-
console.log('')
|
|
248
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Activate a provider by name
|
|
62
|
+
* @param {string} name - Provider name to activate
|
|
63
|
+
* @returns {Promise<boolean>} Success status
|
|
64
|
+
*/
|
|
65
|
+
async activateProvider(name) {
|
|
249
66
|
try {
|
|
250
|
-
|
|
251
|
-
console.log(colors.errorMessage('Provider manager not available'))
|
|
252
|
-
return { success: false, error: 'Provider manager not available' }
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const provider = this.providerManager.findProviderByName(targetProvider)
|
|
256
|
-
|
|
67
|
+
const provider = this.findProviderByName(name)
|
|
257
68
|
if (!provider) {
|
|
258
|
-
|
|
259
|
-
return { success: false, error: `Provider '${targetProvider}' not found` }
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Check if provider is configured
|
|
263
|
-
const isConfigured = provider.isAvailable()
|
|
264
|
-
if (!isConfigured) {
|
|
265
|
-
console.log(colors.errorMessage(`Provider '${targetProvider}' is not properly configured`))
|
|
266
|
-
return { success: false, error: 'Provider not configured' }
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// Get available models
|
|
270
|
-
console.log(colors.processingMessage('š Fetching available models...'))
|
|
271
|
-
const models = await provider.getAvailableModels()
|
|
272
|
-
|
|
273
|
-
if (!models || models.length === 0) {
|
|
274
|
-
console.log(colors.warningMessage('No models found'))
|
|
275
|
-
return { success: true, models: [] }
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
console.log(colors.successMessage(`ā
Found ${colors.number(models.length)} models`))
|
|
279
|
-
console.log('')
|
|
280
|
-
|
|
281
|
-
const validationResults = []
|
|
282
|
-
|
|
283
|
-
// Display and optionally test each model
|
|
284
|
-
for (const model of models) {
|
|
285
|
-
const modelName = model.name || model
|
|
286
|
-
console.log(colors.subheader(`š¤ ${colors.highlight(modelName)}`))
|
|
287
|
-
|
|
288
|
-
if (model.description) {
|
|
289
|
-
console.log(` ${colors.label('Description')}: ${colors.value(model.description)}`)
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (checkCapabilities && model.capabilities) {
|
|
293
|
-
console.log(
|
|
294
|
-
` ${colors.label('Capabilities')}: ${Object.entries(model.capabilities)
|
|
295
|
-
.filter(([_key, value]) => value === true)
|
|
296
|
-
.map(([key]) => key)
|
|
297
|
-
.join(', ')}`
|
|
298
|
-
)
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
if (model.contextWindow) {
|
|
302
|
-
console.log(
|
|
303
|
-
` ${colors.label('Context Window')}: ${colors.number(model.contextWindow)} tokens`
|
|
304
|
-
)
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
if (model.maxTokens) {
|
|
308
|
-
console.log(` ${colors.label('Max Output')}: ${colors.number(model.maxTokens)} tokens`)
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// Test model if requested
|
|
312
|
-
if (testModels) {
|
|
313
|
-
console.log(colors.processingMessage(` š§Ŗ Testing ${modelName}...`))
|
|
314
|
-
try {
|
|
315
|
-
const testResult = await provider.testModel(modelName)
|
|
316
|
-
if (testResult.success) {
|
|
317
|
-
console.log(colors.successMessage(' ā
Model test passed'))
|
|
318
|
-
if (testResult.responseTime) {
|
|
319
|
-
console.log(
|
|
320
|
-
` ${colors.label('Response Time')}: ${colors.number(testResult.responseTime)}ms`
|
|
321
|
-
)
|
|
322
|
-
}
|
|
323
|
-
} else {
|
|
324
|
-
console.log(colors.errorMessage(` ā Model test failed: ${testResult.error}`))
|
|
325
|
-
}
|
|
326
|
-
validationResults.push({ model: modelName, ...testResult })
|
|
327
|
-
} catch (error) {
|
|
328
|
-
console.log(colors.errorMessage(` ā Model test error: ${error.message}`))
|
|
329
|
-
validationResults.push({ model: modelName, success: false, error: error.message })
|
|
330
|
-
}
|
|
331
|
-
} else {
|
|
332
|
-
validationResults.push({ model: modelName, success: true })
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
console.log('')
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Summary
|
|
339
|
-
if (testModels) {
|
|
340
|
-
const successfulTests = validationResults.filter((r) => r.success).length
|
|
341
|
-
const failedTests = validationResults.length - successfulTests
|
|
342
|
-
|
|
343
|
-
console.log(colors.subheader('š Test Summary:'))
|
|
344
|
-
console.log(` ${colors.label('Successful')}: ${colors.successMessage(successfulTests)}`)
|
|
345
|
-
if (failedTests > 0) {
|
|
346
|
-
console.log(` ${colors.label('Failed')}: ${colors.errorMessage(failedTests)}`)
|
|
347
|
-
}
|
|
69
|
+
throw new Error(`Provider '${name}' not found`)
|
|
348
70
|
}
|
|
349
71
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
provider: targetProvider,
|
|
353
|
-
models,
|
|
354
|
-
validationResults: testModels ? validationResults : null,
|
|
355
|
-
summary: {
|
|
356
|
-
total: models.length,
|
|
357
|
-
tested: testModels ? validationResults.length : 0,
|
|
358
|
-
successful: testModels
|
|
359
|
-
? validationResults.filter((r) => r.success).length
|
|
360
|
-
: models.length,
|
|
361
|
-
},
|
|
362
|
-
}
|
|
72
|
+
this.activeProvider = provider.instance
|
|
73
|
+
return true
|
|
363
74
|
} catch (error) {
|
|
364
|
-
console.error(
|
|
365
|
-
return
|
|
75
|
+
console.error(`Failed to activate provider ${name}:`, error.message)
|
|
76
|
+
return false
|
|
366
77
|
}
|
|
367
78
|
}
|
|
368
79
|
|
|
369
|
-
|
|
370
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Deactivate current provider
|
|
82
|
+
* @returns {boolean} Success status
|
|
83
|
+
*/
|
|
84
|
+
deactivateProvider() {
|
|
371
85
|
try {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return { available: false, error: 'Provider not found' }
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
return {
|
|
378
|
-
available: provider.isAvailable(),
|
|
379
|
-
name: provider.getName(),
|
|
380
|
-
configuration: provider.getConfiguration(),
|
|
381
|
-
requiredVars: provider.getRequiredEnvVars(),
|
|
382
|
-
}
|
|
86
|
+
this.activeProvider = null
|
|
87
|
+
return true
|
|
383
88
|
} catch (error) {
|
|
384
|
-
|
|
89
|
+
console.error('Failed to deactivate provider:', error.message)
|
|
90
|
+
return false
|
|
385
91
|
}
|
|
386
92
|
}
|
|
387
93
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Get provider lifecycle status
|
|
96
|
+
* @param {string} name - Provider name
|
|
97
|
+
* @returns {Object} Lifecycle status information
|
|
98
|
+
*/
|
|
99
|
+
getProviderLifecycle(name) {
|
|
100
|
+
const provider = this.findProviderByName(name)
|
|
101
|
+
return {
|
|
102
|
+
name,
|
|
103
|
+
exists: !!provider,
|
|
104
|
+
available: provider?.available,
|
|
105
|
+
active: this.activeProvider === provider?.instance,
|
|
106
|
+
initialized: provider?.instance?.isInitialized?.(),
|
|
399
107
|
}
|
|
400
108
|
}
|
|
401
109
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
110
|
+
/**
|
|
111
|
+
* Get provider registry information
|
|
112
|
+
* @returns {Object} Registry information
|
|
113
|
+
*/
|
|
114
|
+
getProviderRegistry() {
|
|
115
|
+
return {
|
|
116
|
+
total: this.providers.length,
|
|
117
|
+
active: this.activeProvider ? this.activeProvider.constructor.name : null,
|
|
118
|
+
available: this.providers.filter((p) => p.available).length,
|
|
119
|
+
providers: this.providers.map((p) => ({
|
|
120
|
+
name: p.name,
|
|
121
|
+
available: p.available,
|
|
122
|
+
type: p.instance.constructor.name,
|
|
123
|
+
})),
|
|
124
|
+
}
|
|
125
|
+
}
|
|
416
126
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
127
|
+
/**
|
|
128
|
+
* Validate all provider configurations
|
|
129
|
+
* @returns {Promise<Object>} Validation results
|
|
130
|
+
*/
|
|
131
|
+
async validateConfiguration() {
|
|
132
|
+
const results = {
|
|
133
|
+
valid: 0,
|
|
134
|
+
invalid: 0,
|
|
135
|
+
errors: [],
|
|
136
|
+
}
|
|
421
137
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
results.push({
|
|
430
|
-
} catch (error) {
|
|
431
|
-
console.log(colors.errorMessage(`ā ${provider.name} - ${error.message}`))
|
|
432
|
-
results.push({ provider: provider.name, success: false, error: error.message })
|
|
138
|
+
for (const provider of this.providers) {
|
|
139
|
+
try {
|
|
140
|
+
const isValid = await provider.instance.isAvailable?.()
|
|
141
|
+
if (isValid) {
|
|
142
|
+
results.valid++
|
|
143
|
+
} else {
|
|
144
|
+
results.invalid++
|
|
145
|
+
results.errors.push(`${provider.name}: Not available`)
|
|
433
146
|
}
|
|
147
|
+
} catch (error) {
|
|
148
|
+
results.invalid++
|
|
149
|
+
results.errors.push(`${provider.name}: ${error.message}`)
|
|
434
150
|
}
|
|
151
|
+
}
|
|
435
152
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
const failed = results.length - successful
|
|
439
|
-
|
|
440
|
-
console.log(colors.subheader('\nš Test Results Summary:'))
|
|
441
|
-
console.log(` ${colors.label('Total Providers')}: ${colors.number(results.length)}`)
|
|
442
|
-
console.log(` ${colors.label('Successful')}: ${colors.successMessage(successful)}`)
|
|
443
|
-
if (failed > 0) {
|
|
444
|
-
console.log(` ${colors.label('Failed')}: ${colors.errorMessage(failed)}`)
|
|
445
|
-
}
|
|
153
|
+
return results
|
|
154
|
+
}
|
|
446
155
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Clean up provider resources
|
|
158
|
+
* @returns {Promise<void>}
|
|
159
|
+
*/
|
|
160
|
+
async cleanup() {
|
|
161
|
+
this.activeProvider = null
|
|
162
|
+
this.providers = []
|
|
452
163
|
}
|
|
453
164
|
}
|
|
165
|
+
|
|
166
|
+
// Export as default for compatibility
|
|
167
|
+
export default ProviderManagementService
|
|
@@ -446,6 +446,17 @@ export function ConfigurationMixin(providerName, defaults = {}) {
|
|
|
446
446
|
return buildClientOptions(providerConfig, { ...defaults, ...extraDefaults })
|
|
447
447
|
},
|
|
448
448
|
|
|
449
|
+
getRequiredEnvVars() {
|
|
450
|
+
// Default implementation - providers should override if needed
|
|
451
|
+
const baseKey = `${providerName.toUpperCase()}_API_KEY`
|
|
452
|
+
return [baseKey]
|
|
453
|
+
},
|
|
454
|
+
|
|
455
|
+
getDefaultModel() {
|
|
456
|
+
const modelConfig = this.getProviderModelConfig()
|
|
457
|
+
return modelConfig.standardModel || 'unknown'
|
|
458
|
+
},
|
|
459
|
+
|
|
449
460
|
getProviderInfo() {
|
|
450
461
|
const providerConfig = this.getProviderConfig()
|
|
451
462
|
const availableModels = this.getAvailableModels ? this.getAvailableModels() : []
|
|
@@ -223,8 +223,13 @@ export class EnhancedConsole {
|
|
|
223
223
|
EnhancedConsole.log(message, 'ai')
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
-
static metrics(
|
|
227
|
-
|
|
226
|
+
static metrics(data, title = 'Metrics') {
|
|
227
|
+
if (typeof data === 'string') {
|
|
228
|
+
EnhancedConsole.log(data, 'metrics')
|
|
229
|
+
} else if (data && Object.keys(data).length > 0) {
|
|
230
|
+
EnhancedConsole.section(title)
|
|
231
|
+
console.log(colors.formatMetrics(data))
|
|
232
|
+
}
|
|
228
233
|
}
|
|
229
234
|
|
|
230
235
|
static section(title, content = '') {
|
|
@@ -252,13 +257,6 @@ export class EnhancedConsole {
|
|
|
252
257
|
}
|
|
253
258
|
}
|
|
254
259
|
|
|
255
|
-
static metrics(metrics, title = 'Metrics') {
|
|
256
|
-
if (metrics && Object.keys(metrics).length > 0) {
|
|
257
|
-
EnhancedConsole.section(title)
|
|
258
|
-
console.log(colors.formatMetrics(metrics))
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
260
|
static divider(char = 'ā', length = 60) {
|
|
263
261
|
console.log(colors.separator(char, length))
|
|
264
262
|
}
|
|
@@ -438,7 +436,7 @@ export const cliUtils = {
|
|
|
438
436
|
// Format bytes
|
|
439
437
|
formatBytes(bytes) {
|
|
440
438
|
const sizes = ['B', 'KB', 'MB', 'GB']
|
|
441
|
-
if (bytes
|
|
439
|
+
if (bytes <= 0 || !Number.isFinite(bytes)) {
|
|
442
440
|
return '0B'
|
|
443
441
|
}
|
|
444
442
|
const i = Math.floor(Math.log(bytes) / Math.log(1024))
|