You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ac01b79: Allow validating assistant UI messages with empty parts so persisted errored responses remain loadable.
2696562: experimental_streamTranscribe result promises now resolve without consuming fullStream: accessing any result promise consumes the stream internally. Previously await result.text alone deadlocked on transform backpressure. Because live transcription streams can be unbounded, fullStream is explicitly single-consumer (no replay buffering): access it once, before any result promise, when both stream parts and final results are needed.
7805e4a: Cancelling the experimental_streamTranscribefullStream now also aborts a still-pending doStream setup, so a model whose doStream has not yet resolved is cancelled instead of leaking.
f8e82fd: Update the experimental_streamTranscribe unsupported-model error message now that gateway string model IDs can support streaming transcription.
be7f05a: Add fingerprintTools and detectToolDrift to detect MCP tool-definition drift ("rug pull"). Pin a tool set's server-controlled fields (string description, input schema, title) at trust time with fingerprintTools, then diff later fetches with detectToolDrift to catch injected descriptions or widened schemas before passing tools to the model. Baseline storage and the drift response remain the app's responsibility.
ee55a07: Preserve tool approval signatures when approvals transition to responded.
aad737d: Use own-property checks when resolving per-tool approvals so tool names and approval ids that match inherited object properties (e.g. constructor, toString, valueOf, __proto__) are treated as unconfigured/absent.
@ai-sdk/policy-opa: wrapMcpTools builds its per-tool map with a null prototype and reads supplied approvals via an own-property check, and shadow guards its per-tool map lookup the same way.
ai: tool and tool-context lookups keyed by a model- or client-supplied name now go through an own-property check (getOwn), so a name matching an inherited object property resolves to "no such tool"/"unconfigured" instead of a prototype value. This covers the approval path (per-tool approval resolution and replay re-validation) as well as tool-call parsing, execution, streaming callbacks, and UI message conversion/validation. The human-in-the-loop approval matching (collectToolApprovals) and streaming tool-name maps are built with a null prototype so a client-supplied id that matches an inherited property no longer slips past the "unknown approval" / "tool call not found" guards.
0f93c57: feat (video): support video (not just image) reference inputs in inputReferences for reference-to-video generation
d598481: Fix: convertToModelMessages no longer emits an empty assistant message when a block contains only unknown data parts (e.g. a data part before step-start with no convertDataPart provided)
a2750db: fix(ai): prune orphaned tool-approval responses in pruneMessages
When pruning a specific tool by name (toolCalls: [{ type, tools: [...] }]), pruneMessages left the tool's tool-approval-response in place while removing its tool-approval-request and tool-call. The tool name of an approval response was resolved per-message, but approval responses live in a separate tool message from their approval request, so the name could never be resolved and the response was always kept. Tool name resolution is now done across all messages, so approval requests and responses are pruned together.
3debdb7: feat(ai): rename stepCountIs to isStepCount
fcc6869: refactor(ai/core): rename ModelCallStreamPart to LanguageModelStreamPart and align stream model call naming (streamLanguageModelCall, experimental_streamLanguageModelCall).
This updates experimental low-level stream primitives to use "language model call" terminology consistently.
ef992f8: Remove CommonJS exports from all packages. All packages are now ESM-only ("type": "module"). Consumers using require() must switch to ESM import syntax.
493295c: Remove the deprecated ToolCallOptions export.
Use ToolExecutionOptions instead.
116c89f: feat(ai): remove telemetry data from the user-facing event data
c29a26f: feat(provider): add support for provider references and uploading files as supported per provider
3887c70: feat(provider): add new top-level reasoning parameter to spec and support it in generateText and streamText
9bd6512: feat(provider): change file part data property to be tagged with a type and remove the image part type
4b46062: refactoring(ai): extract tool callback invocation into separate function and forward chunks before callback invocation
7e26e81: chore: rename experimental_context to context
b9cf502: refactoring(ai): delay tool execution in stream text until model call is finished
5b8c58f: feat(ai): decouple otel from core functions
4e095b0: fix(ai): reject system messages in messages or prompt by default (opt-in)
Patch Changes
e3d9c0e: Add allowSystemInMessages option to ToolLoopAgent.
This exposes the same option that exists on streamText and generateText, whether role: "system" messages are allowed in the prompt or messages fields. When unset, system messages are rejected because they can create a prompt injection attack risk. Ideally, use the instructions option instead. Set to true to allow system messages, or false to explicitly reject them.
7bf7d7f: feat(ai): enable:true for telemetry by default
99bf941: feat(ai): extract streamModelCall function for streaming text generation
e95e38d: fix: Make generateText and streamText result usage report total usage across all steps and deprecate totalUsage.
6a3793e: chore(ai): add optional ChatRequestOptions to addToolApprovalResponse and addToolOutput
5f3749c: refactoring: rename toolNeedsApproval to toolApproval
016e877: feat(ai): add instructions as the primary prompt option and deprecate system
2fe1099: feat(ai): emit streaming chunks throught the onChunk callback
f319fde: feat(ai): validate tool context against contextSchema at runtime
Tool execution and approval callbacks now validate each tool's toolsContext entry against its contextSchema. Invalid tool context now throws TypeValidationError with tool-context validation metadata in error.context.
31ee822: refactoring(ai): extract filterActiveTools and expose it as experimental_filterActiveTools
e68be55: fix(ai): skip stringifying text when streaming partial text
1db29c8: feat(ai): break CallSettings apart into LanguageModelCallOptions and RequestOptions
0a51f7d: fix(ai): enforce callOptionsSchema at runtime in ToolLoopAgent
ToolLoopAgentSettings.callOptionsSchema was declared and documented as a runtime schema for options, but tool-loop-agent.ts never invoked it. Any invariant a developer encoded in the schema was silently bypassed at runtime, and unchecked options flowed straight into prepareCall and any instructions template that interpolated them.
ToolLoopAgent.prepareCall now validates caller-supplied options against callOptionsSchema (when set) via safeValidateTypes, throwing InvalidArgumentError on failure before forwarding to prepareCall / generateText / streamText.
d1a8bed: fix(ui): export isDynamicToolUIPart from ai package
bcce2dd: feat(stream-text): expose standalone stream transformation helpers and deprecate the equivalent streamText result methods.
The new toUIMessageChunk and toUIMessageStream helpers let you convert a streamTextstream (or any compatible ReadableStream<TextStreamPart<TOOLS>>) into UI message chunks without going through the result object — useful for custom transports, tests, and other producers of TextStreamPart.
result.toUIMessageStreamResponse(options) and result.pipeUIMessageStreamToResponse(response, options) can migrate by passing toUIMessageStream({ stream: result.stream, ...options }) to createUIMessageStreamResponse or pipeUIMessageStreamToResponse.
The new toTextStream helper extracts text deltas from a streamTextstream, so result.toTextStreamResponse(options) and result.pipeTextStreamToResponse(response, options) can migrate to createTextStreamResponse({ stream: toTextStream({ stream: result.stream }), ...options }) and pipeTextStreamToResponse({ response, stream: toTextStream({ stream: result.stream }), ...options }).
result.toUIMessageStream, result.toUIMessageStreamResponse, result.pipeUIMessageStreamToResponse, result.toTextStreamResponse, and result.pipeTextStreamToResponse are now @deprecated. They still work in v7 and will be removed in the next major release. Migration snippets are in the v6 → v7 migration guide.
2a74d43: Remove the deprecated experimental_prepareStep option from generateText.
Use prepareStep instead.
71d3022: fix(ai): unify generate text event callbacks
fd4f578: fix(ai): exclude request and response bodies from text generation results by default to reduce memory usage.
511902c: skip validation for tool parts in terminal states when tool schema is no longer registered
a5018ab: fix(ai): return schema-transformed elements in array output mode
Previously final array output validation checked each element against the schema but returned the raw model output. Array output now returns the validated values so Zod transforms, coercions, defaults, and pipes are applied consistently with object output.
531251e: fix(security): validate redirect targets in download functions to prevent SSRF bypass
Both downloadBlob and download now validate the final URL after following HTTP redirects, preventing attackers from bypassing SSRF protections via open redirects to internal/private addresses.
eeefc3f: fix(ai): enforce timeout.stepMs for the whole step in streamText
Previously streamText's step timer was cleared synchronously right after the step's stream was registered, before the stream produced anything, so stepMs never aborted a step that stalled before emitting content. The step timer now survives until the step's stream finishes or aborts, matching generateText. chunkMs/totalMs and normal step-finish cleanup are unchanged.
ec98264: feat(ai): allow multiple integrations to be registered at once
43a6750: fix(ai): preserve allowSystemInMessages across streamText retries
67df0a0: feat: add sensitiveContext property to Tool
b79b6a8: fix(ai): add approval guard for denied tool outputs
4181cfe: fix(ai): harden getMediaTypeFromUrl against prototype-property collisions
getMediaTypeFromUrl (used to infer media types for file-url / image-url parts) used ext in URL_EXTENSION_TO_MEDIA_TYPE against a plain object literal. A URL ending in .constructor therefore resolved through the prototype chain and returned the Object constructor function, violating the helper's : string return type and forwarding a non-string value to provider adapters.
Switch to Object.hasOwn(...) so attacker-controlled extensions like .constructor cannot resolve to inherited Object.prototype keys.
208d045: fix(ai): skip global telemetry registration when local integration defined
5a6f514: feat(ai): support several tools in hasToolCall stop condition
ed74dae: fix(ui): make input optional on output-error tool and dynamic-tool UI message parts
validateUIMessages rejected persisted assistant messages whose output-error tool parts had no input key. This happened for any errored tool call where the SDK set input: undefined (e.g. NoSuchToolError / InvalidToolInputError): JSON serialization stripped the undefined value, and Zod 4.4+ treats a missing z.unknown() key as a validation failure (previously it was implicitly optional). The schema now matches the runtime shape produced by process-ui-message-stream, so reloading a thread that contains an errored tool call no longer throws AI_TypeValidationError.
ca99fea: feat: expose finalStep on text generation results
9b47dea: fix(ai): remove otel Tracer api from telemetry settings
877bf12: fix(ai): flatten model attributes for telemetry
2e17091: fix(types): move shared tool set utility types into provider-utils
Moved ToolSet, InferToolSetContext, and UnionToIntersection into @ai-sdk/provider-utils and updated ai internals to import them directly from there. This keeps the shared tool typing utilities colocated with the core tool type definitions.
210ed3d: feat(ai): pass result provider metadata across the stream
a3fd75b: feat(ai): expose Experimental_ModelCallStreamPart type
7f59f04: feat(ai): add approval reason to automatic tool approvals
7677c1e: feat(ai): allow tool approval functions to return undefined
476e1ca: feat(ai): remove telemetry dependency on onChunk callback
008271d: feat(openai-compatible): emit warning when using kebab-case instead of camelCase
7fc6bd6: Raise minimum supported Node.js version to 22. Supported versions: 22, 24, and 26.
594029e: feat(ai): wrap the model call in telemetry context
426dbbb: fix(ai): reject streamText result promises with NoOutputGeneratedError when the model stream ends without producing any output. Previously such streams resolved with an empty step. Incomplete streams with partial output still resolve with the partial result.
75ef93e: remove the deprecated experimental_output alias and document the output migration for AI SDK 7
c26ca8d: Remove custom User-Agent header from HttpChatTransport to fix CORS preflight failures in Safari and Firefox
eaf849f: Rename rerank telemetry finish callback to onRerankEnd.
664a0eb: feat (ai/core): support plain string model IDs in rerank() function
The rerank() function now accepts plain model strings (e.g., 'cohere/rerank-v3.5') in addition to RerankingModel objects, matching the behavior of generateText, embed, and other core functions.
08d2129: feat(mcp): propagate the server name through dynamic tool parts
5faf71c: feat: introduce responseMessages on GenerateTextResult and StreamTextResult
ce769dd: feat(provider): add experimental Realtime API support for voice conversations
Adds first-class support for realtime (speech-to-speech) APIs:
Experimental_RealtimeModelV4 spec in @ai-sdk/provider with normalized event types and factory
OpenAI, Google, and xAI realtime provider implementations
openai.experimental_realtime() / google.experimental_realtime() / xai.experimental_realtime() work in both server and browser
.getToken() static method on each provider for server-side ephemeral token creation
experimental_getRealtimeToolDefinitions helper for provider session tool definitions
experimental_useRealtime hook in @ai-sdk/react returning UIMessage[] (aligned with useChat), with onToolCall and addToolOutput for client-driven tool execution
inputAudioTranscription session config for showing transcribed user audio messages when supported by the provider
e3a0419: fix(ai): default missing embedding warnings to an empty array
f04adcb: feat(ai): refresh customProvider and createProviderRegistry to support file and skill upload abstractions
876fd3e: fix(ai): limit tool execution time duration to actual tool execution
e311194: feat(ai): allow passing provider instance to uploadFile and uploadSkill as shorthand
989d3d2: fix(ai): include generated files in OTEL response attributes
b5092f5: fix(ai): do not re-validate tool input for output-error parts in validateUIMessages
6dd6b83: feat(ai): change sensitiveRuntimeContext to telemetry.includeRuntimeContext and make it opt-in
69254e0: feat(ai): add toolMetadata for tool specific metdata
6abd098: split prepareToolsAndToolChoice() into prepareTools() and prepareToolChoice()
e1bfb9c: feat(ai): remove unnecessary data from events
375fdd7: fix: harden download URL SSRF guard against hostname and redirect bypasses
validateDownloadUrl and the file download helpers (downloadBlob, download) could be bypassed in several ways when handling untrusted URLs:
A fully-qualified hostname with a trailing dot (e.g. localhost., myhost.local.) skipped the localhost/.local blocklist.
IPv6 addresses that embed an IPv4 address in their last 32 bits — IPv4-compatible (::127.0.0.1), IPv4-translated (::ffff:0:127.0.0.1), and NAT64 (64:ff9b::127.0.0.1, including the 64:ff9b:1::/48 local-use prefix) — were not decoded and checked against the private IPv4 ranges.
Redirects were validated only afterfetch had already followed them, so the request to a redirect target (e.g. an internal/metadata address) had already been issued before the check ran.
Several reserved/internal address ranges were not blocked: CGNAT (100.64.0.0/10, used by some cloud providers for internal traffic), benchmarking (198.18.0.0/15), IETF protocol assignments (192.0.0.0/24), the reserved 240.0.0.0/4 block (including the 255.255.255.255 broadcast address), and IPv6 site-local (fec0::/10) and multicast (ff00::/8).
The validator now strips trailing dots before the hostname checks and fully expands IPv6 addresses to detect embedded private IPv4 targets. The download helpers now follow redirects manually (redirect: 'manual'), re-validating each hop before requesting it, so an unsafe redirect target is never fetched. When a redirect cannot be inspected because the runtime returns an opaque response, the helpers fail closed (reject the redirect) on the server; only in a real browser — where SSRF is not reachable (fetch is constrained by CORS and cannot reach a server's internal network or cloud-metadata endpoints) — is the redirect followed natively so legitimate redirected downloads keep working.
89ad56f: Promote generateSpeech and SpeechResult to stable exports.
f9a496f: Promote transcribe and TranscriptionResult to stable exports, with deprecated experimental aliases for backwards compatibility.
334ae5d: Update step performance metrics with explicit effective, input, output, and total token throughput fields.
3295831: Harden stream text processing and middleware against prototype pollution from stream part IDs.
b097c52: feat(ai): use tracing channels to track parent-child context
e79e644: chore(ai/core): remove timeout from CallSettings as it was effectively unused there
bcacd48: fix(ai): accumulative properties on StreamTextResult, GenerateTextResult
e92fc45: feat(ai): introduce onAbort hook to close telemetry spans
083947b: feat(ai): separate toolsContext from context
47e65d6: fix(ai): tag step/chunk timeout aborts with TimeoutError reason
When timeout: { stepMs } or timeout: { chunkMs } fires, the abort reason is now a TimeoutErrorDOMException, matching what AbortSignal.timeout() produces natively. Consumers can distinguish a framework timeout from a user-initiated cancel via signal.reason.name === 'TimeoutError'.
6a2caf9: Serialize undefined tool output to null in UI message chunks
202f107: feat(ai): create a diagnostics channel to push event data
bae5e2b: fix(security): re-validate tool approvals from client message history before execution
The approval-replay path in generateText/streamText (and WorkflowAgent.stream) reconstructed approved tool calls from the client-supplied messages array and executed them without re-validating input against the tool's schema or re-applying the approval policy. A client could forge an assistant message with a pre-approved tool-call part and have the server execute a tool with attacker-chosen arguments.
The replay path now validates HMAC signature (when experimental_toolApprovalSecret is configured), re-validates tool-call input against the tool's input schema, and re-resolves the approval policy before execution.
c907622: Add a toolOrder option to control the order in which tools are sent to provider APIs.
90e2d8a: chore: fix unused vars not being flagged by our lint tooling
f18b08f: fix: redact server error details from UI message streams by default
toUIMessageStream, createUIMessageStream, and toUIMessageChunk defaulted their onError callback to getErrorMessage, which serializes the raw error (error.toString() / JSON.stringify(error)) into the client-facing { type: 'error', errorText } chunk — and also into tool-output-error parts. The documented default was () => 'An error occurred.', so applications relying on the documented behavior were unknowingly streaming server exception details (internal hostnames, paths, provider request data, validation inputs) to end users.
The default onError now returns the documented generic 'An error occurred.'. Raw error details are only emitted when the developer explicitly supplies an onError handler. This also redacts tool-output-error and invalid-tool-input error text by default; pass an onError to surface richer messages.
7fd3360: Harden UI message stream processing against prototype pollution from chunk IDs.
b4507d5: fix(provider-utils): cancel response body on download rejection to prevent socket leak
When a download was rejected early — because the Content-Length header exceeded the size limit, the response status was not ok, or a redirect resolved to a blocked URL — the fetch response body was left unconsumed and uncancelled. With WHATWG Fetch/undici this leaves the underlying TCP socket open instead of returning it to the connection pool, allowing an attacker-controlled origin to exhaust file descriptors and cause a denial of service. The body is now cancelled on all early-rejection paths in readResponseWithSizeLimit, download, and downloadBlob, and fetchWithValidatedRedirects cancels each redirect hop's body before following or rejecting the next hop.
Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.
This PR includes no changesets
When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types
@thomasyuill-livekit I will let you take this one since it is agents-ui specific and such a large version bump (multiple major versions). Is CI passing a good barometer for this being ok, or is there any further manual validation you'd like to do before this is merged?
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
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.
This PR contains the following updates:
^5.0.105→^7.0.0Release Notes
vercel/ai (ai)
v7.0.29Compare Source
Patch Changes
7069785]4bf9ac2]v7.0.28Compare Source
Patch Changes
0bc8d4f: Fix chatonFinishhandling when overlapping requests clear the active response before a resume stream finishes.v7.0.27Compare Source
Patch Changes
ac01b79: Allow validating assistant UI messages with empty parts so persisted errored responses remain loadable.2696562:experimental_streamTranscriberesult promises now resolve without consumingfullStream: accessing any result promise consumes the stream internally. Previouslyawait result.textalone deadlocked on transform backpressure. Because live transcription streams can be unbounded,fullStreamis explicitly single-consumer (no replay buffering): access it once, before any result promise, when both stream parts and final results are needed.31c7be8]4d096f6]v7.0.26Compare Source
Patch Changes
27d294d: feat(ai): group orphaned tool calls after tool approvals under parent spanv7.0.25Compare Source
Patch Changes
7805e4a: Cancelling theexperimental_streamTranscribefullStreamnow also aborts a still-pendingdoStreamsetup, so a model whosedoStreamhas not yet resolved is cancelled instead of leaking.f8e82fd: Update theexperimental_streamTranscribeunsupported-model error message now that gateway string model IDs can support streaming transcription.4be62c1]f8e82fd]7805e4a]cd12954]v7.0.23Compare Source
Patch Changes
930f949: feat(ai): wrap embedMany in tracing channel context867f80a]v7.0.22Compare Source
Patch Changes
8f89c25: Add the Cartesia provider with Sonic 3.5 speech generation, Ink-Whisper batch transcription, and Ink 2 realtime transcription support.v7.0.21Compare Source
Patch Changes
308a519: chore: enforce consistent imports fromzod/v4instead ofzod308a519]7fe53d2]v7.0.20Compare Source
Patch Changes
b9ac19f: Flush compressed Node.js response chunks as they are piped so UI message and text streams remain incremental in Express and Next.js.a4186d6: Promote therepairToolCalloption to stable, with a deprecatedexperimental_repairToolCallalias for backwards compatibility.v7.0.19Compare Source
Patch Changes
be7f05a: AddfingerprintToolsanddetectToolDriftto detect MCP tool-definition drift ("rug pull"). Pin a tool set's server-controlled fields (string description, input schema, title) at trust time withfingerprintTools, then diff later fetches withdetectToolDriftto catch injected descriptions or widened schemas before passing tools to the model. Baseline storage and the drift response remain the app's responsibility.ee55a07: Preserve tool approval signatures when approvals transition to responded.aad737d: Use own-property checks when resolving per-tool approvals so tool names and approval ids that match inherited object properties (e.g.constructor,toString,valueOf,__proto__) are treated as unconfigured/absent.@ai-sdk/policy-opa:wrapMcpToolsbuilds its per-tool map with a null prototype and reads supplied approvals via an own-property check, andshadowguards its per-tool map lookup the same way.ai: tool and tool-context lookups keyed by a model- or client-supplied name now go through an own-property check (getOwn), so a name matching an inherited object property resolves to "no such tool"/"unconfigured" instead of a prototype value. This covers the approval path (per-tool approval resolution and replay re-validation) as well as tool-call parsing, execution, streaming callbacks, and UI message conversion/validation. The human-in-the-loop approval matching (collectToolApprovals) and streaming tool-name maps are built with a null prototype so a client-supplied id that matches an inherited property no longer slips past the "unknown approval" / "tool call not found" guards.0f93c57: feat (video): support video (not just image) reference inputs ininputReferencesfor reference-to-video generationUpdated dependencies [
e12411e]Updated dependencies [
5d894a7]Updated dependencies [
fdb6d5d]Updated dependencies [
0f93c57]Updated dependencies [
d25a084]v7.0.18Compare Source
Patch Changes
ac306ed]v7.0.17Compare Source
Patch Changes
cad8227]v7.0.16Compare Source
Patch Changes
a8f9b6d: Preserve signed tool approval metadata when recording approval responses.v7.0.15Compare Source
Patch Changes
0c3c7e4]c8d2726]v7.0.14Compare Source
Patch Changes
5c5c0f5: Add experimental streaming transcription support for transcription models, including OpenAIgpt-realtime-whisperand xAI WebSocket STT.5c5c0f5]v7.0.13Compare Source
Patch Changes
31abef7]v7.0.12Compare Source
Patch Changes
ecfeb6f: Sort tool results by their tool call order when converting generation output to response messages.a193137: FixextractJsonMiddlewarepreserving leading whitespace in the final streamed text suffix when no markdown fence prefix was stripped.c6f5e62]v7.0.11Compare Source
Patch Changes
0a87626: fix(ai): replace dynamic import() with loadBuiltinModule for diagnostics_channel to fix React Native/Hermes buildsv7.0.10Compare Source
Patch Changes
8c616f0: feat(mcp): add maxRetries option for failed mcp tool calls8c616f0]v7.0.9Compare Source
Patch Changes
2edc641]c18018c]v7.0.8Compare Source
Patch Changes
0274f34: feat (video): add first-classframeImagesandinputReferencescall options for video generation0274f34]v7.0.7Compare Source
Patch Changes
d598481: Fix:convertToModelMessagesno longer emits an empty assistant message when a block contains only unknown data parts (e.g. a data part beforestep-startwith noconvertDataPartprovided)v7.0.6Compare Source
Patch Changes
989402d: Add ToolLoopAgent types for deprecated tool call callback aliases.7e3c99e]v7.0.5Compare Source
Patch Changes
a2750db: fix(ai): prune orphaned tool-approval responses inpruneMessagesWhen pruning a specific tool by name (
toolCalls: [{ type, tools: [...] }]),pruneMessagesleft the tool'stool-approval-responsein place while removing itstool-approval-requestandtool-call. The tool name of an approval response was resolved per-message, but approval responses live in a separatetoolmessage from their approval request, so the name could never be resolved and the response was always kept. Tool name resolution is now done across all messages, so approval requests and responses are pruned together.v7.0.4Compare Source
Patch Changes
6a436e3]v7.0.3Compare Source
Patch Changes
728eaa0]v7.0.2Compare Source
Patch Changes
9dce0a7]v7.0.1Compare Source
Patch Changes
8c616f0: feat(mcp): add maxRetries option for failed mcp tool calls8c616f0]v7.0.0Compare Source
Major Changes
986c6fd: feat(ai): change type of experimental_context from unknown to genericb0c2869: chore(ai): remove deprecatedmediatype part fromToolResultOutput1949571: feat(ai): make experimental_telemetry stable6542d93: feat(ai): change naming nomenclature for*TelemetryIntegrationto*Telemetry31f69de: fix(ai): carry prepareStep message overrides forward across steps7c71ac6: fix(ai): limit response messages in StepResult to messages created in that stepcf93359: feat(ai): remove/refactor event data sent via callbacks776b617: feat(provider): adding new 'custom' content type34bd95d: feat(ai): add support for uploading provider skills using the provider references abstraction1f7db50: fix(ai): remove experimental_customProvider3debdb7: feat(ai): renamestepCountIstoisStepCountfcc6869: refactor(ai/core): renameModelCallStreamParttoLanguageModelStreamPartand align stream model call naming (streamLanguageModelCall,experimental_streamLanguageModelCall).This updates experimental low-level stream primitives to use "language model call" terminology consistently.
ef992f8: Remove CommonJS exports from all packages. All packages are now ESM-only ("type": "module"). Consumers usingrequire()must switch to ESMimportsyntax.493295c: Remove the deprecatedToolCallOptionsexport.Use
ToolExecutionOptionsinstead.116c89f: feat(ai): remove telemetry data from the user-facing event datac29a26f: feat(provider): add support for provider references and uploading files as supported per provider3887c70: feat(provider): add new top-level reasoning parameter to spec and support it ingenerateTextandstreamText9bd6512: feat(provider): change file part data property to be tagged with a type and remove the image part type4b46062: refactoring(ai): extract tool callback invocation into separate function and forward chunks before callback invocation7e26e81: chore: rename experimental_context to context8359612: Start v7 pre-release5463d0d: feat(provider): align tool result output content file part types with top-level message file part types72223e7: chore(ai): remove deprecated isToolOrDynamicToolUIPart function57bf606: chore(ai): simplify unified telemetry creationb3c9f6a: feat(ai): create new opentelemetry package (@ai-sdk/otel)b9cf502: refactoring(ai): delay tool execution in stream text until model call is finished5b8c58f: feat(ai): decouple otel from core functions4e095b0: fix(ai): reject system messages in messages or prompt by default (opt-in)Patch Changes
e3d9c0e: AddallowSystemInMessagesoption toToolLoopAgent.This exposes the same option that exists on
streamTextandgenerateText, whetherrole: "system"messages are allowed in thepromptormessagesfields. When unset, system messages are rejected because they can create a prompt injection attack risk. Ideally, use theinstructionsoption instead. Set totrueto allow system messages, orfalseto explicitly reject them.The option can also be returned from
prepareCallfor dynamic per-call configuration.b56301c: feat(ai): decouple otel from generate/streamObject2427d88: feat(ai): change Tool.sensitiveContext to telemetry.includeToolsContext and make it opt-in38fc777: Add AI Gateway hint to provider READMEs023550e: DeprecatestreamTextresultfullStreamin favor ofstream.38ca8dc: fix(gateway): enable retry support for gateway errors19736ee: feat(ai): rename onStepFinish to onStepEnd6d76710: fix URL of hero animation in README5ceed7d: fix(ai): doStream should reflect transformed values4757690: feat(ai): rename onObjectStepFinish to onObjectStepEndbc47739: chore(ai): cleanup telemetry event datad1b3786: fix(ai): deprecate properties on result that have moved to finalStep382d53b: refactoring: rename context to runtimeContextff9ce30: feat(ai): introduce experimental callbacks for embed functionee798eb: chore(provider-utils): renameExperimental_SandboxtoExperimental_SandboxSession4873966: chore(ai): allow general usage oflogWarningsand emit them via Node API when availablee67d80e: fix: rename onFinish to onEnd7bf7d7f: feat(ai): enable:true for telemetry by default99bf941: feat(ai): extract streamModelCall function for streaming text generatione95e38d: fix: MakegenerateTextandstreamTextresultusagereport total usage across all steps and deprecatetotalUsage.6a3793e: chore(ai): add optional ChatRequestOptions toaddToolApprovalResponseandaddToolOutput5f3749c: refactoring: rename toolNeedsApproval to toolApproval016e877: feat(ai): addinstructionsas the primary prompt option and deprecatesystem2fe1099: feat(ai): emit streaming chunks throught the onChunk callbackf319fde: feat(ai): validate tool context against contextSchema at runtimeTool execution and approval callbacks now validate each tool's
toolsContextentry against itscontextSchema. Invalid tool context now throwsTypeValidationErrorwith tool-context validation metadata inerror.context.31ee822: refactoring(ai): extract filterActiveTools and expose it as experimental_filterActiveToolsb67525f: feat: instructions as prepareStep inpute68be55: fix(ai): skip stringifying text when streaming partial text1db29c8: feat(ai): breakCallSettingsapart intoLanguageModelCallOptionsandRequestOptions0a51f7d: fix(ai): enforcecallOptionsSchemaat runtime inToolLoopAgentToolLoopAgentSettings.callOptionsSchemawas declared and documented as a runtime schema foroptions, buttool-loop-agent.tsnever invoked it. Any invariant a developer encoded in the schema was silently bypassed at runtime, and uncheckedoptionsflowed straight intoprepareCalland anyinstructionstemplate that interpolated them.ToolLoopAgent.prepareCallnow validates caller-suppliedoptionsagainstcallOptionsSchema(when set) viasafeValidateTypes, throwingInvalidArgumentErroron failure before forwarding toprepareCall/generateText/streamText.d1a8bed: fix(ui): exportisDynamicToolUIPartfromaipackagebcce2dd: feat(stream-text): expose standalone stream transformation helpers and deprecate the equivalentstreamTextresult methods.The new
toUIMessageChunkandtoUIMessageStreamhelpers let you convert astreamTextstream(or any compatibleReadableStream<TextStreamPart<TOOLS>>) into UI message chunks without going through the result object — useful for custom transports, tests, and other producers ofTextStreamPart.result.toUIMessageStreamResponse(options)andresult.pipeUIMessageStreamToResponse(response, options)can migrate by passingtoUIMessageStream({ stream: result.stream, ...options })tocreateUIMessageStreamResponseorpipeUIMessageStreamToResponse.The new
toTextStreamhelper extracts text deltas from astreamTextstream, soresult.toTextStreamResponse(options)andresult.pipeTextStreamToResponse(response, options)can migrate tocreateTextStreamResponse({ stream: toTextStream({ stream: result.stream }), ...options })andpipeTextStreamToResponse({ response, stream: toTextStream({ stream: result.stream }), ...options }).result.toUIMessageStream,result.toUIMessageStreamResponse,result.pipeUIMessageStreamToResponse,result.toTextStreamResponse, andresult.pipeTextStreamToResponseare now@deprecated. They still work in v7 and will be removed in the next major release. Migration snippets are in the v6 → v7 migration guide.2a74d43: Remove the deprecatedexperimental_prepareStepoption fromgenerateText.Use
prepareStepinstead.71d3022: fix(ai): unify generate text event callbacks6cca112: feat: add timeBetweenOutputTokensMs statsfd4f578: fix(ai): exclude request and response bodies from text generation results by default to reduce memory usage.511902c: skip validation for tool parts in terminal states when tool schema is no longer registereda5018ab: fix(ai): return schema-transformed elements in array output modePreviously final array output validation checked each element against the schema but returned the raw model output. Array output now returns the validated values so Zod transforms, coercions, defaults, and pipes are applied consistently with object output.
531251e: fix(security): validate redirect targets in download functions to prevent SSRF bypassBoth
downloadBlobanddownloadnow validate the final URL after following HTTP redirects, preventing attackers from bypassing SSRF protections via open redirects to internal/private addresses.eeefc3f: fix(ai): enforcetimeout.stepMsfor the whole step instreamTextPreviously
streamText's step timer was cleared synchronously right after the step's stream was registered, before the stream produced anything, sostepMsnever aborted a step that stalled before emitting content. The step timer now survives until the step's stream finishes or aborts, matchinggenerateText.chunkMs/totalMsand normal step-finish cleanup are unchanged.ec98264: feat(ai): allow multiple integrations to be registered at once43a6750: fix(ai): preserveallowSystemInMessagesacrossstreamTextretries67df0a0: feat: add sensitiveContext property to Toolb79b6a8: fix(ai): add approval guard for denied tool outputs81caa5d: fix(ai): remove ExtractLiteralUnion export4181cfe: fix(ai): hardengetMediaTypeFromUrlagainst prototype-property collisionsgetMediaTypeFromUrl(used to infer media types forfile-url/image-urlparts) usedext in URL_EXTENSION_TO_MEDIA_TYPEagainst a plain object literal. A URL ending in.constructortherefore resolved through the prototype chain and returned theObjectconstructor function, violating the helper's: stringreturn type and forwarding a non-string value to provider adapters.Switch to
Object.hasOwn(...)so attacker-controlled extensions like.constructorcannot resolve to inheritedObject.prototypekeys.208d045: fix(ai): skip global telemetry registration when local integration defined5a6f514: feat(ai): support several tools in hasToolCall stop conditioned74dae: fix(ui): makeinputoptional onoutput-errortool and dynamic-tool UI message partsvalidateUIMessagesrejected persisted assistant messages whoseoutput-errortool parts had noinputkey. This happened for any errored tool call where the SDK setinput: undefined(e.g.NoSuchToolError/InvalidToolInputError): JSON serialization stripped theundefinedvalue, and Zod 4.4+ treats a missingz.unknown()key as a validation failure (previously it was implicitly optional). The schema now matches the runtime shape produced byprocess-ui-message-stream, so reloading a thread that contains an errored tool call no longer throwsAI_TypeValidationError.ca99fea: feat: exposefinalStepon text generation results9b47dea: fix(ai): remove otel Tracer api from telemetry settings877bf12: fix(ai): flatten model attributes for telemetryeea8d98: refactoring: rename tool execution eventsd66ae02: Return validated elements from generateText array output5d0f18e: feat(ai): move opentelemetry to new package21d3d60: feat(harness): implement harness specification1582efa: chore(ai): remove the metadata field from the telemetry settings80d4dde: fix(ai): include tool input on tool result for provider executed dynamic tools98627e5: feat(ai): remove onChunk event from telemetry51ce232: feat(ai): add sensitiveRuntimeContext option82fc0ab: fix(ai): pass all stream text parts toonChunk1f509d4: fix(ai): force template check on 'kind' paramca446f8: feat: flexible tool descriptions176466a: chore(provider): align V4 model return types to have their own definitions across all model interfacesc0c8ca2: fix(ai): remove deprecated LanguageModelUsage properties75763b0: agents: tag outgoing requests with an ai-sdk-agent user-agent segment for usage attribution (tool-loop, workflow)6ec57f5: feat(ai): make the experimental lifecycle callbacks stable3ae1786: fix: better context type inferencea7de9c9: fix: make sandbox experimentalcaf1b6f: feat(ai): introduce experimental callbacks for rerank function9f0e36c: trigger release for all packages after provenance setupbefb78c: refactoring: remove real-time delays in unit tests6866afe: fix(ai): fixlastAssistantMessageIsCompleteWithApprovalResponsesto no longer ignoreproviderExecutedtool approvals29d8cf4: feat(ai): rename the core-event types2e17091: fix(types): move shared tool set utility types into provider-utilsMoved
ToolSet,InferToolSetContext, andUnionToIntersectioninto@ai-sdk/provider-utilsand updatedaiinternals to import them directly from there. This keeps the shared tool typing utilities colocated with the core tool type definitions.210ed3d: feat(ai): pass result provider metadata across the streama3fd75b: feat(ai): expose Experimental_ModelCallStreamPart typef4cc8eb: feat: add performance statistics2add429: fix(ai): skip passing invalid JSON inputs to response messages5588abd: feat(ai): add experimental_refineToolInput option to ToolLoopAgent, generateText, streamTexte80ada0: fix(ai): download tool-result file URLs58a2ad7: fix: more precise default message for tool execution denial62d6481: Post-publish release notifications now link to each package’s GitHub release and npm page.1fe058b: fix(anthropic): preserve the error code returned by model5c4d910: feat(ai): add newisLoopFinishedstop condition helper for unlimited stepse4182bd: chore: rm export of OutputInterface34fd051: feat(ai): add toolMs to timeout configuration72cb801: feat(ai): concurrent event notification2e98477: fix: retain stack traces on async errorsadd1126: refactoring: executeTool uses tool as parameter81a284b: fix(ai): handle partial unicode escapes in fixJson76fd58c: fix: consider file outputs and tool calls for time to first output7392266: feat: move includeRawChunks to include.rawChunks69aeb0e: feat: add deprecated tool call lifecycle callback aliases for AI SDK 6 compatibility.37d69b2: feat(ai): access runtime context in tool approval functions1043274: feat(ai): add a ModelCall start/end event350ea38: refactoring: introduce Arrayable type7f59f04: feat(ai): add approval reason to automatic tool approvals7677c1e: feat(ai): allow tool approval functions to return undefined476e1ca: feat(ai): remove telemetry dependency on onChunk callback008271d: feat(openai-compatible): emit warning when using kebab-case instead of camelCase7fc6bd6: Raise minimum supported Node.js version to 22. Supported versions: 22, 24, and 26.594029e: feat(ai): wrap the model call in telemetry context426dbbb: fix(ai): rejectstreamTextresult promises withNoOutputGeneratedErrorwhen the model stream ends without producing any output. Previously such streams resolved with an empty step. Incomplete streams with partial output still resolve with the partial result.25a64f8: Remove deprecated experimental generateImage exports.75ef93e: remove the deprecatedexperimental_outputalias and document theoutputmigration for AI SDK 7c26ca8d: Remove custom User-Agent header from HttpChatTransport to fix CORS preflight failures in Safari and Firefoxeaf849f: Rename rerank telemetry finish callback toonRerankEnd.664a0eb: feat (ai/core): support plain string model IDs inrerank()functionThe
rerank()function now accepts plain model strings (e.g.,'cohere/rerank-v3.5') in addition toRerankingModelobjects, matching the behavior ofgenerateText,embed, and other core functions.08d2129: feat(mcp): propagate the server name through dynamic tool parts5faf71c: feat: introduce responseMessages on GenerateTextResult and StreamTextResult0c4c275: trigger initial canary release118b953: feat(ai): decouple otel from embed functions6fd51c0: fix(provider): preserve error type prefix in getErrorMessage1dca341: fix: rename telemetry onFinish to onEndebd4da2: feat(ai): add missing usage attributesbc67b4f: feat(ai): add experimental callbacks for structured outputsf0b0b20: feat(ai): add per-tool timeout overrides via toolTimeouts2852a84: fix(ai): make input optional on input-streaming UIMessagePart variants2a9c144: feat(ai): add toolNeedsApproval optionce769dd: feat(provider): add experimental Realtime API support for voice conversationsAdds first-class support for realtime (speech-to-speech) APIs:
Experimental_RealtimeModelV4spec in@ai-sdk/providerwith normalized event types and factoryopenai.experimental_realtime()/google.experimental_realtime()/xai.experimental_realtime()work in both server and browser.getToken()static method on each provider for server-side ephemeral token creationexperimental_getRealtimeToolDefinitionshelper for provider session tool definitionsexperimental_useRealtimehook in@ai-sdk/reactreturningUIMessage[](aligned withuseChat), withonToolCallandaddToolOutputfor client-driven tool executioninputAudioTranscriptionsession config for showing transcribed user audio messages when supported by the providere3a0419: fix(ai): default missing embedding warnings to an empty arrayf04adcb: feat(ai): refreshcustomProviderandcreateProviderRegistryto support file and skill upload abstractions876fd3e: fix(ai): limit tool execution time duration to actual tool executione311194: feat(ai): allow passing provider instance touploadFileanduploadSkillas shorthand989d3d2: fix(ai): include generated files in OTEL response attributesb5092f5: fix(ai): do not re-validate tool input for output-error parts in validateUIMessages6dd6b83: feat(ai): change sensitiveRuntimeContext to telemetry.includeRuntimeContext and make it opt-in69254e0: feat(ai): add toolMetadata for tool specific metdata79b2468: feat: add request.messages to StepResult6c93e36: feat(provider-utils): addspawnCommandmethod toExperimental_Sandboxto allow for detached command execution2605e5f: fix test mocks to return the first array-backed result on the first call258c093: chore: ensure consistent import handling and avoid import duplicates or cyclesf58f9bc: fix(ai): remove stopWhen from onStart event8565dcb: fix: rename onEmbedFinish to onEmbedEnd6abd098: splitprepareToolsAndToolChoice()intoprepareTools()andprepareToolChoice()e1bfb9c: feat(ai): remove unnecessary data from events375fdd7: fix: harden download URL SSRF guard against hostname and redirect bypassesvalidateDownloadUrland the file download helpers (downloadBlob,download) could be bypassed in several ways when handling untrusted URLs:localhost.,myhost.local.) skipped the localhost/.localblocklist.::127.0.0.1), IPv4-translated (::ffff:0:127.0.0.1), and NAT64 (64:ff9b::127.0.0.1, including the64:ff9b:1::/48local-use prefix) — were not decoded and checked against the private IPv4 ranges.fetchhad already followed them, so the request to a redirect target (e.g. an internal/metadata address) had already been issued before the check ran.100.64.0.0/10, used by some cloud providers for internal traffic), benchmarking (198.18.0.0/15), IETF protocol assignments (192.0.0.0/24), the reserved240.0.0.0/4block (including the255.255.255.255broadcast address), and IPv6 site-local (fec0::/10) and multicast (ff00::/8).The validator now strips trailing dots before the hostname checks and fully expands IPv6 addresses to detect embedded private IPv4 targets. The download helpers now follow redirects manually (
redirect: 'manual'), re-validating each hop before requesting it, so an unsafe redirect target is never fetched. When a redirect cannot be inspected because the runtime returns an opaque response, the helpers fail closed (reject the redirect) on the server; only in a real browser — where SSRF is not reachable (fetch is constrained by CORS and cannot reach a server's internal network or cloud-metadata endpoints) — is the redirect followed natively so legitimate redirected downloads keep working.89ad56f: PromotegenerateSpeechandSpeechResultto stable exports.f9a496f: PromotetranscribeandTranscriptionResultto stable exports, with deprecated experimental aliases for backwards compatibility.334ae5d: Update step performance metrics with explicit effective, input, output, and total token throughput fields.3295831: Harden stream text processing and middleware against prototype pollution from stream part IDs.b097c52: feat(ai): use tracing channels to track parent-child contexte79e644: chore(ai/core): removetimeoutfromCallSettingsas it was effectively unused there3015fc3: feat: sandbox shell execution abstractionb8396f0: trigger initial beta release48e92f3: feat: make include stable33d099c: fix(ai): omit reasoning-start/end when sendReasoning is falsee87d71b: feat(ai): support automatic tool approval in ui messagesa6617c5: feat(provider-utils): addreadFileandwriteFileplus convenience wrappers toExperimental_Sandboxabstractioneee1166: feat(ai): expose initial and response messages in prepareStep9d486aa: feat(ai): generic tool approval functionc3d4019: chore(ai): rename 'TelemetrySettings' to 'TelemetryOptions'28dfa06: fix: support tools with optional contextbcacd48: fix(ai): accumulative properties on StreamTextResult, GenerateTextResulte92fc45: feat(ai): introduce onAbort hook to close telemetry spans083947b: feat(ai): separate toolsContext from context47e65d6: fix(ai): tag step/chunk timeout aborts withTimeoutErrorreasonWhen
timeout: { stepMs }ortimeout: { chunkMs }fires, the abort reason is now aTimeoutErrorDOMException, matching whatAbortSignal.timeout()produces natively. Consumers can distinguish a framework timeout from a user-initiated cancel viasignal.reason.name === 'TimeoutError'.6a2caf9: Serializeundefinedtool output tonullin UI message chunks202f107: feat(ai): create a diagnostics channel to push event databae5e2b: fix(security): re-validate tool approvals from client message history before executionThe approval-replay path in
generateText/streamText(andWorkflowAgent.stream) reconstructed approved tool calls from the client-supplied messages array and executed them without re-validating input against the tool's schema or re-applying the approval policy. A client could forge an assistant message with a pre-approved tool-call part and have the server execute a tool with attacker-chosen arguments.The replay path now validates HMAC signature (when
experimental_toolApprovalSecretis configured), re-validates tool-call input against the tool's input schema, and re-resolves the approval policy before execution.c907622: Add atoolOrderoption to control the order in which tools are sent to provider APIs.90e2d8a: chore: fix unused vars not being flagged by our lint toolingc4f4b5f: refactoring(ai): remove deprecated experimental_activeTools optionf4cfccd: feat(ai): decouple otel from rerank functionf5a6f89: README updatesf18b08f: fix: redact server error details from UI message streams by defaulttoUIMessageStream,createUIMessageStream, andtoUIMessageChunkdefaulted theironErrorcallback togetErrorMessage, which serializes the raw error (error.toString()/JSON.stringify(error)) into the client-facing{ type: 'error', errorText }chunk — and also intotool-output-errorparts. The documented default was() => 'An error occurred.', so applications relying on the documented behavior were unknowingly streaming server exception details (internal hostnames, paths, provider request data, validation inputs) to end users.The default
onErrornow returns the documented generic'An error occurred.'. Raw error details are only emitted when the developer explicitly supplies anonErrorhandler. This also redactstool-output-errorand invalid-tool-input error text by default; pass anonErrorto surface richer messages.7fd3360: Harden UI message stream processing against prototype pollution from chunk IDs.0416e3e: feat (video): add first-classgenerateAudiocall optiond775a57: feat: introduce Instructions typeb4507d5: fix(provider-utils): cancel response body on download rejection to prevent socket leakWhen a download was rejected early — because the
Content-Lengthheader exceeded the size limit, the response status was not ok, or a redirect resolved to a blocked URL — the fetch response body was left unconsumed and uncancelled. With WHATWG Fetch/undici this leaves the underlying TCP socket open instead of returning it to the connection pool, allowing an attacker-controlled origin to exhaust file descriptors and cause a denial of service. The body is now cancelled on all early-rejection paths inreadResponseWithSizeLimit,download, anddownloadBlob, andfetchWithValidatedRedirectscancels each redirect hop's body before following or rejecting the next hop.[
6147cdf](https://redirect.github.com/vercel/aiConfiguration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.