AI SDK 4.0 removes the 2.x streaming architecture. Every per-provider stream helper, AIStream and its supporting exports, StreamingTextResponse and streamToResponse are gone from the package. Anything that built a route on a helper wrapping a raw provider response has to move to streamText and the method its result exposes for the same job.
What changed
- The per-provider stream helpers are gone.
OpenAIStream,AnthropicStream,MistralStream,GoogleGenerativeAIStream,HuggingFaceStream,CohereStream,LangChainStream,ReplicateStream,InkeepStreamand the fiveAWSBedrockvariants are all exported by 3.4.33 and none by 4.0.0.streamText, called with a model from the matching@ai-sdkprovider package, replaces the call each one wrapped. AIStreamand its supporting exports are gone.AIStream,createCallbacksTransformer,createEventStreamTransformer,trimStartOfStreamHelperandreadableFromAsyncIterablego with it.streamText’stoDataStream()replaces the hand-built stream.StreamingTextResponseis gone. A route returnsstreamText’stoDataStreamResponse()instead of wrapping a stream in this class.streamToResponseis gone. A Node route callspipeDataStreamToResponse()onstreamText’s result instead of piping a stream into aServerResponse.
Before and after
A 2.x route wrapping a provider response and returning it:
import { OpenAIStream, StreamingTextResponse } from 'ai';
export async function openaiRoute(response: Response): Promise<Response> { const stream = OpenAIStream(response); return new StreamingTextResponse(stream);}The 4.0 shape moves the provider call inside streamText and returns its own response:
import { streamText } from 'ai';import { openai } from '@ai-sdk/openai';
export async function route(prompt: string): Promise<Response> { const result = streamText({ model: openai('gpt-4o'), prompt }); return result.toDataStreamResponse();}The Node server case follows the same shape, with pipeDataStreamToResponse() taking the ServerResponse that streamToResponse used to:
import { AIStream, streamToResponse } from 'ai';
export function nodeRoute(response: Response, serverResponse: ServerResponse): void { const stream = AIStream(response); streamToResponse(stream, serverResponse);}becomes
import { streamText } from 'ai';import { openai } from '@ai-sdk/openai';
export function nodeRoute(prompt: string, serverResponse: ServerResponse): void { const result = streamText({ model: openai('gpt-4o'), prompt }); result.pipeDataStreamToResponse(serverResponse);}Migration guidance and its limits
All four changes need a model provider named on the command line or in emendant.json. None has a deterministic patch, because each one restructures the call rather than renaming it: the helper took a raw provider response, and streamText makes the provider call itself, so an edit at the import site alone cannot produce the new shape.
Where a route imports both a provider helper and StreamingTextResponse, the two findings describe one migration rather than two. Move the provider call into streamText first, and the response wrapper falls away with it.
A clean scan proves only that none of the four removed names is imported from ai in the files it walked. It does not prove the route still streams correctly after the rewrite, or that a callback passed to a removed helper’s options was carried over to streamText’s onFinish or onChunk. Typecheck and test the result, as the entry asks.
What Emendant detects, fixes and verifies
4 changes in ai 4.0.0. 0 patched by a transform, 4 patched only with a model provider you name, 0 report only. Every patch is proved in a copy of your repository before it is offered, and its header names the checks that passed. This table is generated from the feed entry, so it cannot claim more than the entry does.
| Change | Severity | Detects | Fix | Verified by |
|---|---|---|---|---|
The 2.x provider stream helpers were removedai-npm-4.0.0-legacy-provider-streams-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
AIStream and its related exports were removedai-npm-4.0.0-aistream-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
StreamingTextResponse was removedai-npm-4.0.0-streamingtextresponse-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
streamToResponse was removedai-npm-4.0.0-streamtoresponse-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
emendant explain <change-id> prints any row's entry, guidance and sources at the terminal.
Coverage
- Snapshot
2026-08-28.1, sequence 11, signed 28 August 2026- Minimum CLI
emendant@0.1.0- Feed entry
feed/npm/ai/4.0.0.json
emendant feed status shows the snapshot your machine holds, and emendant feed update fetches the latest.
Primary sources
Every claim above was checked against these, each pinned to the release rather than to a default branch.
- Migration guidevercel/ai at ai@4.0.0
- ai@4.0.0npm registry, the published package
- ai@3.4.33npm registry, the published package
Scan your repository
Runs locally, reads your lockfile and source, sends nothing anywhere.
npx emendant scanThen npx emendant fix writes the patches the table says exist. The getting started guide covers the flags and the patch grades.