Skip to content

feat(opencode): surface context-window usage and session cost on the meter - #8659

Open
ardevdevts wants to merge 5 commits into
pingdotgg:mainfrom
ardevdevts:t3code/opencode-context-window-usage
Open

feat(opencode): surface context-window usage and session cost on the meter#8659
ardevdevts wants to merge 5 commits into
pingdotgg:mainfrom
ardevdevts:t3code/opencode-context-window-usage

Conversation

@ardevdevts

@ardevdevts ardevdevts commented Aug 29, 2026

Copy link
Copy Markdown

Problem

OpenCode sessions never reported token usage, so the context-window meter stayed empty for them while Codex and Claude sessions render usage.

Change

  • OpenCodeAdapter now emits thread.token-usage.updated: per-message counts from assistant message.updated events folded with cumulative session totals and USD cost from session.updated events. Emissions are deduped over every input that shapes the snapshot, so unchanged session replays don't spam the event log while real changes (including output-only growth mid-stream) re-emit.
  • Context-window size (maxTokens) is resolved once per model from the provider.list catalog; a transient catalog failure is retried on the next session.updated instead of giving up for the session's lifetime.
  • Zero-token updates (e.g. compaction summary messages) no longer clobber the meter's per-message usage.
  • Contract: optional cost on ThreadTokenUsageSnapshot; the web context-window meter renders a Cost row when a provider reports it.

Note: Claude's total_cost_usd currently lands on the turn.completed payload and is not wired into the meter — left as-is for now.

Verification

Focused tests pass (OpenCodeAdapter 92, ContextWindowMeter + contextWindow 11) covering the mapping, dedupe, late/retried catalog resolution, zero-token handling, and model switches; targeted typecheck is clean.

image

Model: glm-5.3-flash · harness: opencode

Note

Surface context-window usage and session cost on the ContextWindowMeter

  • OpenCodeAdapter now emits thread.token-usage.updated events on assistant message and session updates, carrying normalized token counts (input, output, reasoning, cacheRead, cacheWrite), optional maxTokens resolved via client.provider.list(), and optional cumulative session cost.
  • New helpers normalizeOpenCodeTokenCounts and normalizeOpenCodeTokenUsage clamp non-finite/negative/undefined values to zero and build a ThreadTokenUsageSnapshot. Emissions are deduped by a composite key; zero-token assistant messages no longer clobber prior per-message usage.
  • resolveOpenCodeMaxTokens caches per-model context-window size, drops the value on model switch, times out after 5s, and retries on subsequent session updates.
  • providerRuntime.ts adds an optional non-negative cost field to ThreadTokenUsageSnapshot. ContextWindowMeter.tsx renders a Cost row in the popover when usage.cost > 0, formatted via new formatContextWindowCost (2 decimals, or 4 for sub-cent amounts).
  • Behavioral Change: session.updated and message.updated handlers in makeOpenCodeAdapter now perform catalog lookups and emit usage events on every relevant update; catalog failures leave maxTokens unresolved until a later update succeeds.

Macroscope summarized 1f71e67.


Note

Medium Risk
Changes the OpenCode event pump (catalog calls on session.updated) and a shared usage contract/UI path; behavior is heavily tested but incorrect token or cost mapping would affect metering accuracy.

Overview
OpenCode sessions now drive the same context-window meter as other providers by emitting thread.token-usage.updated from assistant message.updated and session.updated events, with normalization helpers that clamp bad token payloads and map OpenCode’s split counts into ThreadTokenUsageSnapshot (used vs cumulative totals, optional breakdown fields).

maxTokens is looked up once per model via provider.list on the event path (short timeout, retry on later session updates). Model switches clear stale limits; emissions are deduped unless usage, cost, or capacity actually changes. Zero-token assistant messages no longer wipe the last real per-message usage.

UI/contracts: ThreadTokenUsageSnapshot gains optional cost (USD); the context-window meter popover shows a Cost row when the provider reports it (formatContextWindowCost). Tests cover mapping, dedupe, catalog failure/retry, model switches, and the new meter row.

Reviewed by Cursor Bugbot for commit 1f71e67. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0a20ac01-005b-431a-bc60-299cca213b4b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 29, 2026
Comment thread apps/server/src/provider/Layers/OpenCodeAdapter.ts
Comment thread apps/server/src/provider/Layers/OpenCodeAdapter.ts
@ardevdevts
ardevdevts marked this pull request as ready for review August 29, 2026 18:00
@macroscopeapp

macroscopeapp Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a cross-layer OpenCode metering capability that changes the production event pump, shared usage contract, persisted activity stream, and user-facing context meter. Because it automatically adds token/cost tracking and catalog lookups to existing sessions, the change warrants human review.

Notes:

  • No code objects were reviewed. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

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

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant