@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.
Files changed (51) hide show
  1. package/CHANGELOG.md +383 -785
  2. package/README.md +30 -3
  3. package/ai-changelog-mcp.sh +0 -0
  4. package/ai-changelog.sh +0 -0
  5. package/bin/ai-changelog-dxt.js +9 -9
  6. package/bin/ai-changelog-mcp.js +19 -17
  7. package/bin/ai-changelog.js +6 -6
  8. package/package.json +84 -52
  9. package/src/ai-changelog-generator.js +83 -81
  10. package/src/application/orchestrators/changelog.orchestrator.js +1040 -296
  11. package/src/application/services/application.service.js +145 -123
  12. package/src/cli.js +76 -57
  13. package/src/domains/ai/ai-analysis.service.js +289 -209
  14. package/src/domains/analysis/analysis.engine.js +253 -193
  15. package/src/domains/changelog/changelog.service.js +1062 -784
  16. package/src/domains/changelog/workspace-changelog.service.js +420 -249
  17. package/src/domains/git/git-repository.analyzer.js +348 -258
  18. package/src/domains/git/git.service.js +132 -112
  19. package/src/infrastructure/cli/cli.controller.js +415 -247
  20. package/src/infrastructure/config/configuration.manager.js +220 -190
  21. package/src/infrastructure/interactive/interactive-staging.service.js +332 -0
  22. package/src/infrastructure/interactive/interactive-workflow.service.js +200 -159
  23. package/src/infrastructure/mcp/mcp-server.service.js +208 -207
  24. package/src/infrastructure/metrics/metrics.collector.js +140 -123
  25. package/src/infrastructure/providers/core/base-provider.js +87 -40
  26. package/src/infrastructure/providers/implementations/anthropic.js +101 -99
  27. package/src/infrastructure/providers/implementations/azure.js +124 -101
  28. package/src/infrastructure/providers/implementations/bedrock.js +136 -126
  29. package/src/infrastructure/providers/implementations/dummy.js +23 -23
  30. package/src/infrastructure/providers/implementations/google.js +123 -114
  31. package/src/infrastructure/providers/implementations/huggingface.js +94 -87
  32. package/src/infrastructure/providers/implementations/lmstudio.js +75 -60
  33. package/src/infrastructure/providers/implementations/mock.js +69 -73
  34. package/src/infrastructure/providers/implementations/ollama.js +89 -66
  35. package/src/infrastructure/providers/implementations/openai.js +88 -89
  36. package/src/infrastructure/providers/implementations/vertex.js +227 -197
  37. package/src/infrastructure/providers/provider-management.service.js +245 -207
  38. package/src/infrastructure/providers/provider-manager.service.js +145 -125
  39. package/src/infrastructure/providers/utils/base-provider-helpers.js +308 -302
  40. package/src/infrastructure/providers/utils/model-config.js +220 -195
  41. package/src/infrastructure/providers/utils/provider-utils.js +105 -100
  42. package/src/infrastructure/validation/commit-message-validation.service.js +556 -0
  43. package/src/shared/constants/colors.js +467 -172
  44. package/src/shared/utils/cli-demo.js +285 -0
  45. package/src/shared/utils/cli-entry-utils.js +257 -249
  46. package/src/shared/utils/cli-ui.js +447 -0
  47. package/src/shared/utils/diff-processor.js +513 -0
  48. package/src/shared/utils/error-classes.js +125 -156
  49. package/src/shared/utils/json-utils.js +93 -89
  50. package/src/shared/utils/utils.js +1299 -775
  51. package/types/index.d.ts +353 -344
@@ -1,5 +1,7 @@
1
- import colors from '../../shared/constants/colors.js';
2
- import { formatDuration } from '../../shared/utils/utils.js';
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: Infinity,
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(reason = 'unknown') {
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(warning = {}) {
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) return 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: this.metrics.fastestRequest === Infinity ? 0 : this.metrics.fastestRequest,
202
+ fastestRequest:
203
+ this.metrics.fastestRequest === Number.POSITIVE_INFINITY ? 0 : this.metrics.fastestRequest,
199
204
  totalTokens: this.metrics.totalTokens,
200
- cacheHitRate: this.metrics.apiCalls > 0 ?
201
- Math.round((this.metrics.cacheHits / this.metrics.apiCalls) * 100) : 0
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(` ${colors.label('Commits processed')}: ${colors.number(metrics.commitsProcessed)}`);
223
- console.log(` ${colors.label('Files analyzed')}: ${colors.number(metrics.filesAnalyzed)}`);
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(` ${colors.label('Avg response time')}: ${colors.value(Math.round(metrics.averageResponseTime))}ms`);
229
- console.log(` ${colors.label('Success rate')}: ${colors.percentage(metrics.successRate + '%')}`);
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(` ${colors.label('Rule-based fallbacks')}: ${colors.warningMessage(metrics.ruleBasedFallbacks)}`);
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(` Cache Hits: ${colors.number(metrics.cacheHits)} (${performance.cacheHitRate}%)`);
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(` Model Usage:`);
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).map(v =>
319
- typeof v === 'object' ? JSON.stringify(v) : v
320
- ).join(',');
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 -= (metrics.errors * 10);
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 = metrics.apiCalls > 0 ?
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
+ }