Skip to content

feat(opencode): let a custom fetch mark stream errors retryable - #51616

Open
iceteaSA wants to merge 2 commits into
anomalyco:devfrom
iceteaSA:stream-retryable
Open

iceteaSA wants to merge 2 commits into
anomalyco:devfrom
iceteaSA:stream-retryable

Conversation

@iceteaSA

Copy link
Copy Markdown

Stacked on #51548; only the last commit is new.

Issue for this PR

Related: #44894, #37852 (closed by #51548).

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

#51548 retries a stream that fails partway, after discarding what the failed attempt wrote. A provider plugin with its own fetch, such as a WebSocket transport, has no supported way to say that a failure is transient. So when the connection drops after output has started, its errors are never retried.

With this change, a custom fetch can throw an Error with isRetryable: true, optionally with responseHeaders carrying retry-after or retry-after-ms. AI SDK APICallError.isRetryable already worked; this covers errors that aren't an APICallError. Retries stay bounded and stop once a tool call has started. The contract is documented in providers.mdx and on AuthHook.loader.

How did you verify your code works?

From packages/opencode: bun test test/session/processor-effect.test.ts test/session/retry.test.ts, 94 pass / 0 fail. The new tests fail without the change.

Screenshots / recordings

Not applicable.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

…stream

The processor retries a whole stream when it fails with a retryable
error, but it never removed what the failed attempt had already
written. A retry after partial output left duplicate text and
reasoning, parts that were never closed, and could run a tool the
failed attempt had already started a second time.

Before a retry, remove the parts the failed attempt created and restore
the message's finish, cost, tokens and file snapshot to what they were
when the attempt started. If a tool from that attempt had started
running, don't retry; end the turn with the error.

A stream that ends with no finish reason, no usage and no text or tool
output is now a retryable stream error instead of a normal stop, so a
dropped connection is retried and, once retries run out, shows an
error.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant