mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-08-10 08:21:54 +00:00
fix: default empty Responses tool-call arguments to {}
Missing or empty Chat Completions tool-call arguments were forwarded
as an empty string, which is invalid JSON for Responses API
function_call items and breaks parse_tool_call_args. Normalize to
"{}" and cover the case in regression tests. Also assert a supplied
tool-call id is preserved as call_id.
Co-authored-by: Rip&Tear <theCyberTech@users.noreply.github.com>
This commit is contained in:
@@ -771,15 +771,17 @@ class OpenAICompletion(BaseLLM):
|
||||
items.append({"role": "assistant", "content": content})
|
||||
for call in message["tool_calls"]:
|
||||
function = call.get("function", {})
|
||||
args = function.get("arguments", "")
|
||||
args = function.get("arguments")
|
||||
if args is None or args == "":
|
||||
args = "{}"
|
||||
elif not isinstance(args, str):
|
||||
args = json.dumps(args)
|
||||
items.append(
|
||||
{
|
||||
"type": "function_call",
|
||||
"call_id": call.get("id") or f"call_{id(call)}",
|
||||
"name": function.get("name", ""),
|
||||
"arguments": args
|
||||
if isinstance(args, str)
|
||||
else json.dumps(args),
|
||||
"arguments": args,
|
||||
}
|
||||
)
|
||||
return items
|
||||
@@ -810,7 +812,7 @@ class OpenAICompletion(BaseLLM):
|
||||
- Internally-tagged tool format (flat structure)
|
||||
"""
|
||||
instructions: str | None = self.instructions
|
||||
input_messages: list[Any] = []
|
||||
input_messages: list[dict[str, Any] | LLMMessage] = []
|
||||
|
||||
for message in messages:
|
||||
if message.get("role") == "system":
|
||||
@@ -824,7 +826,7 @@ class OpenAICompletion(BaseLLM):
|
||||
input_messages.extend(self._to_responses_input(message))
|
||||
|
||||
# Prepend reasoning items for ZDR (zero-data-retention) chaining when configured
|
||||
final_input: list[Any] = []
|
||||
final_input: list[dict[str, Any] | LLMMessage] = []
|
||||
if self.auto_chain_reasoning and self._last_reasoning_items:
|
||||
final_input.extend(self._last_reasoning_items)
|
||||
final_input.extend(input_messages if input_messages else messages)
|
||||
|
||||
@@ -1017,6 +1017,7 @@ def test_openai_responses_api_preserves_assistant_content_with_tool_calls():
|
||||
"tool_calls": [
|
||||
{
|
||||
"type": "function",
|
||||
"id": "call_fetch_page",
|
||||
"function": {
|
||||
"name": "fetch_page",
|
||||
"arguments": {"url": "https://example.com"},
|
||||
@@ -1033,10 +1034,39 @@ def test_openai_responses_api_preserves_assistant_content_with_tool_calls():
|
||||
"content": "I'll fetch that page now.",
|
||||
}
|
||||
assert params["input"][1]["type"] == "function_call"
|
||||
assert params["input"][1]["call_id"].startswith("call_")
|
||||
assert params["input"][1]["call_id"] == "call_fetch_page"
|
||||
assert params["input"][1]["arguments"] == '{"url": "https://example.com"}'
|
||||
|
||||
|
||||
def test_openai_responses_api_defaults_missing_tool_call_arguments():
|
||||
"""Missing or empty tool-call arguments must become a valid JSON object."""
|
||||
llm = OpenAICompletion(model="gpt-4o-mini", api="responses")
|
||||
|
||||
messages = [
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": None,
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "call_no_args",
|
||||
"type": "function",
|
||||
"function": {"name": "ping"},
|
||||
},
|
||||
{
|
||||
"id": "call_empty_args",
|
||||
"type": "function",
|
||||
"function": {"name": "ping", "arguments": ""},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
params = llm._prepare_responses_params(messages)
|
||||
|
||||
assert params["input"][0]["arguments"] == "{}"
|
||||
assert params["input"][1]["arguments"] == "{}"
|
||||
|
||||
|
||||
def test_openai_responses_api_converts_tool_result_message():
|
||||
"""Regression: tool-role messages (Chat-Completions shape) must become
|
||||
function_call_output input items for the Responses API.
|
||||
|
||||
Reference in New Issue
Block a user