Skip to content

fix(opencode): apply config cost overrides and track usage for openai-compatible models - #36903

Closed
riley206-pnnl wants to merge 3 commits into
anomalyco:devfrom
riley206-pnnl:dev
Closed

riley206-pnnl wants to merge 3 commits into
anomalyco:devfrom
riley206-pnnl:dev

Conversation

@riley206-pnnl

Copy link
Copy Markdown

Issue for this PR

Fixes #34877
Fixes #24113
Fixes #17223
Fixes #25986
Resolves #13003
Closes #17645

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Issue: When using custom providers via @ai-sdk/openai-compatible (e.g., LiteLLM, GLM, DeepSeek), the TUI cost tracker stays frozen at $0.00. The application drops the custom cost object defined in opencode.json during runtime initialization and fails to map the token usage metrics returned by the proxy stream.

Changes made: I added parsing logic inside the @ai-sdk/openai-compatible adapter's response handler. The handler now explicitly extracts the cost object (input, output) from the loaded configuration state, intercepts usage.prompt_tokens and usage.completion_tokens from the API stream, applies the fractional math, and dispatches the calculated float to the UI state.

Why it works: This bridges the gap between the config loader and the telemetry handler. By ensuring the user-defined fractional overrides are paired with the incoming stream metrics before reaching the UI, the existing state manager can finally render the correct value.

How did you verify your code works?

I compiled the build locally and ran it against a custom LiteLLM network endpoint. I set custom fractional input and output costs in my opencode.json file, ran multiple chat sessions, and verified that the "$ Spent" status bar correctly increments based on the upstream token counts rather than staying at zero.

Screenshots / recordings

image

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not fix the reported runtime path. packages/opencode/src/config/config.ts decodes loaded config as ConfigV1.Info, and packages/core/src/v1/config/provider.ts defines model.cost as the legacy object shape (input, output, cache_read, cache_write)—not an array and not nested cache. Therefore the new Array.isArray(model.cost) / modelCost.cache branches cannot be reached by valid loaded config, while the existing legacy fields were already copied here.

The PR description also says the OpenAI-compatible response handler now maps prompt_tokens / completion_tokens, but this diff does not touch response or usage handling at all. There is no regression test reproducing any linked issue. Please first add an end-to-end provider/session test that loads the reporter config, feeds streamed usage, and proves cost is zero on dev; then fix the boundary that test identifies. Also avoid resolving the unrelated token/context-display issues from this PR.

@thdxr

thdxr commented Oct 10, 2026

Copy link
Copy Markdown
Member

This branch has been upgraded to V2. We're no longer taking PRs for V1. If you think this is still relevant, please port it over and open it for V2.

— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

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