diff --git a/extensions/discord/src/monitor/gateway-plugin.ts b/extensions/discord/src/monitor/gateway-plugin.ts index f97babae40c..fda66c215c8 100644 --- a/extensions/discord/src/monitor/gateway-plugin.ts +++ b/extensions/discord/src/monitor/gateway-plugin.ts @@ -270,11 +270,22 @@ function createGatewayPlugin(params: { } override createWebSocket(url: string) { - if (!params.wsAgent) { - return super.createWebSocket(url); + if (!url) { + throw new Error("Gateway URL is required"); } + // Avoid Node's undici-backed global WebSocket here. We have seen late + // close-path crashes during Discord gateway teardown; the ws transport is + // already our proxy path and behaves predictably for lifecycle cleanup. const WebSocketCtor = params.testing?.webSocketCtor ?? ws.default; - return new WebSocketCtor(url, { agent: params.wsAgent }); + const socket = new WebSocketCtor(url, params.wsAgent ? { agent: params.wsAgent } : undefined); + if ("binaryType" in socket) { + try { + socket.binaryType = "arraybuffer"; + } catch { + // Ignore runtimes that expose a readonly binaryType. + } + } + return socket; } } diff --git a/extensions/discord/src/monitor/provider.proxy.test.ts b/extensions/discord/src/monitor/provider.proxy.test.ts index 4fdf8c939cb..1f9eac6887c 100644 --- a/extensions/discord/src/monitor/provider.proxy.test.ts +++ b/extensions/discord/src/monitor/provider.proxy.test.ts @@ -244,6 +244,21 @@ describe("createDiscordGatewayPlugin", () => { expect(baseRegisterClientSpy).toHaveBeenCalledTimes(1); }); + it("uses ws for gateway sockets even without proxy", () => { + const runtime = createRuntime(); + const plugin = createDiscordGatewayPlugin({ + discordConfig: {}, + runtime, + }); + + const createWebSocket = (plugin as unknown as { createWebSocket: (url: string) => unknown }) + .createWebSocket; + createWebSocket("wss://gateway.discord.gg"); + + expect(webSocketSpy).toHaveBeenCalledWith("wss://gateway.discord.gg", undefined); + expect(wsProxyAgentSpy).not.toHaveBeenCalled(); + }); + it("maps plain-text Discord 503 responses to fetch failed", async () => { await expectGatewayRegisterFallback({ ok: false,