fix(reporter): read opencode sessions from opencode.db - #37
Open
nicko170 wants to merge 1 commit into
Open
Conversation
opencode >= 1.x stores messages in a SQLite database at <data-dir>/opencode.db; the reporter only knew the older layout of one JSON file per message under <data-dir>/storage/message/<sessionID>/. On any machine running a current opencode that directory no longer exists, so readdirSync throws, collectOpencodeRows skips the root, and `tokenmaxer backfill opencode` reports "backfilled 0 opencode row(s)" as a success. The opencode-sessionstart hook is silently a no-op too. Read the database when it is present, falling back to the legacy tree so machines that have not upgraded (or that still hold pre-upgrade sessions) keep reporting. The `data` column holds the same message object the JSON files did, so parseOpencodeMessages is reused unchanged; sessions found in the database take precedence over a same-id legacy directory. node:sqlite is already used for Cursor's state.vscdb, so this adds no dependency. The database is opened read-only, and an unreadable or unexpected schema falls through to the legacy path rather than throwing. Verified against a real 25-session opencode.db: input/output totals match the aggregates opencode keeps in its own `session` table exactly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
tokenmaxer backfill opencodereturns zero rows on any machine running a current opencode, and reports it as success:opencode >= 1.x stores messages in a SQLite database at
<data-dir>/opencode.db. The reporter only knows the older layout — one JSON file per message under<data-dir>/storage/message/<sessionID>/. On opencode 1.18.15 that directory does not exist at all:So
readdirSync(root)throws,collectOpencodeRowshits itscatch { continue }, and the source silently contributes nothing.opencode-sessionstart/opencode-sessionendare no-ops for the same reason, so ongoing reporting is affected too, not just backfill.Fix
Read
opencode.dbwhen it is present, and keep the legacy tree as a fallback so machines that have not upgraded — or that still hold pre-upgrade sessions alongside the database — keep reporting. Sessions found in the database win over a same-id legacy directory.The
message.datacolumn holds the same message object the JSON files did (role,modelID,tokens.{input,output,reasoning,cache.{read,write}},time.created), soparseOpencodeMessagesis reused unchanged and both layouts share one parser.Notes:
node:sqliteis already used for Cursor'sstate.vscdb, so no new dependency.readOnly, and an unreadable file or unexpected schema returnsnullto fall through to the legacy path rather than throwing.sinceMsis applied as aWHERE time_created >= ?predicate, matching the mtime filter the file path uses.Verification
pnpm checkpasses — lint, format, typecheck, 374 tests across 42 files.New
src/__tests__/reporter-opencode-db.test.tscovers per-session/per-model summing,started_atbeing the earliest message,sinceMsfiltering, the legacy layout still working, and the empty case. The tests seed a real SQLite database and pinOPENCODE_DATA_DIR/XDG_DATA_HOME/HOMEat a temp dir so they do not read the developer's own opencode store.End-to-end against a real 25-session
opencode.db, the reporter's totals match the aggregates opencode maintains independently in its ownsessiontable:sessiontablePossibly worth a follow-up
A source whose data directory is entirely absent is indistinguishable from one with no recent activity — both print
backfilled 0 row(s)and exit 0. That is what made this quiet for so long. Happy to add a warning when no candidate root exists for a requested source, if you'd want it.