Skip to content

fix(proxy): preserve streaming tool identity for strict clients - #13

Open
guguguc wants to merge 1 commit into
emanuelcasco:mainfrom
guguguc:fix/tool-calls-null-id-name
Open

fix(proxy): preserve streaming tool identity for strict clients#13
guguguc wants to merge 1 commit into
emanuelcasco:mainfrom
guguguc:fix/tool-calls-null-id-name

Conversation

@guguguc

@guguguc guguguc commented Aug 23, 2026

Copy link
Copy Markdown

Problem

Streaming clients like @deepseek-ai/dsh failed to call tools when routed through the ocgo proxy (error: unknown tool "" / SSE stream ended without [DONE]).

The upstream OpenAI chat/completions stream emits id/name on the first tool_calls chunk, then "id":null,"name":null on subsequent argument deltas. Strict clients parse each delta with a !== undefined check and treat null as an override, wiping out the tool identity.

/v1/chat/completions is a pure passthrough (io.Copy) for non-Anthropic-endpoint models, so the nulls reached clients untouched.

Fix

  • Filter null/empty id and function.name fields out of tool_calls deltas while streaming (OpenAI spec only requires them on the first chunk).
  • Stream the passthrough explicitly instead of io.Copy, ensuring data: [DONE] is always forwarded (readSSE previously swallowed it, causing clients to wait for a terminator that never came).
  • Added unit tests covering null-stripping, value preservation, tool identity retention, and [DONE] forwarding.

Test plan

go test ./...

Verified by curling the proxy with a streaming tool-call request: the tool name is retained and the stream terminates with data: [DONE].

Upstream OpenAI chat completions streams can emit null id/name fields on
tool_calls argument deltas. Strict streaming clients (e.g. dsh) treat null
as an override and end up calling an empty tool name. Filter those fields
out while passing the stream through, keeping the tool identity set on the
first chunk.
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.

2 participants