fix(tools): bound memory forget requests - #1451
Merged
ishaanxgupta merged 1 commit intoAug 13, 2026
Merged
Conversation
ishaanxgupta
approved these changes
Aug 13, 2026
This was referenced Aug 19, 2026
addyCooks
added a commit
to addyCooks/supermemory
that referenced
this pull request
Aug 19, 2026
supermemoryai#1451 bounded `DELETE /v4/memories` with a 30s abort, but the two signals were selected between with `??`: signal: options?.signal ?? AbortSignal.timeout(FETCH_TIMEOUT_MS) so they were mutually exclusive. Any caller who passed a cancellation signal silently dropped the timeout and the request went unbounded again - exactly the hang supermemoryai#1451 set out to remove - and there was no way to ask for both through the API. No production call site passes options today (ai-sdk.ts and openai/tools.ts both omit it), so this was latent. Composes the two with `AbortSignal.any` instead, so a caller signal cancels the request and the 30s ceiling still applies. The timeout signal is built once and reused for the bare case. Verified against a server that never responds: before this change the caller-signal path hangs indefinitely; after it, it rejects with TimeoutError at the deadline, an early caller abort still wins with AbortError, and an already-aborted signal rejects immediately. Test coverage in tool-operations.test.ts replaces the case that asserted the old select-one behaviour with four: caller abort propagates to the composed signal, the timeout still fires while the caller signal stays live, an already-aborted caller signal is forwarded, and an options object without a signal still gets the timeout.
addyCooks
added a commit
to addyCooks/supermemory
that referenced
this pull request
Aug 19, 2026
supermemoryai#1451 bounded `DELETE /v4/memories` with a 30s abort, but the two signals were selected between with `??`: signal: options?.signal ?? AbortSignal.timeout(FETCH_TIMEOUT_MS) so they were mutually exclusive. Any caller who passed a cancellation signal silently dropped the timeout and the request went unbounded again - exactly the hang supermemoryai#1451 set out to remove - and there was no way to ask for both through the API. No production call site passes options today (ai-sdk.ts and openai/tools.ts both omit it), so this was latent. Composes the two with `AbortSignal.any` instead, so a caller signal cancels the request and the 30s ceiling still applies. The timeout signal is built once and reused for the bare case. Verified against a server that never responds: before this change the caller-signal path hangs indefinitely; after it, it rejects with TimeoutError at the deadline, an early caller abort still wins with AbortError, and an already-aborted signal rejects immediately. tool-operations.test.ts replaces the case that asserted the old select-one behaviour with five: the caller signal is composed rather than substituted and its abort reason reaches the request, the timeout still fires while the caller signal stays open, an already-aborted caller signal is forwarded, the bare path still gets the 30s timeout signal itself, and an aborted fetch surfaces to the caller. Each case was checked against mutants of the fix - dropping the timeout from AbortSignal.any, composing with a signal that never fires, reverting to ??, and shortening the timeout - and every mutant fails at least one of them.
Agnik47
added a commit
to Agnik47/supermemory
that referenced
this pull request
Aug 25, 2026
`forgetMemoryRequest` combined the caller's signal and the 30s abort with `??`, making them mutually exclusive. Passing a cancellation signal removed the timeout, so a hung `DELETE /v4/memories` could wedge the tool call again — the exact condition supermemoryai#1451 set out to remove. There was also no way for a caller to ask for both cancellation and a timeout. Compose the two with `AbortSignal.any` instead of choosing between them. `AbortSignal.any` is available in Node 20.3+, Bun and workerd. No production call site passes `options` today (`ai-sdk.ts` and `openai/tools.ts` both omit it), so this was latent rather than live. The existing test asserted the buggy behaviour (`init.signal` being the caller's own signal), so it is replaced by two tests that pin the composed semantics: aborting the caller aborts the request, and the timeout leg still aborts the request on its own. Both fail against the previous implementation. Fixes supermemoryai#1549
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This prevents AI SDK and OpenAI tool memory-forget calls from remaining pending indefinitely when the API or network stalls.
Fixes #1452
Testing
The full tools test command still has two pre-existing failures requiring SUPERMEMORY_API_KEY and a missing test/claude-memory module. Package type-checking also reports existing dependency/test errors unrelated to this change.
Checklist