Conversation
…ng in StreamUsageWrapper The rolling buffer approach could truncate large SSE events (like the Responses API's final event containing the full response object + usage). Switch to incremental parsing that processes complete events on each \n\n boundary, caching usage data as it's found. Also adds usage field to mock provider's streaming response.done event and new tests for Responses API format, large events, and fragmented reads. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… in /v1/responses OpenAI's Responses API sends response.completed (not response.done) as the final event. Our wrappers and converters now emit/accept the correct type, fixing silent usage tracking failures for native OpenAI streaming. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review infoConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughRenames the streaming completion event from "response.done" to "response.completed" across providers and tests, and refactors stream usage extraction to incremental SSE parsing with buffered event processing and safer remainder bounds. Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
internal/providers/xai/xai_test.go (1)
649-671: 🧹 Nitpick | 🔵 Trivial
checkStreamdoesn't assert theresponse.completedevent it is testing.The mock response body at Lines 643–644 now emits
response.completed, but thecheckStreamclosure only assertsresponse.created,response.output_text.delta, and[DONE]. Adding a check forresponse.completedmakes the test actually verify the renamed event survives the passthrough.✅ Suggested addition
if !strings.Contains(responseStr, "[DONE]") { t.Error("response should end with [DONE]") } +if !strings.Contains(responseStr, "response.completed") { + t.Error("response should contain response.completed event") +}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/providers/xai/xai_test.go` around lines 649 - 671, The test's checkStream closure (checkStream func(t *testing.T, body io.ReadCloser)) currently asserts response.created, response.output_text.delta and [DONE] but omits verifying the response.completed event; update the closure to also assert that the streamed response contains "response.completed" (e.g., add an if !strings.Contains(responseStr, "response.completed") { t.Error("response should contain response.completed event") }) so the test confirms the renamed event passes through.internal/providers/groq/groq_test.go (1)
580-590: 🧹 Nitpick | 🔵 Trivial
TestStreamResponsesmissing assertion forresponse.completed.
TestStreamResponsesverifiesresponse.createdandresponse.output_text.deltabut does not assertresponse.completed, leaving the final event untested here.TestGroqResponsesStreamConvertercovers this via the converter directly, butTestStreamResponsesexercises the fullStreamResponses→ converter path and should assert the same terminal event for full regression coverage.✅ Suggested addition
if !strings.Contains(responseStr, "[DONE]") { t.Error("response should end with [DONE]") } +if !strings.Contains(responseStr, "response.completed") { + t.Error("response should contain response.completed event") +}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/providers/groq/groq_test.go` around lines 580 - 590, Add an assertion in TestStreamResponses to check that the streaming output includes the terminal "response.completed" event: after the existing checks on responseStr (which currently asserts "response.created", "response.output_text.delta", and "[DONE]"), add a strings.Contains check for "response.completed" and call t.Error (or t.Fatalf) if it's missing so the full StreamResponses → TestGroqResponsesStreamConverter path verifies the terminal event as well.internal/providers/ollama/ollama_test.go (1)
640-650: 🧹 Nitpick | 🔵 Trivial
TestStreamResponsesmissing assertion forresponse.completed.Same gap as
groq/groq_test.go:TestStreamResponsesverifiesresponse.createdandresponse.output_text.deltabut omits a check forresponse.completed, leaving the final event untested on the fullStreamResponsespath.✅ Suggested addition
if !strings.Contains(responseStr, "[DONE]") { t.Error("response should end with [DONE]") } +if !strings.Contains(responseStr, "response.completed") { + t.Error("response should contain response.completed event") +}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/providers/ollama/ollama_test.go` around lines 640 - 650, Add an assertion in TestStreamResponses to verify the final "response.completed" event is present: after converting respBody to responseStr (variable responseStr) add a check using strings.Contains(responseStr, "response.completed") and call t.Error with a descriptive message if it's missing, mirroring the existing checks for "response.created" and "response.output_text.delta" to ensure the full StreamResponses path emits the completed event.internal/providers/openai/openai_test.go (1)
624-651:⚠️ Potential issue | 🟡 MinorAssert
response.completedexplicitly in stream validation.The fixture now uses
response.completed(Line 624), butcheckStreamdoesn’t assert it. This can let final-event regressions slip through.Proposed assertion update
if !strings.Contains(responseStr, "response.output_text.delta") { t.Error("response should contain response.output_text.delta event") } + if !strings.Contains(responseStr, "response.completed") { + t.Error("response should contain response.completed event") + } if !strings.Contains(responseStr, "[DONE]") { t.Error("response should end with [DONE]") }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/providers/openai/openai_test.go` around lines 624 - 651, The test's stream validator (the checkStream closure in the test case) currently asserts for "response.created", "response.output_text.delta", and "[DONE]" but doesn't assert the new "response.completed" event; update the checkStream function used in internal/providers/openai/openai_test.go to also verify that the response body string contains "response.completed" (e.g., add an assertion that checks strings.Contains(responseStr, "response.completed") and fails the test if it's missing) alongside the existing assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@internal/usage/stream_wrapper.go`:
- Around line 68-70: The current logic uses w.eventBuffer.Reset() when
w.eventBuffer.Len() > maxEventBufferRemainder which silently drops in-flight
events (including a large response.completed). Instead of Reset(), trim the
buffer to keep only the newest maxEventBufferRemainder bytes: read b :=
w.eventBuffer.Bytes(), compute start := max(0, len(b)-maxEventBufferRemainder),
create a new bytes.Buffer (or reuse w.eventBuffer by Reset then Write) and write
b[start:], and assign that back to w.eventBuffer; apply this change at the spots
referencing w.eventBuffer and maxEventBufferRemainder (the branches currently
calling w.eventBuffer.Reset()) so partial events are preserved rather than
discarded.
---
Outside diff comments:
In `@internal/providers/groq/groq_test.go`:
- Around line 580-590: Add an assertion in TestStreamResponses to check that the
streaming output includes the terminal "response.completed" event: after the
existing checks on responseStr (which currently asserts "response.created",
"response.output_text.delta", and "[DONE]"), add a strings.Contains check for
"response.completed" and call t.Error (or t.Fatalf) if it's missing so the full
StreamResponses → TestGroqResponsesStreamConverter path verifies the terminal
event as well.
In `@internal/providers/ollama/ollama_test.go`:
- Around line 640-650: Add an assertion in TestStreamResponses to verify the
final "response.completed" event is present: after converting respBody to
responseStr (variable responseStr) add a check using
strings.Contains(responseStr, "response.completed") and call t.Error with a
descriptive message if it's missing, mirroring the existing checks for
"response.created" and "response.output_text.delta" to ensure the full
StreamResponses path emits the completed event.
In `@internal/providers/openai/openai_test.go`:
- Around line 624-651: The test's stream validator (the checkStream closure in
the test case) currently asserts for "response.created",
"response.output_text.delta", and "[DONE]" but doesn't assert the new
"response.completed" event; update the checkStream function used in
internal/providers/openai/openai_test.go to also verify that the response body
string contains "response.completed" (e.g., add an assertion that checks
strings.Contains(responseStr, "response.completed") and fails the test if it's
missing) alongside the existing assertions.
In `@internal/providers/xai/xai_test.go`:
- Around line 649-671: The test's checkStream closure (checkStream func(t
*testing.T, body io.ReadCloser)) currently asserts response.created,
response.output_text.delta and [DONE] but omits verifying the response.completed
event; update the closure to also assert that the streamed response contains
"response.completed" (e.g., add an if !strings.Contains(responseStr,
"response.completed") { t.Error("response should contain response.completed
event") }) so the test confirms the renamed event passes through.
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (15)
internal/auditlog/stream_wrapper.gointernal/providers/anthropic/anthropic.gointernal/providers/groq/groq_test.gointernal/providers/ollama/ollama_test.gointernal/providers/openai/openai_test.gointernal/providers/responses_converter.gointernal/providers/xai/xai_test.gointernal/server/handlers_test.gointernal/usage/constants.gointernal/usage/stream_wrapper.gointernal/usage/stream_wrapper_test.gotests/e2e/helpers_test.gotests/e2e/mock_provider.gotests/e2e/responses_test.gotests/integration/setup_test.go
💤 Files with no reviewable changes (1)
- internal/usage/constants.go
When the SSE event buffer exceeds maxEventBufferRemainder, keep the newest bytes rather than resetting entirely. This preserves the tail of in-flight partial events (where usage data in JSON is most likely found) instead of silently dropping them. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary by CodeRabbit
Breaking Changes
Improvements