Skip to content

fix(streaming): record Responses terminal usage instead of zero tokens - #165

Merged
samueltuyizere merged 1 commit into
routatic:mainfrom
alecchen:fix/streaming-responses-usage-tokens
Sep 3, 2026
Merged

fix(streaming): record Responses terminal usage instead of zero tokens#165
samueltuyizere merged 1 commit into
routatic:mainfrom
alecchen:fix/streaming-responses-usage-tokens

Conversation

@alecchen

@alecchen alecchen commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Bug

Streaming spark requests logged and stored 0/0 tokens. The opencode dashboard showed real usage for the same calls.

Why

The Responses streaming path dropped upstream usage. ProxyResponsesStream (internal/transformer/stream.go) built the terminal Anthropic message_delta with usage hardcoded to zero, and processResponsesSSELine never handled response.completed, which is where upstream puts usage. extractUsageFromSSE (internal/handlers/messages.go) only reads message_delta chunks, so the log and history both got the hardcoded zeros. Chat streaming and non-streaming Responses read usage fine. This path was the only one that did not.

Fix

Read the terminal event and pass its usage through:

  • pkg/types/zen.go: ResponsesChunk now decodes the nested response.usage shape alongside the flat one.
  • internal/transformer/stream.go: stash usage from response.completed (flat first, nested second, last one wins) and emit it in the terminal message_delta through responsesUsageToAnthropic. A stream with no usage event still records 0.
  • Both callers (handleResponsesStreaming, StreamProxy.ProxyStream) share ProxyResponsesStream, so one change fixes both.

Validation

  • go test ./internal/transformer/ -run TestProxyResponsesStream: 8 passed (5 existing, 3 new covering flat, nested, and missing usage).
  • go test ./... green; gofmt, go vet clean.
  • Live: streaming spark call now shows nonzero tokens in the log and /api/history. Other models unaffected.

ProxyResponsesStream hardcoded the terminal message_delta usage to 0/0
and processResponsesSSELine never read response.completed, so wire_format
responses models (muse-spark) logged and stored 0 input/output tokens on
every streaming request. Capture flat or nested response.usage from the
terminal event into the Anthropic message_delta; missing usage keeps 0.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@alecchen
alecchen force-pushed the fix/streaming-responses-usage-tokens branch from 48bb601 to 6e1ef5b Compare September 3, 2026 12:31
@alecchen
alecchen marked this pull request as ready for review September 3, 2026 12:35
@kilo-code-bot

kilo-code-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Code Review Roast 🔥

Verdict: 1 Issue Found | Recommendation: Add CHANGELOG entry, then merge

Overview

Severity Count
🚨 critical 0
⚠️ warning 0
💡 suggestion 1
🤏 nitpick 0
Issue Details (click to expand)
File Line Roast
CHANGELOG.md 10-16 You fixed a bug that makes spark model tokens actually show up in logs and /api/history instead of 0/0, but forgot to tell the CHANGELOG about it under [Unreleased] > ### Fixed. The git history isn't going to write itself, and future humans debugging this will want to know when the great token-reveal happened.

🏆 Best part: The author actually wrote tests for the bug they fixed — three of them covering flat nested, and missing usage on response.completed. I need to sit down. Not only that, but they verified existing tests (which already include bare response.completed lines) still pass, confirming the new handler is a clean no-op when no usage data is present.

💀 Worst part: The CHANGELOG got ghosted. You fixed a user-facing bug that changes what users see in their logs and dashboard, but left the changelog entry field blank. That's the kind of omission that turns a 5-minute blame search into a 3am rabbit hole.

📊 Overall: Like a surgeon's precision on a papercut — the fix is clean, tested, and correct, routing both flat and nested response.usage shapes through the terminal message_delta via responsesUsageToAnthropic, but don't forget to document it for posterity.

Files Reviewed (3 files)
  • pkg/types/zen.go - 0 issues (new ResponsesResult type and Response field on ResponsesChunk, properly documented)
  • internal/transformer/stream.go - 0 issues (new responsesUsageToAnthropic helper, response.completed capture in processResponsesSSELine, terminal message_delta usage wired up)
  • internal/transformer/stream_test.go - 0 issues (3 new tests covering flat nested, and missing usage scenarios)

Reviewed by free · Input: 236.5K · Output: 35.7K · Cached: 820.4K

Review guidance: REVIEW.md from base branch main (truncated)

@samueltuyizere
samueltuyizere merged commit 722ff60 into routatic:main Sep 3, 2026
4 checks passed
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