Skip to content

fix(workers-ai-provider): don't duplicate streaming text on dual-format chunks - #615

Open
carlos-rsalazar wants to merge 1 commit into
cloudflare:mainfrom
carlos-rsalazar:fix/workers-ai-provider-streaming-double-text
Open

fix(workers-ai-provider): don't duplicate streaming text on dual-format chunks#615
carlos-rsalazar wants to merge 1 commit into
cloudflare:mainfrom
carlos-rsalazar:fix/workers-ai-provider-streaming-double-text

Conversation

@carlos-rsalazar

Copy link
Copy Markdown

Problem

Workers AI's OpenAI-compatible streaming emits both the native top-level response field and choices[0].delta.content in the same SSE chunk, with identical content (observed with @cf/meta/llama-3.3-70b-instruct-fp8-fast).

In streaming.ts, getMappedStream() handles the two formats in two independent if blocks (native response ~L168, OpenAI choices[0].delta.content ~L224), each enqueue-ing a text-delta. When a chunk carries both, every token is emitted twice, so streamed output is doubled and the doubled text is what consumers persist/render:

"Hello world"  ->  "HelloHello world world"

This reproduces reliably for any model whose streaming response includes both fields.

Fix

Treat the native and OpenAI text fields as mutually exclusive: use choices[0].delta.content only when the native response field is absent for that chunk (they're redundant duplicates when both present). One-line behavioral change plus a comment.

Test

Adds a regression test in stream-text.test.ts that streams a chunk carrying both response and choices[].delta.content:

  • Before the fix it fails with Received: "Hello Hello worldworld".
  • After the fix it passes ("Hello world").

Full workers-ai-provider suite green (455 tests). Formatted with oxfmt, lint-clean.

Changeset

patch for workers-ai-provider.


Found while integrating workers-ai-provider into a Cloudflare-Workers app; happy to adjust the approach if you'd prefer the guard on the native branch instead.

…at chunks

Workers AI's OpenAI-compatible streaming emits BOTH the native top-level `response`
field AND `choices[0].delta.content` in the same SSE chunk, with identical content
(e.g. @cf/meta/llama-3.3-70b-instruct-fp8-fast). getMappedStream() emits a text-delta
for each in two independent if-blocks, so every token is duplicated
("Hello world" -> "HelloHello world world") — and the doubled text is what consumers
persist/render.

Treat the two as mutually exclusive: use choices[0].delta.content only when the native
`response` field is absent for that chunk. Adds a regression test (fails before, passes
after) and a changeset.
@changeset-bot

changeset-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 27c1331

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
workers-ai-provider Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

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