A chat-completions stream that ends with no finish_reason while a tool call's
arguments are cut at a value boundary leaves the assembler holding a prefix
that _repair_tool_call_arguments closes into valid JSON: '"timeout": 600' cut
after its first digit becomes timeout=6, a todo list cut after its second item
replaces the whole list with two. The repaired call was no longer flagged as
truncated, so _finish_chat_stream stamped the turn "stop" and dispatched it
with every key and digit that never arrived missing. Only a cut inside a
string stayed on the partial-stream stub path.
The assembler now repairs only calls the provider finished (any
finish_reason). A dropped stream's malformed arguments are flagged and take
the existing stub retry, like the empty-argument (#80498) and repetition
guards beside it. Repair of completed responses (#115061, GLM via Ollama) is
unchanged.
Ported from the second commit of #105017 onto
_StreamingCall._assemble_tool_calls. Its finish_reason="length" arm is left
out: that path already retries the call without executing it.
(cherry picked from commit 0895ffe009613dc6b6087c99d2cf599211ec87dc)
Co-authored-by: John Paul Soliva <soliva.johnpaul@icloud.com>