Skip to content
Closed
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
8 changes: 6 additions & 2 deletions litellm/llms/bedrock_mantle/responses/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@
)

# Per Bedrock Mantle Responses API validation errors.
_BEDROCK_MANTLE_SUPPORTED_RESPONSE_TOOL_TYPES = frozenset({"function", "mcp", "custom", "namespace", "tool_search"})
_BEDROCK_MANTLE_SUPPORTED_RESPONSE_TOOL_TYPES: Final = frozenset(
{"function", "mcp", "custom", "namespace", "tool_search"}
)

_BEDROCK_MANTLE_SUPPORTED_SERVICE_TIERS: Final = frozenset({"auto", "default"})

Expand Down Expand Up @@ -110,7 +112,9 @@ def _filter_unsupported_tools(tools: list[Any]) -> list[Any]:
kept.append(tool)
continue
tool_type = tool.get("type")
if tool_type in _BEDROCK_MANTLE_SUPPORTED_RESPONSE_TOOL_TYPES:
if tool_type in _BEDROCK_MANTLE_SUPPORTED_RESPONSE_TOOL_TYPES or (
isinstance(tool_type, str) and tool_type.startswith("web_search")
):
kept.append(tool)
else:
dropped_types.append(str(tool_type))
Expand Down
5 changes: 5 additions & 0 deletions litellm/model_prices_and_context_window_backup.json
Original file line number Diff line number Diff line change
Expand Up @@ -46939,6 +46939,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_web_search": true,
"supports_tool_choice": true,
"supports_vision": true
},
Expand Down Expand Up @@ -46971,6 +46972,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_web_search": true,
"supports_tool_choice": true,
"supports_vision": true
},
Expand Down Expand Up @@ -47003,6 +47005,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_web_search": true,
"supports_tool_choice": true,
"supports_vision": true
},
Expand Down Expand Up @@ -47030,6 +47033,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_web_search": true,
"supports_tool_choice": true,
"supports_vision": true
},
Expand Down Expand Up @@ -47057,6 +47061,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_web_search": true,
"supports_tool_choice": true,
"supports_vision": true
},
Expand Down
5 changes: 5 additions & 0 deletions model_prices_and_context_window.json
Original file line number Diff line number Diff line change
Expand Up @@ -46939,6 +46939,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_web_search": true,
"supports_tool_choice": true,
"supports_vision": true
},
Expand Down Expand Up @@ -46971,6 +46972,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_web_search": true,
"supports_tool_choice": true,
"supports_vision": true
},
Expand Down Expand Up @@ -47003,6 +47005,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_web_search": true,
"supports_tool_choice": true,
"supports_vision": true
},
Expand Down Expand Up @@ -47030,6 +47033,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_web_search": true,
"supports_tool_choice": true,
"supports_vision": true
},
Expand Down Expand Up @@ -47057,6 +47061,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_web_search": true,
"supports_tool_choice": true,
"supports_vision": true
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,12 +328,44 @@ def test_standard_path_outbound_body_carries_bare_model(self):


class TestBedrockMantleResponsesTools:
@pytest.mark.parametrize(
"tool_type", ["web_search", "web_search_preview", "web_search_2025_08_26"]
)
def test_web_search_tool_family_survives_map_openai_params(self, tool_type):
tool = {"type": tool_type, "filters": {"domains": ["example.com"]}}
cfg = BedrockMantleResponsesAPIConfig()

params = cfg.map_openai_params(
response_api_optional_params={"tools": [tool]},
model="openai.gpt-5.5",
drop_params=False,
)

assert params["tools"] == [tool]

@pytest.mark.parametrize(
"tool_type", ["web_search", "web_search_preview", "web_search_2025_08_26"]
)
def test_web_search_tool_family_survives_transform_responses_api_request(self, tool_type):
tool = {"type": tool_type, "filters": {"domains": ["example.com"]}}
cfg = BedrockMantleResponsesAPIConfig()

body = cfg.transform_responses_api_request(
model="openai.gpt-5.5",
input="hello",
response_api_optional_request_params={"tools": [tool]},
litellm_params=GenericLiteLLMParams(),
headers={},
)

assert body["tools"] == [tool]

def test_map_openai_params_drops_unsupported_tools(self):
cfg = BedrockMantleResponsesAPIConfig()
params = cfg.map_openai_params(
response_api_optional_params={
"tools": [
{"type": "web_search"},
{"type": "file_search"},
{"type": "function", "name": "exec_command"},
]
},
Expand All @@ -342,10 +374,13 @@ def test_map_openai_params_drops_unsupported_tools(self):
)
assert params["tools"] == [{"type": "function", "name": "exec_command"}]

def test_map_openai_params_removes_tools_when_all_unsupported(self):
@pytest.mark.parametrize(
"tool_type", ["file_search", "image_generation", "code_interpreter"]
)
def test_map_openai_params_removes_tools_when_all_unsupported(self, tool_type):
cfg = BedrockMantleResponsesAPIConfig()
params = cfg.map_openai_params(
response_api_optional_params={"tools": [{"type": "web_search"}]},
response_api_optional_params={"tools": [{"type": tool_type}]},
model="openai.gpt-5.5",
drop_params=False,
)
Expand All @@ -359,12 +394,12 @@ def test_dropped_tools_are_logged_at_warning_level(self):
"litellm.llms.bedrock_mantle.responses.transformation.verbose_logger.warning"
) as mock_warning:
cfg.map_openai_params(
response_api_optional_params={"tools": [{"type": "web_search"}]},
response_api_optional_params={"tools": [{"type": "file_search"}]},
model="openai.gpt-5.5",
drop_params=False,
)
assert mock_warning.call_count == 1
assert "web_search" in str(mock_warning.call_args)
assert "file_search" in str(mock_warning.call_args)


def _codex_exec_tool():
Expand Down Expand Up @@ -545,14 +580,17 @@ def test_hoisted_tools_append_after_existing_tools(self):
)
assert body["tools"] == [existing_tool, *self._CODEX_TOOLS]

def test_unsupported_hoisted_tool_types_are_dropped(self):
@pytest.mark.parametrize(
"tool_type", ["file_search", "image_generation", "code_interpreter"]
)
Comment on lines +583 to +585

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Cover hoisted web-search preservation

The changed tests cover unsupported hoisted tools, but not web-search preservation, leaving this distinct transformation path without regression protection

Context Used: CLAUDE.md (source)

Knowledge Base Used: LLM Provider Adapters

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

def test_unsupported_hoisted_tool_types_are_dropped(self, tool_type):
body = self._transform(
input=[
{
"type": "additional_tools",
"role": "developer",
"tools": [
{"type": "web_search"},
{"type": tool_type},
{"type": "function", "name": "wait"},
],
},
Expand All @@ -564,7 +602,7 @@ def test_unsupported_hoisted_tool_types_are_dropped(self):
def test_item_stripped_even_when_no_hoisted_tool_survives(self):
body = self._transform(
input=[
{"type": "additional_tools", "role": "developer", "tools": [{"type": "web_search"}]},
{"type": "additional_tools", "role": "developer", "tools": [{"type": "file_search"}]},
self._USER_MESSAGE,
]
)
Expand Down
Loading