Skip to content

fix(ai-gateway): make SSE rewriting stream-safe#3817

Open
catrielmuller wants to merge 2 commits into
mainfrom
catrielmuller/improve-sse-rewrite
Open

fix(ai-gateway): make SSE rewriting stream-safe#3817
catrielmuller wants to merge 2 commits into
mainfrom
catrielmuller/improve-sse-rewrite

Conversation

@catrielmuller

Copy link
Copy Markdown
Contributor

Summary

  • Refactor free-model SSE rewriting into a backpressure-aware byte stream shared by chat, messages, and responses APIs.
  • Preserve split UTF-8 input, final unterminated events, event IDs, cancellation, and upstream errors while preventing proxy transformation of event streams.
  • Clone responses inside metrics and request-logging helpers so concurrent background drains do not disturb the client response.

Verification

  • Not manually tested; the change targets low-level Response stream behavior exercised in isolation.

Visual Changes

N/A

Reviewer Notes

Focus on stream cancellation/error propagation and response-clone timing around usage, metrics, and request logging.

Comment thread apps/web/src/lib/rewriteModelResponse.ts Outdated
Comment thread apps/web/src/lib/rewriteModelResponse.ts Outdated
@kilo-code-bot

kilo-code-bot Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The new commit (add112a6) addresses both previously reported issues: the backpressure violation (multiple enqueues per pull()) and the redundant outputController closure variable. The refactored pull() loop now correctly dequeues exactly one chunk per invocation and uses the controller parameter directly.

Previously Reported Issues — All Resolved
File Line Issue Status
apps/web/src/lib/rewriteModelResponse.ts WARNING: Backpressure bypass — multiple events enqueued per pull() ✅ Fixed
apps/web/src/lib/rewriteModelResponse.ts SUGGESTION: outputController closure variable redundant alongside controller param ✅ Fixed
Other Observations (pre-existing, not introduced by this PR)

captureProxyError still clones inside after() (apps/web/src/lib/ai-gateway/llm-proxy-helpers.ts:363): response.clone() is called inside an after() callback. For error responses the body is typically small and non-streaming, so this rarely causes an issue in practice — but a streaming error body could silently fail. Pre-existing and unchanged by this PR.

Test coverage for _ChatCompletions and _Messages streaming paths: The createRewrittenSseStream shared helper is exercised by the _Responses tests, but stream-specific rewrites in the other two variants lack parallel integration tests for UTF-8 chunking, cancellation, error propagation, and final-event flush. Pre-existing and unchanged.

Files Reviewed (8 files)
  • apps/web/src/app/api/openrouter/[...path]/route.ts — no issues
  • apps/web/src/app/api/openrouter/audio/transcriptions/route.ts — no issues
  • apps/web/src/app/api/openrouter/embeddings/route.ts — no issues
  • apps/web/src/lib/ai-gateway/handleRequestLogging.ts — no issues
  • apps/web/src/lib/ai-gateway/llm-proxy-helpers.ts — no issues
  • apps/web/src/lib/ai-gateway/o11y/api-metrics.server.ts — no issues
  • apps/web/src/lib/rewriteModelResponse.ts — 0 issues (2 previously reported issues resolved)
  • apps/web/src/lib/rewriteModelResponse.test.ts — no issues

Fix these issues in Kilo Cloud


Reviewed by claude-4.6-sonnet-20260217 · 339,177 tokens

Review guidance: REVIEW.md from base branch main

@catrielmuller catrielmuller requested a review from chrarnoldus June 8, 2026 21:10
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