@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
@@ -4,40 +4,40 @@
4
4
  * Supports multi-provider routing, chat completion, and latest models
5
5
  */
6
6
 
7
- import { InferenceClient } from '@huggingface/inference';
8
- import { BaseProvider } from '../core/base-provider.js';
9
- import { ProviderError } from '../../../shared/utils/utils.js';
10
- import { applyMixins } from '../utils/base-provider-helpers.js';
11
- import { buildClientOptions } from '../utils/provider-utils.js';
7
+ import { InferenceClient } from '@huggingface/inference'
8
+
9
+ import { BaseProvider } from '../core/base-provider.js'
10
+ import { applyMixins } from '../utils/base-provider-helpers.js'
11
+ import { buildClientOptions } from '../utils/provider-utils.js'
12
12
 
13
13
  class HuggingFaceProvider extends BaseProvider {
14
14
  constructor(config) {
15
- super(config);
16
- this.client = null;
15
+ super(config)
16
+ this.client = null
17
17
 
18
18
  if (this.isAvailable()) {
19
- this.initializeClient();
19
+ this.initializeClient()
20
20
  }
21
21
  }
22
22
 
23
23
  initializeClient() {
24
24
  const clientOptions = buildClientOptions(this.getProviderConfig(), {
25
- timeout: 60000
26
- });
25
+ timeout: 60000,
26
+ })
27
27
 
28
28
  this.client = new InferenceClient({
29
29
  token: clientOptions.apiKey,
30
30
  endpointUrl: clientOptions.endpointUrl,
31
- timeout: clientOptions.timeout
32
- });
31
+ timeout: clientOptions.timeout,
32
+ })
33
33
  }
34
34
 
35
35
  getName() {
36
- return 'huggingface';
36
+ return 'huggingface'
37
37
  }
38
38
 
39
39
  isAvailable() {
40
- return !!this.config.HUGGINGFACE_API_KEY;
40
+ return !!this.config.HUGGINGFACE_API_KEY
41
41
  }
42
42
 
43
43
  async generateCompletion(messages, options = {}) {
@@ -45,13 +45,13 @@ class HuggingFaceProvider extends BaseProvider {
45
45
  return this.handleProviderError(
46
46
  new Error('Hugging Face provider is not configured'),
47
47
  'generate_completion'
48
- );
48
+ )
49
49
  }
50
50
 
51
51
  try {
52
- const modelConfig = this.getProviderModelConfig();
53
- const modelId = options.model || modelConfig.standardModel;
54
- const provider = options.provider || 'auto';
52
+ const modelConfig = this.getProviderModelConfig()
53
+ const modelId = options.model || modelConfig.standardModel
54
+ const provider = options.provider || 'auto'
55
55
 
56
56
  const params = {
57
57
  model: modelId,
@@ -59,34 +59,34 @@ class HuggingFaceProvider extends BaseProvider {
59
59
  max_tokens: options.max_tokens || 1000,
60
60
  temperature: options.temperature || 0.3,
61
61
  top_p: options.top_p || 0.95,
62
- stream: false
63
- };
62
+ stream: false,
63
+ }
64
64
 
65
65
  if (provider && provider !== 'auto') {
66
- params.provider = provider;
66
+ params.provider = provider
67
67
  }
68
68
 
69
69
  if (options.tools && this.getCapabilities(modelId).function_calling) {
70
- params.tools = this.formatTools(options.tools);
71
- params.tool_choice = options.tool_choice || 'auto';
70
+ params.tools = this.formatTools(options.tools)
71
+ params.tool_choice = options.tool_choice || 'auto'
72
72
  }
73
73
 
74
74
  if (options.stream && typeof options.onStreamData === 'function') {
75
- params.stream = true;
75
+ params.stream = true
76
76
 
77
- let fullContent = '';
78
- const stream = this.client.chatCompletionStream(params);
77
+ let fullContent = ''
78
+ const stream = this.client.chatCompletionStream(params)
79
79
 
80
80
  for await (const chunk of stream) {
81
- const chunkContent = chunk.choices[0]?.delta?.content || '';
81
+ const chunkContent = chunk.choices[0]?.delta?.content || ''
82
82
  if (chunkContent) {
83
- fullContent += chunkContent;
83
+ fullContent += chunkContent
84
84
  options.onStreamData({
85
85
  content: chunkContent,
86
86
  model: modelId,
87
87
  finish_reason: null,
88
- done: false
89
- });
88
+ done: false,
89
+ })
90
90
  }
91
91
 
92
92
  if (chunk.choices[0]?.finish_reason) {
@@ -94,9 +94,9 @@ class HuggingFaceProvider extends BaseProvider {
94
94
  content: '',
95
95
  model: modelId,
96
96
  finish_reason: chunk.choices[0].finish_reason,
97
- done: true
98
- });
99
- break;
97
+ done: true,
98
+ })
99
+ break
100
100
  }
101
101
  }
102
102
 
@@ -104,77 +104,78 @@ class HuggingFaceProvider extends BaseProvider {
104
104
  content: fullContent,
105
105
  model: modelId,
106
106
  tokens: this.estimateTokenCount(fullContent),
107
- finish_reason: 'stop'
108
- };
107
+ finish_reason: 'stop',
108
+ }
109
109
  }
110
110
 
111
- const response = await this.client.chatCompletion(params);
111
+ const response = await this.client.chatCompletion(params)
112
112
 
113
- const choice = response.choices[0];
114
- const content = choice.message.content;
113
+ const choice = response.choices[0]
114
+ const content = choice.message.content
115
115
 
116
- const toolCalls = choice.message.tool_calls ?
117
- choice.message.tool_calls.map(call => ({
118
- id: call.id,
119
- type: call.type,
120
- function: {
121
- name: call.function.name,
122
- arguments: call.function.arguments
123
- }
124
- })) : undefined;
116
+ const toolCalls = choice.message.tool_calls
117
+ ? choice.message.tool_calls.map((call) => ({
118
+ id: call.id,
119
+ type: call.type,
120
+ function: {
121
+ name: call.function.name,
122
+ arguments: call.function.arguments,
123
+ },
124
+ }))
125
+ : undefined
125
126
 
126
127
  return {
127
- content: content,
128
+ content,
128
129
  model: response.model || modelId,
129
130
  tokens: response.usage?.total_tokens || this.estimateTokenCount(content),
130
131
  finish_reason: choice.finish_reason || 'stop',
131
- tool_calls: toolCalls
132
- };
132
+ tool_calls: toolCalls,
133
+ }
133
134
  } catch (error) {
134
135
  if (error.message.includes('rate limit') || error.message.includes('quota')) {
135
- console.warn('Hugging Face rate limit hit, implementing backoff...');
136
- await this.sleep(2000);
136
+ console.warn('Hugging Face rate limit hit, implementing backoff...')
137
+ await this.sleep(2000)
137
138
  }
138
139
 
139
- return this.handleProviderError(error, 'generate_completion', { model: options.model });
140
+ return this.handleProviderError(error, 'generate_completion', { model: options.model })
140
141
  }
141
142
  }
142
143
 
143
144
  // HuggingFace-specific helper methods
144
145
  formatMessages(messages) {
145
- return messages.map(msg => {
146
+ return messages.map((msg) => {
146
147
  if (msg.role === 'system') {
147
- return { role: 'system', content: msg.content };
148
+ return { role: 'system', content: msg.content }
148
149
  }
149
150
  return {
150
151
  role: msg.role === 'assistant' ? 'assistant' : 'user',
151
- content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content)
152
- };
153
- });
152
+ content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content),
153
+ }
154
+ })
154
155
  }
155
156
 
156
157
  formatTools(tools) {
157
- return tools.map(tool => {
158
+ return tools.map((tool) => {
158
159
  if (tool.type === 'function') {
159
160
  return {
160
161
  type: 'function',
161
162
  function: {
162
163
  name: tool.function.name,
163
164
  description: tool.function.description || '',
164
- parameters: tool.function.parameters || {}
165
- }
166
- };
165
+ parameters: tool.function.parameters || {},
166
+ },
167
+ }
167
168
  }
168
- return tool;
169
- });
169
+ return tool
170
+ })
170
171
  }
171
172
 
172
173
  estimateTokenCount(text) {
173
- return Math.ceil(text.length / 4);
174
+ return Math.ceil(text.length / 4)
174
175
  }
175
176
 
176
177
  sleep(ms) {
177
- return new Promise(resolve => setTimeout(resolve, ms));
178
+ return new Promise((resolve) => setTimeout(resolve, ms))
178
179
  }
179
180
 
180
181
  getAvailableModels() {
@@ -189,7 +190,7 @@ class HuggingFaceProvider extends BaseProvider {
189
190
  outputCost: 0.000009,
190
191
  features: ['text', 'tools', 'multilingual'],
191
192
  description: 'Latest Qwen model with enhanced capabilities',
192
- provider: 'auto'
193
+ provider: 'auto',
193
194
  },
194
195
  {
195
196
  id: 'meta-llama/Llama-3.3-70B-Instruct',
@@ -200,7 +201,7 @@ class HuggingFaceProvider extends BaseProvider {
200
201
  outputCost: 0.000006,
201
202
  features: ['text', 'tools', 'reasoning'],
202
203
  description: 'Latest Llama 3.3 with improved reasoning',
203
- provider: 'together'
204
+ provider: 'together',
204
205
  },
205
206
  {
206
207
  id: 'meta-llama/Llama-3.1-405B-Instruct',
@@ -211,7 +212,7 @@ class HuggingFaceProvider extends BaseProvider {
211
212
  outputCost: 0.000015,
212
213
  features: ['text', 'tools', 'reasoning'],
213
214
  description: 'Most capable Llama model from Meta AI',
214
- provider: 'replicate'
215
+ provider: 'replicate',
215
216
  },
216
217
  {
217
218
  id: 'mistralai/Mixtral-8x22B-Instruct-v0.1',
@@ -222,7 +223,7 @@ class HuggingFaceProvider extends BaseProvider {
222
223
  outputCost: 0.0000027,
223
224
  features: ['text', 'tools', 'multilingual'],
224
225
  description: 'Large mixture of experts model from Mistral',
225
- provider: 'together'
226
+ provider: 'together',
226
227
  },
227
228
  {
228
229
  id: 'microsoft/WizardLM-2-8x22B',
@@ -233,28 +234,28 @@ class HuggingFaceProvider extends BaseProvider {
233
234
  outputCost: 0.000003,
234
235
  features: ['text', 'reasoning', 'complex_tasks'],
235
236
  description: 'Advanced reasoning model from Microsoft',
236
- provider: 'sambanova'
237
+ provider: 'sambanova',
237
238
  },
238
239
  {
239
240
  id: 'black-forest-labs/FLUX.1-dev',
240
241
  name: 'FLUX.1 Dev',
241
242
  contextWindow: 0,
242
243
  maxOutput: 0,
243
- inputCost: 0.000050,
244
- outputCost: 0.000050,
244
+ inputCost: 0.00005,
245
+ outputCost: 0.00005,
245
246
  features: ['text_to_image', 'high_quality'],
246
247
  description: 'State-of-the-art text-to-image generation',
247
- provider: 'replicate'
248
- }
249
- ];
248
+ provider: 'replicate',
249
+ },
250
+ ]
250
251
  }
251
252
 
252
253
  getDefaultModel() {
253
- return 'Qwen/Qwen2.5-72B-Instruct';
254
+ return 'Qwen/Qwen2.5-72B-Instruct'
254
255
  }
255
256
 
256
257
  getRequiredEnvVars() {
257
- return ['HUGGINGFACE_API_KEY'];
258
+ return ['HUGGINGFACE_API_KEY']
258
259
  }
259
260
 
260
261
  getProviderModelConfig() {
@@ -267,21 +268,27 @@ class HuggingFaceProvider extends BaseProvider {
267
268
  multilingualModel: 'mistralai/Mixtral-8x22B-Instruct-v0.1',
268
269
  default: 'Qwen/Qwen2.5-72B-Instruct',
269
270
  temperature: 0.3,
270
- maxTokens: 1000
271
- };
271
+ maxTokens: 1000,
272
+ }
272
273
  }
273
274
 
274
275
  getModelCapabilities(modelName) {
275
276
  return {
276
- reasoning: modelName.includes('Llama-3') || modelName.includes('WizardLM') || modelName.includes('Qwen'),
277
+ reasoning:
278
+ modelName.includes('Llama-3') ||
279
+ modelName.includes('WizardLM') ||
280
+ modelName.includes('Qwen'),
277
281
  function_calling: modelName.includes('Instruct') && !modelName.includes('FLUX'),
278
282
  json_mode: true,
279
283
  multimodal: modelName.includes('FLUX'),
280
- largeContext: modelName.includes('Llama-3.3') || modelName.includes('Mixtral') || modelName.includes('Qwen'),
284
+ largeContext:
285
+ modelName.includes('Llama-3.3') ||
286
+ modelName.includes('Mixtral') ||
287
+ modelName.includes('Qwen'),
281
288
  multilingual: modelName.includes('Qwen') || modelName.includes('Mixtral'),
282
289
  multiProvider: true,
283
- imageGeneration: modelName.includes('FLUX')
284
- };
290
+ imageGeneration: modelName.includes('FLUX'),
291
+ }
285
292
  }
286
293
 
287
294
  getCapabilities(modelName) {
@@ -292,10 +299,10 @@ class HuggingFaceProvider extends BaseProvider {
292
299
  json_mode: true,
293
300
  reasoning: modelName ? this.getModelCapabilities(modelName).reasoning : true,
294
301
  multimodal: modelName ? this.getModelCapabilities(modelName).multimodal : false,
295
- multiProvider: true
296
- };
302
+ multiProvider: true,
303
+ }
297
304
  }
298
305
  }
299
306
 
300
307
  // Apply mixins to add standard provider functionality
301
- export default applyMixins(HuggingFaceProvider, 'huggingface');
308
+ export default applyMixins(HuggingFaceProvider, 'huggingface')
@@ -1,14 +1,15 @@
1
- import { OpenAI } from 'openai';
2
- import { BaseProvider } from '../core/base-provider.js';
3
- import { applyMixins } from '../utils/base-provider-helpers.js';
4
- import { buildClientOptions } from '../utils/provider-utils.js';
1
+ import { OpenAI } from 'openai'
2
+
3
+ import { BaseProvider } from '../core/base-provider.js'
4
+ import { applyMixins } from '../utils/base-provider-helpers.js'
5
+ import { buildClientOptions } from '../utils/provider-utils.js'
5
6
 
6
7
  class LMStudioProvider extends BaseProvider {
7
8
  constructor(config) {
8
- super(config);
9
- this.client = null;
9
+ super(config)
10
+ this.client = null
10
11
  if (this.isAvailable()) {
11
- this.initializeClient();
12
+ this.initializeClient()
12
13
  }
13
14
  }
14
15
 
@@ -17,71 +18,79 @@ class LMStudioProvider extends BaseProvider {
17
18
  baseURL: 'http://localhost:1234/v1',
18
19
  apiKey: 'lm-studio', // Not required by LM Studio
19
20
  timeout: 120000,
20
- maxRetries: 2
21
- });
22
-
21
+ maxRetries: 2,
22
+ })
23
+
23
24
  // LM Studio uses OpenAI-compatible API
24
25
  this.client = new OpenAI({
25
26
  baseURL: clientOptions.baseURL,
26
27
  apiKey: clientOptions.apiKey,
27
28
  timeout: clientOptions.timeout,
28
29
  maxRetries: clientOptions.maxRetries,
29
- });
30
+ })
30
31
  }
31
32
 
32
33
  getName() {
33
- return 'lmstudio';
34
+ return 'lmstudio'
34
35
  }
35
36
 
