Skip to content

bug: AI SDK V2 providers silently lose usage and disable auto-compaction #50338

Closed as not planned

Description

@ton618to

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

  1. Configure a dynamically loaded AI SDK V2 provider with a model that has a valid context limit.
  2. Run:
opencode run --pure --format json --model <provider>/<model> --agent build "Reply exactly OK"
  1. Inspect the step_finish event.

Actual result:

{
  "tokens": {
    "input": 0,
    "output": 0,
    "reasoning": 0,
    "cache": { "read": 0, "write": 0 }
  }
}
  1. 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 streamText and 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

  1. ton618to commented on Oct 16, 2026

    @ton618to
    Author

    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:

    Error: Schema validation failed
        at .../effect/dist/SchemaParser.js:921:13
        at streamPartEvents (.../packages/core/src/aisdk.ts:854:18)
        at SessionStep.attempt (.../packages/core/src/session/runner/llm.ts:248:38)
    

    The constructor is LLMEvent.stepFinish; the nested rejected field is reason.normalized. The affected live model was sap-ai-core/gpt-6-astra, using @jerome-benoit/sap-ai-provider-v2@5.0.3 (specificationVersion: "v2").

    The V2 provider returns finishReason: "stop" and numeric usage.inputTokens / usage.outputTokens. The core bridge reads finishReason.unified and nested token totals as if the event were V3. normalized therefore becomes undefined, 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.locationLayer and LLMClient.generate, with no user plugins or PluginHost. Both streams contained the same text-start/delta/end events and OK text. Only the finish-event format differed:

    Finish event Observed result
    V2: finishReason: "stop", flat usage 10 / 2 / 12 Same schema failure at aisdk.ts:854
    V3: { unified: "stop", raw: "stop" }, nested usage Successful completion; normalized stop; input 10, output 2, total 12

    Separately, 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-202610161547 from 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.

  2. Tarquinen commented on Oct 20, 2026

    @Tarquinen
    Member

    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 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions