mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-16 09:45:24 -04:00
fix(agent): coerce non-object tool-call arguments instead of crashing (#1370)
A native function/tool call whose `arguments` field is valid JSON but not an
object — a bare array like ["ls -la"], or a string/number/bool/null — parsed
fine in function_call_to_tool_block and then every branch called args.get(...),
raising AttributeError ('list'/'str' object has no attribute 'get'). That
propagated out of the streamed agent loop (no surrounding try/except at the
call site in stream_agent_loop) and aborted the user's entire turn. Weaker and
local models routinely emit malformed args like this.
Coerce non-dict parsed arguments to {} (mirrors the existing empty-arguments
behavior), so the tool runs with empty args instead of killing the stream.
Adds tests/test_function_call_non_object_args.py covering array/string/number/
bool/null arguments — they fail before this change and pass after.
This commit is contained in:
@@ -1074,6 +1074,14 @@ def function_call_to_tool_block(name: str, arguments: str) -> Optional[ToolBlock
|
||||
logger.error(f"Failed to parse function call arguments for {name}: {arguments}")
|
||||
return None
|
||||
|
||||
# Some models emit valid JSON that isn't an object (e.g. a bare array
|
||||
# ["ls -la"], string, or number) as the function arguments. Every branch
|
||||
# below assumes a dict and calls args.get(...), so a non-dict would raise
|
||||
# AttributeError and abort the whole agent stream. Coerce to {} instead.
|
||||
if not isinstance(args, dict):
|
||||
logger.warning(f"Non-object function call arguments for {name}: {args!r}; treating as empty")
|
||||
args = {}
|
||||
|
||||
tool_type = _TOOL_NAME_MAP.get(name, name)
|
||||
|
||||
# Allow MCP tools through (namespaced as mcp__serverid__toolname)
|
||||
|
||||
Reference in New Issue
Block a user