Skip to content

Read OpenCode Go local token counts - #3995

Closed
Yuxin-Qiao wants to merge 1 commit into
steipete:mainfrom
Yuxin-Qiao:fix/opencodego-local-tokens
Closed

Yuxin-Qiao wants to merge 1 commit into
steipete:mainfrom
Yuxin-Qiao:fix/opencodego-local-tokens

Conversation

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor

Summary

The Spend dashboard's Token activity heatmap showed "Unavailable · Coverage 0 / 365" whenever OpenCode Go was an enabled source.

OpenCodeGoLocalUsageReader only selected cost from opencode.db and emitted every daily entry with totalTokens: nil, while the snapshot still declared established history coverage. The heatmap intentionally treats a scanned-but-unresolved source day as unknown, so OpenCode Go poisoned every day in its window, including days where other sources (Codex, Cursor, Antigravity) had complete token data.

OpenCode already persists per-message and per-step-finish token counts (tokens.input/output/reasoning/cache.read/cache.write/total), so this reads them:

  • select the tokens object alongside cost in both the message-only and message+part queries; step-finish part tokens replace message tokens exactly like cost does
  • derive total from the components for older rows that omit it
  • populate daily entries and per-model breakdowns with input/output/reasoning/cache/total tokens
  • keep a day's token total unknown (nil) if any contributing row lacks token data, so partial days never masquerade as complete totals

With every day resolved, last30DaysTokens matches the daily sum, the dashboard treats OpenCode Go history as complete, and days without OpenCode Go usage count as zero instead of unknown.

Tests

  • New OpenCodeGoLocalUsageReaderTests: per-day/per-model token totals (including rows without total), step-finish tokens replacing message tokens, and a tokenless row keeping the day unknown
  • New SpendActivityHeatmapTests regression: an OpenCode Go snapshot alongside another source keeps shared activity days covered
  • swift build --product CodexBarCLI
  • swiftformat --lint on changed files

I could not run swift test / make check locally (Command Line Tools only, no Xcode for actool/sourcekitd), so opening as draft to let CI run the suite.

Proof

Ran the new reader through a scratch executable against a synthetic fixture and, read-only, against a real local opencode.db (model names omitted):

== fixture: 2 day(s)
  2026-03-05 total=nil in=nil out=nil reasoning=nil cacheRead=nil cacheWrite=nil
  2026-03-06 total=1720 in=190 out=45 reasoning=31 cacheRead=1404 cacheWrite=50
  last30DaysTokens=nil daysMissingTokens=1
== local opencode.db: 8 day(s)
  2026-09-04 total=32188717 in=1142874 out=92629 reasoning=76149 cacheRead=30877065 cacheWrite=0
  2026-09-05 total=193225639 in=13805441 out=240889 reasoning=215214 cacheRead=178964095 cacheWrite=0
  2026-09-16 total=52116 in=14583 out=583 reasoning=1938 cacheRead=35012 cacheWrite=0
  ...
  last30DaysTokens=535086100 daysMissingTokens=0

Before this change every entry reported total=nil. No live provider probes or Keychain reads were run.

Co-authored-by: Cursor <cursoragent@cursor.com>
@clawsweeper

clawsweeper Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@Yuxin-Qiao
Yuxin-Qiao marked this pull request as ready for review September 25, 2026 16:47
@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Sep 25, 2026
@clawsweeper

clawsweeper Bot commented Sep 25, 2026

Copy link
Copy Markdown

Codex review: needs changes before merge. Reviewed September 25, 2026, 12:53 PM ET / 16:53 UTC.

ClawSweeper review

What this changes

The branch reads OpenCode Go token counts from local SQLite messages and step-finish records, adds them to daily and per-model spend history, and adds reader and heatmap tests.

Merge readiness

⛔ Needs changes before merge - 2 items remain

This PR addresses a real gap in OpenCode Go token history and includes a redacted run against a local database. One parsing edge still needs repair: an empty token object is reported as a measured zero, which can make incomplete history appear complete.

Priority: P2
Reviewed head: 003bc4187c537d083ab04a9ae2453c1495104e91

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) Real local-database output and focused tests support the main behavior, while the empty-object parsing defect limits merge confidence.
Proof confidence 🐚 platinum hermit (4/6) Sufficient (terminal): The contributor reports exercising the changed local reader through a scratch executable against a synthetic fixture and a real opencode.db, with redacted after-fix daily totals and a 30-day sum; this supports the normal token path but does not cover an empty token object. The diff changes read-only parsing, so stored-data compatibility is not applicable.
Patch quality 🦐 gold shrimp (3/6) 1 actionable review finding remain.

Verification

Check Result Evidence
Real behavior Verified Sufficient (terminal): The contributor reports exercising the changed local reader through a scratch executable against a synthetic fixture and a real opencode.db, with redacted after-fix daily totals and a 30-day sum; this supports the normal token path but does not cover an empty token object. The diff changes read-only parsing, so stored-data compatibility is not applicable.
Evidence reviewed 6 items Introduced token parsing: The patch accepts any JSON token object, substitutes zero for every absent component, and derives a zero total when the total is absent; a row with tokens: {} is therefore treated as complete.
Coverage consequence: The heatmap treats a scanned provider's non-nil daily token total as resolved, so a fabricated zero can be shown as covered history.
Existing product boundary: OpenCode Go's local strategy reads assistant records from opencode.db for device-local daily history; this PR extends that existing reader.
Findings 1 actionable finding [P2] Keep empty token objects unresolved
Security None None.

