Skip to content

fix: count OpenCode cache-read tokens in usage totals - #21457

Closed
innocarpe wants to merge 2 commits into
stablyai:mainfrom
innocarpe:fix/opencode-cache-read-tokens
Closed

innocarpe wants to merge 2 commits into
stablyai:mainfrom
innocarpe:fix/opencode-cache-read-tokens

Conversation

@innocarpe

Copy link
Copy Markdown
Contributor

Description

OpenCode usage totals now include tokens_cache_read instead of capping cache reads at input tokens and omitting them from totalTokens. Existing caches rescan after a schema bump.

Focused fix

  • In scope: parse/session-row totals, cachedInputTokens without the input cap, and OPENCODE_USAGE_SCHEMA_VERSION 2 → 3.
  • Out of scope: free-model estimatedCostUsd: null display, Claude/Codex readers, and usage-card UI redesign.

Preserves

  • Input, output, and reasoning stay as reported.
  • Cost/estimatedCostUsd is unchanged; null free-model cost is not invented.
  • If a provider tokens.total already includes cache reads, they are not double-counted.

Evidence

  • Test: pnpm exec vitest run --config config/vitest.config.ts src/main/opencode-usage/scanner.test.ts src/main/opencode-usage/store.test.ts src/main/opencode-usage/scanner-windows-data-directory.test.ts (24 tests)
  • Changed-code quality against upstream/main passed.

User-regression-tradeoffs

  • Headline OpenCode token counts will jump on cache-heavy workloads (that is the bug). Persisted orca-opencode-usage.json v2 files are discarded and rescanned.

Fixes #21440

@coderabbitai

coderabbitai Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Warning

Review limit reached

Next included review available in 11 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: bbcf680a-ca43-4077-997a-9daac4353189

📥 Commits

Reviewing files that changed from the base of the PR and between 793989ed75eeeff279f8278cdc7e9b042ac161ab and 8d6892d.

📒 Files selected for processing (2)
  • src/main/opencode-usage/persisted-state-normalization.ts
  • src/main/opencode-usage/store.test.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 83396015-5b8f-49ad-b3f0-025141a62314

📥 Commits

Reviewing files that changed from the base of the PR and between 47d107c and 793989ed75eeeff279f8278cdc7e9b042ac161ab.

📒 Files selected for processing (5)
  • src/main/opencode-usage/opencode-usage-provider.ts
  • src/main/opencode-usage/opencode-usage-row-parsing.ts
  • src/main/opencode-usage/opencode-usage-row-queries.ts
  • src/main/opencode-usage/scanner.test.ts
  • src/main/opencode-usage/store.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

OpenCode usage parsing now preserves the raw cache.read value and includes it in totalTokens. Session-level serialized totals also include cache-read tokens. The schema version increases from 2 to 3 so existing data is rescanned. Tests cover cache-heavy sessions, totals that already include cache reads, materialized aggregates, and persisted-state normalization.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 79398

Cache-read tokens are included in OpenCode totals and older cached usage is rescanned. No actionable current-head risk remains.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the fix, scope, rationale, linked issue, regression trade-off, and automated test command. However, it does not follow the required template and omits several required section… Reformat the description using the repository template. Add the missing required sections, provide an explicit Visual Proof N/A with a reason, document manual testing and supported platforms, complete the testing and checklist items, and in…
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: counting OpenCode cache-read tokens in usage totals.
Linked Issues check ✅ Passed The changes satisfy #21440. opencode-usage-row-queries.ts adds tokens_cache_read to materialized totals. parseOpenCodeUsageRow preserves uncapped cache reads and uses `Math.max(reportedTotal, pa…
Out of Scope Changes check ✅ Passed The changed production files implement the linked usage-total and cache-rescan objectives. The test changes verify those objectives. No unrelated reader, UI, cost, or provider changes are present in t…
Full details: Description check

Explanation

The description explains the fix, scope, rationale, linked issue, regression trade-off, and automated test command. However, it does not follow the required template and omits several required sections, including ELI5, What Changed, Why, Visual Proof with an explicit N/A, Testing checkboxes and platform details, AI Disclosure, Review, Agent skill upstream boundary, Notes, and Checklist.

Resolution

Reformat the description using the repository template. Add the missing required sections, provide an explicit Visual Proof N/A with a reason, document manual testing and supported platforms, complete the testing and checklist items, and include the required cross-platform, SSH, compatibility, security, and performance notes.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

The 2 → 3 schema bump invalidates the cache but also resets scanState.enabled to false, silently turning OpenCode usage tracking off for every existing user who had it on. Details inline.

Reviewed changes

  • Cache-read tokens counted in totals — opencode-usage-row-parsing.ts drops the Math.min(cache.read, inputTokens) cap and sets totalTokens = Math.max(reportedTotal, partsTotal), where partsTotal includes cache.read.
  • Session-table path includes cache reads — opencode-usage-row-queries.ts adds tokens_cache_read to the materialized total it feeds the parser.
  • Schema bump — OPENCODE_USAGE_SCHEMA_VERSION 2 → 3 so v2 caches are discarded and rescanned.
  • Tests — parser and database totals updated for the new arithmetic; store test now uses the schema constant and pins mismatch normalization.

I verified the underlying model against OpenCode's current source: persisted tokens.input is the non-cached input count (cache read/write are subtracted out), so cache.read is disjoint and adding it is correct; tokens.total already includes cache when present, which Math.max guards. Tests pass locally (24).

ℹ️ Nitpicks

  • tokens_cache_write is still dropped (write: 0 in the session-row query and not added to partsTotal), so totalTokens understates by the cache-write amount whenever tokens.total is absent. Issue #21440 called this out; fine to defer, but worth a follow-up if the card is meant to reflect true volume.
  • The new "does not double-count cache.read when tokens.total already includes it" test cannot fail under the current data model: its fixture has partsTotal === reportedTotal (1000 + 250 + 100 + 400 = 1750), so an implementation that ignores reportedTotal entirely still passes. It only rejects reportedTotal + cachedInputTokens.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Stop capping cache.read at inputTokens, include cache reads in
totalTokens, and bump the usage schema so existing caches rescan.
Schema mismatches still discard cached analytics, but scanState.enabled
now survives like the Claude and Codex normalizers so existing tracking
stays on after upgrade.
@innocarpe
innocarpe force-pushed the fix/opencode-cache-read-tokens branch from 793989e to 8d6892d Compare September 18, 2026 13:19

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

The follow-up commit resolves the prior review finding by preserving the persisted OpenCode tracking flag across the v3 schema bump.

  • Preserved scanState.enabled on schema mismatch — persisted-state-normalization.ts now returns the default state with enabled carried over from the stale state instead of resetting it to false, matching the Claude and Codex normalizers.
  • Regression test — store.test.ts seeds a stale state with enabled: true and asserts it survives normalization; the assertion fails against the previous wholesale getDefaultState() reset.

The change is correct and the existing tests pass (24). The two previously raised nitpicks (tokens_cache_write omission and the non-falsifiable double-count test) remain author-scoped out and unchanged by this delta.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@nwparker

Copy link
Copy Markdown
Contributor

This implementation is superseded by #21886, which covers both cache-read and cache-write counters, write-only sessions, and older databases without tokens_cache_write. #21886 is based on current main and addresses the conflicting/stale branch here.

@nwparker

Copy link
Copy Markdown
Contributor

Closing as superseded by #21886, which includes the cache-write compatibility and regression coverage.

@nwparker nwparker closed this Sep 21, 2026
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.

OpenCode usage reader omits cache-read tokens; reports ~2% of actual volume (schemaVersion 2 vs Claude's 6)

2 participants