Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions litellm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,7 @@ def add_known_models():
from .llms.azure.responses.o_series_transformation import (
AzureOpenAIOSeriesResponsesAPIConfig,
)
from .llms.xai.responses.transformation import XAIResponsesAPIConfig
from .llms.litellm_proxy.responses.transformation import (
LiteLLMProxyResponsesAPIConfig,
)
Expand Down
146 changes: 146 additions & 0 deletions litellm/llms/xai/responses/transformation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
from typing import TYPE_CHECKING, Any, Dict, List, Optional

import litellm
from litellm._logging import verbose_logger
from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.openai import ResponsesAPIOptionalRequestParams
from litellm.types.router import GenericLiteLLMParams
from litellm.types.utils import LlmProviders

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj

LiteLLMLoggingObj = _LiteLLMLoggingObj
else:
LiteLLMLoggingObj = Any

XAI_API_BASE = "https://api.x.ai/v1"


class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig):
"""
Configuration for XAI's Responses API.

Inherits from OpenAIResponsesAPIConfig since XAI's Responses API is largely
compatible with OpenAI's, with a few differences:
- Does not support the 'instructions' parameter
- Requires code_interpreter tools to have 'container' field removed
- Recommends store=false when sending images

Reference: https://docs.x.ai/docs/api-reference#create-new-response
"""

@property
def custom_llm_provider(self) -> LlmProviders:
return LlmProviders.XAI

def get_supported_openai_params(self, model: str) -> list:
"""
Get supported parameters for XAI Responses API.

XAI supports most OpenAI Responses API params except 'instructions'.
"""
supported_params = super().get_supported_openai_params(model)

# Remove 'instructions' as it's not supported by XAI
if "instructions" in supported_params:
supported_params.remove("instructions")

return supported_params

def map_openai_params(
self,
response_api_optional_params: ResponsesAPIOptionalRequestParams,
model: str,
drop_params: bool,
) -> Dict:
"""
Map parameters for XAI Responses API.

Handles XAI-specific transformations:
1. Drops 'instructions' parameter (not supported)
2. Transforms code_interpreter tools to remove 'container' field
3. Sets store=false when images are detected (recommended by XAI)
"""
params = dict(response_api_optional_params)

# Drop instructions parameter (not supported by XAI)
if "instructions" in params:
verbose_logger.debug(
"XAI Responses API does not support 'instructions' parameter. Dropping it."
)
params.pop("instructions")

# Transform code_interpreter tools - remove container field
if "tools" in params and params["tools"]:
tools_list = params["tools"]
# Ensure tools is a list for iteration
if not isinstance(tools_list, list):
tools_list = [tools_list]

transformed_tools: List[Any] = []
for tool in tools_list:
if isinstance(tool, dict) and tool.get("type") == "code_interpreter":
# XAI supports code_interpreter but doesn't use the container field
# Keep only the type field
verbose_logger.debug(
"XAI: Transforming code_interpreter tool, removing container field"
)
transformed_tools.append({"type": "code_interpreter"})
else:
transformed_tools.append(tool)
params["tools"] = transformed_tools

return params

def validate_environment(
self, headers: dict, model: str, litellm_params: Optional[GenericLiteLLMParams]
) -> dict:
"""
Validate environment and set up headers for XAI API.

Uses XAI_API_KEY from environment or litellm_params.
"""
litellm_params = litellm_params or GenericLiteLLMParams()
api_key = (
litellm_params.api_key
or litellm.api_key
or get_secret_str("XAI_API_KEY")
)

if not api_key:
raise ValueError(
"XAI API key is required. Set XAI_API_KEY environment variable or pass api_key parameter."
)

headers.update(
{
"Authorization": f"Bearer {api_key}",
}
)
return headers

def get_complete_url(
self,
api_base: Optional[str],
litellm_params: dict,
) -> str:
"""
Get the complete URL for XAI Responses API endpoint.

Returns:
str: The full URL for the XAI /responses endpoint
"""
api_base = (
api_base
or litellm.api_base
or get_secret_str("XAI_API_BASE")
or XAI_API_BASE
)

# Remove trailing slashes
api_base = api_base.rstrip("/")

return f"{api_base}/responses"

2 changes: 2 additions & 0 deletions litellm/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,13 +373,13 @@
):
try:
if log_level == "DEBUG":
verbose_logger.debug(print_statement)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear
elif log_level == "INFO":
verbose_logger.info(print_statement)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear
elif log_level == "ERROR":
verbose_logger.error(print_statement)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear
if litellm.set_verbose is True and logger_only is False:
print(print_statement) # noqa

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear
except Exception:
pass

Expand Down Expand Up @@ -2002,7 +2002,7 @@
)
except Exception as e:
verbose_logger.debug(
f"Model not found or error in checking response schema support. You passed model={model}, custom_llm_provider={custom_llm_provider}. Error: {str(e)}"

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
)
return False

Expand Down Expand Up @@ -2119,7 +2119,7 @@
return False
except Exception as e:
verbose_logger.debug(
f"Model not found or error in checking {key} support. You passed model={model}, custom_llm_provider={custom_llm_provider}. Error: {str(e)}"

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
This expression logs sensitive data (secret) as clear text.
This expression logs sensitive data (password) as clear text.
)

supported_by_provider = _supports_provider_info_factory(
Expand Down Expand Up @@ -7374,6 +7374,8 @@
return litellm.AzureOpenAIOSeriesResponsesAPIConfig()
else:
return litellm.AzureOpenAIResponsesAPIConfig()
elif litellm.LlmProviders.XAI == provider:
return litellm.XAIResponsesAPIConfig()
elif litellm.LlmProviders.LITELLM_PROXY == provider:
return litellm.LiteLLMProxyResponsesAPIConfig()
return None
Expand Down
112 changes: 112 additions & 0 deletions tests/test_litellm/llms/xai/responses/test_transformation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
"""
Tests for XAI Responses API transformation

Tests the XAIResponsesAPIConfig class that handles XAI-specific
transformations for the Responses API.

Source: litellm/llms/xai/responses/transformation.py
"""
import sys
import os

sys.path.insert(0, os.path.abspath("../../../../.."))

import pytest
from litellm.types.utils import LlmProviders
from litellm.utils import ProviderConfigManager
from litellm.llms.xai.responses.transformation import XAIResponsesAPIConfig
from litellm.types.llms.openai import ResponsesAPIOptionalRequestParams


class TestXAIResponsesAPITransformation:
"""Test XAI Responses API configuration and transformations"""

def test_xai_provider_config_registration(self):
"""Test that XAI provider returns XAIResponsesAPIConfig"""
config = ProviderConfigManager.get_provider_responses_api_config(
model="xai/grok-4-fast",
provider=LlmProviders.XAI,
)

assert config is not None, "Config should not be None for XAI provider"
assert isinstance(
config, XAIResponsesAPIConfig
), f"Expected XAIResponsesAPIConfig, got {type(config)}"
assert (
config.custom_llm_provider == LlmProviders.XAI
), "custom_llm_provider should be XAI"

def test_code_interpreter_container_field_removed(self):
"""Test that container field is removed from code_interpreter tools"""
config = XAIResponsesAPIConfig()

params = ResponsesAPIOptionalRequestParams(
tools=[
{
"type": "code_interpreter",
"container": {"type": "auto"}
}
]
)

result = config.map_openai_params(
response_api_optional_params=params,
model="grok-4-fast",
drop_params=False
)

assert "tools" in result
assert len(result["tools"]) == 1
assert result["tools"][0]["type"] == "code_interpreter"
assert "container" not in result["tools"][0], "Container field should be removed"

def test_instructions_parameter_dropped(self):
"""Test that instructions parameter is dropped for XAI"""
config = XAIResponsesAPIConfig()

params = ResponsesAPIOptionalRequestParams(
instructions="You are a helpful assistant.",
temperature=0.7
)

result = config.map_openai_params(
response_api_optional_params=params,
model="grok-4-fast",
drop_params=False
)

assert "instructions" not in result, "Instructions should be dropped"
assert result.get("temperature") == 0.7, "Other params should be preserved"

def test_supported_params_excludes_instructions(self):
"""Test that get_supported_openai_params excludes instructions"""
config = XAIResponsesAPIConfig()
supported = config.get_supported_openai_params("grok-4-fast")

assert "instructions" not in supported, "instructions should not be supported"
assert "tools" in supported, "tools should be supported"
assert "temperature" in supported, "temperature should be supported"
assert "model" in supported, "model should be supported"

def test_xai_responses_endpoint_url(self):
"""Test that get_complete_url returns correct XAI endpoint"""
config = XAIResponsesAPIConfig()

# Test with default XAI API base
url = config.get_complete_url(api_base=None, litellm_params={})
assert url == "https://api.x.ai/v1/responses", f"Expected XAI responses endpoint, got {url}"

# Test with custom api_base
custom_url = config.get_complete_url(
api_base="https://custom.x.ai/v1",
litellm_params={}
)
assert custom_url == "https://custom.x.ai/v1/responses", f"Expected custom endpoint, got {custom_url}"

# Test with trailing slash
url_with_slash = config.get_complete_url(
api_base="https://api.x.ai/v1/",
litellm_params={}
)
assert url_with_slash == "https://api.x.ai/v1/responses", "Should handle trailing slash"

Loading