Skip to content

Commit ec58afe

Browse files
authored
Merge branch 'dev' into fix/mcp-async-status
2 parents 7bba9ed + 9136598 commit ec58afe

2 files changed

Lines changed: 29 additions & 19 deletions

File tree

packages/opencode/src/plugin/openai/ws.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,6 @@ export function streamResponsesWebSocket(options: StreamResponsesWebSocketOption
159159
if (!options.idleTimeout) return
160160
if (idleTimer) clearTimeout(idleTimer)
161161
idleTimer = setTimeout(() => invalidate(new ProviderError.ResponseStreamError(message)), options.idleTimeout)
162-
if (typeof idleTimer === "object" && "unref" in idleTimer && typeof idleTimer.unref === "function") {
163-
idleTimer.unref()
164-
}
165162
}
166163

167164
async function onMessage(data: WebSocket.RawData, isBinary: boolean) {

packages/opencode/test/plugin/openai-ws.test.ts

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ describe("plugin.openai.ws", () => {
5151
onConnectionInvalid: (error) => invalid.push(error.message),
5252
})
5353

54-
await expect(response.text()).rejects.toThrow("idle timeout sending websocket request")
54+
expect((await readTextError(response.text())).message).toContain("idle timeout sending websocket request")
5555
expect(invalid).toEqual(["idle timeout sending websocket request"])
5656
})
5757

@@ -100,7 +100,7 @@ describe("plugin.openai.ws", () => {
100100
onConnectionInvalid: (error) => invalid.push(error),
101101
})
102102

103-
await expect(response.text()).rejects.toThrow(
103+
expect((await readTextError(response.text())).message).toContain(
104104
"WebSocket closed before response.completed (code 1009: message too big: payload too large)",
105105
)
106106
expect(invalid[0]).toBeInstanceOf(ProviderError.ResponseStreamError)
@@ -124,7 +124,7 @@ describe("plugin.openai.ws", () => {
124124
onConnectionInvalid: (error) => invalid.push(error.message),
125125
})
126126

127-
await expect(response.text()).rejects.toThrow("Unexpected binary WebSocket frame")
127+
expect((await readTextError(response.text())).message).toContain("Unexpected binary WebSocket frame")
128128
expect(invalid).toEqual(["Unexpected binary WebSocket frame"])
129129
})
130130
})
@@ -186,7 +186,7 @@ describe("plugin.openai.ws-pool", () => {
186186
})
187187

188188
const first = await fetch(server.url, streamRequest({ [TITLE_HEADER]: "false" }))
189-
await expect(first.text()).rejects.toBeInstanceOf(ProviderError.ResponseStreamError)
189+
expect(await readTextError(first.text())).toBeInstanceOf(ProviderError.ResponseStreamError)
190190
const second = await fetch(server.url, streamRequest({ [TITLE_HEADER]: "false" }))
191191
const third = await fetch(server.url, streamRequest({ [TITLE_HEADER]: "false" }))
192192

@@ -271,7 +271,7 @@ describe("plugin.openai.ws-pool", () => {
271271
})
272272

273273
const first = await fetch(server.url, streamRequest())
274-
await expect(first.text()).rejects.toThrow("Responses websocket connection limit reached")
274+
expect((await readTextError(first.text())).message).toContain("Responses websocket connection limit reached")
275275
const second = await fetch(server.url, streamRequest())
276276
const text = await second.text()
277277

@@ -308,9 +308,9 @@ describe("plugin.openai.ws-pool", () => {
308308
})
309309

310310
const first = await fetch(server.url, streamRequest())
311-
await expect(first.text()).rejects.toThrow("Responses websocket connection limit reached")
311+
expect((await readTextError(first.text())).message).toContain("Responses websocket connection limit reached")
312312
const second = await fetch(server.url, streamRequest())
313-
await expect(second.text()).rejects.toThrow("Responses websocket connection limit reached")
313+
expect((await readTextError(second.text())).message).toContain("Responses websocket connection limit reached")
314314
const third = await fetch(server.url, streamRequest())
315315
const fourth = await fetch(server.url, streamRequest())
316316

@@ -348,7 +348,7 @@ describe("plugin.openai.ws-pool", () => {
348348
})
349349

