diff --git a/src/discord/monitor/gateway-plugin.ts b/src/discord/monitor/gateway-plugin.ts index 3e6e70944d2..b4030bcb386 100644 --- a/src/discord/monitor/gateway-plugin.ts +++ b/src/discord/monitor/gateway-plugin.ts @@ -11,9 +11,12 @@ const DISCORD_GATEWAY_BOT_URL = "https://discord.com/api/v10/gateway/bot"; const DEFAULT_DISCORD_GATEWAY_URL = "wss://gateway.discord.gg/"; type DiscordGatewayMetadataResponse = Pick; +type DiscordGatewayFetchInit = Record & { + headers?: Record; +}; type DiscordGatewayFetch = ( input: string, - init?: Record, + init?: DiscordGatewayFetchInit, ) => Promise; export function resolveDiscordGatewayIntents( @@ -74,15 +77,16 @@ function createGatewayMetadataError(params: { async function fetchDiscordGatewayInfo(params: { token: string; fetchImpl: DiscordGatewayFetch; - fetchInit?: Record; + fetchInit?: DiscordGatewayFetchInit; }): Promise { let response: DiscordGatewayMetadataResponse; try { response = await params.fetchImpl(DISCORD_GATEWAY_BOT_URL, { + ...params.fetchInit, headers: { + ...params.fetchInit?.headers, Authorization: `Bot ${params.token}`, }, - ...params.fetchInit, }); } catch (error) { throw createGatewayMetadataError({ @@ -92,7 +96,16 @@ async function fetchDiscordGatewayInfo(params: { }); } - const body = await response.text(); + let body: string; + try { + body = await response.text(); + } catch (error) { + throw createGatewayMetadataError({ + detail: error instanceof Error ? error.message : String(error), + transient: true, + cause: error, + }); + } const summary = summarizeGatewayResponseBody(body); const transient = isTransientDiscordGatewayResponse(response.status, body); @@ -128,7 +141,7 @@ function createGatewayPlugin(params: { autoInteractions: boolean; }; fetchImpl: DiscordGatewayFetch; - fetchInit?: Record; + fetchInit?: DiscordGatewayFetchInit; wsAgent?: HttpsProxyAgent; }): GatewayPlugin { class SafeGatewayPlugin extends GatewayPlugin { diff --git a/src/discord/monitor/provider.proxy.test.ts b/src/discord/monitor/provider.proxy.test.ts index 50caec4a2c8..0b45fd2a2e7 100644 --- a/src/discord/monitor/provider.proxy.test.ts +++ b/src/discord/monitor/provider.proxy.test.ts @@ -255,4 +255,30 @@ describe("createDiscordGatewayPlugin", () => { ); expect(baseRegisterClientSpy).toHaveBeenCalledTimes(1); }); + + it("maps body read failures to fetch failed", async () => { + const runtime = createRuntime(); + globalFetchMock.mockResolvedValue({ + ok: true, + status: 200, + text: async () => { + throw new Error("body stream closed"); + }, + } as unknown as Response); + const plugin = createDiscordGatewayPlugin({ + discordConfig: {}, + runtime, + }); + + await expect( + ( + plugin as unknown as { + registerClient: (client: { options: { token: string } }) => Promise; + } + ).registerClient({ + options: { token: "token-123" }, + }), + ).rejects.toThrow("Failed to get gateway information from Discord: fetch failed"); + expect(baseRegisterClientSpy).not.toHaveBeenCalled(); + }); });