Skip to content

Recover truncated tool calls, and never pass a leaked one off as an answer#3

Merged
hacksics merged 1 commit into
mainfrom
unparsed-tool-calls
Jul 27, 2026
Merged

Recover truncated tool calls, and never pass a leaked one off as an answer#3
hacksics merged 1 commit into
mainfrom
unparsed-tool-calls

Conversation

@hacksics

Copy link
Copy Markdown
Owner

Same change as upstream andrewyng/openworker#219, on top of this fork's main (which already has the Developer persona and the LM Studio provider).

Fixes two failures that both end a turn looking like the model simply stopped mid-sentence — the symptom seen with qwen3.5-9b on LM Studio, though the cause is model-agnostic.

Truncated calls are recovered. Salvage takes the function name plus every parameter that actually closed; a trailing unterminated <parameter=…> is dropped rather than guessed, so a half-written path or file body can never reach a tool.

A leaked call is no longer a "completed" answer. It ends on the error path so the GUI offers Retry — the right affordance, since this drift is probabilistic and retrying usually works. Detection strips fenced and inline code, so a model explaining tool-call syntax still counts as a real answer.

939 passed on this branch (+5).

🤖 Generated with Claude Code

…nswer

Small local models drift off the tool-call format, especially with a large
tool schema in play. Two failures followed from that, both of which ended
the turn looking like the model had simply stopped mid-sentence.

Salvage handled well-formed Qwen/Hermes XML but gave up entirely on a call
cut off partway through. It now takes the function name plus every
parameter that actually closed. A trailing unterminated `<parameter=…>` is
dropped rather than guessed, so a half-written path or file body can never
reach a tool; if that leaves a required argument missing, the call fails
validation and the model gets a corrective tool error, which is the agent
loop working.

Worse, a call that never parsed at all was reported as `status: completed`
— indistinguishable from the model deciding it was done, leaving the user
with narration trailing off into stray closing tags. It now ends on the
error path, so the GUI offers Retry. That is the right affordance here: the
drift is probabilistic, not deterministic, so the same model usually
succeeds on a second attempt.

Detection ignores fenced and inline code, so a model *explaining* tool-call
syntax is still a real answer, and requires that tools were offered at all.

Reported against qwen3.5-9b on LM Studio, 2026-07-26.

Co-Authored-By: Claude <noreply@anthropic.com>
@hacksics
hacksics merged commit bb5cd59 into main Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant