From 80dcd2d05476555fbc018d4c7e1a3542c5f47697 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 15 Feb 2026 03:11:10 +0000 Subject: [PATCH] Cover repeated inactive cleanup failures with per-attempt onError Co-authored-by: Eric Allam --- packages/ai/src/chatTransport.test.ts | 59 +++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/packages/ai/src/chatTransport.test.ts b/packages/ai/src/chatTransport.test.ts index 425d600b6..40947ddaf 100644 --- a/packages/ai/src/chatTransport.test.ts +++ b/packages/ai/src/chatTransport.test.ts @@ -625,6 +625,59 @@ describe("TriggerChatTransport", function () { expect(errors[0]?.error.message).toBe("cleanup delete failed"); }); + it("retries inactive cleanup and reports each persistent delete failure", async function () { + const errors: TriggerChatTransportError[] = []; + const runStore = new AlwaysFailCleanupDeleteRunStore(); + runStore.set({ + chatId: "chat-inactive-delete-always-fails", + runId: "run_inactive_delete_always_fails", + publicAccessToken: "pk_inactive_delete_always_fails", + streamKey: "chat-stream", + lastEventId: "10-0", + isActive: false, + }); + + const transport = new TriggerChatTransport({ + task: "chat-task", + stream: "chat-stream", + accessToken: "pk_trigger", + runStore, + onError: function onError(error) { + errors.push(error); + }, + }); + + let fetchCalls = 0; + (transport as any).fetchRunStream = async function fetchRunStream() { + fetchCalls += 1; + throw new Error("unexpected reconnect fetch"); + }; + + const firstReconnect = await transport.reconnectToStream({ + chatId: "chat-inactive-delete-always-fails", + }); + const secondReconnect = await transport.reconnectToStream({ + chatId: "chat-inactive-delete-always-fails", + }); + + expect(firstReconnect).toBeNull(); + expect(secondReconnect).toBeNull(); + expect(fetchCalls).toBe(0); + expect(errors).toHaveLength(2); + expect(errors[0]).toMatchObject({ + phase: "reconnect", + chatId: "chat-inactive-delete-always-fails", + runId: "run_inactive_delete_always_fails", + }); + expect(errors[1]).toMatchObject({ + phase: "reconnect", + chatId: "chat-inactive-delete-always-fails", + runId: "run_inactive_delete_always_fails", + }); + expect(errors[0]?.error.message).toBe("cleanup delete always fails"); + expect(errors[1]?.error.message).toBe("cleanup delete always fails"); + }); + it("retries inactive reconnect cleanup on subsequent reconnect attempts", async function () { const errors: TriggerChatTransportError[] = []; const runStore = new FailingCleanupDeleteRunStore(1); @@ -3802,6 +3855,12 @@ class FailingCleanupDeleteValueRunStore extends InMemoryTriggerChatRunStore { } } +class AlwaysFailCleanupDeleteRunStore extends InMemoryTriggerChatRunStore { + public delete(_chatId: string): void { + throw new Error("cleanup delete always fails"); + } +} + class FailingCleanupSetAndDeleteRunStore extends InMemoryTriggerChatRunStore { private setCallCount = 0; public readonly setCalls: string[] = [];