Repository navigation
Conversation
…quest The Converse adapter called `client.send(command)` without the caller's signal. Aborting a chat left the request to Bedrock open until Bedrock answered. `chatStream`, `structuredOutput` and `structuredOutputStream` now pass `request.signal` to `client.send` as the SDK's `abortSignal`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uest The adapter sent its raw stream fetch and its `chat.complete` call without the caller's signal. Aborting a chat left the request to Mistral open until Mistral answered. Both calls now carry `request.signal`. The SDK drops its timeout (`timeoutMs`, 30 s by default) when a request has a signal. The structured output call combines the two signals with `AbortSignal.any`, so it still times out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: f527e71 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Bedrock Converse signal forwarding packages/ai-bedrock/src/adapters/converse-text.ts, packages/ai-bedrock/tests/converse/abort-signal-wire.test.ts, .changeset/bedrock-converse-forward-abort-signal.md |
Bedrock Converse methods pass request signals to the AWS SDK for streaming and structured-output requests. Tests check propagation for streaming chat and structured output. |
Mistral signal and timeout forwarding packages/ai-mistral/src/adapters/text.ts, packages/ai-mistral/tests/abort-signal-wire.test.ts, .changeset/mistral-forward-abort-signal.md |
Mistral streaming and structured-output requests receive the request signal. Structured output combines the signal with a timeout when applicable. Tests check abort propagation and timeout rejection. |
Priority:
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Bug fix
Sequence Diagram(s)
sequenceDiagram
participant Caller
participant BedrockConverseTextAdapter
participant AWS SDK client
Caller->>BedrockConverseTextAdapter: Send request with AbortSignal
BedrockConverseTextAdapter->>AWS SDK client: Send Converse request with abortSignal
Caller->>BedrockConverseTextAdapter: Abort request
AWS SDK client-->>BedrockConverseTextAdapter: Reject aborted request
sequenceDiagram
participant Caller
participant MistralTextAdapter
participant Mistral request
Caller->>MistralTextAdapter: Send request with AbortSignal
MistralTextAdapter->>Mistral request: Pass signal to fetch or chat.complete
Caller->>MistralTextAdapter: Abort request
Mistral request-->>MistralTextAdapter: Reject aborted request
Suggested reviewers: alemtuzlak
Merge Risk: 
Minimal · up to f527e
-
No actionable merge-blocking risk remains for abort-signal forwarding under the supported test workflows.
Pre-merge checks: 
5
-
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 4 files. (2 skipped: 2 unsupported.)
-
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
Aborting a
chat()run on the Bedrock Converse adapter or the Mistral adapter now cancels the request to the provider, for both streaming and structured output.🎯 Changes
BedrockConverseTextAdapterpasses the caller's abort signal (options.request.signal) toclient.sendas the AWS SDK'sabortSignal. This coverschatStream,structuredOutputandstructuredOutputStream.MistralTextAdaptersets the signal on the fetch of its raw stream and passes it tochat.completefor structured output. That call keeps the SDK's timeout (see Root cause).packages/ai-bedrock/tests/converse/abort-signal-wire.test.tsandpackages/ai-mistral/tests/abort-signal-wire.test.ts.@tanstack/ai-bedrockand one for@tanstack/ai-mistral.Docs: no change.
docs/chat/streaming.mdalready says that theAbortControllergiven tochat()stops the model on the server. These two adapters now do that.✅ Checklist
pnpm run test:pr, or these tests do not apply to this pull request.docs/for this change, or this change is not user-facing.pnpm changeset), or this PR does not change a published package.🚀 Release Impact
Root cause
Issue.
abortController.abort()on achat()run with the Bedrock Converse adapter or the Mistral adapter leaves the HTTP request open, and the provider keeps generating. In a 45 s run against a server that never answers, the Bedrock request and the Mistral stream stayed open. Mistral structured output closed only at the SDK's 30 s timeout.Cause. The engine passes the caller's signal to the adapter as
request.signal.BedrockConverseTextAdaptercalledclient.send(command)with no options.MistralTextAdaptersent its raw streamfetchandclient.chat.complete(params)without the signal.Fix. Converse gives the signal to
client.sendas{ abortSignal }. Mistral setssignalon the raw stream fetch and passes{ signal }tochat.complete. The Mistral SDK applies its timeout (timeoutMs, 30 s by default) only to a request without a signal. So the structured output call combines the caller's signal and that timeout withAbortSignal.any. A call without a signal sends the same request as before.Possible alternatives
ollamatakes no per-call signal. Both SDKs here take a per-call signal, so a per-call client adds code for no gain.AbortControllerthen loses the 30 s timeout, or thetimeoutMsthat the user set. A timeout for every adapter belongs inchat({ timeout })(feat(ai): add a timeout option to chat(), matching the media activities #1517). The30_000default is safe to copy, because@tanstack/ai-mistralpins@mistralai/mistralaito 2.2.0.Testing
Commands run
pnpm run test:prpasses.@tanstack/ai-bedrock: 199 tests pass.@tanstack/ai-mistral: 115 tests pass. Onmain, 5 of the 6 new tests fail. The sixth makes sure that structured output with a signal still times out.bedrock,bedrock-responses,mistralandvertex-mistralproviders pass, withbedrock-converse-cache,bedrock-converse-truncated-tool-callandmistral-strict-tool-null-wire.testing/e2e/README.md, and only two narrow specs drive it:bedrock-converse-cache.spec.tsthrough a fixed-stream mount, andbedrock-converse-truncated-tool-call.spec.tsthrough one aimock fixture. Also, aimock cannot show that the provider request closed.Repro, written for this PR and not committed: a local server that never answers. Bedrock uses an HTTP/2 server, because the AWS SDK's default handler is
NodeHttp2Handler. Mistral uses an HTTP/1.1 server. When the server gets the request, the test aborts and waits 1 s for the request to close. Themid-streamcase aborts after the response headers.On
main(98055ca):On this branch:
Manual test
main, copypackages/ai-bedrock/tests/converse/abort-signal-wire.test.tsandpackages/ai-mistral/tests/abort-signal-wire.test.tsfrom this branch.pnpm --filter @tanstack/ai-bedrock test:lib abort-signal-wire. All 3 tests fail.pnpm --filter @tanstack/ai-mistral test:lib abort-signal-wire. The two abort tests fail. The timeout test passes, becausemainsends no signal.How this PR makes testing easy
The two
abort-signal-wire.test.tsfiles run the real SDK clients against a transport that never answers. Only the caller's signal can end the request.Risk / rollback
Low. A call without a signal sends the same request as before.
sendStreamandsendonBedrockConverseTextAdapterare protected and now take an optionalsignal. A subclass that overrides them still compiles, but it must pass the signal toclient.sendto keep the abort. To undo, revert this PR.🤖 Generated with Claude Code
Summary by CodeRabbit