Skip to content

core: recover gracefully from truncated provider streams #38747

Description

@rekram1-node

Summary

V2 correctly detects provider streams that end before their protocol completion boundary, but currently treats the result as a terminal invalid-provider-output failure. Preserve truthful failure semantics while providing a safe, explicit recovery path for partial assistant output instead of leaving users to manually reconstruct or repeat the turn.

Environment

  • opencode version: 0.0.0-next-16175
  • OS: Darwin 25.5.0, arm64
  • Terminal: Ghostty (TERM=xterm-256color, COLORTERM=truecolor)
  • Shell: /bin/zsh
  • Install/channel: local V2 next build
  • Active plugins: none configured

Reproduction

  1. Start a V2 Session using a streaming provider.
  2. Allow the provider to emit visible text, reasoning, or tool activity.
  3. Interrupt the upstream connection after terminal metadata such as Anthropic message_delta, but before the protocol completion event such as message_stop.
  4. Observe V2 record an invalid/truncated provider-stream failure with partial assistant content.

Expected Behavior

V2 should detect the truncation as a failure and preserve the partial assistant content, while exposing a safe recovery path appropriate to the amount and kind of work already observed.

Before any assistant output or tool activity, an automatic bounded retry may be safe. After visible output or tool activity, V2 should not blindly retry provider work because that can duplicate output or side effects. It should durably reconcile open content/tool state, clearly mark the response as interrupted, and allow an explicit or policy-driven continuation from the partial history.

The recovery behavior should be provider-neutral while respecting protocol-specific completion boundaries.

Actual Behavior

The native route correctly rejects a stream that ends without its terminal completion event, but the Session ends in a provider failure. Users must manually prompt the agent to continue, and the product does not distinguish a recoverable upstream truncation from other invalid provider output.

There is no explicit recovery policy for:

  • truncation before any output;
  • truncation after text or reasoning;
  • truncation during local tool input or execution;
  • truncation during provider-hosted tools;
  • preserving partial opaque reasoning state safely;
  • communicating interrupted versus completed output to clients.

Additional Context

Anthropic demonstrates the issue clearly: message_delta carries final stop and usage fields, but message_stop is the actual successful completion boundary. PR #38733 changes V2 to reject EOF between those events rather than recording a false success.

The recovery design should preserve these invariants:

  • Never convert a truncated stream into a successful completion.
  • Never blindly replay provider work after durable retry evidence exists.
  • Never duplicate local or hosted tool side effects.
  • Preserve partial text, reasoning, signatures, and redacted provider state when valid.
  • Settle or reconcile every opened tool/content block before continuation.
  • Make interruption visible to TUI, app, API, and later replay.
  • Keep retry and continuation bounded by existing step limits.

Related:

Metadata

Metadata

Assignees

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