AI SDK 5 redesigned the message model, and most of what it breaks follows from that. The ai package dropped its React and RSC entrypoints, replaced the data stream API, and renamed or reshaped the types that describe a message. It also renamed the key that holds a tool’s schema and the fields on the parts streamText streams. Upgrade from 4.x and the typecheck fails on the first file that touches any of them.
What changed
- Two entrypoints left the package.
ai/reactis now@ai-sdk/reactandai/rscis now@ai-sdk/rsc, same names, new dependency. - Model message types were renamed, with aliases kept.
CoreMessageisModelMessage, the four role types gained theModelMessagesuffix, andconvertToCoreMessagesisconvertToModelMessages. The old names still compile as deprecated aliases. - Two renames are breaks.
IDGeneratorisIdGenerator, andexperimental_wrapLanguageModelis exported only aswrapLanguageModel. - UI message types changed shape.
MessageisUIMessage, and it has nocontentstring: text, files and tool calls are entries in apartsarray.ToolInvocation,Attachmentand theCoreTooltype family went with the fields they described. - A tool’s schema key is
inputSchema.parametersis a type error in v5, on the object handed totool()and on each entry oftoolshanded togenerateTextorstreamText. It is still wrong at every release up toai@7.0.99. - Stream parts renamed their fields. On what
streamTextstreams,textDeltaistext,argsisinputandresultisoutput.tool-call-deltabecametool-input-deltacarryingdelta,step-finishbecamefinish-stepwithproviderMetadata, andlogprobsis gone with no replacement. - The data stream API was replaced.
StreamDataand thecreateDataStream*helpers are gone; custom data travels as typed parts on a UI message stream. The LangChain and LlamaIndex adapters moved to their own packages. The assistant API was removed with no replacement.
Before and after
Renames with no shape change are what Emendant rewrites. This file passes one of them on without calling it, which is why the entry anchors on the import:
import { experimental_wrapLanguageModel, type IDGenerator } from 'ai';
export const wrapped = (model: never, middleware: never) => experimental_wrapLanguageModel({ model, middleware });
export function label(generate: IDGenerator): string { return `msg_${generate()}`;}
export const wrap = experimental_wrapLanguageModel;After npx emendant fix:
import { wrapLanguageModel, type IdGenerator } from 'ai';
export const wrapped = (model: never, middleware: never) => wrapLanguageModel({ model, middleware });
export function label(generate: IdGenerator): string { return `msg_${generate()}`;}
export const wrap = wrapLanguageModel;The tool rename is one key at each site, and the schema value stays put:
export const weather = tool({ description: 'Look up the weather', parameters: schema, execute: async () => ({ temperature: 12 }),});export const weather = tool({ description: 'Look up the weather', inputSchema: schema, execute: async () => ({ temperature: 12 }),});The entrypoint moves are the same edit on the specifier: 'ai/react' becomes '@ai-sdk/react' and 'ai/rsc' becomes '@ai-sdk/rsc'. Three reads off a fullStream part are one word each: part.textDelta becomes part.text, part.args becomes part.input and part.result becomes part.output. The shape changes have no mechanical form: a StreamData route becomes a writer inside createUIMessageStream, and message.content becomes the text parts of message.parts.
Migration guidance and its limits
The ten deterministic patches are safe as offered. The two entrypoint rewrites do not add @ai-sdk/react or @ai-sdk/rsc to your manifest, so install them, or the verification run reports those patches as failing until you do.
The nine assisted changes are the reshapes. Emendant writes them only when you name a model provider, because the right edit depends on how your code reads a message or builds a stream. Two of them turn on the type tag too: argsTextDelta sits in a branch v5 never enters, and experimental_providerMetadata is a rename under step-finish and a removal under finish. Without a provider they are reported with guidance. The assistant API removal and a logprobs read are report only, because nothing in v5 replaces either.
A repository on 6.x or 7.x still writing parameters is reported without --adopted, under a heading saying it is affected today.
Two limits: createIdGenerator now takes its size at creation, which the IdGenerator rename does not touch, and useChat itself changed in 5.0.0 in ways this entry does not describe. A clean scan says a file uses none of the constructs below, nothing more.
What Emendant detects, fixes and verifies
22 changes in ai 5.0.0. 10 patched by a transform, 10 patched only with a model provider you name, 2 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 v4 UI message types were replaced by the UIMessage typesai-npm-5.0.0-message-types-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
CoreMessage renamed to ModelMessageai-npm-5.0.0-coremessage-deprecated | Deprecation |
| Patch, written by the replace-import-specifier transform | Your typecheck and tests |
The role specific CoreMessage types were renamedai-npm-5.0.0-coremessage-role-aliases-deprecated | Deprecation |
| Patch, only when you name a model provider | Your typecheck and tests |
convertToCoreMessages renamed to convertToModelMessagesai-npm-5.0.0-converttocoremessages-deprecated | Deprecation |
| Patch, written by the replace-import-specifier transform | Your typecheck and tests |
IDGenerator renamed to IdGeneratorai-npm-5.0.0-idgenerator-type-renamed | Breaking |
| Patch, written by the replace-import-specifier transform | Your typecheck and tests |
experimental_wrapLanguageModel became wrapLanguageModelai-npm-5.0.0-wraplanguagemodel-stable | Breaking |
| Patch, written by the replace-import-specifier transform | Your typecheck and tests |
The ai/rsc entrypoint moved to @ai-sdk/rscai-npm-5.0.0-rsc-subpath-extracted | Breaking |
| Patch, written by the replace-module-path transform | Your typecheck and tests |
The ai/react entrypoint was removedai-npm-5.0.0-react-subpath-removed | Breaking |
| Patch, written by the replace-module-path transform | Your typecheck and tests |
The data stream API was replaced by UI message streamsai-npm-5.0.0-data-stream-api-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
LangChainAdapter moved to @ai-sdk/langchainai-npm-5.0.0-langchain-adapter-moved | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
LlamaIndexAdapter moved to @ai-sdk/llamaindexai-npm-5.0.0-llamaindex-adapter-moved | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
The deprecated CoreTool types were removedai-npm-5.0.0-coretool-types-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
The assistant API was removedai-npm-5.0.0-assistant-api-removed | Breaking |
| Report only | Not applicable |
ToolInvocation was replaced by typed tool partsai-npm-5.0.0-toolinvocation-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
Attachment was replaced by file partsai-npm-5.0.0-attachment-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
A tool definition names its schema inputSchema instead of parametersai-npm-5.0.0-tool-parameters-renamed | Breaking |
| Patch, written by the rename-property transform | Your typecheck and tests |
A text-delta part on streamText's fullStream carries text instead of textDeltaai-npm-5.0.0-fullstream-textdelta-renamed | Breaking |
| Patch, written by the rename-property transform | Your typecheck and tests |
Tool parts on streamText's fullStream carry input instead of argsai-npm-5.0.0-fullstream-args-renamed | Breaking |
| Patch, written by the rename-property transform | Your typecheck and tests |
A tool-result part on streamText's fullStream carries output instead of resultai-npm-5.0.0-fullstream-result-renamed | Breaking |
| Patch, written by the rename-property transform | Your typecheck and tests |
experimental_providerMetadata is gone from the parts fullStream yieldsai-npm-5.0.0-fullstream-provider-metadata-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
logprobs is gone from the parts fullStream yieldsai-npm-5.0.0-fullstream-logprobs-removed | Breaking |
| Report only | Not applicable |
The tool-call-delta part became tool-input-delta and carries delta instead of argsTextDeltaai-npm-5.0.0-fullstream-argstextdelta-renamed | 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-09-21.1, sequence 28, signed 21 September 2026- Minimum CLI
emendant@0.1.4- Feed entry
feed/npm/ai/5.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@5.0.0
- package.jsonvercel/ai at ai@5.0.0
- ai@5.0.0npm registry, the published package
- ai@4.0.0npm registry, the published package
- ai@7.0.99npm 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.