Compare commits
2 Commits
build-runt
...
fix/5266-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13c8b2ada5 | ||
|
|
261a05bfc7 |
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -114,6 +114,7 @@ export class UrbitSSEClient {
|
||||
Cookie: this.cookie,
|
||||
},
|
||||
body: JSON.stringify([subscription]),
|
||||
signal: AbortSignal.timeout(30_000),
|
||||
});
|
||||
|
||||
if (!response.ok && response.status !== 204) {
|
||||
@@ -130,6 +131,7 @@ export class UrbitSSEClient {
|
||||
Cookie: this.cookie,
|
||||
},
|
||||
body: JSON.stringify(this.subscriptions),
|
||||
signal: AbortSignal.timeout(30_000),
|
||||
});
|
||||
|
||||
if (!createResp.ok && createResp.status !== 204) {
|
||||
@@ -152,6 +154,7 @@ export class UrbitSSEClient {
|
||||
json: "Opening API channel",
|
||||
},
|
||||
]),
|
||||
signal: AbortSignal.timeout(30_000),
|
||||
});
|
||||
|
||||
if (!pokeResp.ok && pokeResp.status !== 204) {
|
||||
@@ -164,12 +167,21 @@ export class UrbitSSEClient {
|
||||
}
|
||||
|
||||
async openStream() {
|
||||
// Use AbortController with manual timeout so we only abort during initial connection,
|
||||
// not after the SSE stream is established and actively streaming.
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 60_000);
|
||||
|
||||
const response = await fetch(this.channelUrl, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Accept: "text/event-stream",
|
||||
Cookie: this.cookie,
|
||||
},
|
||||
signal: controller.signal,
|
||||
}).finally(() => {
|
||||
// Clear timeout once connection established (headers received) or on failure.
|
||||
clearTimeout(timeoutId);
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -279,6 +291,7 @@ export class UrbitSSEClient {
|
||||
Cookie: this.cookie,
|
||||
},
|
||||
body: JSON.stringify([pokeData]),
|
||||
signal: AbortSignal.timeout(30_000),
|
||||
});
|
||||
|
||||
if (!response.ok && response.status !== 204) {
|
||||
@@ -296,6 +309,7 @@ export class UrbitSSEClient {
|
||||
headers: {
|
||||
Cookie: this.cookie,
|
||||
},
|
||||
signal: AbortSignal.timeout(30_000),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -364,6 +378,7 @@ export class UrbitSSEClient {
|
||||
Cookie: this.cookie,
|
||||
},
|
||||
body: JSON.stringify(unsubscribes),
|
||||
signal: AbortSignal.timeout(30_000),
|
||||
});
|
||||
|
||||
await fetch(this.channelUrl, {
|
||||
@@ -371,6 +386,7 @@ export class UrbitSSEClient {
|
||||
headers: {
|
||||
Cookie: this.cookie,
|
||||
},
|
||||
signal: AbortSignal.timeout(30_000),
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.error?.(`Error closing channel: ${String(error)}`);
|
||||
|
||||
Reference in New Issue
Block a user