@entro314labs/ai-changelog-generator 3.0.5 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +383 -785
- package/README.md +30 -3
- package/ai-changelog-mcp.sh +0 -0
- package/ai-changelog.sh +0 -0
- package/bin/ai-changelog-dxt.js +9 -9
- package/bin/ai-changelog-mcp.js +19 -17
- package/bin/ai-changelog.js +6 -6
- package/package.json +84 -52
- package/src/ai-changelog-generator.js +83 -81
- package/src/application/orchestrators/changelog.orchestrator.js +1040 -296
- package/src/application/services/application.service.js +145 -123
- package/src/cli.js +76 -57
- package/src/domains/ai/ai-analysis.service.js +289 -209
- package/src/domains/analysis/analysis.engine.js +253 -193
- package/src/domains/changelog/changelog.service.js +1062 -784
- package/src/domains/changelog/workspace-changelog.service.js +420 -249
- package/src/domains/git/git-repository.analyzer.js +348 -258
- package/src/domains/git/git.service.js +132 -112
- package/src/infrastructure/cli/cli.controller.js +415 -247
- package/src/infrastructure/config/configuration.manager.js +220 -190
- package/src/infrastructure/interactive/interactive-staging.service.js +332 -0
- package/src/infrastructure/interactive/interactive-workflow.service.js +200 -159
- package/src/infrastructure/mcp/mcp-server.service.js +208 -207
- package/src/infrastructure/metrics/metrics.collector.js +140 -123
- package/src/infrastructure/providers/core/base-provider.js +87 -40
- package/src/infrastructure/providers/implementations/anthropic.js +101 -99
- package/src/infrastructure/providers/implementations/azure.js +124 -101
- package/src/infrastructure/providers/implementations/bedrock.js +136 -126
- package/src/infrastructure/providers/implementations/dummy.js +23 -23
- package/src/infrastructure/providers/implementations/google.js +123 -114
- package/src/infrastructure/providers/implementations/huggingface.js +94 -87
- package/src/infrastructure/providers/implementations/lmstudio.js +75 -60
- package/src/infrastructure/providers/implementations/mock.js +69 -73
- package/src/infrastructure/providers/implementations/ollama.js +89 -66
- package/src/infrastructure/providers/implementations/openai.js +88 -89
- package/src/infrastructure/providers/implementations/vertex.js +227 -197
- package/src/infrastructure/providers/provider-management.service.js +245 -207
- package/src/infrastructure/providers/provider-manager.service.js +145 -125
- package/src/infrastructure/providers/utils/base-provider-helpers.js +308 -302
- package/src/infrastructure/providers/utils/model-config.js +220 -195
- package/src/infrastructure/providers/utils/provider-utils.js +105 -100
- package/src/infrastructure/validation/commit-message-validation.service.js +556 -0
- package/src/shared/constants/colors.js +467 -172
- package/src/shared/utils/cli-demo.js +285 -0
- package/src/shared/utils/cli-entry-utils.js +257 -249
- package/src/shared/utils/cli-ui.js +447 -0
- package/src/shared/utils/diff-processor.js +513 -0
- package/src/shared/utils/error-classes.js +125 -156
- package/src/shared/utils/json-utils.js +93 -89
- package/src/shared/utils/utils.js +1299 -775
- package/types/index.d.ts +353 -344
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import process from 'node:process'
|
|
2
|
+
|
|
3
|
+
import colors from '../../shared/constants/colors.js'
|
|
4
|
+
import { formatDuration } from '../../shared/utils/utils.js'
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Metrics Collector Service
|
|
@@ -8,7 +10,7 @@ import { formatDuration } from '../../shared/utils/utils.js';
|
|
|
8
10
|
*/
|
|
9
11
|
export class MetricsCollector {
|
|
10
12
|
constructor() {
|
|
11
|
-
this.reset()
|
|
13
|
+
this.reset()
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
reset() {
|
|
@@ -33,7 +35,7 @@ export class MetricsCollector {
|
|
|
33
35
|
averageResponseTime: 0,
|
|
34
36
|
totalResponseTime: 0,
|
|
35
37
|
slowestRequest: 0,
|
|
36
|
-
fastestRequest:
|
|
38
|
+
fastestRequest: Number.POSITIVE_INFINITY,
|
|
37
39
|
|
|
38
40
|
// Error tracking
|
|
39
41
|
errors: 0,
|
|
@@ -52,124 +54,126 @@ export class MetricsCollector {
|
|
|
52
54
|
|
|
53
55
|
// Session info
|
|
54
56
|
sessionId: this.generateSessionId(),
|
|
55
|
-
version: process.env.npm_package_version || 'unknown'
|
|
56
|
-
}
|
|
57
|
+
version: process.env.npm_package_version || 'unknown',
|
|
58
|
+
}
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
generateSessionId() {
|
|
60
|
-
return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}
|
|
62
|
+
return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
// Processing tracking
|
|
64
66
|
incrementCommitsProcessed(count = 1) {
|
|
65
|
-
this.metrics.commitsProcessed += count
|
|
67
|
+
this.metrics.commitsProcessed += count
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
incrementFilesAnalyzed(count = 1) {
|
|
69
|
-
this.metrics.filesAnalyzed += count
|
|
71
|
+
this.metrics.filesAnalyzed += count
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
incrementBatchesProcessed(count = 1) {
|
|
73
|
-
this.metrics.batchesProcessed += count
|
|
75
|
+
this.metrics.batchesProcessed += count
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
// AI metrics tracking
|
|
77
79
|
recordApiCall(tokens = {}, responseTime = 0, model = 'unknown') {
|
|
78
|
-
this.metrics.apiCalls
|
|
80
|
+
this.metrics.apiCalls++
|
|
79
81
|
|
|
80
82
|
if (tokens.prompt_tokens) {
|
|
81
|
-
this.metrics.promptTokens += tokens.prompt_tokens
|
|
83
|
+
this.metrics.promptTokens += tokens.prompt_tokens
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
if (tokens.completion_tokens) {
|
|
85
|
-
this.metrics.completionTokens += tokens.completion_tokens
|
|
87
|
+
this.metrics.completionTokens += tokens.completion_tokens
|
|
86
88
|
}
|
|
87
89
|
|
|
88
|
-
this.metrics.totalTokens = this.metrics.promptTokens + this.metrics.completionTokens
|
|
90
|
+
this.metrics.totalTokens = this.metrics.promptTokens + this.metrics.completionTokens
|
|
89
91
|
|
|
90
92
|
// Track response times
|
|
91
|
-
this.metrics.totalResponseTime += responseTime
|
|
92
|
-
this.metrics.averageResponseTime = this.metrics.totalResponseTime / this.metrics.apiCalls
|
|
93
|
+
this.metrics.totalResponseTime += responseTime
|
|
94
|
+
this.metrics.averageResponseTime = this.metrics.totalResponseTime / this.metrics.apiCalls
|
|
93
95
|
|
|
94
96
|
if (responseTime > this.metrics.slowestRequest) {
|
|
95
|
-
this.metrics.slowestRequest = responseTime
|
|
97
|
+
this.metrics.slowestRequest = responseTime
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
if (responseTime < this.metrics.fastestRequest) {
|
|
99
|
-
this.metrics.fastestRequest = responseTime
|
|
101
|
+
this.metrics.fastestRequest = responseTime
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
// Track model usage
|
|
103
105
|
if (!this.metrics.modelUsage[model]) {
|
|
104
|
-
this.metrics.modelUsage[model] = 0
|
|
106
|
+
this.metrics.modelUsage[model] = 0
|
|
105
107
|
}
|
|
106
|
-
this.metrics.modelUsage[model]
|
|
108
|
+
this.metrics.modelUsage[model]++
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
recordRuleBasedFallback(
|
|
110
|
-
this.metrics.ruleBasedFallbacks
|
|
111
|
+
recordRuleBasedFallback(_reason = 'unknown') {
|
|
112
|
+
this.metrics.ruleBasedFallbacks++
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
recordCacheHit() {
|
|
114
|
-
this.metrics.cacheHits
|
|
116
|
+
this.metrics.cacheHits++
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
// Error tracking
|
|
118
120
|
recordError(error = {}) {
|
|
119
|
-
this.metrics.errors
|
|
121
|
+
this.metrics.errors++
|
|
120
122
|
|
|
121
123
|
// Log error details if in debug mode
|
|
122
124
|
if (process.env.DEBUG) {
|
|
123
|
-
console.error(colors.errorMessage('Metrics: Error recorded'), error)
|
|
125
|
+
console.error(colors.errorMessage('Metrics: Error recorded'), error)
|
|
124
126
|
}
|
|
125
127
|
}
|
|
126
128
|
|
|
127
|
-
recordWarning(
|
|
128
|
-
this.metrics.warnings
|
|
129
|
+
recordWarning(_warning = {}) {
|
|
130
|
+
this.metrics.warnings++
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
recordRetry() {
|
|
132
|
-
this.metrics.retries
|
|
134
|
+
this.metrics.retries++
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
// Feature usage tracking
|
|
136
138
|
setAnalysisMode(mode) {
|
|
137
|
-
this.metrics.analysisMode = mode
|
|
139
|
+
this.metrics.analysisMode = mode
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
setProvider(provider) {
|
|
141
|
-
this.metrics.provider = provider
|
|
143
|
+
this.metrics.provider = provider
|
|
142
144
|
}
|
|
143
145
|
|
|
144
146
|
recordCommandUsed(command) {
|
|
145
147
|
if (!this.metrics.commandsUsed.includes(command)) {
|
|
146
|
-
this.metrics.commandsUsed.push(command)
|
|
148
|
+
this.metrics.commandsUsed.push(command)
|
|
147
149
|
}
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
// Quality metrics
|
|
151
153
|
calculateSuccessRate() {
|
|
152
|
-
const totalOperations = this.metrics.apiCalls + this.metrics.ruleBasedFallbacks
|
|
153
|
-
if (totalOperations === 0)
|
|
154
|
+
const totalOperations = this.metrics.apiCalls + this.metrics.ruleBasedFallbacks
|
|
155
|
+
if (totalOperations === 0) {
|
|
156
|
+
return 0
|
|
157
|
+
}
|
|
154
158
|
|
|
155
|
-
const successful = totalOperations - this.metrics.errors
|
|
156
|
-
this.metrics.successRate = Math.round((successful / totalOperations) * 100)
|
|
157
|
-
return this.metrics.successRate
|
|
159
|
+
const successful = totalOperations - this.metrics.errors
|
|
160
|
+
this.metrics.successRate = Math.round((successful / totalOperations) * 100)
|
|
161
|
+
return this.metrics.successRate
|
|
158
162
|
}
|
|
159
163
|
|
|
160
164
|
// Session management
|
|
161
165
|
startSession() {
|
|
162
|
-
this.metrics.startTime = Date.now()
|
|
166
|
+
this.metrics.startTime = Date.now()
|
|
163
167
|
}
|
|
164
168
|
|
|
165
169
|
endSession() {
|
|
166
|
-
this.metrics.endTime = Date.now()
|
|
167
|
-
this.calculateSuccessRate()
|
|
170
|
+
this.metrics.endTime = Date.now()
|
|
171
|
+
this.calculateSuccessRate()
|
|
168
172
|
}
|
|
169
173
|
|
|
170
174
|
getDuration() {
|
|
171
|
-
const end = this.metrics.endTime || Date.now()
|
|
172
|
-
return end - this.metrics.startTime
|
|
175
|
+
const end = this.metrics.endTime || Date.now()
|
|
176
|
+
return end - this.metrics.startTime
|
|
173
177
|
}
|
|
174
178
|
|
|
175
179
|
// Metrics retrieval
|
|
@@ -177,8 +181,8 @@ export class MetricsCollector {
|
|
|
177
181
|
return {
|
|
178
182
|
...this.metrics,
|
|
179
183
|
duration: this.getDuration(),
|
|
180
|
-
successRate: this.calculateSuccessRate()
|
|
181
|
-
}
|
|
184
|
+
successRate: this.calculateSuccessRate(),
|
|
185
|
+
}
|
|
182
186
|
}
|
|
183
187
|
|
|
184
188
|
getBasicMetrics() {
|
|
@@ -187,19 +191,22 @@ export class MetricsCollector {
|
|
|
187
191
|
commitsProcessed: this.metrics.commitsProcessed,
|
|
188
192
|
apiCalls: this.metrics.apiCalls,
|
|
189
193
|
errors: this.metrics.errors,
|
|
190
|
-
successRate: this.calculateSuccessRate()
|
|
191
|
-
}
|
|
194
|
+
successRate: this.calculateSuccessRate(),
|
|
195
|
+
}
|
|
192
196
|
}
|
|
193
197
|
|
|
194
198
|
getPerformanceMetrics() {
|
|
195
199
|
return {
|
|
196
200
|
averageResponseTime: Math.round(this.metrics.averageResponseTime),
|
|
197
201
|
slowestRequest: this.metrics.slowestRequest,
|
|
198
|
-
fastestRequest:
|
|
202
|
+
fastestRequest:
|
|
203
|
+
this.metrics.fastestRequest === Number.POSITIVE_INFINITY ? 0 : this.metrics.fastestRequest,
|
|
199
204
|
totalTokens: this.metrics.totalTokens,
|
|
200
|
-
cacheHitRate:
|
|
201
|
-
|
|
202
|
-
|
|
205
|
+
cacheHitRate:
|
|
206
|
+
this.metrics.apiCalls > 0
|
|
207
|
+
? Math.round((this.metrics.cacheHits / this.metrics.apiCalls) * 100)
|
|
208
|
+
: 0,
|
|
209
|
+
}
|
|
203
210
|
}
|
|
204
211
|
|
|
205
212
|
getUsageMetrics() {
|
|
@@ -208,155 +215,165 @@ export class MetricsCollector {
|
|
|
208
215
|
provider: this.metrics.provider,
|
|
209
216
|
modelUsage: this.metrics.modelUsage,
|
|
210
217
|
commandsUsed: this.metrics.commandsUsed,
|
|
211
|
-
ruleBasedFallbacks: this.metrics.ruleBasedFallbacks
|
|
212
|
-
}
|
|
218
|
+
ruleBasedFallbacks: this.metrics.ruleBasedFallbacks,
|
|
219
|
+
}
|
|
213
220
|
}
|
|
214
221
|
|
|
215
222
|
// Reporting
|
|
216
223
|
displaySummary() {
|
|
217
|
-
const metrics = this.getMetrics()
|
|
224
|
+
const metrics = this.getMetrics()
|
|
218
225
|
|
|
219
|
-
console.log(colors.header('\n📊 Session Summary:'))
|
|
220
|
-
console.log(` ${colors.label('Session ID')}: ${colors.value(metrics.sessionId)}`)
|
|
221
|
-
console.log(` ${colors.label('Duration')}: ${colors.value(formatDuration(metrics.duration))}`)
|
|
222
|
-
console.log(
|
|
223
|
-
|
|
226
|
+
console.log(colors.header('\n📊 Session Summary:'))
|
|
227
|
+
console.log(` ${colors.label('Session ID')}: ${colors.value(metrics.sessionId)}`)
|
|
228
|
+
console.log(` ${colors.label('Duration')}: ${colors.value(formatDuration(metrics.duration))}`)
|
|
229
|
+
console.log(
|
|
230
|
+
` ${colors.label('Commits processed')}: ${colors.number(metrics.commitsProcessed)}`
|
|
231
|
+
)
|
|
232
|
+
console.log(` ${colors.label('Files analyzed')}: ${colors.number(metrics.filesAnalyzed)}`)
|
|
224
233
|
|
|
225
234
|
if (metrics.apiCalls > 0) {
|
|
226
|
-
console.log(` ${colors.label('AI calls')}: ${colors.number(metrics.apiCalls)}`)
|
|
227
|
-
console.log(` ${colors.label('Total tokens')}: ${colors.number(metrics.totalTokens)}`)
|
|
228
|
-
console.log(
|
|
229
|
-
|
|
235
|
+
console.log(` ${colors.label('AI calls')}: ${colors.number(metrics.apiCalls)}`)
|
|
236
|
+
console.log(` ${colors.label('Total tokens')}: ${colors.number(metrics.totalTokens)}`)
|
|
237
|
+
console.log(
|
|
238
|
+
` ${colors.label('Avg response time')}: ${colors.value(Math.round(metrics.averageResponseTime))}ms`
|
|
239
|
+
)
|
|
240
|
+
console.log(
|
|
241
|
+
` ${colors.label('Success rate')}: ${colors.percentage(`${metrics.successRate}%`)}`
|
|
242
|
+
)
|
|
230
243
|
}
|
|
231
244
|
|
|
232
245
|
if (metrics.ruleBasedFallbacks > 0) {
|
|
233
|
-
console.log(
|
|
246
|
+
console.log(
|
|
247
|
+
` ${colors.label('Rule-based fallbacks')}: ${colors.warningMessage(metrics.ruleBasedFallbacks)}`
|
|
248
|
+
)
|
|
234
249
|
}
|
|
235
250
|
|
|
236
251
|
if (metrics.errors > 0) {
|
|
237
|
-
console.log(` ${colors.label('Errors')}: ${colors.error(metrics.errors)}`)
|
|
252
|
+
console.log(` ${colors.label('Errors')}: ${colors.error(metrics.errors)}`)
|
|
238
253
|
}
|
|
239
254
|
|
|
240
255
|
if (metrics.warnings > 0) {
|
|
241
|
-
console.log(` ${colors.label('Warnings')}: ${colors.warningMessage(metrics.warnings)}`)
|
|
256
|
+
console.log(` ${colors.label('Warnings')}: ${colors.warningMessage(metrics.warnings)}`)
|
|
242
257
|
}
|
|
243
258
|
}
|
|
244
259
|
|
|
245
260
|
displayDetailedReport() {
|
|
246
|
-
const metrics = this.getMetrics()
|
|
247
|
-
const performance = this.getPerformanceMetrics()
|
|
248
|
-
const usage = this.getUsageMetrics()
|
|
261
|
+
const metrics = this.getMetrics()
|
|
262
|
+
const performance = this.getPerformanceMetrics()
|
|
263
|
+
const usage = this.getUsageMetrics()
|
|
249
264
|
|
|
250
|
-
console.log(colors.header('\n📈 Detailed Metrics Report:'))
|
|
251
|
-
console.log(colors.separator())
|
|
265
|
+
console.log(colors.header('\n📈 Detailed Metrics Report:'))
|
|
266
|
+
console.log(colors.separator())
|
|
252
267
|
|
|
253
268
|
// Session info
|
|
254
|
-
console.log(colors.subheader('🔍 Session Information:'))
|
|
255
|
-
console.log(` Session ID: ${colors.value(metrics.sessionId)}`)
|
|
256
|
-
console.log(` Duration: ${colors.value(formatDuration(metrics.duration))}`)
|
|
257
|
-
console.log(` Analysis Mode: ${colors.highlight(metrics.analysisMode)}`)
|
|
258
|
-
console.log(` Provider: ${colors.highlight(metrics.provider)}`)
|
|
259
|
-
console.log(` Commands Used: ${colors.value(usage.commandsUsed.join(', ') || 'None')}`)
|
|
269
|
+
console.log(colors.subheader('🔍 Session Information:'))
|
|
270
|
+
console.log(` Session ID: ${colors.value(metrics.sessionId)}`)
|
|
271
|
+
console.log(` Duration: ${colors.value(formatDuration(metrics.duration))}`)
|
|
272
|
+
console.log(` Analysis Mode: ${colors.highlight(metrics.analysisMode)}`)
|
|
273
|
+
console.log(` Provider: ${colors.highlight(metrics.provider)}`)
|
|
274
|
+
console.log(` Commands Used: ${colors.value(usage.commandsUsed.join(', ') || 'None')}`)
|
|
260
275
|
|
|
261
276
|
// Processing stats
|
|
262
|
-
console.log(colors.subheader('\n⚙️ Processing Statistics:'))
|
|
263
|
-
console.log(` Commits Processed: ${colors.number(metrics.commitsProcessed)}`)
|
|
264
|
-
console.log(` Files Analyzed: ${colors.number(metrics.filesAnalyzed)}`)
|
|
265
|
-
console.log(` Batches Processed: ${colors.number(metrics.batchesProcessed)}`)
|
|
277
|
+
console.log(colors.subheader('\n⚙️ Processing Statistics:'))
|
|
278
|
+
console.log(` Commits Processed: ${colors.number(metrics.commitsProcessed)}`)
|
|
279
|
+
console.log(` Files Analyzed: ${colors.number(metrics.filesAnalyzed)}`)
|
|
280
|
+
console.log(` Batches Processed: ${colors.number(metrics.batchesProcessed)}`)
|
|
266
281
|
|
|
267
282
|
// AI stats
|
|
268
283
|
if (metrics.apiCalls > 0) {
|
|
269
|
-
console.log(colors.subheader('\n🤖 AI Statistics:'))
|
|
270
|
-
console.log(` API Calls: ${colors.number(metrics.apiCalls)}`)
|
|
271
|
-
console.log(` Total Tokens: ${colors.number(metrics.totalTokens)}`)
|
|
272
|
-
console.log(` Prompt Tokens: ${colors.number(metrics.promptTokens)}`)
|
|
273
|
-
console.log(` Completion Tokens: ${colors.number(metrics.completionTokens)}`)
|
|
274
|
-
console.log(
|
|
284
|
+
console.log(colors.subheader('\n🤖 AI Statistics:'))
|
|
285
|
+
console.log(` API Calls: ${colors.number(metrics.apiCalls)}`)
|
|
286
|
+
console.log(` Total Tokens: ${colors.number(metrics.totalTokens)}`)
|
|
287
|
+
console.log(` Prompt Tokens: ${colors.number(metrics.promptTokens)}`)
|
|
288
|
+
console.log(` Completion Tokens: ${colors.number(metrics.completionTokens)}`)
|
|
289
|
+
console.log(
|
|
290
|
+
` Cache Hits: ${colors.number(metrics.cacheHits)} (${performance.cacheHitRate}%)`
|
|
291
|
+
)
|
|
275
292
|
|
|
276
293
|
if (Object.keys(usage.modelUsage).length > 0) {
|
|
277
|
-
console.log(
|
|
294
|
+
console.log(' Model Usage:')
|
|
278
295
|
Object.entries(usage.modelUsage).forEach(([model, count]) => {
|
|
279
|
-
console.log(` - ${colors.highlight(model)}: ${colors.number(count)} calls`)
|
|
280
|
-
})
|
|
296
|
+
console.log(` - ${colors.highlight(model)}: ${colors.number(count)} calls`)
|
|
297
|
+
})
|
|
281
298
|
}
|
|
282
299
|
}
|
|
283
300
|
|
|
284
301
|
// Performance stats
|
|
285
|
-
console.log(colors.subheader('\n🚀 Performance Metrics:'))
|
|
286
|
-
console.log(` Average Response Time: ${colors.value(performance.averageResponseTime)}ms`)
|
|
287
|
-
console.log(` Fastest Request: ${colors.value(performance.fastestRequest)}ms`)
|
|
288
|
-
console.log(` Slowest Request: ${colors.value(performance.slowestRequest)}ms`)
|
|
302
|
+
console.log(colors.subheader('\n🚀 Performance Metrics:'))
|
|
303
|
+
console.log(` Average Response Time: ${colors.value(performance.averageResponseTime)}ms`)
|
|
304
|
+
console.log(` Fastest Request: ${colors.value(performance.fastestRequest)}ms`)
|
|
305
|
+
console.log(` Slowest Request: ${colors.value(performance.slowestRequest)}ms`)
|
|
289
306
|
|
|
290
307
|
// Quality stats
|
|
291
|
-
console.log(colors.subheader('\n📊 Quality Metrics:'))
|
|
292
|
-
console.log(` Success Rate: ${colors.percentage(metrics.successRate
|
|
293
|
-
console.log(` Errors: ${colors.error(metrics.errors)}`)
|
|
294
|
-
console.log(` Warnings: ${colors.warningMessage(metrics.warnings)}`)
|
|
295
|
-
console.log(` Retries: ${colors.number(metrics.retries)}`)
|
|
296
|
-
console.log(` Rule-based Fallbacks: ${colors.warningMessage(metrics.ruleBasedFallbacks)}`)
|
|
297
|
-
|
|
298
|
-
console.log(colors.separator())
|
|
308
|
+
console.log(colors.subheader('\n📊 Quality Metrics:'))
|
|
309
|
+
console.log(` Success Rate: ${colors.percentage(`${metrics.successRate}%`)}`)
|
|
310
|
+
console.log(` Errors: ${colors.error(metrics.errors)}`)
|
|
311
|
+
console.log(` Warnings: ${colors.warningMessage(metrics.warnings)}`)
|
|
312
|
+
console.log(` Retries: ${colors.number(metrics.retries)}`)
|
|
313
|
+
console.log(` Rule-based Fallbacks: ${colors.warningMessage(metrics.ruleBasedFallbacks)}`)
|
|
314
|
+
|
|
315
|
+
console.log(colors.separator())
|
|
299
316
|
}
|
|
300
317
|
|
|
301
318
|
// Export metrics for external analysis
|
|
302
319
|
exportMetrics(format = 'json') {
|
|
303
|
-
const metrics = this.getMetrics()
|
|
320
|
+
const metrics = this.getMetrics()
|
|
304
321
|
|
|
305
322
|
if (format === 'json') {
|
|
306
|
-
return JSON.stringify(metrics, null, 2)
|
|
323
|
+
return JSON.stringify(metrics, null, 2)
|
|
307
324
|
}
|
|
308
325
|
|
|
309
326
|
if (format === 'csv') {
|
|
310
|
-
return this.metricsToCSV(metrics)
|
|
327
|
+
return this.metricsToCSV(metrics)
|
|
311
328
|
}
|
|
312
329
|
|
|
313
|
-
return metrics
|
|
330
|
+
return metrics
|
|
314
331
|
}
|
|
315
332
|
|
|
316
333
|
metricsToCSV(metrics) {
|
|
317
|
-
const headers = Object.keys(metrics).join(',')
|
|
318
|
-
const values = Object.values(metrics)
|
|
319
|
-
typeof v === 'object' ? JSON.stringify(v) : v
|
|
320
|
-
|
|
334
|
+
const headers = Object.keys(metrics).join(',')
|
|
335
|
+
const values = Object.values(metrics)
|
|
336
|
+
.map((v) => (typeof v === 'object' ? JSON.stringify(v) : v))
|
|
337
|
+
.join(',')
|
|
321
338
|
|
|
322
|
-
return `${headers}\n${values}
|
|
339
|
+
return `${headers}\n${values}`
|
|
323
340
|
}
|
|
324
341
|
|
|
325
342
|
// Utilities for metric analysis
|
|
326
343
|
getTopModels(limit = 3) {
|
|
327
344
|
const models = Object.entries(this.metrics.modelUsage)
|
|
328
|
-
.sort(([,a], [,b]) => b - a)
|
|
329
|
-
.slice(0, limit)
|
|
345
|
+
.sort(([, a], [, b]) => b - a)
|
|
346
|
+
.slice(0, limit)
|
|
330
347
|
|
|
331
|
-
return models.map(([model, usage]) => ({ model, usage }))
|
|
348
|
+
return models.map(([model, usage]) => ({ model, usage }))
|
|
332
349
|
}
|
|
333
350
|
|
|
334
351
|
getEfficiencyScore() {
|
|
335
|
-
const metrics = this.getMetrics()
|
|
336
|
-
let score = 100
|
|
352
|
+
const metrics = this.getMetrics()
|
|
353
|
+
let score = 100
|
|
337
354
|
|
|
338
355
|
// Penalize errors
|
|
339
356
|
if (metrics.errors > 0) {
|
|
340
|
-
score -=
|
|
357
|
+
score -= metrics.errors * 10
|
|
341
358
|
}
|
|
342
359
|
|
|
343
360
|
// Penalize slow responses
|
|
344
361
|
if (metrics.averageResponseTime > 5000) {
|
|
345
|
-
score -= 20
|
|
362
|
+
score -= 20
|
|
346
363
|
} else if (metrics.averageResponseTime > 2000) {
|
|
347
|
-
score -= 10
|
|
364
|
+
score -= 10
|
|
348
365
|
}
|
|
349
366
|
|
|
350
367
|
// Penalize high fallback rate
|
|
351
|
-
const fallbackRate =
|
|
352
|
-
(metrics.ruleBasedFallbacks / metrics.apiCalls) * 100 : 0
|
|
368
|
+
const fallbackRate =
|
|
369
|
+
metrics.apiCalls > 0 ? (metrics.ruleBasedFallbacks / metrics.apiCalls) * 100 : 0
|
|
353
370
|
|
|
354
371
|
if (fallbackRate > 50) {
|
|
355
|
-
score -= 30
|
|
372
|
+
score -= 30
|
|
356
373
|
} else if (fallbackRate > 20) {
|
|
357
|
-
score -= 15
|
|
374
|
+
score -= 15
|
|
358
375
|
}
|
|
359
376
|
|
|
360
|
-
return Math.max(0, Math.min(100, score))
|
|
377
|
+
return Math.max(0, Math.min(100, score))
|
|
361
378
|
}
|
|
362
|
-
}
|
|
379
|
+
}
|