From 3ff6fef086833b48918f1cf71c48aa690bb6c045 Mon Sep 17 00:00:00 2001 From: Raymond Lucke Date: Thu, 10 Jul 2025 17:44:51 -0700 Subject: [PATCH 1/6] Add configuration for Grok 4. --- providers/xai.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/providers/xai.py b/providers/xai.py index dcb14a1..98dbd55 100644 --- a/providers/xai.py +++ b/providers/xai.py @@ -21,6 +21,24 @@ class XAIModelProvider(OpenAICompatibleProvider): # Model configurations using ModelCapabilities objects SUPPORTED_MODELS = { + "grok-4-0709": ModelCapabilities( + provider=ProviderType.XAI, + model_name="grok-4-0709", + friendly_name="X.AI (Grok 4)", + context_window=256_000, # 256K tokens + max_output_tokens=256000, + supports_extended_thinking=True, # Supports reasoning mode + supports_system_prompts=True, + supports_streaming=True, + supports_function_calling=True, + supports_json_mode=True, # Supports structured outputs + supports_images=True, # Supports vision/image analysis + max_image_size_mb=20.0, # Assuming standard limit + supports_temperature=True, + temperature_constraint=create_temperature_constraint("range"), + description="GROK-4 (256K context) - Latest flagship model with reasoning, vision, and structured outputs", + aliases=["grok-4", "grok-4-latest", "grok4", "grok"], + ), "grok-3": ModelCapabilities( provider=ProviderType.XAI, model_name="grok-3", @@ -37,7 +55,7 @@ class XAIModelProvider(OpenAICompatibleProvider): supports_temperature=True, temperature_constraint=create_temperature_constraint("range"), description="GROK-3 (131K context) - Advanced reasoning model from X.AI, excellent for complex analysis", - aliases=["grok", "grok3"], + aliases=["grok3"], ), "grok-3-fast": ModelCapabilities( provider=ProviderType.XAI, @@ -130,6 +148,6 @@ class XAIModelProvider(OpenAICompatibleProvider): def supports_thinking_mode(self, model_name: str) -> bool: """Check if the model supports extended thinking mode.""" - # Currently GROK models do not support extended thinking - # This may change with future GROK model releases - return False + # Grok-4 supports extended thinking/reasoning mode + resolved_name = self._resolve_model_name(model_name) + return resolved_name == "grok-4-0709" From 39e2bc61b65cea907575fd213271c9c175f692e8 Mon Sep 17 00:00:00 2001 From: Raymond Lucke Date: Thu, 10 Jul 2025 18:15:31 -0700 Subject: [PATCH 2/6] Tests for Grok 4. --- tests/test_auto_mode_provider_selection.py | 3 +- tests/test_supported_models_aliases.py | 12 ++- tests/test_xai_provider.py | 118 ++++++++++++++++----- 3 files changed, 105 insertions(+), 28 deletions(-) diff --git a/tests/test_auto_mode_provider_selection.py b/tests/test_auto_mode_provider_selection.py index f610be4..7b32988 100644 --- a/tests/test_auto_mode_provider_selection.py +++ b/tests/test_auto_mode_provider_selection.py @@ -320,7 +320,8 @@ class TestAutoModeProviderSelection: ("pro", ProviderType.GOOGLE, "gemini-2.5-pro"), ("mini", ProviderType.OPENAI, "o4-mini"), ("o3mini", ProviderType.OPENAI, "o3-mini"), - ("grok", ProviderType.XAI, "grok-3"), + ("grok", ProviderType.XAI, "grok-4-0709"), + ("grok3", ProviderType.XAI, "grok-3"), ("grokfast", ProviderType.XAI, "grok-3-fast"), ] diff --git a/tests/test_supported_models_aliases.py b/tests/test_supported_models_aliases.py index 1eb76b5..1a4556c 100644 --- a/tests/test_supported_models_aliases.py +++ b/tests/test_supported_models_aliases.py @@ -75,19 +75,25 @@ class TestSupportedModelsAliases: assert isinstance(config.aliases, list), f"{model_name} aliases must be a list" # Test specific aliases - assert "grok" in provider.SUPPORTED_MODELS["grok-3"].aliases + assert "grok" in provider.SUPPORTED_MODELS["grok-4-0709"].aliases + assert "grok-4" in provider.SUPPORTED_MODELS["grok-4-0709"].aliases + assert "grok-4-latest" in provider.SUPPORTED_MODELS["grok-4-0709"].aliases + assert "grok4" in provider.SUPPORTED_MODELS["grok-4-0709"].aliases assert "grok3" in provider.SUPPORTED_MODELS["grok-3"].aliases assert "grok3fast" in provider.SUPPORTED_MODELS["grok-3-fast"].aliases assert "grokfast" in provider.SUPPORTED_MODELS["grok-3-fast"].aliases # Test alias resolution - assert provider._resolve_model_name("grok") == "grok-3" + assert provider._resolve_model_name("grok") == "grok-4-0709" + assert provider._resolve_model_name("grok4") == "grok-4-0709" + assert provider._resolve_model_name("grok-4") == "grok-4-0709" assert provider._resolve_model_name("grok3") == "grok-3" assert provider._resolve_model_name("grok3fast") == "grok-3-fast" assert provider._resolve_model_name("grokfast") == "grok-3-fast" # Test case insensitive resolution - assert provider._resolve_model_name("Grok") == "grok-3" + assert provider._resolve_model_name("Grok") == "grok-4-0709" + assert provider._resolve_model_name("GROK4") == "grok-4-0709" assert provider._resolve_model_name("GROKFAST") == "grok-3-fast" def test_dial_provider_aliases(self): diff --git a/tests/test_xai_provider.py b/tests/test_xai_provider.py index 978d9c1..fc00d1a 100644 --- a/tests/test_xai_provider.py +++ b/tests/test_xai_provider.py @@ -45,6 +45,10 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") # Test valid models + assert provider.validate_model_name("grok-4-0709") is True + assert provider.validate_model_name("grok-4") is True + assert provider.validate_model_name("grok-4-latest") is True + assert provider.validate_model_name("grok4") is True assert provider.validate_model_name("grok-3") is True assert provider.validate_model_name("grok-3-fast") is True assert provider.validate_model_name("grok") is True @@ -62,12 +66,16 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") # Test shorthand resolution - assert provider._resolve_model_name("grok") == "grok-3" + assert provider._resolve_model_name("grok") == "grok-4-0709" + assert provider._resolve_model_name("grok4") == "grok-4-0709" + assert provider._resolve_model_name("grok-4") == "grok-4-0709" + assert provider._resolve_model_name("grok-4-latest") == "grok-4-0709" assert provider._resolve_model_name("grok3") == "grok-3" assert provider._resolve_model_name("grokfast") == "grok-3-fast" assert provider._resolve_model_name("grok3fast") == "grok-3-fast" # Test full name passthrough + assert provider._resolve_model_name("grok-4-0709") == "grok-4-0709" assert provider._resolve_model_name("grok-3") == "grok-3" assert provider._resolve_model_name("grok-3-fast") == "grok-3-fast" @@ -90,6 +98,27 @@ class TestXAIProvider: assert capabilities.temperature_constraint.max_temp == 2.0 assert capabilities.temperature_constraint.default_temp == 0.7 + def test_get_capabilities_grok4(self): + """Test getting model capabilities for GROK-4.""" + provider = XAIModelProvider("test-key") + + capabilities = provider.get_capabilities("grok-4-0709") + assert capabilities.model_name == "grok-4-0709" + assert capabilities.friendly_name == "X.AI (Grok 4)" + assert capabilities.context_window == 256_000 + assert capabilities.provider == ProviderType.XAI + assert capabilities.supports_extended_thinking is True + assert capabilities.supports_system_prompts is True + assert capabilities.supports_streaming is True + assert capabilities.supports_function_calling is True + assert capabilities.supports_json_mode is True + assert capabilities.supports_images is True + + # Test temperature range + assert capabilities.temperature_constraint.min_temp == 0.0 + assert capabilities.temperature_constraint.max_temp == 2.0 + assert capabilities.temperature_constraint.default_temp == 0.7 + def test_get_capabilities_grok3_fast(self): """Test getting model capabilities for GROK-3 Fast.""" provider = XAIModelProvider("test-key") @@ -106,8 +135,12 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") capabilities = provider.get_capabilities("grok") - assert capabilities.model_name == "grok-3" # Should resolve to full name - assert capabilities.context_window == 131_072 + assert capabilities.model_name == "grok-4-0709" # Should resolve to full name + assert capabilities.context_window == 256_000 + + capabilities_3 = provider.get_capabilities("grok3") + assert capabilities_3.model_name == "grok-3" # Should resolve to full name + assert capabilities_3.context_window == 131_072 capabilities_fast = provider.get_capabilities("grokfast") assert capabilities_fast.model_name == "grok-3-fast" # Should resolve to full name @@ -119,13 +152,19 @@ class TestXAIProvider: with pytest.raises(ValueError, match="Unsupported X.AI model"): provider.get_capabilities("invalid-model") - def test_no_thinking_mode_support(self): - """Test that X.AI models don't support thinking mode.""" + def test_thinking_mode_support(self): + """Test thinking mode support for X.AI models.""" provider = XAIModelProvider("test-key") + # Grok-4 supports thinking mode + assert provider.supports_thinking_mode("grok-4-0709") is True + assert provider.supports_thinking_mode("grok-4") is True + assert provider.supports_thinking_mode("grok") is True # Resolves to grok-4 + + # Grok-3 models don't support thinking mode assert not provider.supports_thinking_mode("grok-3") assert not provider.supports_thinking_mode("grok-3-fast") - assert not provider.supports_thinking_mode("grok") + assert not provider.supports_thinking_mode("grok3") assert not provider.supports_thinking_mode("grokfast") def test_provider_type(self): @@ -145,7 +184,11 @@ class TestXAIProvider: # grok-3 should be allowed assert provider.validate_model_name("grok-3") is True - assert provider.validate_model_name("grok") is True # Shorthand for grok-3 + assert provider.validate_model_name("grok3") is True # Shorthand for grok-3 + + # grok-4 and its aliases should be blocked + assert provider.validate_model_name("grok-4-0709") is False + assert provider.validate_model_name("grok") is False # Now resolves to grok-4 # grok-3-fast should be blocked by restrictions assert provider.validate_model_name("grok-3-fast") is False @@ -161,10 +204,13 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") - # Shorthand "grok" should be allowed (resolves to grok-3) + # Shorthand "grok" should be allowed (resolves to grok-4-0709) assert provider.validate_model_name("grok") is True - # Full name "grok-3" should NOT be allowed (only shorthand "grok" is in restriction list) + # Full name "grok-4-0709" should NOT be allowed (only shorthand "grok" is in restriction list) + assert provider.validate_model_name("grok-4-0709") is False + + # "grok-3" should NOT be allowed (not in restriction list) assert provider.validate_model_name("grok-3") is False # "grok-3-fast" should be allowed (explicitly listed) @@ -173,7 +219,7 @@ class TestXAIProvider: # Shorthand "grokfast" should be allowed (resolves to grok-3-fast) assert provider.validate_model_name("grokfast") is True - @patch.dict(os.environ, {"XAI_ALLOWED_MODELS": "grok,grok-3"}) + @patch.dict(os.environ, {"XAI_ALLOWED_MODELS": "grok,grok-3,grok-4-0709"}) def test_both_shorthand_and_full_name_allowed(self): """Test that both shorthand and full name can be allowed.""" # Clear cached restriction service @@ -184,8 +230,9 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") # Both shorthand and full name should be allowed - assert provider.validate_model_name("grok") is True + assert provider.validate_model_name("grok") is True # Resolves to grok-4-0709 assert provider.validate_model_name("grok-3") is True + assert provider.validate_model_name("grok-4-0709") is True # Other models should not be allowed assert provider.validate_model_name("grok-3-fast") is False @@ -201,10 +248,12 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") + assert provider.validate_model_name("grok-4-0709") is True assert provider.validate_model_name("grok-3") is True assert provider.validate_model_name("grok-3-fast") is True assert provider.validate_model_name("grok") is True assert provider.validate_model_name("grokfast") is True + assert provider.validate_model_name("grok4") is True def test_friendly_name(self): """Test friendly name constant.""" @@ -219,22 +268,30 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") # Check that all expected base models are present + assert "grok-4-0709" in provider.SUPPORTED_MODELS assert "grok-3" in provider.SUPPORTED_MODELS assert "grok-3-fast" in provider.SUPPORTED_MODELS # Check model configs have required fields from providers.base import ModelCapabilities - grok3_config = provider.SUPPORTED_MODELS["grok-3"] - assert isinstance(grok3_config, ModelCapabilities) - assert hasattr(grok3_config, "context_window") - assert hasattr(grok3_config, "supports_extended_thinking") - assert hasattr(grok3_config, "aliases") - assert grok3_config.context_window == 131_072 - assert grok3_config.supports_extended_thinking is False + grok4_config = provider.SUPPORTED_MODELS["grok-4-0709"] + assert isinstance(grok4_config, ModelCapabilities) + assert hasattr(grok4_config, "context_window") + assert hasattr(grok4_config, "supports_extended_thinking") + assert hasattr(grok4_config, "aliases") + assert grok4_config.context_window == 256_000 + assert grok4_config.supports_extended_thinking is True # Check aliases are correctly structured - assert "grok" in grok3_config.aliases + assert "grok" in grok4_config.aliases + assert "grok-4" in grok4_config.aliases + assert "grok-4-latest" in grok4_config.aliases + assert "grok4" in grok4_config.aliases + + grok3_config = provider.SUPPORTED_MODELS["grok-3"] + assert grok3_config.context_window == 131_072 + assert grok3_config.supports_extended_thinking is False assert "grok3" in grok3_config.aliases grok3fast_config = provider.SUPPORTED_MODELS["grok-3-fast"] @@ -257,7 +314,7 @@ class TestXAIProvider: mock_response.choices = [MagicMock()] mock_response.choices[0].message.content = "Test response" mock_response.choices[0].finish_reason = "stop" - mock_response.model = "grok-3" # API returns the resolved model name + mock_response.model = "grok-4-0709" # API returns the resolved model name mock_response.id = "test-id" mock_response.created = 1234567890 mock_response.usage = MagicMock() @@ -271,15 +328,17 @@ class TestXAIProvider: # Call generate_content with alias 'grok' result = provider.generate_content( - prompt="Test prompt", model_name="grok", temperature=0.7 # This should be resolved to "grok-3" + prompt="Test prompt", model_name="grok", temperature=0.7 # This should be resolved to "grok-4-0709" ) # Verify the API was called with the RESOLVED model name mock_client.chat.completions.create.assert_called_once() call_kwargs = mock_client.chat.completions.create.call_args[1] - # CRITICAL ASSERTION: The API should receive "grok-3", not "grok" - assert call_kwargs["model"] == "grok-3", f"Expected 'grok-3' but API received '{call_kwargs['model']}'" + # CRITICAL ASSERTION: The API should receive "grok-4-0709", not "grok" + assert ( + call_kwargs["model"] == "grok-4-0709" + ), f"Expected 'grok-4-0709' but API received '{call_kwargs['model']}'" # Verify other parameters assert call_kwargs["temperature"] == 0.7 @@ -289,7 +348,7 @@ class TestXAIProvider: # Verify response assert result.content == "Test response" - assert result.model_name == "grok-3" # Should be the resolved name + assert result.model_name == "grok-4-0709" # Should be the resolved name @patch("providers.openai_compatible.OpenAI") def test_generate_content_other_aliases(self, mock_openai_class): @@ -311,6 +370,17 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") + # Test grok4 -> grok-4-0709 + mock_response.model = "grok-4-0709" + provider.generate_content(prompt="Test", model_name="grok4", temperature=0.7) + call_kwargs = mock_client.chat.completions.create.call_args[1] + assert call_kwargs["model"] == "grok-4-0709" + + # Test grok-4 -> grok-4-0709 + provider.generate_content(prompt="Test", model_name="grok-4", temperature=0.7) + call_kwargs = mock_client.chat.completions.create.call_args[1] + assert call_kwargs["model"] == "grok-4-0709" + # Test grok3 -> grok-3 mock_response.model = "grok-3" provider.generate_content(prompt="Test", model_name="grok3", temperature=0.7) From 346410e34e1f4b8874e18f0c38c1fbaabfbc1cd6 Mon Sep 17 00:00:00 2001 From: Raymond Lucke Date: Thu, 10 Jul 2025 18:21:44 -0700 Subject: [PATCH 3/6] Use ModelCapabilities for Grok thinking mode support check Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- providers/xai.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/providers/xai.py b/providers/xai.py index 98dbd55..aca75cb 100644 --- a/providers/xai.py +++ b/providers/xai.py @@ -148,6 +148,10 @@ class XAIModelProvider(OpenAICompatibleProvider): def supports_thinking_mode(self, model_name: str) -> bool: """Check if the model supports extended thinking mode.""" - # Grok-4 supports extended thinking/reasoning mode - resolved_name = self._resolve_model_name(model_name) - return resolved_name == "grok-4-0709" + # Check capabilities to determine thinking mode support + try: + capabilities = self.get_capabilities(model_name) + return capabilities.supports_extended_thinking + except ValueError: + # If the model is not supported, it doesn't support thinking mode. + return False From 0b4167bd6fcecef4455790f36582eb101dd663d9 Mon Sep 17 00:00:00 2001 From: Raymond Lucke Date: Thu, 10 Jul 2025 18:41:50 -0700 Subject: [PATCH 4/6] Update Grok 4 max_output_tokens to 16K to match Grok 3. --- providers/xai.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/xai.py b/providers/xai.py index aca75cb..369042c 100644 --- a/providers/xai.py +++ b/providers/xai.py @@ -26,7 +26,7 @@ class XAIModelProvider(OpenAICompatibleProvider): model_name="grok-4-0709", friendly_name="X.AI (Grok 4)", context_window=256_000, # 256K tokens - max_output_tokens=256000, + max_output_tokens=16_384, supports_extended_thinking=True, # Supports reasoning mode supports_system_prompts=True, supports_streaming=True, From 3e2dcc9c784216d9daa8d7fb31ec41ca8a8e666d Mon Sep 17 00:00:00 2001 From: Ted Slesinski Date: Sat, 12 Jul 2025 09:42:29 -0400 Subject: [PATCH 5/6] Update docs for grok 4 --- README.md | 1 + docs/advanced-usage.md | 5 +++++ docs/configuration.md | 9 ++++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d7b516c..f2bc0ba 100644 --- a/README.md +++ b/README.md @@ -290,6 +290,7 @@ nano .env # The file will contain, at least one should be set: # GEMINI_API_KEY=your-gemini-api-key-here # For Gemini models # OPENAI_API_KEY=your-openai-api-key-here # For O3 model +# XAI_API_KEY=your-xai-api-key-here # For Grok models # OPENROUTER_API_KEY=your-openrouter-key # For OpenRouter (see docs/custom_models.md) # DIAL_API_KEY=your-dial-api-key-here # For DIAL platform diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 9383354..63856da 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -39,6 +39,9 @@ Regardless of your default configuration, you can specify models per request: | **`o3-mini`** | OpenAI | 200K tokens | Balanced speed/quality | Moderate complexity tasks | | **`o4-mini`** | OpenAI | 200K tokens | Latest reasoning model | Optimized for shorter contexts | | **`gpt4.1`** | OpenAI | 1M tokens | Latest GPT-4 with extended context | Large codebase analysis, comprehensive reviews | +| **`grok-4-latest`** | X.AI | 256K tokens | Latest flagship model with reasoning, vision | Complex analysis, reasoning tasks | +| **`grok-3`** | X.AI | 131K tokens | Advanced reasoning model | Deep analysis, complex problems | +| **`grok-3-fast`** | X.AI | 131K tokens | Higher performance variant | Fast responses with reasoning | | **`llama`** (Llama 3.2) | Custom/Local | 128K tokens | Local inference, privacy | On-device analysis, cost-free processing | | **Any model** | OpenRouter | Varies | Access to GPT-4, Claude, Llama, etc. | User-specified or based on task requirements | @@ -49,6 +52,8 @@ cloud models (expensive/powerful) AND local models (free/private) in the same co - **Gemini Models**: Support thinking modes (minimal to max), web search, 1M context - **O3 Models**: Excellent reasoning, systematic analysis, 200K context - **GPT-4.1**: Extended context window (1M tokens), general capabilities +- **Grok-4**: Extended thinking support, vision capabilities, 256K context +- **Grok-3 Models**: Advanced reasoning, 131K context ## Model Usage Restrictions diff --git a/docs/configuration.md b/docs/configuration.md index 473b6de..12e9d65 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -74,7 +74,8 @@ DEFAULT_MODEL=auto # Claude picks best model for each task (recommended) - **`o3`**: Strong logical reasoning (200K context) - **`o3-mini`**: Balanced speed/quality (200K context) - **`o4-mini`**: Latest reasoning model, optimized for shorter contexts -- **`grok`**: GROK-3 advanced reasoning (131K context) +- **`grok-3`**: GROK-3 advanced reasoning (131K context) +- **`grok-4-latest`**: GROK-4 latest flagship model (256K context) - **Custom models**: via OpenRouter or local APIs ### Thinking Mode Configuration @@ -107,7 +108,7 @@ OPENAI_ALLOWED_MODELS=o3-mini,o4-mini,mini GOOGLE_ALLOWED_MODELS=flash,pro # X.AI GROK model restrictions -XAI_ALLOWED_MODELS=grok-3,grok-3-fast +XAI_ALLOWED_MODELS=grok-3,grok-3-fast,grok-4-latest # OpenRouter model restrictions (affects models via custom provider) OPENROUTER_ALLOWED_MODELS=opus,sonnet,mistral @@ -128,9 +129,11 @@ OPENROUTER_ALLOWED_MODELS=opus,sonnet,mistral - `pro` (shorthand for Pro model) **X.AI GROK Models:** +- `grok-4-latest` (256K context, latest flagship model with reasoning, vision, and structured outputs) - `grok-3` (131K context, advanced reasoning) - `grok-3-fast` (131K context, higher performance) -- `grok` (shorthand for grok-3) +- `grok` (shorthand for grok-4-latest) +- `grok4` (shorthand for grok-4-latest) - `grok3` (shorthand for grok-3) - `grokfast` (shorthand for grok-3-fast) From 912cde42d117a2078343299e593437ef5893f1af Mon Sep 17 00:00:00 2001 From: Beehive Innovations Date: Fri, 8 Aug 2025 10:06:38 +0400 Subject: [PATCH 6/6] Update test_xai_provider.py --- tests/test_xai_provider.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/tests/test_xai_provider.py b/tests/test_xai_provider.py index 8f292c2..7ed62b7 100644 --- a/tests/test_xai_provider.py +++ b/tests/test_xai_provider.py @@ -45,7 +45,6 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") # Test valid models - assert provider.validate_model_name("grok-4-0709") is True assert provider.validate_model_name("grok-4") is True assert provider.validate_model_name("grok-4-latest") is True assert provider.validate_model_name("grok4") is True @@ -73,7 +72,7 @@ class TestXAIProvider: assert provider._resolve_model_name("grok3fast") == "grok-3-fast" # Test full name passthrough - assert provider._resolve_model_name("grok-4-0709") == "grok-4-0709" + assert provider._resolve_model_name("grok-4") == "grok-4" assert provider._resolve_model_name("grok-3") == "grok-3" assert provider._resolve_model_name("grok-3-fast") == "grok-3-fast" @@ -100,8 +99,8 @@ class TestXAIProvider: """Test getting model capabilities for GROK-4.""" provider = XAIModelProvider("test-key") - capabilities = provider.get_capabilities("grok-4-0709") - assert capabilities.model_name == "grok-4-0709" + capabilities = provider.get_capabilities("grok-4") + assert capabilities.model_name == "grok-4" assert capabilities.friendly_name == "X.AI (Grok 4)" assert capabilities.context_window == 256_000 assert capabilities.provider == ProviderType.XAI @@ -151,7 +150,6 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") # Grok-4 supports thinking mode - assert provider.supports_thinking_mode("grok-4-0709") is True assert provider.supports_thinking_mode("grok-4") is True assert provider.supports_thinking_mode("grok") is True # Resolves to grok-4 @@ -202,8 +200,8 @@ class TestXAIProvider: # Shorthand "grok" should be allowed (resolves to grok-4) assert provider.validate_model_name("grok") is True - # Full name "grok-4-0709" should NOT be allowed (only shorthand "grok" is in restriction list) - assert provider.validate_model_name("grok-4-0709") is False + # Full name "grok-4" should NOT be allowed (only shorthand "grok" is in restriction list) + assert provider.validate_model_name("grok-4") is False # "grok-3" should NOT be allowed (not in restriction list) assert provider.validate_model_name("grok-3") is False @@ -214,7 +212,7 @@ class TestXAIProvider: # Shorthand "grokfast" should be allowed (resolves to grok-3-fast) assert provider.validate_model_name("grokfast") is True - @patch.dict(os.environ, {"XAI_ALLOWED_MODELS": "grok,grok-3,grok-4-0709"}) + @patch.dict(os.environ, {"XAI_ALLOWED_MODELS": "grok,grok-3,grok-4"}) def test_both_shorthand_and_full_name_allowed(self): """Test that both shorthand and full name can be allowed.""" # Clear cached restriction service @@ -225,9 +223,9 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") # Both shorthand and full name should be allowed - assert provider.validate_model_name("grok") is True # Resolves to grok-4-0709 + assert provider.validate_model_name("grok") is True # Resolves to grok-4 assert provider.validate_model_name("grok-3") is True - assert provider.validate_model_name("grok-4-0709") is True + assert provider.validate_model_name("grok-4") is True # Other models should not be allowed assert provider.validate_model_name("grok-3-fast") is False @@ -243,7 +241,7 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") - assert provider.validate_model_name("grok-4-0709") is True + assert provider.validate_model_name("grok-4") is True assert provider.validate_model_name("grok-3") is True assert provider.validate_model_name("grok-3-fast") is True assert provider.validate_model_name("grok") is True @@ -270,7 +268,7 @@ class TestXAIProvider: # Check model configs have required fields from providers.base import ModelCapabilities - grok4_config = provider.SUPPORTED_MODELS["grok-4-0709"] + grok4_config = provider.SUPPORTED_MODELS["grok-4"] assert isinstance(grok4_config, ModelCapabilities) assert hasattr(grok4_config, "context_window") assert hasattr(grok4_config, "supports_extended_thinking") @@ -315,7 +313,7 @@ class TestXAIProvider: mock_response.choices = [MagicMock()] mock_response.choices[0].message.content = "Test response" mock_response.choices[0].finish_reason = "stop" - mock_response.model = "grok-4-0709" # API returns the resolved model name + mock_response.model = "grok-4" # API returns the resolved model name mock_response.id = "test-id" mock_response.created = 1234567890 mock_response.usage = MagicMock() @@ -369,16 +367,16 @@ class TestXAIProvider: provider = XAIModelProvider("test-key") - # Test grok4 -> grok-4-0709 - mock_response.model = "grok-4-0709" + # Test grok4 -> grok-4 + mock_response.model = "grok-4" provider.generate_content(prompt="Test", model_name="grok4", temperature=0.7) call_kwargs = mock_client.chat.completions.create.call_args[1] - assert call_kwargs["model"] == "grok-4-0709" + assert call_kwargs["model"] == "grok-4" - # Test grok-4 -> grok-4-0709 + # Test grok-4 -> grok-4 provider.generate_content(prompt="Test", model_name="grok-4", temperature=0.7) call_kwargs = mock_client.chat.completions.create.call_args[1] - assert call_kwargs["model"] == "grok-4-0709" + assert call_kwargs["model"] == "grok-4" # Test grok3 -> grok-3 mock_response.model = "grok-3"