350350
const first = await fetch(server.url, streamRequest())
351-
await expect(first.text()).rejects.toThrow("WebSocket closed before response.completed")
351+
expect((await readTextError(first.text())).message).toContain("WebSocket closed before response.completed")
352352
const second = await fetch(server.url, streamRequest())
353353

354354
expect(await second.text()).toBe("http")
@@ -370,7 +370,7 @@ describe("plugin.openai.ws-pool", () => {
370370
})
371371

372372
const first = await fetch(server.url, streamRequest())
373-
await expect(first.text()).rejects.toThrow("idle timeout waiting for websocket")
373+
expect((await readTextError(first.text())).message).toContain("idle timeout waiting for websocket")
374374
const second = await fetch(server.url, streamRequest())
375375
const third = await fetch(server.url, streamRequest())
376376

@@ -394,9 +394,9 @@ describe("plugin.openai.ws-pool", () => {
394394
})
395395

396396
const first = await fetch(server.url, streamRequest())
397-
await expect(first.text()).rejects.toThrow("idle timeout waiting for websocket")
397+
expect((await readTextError(first.text())).message).toContain("idle timeout waiting for websocket")
398398
const second = await fetch(server.url, streamRequest())
399-
await expect(second.text()).rejects.toThrow("idle timeout waiting for websocket")
399+
expect((await readTextError(second.text())).message).toContain("idle timeout waiting for websocket")
400400
const third = await fetch(server.url, streamRequest())
401401

402402
expect(await third.text()).toBe("http")
@@ -425,11 +425,11 @@ describe("plugin.openai.ws-pool", () => {
425425
})
426426

427427
const first = await fetch(server.url, streamRequest())
428-
await expect(first.text()).rejects.toThrow("WebSocket closed before response.completed")
428+
expect((await readTextError(first.text())).message).toContain("WebSocket closed before response.completed")
429429
const second = await fetch(server.url, streamRequest())
430430
expect(await second.text()).toContain("data: [DONE]")
431431
const third = await fetch(server.url, streamRequest())
432-
await expect(third.text()).rejects.toThrow("WebSocket closed before response.completed")
432+
expect((await readTextError(third.text())).message).toContain("WebSocket closed before response.completed")
433433
const fourth = await fetch(server.url, streamRequest())
434434

435435
expect(await fourth.text()).toContain("data: [DONE]")
@@ -480,7 +480,7 @@ describe("plugin.openai.ws-pool", () => {
480480
expect(server.httpRequests).toHaveLength(1)
481481
expect(connections).toBe(1)
482482
abort.abort(new Error("stop"))
483-
await expect(firstText).rejects.toThrow("stop")
483+
expect((await readTextError(firstText)).message).toContain("stop")
484484
fetch.close()
485485
})
486486

@@ -518,7 +518,7 @@ describe("plugin.openai.ws-pool", () => {
518518
})
519519

520520
const first = await fetch(server.url, streamRequest())
521-
await expect(first.text()).rejects.toThrow("WebSocket closed before response.completed")
521+
expect((await readTextError(first.text())).message).toContain("WebSocket closed before response.completed")
522522
const second = await fetch(server.url, streamRequest())
523523
const third = await fetch(server.url, streamRequest())
524524

@@ -550,7 +550,7 @@ describe("plugin.openai.ws-pool", () => {
550550
const firstText = first.text()
551551
await waitFor(() => connections === 1, "first websocket did not connect")
552552
abort.abort(new Error("stop"))
553-
await expect(firstText).rejects.toThrow("stop")
553+
expect((await readTextError(firstText)).message).toContain("stop")
554554

555555
const second = await fetch(server.url, streamRequest())
556556

@@ -602,6 +602,19 @@ function streamRequest(headers?: Record<string, string>, signal?: AbortSignal):
602602
}
603603
}
604604

605+
async function readTextError(promise: Promise<string>) {
606+
// Bun 1.3.14 hangs on expect(response.text()).rejects for streams errored from ws callbacks.
607+
return promise.then(
608+
() => {
609+
throw new Error("Expected response text to reject")
610+
},
611+
(error) => {
612+
expect(error).toBeInstanceOf(Error)
613+
return error as Error
614+
},
615+
)
616+
}
617+
605618
async function createWebSocketServer(onConnection: (socket: WebSocket, request: IncomingMessage) => void) {
606619
const http = await createHttpServer()
607620
const server = new WebSocketServer({ server: http.server })

0 commit comments

Comments
 (0)