Replies: 1 comment
|
Confirmation from a second, independent harness: this defect is not specific to We added your shape to our wire-conformance battery (fault injection into the unmodified pi-ai client/parser/accumulator): two complete tool calls arriving under the same Filed upstream with a proposed fix (a delta whose non-empty So both accumulators in the ecosystem currently lose data on index reuse, in the same direction — worth fixing with the same id-over-index rule on both sides, and your mechanical proof plus ours make a matched pair of regression fixtures. |
Uh oh!
There was an error while loading. Please reload this page.
Package:
@deepseek-ai/dsh-llm-deepseek(src/translate.ts)Severity: high · Confidence: high — mechanically proven against the real parser with synthetic provider bytes
Problem
Streaming tool-call deltas are keyed solely by the provider-sent
index, with no duplicate detection, no id-change alarm, and no name-stability check:Two logical calls sharing a wire index merge into ONE block: fragments concatenate, and the last fragment's
id/namewin. The other call vanishes entirely.Proven outcome
Feeding two interleaved calls both at
index: 0—read_file({"path":"/etc/pa…then…sswd"}})under namedelete_file, idcall_BBB— produces exactly one assembled call:Valid JSON pointing at
/etc/passwd. The harness executesdelete_file("/etc/passwd"); nothing the model called survives. Control cases (distinct indices, out-of-order arrival) assemble correctly, isolating the defect to index collision.Trigger
Any buggy OpenAI-compatible gateway on the supported custom
baseURLthat reuses indices (a historically recurring bug class), or a hostile gateway. The harness is the confused deputy that turns a gateway bug into wrong-tool execution with attacker-shaped arguments.Fix direction
At the JSON.parse boundary: reject or split on index reuse once a block has an id/name (id change ⇒ new logical call or hard error), require non-empty stable identity, and fail loud instead of concatenating.
All reactions