Skip to content

readOpencodeSessionMessages drops per-message tokens, per-part timings and tool status, so a transcript reader has to read the rows itself #728

Description

@drewstone

What the gap is

@tangle-network/agent-eval/rollout owns the opencode session store. openOpencodeDb is a good citizen — read-only, returns null rather than throwing on a corrupt or half-written file — and discovery-lab uses it for every open.

readOpencodeSessionMessages is not used, and the reason is a capability gap rather than a preference. It projects the store into canonical chat messages, and that projection drops three fields that are present in the tables it reads:

Dropped Where it lives What it answers
per-message tokens {input, output, reasoning, cache} the message row what a single turn cost — the only per-turn cost signal that exists
per-part time {start, end} the part row where a turn spent its wall time; which tool call was the slow one
tool state.status the part row whether a call is pending, errored, or completed — and whether its output was ever persisted

The supervisor's journal records that a worker existed, what it was called, and how it died. It records none of the above. The store is the only place these three exist, and the canonical projection is where they are lost.

What the consumer does today

discovery-lab/dashboard/lib/transcript.mjs opens the store with your openOpencodeDb and uses your session parser's column set, then reads the message and part rows directly for those three fields. That is a strictly additive read of the same tables through the same handle — it does not fork the schema — but it means the store has two readers in the stack instead of one, and the second one is in a viewer.

The file says so in its own header. Closing this gap deletes that function, not that file.

Suggested shape

An options flag on the existing reader rather than a second entry point, so the canonical projection stays the default:

readOpencodeSessionMessages(db, sessionId, { withUsage: true })

carrying, per message, the token object as recorded (absent rather than zero when the row has none — an unmeasured turn must not read as a free one), and per part, time and state.status as recorded.

Not asking for

No change to the default projection's shape, and no new dependency. The rows are already being read; this is about what survives the projection.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions