Streamed tool-call deltas with null id/name break tool calls (ToolNotFoundError loop) #4370
Replies: 2 comments
|
Verified against rc.2 (HEAD b150a55) — the source matches your built Family convergence: 5th instance of the explicit-null classYour trace is the exact mechanism of #1713 (SGLang) → #2090 (Xreative) → #2997 (opencode.ai zen) → #4265 (opencode.ai/zen/go/v1 relay) → yours: the first delta captures the correct id/name, later "no update" frames send
The refinement:
|
|
Thanks for the detail. I've updated the local patch to truthy guards on both fields and re-verified the tool flow. Will post the silent-success (completed + exit 0) issue as its own thread. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
dsh 0.1.1-rc.2, Windows 11, @deepseek-ai/dsh-llm-deepseek.
Any task that needs a tool call fails: the agent emits tool/call with an empty name, the harness answers ToolNotFoundError (UNKNOWN_TOOL), and it loops the same call until it gives up. The final turn still reports reason.kind = "completed", so headless exits 0 with no output — looks like success.
Root cause is in dsh-llm-deepseek/lib/index.js (lines ~1063-1064):
With streamed deltas, the first chunk carries the correct id/name, and later chunks carry "id": null / "name": null (the OpenAI streaming convention for "no update"). Those pass the !== void 0 check and overwrite the real values; closeBlock then resolves name ?? "" to "".
Verified on a capture: the upstream response contains "name":"pwsh" correctly; the merged block ends up {"type":"tool-call","id":"","name":"","arguments":"..."}.
Fix (tested locally):
Only check for string, ignore null/undefined.
All reactions