Pull requests / #525
#525 serve: rescue a tool call stranded in an unclosed thinking span
closed · @chimpera · 0 Kommentare · Auf GitHub
Beschreibung
Some chat templates render a tool call right after the reasoning block without ever emitting `</think>` before it. The whole call then streams out as `reasoning_content`, and a client that runs tools from the content channel ends its turn with nothing to execute — seen live as agents stopping silently mid-task (transcript: thinking-only message, `end_turn`, thinking text ends with a complete `<tool_call>` block). The rescue is deliberately conservative: during generation the parser behaves exactly as before (no divert, nothing withheld). It keeps the reasoning text from the first `<tool_call>` opener aside; a `</think>` after the opener clears it — a valid quoted call example inside a *closed* thinking span is a mention, not an act, and is never fired as a call. Only at end of generation, in a span that never closed, is the kept tail delivered as `tool_call` events, and only when every complete block parses against the request's tool schemas. Malformed or unfinished bodies stay reasoning; a reply cut by max tokens mid-call is untouched (#530 already names that case). Deferred rather than opt-in: a rescued call is by construction at the very end of the reply (the span never closed and generation ended), so nothing is delayed in practice — the only thing given up is `stream_tools` progressive args for rescued calls, which arrive whole at end of stream. Tests: the live stranded shape (chunked at 1/7/10k × `stream_tools` on/off), a valid quoted example in a closed span (the review's false positive — the first version of this fix fired it as a real call), a stranded call with trailing thought, two stranded calls, a malformed mention in an unclosed span, `</think>`-before-opener, an unfinished call, and the content-channel path. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Mehr auf der Site
Links zu Install, Modellen, Releases.