anomalyco / anomalyco/opencode
DeepSeek BYOK: local cost meter under-reports API spend — models.dev static prices don't reflect peak/off-peak pricing
@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:1217—cost()mapsModelsDev.Model["cost"](input,output,cache.read,cache.write) straight onto the model.packages/opencode/src/session/session.ts:338—getUsage()chargesinput · cost.input + output · cost.output + reasoning · cost.output + cache.read · cost.cache.read + cache.write · cost.cache.write(there is even aTODO: update models.dev to have better pricing modelat 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:
- 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.
- 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 havegetUsage()pick the rate using the call timestamp (per-message timestamps + cached/uncached/reasoning splits are already stored, so this is recomputable offline). This is theTODOatsession.ts:398. - 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.