@entro314labs/ai-changelog-generator 3.1.1 → 3.2.1

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 +412 -875
  2. package/README.md +8 -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 +80 -48
  9. package/src/ai-changelog-generator.js +91 -81
  10. package/src/application/orchestrators/changelog.orchestrator.js +791 -516
  11. package/src/application/services/application.service.js +137 -128
  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 +328 -192
  15. package/src/domains/changelog/changelog.service.js +1174 -783
  16. package/src/domains/changelog/workspace-changelog.service.js +487 -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 +390 -274
  20. package/src/infrastructure/config/configuration.manager.js +220 -190
  21. package/src/infrastructure/interactive/interactive-staging.service.js +154 -135
  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 +259 -161
  43. package/src/shared/constants/colors.js +453 -180
  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 +1117 -945
  51. package/types/index.d.ts +353 -344
@@ -2,16 +2,20 @@
2
2
  * Abstract Base Provider for AI models.
3
3
  * Defines the interface that all provider plugins must implement.
4
4
  */
5
- import { AbstractMethodError } from '../../../shared/utils/utils.js';
5
+ import { AbstractMethodError } from '../../../shared/utils/utils.js'
6
6
 
7
7
  export class BaseProvider {
8
8
  constructor(config) {
9
9
  if (this.constructor === BaseProvider) {
10
- throw new AbstractMethodError("Abstract classes can't be instantiated", 'BaseProvider', 'constructor');
10
+ throw new AbstractMethodError(
11
+ "Abstract classes can't be instantiated",
12
+ 'BaseProvider',
13
+ 'constructor'
14
+ )
11
15
  }
12
- this.config = config;
13
- this.modelConfig = null;
14
- this.capabilities = {};
16
+ this.config = config
17
+ this.modelConfig = null
18
+ this.capabilities = {}
15
19
  }
16
20
 
17
21
  /**
@@ -19,7 +23,11 @@ export class BaseProvider {
19
23
  * @returns {string} The provider's name (e.g., 'openai', 'azure').
20
24
  */
21
25
  getName() {
22
- throw new AbstractMethodError('Method "getName()" must be implemented', this.constructor.name, 'getName');
26
+ throw new AbstractMethodError(
27
+ 'Method "getName()" must be implemented',
28
+ this.constructor.name,
29
+ 'getName'
30
+ )
23
31
  }
24
32
 
25
33
  /**
@@ -27,7 +35,11 @@ export class BaseProvider {
27
35
  * @returns {boolean} True if the provider is available, false otherwise.
28
36
  */
29
37
  isAvailable() {
30
- throw new AbstractMethodError('Method "isAvailable()" must be implemented', this.constructor.name, 'isAvailable');
38
+ throw new AbstractMethodError(
39
+ 'Method "isAvailable()" must be implemented',
40
+ this.constructor.name,
41
+ 'isAvailable'
42
+ )
31
43
  }
32
44
 
33
45
  /**
@@ -36,8 +48,12 @@ export class BaseProvider {
36
48
  * @param {object} options - Additional options for the completion (e.g., max_tokens).
37
49
  * @returns {Promise<object>} The AI's response.
38
50
  */
39
- async generateCompletion(messages, options = {}) {
40
- throw new AbstractMethodError('Method "generateCompletion()" must be implemented', this.constructor.name, 'generateCompletion');
51
+ async generateCompletion(_messages, _options = {}) {
52
+ throw new AbstractMethodError(
53
+ 'Method "generateCompletion()" must be implemented',
54
+ this.constructor.name,
55
+ 'generateCompletion'
56
+ )
41
57
  }
42
58
 
43
59
  /**
@@ -47,7 +63,7 @@ export class BaseProvider {
47
63
  * @returns {Promise<object>} The AI's response.
48
64
  */
49
65
  async generateText(messages, model = null) {
50
- return this.generateCompletion(messages, { model });
66
+ return this.generateCompletion(messages, { model })
51
67
  }
52
68
 
53
69
  /**
@@ -55,8 +71,12 @@ export class BaseProvider {
55
71
  * @param {object} commitDetails - Details about the commit (e.g., files changed, lines changed).
56
72
  * @returns {object} The recommended model and reason.
57
73
  */
58
- getModelRecommendation(commitDetails) {
59
- throw new AbstractMethodError('Method "getModelRecommendation()" must be implemented', this.constructor.name, 'getModelRecommendation');
74
+ getModelRecommendation(_commitDetails) {
75
+ throw new AbstractMethodError(
76
+ 'Method "getModelRecommendation()" must be implemented',
77
+ this.constructor.name,
78
+ 'getModelRecommendation'
79
+ )
60
80
  }
61
81
 
62
82
  /**
@@ -66,9 +86,9 @@ export class BaseProvider {
66
86
  */
67
87
  async selectOptimalModel(commitInfo) {
68
88
  try {
69
- return this.getModelRecommendation(commitInfo);
70
- } catch (error) {
71
- return { model: this.getDefaultModel(), reason: 'fallback' };
89
+ return this.getModelRecommendation(commitInfo)
90
+ } catch (_error) {
91
+ return { model: this.getDefaultModel(), reason: 'fallback' }
72
92
  }
73
93
  }
74
94
 
@@ -77,8 +97,12 @@ export class BaseProvider {
77
97
  * @param {string} modelName - The name of the model to validate.
78
98
  * @returns {Promise<object>} An object indicating availability and capabilities.
79
99
  */
80
- async validateModelAvailability(modelName) {
81
- throw new AbstractMethodError('Method "validateModelAvailability()" must be implemented', this.constructor.name, 'validateModelAvailability');
100
+ async validateModelAvailability(_modelName) {
101
+ throw new AbstractMethodError(
102
+ 'Method "validateModelAvailability()" must be implemented',
103
+ this.constructor.name,
104
+ 'validateModelAvailability'
105
+ )
82
106
  }
83
107
 
84
108
  /**
@@ -86,7 +110,11 @@ export class BaseProvider {
86
110
  * @returns {Promise<object>} An object indicating success or failure.
87
111
  */
88
112
  async testConnection() {
89
- throw new AbstractMethodError('Method "testConnection()" must be implemented', this.constructor.name, 'testConnection');
113
+ throw new AbstractMethodError(
114
+ 'Method "testConnection()" must be implemented',
115
+ this.constructor.name,
116
+ 'testConnection'
117
+ )
90
118
  }
91
119
 
92
120
  /**
@@ -94,8 +122,12 @@ export class BaseProvider {
94
122
  * @param {string} [modelName] - Optional model name to get specific capabilities.
95
123
  * @returns {object} An object listing the provider's capabilities.
96
124
  */
97
- getCapabilities(modelName) {
98
- throw new AbstractMethodError('Method "getCapabilities()" must be implemented', this.constructor.name, 'getCapabilities');
125
+ getCapabilities(_modelName) {
126
+ throw new AbstractMethodError(
127
+ 'Method "getCapabilities()" must be implemented',
128
+ this.constructor.name,
129
+ 'getCapabilities'
130
+ )
99
131
  }
100
132
 
101
133
  /**
@@ -103,7 +135,11 @@ export class BaseProvider {
103
135
  * @returns {Promise<Array>} List of available models
104
136
  */
105
137
  async getAvailableModels() {
106
- throw new AbstractMethodError('Method "getAvailableModels()" must be implemented', this.constructor.name, 'getAvailableModels');
138
+ throw new AbstractMethodError(
139
+ 'Method "getAvailableModels()" must be implemented',
140
+ this.constructor.name,
141
+ 'getAvailableModels'
142
+ )
107
143
  }
108
144
 
109
145
  /**
@@ -111,7 +147,11 @@ export class BaseProvider {
111
147
  * @returns {string} Default model name
112
148
  */
113
149
  getDefaultModel() {
114
- throw new AbstractMethodError('Method "getDefaultModel()" must be implemented', this.constructor.name, 'getDefaultModel');
150
+ throw new AbstractMethodError(
151
+ 'Method "getDefaultModel()" must be implemented',
152
+ this.constructor.name,
153
+ 'getDefaultModel'
154
+ )
115
155
  }
116
156
 
117
157
  /**
@@ -119,7 +159,7 @@ export class BaseProvider {
119
159
  * @returns {object} Provider configuration
120
160
  */
121
161
  getConfiguration() {
122
- return this.config || {};
162
+ return this.config || {}
123
163
  }
124
164
 
125
165
  /**
@@ -127,7 +167,11 @@ export class BaseProvider {
127
167
  * @returns {Array<string>} List of required env vars
128
168
  */
129
169
  getRequiredEnvVars() {
130
- throw new AbstractMethodError('Method "getRequiredEnvVars()" must be implemented', this.constructor.name, 'getRequiredEnvVars');
170
+ throw new AbstractMethodError(
171
+ 'Method "getRequiredEnvVars()" must be implemented',
172
+ this.constructor.name,
173
+ 'getRequiredEnvVars'
174
+ )
131
175
  }
132
176
 
133
177
  /**
@@ -135,7 +179,7 @@ export class BaseProvider {
135
179
  * @returns {string} Provider information string.
136
180
  */
137
181
  getProviderInfo() {
138
- return `${this.getName()} provider`;
182
+ return `${this.getName()} provider`
139
183
  }
140
184
 
141
185
  /**
@@ -145,14 +189,15 @@ export class BaseProvider {
145
189
  */
146
190
  async testModel(modelName) {
147
191
  try {
148
- const startTime = Date.now();
149
- await this.generateCompletion([
150
- { role: 'user', content: 'Test message' }
151
- ], { model: modelName, max_tokens: 5 });
152
- const responseTime = Date.now() - startTime;
153
- return { success: true, responseTime };
192
+ const startTime = Date.now()
193
+ await this.generateCompletion([{ role: 'user', content: 'Test message' }], {
194
+ model: modelName,
195
+ max_tokens: 5,
196
+ })
197
+ const responseTime = Date.now() - startTime
198
+ return { success: true, responseTime }
154
199
  } catch (error) {
155
- return { success: false, error: error.message };
200
+ return { success: false, error: error.message }
156
201
  }
157
202
  }
158
203
 
@@ -161,11 +206,13 @@ export class BaseProvider {
161
206
  * @returns {object} Provider model configuration
162
207
  */
163
208
  getProviderModelConfig() {
164
- return this.modelConfig || {
165
- default: this.getDefaultModel(),
166
- temperature: 0.3,
167
- maxTokens: 1000
168
- };
209
+ return (
210
+ this.modelConfig || {
211
+ default: this.getDefaultModel(),
212
+ temperature: 0.3,
213
+ maxTokens: 1000,
214
+ }
215
+ )
169
216
  }
170
217
 
171
218
  /**
@@ -176,9 +223,9 @@ export class BaseProvider {
176
223
  return {
177
224
  name: this.getName(),
178
225
  config: this.config,
179
- available: this.isAvailable()
180
- };
226
+ available: this.isAvailable(),
227
+ }
181
228
  }
182
229
  }
183
230
 
184
- export default BaseProvider;
231
+ export default BaseProvider
@@ -1,15 +1,15 @@
1
- import Anthropic from '@anthropic-ai/sdk';
2
- import { BaseProvider } from '../core/base-provider.js';
3
- import { ProviderError } from '../../../shared/utils/utils.js';
4
- import { applyMixins, ProviderResponseHandler } from '../utils/base-provider-helpers.js';
5
- import { buildClientOptions } from '../utils/provider-utils.js';
1
+ import Anthropic from '@anthropic-ai/sdk'
2
+
3
+ import { BaseProvider } from '../core/base-provider.js'
4
+ import { applyMixins, ProviderResponseHandler } from '../utils/base-provider-helpers.js'
5
+ import { buildClientOptions } from '../utils/provider-utils.js'
6
6
 
7
7
  export class AnthropicProvider extends BaseProvider {
8
8
  constructor(config) {
9
- super(config);
10
- this.anthropic = null;
9
+ super(config)
10
+ this.anthropic = null
11
11
  if (this.isAvailable()) {
12
- this.initializeClient();
12
+ this.initializeClient()
13
13
  }
14
14
  }
15
15
 
@@ -19,33 +19,33 @@ export class AnthropicProvider extends BaseProvider {
19
19
  maxRetries: 2,
20
20
  defaultHeaders: {
21
21
  'X-Client-Name': 'ai-changelog-generator',
22
- 'X-Client-Version': '1.0.0'
23
- }
24
- });
22
+ 'X-Client-Version': '1.0.0',
23
+ },
24
+ })
25
25
 
26
26
  this.anthropic = new Anthropic({
27
27
  apiKey: clientOptions.apiKey,
28
28
  baseURL: clientOptions.baseURL,
29
29
  timeout: clientOptions.timeout,
30
30
  maxRetries: clientOptions.maxRetries,
31
- defaultHeaders: clientOptions.defaultHeaders
32
- });
31
+ defaultHeaders: clientOptions.defaultHeaders,
32
+ })
33
33
  }
34
34
 
35
35
  getName() {
36
- return 'anthropic';
36
+ return 'anthropic'
37
37
  }
38
38
 
39
39
  isAvailable() {
40
- return !!this.config.ANTHROPIC_API_KEY;
40
+ return !!this.config.ANTHROPIC_API_KEY
41
41
  }
42
42
 
43
43
  getRequiredEnvVars() {
44
- return ['ANTHROPIC_API_KEY'];
44
+ return ['ANTHROPIC_API_KEY']
45
45
  }
46
46
 
47
47
  getDefaultModel() {
48
- return 'claude-sonnet-4-20250514';
48
+ return 'claude-sonnet-4-20250514'
49
49
  }
50
50
 
51
51
  async generateCompletion(messages, options = {}) {
@@ -53,11 +53,11 @@ export class AnthropicProvider extends BaseProvider {
53
53
  this,
54
54
  'generate_completion',
55
55
  async () => {
56
- const modelConfig = this.getProviderModelConfig();
56
+ const modelConfig = this.getProviderModelConfig()
57
57
 
58
58
  // Anthropic API uses a slightly different message format
59
- const systemMessage = messages.find(m => m.role === 'system');
60
- const userMessages = messages.filter(m => m.role !== 'system');
59
+ const systemMessage = messages.find((m) => m.role === 'system')
60
+ const userMessages = messages.filter((m) => m.role !== 'system')
61
61
 
62
62
  const params = {
63
63
  model: options.model || modelConfig.standardModel || this.getDefaultModel(),
@@ -65,33 +65,33 @@ export class AnthropicProvider extends BaseProvider {
65
65
  messages: userMessages,
66
66
  max_tokens: options.max_tokens || 4096,
67
67
  temperature: options.temperature || 0.3,
68
- };
68
+ }
69
69
 
70
70
  // Add tool calling if provided
71
71
  if (options.tools) {
72
- params.tools = options.tools;
73
- params.tool_choice = options.tool_choice || 'auto';
72
+ params.tools = options.tools
73
+ params.tool_choice = options.tool_choice || 'auto'
74
74
  }
75
75
 
76
76
  // Add streaming if requested
77
77
  if (options.stream) {
78
- params.stream = true;
79
- const stream = await this.anthropic.messages.create(params);
80
- return { stream, model: params.model };
78
+ params.stream = true
79
+ const stream = await this.anthropic.messages.create(params)
80
+ return { stream, model: params.model }
81
81
  }
82
82
 
83
- const response = await this.anthropic.messages.create(params);
83
+ const response = await this.anthropic.messages.create(params)
84
84
 
85
85
  // Check if there are tool calls in the response
86
- const toolCalls = response.content.some(c => c.type === 'tool_use')
87
- ? response.content.filter(c => c.type === 'tool_use').map(c => c.tool_use)
88
- : null;
86
+ const toolCalls = response.content.some((c) => c.type === 'tool_use')
87
+ ? response.content.filter((c) => c.type === 'tool_use').map((c) => c.tool_use)
88
+ : null
89
89
 
90
90
  // Get the text content
91
91
  const textContent = response.content
92
- .filter(c => c.type === 'text')
93
- .map(c => c.text)
94
- .join('\n');
92
+ .filter((c) => c.type === 'text')
93
+ .map((c) => c.text)
94
+ .join('\n')
95
95
 
96
96
  return {
97
97
  text: textContent,
@@ -101,16 +101,16 @@ export class AnthropicProvider extends BaseProvider {
101
101
  tokens: response.usage.input_tokens + response.usage.output_tokens,
102
102
  tool_calls: toolCalls,
103
103
  stop_reason: response.stop_reason,
104
- stop_sequence: response.stop_sequence
105
- };
104
+ stop_sequence: response.stop_sequence,
105
+ }
106
106
  },
107
107
  { model: options.model }
108
- );
108
+ )
109
109
  }
110
110
 
111
111
  async generateText(messages, model = null) {
112
- const response = await this.generateCompletion(messages, { model });
113
- return response;
112
+ const response = await this.generateCompletion(messages, { model })
113
+ return response
114
114
  }
115
115
 
116
116
  async getAvailableModels() {
@@ -127,8 +127,8 @@ export class AnthropicProvider extends BaseProvider {
127
127
  json_mode: true,
128
128
  multimodal: true,
129
129
  largeContext: true,
130
- toolUse: true
131
- }
130
+ toolUse: true,
131
+ },
132
132
  },
133
133
  {
134
134
  name: 'claude-opus-4-20250514',
@@ -142,8 +142,8 @@ export class AnthropicProvider extends BaseProvider {
142
142
  multimodal: true,
143
143
  largeContext: true,
144
144
  toolUse: true,
145
- advancedReasoning: true
146
- }
145
+ advancedReasoning: true,
146
+ },
147
147
  },
148
148
  {
149
149
  name: 'claude-3.7-sonnet-20250219',
@@ -156,8 +156,8 @@ export class AnthropicProvider extends BaseProvider {
156
156
  json_mode: true,
157
157
  multimodal: true,
158
158
  largeContext: true,
159
- toolUse: true
160
- }
159
+ toolUse: true,
160
+ },
161
161
  },
162
162
  {
163
163
  name: 'claude-3-5-sonnet-20241022',
@@ -168,8 +168,8 @@ export class AnthropicProvider extends BaseProvider {
168
168
  reasoning: true,
169
169
  function_calling: true,
170
170
  json_mode: true,
171
- multimodal: true
172
- }
171
+ multimodal: true,
172
+ },
173
173
  },
174
174
  {
175
175
  name: 'claude-3-5-haiku-20241022',
@@ -180,57 +180,60 @@ export class AnthropicProvider extends BaseProvider {
180
180
  reasoning: true,
181
181
  function_calling: true,
182
182
  json_mode: true,
183
- multimodal: true
184
- }
185
- }
186
- ];
183
+ multimodal: true,
184
+ },
185
+ },
186
+ ]
187
187
  }
188
188
 
189
189
  async validateModelAvailability(modelName) {
190
190
  try {
191
- const models = await this.getAvailableModels();
192
- const model = models.find(m => m.name === modelName);
191
+ const models = await this.getAvailableModels()
192
+ const model = models.find((m) => m.name === modelName)
193
193
 
194
194
  if (model) {
195
195
  return {
196
196
  available: true,
197
197
  model: modelName,
198
198
  capabilities: model.capabilities,
199
- contextWindow: model.contextWindow
200
- };
201
- } else {
202
- const availableModels = models.map(m => m.name);
203
- return {
204
- available: false,
205
- error: `Model '${modelName}' not available`,
206
- alternatives: availableModels.slice(0, 5)
207
- };
199
+ contextWindow: model.contextWindow,
200
+ }
201
+ }
202
+ const availableModels = models.map((m) => m.name)
203
+ return {
204
+ available: false,
205
+ error: `Model '${modelName}' not available`,
206
+ alternatives: availableModels.slice(0, 5),
208
207
  }
209
208
  } catch (error) {
210
209
  return {
211
210
  available: false,
212
211
  error: error.message,
213
- alternatives: ['claude-sonnet-4-20250514', 'claude-opus-4-20250514', 'claude-3.7-sonnet-20250219']
214
- };
212
+ alternatives: [
213
+ 'claude-sonnet-4-20250514',
214
+ 'claude-opus-4-20250514',
215
+ 'claude-3.7-sonnet-20250219',
216
+ ],
217
+ }
215
218
  }
216
219
  }
217
220
 
218
221
  async testConnection() {
219
222
  try {
220
- const response = await this.generateCompletion([
221
- { role: 'user', content: 'Hello' }
222
- ], { max_tokens: 5 });
223
+ const response = await this.generateCompletion([{ role: 'user', content: 'Hello' }], {
224
+ max_tokens: 5,
225
+ })
223
226
 
224
227
  return {
225
228
  success: true,
226
229
  model: response.model,
227
- message: 'Connection successful'
228
- };
230
+ message: 'Connection successful',
231
+ }
229
232
  } catch (error) {
230
233
  return {
231
234
  success: false,
232
- error: error.message
233
- };
235
+ error: error.message,
236
+ }
234
237
  }
235
238
  }
236
239
 
@@ -239,23 +242,23 @@ export class AnthropicProvider extends BaseProvider {
239
242
  const response = await this.anthropic.messages.create({
240
243
  model: modelName,
241
244
  messages: [{ role: 'user', content: 'Test' }],
242
- max_tokens: 1
243
- });
245
+ max_tokens: 1,
246
+ })
244
247
 
245
248
  return {
246
249
  success: true,
247
250
  model: response.model,
248
- sdk_version: '0.56.0'
249
- };
251
+ sdk_version: '0.56.0',
252
+ }
250
253
  } catch (error) {
251
254
  return {
252
255
  success: false,
253
- error: error.message
254
- };
256
+ error: error.message,
257
+ }
255
258
  }
256
259
  }
257
260
 
258
- getCapabilities(modelName) {
261
+ getCapabilities(_modelName) {
259
262
  return {
260
263
  completion: true,
261
264
  streaming: true,
@@ -263,52 +266,51 @@ export class AnthropicProvider extends BaseProvider {
263
266
  json_mode: true,
264
267
  reasoning: true,
265
268
  multimodal: true,
266
- large_context: true
267
- };
269
+ large_context: true,
270
+ }
268
271
  }
269
272
 
270
273
  getModelRecommendation(commitDetails) {
271
- const { files = 0, lines = 0, breaking = false, complex = false } = commitDetails;
274
+ const { files = 0, lines = 0, breaking = false, complex = false } = commitDetails
272
275
 
273
276
  // Use the most capable model for complex or breaking changes
274
277
  if (breaking || complex || files > 20 || lines > 1000) {
275
278
  return {
276
279
  model: 'claude-3-5-sonnet-20241022',
277
- reason: 'Complex or breaking change requiring advanced reasoning'
278
- };
280
+ reason: 'Complex or breaking change requiring advanced reasoning',
281
+ }
279
282
  }
280
283
 
281
284
  // Use standard model for medium changes
282
285
  if (files > 5 || lines > 200) {
283
286
  return {
284
287
  model: 'claude-3-sonnet-20240229',
285
- reason: 'Medium-sized change requiring good analysis'
286
- };
288
+ reason: 'Medium-sized change requiring good analysis',
289
+ }
287
290
  }
288
291
 
289
292
  // Use efficient model for small changes
290
293
  return {
291
294
  model: 'claude-3-haiku-20240307',
292
- reason: 'Small change, optimized for efficiency'
293
- };
295
+ reason: 'Small change, optimized for efficiency',
296
+ }
294
297
  }
295
298
 
296
299
  async selectOptimalModel(commitInfo) {
297
- const recommendation = this.getModelRecommendation(commitInfo);
298
- const validation = await this.validateModelAvailability(recommendation.model);
300
+ const recommendation = this.getModelRecommendation(commitInfo)
301
+ const validation = await this.validateModelAvailability(recommendation.model)
299
302
 
300
303
  if (validation.available) {
301
304
  return {
302
305
  model: recommendation.model,
303
306
  reason: recommendation.reason,
304
- capabilities: validation.capabilities
305
- };
306
- } else {
307
- return {
308
- model: this.getDefaultModel(),
309
- reason: 'Fallback to default model',
310
- capabilities: this.getCapabilities(this.getDefaultModel())
311
- };
307
+ capabilities: validation.capabilities,
308
+ }
309
+ }
310
+ return {
311
+ model: this.getDefaultModel(),
312
+ reason: 'Fallback to default model',
313
+ capabilities: this.getCapabilities(this.getDefaultModel()),
312
314
  }
313
315
  }
314
316
 
@@ -320,10 +322,10 @@ export class AnthropicProvider extends BaseProvider {
320
322
  complexModel: 'claude-opus-4-20250514',
321
323
  default: 'claude-sonnet-4-20250514',
322
324
  temperature: 0.3,
323
- maxTokens: 4096
324
- };
325
+ maxTokens: 4096,
326
+ }
325
327
  }
326
328
  }
327
329
 
328
330
  // Apply mixins to add standard provider functionality
329
- export default applyMixins ? applyMixins(AnthropicProvider, 'anthropic') : AnthropicProvider;
331
+ export default applyMixins ? applyMixins(AnthropicProvider, 'anthropic') : AnthropicProvider