From ea10f55097056ee5c6ba375bb900155c9e9a877a Mon Sep 17 00:00:00 2001 From: cthomas Date: Wed, 10 Sep 2025 12:31:40 -0700 Subject: [PATCH] feat: handle incorrect booleans in json from llm (#2820) --- .../interfaces/anthropic_streaming_interface.py | 16 ++++++++++------ letta/server/rest_api/json_parser.py | 2 ++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/letta/interfaces/anthropic_streaming_interface.py b/letta/interfaces/anthropic_streaming_interface.py index 56def5e6..0c394287 100644 --- a/letta/interfaces/anthropic_streaming_interface.py +++ b/letta/interfaces/anthropic_streaming_interface.py @@ -106,15 +106,19 @@ class AnthropicStreamingInterface: try: tool_input = json.loads(self.accumulated_tool_call_args) except json.JSONDecodeError as e: - logger.warning( - f"Failed to decode tool call arguments for tool_call_id={self.tool_call_id}, " - f"name={self.tool_call_name}. Raw input: {self.accumulated_tool_call_args!r}. Error: {e}" - ) - raise + # Attempt to use OptimisticJSONParser to handle incomplete/malformed JSON + try: + tool_input = self.json_parser.parse(self.accumulated_tool_call_args) + except: + logger.warning( + f"Failed to decode tool call arguments for tool_call_id={self.tool_call_id}, " + f"name={self.tool_call_name}. Raw input: {self.accumulated_tool_call_args!r}. Error: {e}" + ) + raise e if "id" in tool_input and tool_input["id"].startswith("toolu_") and "function" in tool_input: arguments = str(json.dumps(tool_input["function"]["arguments"], indent=2)) else: - arguments = self.accumulated_tool_call_args + arguments = str(json.dumps(tool_input, indent=2)) return ToolCall(id=self.tool_call_id, function=FunctionCall(arguments=arguments, name=self.tool_call_name)) def _check_inner_thoughts_complete(self, combined_args: str) -> bool: diff --git a/letta/server/rest_api/json_parser.py b/letta/server/rest_api/json_parser.py index 0a05bba4..610b9fa4 100644 --- a/letta/server/rest_api/json_parser.py +++ b/letta/server/rest_api/json_parser.py @@ -63,6 +63,8 @@ class OptimisticJSONParser(JSONParser): '"': self._parse_string, "t": self._parse_true, "f": self._parse_false, + "T": self._parse_true, + "F": self._parse_false, "n": self._parse_null, } # Register number parser for digits and signs