omnimancer-cli 0.1.0__py3-none-any.whl
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.
- omnimancer/__init__.py +42 -0
- omnimancer/__main__.py +9 -0
- omnimancer/cli/__init__.py +8 -0
- omnimancer/cli/agent_manager.py +826 -0
- omnimancer/cli/agent_wizard.py +944 -0
- omnimancer/cli/approval_formatter.py +734 -0
- omnimancer/cli/approval_integration.py +734 -0
- omnimancer/cli/approval_prompt.py +1286 -0
- omnimancer/cli/batch_approval_display.py +617 -0
- omnimancer/cli/batch_approval_filters.py +729 -0
- omnimancer/cli/batch_operation_monitor.py +775 -0
- omnimancer/cli/commands/performance_cmd.py +624 -0
- omnimancer/cli/commands.py +757 -0
- omnimancer/cli/completion_handler.py +281 -0
- omnimancer/cli/config_setup_wizard.py +783 -0
- omnimancer/cli/dynamic_commands.py +371 -0
- omnimancer/cli/handlers/__init__.py +18 -0
- omnimancer/cli/handlers/agent_handler.py +865 -0
- omnimancer/cli/handlers/agent_persona_handler.py +1048 -0
- omnimancer/cli/handlers/custom_agent_handler.py +352 -0
- omnimancer/cli/handlers/permissions_handler.py +1609 -0
- omnimancer/cli/interface.py +6695 -0
- omnimancer/cli/performance_dashboard.py +612 -0
- omnimancer/core/__init__.py +34 -0
- omnimancer/core/agent/__init__.py +256 -0
- omnimancer/core/agent/agent_config.py +715 -0
- omnimancer/core/agent/agent_switcher.py +668 -0
- omnimancer/core/agent/approval_context.py +460 -0
- omnimancer/core/agent/approval_dialog.py +902 -0
- omnimancer/core/agent/approval_interface.py +628 -0
- omnimancer/core/agent/approval_manager.py +760 -0
- omnimancer/core/agent/cli_integration.py +470 -0
- omnimancer/core/agent/config.py +845 -0
- omnimancer/core/agent/custom_agent_integration.py +654 -0
- omnimancer/core/agent/diff_renderer.py +706 -0
- omnimancer/core/agent/file_content_display.py +503 -0
- omnimancer/core/agent/file_modification_workflow.py +658 -0
- omnimancer/core/agent/file_system_manager.py +1790 -0
- omnimancer/core/agent/input_handler.py +614 -0
- omnimancer/core/agent/metrics_collector.py +771 -0
- omnimancer/core/agent/optimization_engine.py +729 -0
- omnimancer/core/agent/performance_monitor.py +717 -0
- omnimancer/core/agent/persona.py +870 -0
- omnimancer/core/agent/persona_validator.py +672 -0
- omnimancer/core/agent/program_executor.py +748 -0
- omnimancer/core/agent/proposed_changes_integration.py +663 -0
- omnimancer/core/agent/read_before_write_errors.py +492 -0
- omnimancer/core/agent/read_before_write_ui.py +647 -0
- omnimancer/core/agent/rich_renderer.py +763 -0
- omnimancer/core/agent/status_config.py +238 -0
- omnimancer/core/agent/status_core.py +446 -0
- omnimancer/core/agent/status_integrated_engine.py +540 -0
- omnimancer/core/agent/status_manager.py +878 -0
- omnimancer/core/agent/status_ui_components.py +535 -0
- omnimancer/core/agent/template_applicator.py +548 -0
- omnimancer/core/agent/terminal_status_listener.py +394 -0
- omnimancer/core/agent/token_tracker.py +679 -0
- omnimancer/core/agent/types.py +60 -0
- omnimancer/core/agent/web_client.py +745 -0
- omnimancer/core/agent/workflow_orchestrator.py +826 -0
- omnimancer/core/agent_engine.py +1625 -0
- omnimancer/core/agent_mode_manager.py +706 -0
- omnimancer/core/agent_progress_ui.py +545 -0
- omnimancer/core/chat_manager.py +141 -0
- omnimancer/core/config_manager.py +2199 -0
- omnimancer/core/config_migration.py +772 -0
- omnimancer/core/config_provider.py +1974 -0
- omnimancer/core/config_security_validator.py +393 -0
- omnimancer/core/config_validator.py +768 -0
- omnimancer/core/conversation_manager.py +352 -0
- omnimancer/core/engine.py +787 -0
- omnimancer/core/enhanced_input.py +523 -0
- omnimancer/core/env_loader.py +83 -0
- omnimancer/core/fallback_manager.py +568 -0
- omnimancer/core/health_monitor.py +462 -0
- omnimancer/core/history_manager.py +462 -0
- omnimancer/core/mcp_integration_layer.py +878 -0
- omnimancer/core/models.py +1889 -0
- omnimancer/core/provider_capabilities.py +403 -0
- omnimancer/core/provider_initializer.py +450 -0
- omnimancer/core/provider_registry.py +432 -0
- omnimancer/core/security/__init__.py +16 -0
- omnimancer/core/security/approval_workflow.py +406 -0
- omnimancer/core/security/audit_logger.py +511 -0
- omnimancer/core/security/permission_controller.py +511 -0
- omnimancer/core/security/sandbox_manager.py +379 -0
- omnimancer/core/security/security_manager.py +530 -0
- omnimancer/core/setup_wizard.py +345 -0
- omnimancer/core/setup_wizard_core.py +449 -0
- omnimancer/core/setup_wizard_guide_generator.py +376 -0
- omnimancer/core/setup_wizard_provider_setup.py +454 -0
- omnimancer/core/setup_wizard_ui.py +317 -0
- omnimancer/core/setup_wizard_validation.py +371 -0
- omnimancer/core/signal_handler.py +174 -0
- omnimancer/mcp/__init__.py +11 -0
- omnimancer/mcp/client.py +725 -0
- omnimancer/mcp/manager.py +649 -0
- omnimancer/providers/__init__.py +24 -0
- omnimancer/providers/azure.py +608 -0
- omnimancer/providers/base.py +262 -0
- omnimancer/providers/bedrock.py +711 -0
- omnimancer/providers/claude.py +426 -0
- omnimancer/providers/claude_code.py +406 -0
- omnimancer/providers/cohere.py +412 -0
- omnimancer/providers/factory.py +988 -0
- omnimancer/providers/gemini.py +708 -0
- omnimancer/providers/mistral.py +554 -0
- omnimancer/providers/ollama.py +510 -0
- omnimancer/providers/openai.py +362 -0
- omnimancer/providers/openrouter.py +709 -0
- omnimancer/providers/perplexity.py +476 -0
- omnimancer/providers/vertex.py +617 -0
- omnimancer/providers/xai.py +484 -0
- omnimancer/ui/__init__.py +6 -0
- omnimancer/ui/cancellation_handler.py +235 -0
- omnimancer/ui/progress_indicator.py +318 -0
- omnimancer/utils/__init__.py +22 -0
- omnimancer/utils/error_handler.py +589 -0
- omnimancer/utils/errors.py +667 -0
- omnimancer/utils/retry.py +238 -0
- omnimancer_cli-0.1.0.dist-info/METADATA +413 -0
- omnimancer_cli-0.1.0.dist-info/RECORD +126 -0
- omnimancer_cli-0.1.0.dist-info/WHEEL +5 -0
- omnimancer_cli-0.1.0.dist-info/entry_points.txt +4 -0
- omnimancer_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
- omnimancer_cli-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Mistral AI provider implementation for Omnimancer.
|
|
3
|
+
|
|
4
|
+
This module provides the Mistral AI provider implementation using Mistral's API
|
|
5
|
+
with support for safety settings and advanced parameters.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from typing import Dict, List
|
|
10
|
+
|
|
11
|
+
import httpx
|
|
12
|
+
|
|
13
|
+
from ..core.models import (
|
|
14
|
+
ChatContext,
|
|
15
|
+
ChatResponse,
|
|
16
|
+
EnhancedModelInfo,
|
|
17
|
+
ToolCall,
|
|
18
|
+
ToolDefinition,
|
|
19
|
+
)
|
|
20
|
+
from ..utils.errors import (
|
|
21
|
+
AuthenticationError,
|
|
22
|
+
ModelNotFoundError,
|
|
23
|
+
NetworkError,
|
|
24
|
+
ProviderError,
|
|
25
|
+
RateLimitError,
|
|
26
|
+
)
|
|
27
|
+
from .base import BaseProvider
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class MistralProvider(BaseProvider):
|
|
31
|
+
"""
|
|
32
|
+
Mistral AI provider implementation using Mistral's API.
|
|
33
|
+
|
|
34
|
+
Supports Mistral models with safety settings, function calling,
|
|
35
|
+
and advanced conversation parameters.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
BASE_URL = "https://api.mistral.ai/v1"
|
|
39
|
+
|
|
40
|
+
def __init__(self, api_key: str, model: str = "", **kwargs):
|
|
41
|
+
"""
|
|
42
|
+
Initialize Mistral provider.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
api_key: Mistral API key
|
|
46
|
+
model: Mistral model to use (e.g., 'mistral-large-latest', 'mistral-small-latest', 'open-mistral-7b')
|
|
47
|
+
**kwargs: Additional configuration including Mistral-specific settings
|
|
48
|
+
"""
|
|
49
|
+
super().__init__(api_key, model or "mistral-large-latest", **kwargs)
|
|
50
|
+
self.max_tokens = kwargs.get("max_tokens", 4096)
|
|
51
|
+
self.temperature = kwargs.get("temperature", 0.7)
|
|
52
|
+
self.top_p = kwargs.get("top_p", 1.0)
|
|
53
|
+
self.safe_prompt = kwargs.get("safe_prompt", False)
|
|
54
|
+
self.random_seed = kwargs.get("random_seed", None)
|
|
55
|
+
self.response_format = kwargs.get("response_format", None) # For JSON mode
|
|
56
|
+
|
|
57
|
+
async def send_message(self, message: str, context: ChatContext) -> ChatResponse:
|
|
58
|
+
"""
|
|
59
|
+
Send a message to Mistral API.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
message: User message
|
|
63
|
+
context: Conversation context
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
ChatResponse with Mistral's reply
|
|
67
|
+
"""
|
|
68
|
+
try:
|
|
69
|
+
# Prepare messages for Mistral API
|
|
70
|
+
messages = self._prepare_messages(message, context)
|
|
71
|
+
|
|
72
|
+
# Build request payload
|
|
73
|
+
payload = {
|
|
74
|
+
"model": self.model,
|
|
75
|
+
"messages": messages,
|
|
76
|
+
"max_tokens": self.max_tokens,
|
|
77
|
+
"temperature": self.temperature,
|
|
78
|
+
"top_p": self.top_p,
|
|
79
|
+
"safe_prompt": self.safe_prompt,
|
|
80
|
+
"stream": False,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Add optional parameters
|
|
84
|
+
if self.random_seed is not None:
|
|
85
|
+
payload["random_seed"] = self.random_seed
|
|
86
|
+
|
|
87
|
+
if self.response_format:
|
|
88
|
+
payload["response_format"] = self.response_format
|
|
89
|
+
|
|
90
|
+
# Make API request
|
|
91
|
+
async with httpx.AsyncClient() as client:
|
|
92
|
+
response = await client.post(
|
|
93
|
+
f"{self.BASE_URL}/chat/completions",
|
|
94
|
+
headers={
|
|
95
|
+
"Content-Type": "application/json",
|
|
96
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
97
|
+
},
|
|
98
|
+
json=payload,
|
|
99
|
+
timeout=30.0,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Handle response
|
|
103
|
+
return self._handle_response(response)
|
|
104
|
+
|
|
105
|
+
except httpx.TimeoutException:
|
|
106
|
+
raise NetworkError("Request to Mistral API timed out")
|
|
107
|
+
except httpx.RequestError as e:
|
|
108
|
+
raise NetworkError(f"Network error: {e}")
|
|
109
|
+
except (
|
|
110
|
+
AuthenticationError,
|
|
111
|
+
RateLimitError,
|
|
112
|
+
ModelNotFoundError,
|
|
113
|
+
ProviderError,
|
|
114
|
+
):
|
|
115
|
+
# Re-raise provider-specific errors without wrapping
|
|
116
|
+
raise
|
|
117
|
+
except Exception as e:
|
|
118
|
+
raise ProviderError(f"Unexpected error: {e}")
|
|
119
|
+
|
|
120
|
+
async def send_message_with_tools(
|
|
121
|
+
self,
|
|
122
|
+
message: str,
|
|
123
|
+
context: ChatContext,
|
|
124
|
+
available_tools: List[ToolDefinition],
|
|
125
|
+
) -> ChatResponse:
|
|
126
|
+
"""
|
|
127
|
+
Send a message with available tools for Mistral to use.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
message: User message
|
|
131
|
+
context: Conversation context
|
|
132
|
+
available_tools: List of tools available for Mistral to use
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
ChatResponse with Mistral's reply and any tool calls
|
|
136
|
+
"""
|
|
137
|
+
try:
|
|
138
|
+
# Prepare messages for Mistral API
|
|
139
|
+
messages = self._prepare_messages(message, context)
|
|
140
|
+
|
|
141
|
+
# Convert tools to Mistral format
|
|
142
|
+
tools = self._convert_tools_to_mistral_format(available_tools)
|
|
143
|
+
|
|
144
|
+
# Build request payload
|
|
145
|
+
payload = {
|
|
146
|
+
"model": self.model,
|
|
147
|
+
"messages": messages,
|
|
148
|
+
"max_tokens": self.max_tokens,
|
|
149
|
+
"temperature": self.temperature,
|
|
150
|
+
"top_p": self.top_p,
|
|
151
|
+
"safe_prompt": self.safe_prompt,
|
|
152
|
+
"tools": tools,
|
|
153
|
+
"tool_choice": "auto",
|
|
154
|
+
"stream": False,
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
# Add optional parameters
|
|
158
|
+
if self.random_seed is not None:
|
|
159
|
+
payload["random_seed"] = self.random_seed
|
|
160
|
+
|
|
161
|
+
# Make API request
|
|
162
|
+
async with httpx.AsyncClient() as client:
|
|
163
|
+
response = await client.post(
|
|
164
|
+
f"{self.BASE_URL}/chat/completions",
|
|
165
|
+
headers={
|
|
166
|
+
"Content-Type": "application/json",
|
|
167
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
168
|
+
},
|
|
169
|
+
json=payload,
|
|
170
|
+
timeout=30.0,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# Handle response with tool calls
|
|
174
|
+
return self._handle_response_with_tools(response)
|
|
175
|
+
|
|
176
|
+
except httpx.TimeoutException:
|
|
177
|
+
raise NetworkError("Request to Mistral API timed out")
|
|
178
|
+
except httpx.RequestError as e:
|
|
179
|
+
raise NetworkError(f"Network error: {e}")
|
|
180
|
+
except Exception as e:
|
|
181
|
+
raise ProviderError(f"Unexpected error: {e}")
|
|
182
|
+
|
|
183
|
+
async def validate_credentials(self) -> bool:
|
|
184
|
+
"""
|
|
185
|
+
Validate Mistral API credentials by making a test request.
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
True if credentials are valid
|
|
189
|
+
"""
|
|
190
|
+
try:
|
|
191
|
+
async with httpx.AsyncClient() as client:
|
|
192
|
+
response = await client.post(
|
|
193
|
+
f"{self.BASE_URL}/chat/completions",
|
|
194
|
+
headers={
|
|
195
|
+
"Content-Type": "application/json",
|
|
196
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
197
|
+
},
|
|
198
|
+
json={
|
|
199
|
+
"model": self.model,
|
|
200
|
+
"messages": [{"role": "user", "content": "Hi"}],
|
|
201
|
+
"max_tokens": 10,
|
|
202
|
+
},
|
|
203
|
+
timeout=10.0,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
return response.status_code == 200
|
|
207
|
+
|
|
208
|
+
except Exception:
|
|
209
|
+
return False
|
|
210
|
+
|
|
211
|
+
def _prepare_messages(
|
|
212
|
+
self, message: str, context: ChatContext
|
|
213
|
+
) -> List[Dict[str, str]]:
|
|
214
|
+
"""
|
|
215
|
+
Prepare messages for Mistral API format.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
message: Current user message
|
|
219
|
+
context: Conversation context
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
List of messages formatted for Mistral API
|
|
223
|
+
"""
|
|
224
|
+
messages = []
|
|
225
|
+
|
|
226
|
+
# Add context messages
|
|
227
|
+
for msg in context.messages:
|
|
228
|
+
messages.append({"role": msg.role.value, "content": msg.content})
|
|
229
|
+
|
|
230
|
+
# Add current message
|
|
231
|
+
messages.append({"role": "user", "content": message})
|
|
232
|
+
|
|
233
|
+
return messages
|
|
234
|
+
|
|
235
|
+
def _convert_tools_to_mistral_format(
|
|
236
|
+
self, tools: List[ToolDefinition]
|
|
237
|
+
) -> List[Dict]:
|
|
238
|
+
"""
|
|
239
|
+
Convert tool definitions to Mistral API format.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
tools: List of tool definitions
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
List of tools formatted for Mistral API
|
|
246
|
+
"""
|
|
247
|
+
mistral_tools = []
|
|
248
|
+
|
|
249
|
+
for tool in tools:
|
|
250
|
+
mistral_tool = {
|
|
251
|
+
"type": "function",
|
|
252
|
+
"function": {
|
|
253
|
+
"name": tool.name,
|
|
254
|
+
"description": tool.description,
|
|
255
|
+
"parameters": tool.parameters,
|
|
256
|
+
},
|
|
257
|
+
}
|
|
258
|
+
mistral_tools.append(mistral_tool)
|
|
259
|
+
|
|
260
|
+
return mistral_tools
|
|
261
|
+
|
|
262
|
+
def _handle_response(self, response: httpx.Response) -> ChatResponse:
|
|
263
|
+
"""
|
|
264
|
+
Handle Mistral API response.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
response: HTTP response from Mistral API
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
ChatResponse object
|
|
271
|
+
|
|
272
|
+
Raises:
|
|
273
|
+
Various provider errors based on response status
|
|
274
|
+
"""
|
|
275
|
+
if response.status_code == 200:
|
|
276
|
+
data = response.json()
|
|
277
|
+
choices = data.get("choices", [])
|
|
278
|
+
|
|
279
|
+
if choices and len(choices) > 0:
|
|
280
|
+
message = choices[0].get("message", {})
|
|
281
|
+
content = message.get("content", "")
|
|
282
|
+
usage = data.get("usage", {})
|
|
283
|
+
|
|
284
|
+
return ChatResponse(
|
|
285
|
+
content=content,
|
|
286
|
+
model_used=self.model,
|
|
287
|
+
tokens_used=usage.get("total_tokens", 0),
|
|
288
|
+
timestamp=datetime.now(),
|
|
289
|
+
)
|
|
290
|
+
else:
|
|
291
|
+
raise ProviderError("Empty response from Mistral API")
|
|
292
|
+
|
|
293
|
+
elif response.status_code == 401:
|
|
294
|
+
raise AuthenticationError("Invalid Mistral API key")
|
|
295
|
+
elif response.status_code == 429:
|
|
296
|
+
raise RateLimitError("Mistral API rate limit exceeded")
|
|
297
|
+
elif response.status_code == 404:
|
|
298
|
+
raise ModelNotFoundError(f"Mistral model '{self.model}' not found")
|
|
299
|
+
else:
|
|
300
|
+
try:
|
|
301
|
+
error_data = response.json()
|
|
302
|
+
error_msg = error_data.get("error", {}).get("message", "Unknown error")
|
|
303
|
+
except:
|
|
304
|
+
error_msg = f"HTTP {response.status_code}"
|
|
305
|
+
|
|
306
|
+
raise ProviderError(f"Mistral API error: {error_msg}")
|
|
307
|
+
|
|
308
|
+
def _handle_response_with_tools(self, response: httpx.Response) -> ChatResponse:
|
|
309
|
+
"""
|
|
310
|
+
Handle Mistral API response with tool calls.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
response: HTTP response from Mistral API
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
ChatResponse object with tool calls
|
|
317
|
+
"""
|
|
318
|
+
if response.status_code == 200:
|
|
319
|
+
data = response.json()
|
|
320
|
+
choices = data.get("choices", [])
|
|
321
|
+
|
|
322
|
+
if choices and len(choices) > 0:
|
|
323
|
+
message = choices[0].get("message", {})
|
|
324
|
+
content = message.get("content", "")
|
|
325
|
+
usage = data.get("usage", {})
|
|
326
|
+
|
|
327
|
+
# Extract tool calls if present
|
|
328
|
+
tool_calls = []
|
|
329
|
+
if "tool_calls" in message:
|
|
330
|
+
for tool_call in message["tool_calls"]:
|
|
331
|
+
if tool_call.get("type") == "function":
|
|
332
|
+
function = tool_call.get("function", {})
|
|
333
|
+
tool_calls.append(
|
|
334
|
+
ToolCall(
|
|
335
|
+
name=function.get("name", ""),
|
|
336
|
+
arguments=function.get("arguments", {}),
|
|
337
|
+
)
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
return ChatResponse(
|
|
341
|
+
content=content,
|
|
342
|
+
model_used=self.model,
|
|
343
|
+
tokens_used=usage.get("total_tokens", 0),
|
|
344
|
+
tool_calls=tool_calls if tool_calls else None,
|
|
345
|
+
timestamp=datetime.now(),
|
|
346
|
+
)
|
|
347
|
+
else:
|
|
348
|
+
raise ProviderError("Empty response from Mistral API")
|
|
349
|
+
else:
|
|
350
|
+
return self._handle_response(response)
|
|
351
|
+
|
|
352
|
+
def get_model_info(self) -> EnhancedModelInfo:
|
|
353
|
+
"""
|
|
354
|
+
Get information about the current Mistral model.
|
|
355
|
+
"""
|
|
356
|
+
model_configs = {
|
|
357
|
+
"mistral-large-latest": {
|
|
358
|
+
"description": "Mistral Large - Most capable model for complex tasks",
|
|
359
|
+
"max_tokens": 128000,
|
|
360
|
+
"cost_per_million_input": 2.0,
|
|
361
|
+
"cost_per_million_output": 6.0,
|
|
362
|
+
"swe_score": 64.6,
|
|
363
|
+
"supports_tools": True,
|
|
364
|
+
"supports_multimodal": False,
|
|
365
|
+
},
|
|
366
|
+
"mistral-medium-latest": {
|
|
367
|
+
"description": "Mistral Medium - Balanced performance and efficiency",
|
|
368
|
+
"max_tokens": 32000,
|
|
369
|
+
"cost_per_million_input": 2.7,
|
|
370
|
+
"cost_per_million_output": 8.1,
|
|
371
|
+
"swe_score": 55.8,
|
|
372
|
+
"supports_tools": True,
|
|
373
|
+
"supports_multimodal": False,
|
|
374
|
+
},
|
|
375
|
+
"mistral-small-latest": {
|
|
376
|
+
"description": "Mistral Small - Fast and cost-effective",
|
|
377
|
+
"max_tokens": 32000,
|
|
378
|
+
"cost_per_million_input": 0.2,
|
|
379
|
+
"cost_per_million_output": 0.6,
|
|
380
|
+
"swe_score": 48.2,
|
|
381
|
+
"supports_tools": True,
|
|
382
|
+
"supports_multimodal": False,
|
|
383
|
+
},
|
|
384
|
+
"mistral-tiny": {
|
|
385
|
+
"description": "Mistral Tiny - Ultra-fast for simple tasks",
|
|
386
|
+
"max_tokens": 32000,
|
|
387
|
+
"cost_per_million_input": 0.14,
|
|
388
|
+
"cost_per_million_output": 0.42,
|
|
389
|
+
"swe_score": 35.1,
|
|
390
|
+
"supports_tools": False,
|
|
391
|
+
"supports_multimodal": False,
|
|
392
|
+
},
|
|
393
|
+
"codestral-latest": {
|
|
394
|
+
"description": "Codestral - Specialized for code generation and analysis",
|
|
395
|
+
"max_tokens": 32000,
|
|
396
|
+
"cost_per_million_input": 0.2,
|
|
397
|
+
"cost_per_million_output": 0.6,
|
|
398
|
+
"swe_score": 78.2,
|
|
399
|
+
"supports_tools": True,
|
|
400
|
+
"supports_multimodal": False,
|
|
401
|
+
},
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
config = model_configs.get(
|
|
405
|
+
self.model,
|
|
406
|
+
{
|
|
407
|
+
"description": f"Mistral model {self.model}",
|
|
408
|
+
"max_tokens": 32000,
|
|
409
|
+
"cost_per_million_input": 2.0,
|
|
410
|
+
"cost_per_million_output": 6.0,
|
|
411
|
+
"swe_score": 50.0,
|
|
412
|
+
"supports_tools": True,
|
|
413
|
+
"supports_multimodal": False,
|
|
414
|
+
},
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
enhanced_info = EnhancedModelInfo(
|
|
418
|
+
name=self.model,
|
|
419
|
+
provider="mistral",
|
|
420
|
+
description=config["description"],
|
|
421
|
+
max_tokens=config["max_tokens"],
|
|
422
|
+
cost_per_million_input=config["cost_per_million_input"],
|
|
423
|
+
cost_per_million_output=config["cost_per_million_output"],
|
|
424
|
+
swe_score=config["swe_score"],
|
|
425
|
+
available=True,
|
|
426
|
+
supports_tools=config["supports_tools"],
|
|
427
|
+
supports_multimodal=config["supports_multimodal"],
|
|
428
|
+
latest_version=self.model == "mistral-large-latest",
|
|
429
|
+
context_window=config["max_tokens"],
|
|
430
|
+
is_free=False,
|
|
431
|
+
release_date=datetime(2024, 9, 1), # Approximate release date
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
# Update SWE rating based on score
|
|
435
|
+
enhanced_info.update_swe_rating()
|
|
436
|
+
|
|
437
|
+
return enhanced_info
|
|
438
|
+
|
|
439
|
+
def get_available_models(self) -> List[EnhancedModelInfo]:
|
|
440
|
+
"""
|
|
441
|
+
Get list of available Mistral models.
|
|
442
|
+
"""
|
|
443
|
+
models = [
|
|
444
|
+
EnhancedModelInfo(
|
|
445
|
+
name="mistral-large-latest",
|
|
446
|
+
provider="mistral",
|
|
447
|
+
description="Mistral Large - Most capable model for complex tasks",
|
|
448
|
+
max_tokens=128000,
|
|
449
|
+
cost_per_million_input=2.0,
|
|
450
|
+
cost_per_million_output=6.0,
|
|
451
|
+
swe_score=64.6,
|
|
452
|
+
available=True,
|
|
453
|
+
supports_tools=True,
|
|
454
|
+
supports_multimodal=False,
|
|
455
|
+
latest_version=True,
|
|
456
|
+
context_window=128000,
|
|
457
|
+
is_free=False,
|
|
458
|
+
release_date=datetime(2024, 9, 1),
|
|
459
|
+
),
|
|
460
|
+
EnhancedModelInfo(
|
|
461
|
+
name="mistral-medium-latest",
|
|
462
|
+
provider="mistral",
|
|
463
|
+
description="Mistral Medium - Balanced performance and efficiency",
|
|
464
|
+
max_tokens=32000,
|
|
465
|
+
cost_per_million_input=2.7,
|
|
466
|
+
cost_per_million_output=8.1,
|
|
467
|
+
swe_score=55.8,
|
|
468
|
+
available=True,
|
|
469
|
+
supports_tools=True,
|
|
470
|
+
supports_multimodal=False,
|
|
471
|
+
context_window=32000,
|
|
472
|
+
is_free=False,
|
|
473
|
+
release_date=datetime(2024, 9, 1),
|
|
474
|
+
),
|
|
475
|
+
EnhancedModelInfo(
|
|
476
|
+
name="mistral-small-latest",
|
|
477
|
+
provider="mistral",
|
|
478
|
+
description="Mistral Small - Fast and cost-effective",
|
|
479
|
+
max_tokens=32000,
|
|
480
|
+
cost_per_million_input=0.2,
|
|
481
|
+
cost_per_million_output=0.6,
|
|
482
|
+
swe_score=48.2,
|
|
483
|
+
available=True,
|
|
484
|
+
supports_tools=True,
|
|
485
|
+
supports_multimodal=False,
|
|
486
|
+
context_window=32000,
|
|
487
|
+
is_free=False,
|
|
488
|
+
release_date=datetime(2024, 9, 1),
|
|
489
|
+
),
|
|
490
|
+
EnhancedModelInfo(
|
|
491
|
+
name="mistral-tiny",
|
|
492
|
+
provider="mistral",
|
|
493
|
+
description="Mistral Tiny - Ultra-fast for simple tasks",
|
|
494
|
+
max_tokens=32000,
|
|
495
|
+
cost_per_million_input=0.14,
|
|
496
|
+
cost_per_million_output=0.42,
|
|
497
|
+
swe_score=35.1,
|
|
498
|
+
available=True,
|
|
499
|
+
supports_tools=False,
|
|
500
|
+
supports_multimodal=False,
|
|
501
|
+
context_window=32000,
|
|
502
|
+
is_free=False,
|
|
503
|
+
release_date=datetime(2024, 9, 1),
|
|
504
|
+
),
|
|
505
|
+
EnhancedModelInfo(
|
|
506
|
+
name="codestral-latest",
|
|
507
|
+
provider="mistral",
|
|
508
|
+
description="Codestral - Specialized for code generation and analysis",
|
|
509
|
+
max_tokens=32000,
|
|
510
|
+
cost_per_million_input=0.2,
|
|
511
|
+
cost_per_million_output=0.6,
|
|
512
|
+
swe_score=78.2,
|
|
513
|
+
available=True,
|
|
514
|
+
supports_tools=True,
|
|
515
|
+
supports_multimodal=False,
|
|
516
|
+
context_window=32000,
|
|
517
|
+
is_free=False,
|
|
518
|
+
release_date=datetime(2024, 9, 1),
|
|
519
|
+
),
|
|
520
|
+
]
|
|
521
|
+
|
|
522
|
+
# Update SWE ratings for all models
|
|
523
|
+
for model in models:
|
|
524
|
+
model.update_swe_rating()
|
|
525
|
+
|
|
526
|
+
return models
|
|
527
|
+
|
|
528
|
+
def supports_tools(self) -> bool:
|
|
529
|
+
"""
|
|
530
|
+
Check if Mistral provider supports tool calling.
|
|
531
|
+
|
|
532
|
+
Returns:
|
|
533
|
+
True for most models except tiny variants
|
|
534
|
+
"""
|
|
535
|
+
non_tool_models = ["mistral-tiny"]
|
|
536
|
+
return self.model not in non_tool_models
|
|
537
|
+
|
|
538
|
+
def supports_multimodal(self) -> bool:
|
|
539
|
+
"""
|
|
540
|
+
Check if Mistral provider supports multimodal inputs.
|
|
541
|
+
|
|
542
|
+
Returns:
|
|
543
|
+
False - Current Mistral models don't support multimodal inputs
|
|
544
|
+
"""
|
|
545
|
+
return False
|
|
546
|
+
|
|
547
|
+
def supports_streaming(self) -> bool:
|
|
548
|
+
"""
|
|
549
|
+
Check if Mistral provider supports streaming responses.
|
|
550
|
+
|
|
551
|
+
Returns:
|
|
552
|
+
True - Mistral supports streaming
|
|
553
|
+
"""
|
|
554
|
+
return True
|