36
37
  isAvailable() {
37
- return !!this.config.LMSTUDIO_API_BASE;
38
+ return !!this.config.LMSTUDIO_API_BASE
38
39
  }
39
40
 
40
41
  async generateCompletion(messages, options) {
41
42
  if (!this.isAvailable()) {
42
43
  return this.handleProviderError(
43
- new Error('LM Studio provider is not configured'),
44
+ new Error('LM Studio provider is not configured'),
44
45
  'generate_completion'
45
- );
46
+ )
46
47
  }
47
48
 
48
49
  // Prepare parameters for the API call
49
50
  const params = {
50
- model: options.model || this.config.AI_MODEL || this.config.LMSTUDIO_MODEL || this.config.LMSTUDIO_DEFAULT_MODEL || 'local-model',
51
- messages: messages,
51
+ model:
52
+ options.model ||
53
+ this.config.AI_MODEL ||
54
+ this.config.LMSTUDIO_MODEL ||
55
+ this.config.LMSTUDIO_DEFAULT_MODEL ||
56
+ 'local-model',
57
+ messages,
52
58
  max_tokens: options.max_tokens || 2048,
53
59
  temperature: options.temperature || 0.7,
54
60
  top_p: options.top_p || 0.95,
55
61
  frequency_penalty: options.frequency_penalty || 0,
56
62
  presence_penalty: options.presence_penalty || 0,
57
- user: options.user || this.config.LMSTUDIO_USER_ID
58
- };
63
+ user: options.user || this.config.LMSTUDIO_USER_ID,
64
+ }
59
65
 
60
66
  // Add function calling if provided and the model supports it
61
67
  if (options.tools && this.getCapabilities(params.model).tool_use) {
62
- params.tools = options.tools;
63
- params.tool_choice = options.tool_choice || 'auto';
68
+ params.tools = options.tools
69
+ params.tool_choice = options.tool_choice || 'auto'
64
70
  }
65
71
 
66
72
  // Add JSON mode if requested and the model supports it
67
- if (options.response_format?.type === 'json_object' && this.getCapabilities(params.model).json_mode) {
68
- params.response_format = { type: 'json_object' };
73
+ if (
74
+ options.response_format?.type === 'json_object' &&
75
+ this.getCapabilities(params.model).json_mode
76
+ ) {
77
+ params.response_format = { type: 'json_object' }
69
78
  }
70
79
 
71
80
  // Handle streaming
72
81
  if (options.stream) {
73
- params.stream = true;
74
- const stream = await this.client.chat.completions.create(params);
75
- return { stream, model: params.model };
82
+ params.stream = true
83
+ const stream = await this.client.chat.completions.create(params)
84
+ return { stream, model: params.model }
76
85
  }
77
86
 
78
87
  // Make the non-streaming API call
79
- const response = await this.client.chat.completions.create(params);
88
+ const response = await this.client.chat.completions.create(params)
80
89
 
81
90
  // Extract tool calls if present
82
- let toolCalls = null;
91
+ let toolCalls = null
83
92
  if (response.choices[0]?.message?.tool_calls?.length > 0) {
84
- toolCalls = response.choices[0].message.tool_calls;
93
+ toolCalls = response.choices[0].message.tool_calls
85
94
  }
86
95
 
87
96
  return {
@@ -89,54 +98,60 @@ class LMStudioProvider extends BaseProvider {
89
98
  model: response.model,
90
99
  tokens: response.usage?.total_tokens || 0,
91
100
  finish_reason: response.choices[0].finish_reason,
92
- tool_calls: toolCalls
93
- };
101
+ tool_calls: toolCalls,
102
+ }
94
103
  }
95
104
 
96
-
97
105
  getCapabilities(modelName) {
98
- const model = modelName || this.config.AI_MODEL || this.config.LMSTUDIO_MODEL || this.config.LMSTUDIO_DEFAULT_MODEL || 'local-model';
99
-
106
+ const model =
107
+ modelName ||
108
+ this.config.AI_MODEL ||
109
+ this.config.LMSTUDIO_MODEL ||
110
+ this.config.LMSTUDIO_DEFAULT_MODEL ||
111
+ 'local-model'
112
+
100
113
  // Base capabilities - all models are local
101
114
  const capabilities = {
102
115
  vision: false,
103
116
  tool_use: false,
104
117
  json_mode: false,
105
118
  reasoning: false,
106
- local: true
107
- };
108
-
119
+ local: true,
120
+ }
121
+
109
122
  // Capabilities depend on the specific model loaded in LM Studio
110
123
  // These are general capabilities based on model family naming conventions
111
-
124
+
112
125
  // Llama models
113
126
  if (model.toLowerCase().includes('llama')) {
114
- capabilities.json_mode = true;
115
-
127
+ capabilities.json_mode = true
128
+
116
129
  // Llama 3 models likely support function calling
117
130
  if (model.includes('3')) {
118
- capabilities.tool_use = true;
131
+ capabilities.tool_use = true
119
132
  }
120
133
  }
121
-
134
+
122
135
  // Mistral models
123
136
  else if (model.toLowerCase().includes('mistral')) {
124
- capabilities.json_mode = true;
125
-
137
+ capabilities.json_mode = true
138
+
126
139
  // Mixtral models likely have better reasoning
127
140
  if (model.toLowerCase().includes('mixtral')) {
128
- capabilities.reasoning = true;
141
+ capabilities.reasoning = true
129
142
  }
130
143
  }
131
-
144
+
132
145
  // Vision models
133
- if (model.toLowerCase().includes('vision') ||
134
- model.toLowerCase().includes('llava') ||
135
- model.toLowerCase().includes('bakllava')) {
136
- capabilities.vision = true;
146
+ if (
147
+ model.toLowerCase().includes('vision') ||
148
+ model.toLowerCase().includes('llava') ||
149
+ model.toLowerCase().includes('bakllava')
150
+ ) {
151
+ capabilities.vision = true
137
152
  }
138
-
139
- return capabilities;
153
+
154
+ return capabilities
140
155
  }
141
156
 
142
157
  getAvailableModels() {
@@ -146,10 +161,10 @@ class LMStudioProvider extends BaseProvider {
146
161
  name: 'Local Model (LM Studio)',
147
162
  contextWindow: 4096,
148
163
  maxOutput: 2048,
149
- inputCost: 0, // Local models are free
164
+ inputCost: 0, // Local models are free
150
165
  outputCost: 0,
151
166
  features: ['text', 'local'],
152
- description: 'Local model running in LM Studio'
167
+ description: 'Local model running in LM Studio',
153
168
  },
154
169
  {
155
170
  id: 'llama-3-8b-instruct',
@@ -159,7 +174,7 @@ class LMStudioProvider extends BaseProvider {
159
174
  inputCost: 0,
160
175
  outputCost: 0,
161
176
  features: ['text', 'tools', 'local'],
162
- description: 'Local Llama 3 8B instruction-tuned model'
177
+ description: 'Local Llama 3 8B instruction-tuned model',
163
178
  },
164
179
  {
165
180
  id: 'mistral-7b-instruct',
@@ -169,7 +184,7 @@ class LMStudioProvider extends BaseProvider {
169
184
  inputCost: 0,
170
185
  outputCost: 0,
171
186
  features: ['text', 'reasoning', 'local'],
172
- description: 'Local Mistral 7B instruction-tuned model'
187
+ description: 'Local Mistral 7B instruction-tuned model',
173
188
  },
174
189
  {
175
190
  id: 'llava-1.5-7b',
@@ -179,11 +194,11 @@ class LMStudioProvider extends BaseProvider {
179
194
  inputCost: 0,
180
195
  outputCost: 0,
181
196
  features: ['text', 'vision', 'local'],
182
- description: 'Local vision-language model'
183
- }
184
- ];
197
+ description: 'Local vision-language model',
198
+ },
199
+ ]
185
200
  }
186
201
  }
187
202
 
188
203
  // Apply mixins to add standard provider functionality
189
- export default applyMixins(LMStudioProvider, 'lmstudio');
204
+ export default applyMixins(LMStudioProvider, 'lmstudio')