Skip to content

fix(chat-bridge): keep index-less streamed tool-call fragments in one block - #264

Open
dex0shubham wants to merge 1 commit into
teamchong:mainfrom
dex0shubham:fix/chat-bridge-toolcall-index
Open

fix(chat-bridge): keep index-less streamed tool-call fragments in one block#264
dex0shubham wants to merge 1 commit into
teamchong:mainfrom
dex0shubham:fix/chat-bridge-toolcall-index

Conversation

@dex0shubham

@dex0shubham dex0shubham commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

The Chat Completions SSE translator (chatStreamEvent in messages-chat-bridge.ts) keyed streamed tool-call deltas by:

const key = typeof tc.index === 'number' ? tc.index : state.calls.size;

Some OpenAI-compatible upstreams — the arbitrary providers this bridge exists to support (Cloudflare Workers AI, Kimi, etc.) — omit index on tool-call deltas and split a single call's arguments across chunks. With index absent, each continuation fragment was keyed by the growing calls.size, so calls.get(key) missed and a new tool_use block was opened per fragment.

Result for a two-chunk {"q": + "cats"} call: a first block with truncated, invalid JSON plus a spurious second block with an empty name and duplicate id — instead of one tool_use with {"q":"cats"}. The entire streamed-tool-call branch was untested.

Fix

Disambiguate the way the OpenAI stream shape already signals it: a delta carrying an id or name opens a new call; an args-only delta continues the most recent call (tracked via a new lastToolKey on the stream state). Strictly-conformant streams that always send index take the unchanged path.

Added a streaming regression test (index-less, split-arguments) — it opens two blocks on the old code and one on the fix.

Full suite green (1207/1207); typecheck clean.

… block

The Chat Completions SSE translator keyed tool-call deltas by
`tc.index ?? state.calls.size`. Some OpenAI-compatible providers (the exact
upstreams this bridge targets) omit `index` on continuation deltas and split
a tool call's arguments across chunks. With `index` absent, each continuation
fragment was keyed by the growing map size and opened a brand-new tool_use
block, so Claude Code saw a truncated first block plus a spurious empty-named
duplicate instead of one call.

Disambiguate the way the OpenAI stream shape does: a delta carrying an id or
name opens a new call; an args-only delta continues the most recent one
(tracked via lastToolKey). Conformant streams that always send `index` are
unaffected.
@dex0shubham
dex0shubham force-pushed the fix/chat-bridge-toolcall-index branch from 57059c1 to daedc8f Compare September 2, 2026 07:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant