From 255f71bac6371ab689ac546124ad7f80c4376b11 Mon Sep 17 00:00:00 2001 From: rajashidattapy Date: Wed, 19 Aug 2026 23:25:49 +0530 Subject: [PATCH 1/2] fix(tools): keep the forget timeout when a caller passes a signal `forgetMemoryRequest` combined the caller signal and the 30s timeout with `??`, so passing a cancellation signal made the DELETE unbounded again -- the exact hang #1451 set out to remove. Compose them with `AbortSignal.any` so cancellation and the timeout both stay live. --- packages/tools/src/shared/forget-memory.ts | 7 ++++++- packages/tools/src/tool-operations.test.ts | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/tools/src/shared/forget-memory.ts b/packages/tools/src/shared/forget-memory.ts index 8691c92ac..917e127d6 100644 --- a/packages/tools/src/shared/forget-memory.ts +++ b/packages/tools/src/shared/forget-memory.ts @@ -33,7 +33,12 @@ export async function forgetMemoryRequest( Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify(params), - signal: options?.signal ?? AbortSignal.timeout(FETCH_TIMEOUT_MS), + signal: options?.signal + ? AbortSignal.any([ + options.signal, + AbortSignal.timeout(FETCH_TIMEOUT_MS), + ]) + : AbortSignal.timeout(FETCH_TIMEOUT_MS), }) if (!response.ok) { diff --git a/packages/tools/src/tool-operations.test.ts b/packages/tools/src/tool-operations.test.ts index 136a19bea..20608e14b 100644 --- a/packages/tools/src/tool-operations.test.ts +++ b/packages/tools/src/tool-operations.test.ts @@ -112,7 +112,7 @@ describe("memoryForget", () => { expect(init.signal).toBeInstanceOf(AbortSignal) }) - it("uses a caller-provided signal instead of creating a timeout", async () => { + it("keeps the timeout when the caller provides a signal", async () => { const fetchMock = stubFetch() const controller = new AbortController() @@ -124,7 +124,10 @@ describe("memoryForget", () => { ) const [, init] = fetchMock.mock.calls[0] as [string, RequestInit] - expect(init.signal).toBe(controller.signal) + // A composed signal, not the caller's — so the 30s timeout still applies. + expect(init.signal).not.toBe(controller.signal) + controller.abort() + expect(init.signal?.aborted).toBe(true) }) it("throws a descriptive error on non-2xx responses", async () => { From a919d4d42caf883a9cedd51b37a31c44eac89136 Mon Sep 17 00:00:00 2001 From: rajashidattapy Date: Wed, 19 Aug 2026 23:29:06 +0530 Subject: [PATCH 2/2] style(tools): apply Biome formatting --- packages/tools/src/shared/forget-memory.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/tools/src/shared/forget-memory.ts b/packages/tools/src/shared/forget-memory.ts index 917e127d6..2f3267222 100644 --- a/packages/tools/src/shared/forget-memory.ts +++ b/packages/tools/src/shared/forget-memory.ts @@ -34,10 +34,7 @@ export async function forgetMemoryRequest( }, body: JSON.stringify(params), signal: options?.signal - ? AbortSignal.any([ - options.signal, - AbortSignal.timeout(FETCH_TIMEOUT_MS), - ]) + ? AbortSignal.any([options.signal, AbortSignal.timeout(FETCH_TIMEOUT_MS)]) : AbortSignal.timeout(FETCH_TIMEOUT_MS), })