fix: make the integration work against a Claude proxy
- Treat an empty tool argument string as no parameters instead of raising JSONDecodeError; the proxy sends "" for tools like the timer status (upstream issue #3). - Do not replay earlier web searches in the history. The chat log keeps only their status, and a search without results makes the model disown the answers it based on it and search again (upstream issue #4). - Look up the home location for web search with the subentry's model instead of gpt-4o-mini, and save the options without city/region if the lookup fails (upstream issue #5). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8737e5d4ec
commit
235c536cab
6 files changed
+224
-70
No files matched your search
@@ -22,7 +22,6 @@ from openai.types.responses import (
|
||||
ResponseFunctionToolCall,
|
||||
ResponseFunctionToolCallParam,
|
||||
ResponseFunctionWebSearch,
|
||||
ResponseFunctionWebSearchParam,
|
||||
ResponseIncompleteEvent,
|
||||
ResponseInputFileParam,
|
||||
ResponseInputImageParam,
|
||||
@@ -181,20 +180,13 @@ def _convert_content_to_param(
|
||||
"""Convert any native chat message for this agent to the native format."""
|
||||
messages: ResponseInputParam = []
|
||||
reasoning_summary: list[str] = []
|
||||
web_search_calls: dict[str, ResponseFunctionWebSearchParam] = {}
|
||||
|
||||
for content in chat_content:
|
||||
if isinstance(content, conversation.ToolResultContent):
|
||||
if (
|
||||
content.tool_name == "web_search_call"
|
||||
and content.tool_call_id in web_search_calls
|
||||
):
|
||||
web_search_call = web_search_calls.pop(content.tool_call_id)
|
||||
web_search_call["status"] = content.tool_result.get( # type: ignore[typeddict-item]
|
||||
"status", "completed"
|
||||
)
|
||||
messages.append(web_search_call)
|
||||
else:
|
||||
# Earlier web searches are not replayed: the chat log only keeps
|
||||
# their status, not their results, and a search without results
|
||||
# makes the model disown the answer it based on that search.
|
||||
if content.tool_name != "web_search_call":
|
||||
messages.append(
|
||||
FunctionCallOutput(
|
||||
type="function_call_output",
|
||||
@@ -217,26 +209,16 @@ def _convert_content_to_param(
|
||||
if isinstance(content, conversation.AssistantContent):
|
||||
if content.tool_calls:
|
||||
for tool_call in content.tool_calls:
|
||||
if (
|
||||
tool_call.external
|
||||
and tool_call.tool_name == "web_search_call"
|
||||
and "action" in tool_call.tool_args
|
||||
):
|
||||
web_search_calls[tool_call.id] = ResponseFunctionWebSearchParam(
|
||||
type="web_search_call",
|
||||
id=tool_call.id,
|
||||
action=tool_call.tool_args["action"],
|
||||
status="completed",
|
||||
)
|
||||
else:
|
||||
messages.append(
|
||||
ResponseFunctionToolCallParam(
|
||||
type="function_call",
|
||||
name=tool_call.tool_name,
|
||||
arguments=json_dumps(tool_call.tool_args),
|
||||
call_id=tool_call.id,
|
||||
)
|
||||
if tool_call.external and tool_call.tool_name == "web_search_call":
|
||||
continue
|
||||
messages.append(
|
||||
ResponseFunctionToolCallParam(
|
||||
type="function_call",
|
||||
name=tool_call.tool_name,
|
||||
arguments=json_dumps(tool_call.tool_args),
|
||||
call_id=tool_call.id,
|
||||
)
|
||||
)
|
||||
|
||||
if content.thinking_content:
|
||||
reasoning_summary.append(content.thinking_content)
|
||||
@@ -418,7 +400,7 @@ async def _transform_stream( # noqa: C901 - This is complex, but better to have
|
||||
llm.ToolInput(
|
||||
id=current_tool_call.call_id,
|
||||
tool_name=current_tool_call.name,
|
||||
tool_args=json.loads(current_tool_call.arguments),
|
||||
tool_args=json.loads(current_tool_call.arguments or "{}"),
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user