Skip to content

Fix OpenCode router calls with missing usage#342

Open
ozymandiashh wants to merge 1 commit into
getagentseal:mainfrom
ozymandiashh:fix/opencode-router-zero-usage
Open

Fix OpenCode router calls with missing usage#342
ozymandiashh wants to merge 1 commit into
getagentseal:mainfrom
ozymandiashh:fix/opencode-router-zero-usage

Conversation

@ozymandiashh
Copy link
Copy Markdown
Contributor

@ozymandiashh ozymandiashh commented May 17, 2026

Summary

Fixes #341 for OpenCode users whose router/provider writes assistant activity but does not persist token or cost usage metadata.

The reporter uses OpenCode through EdenAI as a router. In that kind of setup, OpenCode can still store the assistant response and tool activity in the part table while the assistant message usage fields remain all zero. CodeBurn treated those rows as empty placeholders and skipped them, which could make OpenCode look like it had no usage at all.

Root Cause

The OpenCode parser reads two tables:

  • message: assistant/user metadata, including role, modelID, tokens, and cost
  • part: message content and tool calls

Before this PR, CodeBurn skipped every assistant message where all token fields and cost were zero:

if (allZero && (data.cost ?? 0) === 0) continue

That is safe for truly empty assistant placeholders, but too aggressive for router-backed sessions. A router can produce a real assistant turn like this:

// message.data
{
  "role": "assistant",
  "modelID": "edenai/router-model",
  "cost": 0,
  "tokens": {
    "input": 0,
    "output": 0,
    "reasoning": 0,
    "cache": { "read": 0, "write": 0 }
  }
}

while still having real activity in part:

// part.data, text response
{ "type": "text", "text": "router response text" }

or:

// part.data, tool activity
{
  "type": "tool",
  "tool": "bash",
  "state": { "input": { "command": "npm test" } }
}

Previously both examples were dropped because usage was zero. That is why the provider could report no OpenCode usage even though OpenCode had real assistant turns.

What Changed

The skip condition now distinguishes empty placeholders from zero-usage real activity:

  • Keep the assistant call if usage is zero but part contains non-empty text.
  • Keep the assistant call if usage is zero but part contains a valid tool call.
  • Still skip assistant rows with zero usage and no text/tool activity.

The kept calls intentionally remain zero-token and zero-cost. This avoids inventing token totals or spend that OpenCode did not record, while still allowing CodeBurn to show the session/call/tool activity.

Before / After

Before:

  • OpenCode DB has assistant response text or tool parts.
  • message.data.tokens and message.data.cost are all zero.
  • CodeBurn drops the assistant message.
  • If all assistant turns in the session look like that, CodeBurn reports no OpenCode usage.

After:

  • OpenCode DB has assistant response text or tool parts.
  • message.data.tokens and message.data.cost are all zero.
  • CodeBurn keeps the assistant message as a zero-cost call.
  • Tool names and shell command breakdowns still work when the part row contains tools.
  • Empty zero-usage placeholders are still ignored.

Tests Added

Added focused OpenCode SQLite fixtures for:

  • zero-usage assistant message with text part -> counted as one zero-cost call
  • zero-usage assistant message with tool part -> counted as one zero-cost call, with tool/bash extraction preserved
  • existing zero-usage assistant message with no parts -> still skipped

Validation

  • npx vitest run tests/providers/opencode.test.ts tests/provider-registry.test.ts - 49/49 tests passed.
  • npx tsc --noEmit --pretty false - passed.
  • npm run build - passed.
  • git diff --check - passed.
  • Argus-style review - PASS.
  • Claude Opus 4.7 effort max review - PASS.
  • Gemini 3.1 Pro Preview review - PASS.
  • GitHub checks: check, assess, semgrep - passed.

Safety / Scope

This PR does not change OpenCode database discovery paths and does not add a new schema parser. It only relaxes the existing skip logic when the already-read part rows prove the assistant turn had real activity.

I did not validate against the reporter's local OpenCode database. The coverage uses synthetic SQLite fixtures matching the reported failure mode, so no local project names, prompts, paths, session IDs, usage values, or private product details are included.

@ozymandiashh ozymandiashh marked this pull request as ready for review May 17, 2026 19:06
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.

codeburn does not report opencode

1 participant