fix(routers): a tool call with no arguments needs a clean end-of-stream
Second pass of the adversarial review on this stack: the truncated-
arguments guard added earlier in the branch left one hole open, and it
is the hole that runs a side-effecting tool.
WHY THIS MATTERS
"Arguments present but unparseable" already fails the stream. But the
hole was the case with NO argument bytes at all. The carve-out read
`if (partial.arguments.trim())` - so an empty string skipped every check
and the call executed with `input: {}`. A stream that died right after
the `function.name` delta and before the first `{` therefore ran
delete_document (or any tool whose no-argument form is meaningful) with
empty input, which is exactly the failure mode the guard was written to
prevent.
WHY THE EMPTY STRING CANNOT DECIDE THIS
A parameter-less tool also streams "" - the two cases are byte-identical
in the accumulated arguments. The only thing that tells them apart is
whether the upstream ever said why it stopped. So the carve-out is
re-keyed on a termination signal instead of on the payload:
`endedCleanly` is set when the SSE `[DONE]` sentinel arrives or when a
choice carries `finish_reason: "tool_calls"`. Empty arguments plus a
clean end still mean {}; empty arguments after a silent socket close now
throw the same descriptive error as malformed JSON.
Handling `[DONE]` as a signal rather than a skip also tightened the line
parser: the sentinel and an empty `data:` line are now separate branches
instead of one combined early return.
Tests: openrouter.test.ts gains the died-before-arguments case (no
[DONE], no finish_reason - must reject and never call runTools) and a
parameter-less-tool case that pins {} still executes when the stream
terminated cleanly. Pre-fix the first test does not merely fail its
assertion - it proves the bug, erroring with "results is not iterable"
because runTools WAS invoked for the aborted call.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| Repository | open-legal-products/mike |
|---|---|
| Author | Amal <mamalanand3@gmail.com> |
| Authored | |
| Committed | |
| Parents | e414b530 |
| Stats | 2 files changed , +121 , -5 |
| Part of | Harden model-router selection and failure handling |
Capture this commit into my fork
Download a Markdown prompt that tells Claude how to port this
exact commit into your working tree. Run it via
claude -p < capture-commit-dd7cd96d.md
from inside the repo you want the change in.