Skip to content

fix(executor): honor explicit-zero Claude stream usage fields - #5832

Open
rome-xi wants to merge 1 commit into
router-for-me:devfrom
rome-xi:fix/claude-stream-usage-presence
Open

rome-xi wants to merge 1 commit into
router-for-me:devfrom
rome-xi:fix/claude-stream-usage-presence

Conversation

@rome-xi

@rome-xi rome-xi commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Problem

Claude stream usage is accumulated across message_start and later message_delta events. Parsing used gjson.Int(), which maps both a missing field and an explicit 0 to zero. The shared stream merge then kept any prior positive value whenever the update was 0.

A full cache hit therefore billed incorrectly: message_start can report positive input_tokens / cache-creation, then the final message_delta reports input_tokens: 0 (and often cache_creation_input_tokens: 0) with the real cache_read_input_tokens and output_tokens. The start input was kept, so uncached input and cache-hit rate were wrong.

Omitted-only deltas such as {"output_tokens": 15} must still preserve start input and cache fields.

Fix

Claude metering now tracks field presence (Exists() && Type != Null) and merges on that basis:

  • field present, including explicit 0 → overwrite
  • field missing or JSON null → keep prior

This is scoped to the Claude executor/plugin observe path (ParseClaudeStreamUsage / parseClaudeUsageNode / ObserveClaudeStream / parseClaudeStreamLine). MergeStreamUsageDetail is unchanged for OpenAI and other protocols that still keep prior values on zero.

Tests

  • full cache hit: positive start input/cache, then message_delta with explicit zeros → final detail has input=0, reported cache read, reported output
  • missing input_tokens preserves start
  • input_tokens: null preserves start
  • later SSE line with no usage preserves prior
  • late positive input_tokens replaces start
  • plugin Claude stream path has the same explicit-zero overwrite
go test ./internal/runtime/executor/helps/ -count=1

Claude stream metering treated missing usage fields and explicit zeros the
same (gjson Int() → 0), then MergeStreamUsageDetail kept prior positives.
A final message_delta with input_tokens:0 after a positive message_start
therefore under-counted cache hits.

Parse Claude usage with field presence (Exists && Type != Null) and merge
only present fields so explicit zeros overwrite while omitted/null keep
prior values. Leave OpenAI MergeStreamUsageDetail keep-prior-on-zero
unchanged.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 14, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-14T13:45:28.568297Z 80cda53 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

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