Bug: empty tool-call id/name wipe in llm-deepseek makes session history unloadable #2674
Replies: 1 comment
|
Your diagnosis of the translate-layer overwrite matches what we measured from the outside — adding two datapoints that may help scope the fix: The other accumulator in this ecosystem is structurally immune to exactly this input. We fault-injected the real pi-ai openai-completions accumulator (client/SSE parser/assembly unmodified, only wire bytes synthetic) with the exact shapes you describe — later deltas of the same index carrying Live confirmation the id-carrying path works end to end on real api.deepseek.com via the pi-ai route: a multi-tool-call turn with distinct non-empty call ids and a fully parseable/reloadable history ( Related report with the same root shape, for cross-linking: #3090. Scope honesty: neither datapoint fixes |
Uh oh!
There was an error while loading. Please reload this page.
Summary
DeepSeek official API SSE streams repeat
id: ""/name: nullon latertool_callsdeltas of the same index (argument-only fragments).llm-deepseek's translate layer unconditionally overwrites the valid id/name captured from the first delta, so the assembled tool-call block ends up with empty id/name.The empty-name call is then dispatched as
unknown tool "", and thetool/resultis persisted with an emptycallId. On reload the session validator requires a non-emptycallIdfortool/result, so the whole session history fails to load:Reproduced on deepseek-v4-flash via provider
deepseek-official.Fix (available on fork)
Since external PRs are not accepted at the moment, the fix is committed to a fork:
Changes:
packages/llm/llm-deepseek/src/translate.ts— adopt only non-empty id/name; degenerate follow-up deltas no longer wipe valid valuespackages/llm/llm/src/assembler.ts— same sticky-id guard (defense for any adapter)packages/core/agent-loop/src/tool-calls.ts— synthesizecall-synthetic-Nfor empty-id blocks so tool/call and tool/result stay correlated and sessions stay reloadableRegression tests added in translate.spec.ts / assembler.spec.ts / loop.spec.ts — 101 tests pass.
Happy to rebase or adjust anything if the team wants to cherry-pick.
All reactions