fix(bedrock): preserve tools for nexus claude aliases

This commit is contained in:
milo 2026-05-22 21:44:55 +08:00
parent 8b771ebe4e
commit 8e21611702
2 changed files with 98 additions and 6 deletions

View file

@ -527,8 +527,12 @@ class AmazonConverseConfig(BaseConfig):
## Filter out 'cross-region' from model name
base_model = BedrockModelInfo.get_base_model(model)
is_anthropic_model = base_model.startswith("anthropic") or base_model.startswith(
"claude-"
)
if (
base_model.startswith("anthropic")
is_anthropic_model
or base_model.startswith("mistral")
or base_model.startswith("cohere")
or base_model.startswith("meta.llama3-1")
@ -546,10 +550,14 @@ class AmazonConverseConfig(BaseConfig):
if base_model.startswith("amazon.nova"):
supported_params.append("web_search_options")
if litellm.utils.supports_tool_choice(
model=model, custom_llm_provider=self.custom_llm_provider
) or litellm.utils.supports_tool_choice(
model=base_model, custom_llm_provider=self.custom_llm_provider
if (
is_anthropic_model
or litellm.utils.supports_tool_choice(
model=model, custom_llm_provider=self.custom_llm_provider
)
or litellm.utils.supports_tool_choice(
model=base_model, custom_llm_provider=self.custom_llm_provider
)
):
# only anthropic and mistral support tool choice config. otherwise (E.g. cohere) will fail the call - https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ToolChoice.html
supported_params.append("tool_choice")
@ -1852,6 +1860,7 @@ class AmazonConverseConfig(BaseConfig):
}
tool_name = (
params.pop("command", None)
or params.pop("tool_name", None)
or params.pop("name", None)
or params.pop("tool", None)
)
@ -2258,12 +2267,25 @@ class AmazonConverseConfig(BaseConfig):
if json_mode and not filtered_tools and tools:
initial_finish_reason = "stop"
text_tool_call_tools = optional_params.get("tools")
if text_tool_call_tools is None:
request_data = data
if isinstance(data, str):
try:
request_data = json.loads(data)
except Exception:
request_data = None
if isinstance(request_data, dict):
tool_config = request_data.get("toolConfig")
if isinstance(tool_config, dict):
text_tool_call_tools = tool_config.get("tools")
(
returned_message,
returned_finish_reason,
) = self.apply_tool_call_transformation_if_needed(
message=_message,
tools=optional_params.get("tools"),
tools=text_tool_call_tools,
initial_finish_reason=initial_finish_reason,
)
model_response.choices = [

View file

@ -348,6 +348,65 @@ def test_apply_tool_call_transformation_ignores_text_for_unknown_tool_name():
assert transformed_message.tool_calls is None
def test_transform_response_uses_bedrock_tool_config_for_text_tool_calls():
import httpx
config = AmazonConverseConfig()
raw_response = httpx.Response(
status_code=200,
json={
"output": {
"message": {
"role": "assistant",
"content": [
{
"text": (
"\n<function>\n"
'<parameter name="command">read_file</parameter>\n'
'<parameter name="path">C:\\Projects\\redaigo\\scripts\\run_etf_v13.py</parameter>\n'
'<parameter name="offset">0</parameter>\n'
'<parameter name="length">3000</parameter>\n'
"</function>"
)
}
],
}
},
"stopReason": "end_turn",
"usage": {"inputTokens": 1, "outputTokens": 1, "totalTokens": 2},
},
)
model_response = config._transform_response(
model="bedrock/converse/claude-opus-4.6",
response=raw_response,
model_response=ModelResponse(),
stream=False,
logging_obj=None,
optional_params={},
api_key=None,
data=json.dumps(
{
"toolConfig": {
"tools": [
{
"toolSpec": {
"name": "read_file",
"inputSchema": {"json": {}},
}
}
]
}
}
),
messages=[],
encoding=None,
)
choice = model_response.choices[0]
_assert_read_file_tool_call(choice.message, choice.finish_reason)
def test_transform_tool_call_with_cache_control():
from litellm.llms.bedrock.chat.converse_transformation import AmazonConverseConfig
@ -568,6 +627,17 @@ def test_get_supported_openai_params():
assert "reasoning_effort" in supported_params
@pytest.mark.parametrize(
"model",
["claude-opus-4.6", "claude-sonnet-4.6", "claude-haiku-4.5"],
)
def test_get_supported_openai_params_for_nexus_claude_aliases(model):
config = AmazonConverseConfig()
supported_params = config.get_supported_openai_params(model=model)
assert "tools" in supported_params
assert "tool_choice" in supported_params
def test_get_supported_openai_params_bedrock_converse():
"""
Test that all documented bedrock converse models have the same set of supported openai params when using