Skip to content

fix(dashboard): avoid double-counting cached input tokens - #424

Open
liaohch3 wants to merge 3 commits into
mainfrom
fix/codex-cache-token-total
Open

fix(dashboard): avoid double-counting cached input tokens#424
liaohch3 wants to merge 3 commits into
mainfrom
fix/codex-cache-token-total

Conversation

@liaohch3

@liaohch3 liaohch3 commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • prefer provider-reported usage.total_tokens so OpenAI Responses cached input is not counted twice
  • retain an additive input/output/cache fallback for Anthropic and providers that omit a total
  • rebuild stale dashboard summary caches from stored records under the corrected semantics

Fixes #423.

Validation

  • uv run ruff check .
  • uv run ruff format --check .
  • uv run pytest tests/ -x --timeout=60 (1072 passed, 26 skipped)
  • uv lock --check
  • uv run python scripts/check_screenshots.py .agents/evidence/pr/issue-423-token-totals

Real E2E

  • Codex ran from the local branch through Sub2API using the Responses protocol and gpt-5.6-sol. The real 3-call trace reported 49,546 input, 236 output, 36,096 cached input, and 49,782 provider total.
  • Claude Code ran from the local branch through New API staging using openrouter/claude-haiku-4-5. It made three real /v1/messages calls, used the shell tool, returned ANTHROPIC_ISSUE423_OK 3, and the dashboard fallback totaled 4,261 input + 268 output = 4,529. New API logs confirmed token/model/channel attribution.
  • A reusable staging token named liaohaochun/claude-tap/issue-423 is retained for the owner as token chore: update changelog for v0.1.61 #165 with a non-unlimited 50,000,000 quota (the configured $100 limit) and all models enabled. The key is not included in this PR.

Before / After Evidence

The first image uses the same real Codex SQLite trace rendered by the base commit (v0.1.142): the old dashboard shows 85,878, which equals 49,782 + 36,096 and demonstrates the cache double-counting bug. The second image renders that same trace with this fix and shows the correct provider total 49,782. The third image is a separate real Claude Code/New API trace and shows the provider-compatible Anthropic fallback total 4,529.

Codex before fix: cached input double-counted

Codex after fix: provider total

Claude Code after fix: Anthropic fallback

Trace Detail Evidence

Codex trace detail

Use provider-reported token totals when available and rebuild stale dashboard summaries under the corrected semantics. Preserve Anthropic cache buckets as additive fallback fields when providers omit a total.

Co-authored-by: Talon <talon@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3d232af66d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread claude_tap/trace.py
Comment thread claude_tap/dashboard.py
liaohch3 and others added 2 commits August 12, 2026 12:43
Document the real Codex regression comparison and Claude Code provider fallback evidence in the pull request.

Co-authored-by: Talon <talon@users.noreply.github.com>
Co-authored-by: Talon <talon@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17236cb2b5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread claude_tap/live.py
offset = _session_offset_from_request(request)
limit = _session_limit_from_request(request)
query = _session_query_from_request(request)
repair_stale_session_summaries(query)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make stale-summary repair best-effort

When an upgraded dashboard has any matching stale summaries, this new call performs synchronous repair writes before /api/sessions can return; if the trace DB is opened read-only or another claude-tap process holds the .write.lock long enough for store_summary to raise sqlite3.OperationalError, the exception is not caught here and the whole sessions API returns 500 even though the aggregate/list reads could otherwise still be served from cached data. Consider catching repair failures or moving this to a best-effort/background path so stale-cache repair cannot break the dashboard page.

Useful? React with 👍 / 👎.

Comment thread claude_tap/usage.py
Comment on lines +62 to +64
reported = usage.get("total_tokens")
if isinstance(reported, int) and not isinstance(reported, bool) and reported >= 0:
return reported

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep Bedrock cache buckets in token totals

For AWS Bedrock Converse usage that includes totalTokens together with cacheReadInputTokens or cacheWriteInputTokens, returning the reported total here drops the cache buckets from dashboard summaries and aggregates. AWS defines totalTokens as input plus output, with cache read/write as separate fields, so a response like inputTokens=9, outputTokens=4, totalTokens=13, cacheReadInputTokens=3, cacheWriteInputTokens=2 now shows 13 instead of the previous 18; keep using the provider total only for providers whose cache is embedded, or add native cache buckets for Bedrock-style usage.

Useful? React with 👍 / 👎.

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.

bug: Codex session total_tokens double-counts cached input

1 participant