fix(opencode): retry stalled SSE streams (#29837)

This commit is contained in:
Aiden Cline 2026-05-29 00:19:54 -05:00 committed by GitHub
parent a15d4f9f04
commit c7e1fc5e42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 1 deletions

View file

@ -48,7 +48,7 @@ function wrapSSE(res: Response, ms: number, ctl: AbortController) {
async pull(ctrl) {
const part = await new Promise<Awaited<ReturnType<typeof reader.read>>>((resolve, reject) => {
const id = setTimeout(() => {
const err = new Error("SSE read timed out")
const err = new ProviderError.ResponseStreamError("SSE read timed out")
ctl.abort(err)
void reader.cancel(err)
reject(err)

View file

@ -10,6 +10,7 @@ import { testProviderConfig } from "../lib/test-provider"
import { Env } from "@/env"
import { Plugin } from "@/plugin"
import { Provider } from "@/provider/provider"
import { ProviderError } from "@/provider/error"
import { ModelID, ProviderID } from "@/provider/schema"
afterEach(async () => {
@ -58,6 +59,35 @@ it.live("headerTimeout does not abort delayed SSE body after headers arrive", ()
),
)
it.live("chunkTimeout raises a response stream error when SSE body stalls", () =>
provideTmpdirServer(
({ llm }) =>
Effect.gen(function* () {
yield* llm.push(reply().wait(Bun.sleep(250)).text("late").stop())
const provider = yield* Provider.Service
const model = yield* provider.getModel(ProviderID.make("test"), ModelID.make("test-model"))
const result = streamText({
model: yield* provider.getLanguage(model),
onError() {},
messages: [{ role: "user", content: "hello" }],
})
const error = yield* Effect.promise(async () => {
try {
for await (const part of result.fullStream) {
if (part.type === "error") return part.error
}
} catch (error) {
return error
}
})
expect(error).toBeInstanceOf(ProviderError.ResponseStreamError)
}),
{ config: (url) => providerConfig(url, { chunkTimeout: 50 }) },
),
)
it.live("headerTimeout aborts when response headers do not arrive", () =>
Effect.gen(function* () {
const server = yield* Effect.acquireRelease(