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,484 @@
|
|
|
1
|
+
"""
|
|
2
|
+
xAI (Grok) provider implementation for Omnimancer.
|
|
3
|
+
|
|
4
|
+
This module provides the xAI provider implementation using xAI's API
|
|
5
|
+
with support for Grok models, multimodal capabilities, and tool calling.
|
|
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 XAIProvider(BaseProvider):
|
|
31
|
+
"""
|
|
32
|
+
xAI (Grok) provider implementation using xAI's API.
|
|
33
|
+
|
|
34
|
+
Supports Grok models with advanced reasoning, multimodal capabilities,
|
|
35
|
+
and tool calling functionality.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
BASE_URL = "https://api.x.ai/v1"
|
|
39
|
+
|
|
40
|
+
def __init__(self, api_key: str, model: str = "", **kwargs):
|
|
41
|
+
"""
|
|
42
|
+
Initialize xAI provider.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
api_key: xAI API key
|
|
46
|
+
model: xAI model to use (e.g., 'grok-beta', 'grok-vision-beta')
|
|
47
|
+
**kwargs: Additional configuration including Grok-specific settings
|
|
48
|
+
"""
|
|
49
|
+
super().__init__(api_key, model or "grok-beta", **kwargs)
|
|
50
|
+
self.max_tokens = kwargs.get("max_tokens", 4096)
|
|
51
|
+
self.temperature = kwargs.get("temperature", 0.7)
|
|
52
|
+
self.grok_mode = kwargs.get(
|
|
53
|
+
"grok_mode", "balanced"
|
|
54
|
+
) # balanced, creative, precise
|
|
55
|
+
self.system_prompt = kwargs.get("system_prompt", None)
|
|
56
|
+
self.enable_web_search = kwargs.get("enable_web_search", True)
|
|
57
|
+
self.enable_real_time = kwargs.get("enable_real_time", True)
|
|
58
|
+
|
|
59
|
+
async def send_message(self, message: str, context: ChatContext) -> ChatResponse:
|
|
60
|
+
"""
|
|
61
|
+
Send a message to xAI API.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
message: User message
|
|
65
|
+
context: Conversation context
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
ChatResponse with Grok's reply
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
# Prepare messages for xAI API
|
|
72
|
+
messages = self._prepare_messages(message, context)
|
|
73
|
+
|
|
74
|
+
# Build request payload
|
|
75
|
+
payload = {
|
|
76
|
+
"model": self.model,
|
|
77
|
+
"messages": messages,
|
|
78
|
+
"max_tokens": self.max_tokens,
|
|
79
|
+
"temperature": self._get_temperature_for_mode(),
|
|
80
|
+
"stream": False,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Add Grok-specific parameters
|
|
84
|
+
if self.enable_web_search:
|
|
85
|
+
payload["tools"] = [{"type": "web_search"}]
|
|
86
|
+
|
|
87
|
+
# Make API request
|
|
88
|
+
async with httpx.AsyncClient() as client:
|
|
89
|
+
response = await client.post(
|
|
90
|
+
f"{self.BASE_URL}/chat/completions",
|
|
91
|
+
headers={
|
|
92
|
+
"Content-Type": "application/json",
|
|
93
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
94
|
+
},
|
|
95
|
+
json=payload,
|
|
96
|
+
timeout=60.0, # Longer timeout for complex reasoning
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Handle response
|
|
100
|
+
return self._handle_response(response)
|
|
101
|
+
|
|
102
|
+
except httpx.TimeoutException:
|
|
103
|
+
raise NetworkError("Request to xAI API timed out")
|
|
104
|
+
except httpx.RequestError as e:
|
|
105
|
+
raise NetworkError(f"Network error: {e}")
|
|
106
|
+
except (
|
|
107
|
+
AuthenticationError,
|
|
108
|
+
RateLimitError,
|
|
109
|
+
ModelNotFoundError,
|
|
110
|
+
ProviderError,
|
|
111
|
+
):
|
|
112
|
+
# Re-raise provider-specific errors without wrapping
|
|
113
|
+
raise
|
|
114
|
+
except Exception as e:
|
|
115
|
+
raise ProviderError(f"Unexpected error: {e}")
|
|
116
|
+
|
|
117
|
+
async def send_message_with_tools(
|
|
118
|
+
self,
|
|
119
|
+
message: str,
|
|
120
|
+
context: ChatContext,
|
|
121
|
+
available_tools: List[ToolDefinition],
|
|
122
|
+
) -> ChatResponse:
|
|
123
|
+
"""
|
|
124
|
+
Send a message with available tools for Grok to use.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
message: User message
|
|
128
|
+
context: Conversation context
|
|
129
|
+
available_tools: List of tools available for Grok to use
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
ChatResponse with Grok's reply and any tool calls
|
|
133
|
+
"""
|
|
134
|
+
try:
|
|
135
|
+
# Prepare messages for xAI API
|
|
136
|
+
messages = self._prepare_messages(message, context)
|
|
137
|
+
|
|
138
|
+
# Convert tools to xAI format
|
|
139
|
+
tools = self._convert_tools_to_xai_format(available_tools)
|
|
140
|
+
|
|
141
|
+
# Build request payload
|
|
142
|
+
payload = {
|
|
143
|
+
"model": self.model,
|
|
144
|
+
"messages": messages,
|
|
145
|
+
"max_tokens": self.max_tokens,
|
|
146
|
+
"temperature": self._get_temperature_for_mode(),
|
|
147
|
+
"tools": tools,
|
|
148
|
+
"tool_choice": "auto",
|
|
149
|
+
"stream": False,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# Make API request
|
|
153
|
+
async with httpx.AsyncClient() as client:
|
|
154
|
+
response = await client.post(
|
|
155
|
+
f"{self.BASE_URL}/chat/completions",
|
|
156
|
+
headers={
|
|
157
|
+
"Content-Type": "application/json",
|
|
158
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
159
|
+
},
|
|
160
|
+
json=payload,
|
|
161
|
+
timeout=60.0,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Handle response with tool calls
|
|
165
|
+
return self._handle_response_with_tools(response)
|
|
166
|
+
|
|
167
|
+
except httpx.TimeoutException:
|
|
168
|
+
raise NetworkError("Request to xAI API timed out")
|
|
169
|
+
except httpx.RequestError as e:
|
|
170
|
+
raise NetworkError(f"Network error: {e}")
|
|
171
|
+
except Exception as e:
|
|
172
|
+
raise ProviderError(f"Unexpected error: {e}")
|
|
173
|
+
|
|
174
|
+
async def validate_credentials(self) -> bool:
|
|
175
|
+
"""
|
|
176
|
+
Validate xAI API credentials by making a test request.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
True if credentials are valid
|
|
180
|
+
"""
|
|
181
|
+
try:
|
|
182
|
+
async with httpx.AsyncClient() as client:
|
|
183
|
+
response = await client.post(
|
|
184
|
+
f"{self.BASE_URL}/chat/completions",
|
|
185
|
+
headers={
|
|
186
|
+
"Content-Type": "application/json",
|
|
187
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
188
|
+
},
|
|
189
|
+
json={
|
|
190
|
+
"model": self.model,
|
|
191
|
+
"messages": [{"role": "user", "content": "Hi"}],
|
|
192
|
+
"max_tokens": 10,
|
|
193
|
+
},
|
|
194
|
+
timeout=10.0,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return response.status_code == 200
|
|
198
|
+
|
|
199
|
+
except Exception:
|
|
200
|
+
return False
|
|
201
|
+
|
|
202
|
+
def _prepare_messages(
|
|
203
|
+
self, message: str, context: ChatContext
|
|
204
|
+
) -> List[Dict[str, str]]:
|
|
205
|
+
"""
|
|
206
|
+
Prepare messages for xAI API format.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
message: Current user message
|
|
210
|
+
context: Conversation context
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
List of messages formatted for xAI API
|
|
214
|
+
"""
|
|
215
|
+
messages = []
|
|
216
|
+
|
|
217
|
+
# Add system prompt if specified
|
|
218
|
+
if self.system_prompt:
|
|
219
|
+
messages.append({"role": "system", "content": self.system_prompt})
|
|
220
|
+
|
|
221
|
+
# Add context messages
|
|
222
|
+
for msg in context.messages:
|
|
223
|
+
messages.append({"role": msg.role.value, "content": msg.content})
|
|
224
|
+
|
|
225
|
+
# Add current message
|
|
226
|
+
messages.append({"role": "user", "content": message})
|
|
227
|
+
|
|
228
|
+
return messages
|
|
229
|
+
|
|
230
|
+
def _get_temperature_for_mode(self) -> float:
|
|
231
|
+
"""
|
|
232
|
+
Get temperature setting based on Grok mode.
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
Temperature value for the current mode
|
|
236
|
+
"""
|
|
237
|
+
mode_temperatures = {"precise": 0.1, "balanced": 0.7, "creative": 1.0}
|
|
238
|
+
return mode_temperatures.get(self.grok_mode, self.temperature)
|
|
239
|
+
|
|
240
|
+
def _convert_tools_to_xai_format(self, tools: List[ToolDefinition]) -> List[Dict]:
|
|
241
|
+
"""
|
|
242
|
+
Convert tool definitions to xAI API format.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
tools: List of tool definitions
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
List of tools formatted for xAI API
|
|
249
|
+
"""
|
|
250
|
+
xai_tools = []
|
|
251
|
+
|
|
252
|
+
for tool in tools:
|
|
253
|
+
xai_tool = {
|
|
254
|
+
"type": "function",
|
|
255
|
+
"function": {
|
|
256
|
+
"name": tool.name,
|
|
257
|
+
"description": tool.description,
|
|
258
|
+
"parameters": tool.parameters,
|
|
259
|
+
},
|
|
260
|
+
}
|
|
261
|
+
xai_tools.append(xai_tool)
|
|
262
|
+
|
|
263
|
+
return xai_tools
|
|
264
|
+
|
|
265
|
+
def _handle_response(self, response: httpx.Response) -> ChatResponse:
|
|
266
|
+
"""
|
|
267
|
+
Handle xAI API response.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
response: HTTP response from xAI API
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
ChatResponse object
|
|
274
|
+
|
|
275
|
+
Raises:
|
|
276
|
+
Various provider errors based on response status
|
|
277
|
+
"""
|
|
278
|
+
if response.status_code == 200:
|
|
279
|
+
data = response.json()
|
|
280
|
+
choices = data.get("choices", [])
|
|
281
|
+
|
|
282
|
+
if choices and len(choices) > 0:
|
|
283
|
+
message = choices[0].get("message", {})
|
|
284
|
+
content = message.get("content", "")
|
|
285
|
+
usage = data.get("usage", {})
|
|
286
|
+
|
|
287
|
+
return ChatResponse(
|
|
288
|
+
content=content,
|
|
289
|
+
model_used=self.model,
|
|
290
|
+
tokens_used=usage.get("total_tokens", 0),
|
|
291
|
+
timestamp=datetime.now(),
|
|
292
|
+
)
|
|
293
|
+
else:
|
|
294
|
+
raise ProviderError("Empty response from xAI API")
|
|
295
|
+
|
|
296
|
+
elif response.status_code == 401:
|
|
297
|
+
raise AuthenticationError("Invalid xAI API key")
|
|
298
|
+
elif response.status_code == 429:
|
|
299
|
+
raise RateLimitError("xAI API rate limit exceeded")
|
|
300
|
+
elif response.status_code == 404:
|
|
301
|
+
raise ModelNotFoundError(f"xAI model '{self.model}' not found")
|
|
302
|
+
else:
|
|
303
|
+
try:
|
|
304
|
+
error_data = response.json()
|
|
305
|
+
error_msg = error_data.get("error", {}).get("message", "Unknown error")
|
|
306
|
+
except:
|
|
307
|
+
error_msg = f"HTTP {response.status_code}"
|
|
308
|
+
|
|
309
|
+
raise ProviderError(f"xAI API error: {error_msg}")
|
|
310
|
+
|
|
311
|
+
def _handle_response_with_tools(self, response: httpx.Response) -> ChatResponse:
|
|
312
|
+
"""
|
|
313
|
+
Handle xAI API response with tool calls.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
response: HTTP response from xAI API
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
ChatResponse object with tool calls
|
|
320
|
+
"""
|
|
321
|
+
if response.status_code == 200:
|
|
322
|
+
data = response.json()
|
|
323
|
+
choices = data.get("choices", [])
|
|
324
|
+
|
|
325
|
+
if choices and len(choices) > 0:
|
|
326
|
+
message = choices[0].get("message", {})
|
|
327
|
+
content = message.get("content", "")
|
|
328
|
+
usage = data.get("usage", {})
|
|
329
|
+
|
|
330
|
+
# Extract tool calls if present
|
|
331
|
+
tool_calls = []
|
|
332
|
+
if "tool_calls" in message:
|
|
333
|
+
for tool_call in message["tool_calls"]:
|
|
334
|
+
if tool_call.get("type") == "function":
|
|
335
|
+
function = tool_call.get("function", {})
|
|
336
|
+
tool_calls.append(
|
|
337
|
+
ToolCall(
|
|
338
|
+
name=function.get("name", ""),
|
|
339
|
+
arguments=function.get("arguments", {}),
|
|
340
|
+
)
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
return ChatResponse(
|
|
344
|
+
content=content,
|
|
345
|
+
model_used=self.model,
|
|
346
|
+
tokens_used=usage.get("total_tokens", 0),
|
|
347
|
+
tool_calls=tool_calls if tool_calls else None,
|
|
348
|
+
timestamp=datetime.now(),
|
|
349
|
+
)
|
|
350
|
+
else:
|
|
351
|
+
raise ProviderError("Empty response from xAI API")
|
|
352
|
+
else:
|
|
353
|
+
return self._handle_response(response)
|
|
354
|
+
|
|
355
|
+
def get_model_info(self) -> EnhancedModelInfo:
|
|
356
|
+
"""
|
|
357
|
+
Get information about the current xAI model.
|
|
358
|
+
"""
|
|
359
|
+
model_configs = {
|
|
360
|
+
"grok-beta": {
|
|
361
|
+
"description": "Grok Beta - Advanced reasoning with real-time information",
|
|
362
|
+
"max_tokens": 131072,
|
|
363
|
+
"cost_per_million_input": 5.0,
|
|
364
|
+
"cost_per_million_output": 15.0,
|
|
365
|
+
"swe_score": 70.1,
|
|
366
|
+
"supports_tools": True,
|
|
367
|
+
"supports_multimodal": True,
|
|
368
|
+
},
|
|
369
|
+
"grok-vision-beta": {
|
|
370
|
+
"description": "Grok Vision Beta - Multimodal model with image understanding",
|
|
371
|
+
"max_tokens": 8192,
|
|
372
|
+
"cost_per_million_input": 5.0,
|
|
373
|
+
"cost_per_million_output": 15.0,
|
|
374
|
+
"swe_score": 65.3,
|
|
375
|
+
"supports_tools": True,
|
|
376
|
+
"supports_multimodal": True,
|
|
377
|
+
},
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
config = model_configs.get(
|
|
381
|
+
self.model,
|
|
382
|
+
{
|
|
383
|
+
"description": f"xAI model {self.model}",
|
|
384
|
+
"max_tokens": 131072,
|
|
385
|
+
"cost_per_million_input": 5.0,
|
|
386
|
+
"cost_per_million_output": 15.0,
|
|
387
|
+
"swe_score": 65.0,
|
|
388
|
+
"supports_tools": True,
|
|
389
|
+
"supports_multimodal": True,
|
|
390
|
+
},
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
enhanced_info = EnhancedModelInfo(
|
|
394
|
+
name=self.model,
|
|
395
|
+
provider="xai",
|
|
396
|
+
description=config["description"],
|
|
397
|
+
max_tokens=config["max_tokens"],
|
|
398
|
+
cost_per_million_input=config["cost_per_million_input"],
|
|
399
|
+
cost_per_million_output=config["cost_per_million_output"],
|
|
400
|
+
swe_score=config["swe_score"],
|
|
401
|
+
available=True,
|
|
402
|
+
supports_tools=config["supports_tools"],
|
|
403
|
+
supports_multimodal=config["supports_multimodal"],
|
|
404
|
+
latest_version=self.model == "grok-beta",
|
|
405
|
+
context_window=config["max_tokens"],
|
|
406
|
+
is_free=False,
|
|
407
|
+
release_date=datetime(2024, 12, 1), # Approximate release date
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
# Update SWE rating based on score
|
|
411
|
+
enhanced_info.update_swe_rating()
|
|
412
|
+
|
|
413
|
+
return enhanced_info
|
|
414
|
+
|
|
415
|
+
def get_available_models(self) -> List[EnhancedModelInfo]:
|
|
416
|
+
"""
|
|
417
|
+
Get list of available xAI models.
|
|
418
|
+
"""
|
|
419
|
+
models = [
|
|
420
|
+
EnhancedModelInfo(
|
|
421
|
+
name="grok-beta",
|
|
422
|
+
provider="xai",
|
|
423
|
+
description="Grok Beta - Advanced reasoning with real-time information",
|
|
424
|
+
max_tokens=131072,
|
|
425
|
+
cost_per_million_input=5.0,
|
|
426
|
+
cost_per_million_output=15.0,
|
|
427
|
+
swe_score=70.1,
|
|
428
|
+
available=True,
|
|
429
|
+
supports_tools=True,
|
|
430
|
+
supports_multimodal=True,
|
|
431
|
+
latest_version=True,
|
|
432
|
+
context_window=131072,
|
|
433
|
+
is_free=False,
|
|
434
|
+
release_date=datetime(2024, 12, 1),
|
|
435
|
+
),
|
|
436
|
+
EnhancedModelInfo(
|
|
437
|
+
name="grok-vision-beta",
|
|
438
|
+
provider="xai",
|
|
439
|
+
description="Grok Vision Beta - Multimodal model with image understanding",
|
|
440
|
+
max_tokens=8192,
|
|
441
|
+
cost_per_million_input=5.0,
|
|
442
|
+
cost_per_million_output=15.0,
|
|
443
|
+
swe_score=65.3,
|
|
444
|
+
available=True,
|
|
445
|
+
supports_tools=True,
|
|
446
|
+
supports_multimodal=True,
|
|
447
|
+
context_window=8192,
|
|
448
|
+
is_free=False,
|
|
449
|
+
release_date=datetime(2024, 12, 1),
|
|
450
|
+
),
|
|
451
|
+
]
|
|
452
|
+
|
|
453
|
+
# Update SWE ratings for all models
|
|
454
|
+
for model in models:
|
|
455
|
+
model.update_swe_rating()
|
|
456
|
+
|
|
457
|
+
return models
|
|
458
|
+
|
|
459
|
+
def supports_tools(self) -> bool:
|
|
460
|
+
"""
|
|
461
|
+
Check if xAI provider supports tool calling.
|
|
462
|
+
|
|
463
|
+
Returns:
|
|
464
|
+
True - xAI supports function calling and tools
|
|
465
|
+
"""
|
|
466
|
+
return True
|
|
467
|
+
|
|
468
|
+
def supports_multimodal(self) -> bool:
|
|
469
|
+
"""
|
|
470
|
+
Check if xAI provider supports multimodal inputs.
|
|
471
|
+
|
|
472
|
+
Returns:
|
|
473
|
+
True - xAI models support images and multimodal inputs
|
|
474
|
+
"""
|
|
475
|
+
return True
|
|
476
|
+
|
|
477
|
+
def supports_streaming(self) -> bool:
|
|
478
|
+
"""
|
|
479
|
+
Check if xAI provider supports streaming responses.
|
|
480
|
+
|
|
481
|
+
Returns:
|
|
482
|
+
True - xAI supports streaming
|
|
483
|
+
"""
|
|
484
|
+
return True
|