fix(opencode): report $0 for free models and expose cost like other engines
NA
10h ago
+14+14+01234567890123456789-5-5-0123456789
Why
Two problems with how OpenCode runs report cost:
Free and local models are charged Sonnet prices. When OpenCode reports a step cost of 0, OpenCodeEngineer estimates the cost with calculate_cost. For any model missing from MODEL_PRICING, calculate_cost falls back to Claude Sonnet 4.6 prices. So the default opencode/big-pickle, which is free, and local Ollama models were shown as costing money: $4.50 per 1M input / 100k output tokens. The same happened to the short names in MODEL_MAP (sonnet, opus, haiku), because they were priced before being mapped.
The cost is missing everywhere except the OpenCode summary. OpenCode keeps its cost only under usage.cost. --json usage (total_cost_usd), /history and /resume's session cost all read estimated_cost_usd, which the other engines write. OpenCode's cache writes (cache_creation_tokens) also never reached cache_write_tokens in --json.
What
In the step-finish handler, resolve the model through MODEL_MAP, and estimate a zero API cost only when get_model_pricing knows the model. Unknown models stay at $0 instead of borrowing Sonnet prices. Known models keep the local estimate added in #10 (for example a subscription that reports $0).
Record the running total under estimated_cost_usd as well. usage.cost is kept, so the OpenCode session summary and existing history are unchanged.
Add cache_creation_tokens to the cache_write_tokens candidates in _STABLE_USAGE_KEYS.
README: the agent --json table listed usage.total_cost. The field is total_cost_usd, next to the cache token counts and raw, as scripted-usage.mdx already says.
test_step_finish_calculates_cost_when_zero now sets a priced model. With the default free big-pickle, the correct estimate is $0.
CHANGELOG entries under Unreleased → Fixed.
Verification
Checked that big-pickle and an Ollama model now record $0, opus is priced as claude-opus-4-6, estimated_cost_usd accumulates across steps, and _normalize_usage maps OpenCode's keys.
pytest: 1231 passed, 10 skipped, same as main. ruff check src tests and mypy src are clean.
One behavior to call out: a paid model that is not in MODEL_PRICING (and not in LiteLLM, when installed), on a provider that reports $0, now shows $0 instead of a Sonnet-priced guess. That seemed more honest than a guess, but say if you'd rather keep a fallback there.
This PR and #155 (list/show cost) each add lines in the same CHANGELOG section, so whichever merges second will need a small conflict resolution there.
Summary by cubic
Fixes OpenCode cost reporting so free and local models show $0, and so cost and cache write usage reach the same places other engines report them.
Prices a $0 step only when the model has known pricing, resolving short names like opus through MODEL_MAP first; unknown models (opencode/big-pickle, Ollama) stay at $0 instead of getting Sonnet 4.6 prices.
Records cost under estimated_cost_usd alongside usage.cost, so --json, /history, and /resume see it.
Maps OpenCode's cache_creation_tokens to cache_write_tokens in --json usage, and notes in the README that usage fields appear only when the SDK reports them.
Corrects the README's agent --json usage field from total_cost to total_cost_usd.
Adds tests for free/Ollama models, alias pricing, cost accumulation across steps, and usage key normalization.
Confidence Score: 5/5
The reviewed cost-accounting and usage-export changes are safe to merge; no blocking issues were found.
Summary
Fixes OpenCode cost reporting and exposes its cost and cache writes through the existing JSON fields.
OpenCode keeps free models at zero and reports running costs consistently.
OpenCode cache writes appear in the shared JSON usage fields.
namanarora00 explicitly acknowledged that unknown paid models reporting $0 will now show $0, rather than a Sonnet-priced guess. This is intentional to avoid presenting an unknown cost as a known price.
No blocking issues were found in the reviewed changes. The changes are safe to merge within the reviewed scope.