feat: flattened tool call schema#756
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit dfb36c2. Configure here.
| # Inside nested value — passthrough. | ||
| if self.is_inner_thoughts_value and self.depth == 1: | ||
| return "", self._emit_thought('"') | ||
| return self._emit_main('"'), "" |
There was a problem hiding this comment.
Unreachable condition in _handle_quote nested thought routing
Medium Severity
The condition if self.is_inner_thoughts_value and self.depth == 1 on line 149 is inside a block guarded by if self.depth >= 2 on line 147. Since depth >= 2 and depth == 1 are mutually exclusive, the inner branch can never execute — it's dead code. This means quotes inside nested thought values (if thought were ever an object or array) would be incorrectly routed to _emit_main instead of _emit_thought. Other methods like _handle_open_object, _handle_close_object, and _consume_value_char correctly handle nested thought routing, but _handle_quote does not — both the opening quote path (line 149) and the closing quote path (line 170-171) unconditionally route to main at depth >= 2.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit dfb36c2. Configure here.
| self.main_buffer = stripped[:-1] | ||
| self.main_buffer += "}" | ||
| self.state = "end" | ||
| return "}", "" |
There was a problem hiding this comment.
Streaming deltas contain irrevocable dangling comma when thought is last
Medium Severity
When wait_for_first_key=False (the default) and thought is the last field, _handle_close_object retroactively strips a trailing comma from main_buffer but returns "}" as the delta. The comma was already returned as a delta by _handle_comma in a previous call and cannot be revoked. Concatenating all deltas from process_fragment produces invalid JSON like {"a":"x",}, even though main_buffer is correctly patched to {"a":"x"}. The cumulative buffer and the sum of streaming deltas are inconsistent.
Reviewed by Cursor Bugbot for commit dfb36c2. Configure here.
| inner = json.loads(inner, strict=False) | ||
| except json.JSONDecodeError: | ||
| inner = {} | ||
| args = {"thought": args.get("thought", ""), **(inner if isinstance(inner, dict) else {})} |
There was a problem hiding this comment.
Legacy shim silently discards non-dict action_input values
Low Severity
The backward-compatibility shim in parse_as_tool_call silently converts non-dict action_input values to empty params. When action_input is a JSON string that decodes to a non-dict (e.g., a list or scalar), or is invalid JSON, inner becomes {} and the original parameters are lost. The old code would have raised a recoverable ActionParsingException, prompting the LLM to retry, but the new shim silently proceeds with an empty tool call — a change from "error + retry" to "silent data loss."
Reviewed by Cursor Bugbot for commit dfb36c2. Configure here.
Coverage Report •
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||


Note
Medium Risk
Changes the FC wire/schema contract and streaming parser for all tool calls; legacy
action_inputis shimmed but models and clients must align with flat args.Overview
Function-calling tool arguments are flattened:
thoughtis a top-level field alongside each tool’s real parameters, replacing the nested{ thought, action_input }wrapper. Schemas fromgenerate_function_calling_schemasputthoughtfirst, dropaction_input, and update ReAct FC instructions (including top-leveldelegate_final).Parsing and execution use
ToolCallArgumentswithextra="allow"andto_action_input();parse_as_tool_callstill normalizes the legacy wrapper shape for replay/back-compat. Tool-only calls with no other params yield an empty input dict instead of a hard error.Streaming in FC mode adds
JSONInnerThoughtsExtractorto split streaming argument JSON into REASONING (thought) vs TOOL_INPUT (params withoutthought), with held-buffer flush whenthoughtis missing or late.provide_final_answerstill uses the existing JSON field parser.Tests cover the extractor, flat schemas, streaming behavior, and updated FC recovery (malformed JSON vs missing
action_input).Reviewed by Cursor Bugbot for commit 4382ecd. Bugbot is set up for automated code reviews on this repo. Configure here.