Skip to content

Commit bd96039

Browse files
committed
fix(openrouter-adapter): Improve tool call argument parsing with robust error handling
- Add comprehensive JSON parsing error handling for tool call arguments - Implement fallback mechanism to extract first valid JSON object when parsing fails - Log detailed warnings and errors for malformed JSON input - Prevent adapter from breaking when encountering invalid JSON in tool call arguments - Ensure graceful degradation by using empty dict if parsing completely fails
1 parent 2021344 commit bd96039

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

agentle/generations/providers/openrouter/_adapters/openrouter_message_to_generated_assistant_message_adapter.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,45 @@ def adapt(
8484
tool_parts: list[ToolExecutionSuggestion] = []
8585
for tool_call in tool_calls_data:
8686
function_data = tool_call.get("function", {})
87+
88+
# Parse arguments with error handling for malformed JSON
89+
args_str = str(function_data.get("arguments", "{}"))
90+
args: dict[str, object] = {}
91+
try:
92+
args = json.loads(args_str)
93+
except json.JSONDecodeError as e:
94+
# Log the error and try to extract the first valid JSON object
95+
import logging
96+
97+
logger = logging.getLogger(__name__)
98+
logger.warning(
99+
f"Malformed JSON in tool call arguments: {e}. "
100+
+ "Attempting to parse first valid JSON object. "
101+
+ f"Raw arguments: {args_str[:200]}..."
102+
)
103+
104+
# Try to find the first complete JSON object
105+
try:
106+
# Use JSONDecoder to parse incrementally
107+
decoder = json.JSONDecoder()
108+
args, idx = decoder.raw_decode(args_str)
109+
if idx < len(args_str.strip()):
110+
logger.warning(
111+
f"Extra data found after position {idx}. "
112+
+ "Using first valid JSON object only."
113+
)
114+
except (json.JSONDecodeError, ValueError) as e2:
115+
logger.error(
116+
f"Failed to parse tool call arguments even with recovery: {e2}. "
117+
+ "Using empty dict."
118+
)
119+
args = {}
120+
87121
tool_parts.append(
88122
ToolExecutionSuggestion(
89123
id=str(tool_call.get("id", "")),
90124
tool_name=str(function_data.get("name", "")),
91-
args=json.loads(str(function_data.get("arguments", "{}"))),
125+
args=args,
92126
)
93127
)
94128

0 commit comments

Comments
 (0)