diff --git a/CHANGELOG.md b/CHANGELOG.md index 95088e06ba..a7cbc7480d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Docs: https://docs.openclaw.ai - Telegram: restore draft streaming partials. (#5543) Thanks @obviyus. - Onboarding: friendlier Windows onboarding message. (#6242) Thanks @shanselman. - TUI: prevent crash when searching with digits in the model selector. +- Tlon: clear SSE connection timeout on failed connect. (#5926) Thanks @hclsys. - Agents: wire before_tool_call plugin hook into tool execution. (#6570) Thanks @ryancnelson. - Browser: secure Chrome extension relay CDP sessions. - Docker: use container port for gateway command instead of host port. (#5110) Thanks @mise42. diff --git a/extensions/tlon/src/urbit/sse-client.test.ts b/extensions/tlon/src/urbit/sse-client.test.ts index f194aafc2f..6eea1592ef 100644 --- a/extensions/tlon/src/urbit/sse-client.test.ts +++ b/extensions/tlon/src/urbit/sse-client.test.ts @@ -37,4 +37,23 @@ describe("UrbitSSEClient", () => { path: "/dm/~zod", }); }); + + it("clears the connection timeout when fetch fails", async () => { + const timeoutId = 123 as unknown as NodeJS.Timeout; + const setTimeoutSpy = vi.spyOn(global, "setTimeout").mockReturnValue(timeoutId); + const clearTimeoutSpy = vi.spyOn(global, "clearTimeout"); + + mockFetch.mockRejectedValue(new Error("network down")); + + const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123"); + + try { + await expect(client.openStream()).rejects.toThrow("network down"); + expect(setTimeoutSpy).toHaveBeenCalled(); + expect(clearTimeoutSpy).toHaveBeenCalledWith(timeoutId); + } finally { + setTimeoutSpy.mockRestore(); + clearTimeoutSpy.mockRestore(); + } + }); }); diff --git a/extensions/tlon/src/urbit/sse-client.ts b/extensions/tlon/src/urbit/sse-client.ts index c985cf9f1d..9dbe495c77 100644 --- a/extensions/tlon/src/urbit/sse-client.ts +++ b/extensions/tlon/src/urbit/sse-client.ts @@ -179,11 +179,11 @@ export class UrbitSSEClient { Cookie: this.cookie, }, signal: controller.signal, + }).finally(() => { + // Clear timeout once connection established (headers received) or on failure. + clearTimeout(timeoutId); }); - // Clear timeout once connection established (headers received) - clearTimeout(timeoutId); - if (!response.ok) { throw new Error(`Stream connection failed: ${response.status}`); }