Repository navigation
Description
Description
OpenCode silently drops token usage for dynamically loaded providers that implement AI SDK LanguageModelV2. This is severe because it does not only hide the context-usage indicator: it also disables automatic context compaction.
The affected model can have a valid positive limit.context, but every assistant message is persisted with zero input/output/cache tokens. session/overflow.ts therefore never sees the session approach the model's context limit and never schedules compaction. Long-running sessions continue growing without warning until the provider rejects the request at its hard context limit. Users lose the normal compaction safety mechanism and receive no visible indication that it has stopped working.
Observed with SAP AI Core using @jerome-benoit/sap-ai-provider-v2@4.6.7, but the bug is version-based rather than SAP-specific and can affect any dynamically loaded AI SDK V2 provider.
The model metadata was not the problem: the affected model reported limit.context = 1,000,000 correctly.
Root cause
Provider.getLanguage() is typed as returning LanguageModelV3, although dynamically loaded providers can return a runtime V2 model.
packages/opencode/src/session/llm.ts unconditionally passes that model to wrapLanguageModel() with V3 middleware. The wrapper labels the result as V3 before AI SDK can run its V2-to-V3 compatibility conversion. Finish usage is then lost.
A minimal differential probe produced:
base V2 model: finish-step usage = input 14, output 4, total 18
V3-wrapped model: finish-step usage = undefined
Plugins
None required. Reproduced with --pure.
OpenCode version
1.18.31 / dev commit 0a429ed441
Steps to reproduce
- Configure a dynamically loaded AI SDK V2 provider with a model that has a valid context limit.
- Run:
opencode run --pure --format json --model <provider>/<model> --agent build "Reply exactly OK"- Inspect the
step_finishevent.
Actual result:
{
"tokens": {
"input": 0,
"output": 0,
"reasoning": 0,
"cache": { "read": 0, "write": 0 }
}
}- Continue the session. The context usage indicator remains absent and automatic compaction never triggers, even as the conversation approaches the model's context limit.
Expected behavior
- V2 provider usage MUST survive message transformation and AI SDK compatibility conversion.
- Assistant messages MUST persist non-zero token usage when the provider reports it.
- Automatic compaction MUST continue to trigger based on the model's context limit.
A working fix is to inspect the runtime specificationVersion:
- V2 model: transform messages before
streamTextand pass the model unwrapped, allowing AI SDK's V2-to-V3 converter to preserve usage. - V3 model: retain the existing V3 middleware path.
With that change, the same end-to-end command produced non-zero usage (total: 82061, input: 82057, output: 4), restoring both context display and auto-compaction.
Operating System
macOS 27 (arm64)
Terminal
Zed terminal
Activity
ton618to commentedon Oct 16, 2026
Confirmed V2 impact: SAP responses abort with schema validation errors, not just missing usage
Please treat the V2 case as a provider-blocking response-completion failure. In my compiled OpenCode V2 build, SAP authentication succeeds and text streams to the UI, but the session drain then stops with
Schema validation failed. Three consecutive observed failures in the same SAP session reached the same location:The constructor is
LLMEvent.stepFinish; the nested rejected field isreason.normalized. The affected live model wassap-ai-core/gpt-6-astra, using@jerome-benoit/sap-ai-provider-v2@5.0.3(specificationVersion: "v2").The V2 provider returns
finishReason: "stop"and numericusage.inputTokens/usage.outputTokens. The core bridge readsfinishReason.unifiedand nested token totals as if the event were V3.normalizedtherefore becomesundefined, and the strict schema throws. This explains why users see apparent progress before an error interrupts the request; it is not a request-count limit or an invalid credential.Plugin-free differential verification: a network-free probe ran the production
AISDK.locationLayerandLLMClient.generate, with no user plugins or PluginHost. Both streams contained the same text-start/delta/end events andOKtext. Only the finish-event format differed:finishReason: "stop", flat usage10 / 2 / 12aisdk.ts:854{ unified: "stop", raw: "stop" }, nested usagestop; input 10, output 2, total 12Separately, a real SAP request against an isolated compiled V2 server, after fixing credential propagation, reached this same finish-event schema failure and returned HTTP 500. Disabling user plugins does not resolve it. V1 works with the same valid SAP credentials.
PR #50797 explicitly covers this exact failure and remains open. Please prioritize reviewing the V2 fix: the impact is interrupted SAP sessions in addition to missing token accounting/compaction safety. I have not locally applied or verified that PR, so this comment reports the confirmed failure and control, not a passing end-to-end result with the proposed patch.
Environment: macOS/Darwin 27.0.0 arm64, Bun 1.4.2, local compiled CLI
0.0.0-local-202610161547from a 2.0.31 checkout. This is a local build, not a claim of testing an unmodified published binary.Related but separate: #56126 is the saved-key authentication blocker; #54791 is the source-only Babel/Bun initialization failure. Neither accounts for this post-authentication completion failure.
Tarquinen commentedon Oct 20, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