mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-31 06:56:59 +00:00
Merge 537e521c61 into 84617874b8
This commit is contained in:
commit
533728dd14
2 changed files with 49 additions and 2 deletions
|
|
@ -2533,7 +2533,7 @@ class LiteLLMCompletionResponsesConfig:
|
|||
raw_arguments = REDACTED_TOOL_CALL_ARGUMENTS_PLACEHOLDER
|
||||
if not raw_arguments and function_call.get("type") == "custom_tool_call":
|
||||
raw_input: Final = function_call.get("input") or ""
|
||||
raw_arguments = json.dumps({"content": raw_input}) if raw_input else ""
|
||||
raw_arguments = json.dumps({"content": raw_input})
|
||||
raw_name: Final = function_call.get("name") or ""
|
||||
namespace: Final = function_call.get("namespace") or ""
|
||||
qualify: Final = bool(namespace) and function_call.get("type") != "custom_tool_call"
|
||||
|
|
@ -3622,7 +3622,7 @@ class LiteLLMCompletionResponsesConfig:
|
|||
type="function",
|
||||
function=Function(
|
||||
name=tool_call.get("name") or "",
|
||||
arguments=serialize_tool_call_arguments(tool_call.get("arguments")),
|
||||
arguments=serialize_tool_call_arguments(tool_call.get("arguments"), "{}"),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ from litellm.responses.litellm_completion_transformation.custom_tools import (
|
|||
unwrap_custom_tool_arguments,
|
||||
build_tool_call_item_kwargs,
|
||||
convert_custom_tool_to_function_tool,
|
||||
serialize_tool_call_arguments,
|
||||
_MAX_ARGUMENTS_LEN,
|
||||
)
|
||||
|
||||
|
|
@ -216,6 +217,15 @@ class TestCustomToolUtilities:
|
|||
"""Non-custom tools are not convertible; the caller keeps them as-is."""
|
||||
assert convert_custom_tool_to_function_tool({"type": "function"}) is None
|
||||
|
||||
def test_serialize_tool_call_arguments_default_stays_empty_string(self):
|
||||
"""The serializer default stays "" so non-terminal call sites
|
||||
(streaming accumulation, fallbacks) are unaffected; only terminal
|
||||
sites pass "{}" explicitly."""
|
||||
assert serialize_tool_call_arguments(None) == ""
|
||||
assert serialize_tool_call_arguments("") == ""
|
||||
assert serialize_tool_call_arguments(None, "{}") == "{}"
|
||||
assert serialize_tool_call_arguments("", "{}") == "{}"
|
||||
|
||||
|
||||
class TestTransformationCustomTools:
|
||||
"""Test custom tool handling in transformation logic."""
|
||||
|
|
@ -285,6 +295,43 @@ class TestTransformationCustomTools:
|
|||
{"content": "*** Begin Patch\n+hello\n*** End Patch"}
|
||||
)
|
||||
|
||||
def test_bridge_output_tool_call_empty_arguments_serialize_to_json_object(self):
|
||||
"""Responses->chat bridge output must carry valid JSON arguments.
|
||||
|
||||
A strict OpenAI-compatible gateway rejects assistant tool calls whose
|
||||
arguments are "" (see issue #40369); empty/missing/None arguments
|
||||
must serialize to "{}".
|
||||
"""
|
||||
for arguments in ("", None, "<missing>"):
|
||||
tool_call = {"id": "call_x", "name": "get_weather"}
|
||||
if arguments != "<missing>":
|
||||
tool_call["arguments"] = arguments
|
||||
out = LiteLLMCompletionResponsesConfig._transform_responses_output_tool_call_to_chat_completion_output_tool_call(
|
||||
tool_call
|
||||
)
|
||||
assert out.function.arguments == "{}"
|
||||
assert json.loads(out.function.arguments) == {}
|
||||
|
||||
def test_custom_tool_call_empty_input_serializes_to_content_envelope(self):
|
||||
"""An empty custom-tool input must become {"content": ""}, not "".
|
||||
|
||||
Otherwise the round trip degrades: "" serializes to "{}" at the
|
||||
bridge and unwrap_custom_tool_arguments("{}") returns the literal
|
||||
string "{}" instead of empty content (issue #40369, second point).
|
||||
"""
|
||||
item = {
|
||||
"type": "custom_tool_call",
|
||||
"call_id": "call_1",
|
||||
"name": "apply_patch",
|
||||
"input": "",
|
||||
}
|
||||
messages = LiteLLMCompletionResponsesConfig._transform_responses_api_function_call_to_chat_completion_message(
|
||||
function_call=item
|
||||
)
|
||||
arguments = messages[0]["tool_calls"][0]["function"]["arguments"]
|
||||
assert arguments == json.dumps({"content": ""})
|
||||
assert unwrap_custom_tool_arguments(arguments) == ""
|
||||
|
||||
def test_function_call_input_item_with_empty_arguments_keeps_them_empty(self):
|
||||
"""A plain function_call input item with empty or missing `arguments`
|
||||
must produce an empty arguments string, never a `{"content": ...}`
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue