anomalyco / anomalyco/opencode

DeepSeek BYOK: local cost meter under-reports API spend — models.dev static prices don't reflect peak/off-peak pricing

Open
#47,788 1 comment 2 reactions 1 assignee View on GitHub

@neriousy is already working on this.

Since Sep 7, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Summary

Using DeepSeek with my own API key, the local usage/cost meter under-reports spend by a wide margin. Today opencode shows ~$0.60 for a session while the DeepSeek platform dashboard shows $1.00+ for the same period. This is not an OpenCode Go / Zen quota issue — it's a plain BYOK DeepSeek session, so there is no server-side number opencode could have gotten "right" except its own local estimate.

Why the local estimate is wrong (root cause)

opencode computes session cost by multiplying per-message token counts (input, output, reasoning, cache.read, cache.write) by a single static per-model price taken from models.dev:

  • packages/opencode/src/provider/provider.ts:1217cost() maps ModelsDev.Model["cost"] (input, output, cache.read, cache.write) straight onto the model.
  • packages/opencode/src/session/session.ts:338getUsage() charges input · cost.input + output · cost.output + reasoning · cost.output + cache.read · cost.cache.read + cache.write · cost.cache.write (there is even a TODO: update models.dev to have better pricing model at session.ts:398).

But DeepSeek no longer publishes a single price. Since V4 the official pricing (https://api-docs.deepseek.com/quick_start/pricing/) is time-of-day dynamic, with peak hours (01:00–04:00 and 06:00–10:00 UTC, Mon–Fri) at 2× the off-peak rate:

deepseek-v4-flash (per 1M tokens) models.dev (what opencode uses) Official off-peak Official peak
input (cache miss) $0.14 $0.22 $0.44
output / reasoning $0.28 $0.66 $1.32
cache read (cache hit) $0.0028 $0.007 $0.014

So every component opencode charges is 1.6×–4.7× below what DeepSeek bills. deepseek-v4-pro is similarly stale ($0.435/$0.87 vs official $0.66/$1.98 off-peak and double that at peak). A ~1.7× under-report (as observed) is exactly what you get from a mix of cache-miss input and output at these rates.

Suggested direction for contributors

A static per-model number cannot represent DeepSeek's 2× peak/off-peak multiplier, so this needs more than a data bump:

  1. Fix/refresh the static prices first — update the DeepSeek entries in models.dev (and/or the bundled provider data) to the current published rates so even the estimate is in the right ballpark.
  2. Model time-varying pricing properly — encode a pricing schedule (peak/off-peak windows + rates) rather than a scalar, e.g. extend Model["cost"]/models.dev schema with optional time-window pricing, and have getUsage() pick the rate using the call timestamp (per-message timestamps + cached/uncached/reasoning splits are already stored, so this is recomputable offline). This is the TODO at session.ts:398.
  3. Add a per-provider / per-model cost override so BYOK users can enter accurate prices without waiting on upstream data (config-level, documented as an estimate otherwise).

Separately, the meter also excludes calls DeepSeek does bill (session-title, summarization/compaction, subagent costs) — tracked in #46371 and #45417 — which further widens the gap and should be linked into whatever fix lands here.

Related issues (not duplicates — those concern OpenCode Go/Zen quota or other providers)

  • #46371 Hidden LLM calls (title/summaries) billed but absent from session cost
  • #45417 Session cost excludes subagent cost
  • #40835 Cost display severely underestimates real provider billing
  • #45340 [FEATURE] Where are token costs even being derived from?
  • #34877 Cost tracking shows $0.00 for Chinese model providers via openai-compatible

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.