How this fits together

CodexBar reads OpenCode Go's local database to build daily usage snapshots. The Spend dashboard combines those snapshots with other providers to display token activity and coverage.

flowchart LR
A[OpenCode local database] --> B[Message and step records]
B --> C[Token reader]
C --> D[Daily usage snapshot]
D --> E[Spend dashboard]
E --> F[Token activity heatmap]
Loading

Before merge

  • Keep empty token objects unresolved (P2) - A cost-bearing row with tokens: {} passes hasTokens; every absent component becomes zero and the derived total becomes zero. That marks a day as covered even though the row contains no token count, contrary to the PR's incomplete-day rule. Require a numeric total or at least one valid numeric component, and add a fixture for this case.
  • Complete next step (P2) - Keep token objects without a valid count unresolved and add a regression test before merge.

Findings

  • [P2] Keep empty token objects unresolved — Sources/CodexBarCore/Providers/OpenCodeGo/OpenCodeGoLocalUsageReader.swift:145-155
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Code and test delta production +137/−17, tests +153/−3 The new parsing logic has focused tests, but the unknown-token case needs one more boundary fixture.

Technical review

Best possible solution:

Require an explicit numeric total or at least one valid numeric token component before marking a row resolved, and cover empty and malformed token objects with focused reader tests.

Do we have a high-confidence way to reproduce the issue?

Yes, from source: a cost-bearing row with tokens: {} passes the object check and becomes a zero-token day. The focused test fixture has not been run in this read-only review.

Is this the best way to solve the issue?

Yes, reading the existing local token fields is a narrow fit for the reported heatmap gap, provided unreadable token objects remain unknown.

Full review comments:

  • [P2] Keep empty token objects unresolved — Sources/CodexBarCore/Providers/OpenCodeGo/OpenCodeGoLocalUsageReader.swift:145-155
    A cost-bearing row with tokens: {} passes hasTokens; every absent component becomes zero and the derived total becomes zero. That marks a day as covered even though the row contains no token count, contrary to the PR's incomplete-day rule. Require a numeric total or at least one valid numeric component, and add a fixture for this case.
    Confidence: 0.96

Overall correctness: patch is incorrect
Overall confidence: 0.91

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against df5a637ac02e.

Labels

Label changes:

  • add P2: The PR repairs a limited OpenCode Go dashboard problem, with one bounded data-accuracy defect remaining.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The contributor reports exercising the changed local reader through a scratch executable against a synthetic fixture and a real opencode.db, with redacted after-fix daily totals and a 30-day sum; this supports the normal token path but does not cover an empty token object. The diff changes read-only parsing, so stored-data compatibility is not applicable.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The contributor reports exercising the changed local reader through a scratch executable against a synthetic fixture and a real opencode.db, with redacted after-fix daily totals and a 30-day sum; this supports the normal token path but does not cover an empty token object. The diff changes read-only parsing, so stored-data compatibility is not applicable.

Label justifications:

  • P2: The PR repairs a limited OpenCode Go dashboard problem, with one bounded data-accuracy defect remaining.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The contributor reports exercising the changed local reader through a scratch executable against a synthetic fixture and a real opencode.db, with redacted after-fix daily totals and a 30-day sum; this supports the normal token path but does not cover an empty token object. The diff changes read-only parsing, so stored-data compatibility is not applicable.
  • proof: sufficient: Contributor real behavior proof is sufficient. The contributor reports exercising the changed local reader through a scratch executable against a synthetic fixture and a real opencode.db, with redacted after-fix daily totals and a 30-day sum; this supports the normal token path but does not cover an empty token object. The diff changes read-only parsing, so stored-data compatibility is not applicable.

Evidence

Acceptance criteria:

  • [P1] swift test --filter OpenCodeGoLocalUsageReaderTests.
  • [P1] make test.
  • [P1] make check.

What I checked:

Likely related people:

  • kentoku24: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • Peter Steinberger: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • Yuxin Qiao: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Keep empty or malformed token objects unresolved and add a focused regression fixture.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@steipete

Copy link
Copy Markdown
Owner

Thanks @Yuxin-Qiao. Landed on main via #4000 and ships in the next release, with your changelog credit. The reader now keeps recorded token totals and components from the local OpenCode Go database, prefers step-finish parts, honors explicit totals, and sums older records only when all five components exist; missing, malformed, or overflowing totals stay unknown, and recorded costs and quota behavior are unchanged. Your two token-reading regressions fail on the old reader and pass after the change, and sharing the aggregation trimmed 10 production lines.

pull Bot pushed a commit to Faisal0x0/CodexBar that referenced this pull request Sep 25, 2026
Read the token objects OpenCode Go records locally (step-finish parts preferred, explicit totals honored, older records summed only when all five components exist) so local token history appears in Usage & Spend without inventing costs; malformed or overflowing totals stay unknown. Shares the aggregation with the existing reader and drops its duplicate queries. Adopts steipete#3995.

Closes steipete#3995

Co-authored-by: Yuxin Qiao <yuxin.qiao@example.invalid>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants