Skip to content

fix: read OpenCode v2 sessions from session_v2/session_message tables - #184

Closed
3intermute wants to merge 1 commit into
graykode:mainfrom
3intermute:fix/opencode-v2-schema
Closed

3intermute wants to merge 1 commit into
graykode:mainfrom
3intermute:fix/opencode-v2-schema

Conversation

@3intermute

Copy link
Copy Markdown

Problem

OpenCode v2 replaced the SQLite schema: sessions moved from session/message to session_v2/session_message (same opencode.db). The collector's query fails with no such table: session; run_query() returns None and the failure is swallowed, so on OpenCode v2 abtop silently shows zero sessions — no error in the TUI. v0.5.5 (latest release) and current main are both affected.

This bit the wider ecosystem the same way (ccusage #1644, tokscale #1155).

Fix (one file, src/collector/opencode.rs)

  • Query session_v2 joined to project; read token totals from the row (tokens_input/tokens_output/tokens_cache_read/tokens_cache_write) instead of json_extract aggregation over the message table. One sqlite3 fork per refresh instead of two, and no scan of message blobs.
  • session_v2.model is a JSON blob ({"id":"glm-5.3","providerID":"zai-key2",...}), not a plain string — extract $.id/$.providerID so the TUI keeps rendering provider/model; both still go through sanitize_db_field.
  • Filter parent_id IS NULL: in a long-lived DB 84% of session_v2 rows (4599/5474 here) are subagent child sessions that never map to a user-launched process — without the filter they flood the top-20 and break PID claiming.
  • Turn count from session_message rows with type='assistant', served by the covering index (session_id, type, seq).

PID↔cwd matching, status derivation, and sanitization are unchanged.

Verification

On a live 2.7GB WAL DB (OpenCode 2.2.5, actively written):

  • The exact query runs in ~27ms (EXPLAIN QUERY PLAN confirms the covering index; outer scan is ~880 parent rows).
  • abtop --json before: "sessions": []. After: all 7 running opencode TUI processes matched by cwd, correct zai-key2/glm-5.3 model strings, tokens/cache/turn counts populated.
  • cargo test (222 passed) and cargo clippy -- -D warnings clean.

Note: context-% for OpenCode still over-reports for long sessions because it divides cumulative lifetime tokens by the window — pre-existing behavior, unchanged here.

OpenCode v2 replaced the legacy schema: sessions now live in session_v2
(with token totals on the row) and messages in session_message. The old
query failed with 'no such table: session', which run_query() swallowed,
so OpenCode v2 users silently saw zero sessions.

- Query session_v2 joined to project; read tokens from the row instead
  of json_extract aggregation over the message table (one sqlite3 fork
  per refresh instead of two, no scan of message blobs).
- Extract model/provider from the session_v2.model JSON blob
  ({id,providerID}) so the TUI keeps rendering 'provider/model'.
- Filter parent_id IS NULL: 84% of rows in a long-lived DB are subagent
  child sessions that never map to a user-launched process.
- Turn count from session_message type='assistant' via the covering
  index (session_id, type, seq).

Verified against a live 2.7GB WAL DB (OpenCode 2.2.5): query runs in
~27ms and all running opencode TUI processes are matched by cwd.
@3intermute 3intermute closed this Nov 2, 2026
@3intermute
3intermute deleted the fix/opencode-v2-schema branch November 2, 2026 20:48
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