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.
Files changed (126) hide show
  1. omnimancer/__init__.py +42 -0
  2. omnimancer/__main__.py +9 -0
  3. omnimancer/cli/__init__.py +8 -0
  4. omnimancer/cli/agent_manager.py +826 -0
  5. omnimancer/cli/agent_wizard.py +944 -0
  6. omnimancer/cli/approval_formatter.py +734 -0
  7. omnimancer/cli/approval_integration.py +734 -0
  8. omnimancer/cli/approval_prompt.py +1286 -0
  9. omnimancer/cli/batch_approval_display.py +617 -0
  10. omnimancer/cli/batch_approval_filters.py +729 -0
  11. omnimancer/cli/batch_operation_monitor.py +775 -0
  12. omnimancer/cli/commands/performance_cmd.py +624 -0
  13. omnimancer/cli/commands.py +757 -0
  14. omnimancer/cli/completion_handler.py +281 -0
  15. omnimancer/cli/config_setup_wizard.py +783 -0
  16. omnimancer/cli/dynamic_commands.py +371 -0
  17. omnimancer/cli/handlers/__init__.py +18 -0
  18. omnimancer/cli/handlers/agent_handler.py +865 -0
  19. omnimancer/cli/handlers/agent_persona_handler.py +1048 -0
  20. omnimancer/cli/handlers/custom_agent_handler.py +352 -0
  21. omnimancer/cli/handlers/permissions_handler.py +1609 -0
  22. omnimancer/cli/interface.py +6695 -0
  23. omnimancer/cli/performance_dashboard.py +612 -0
  24. omnimancer/core/__init__.py +34 -0
  25. omnimancer/core/agent/__init__.py +256 -0
  26. omnimancer/core/agent/agent_config.py +715 -0
  27. omnimancer/core/agent/agent_switcher.py +668 -0
  28. omnimancer/core/agent/approval_context.py +460 -0
  29. omnimancer/core/agent/approval_dialog.py +902 -0
  30. omnimancer/core/agent/approval_interface.py +628 -0
  31. omnimancer/core/agent/approval_manager.py +760 -0
  32. omnimancer/core/agent/cli_integration.py +470 -0
  33. omnimancer/core/agent/config.py +845 -0
  34. omnimancer/core/agent/custom_agent_integration.py +654 -0
  35. omnimancer/core/agent/diff_renderer.py +706 -0
  36. omnimancer/core/agent/file_content_display.py +503 -0
  37. omnimancer/core/agent/file_modification_workflow.py +658 -0
  38. omnimancer/core/agent/file_system_manager.py +1790 -0
  39. omnimancer/core/agent/input_handler.py +614 -0
  40. omnimancer/core/agent/metrics_collector.py +771 -0
  41. omnimancer/core/agent/optimization_engine.py +729 -0
  42. omnimancer/core/agent/performance_monitor.py +717 -0
  43. omnimancer/core/agent/persona.py +870 -0
  44. omnimancer/core/agent/persona_validator.py +672 -0
  45. omnimancer/core/agent/program_executor.py +748 -0
  46. omnimancer/core/agent/proposed_changes_integration.py +663 -0
  47. omnimancer/core/agent/read_before_write_errors.py +492 -0
  48. omnimancer/core/agent/read_before_write_ui.py +647 -0
  49. omnimancer/core/agent/rich_renderer.py +763 -0
  50. omnimancer/core/agent/status_config.py +238 -0
  51. omnimancer/core/agent/status_core.py +446 -0
  52. omnimancer/core/agent/status_integrated_engine.py +540 -0
  53. omnimancer/core/agent/status_manager.py +878 -0
  54. omnimancer/core/agent/status_ui_components.py +535 -0
  55. omnimancer/core/agent/template_applicator.py +548 -0
  56. omnimancer/core/agent/terminal_status_listener.py +394 -0
  57. omnimancer/core/agent/token_tracker.py +679 -0
  58. omnimancer/core/agent/types.py +60 -0
  59. omnimancer/core/agent/web_client.py +745 -0
  60. omnimancer/core/agent/workflow_orchestrator.py +826 -0
  61. omnimancer/core/agent_engine.py +1625 -0
  62. omnimancer/core/agent_mode_manager.py +706 -0
  63. omnimancer/core/agent_progress_ui.py +545 -0
  64. omnimancer/core/chat_manager.py +141 -0
  65. omnimancer/core/config_manager.py +2199 -0
  66. omnimancer/core/config_migration.py +772 -0
  67. omnimancer/core/config_provider.py +1974 -0
  68. omnimancer/core/config_security_validator.py +393 -0
  69. omnimancer/core/config_validator.py +768 -0
  70. omnimancer/core/conversation_manager.py +352 -0
  71. omnimancer/core/engine.py +787 -0
  72. omnimancer/core/enhanced_input.py +523 -0
  73. omnimancer/core/env_loader.py +83 -0
  74. omnimancer/core/fallback_manager.py +568 -0
  75. omnimancer/core/health_monitor.py +462 -0
  76. omnimancer/core/history_manager.py +462 -0
  77. omnimancer/core/mcp_integration_layer.py +878 -0
  78. omnimancer/core/models.py +1889 -0
  79. omnimancer/core/provider_capabilities.py +403 -0
  80. omnimancer/core/provider_initializer.py +450 -0
  81. omnimancer/core/provider_registry.py +432 -0
  82. omnimancer/core/security/__init__.py +16 -0
  83. omnimancer/core/security/approval_workflow.py +406 -0
  84. omnimancer/core/security/audit_logger.py +511 -0
  85. omnimancer/core/security/permission_controller.py +511 -0
  86. omnimancer/core/security/sandbox_manager.py +379 -0
  87. omnimancer/core/security/security_manager.py +530 -0
  88. omnimancer/core/setup_wizard.py +345 -0
  89. omnimancer/core/setup_wizard_core.py +449 -0
  90. omnimancer/core/setup_wizard_guide_generator.py +376 -0
  91. omnimancer/core/setup_wizard_provider_setup.py +454 -0
  92. omnimancer/core/setup_wizard_ui.py +317 -0
  93. omnimancer/core/setup_wizard_validation.py +371 -0
  94. omnimancer/core/signal_handler.py +174 -0
  95. omnimancer/mcp/__init__.py +11 -0
  96. omnimancer/mcp/client.py +725 -0
  97. omnimancer/mcp/manager.py +649 -0
  98. omnimancer/providers/__init__.py +24 -0
  99. omnimancer/providers/azure.py +608 -0
  100. omnimancer/providers/base.py +262 -0
  101. omnimancer/providers/bedrock.py +711 -0
  102. omnimancer/providers/claude.py +426 -0
  103. omnimancer/providers/claude_code.py +406 -0
  104. omnimancer/providers/cohere.py +412 -0
  105. omnimancer/providers/factory.py +988 -0
  106. omnimancer/providers/gemini.py +708 -0
  107. omnimancer/providers/mistral.py +554 -0
  108. omnimancer/providers/ollama.py +510 -0
  109. omnimancer/providers/openai.py +362 -0
  110. omnimancer/providers/openrouter.py +709 -0
  111. omnimancer/providers/perplexity.py +476 -0
  112. omnimancer/providers/vertex.py +617 -0
  113. omnimancer/providers/xai.py +484 -0
  114. omnimancer/ui/__init__.py +6 -0
  115. omnimancer/ui/cancellation_handler.py +235 -0
  116. omnimancer/ui/progress_indicator.py +318 -0
  117. omnimancer/utils/__init__.py +22 -0
  118. omnimancer/utils/error_handler.py +589 -0
  119. omnimancer/utils/errors.py +667 -0
  120. omnimancer/utils/retry.py +238 -0
  121. omnimancer_cli-0.1.0.dist-info/METADATA +413 -0
  122. omnimancer_cli-0.1.0.dist-info/RECORD +126 -0
  123. omnimancer_cli-0.1.0.dist-info/WHEEL +5 -0
  124. omnimancer_cli-0.1.0.dist-info/entry_points.txt +4 -0
  125. omnimancer_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
  126. 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
@@ -0,0 +1,6 @@
1
+ """
2
+ UI components for Omnimancer.
3
+
4
+ This package contains user interface components including
5
+ cancellation handlers and visual indicators.
6
+ """