ai 7.0.122 → 7.0.124

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/index.d.ts +7598 -7268
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +19555 -22545
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +2235 -2004
  7. package/dist/internal/index.d.ts.map +1 -0
  8. package/dist/internal/index.js +3261 -3921
  9. package/dist/internal/index.js.map +1 -1
  10. package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
  11. package/dist/test/index.d.ts +294 -273
  12. package/dist/test/index.d.ts.map +1 -0
  13. package/dist/test/index.js +325 -469
  14. package/dist/test/index.js.map +1 -1
  15. package/docs/02-foundations/03-prompts.mdx +3 -1
  16. package/docs/02-foundations/06-provider-options.mdx +1 -1
  17. package/docs/02-getting-started/06-nodejs.mdx +4 -4
  18. package/docs/02-getting-started/08-tanstack-start.mdx +1 -1
  19. package/docs/03-agents/05-configuring-call-options.mdx +1 -1
  20. package/docs/03-ai-sdk-core/10-generating-structured-data.mdx +1 -1
  21. package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +3 -0
  22. package/docs/03-ai-sdk-core/17-mcp-apps.mdx +5 -5
  23. package/docs/03-ai-sdk-core/36-transcription.mdx +36 -0
  24. package/docs/03-ai-sdk-core/37-speech.mdx +22 -1
  25. package/docs/03-ai-sdk-core/42-batch.mdx +1 -1
  26. package/docs/03-ai-sdk-core/60-telemetry.mdx +51 -3
  27. package/docs/03-ai-sdk-harnesses/02-harness-agent.mdx +24 -0
  28. package/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx +12 -12
  29. package/docs/04-ai-sdk-ui/03-chatbot-message-persistence.mdx +9 -7
  30. package/docs/04-ai-sdk-ui/03-chatbot-resume-streams.mdx +2 -2
  31. package/docs/04-ai-sdk-ui/03-chatbot-tool-usage.mdx +7 -9
  32. package/docs/04-ai-sdk-ui/05-completion.mdx +1 -1
  33. package/docs/04-ai-sdk-ui/50-stream-protocol.mdx +2 -2
  34. package/docs/05-ai-sdk-rsc/03-generative-ui-state.mdx +8 -7
  35. package/docs/05-ai-sdk-rsc/06-loading-state.mdx +19 -10
  36. package/docs/05-ai-sdk-rsc/08-error-handling.mdx +2 -0
  37. package/docs/05-ai-sdk-rsc/10-migrating-to-ui.mdx +4 -3
  38. package/docs/06-advanced/02-stopping-streams.mdx +2 -2
  39. package/docs/06-advanced/04-caching.mdx +9 -5
  40. package/docs/06-advanced/05-multiple-streamables.mdx +1 -1
  41. package/docs/06-advanced/07-rendering-ui-with-language-models.mdx +16 -16
  42. package/docs/06-advanced/09-multistep-interfaces.mdx +1 -1
  43. package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +4 -4
  44. package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +4 -4
  45. package/docs/07-reference/01-ai-sdk-core/11-stream-transcribe.mdx +7 -0
  46. package/docs/07-reference/01-ai-sdk-core/11-transcribe.mdx +7 -0
  47. package/docs/07-reference/01-ai-sdk-core/12-generate-speech.mdx +7 -0
  48. package/docs/07-reference/01-ai-sdk-core/14-upload-file.mdx +4 -4
  49. package/docs/07-reference/01-ai-sdk-core/14-upload-skill.mdx +1 -1
  50. package/docs/07-reference/01-ai-sdk-core/15-agent.mdx +1 -1
  51. package/docs/07-reference/01-ai-sdk-core/18-create-agent-ui-stream-response.mdx +1 -4
  52. package/docs/07-reference/01-ai-sdk-core/22-dynamic-tool.mdx +1 -1
  53. package/docs/07-reference/01-ai-sdk-core/23-create-mcp-client.mdx +1 -1
  54. package/docs/07-reference/01-ai-sdk-core/30-model-message.mdx +2 -2
  55. package/docs/07-reference/01-ai-sdk-core/69-add-tool-input-examples-middleware.mdx +1 -1
  56. package/docs/07-reference/01-ai-sdk-core/80-smooth-stream.mdx +1 -1
  57. package/docs/07-reference/02-ai-sdk-ui/31-convert-to-model-messages.mdx +5 -4
  58. package/docs/07-reference/02-ai-sdk-ui/40-create-ui-message-stream.mdx +3 -2
  59. package/docs/07-reference/02-ai-sdk-ui/41-create-ui-message-stream-response.mdx +7 -0
  60. package/docs/07-reference/02-ai-sdk-ui/42-pipe-ui-message-stream-to-response.mdx +7 -0
  61. package/docs/07-reference/02-ai-sdk-ui/50-direct-chat-transport.mdx +2 -2
  62. package/docs/07-reference/03-ai-sdk-rsc/01-stream-ui.mdx +2 -2
  63. package/docs/07-reference/04-ai-sdk-workflow/01-workflow-agent.mdx +1 -1
  64. package/docs/08-migration-guides/25-migration-guide-5-0-data.mdx +4 -5
  65. package/docs/08-migration-guides/26-migration-guide-5-0.mdx +2 -1
  66. package/docs/08-migration-guides/29-migration-guide-4-0.mdx +4 -4
  67. package/docs/08-migration-guides/38-migration-guide-3-2.mdx +1 -1
  68. package/docs/08-migration-guides/39-migration-guide-3-1.mdx +1 -1
  69. package/docs/09-troubleshooting/12-use-chat-an-error-occurred.mdx +8 -6
  70. package/docs/09-troubleshooting/50-react-maximum-update-depth-exceeded.mdx +6 -6
  71. package/docs/09-troubleshooting/70-high-memory-usage-with-images.mdx +1 -1
  72. package/package.json +17 -17
  73. package/src/agent/create-agent-ui-stream-response.ts +3 -0
  74. package/src/agent/pipe-agent-ui-stream-to-response.ts +3 -0
  75. package/src/generate-speech/generate-speech.ts +163 -38
  76. package/src/generate-speech/index.ts +4 -0
  77. package/src/generate-speech/speech-events.ts +91 -0
  78. package/src/generate-text/prune-messages.ts +1 -1
  79. package/src/middleware/extract-reasoning-middleware.ts +27 -11
  80. package/src/telemetry/create-telemetry-dispatcher.ts +18 -5
  81. package/src/telemetry/telemetry.ts +38 -6
  82. package/src/telemetry/tracing-channel.ts +3 -0
  83. package/src/transcribe/index.ts +6 -0
  84. package/src/transcribe/stream-transcribe.ts +182 -31
  85. package/src/transcribe/transcribe.ts +186 -33
  86. package/src/transcribe/transcription-events.ts +111 -0
  87. package/src/ui/convert-to-model-messages.ts +18 -6
  88. package/src/ui-message-stream/create-sse-stream-with-keep-alive.ts +89 -0
  89. package/src/ui-message-stream/create-ui-message-stream-response.ts +7 -1
  90. package/src/ui-message-stream/pipe-ui-message-stream-to-response.ts +7 -1
  91. package/src/ui-message-stream/ui-message-stream-response-init.ts +7 -0
@@ -218,7 +218,7 @@ The diagram above shows the complete lifecycle of a resumable stream:
218
218
  2. **Stream tracking**: Your persistence layer saves the `activeStreamId` in the chat data
219
219
  3. **Client reconnection**: When the client reconnects (page reload), the `resume` option triggers a GET request to `/api/chat/[id]/stream`
220
220
  4. **Stream recovery**: The GET handler checks for an `activeStreamId` and uses `resumeExistingStream` to reconnect. If no active stream exists, it returns a 204 (No Content) response
221
- 5. **Completion cleanup**: When the stream finishes, the `onFinish` callback clears the `activeStreamId` by setting it to `null`
221
+ 5. **Completion cleanup**: When the stream finishes, the `onEnd` callback clears the `activeStreamId` by setting it to `null`
222
222
 
223
223
  ## Customize the resume endpoint
224
224
 
@@ -310,7 +310,7 @@ export function Chat({
310
310
  const assistantMessage =
311
311
  lastMessage?.role === 'assistant' ? lastMessage : undefined;
312
312
 
313
- void fetch(`/api/chat/${chatData.id}/stop`, {
313
+ void fetch(`/api/chat/${encodeURIComponent(chatData.id)}/stop`, {
314
314
  method: 'POST',
315
315
  headers: { 'Content-Type': 'application/json' },
316
316
  body: JSON.stringify(
@@ -228,9 +228,7 @@ export default function Chat() {
228
228
  return <div key={callId}>Approval response received.</div>;
229
229
  case 'output-available':
230
230
  return (
231
- <div key={callId}>
232
- Location access allowed: {part.output}
233
- </div>
231
+ <div key={callId}>Confirmation result: {part.output}</div>
234
232
  );
235
233
  case 'output-error':
236
234
  return <div key={callId}>Error: {part.errorText}</div>;
@@ -356,22 +354,22 @@ export default function Chat() {
356
354
  return;
357
355
  }
358
356
 
359
- if (toolCall.toolName === 'getWeatherInformation') {
357
+ if (toolCall.toolName === 'getLocation') {
360
358
  try {
361
- const weather = await getWeatherInformation(toolCall.input);
359
+ const location = await getLocation();
362
360
 
363
361
  // No await - avoids potential deadlocks
364
362
  addToolOutput({
365
- tool: 'getWeatherInformation',
363
+ tool: 'getLocation',
366
364
  toolCallId: toolCall.toolCallId,
367
- output: weather,
365
+ output: location,
368
366
  });
369
367
  } catch (err) {
370
368
  addToolOutput({
371
- tool: 'getWeatherInformation',
369
+ tool: 'getLocation',
372
370
  toolCallId: toolCall.toolCallId,
373
371
  state: 'output-error',
374
- errorText: 'Unable to get the weather information',
372
+ errorText: 'Unable to get the user location',
375
373
  });
376
374
  }
377
375
  }
@@ -184,7 +184,7 @@ const { messages, input, handleInputChange, handleSubmit } = useCompletion({
184
184
  });
185
185
  ```
186
186
 
187
- In this example, the `useCompletion` hook sends a POST request to the `/api/completion` endpoint with the specified headers, additional body fields, and credentials for that fetch request. On your server side, you can handle the request with these additional information.
187
+ In this example, the `useCompletion` hook sends a POST request to the `/api/custom-completion` endpoint with the specified headers, additional body fields, and credentials for that fetch request. On your server side, you can handle the request with these additional information.
188
188
 
189
189
  You can provide a type for the additional body fields. The type applies to
190
190
  both the body configured on the hook and the body passed to `complete`:
@@ -21,8 +21,8 @@ A text stream contains chunks in plain text, that are streamed to the frontend.
21
21
  Each chunk is then appended together to form a full text response.
22
22
 
23
23
  Text streams are supported by `useChat`, `useCompletion`, and `useObject`.
24
- When you use `useChat` or `useCompletion`, you need to enable text streaming
25
- by setting the `streamProtocol` options to `text`.
24
+ To enable text streaming, use `TextStreamChatTransport` with `useChat`, or set
25
+ the `streamProtocol` option to `text` with `useCompletion`.
26
26
 
27
27
  You can generate text streams with `streamText` in the backend.
28
28
  Pass the result's `stream` to `toTextStream` and return it with
@@ -236,17 +236,18 @@ export default function Page() {
236
236
  const handleSubmit = async event => {
237
237
  event.preventDefault();
238
238
 
239
- setMessages([
240
- ...messages,
241
- { id: Date.now(), role: 'user', display: event.target.message.value },
239
+ setMessages(currentMessages => [
240
+ ...currentMessages,
241
+ {
242
+ id: Date.now().toString(),
243
+ role: 'user',
244
+ display: event.target.message.value,
245
+ },
242
246
  ]);
243
247
 
244
248
  const response = await sendMessage(event.target.message.value);
245
249
 
246
- setMessages([
247
- ...messages,
248
- { id: Date.now(), role: 'assistant', display: response },
249
- ]);
250
+ setMessages(currentMessages => [...currentMessages, response]);
250
251
  };
251
252
 
252
253
  return (
@@ -143,7 +143,7 @@ export async function generateResponse(prompt: string) {
143
143
 
144
144
  ### Client
145
145
 
146
- ```tsx filename='app/page.tsx' highlight="22,30-34"
146
+ ```tsx filename='app/page.tsx' highlight="22,34-42"
147
147
  'use client';
148
148
 
149
149
  import { useState } from 'react';
@@ -169,15 +169,24 @@ export default function Home() {
169
169
 
170
170
  let textContent = '';
171
171
 
172
- for await (const responseDelta of readStreamableValue(response)) {
173
- textContent = `${textContent}${responseDelta}`;
174
- setGeneration(textContent);
175
- }
176
- for await (const loadingDelta of readStreamableValue(loadingState)) {
177
- if (loadingDelta) {
178
- setLoading(loadingDelta.loading);
179
- }
180
- }
172
+ // read both streamable values concurrently
173
+ await Promise.all([
174
+ (async () => {
175
+ for await (const responseDelta of readStreamableValue(response)) {
176
+ textContent = `${textContent}${responseDelta}`;
177
+ setGeneration(textContent);
178
+ }
179
+ })(),
180
+ (async () => {
181
+ for await (const loadingDelta of readStreamableValue(
182
+ loadingState,
183
+ )) {
184
+ if (loadingDelta) {
185
+ setLoading(loadingDelta.loading);
186
+ }
187
+ }
188
+ })(),
189
+ ]);
181
190
  setInput('');
182
191
  setLoading(false);
183
192
  }}
@@ -40,6 +40,8 @@ export async function getStreamedUI() {
40
40
  With this method, you can catch any error with the stream, and return relevant UI. On the client, you can also use a [React Error Boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) to wrap the streamed component and catch any additional errors.
41
41
 
42
42
  ```tsx filename='app/page.tsx'
43
+ 'use client';
44
+
43
45
  import { getStreamedUI } from '@/actions';
44
46
  import { useState } from 'react';
45
47
  import { ErrorBoundary } from './ErrorBoundary';
@@ -82,7 +82,8 @@ export default function Page() {
82
82
  {messages.map(message => message)}
83
83
 
84
84
  <form
85
- onSubmit={async () => {
85
+ onSubmit={async event => {
86
+ event.preventDefault();
86
87
  const response: ReactNode = await sendMessage(input);
87
88
  setMessages(msgs => [...msgs, response]);
88
89
  }}
@@ -642,9 +643,9 @@ export async function generateSampleNotifications() {
642
643
  for await (const partialObject of partialOutputStream) {
643
644
  stream.update(partialObject);
644
645
  }
645
- })();
646
646
 
647
- stream.done();
647
+ stream.done();
648
+ })();
648
649
 
649
650
  return { partialNotificationsStream: stream.value };
650
651
  }
@@ -120,12 +120,12 @@ const result = streamText({
120
120
  model: __MODEL__,
121
121
  prompt: 'Write a long story...',
122
122
  abortSignal: controller.signal,
123
- onAbort: ({ steps }) => {
123
+ onAbort: async ({ steps }) => {
124
124
  // Called when stream is aborted - persist partial results
125
125
  await savePartialResults(steps);
126
126
  await logAbortEvent(steps.length);
127
127
  },
128
- onEnd: ({ steps, totalUsage }) => {
128
+ onEnd: async ({ steps, totalUsage }) => {
129
129
  // Called when stream completes normally
130
130
  await saveFinalResults(steps, totalUsage);
131
131
  },
@@ -133,9 +133,9 @@ Here's an example of how you can use [Upstash Redis](https://upstash.com/redis)
133
133
  ```tsx filename="app/api/chat/route.ts"
134
134
  import {
135
135
  convertToModelMessages,
136
- createUIMessageStreamResponse,
136
+ createTextStreamResponse,
137
137
  streamText,
138
- toUIMessageStream,
138
+ toTextStream,
139
139
  UIMessage,
140
140
  } from 'ai';
141
141
  __PROVIDER_IMPORT__;
@@ -175,9 +175,13 @@ export async function POST(req: Request) {
175
175
  },
176
176
  });
177
177
 
178
- // Respond with the stream
179
- return createUIMessageStreamResponse({
180
- stream: toUIMessageStream({ stream: result.stream }),
178
+ // Respond with a text stream, matching the cached plain text response
179
+ return createTextStreamResponse({
180
+ stream: toTextStream({ stream: result.stream }),
181
181
  });
182
182
  }
183
183
  ```
184
+
185
+ Both the cached and the fresh responses use the
186
+ [text stream protocol](/docs/ai-sdk-ui/stream-protocol#text-stream-protocol),
187
+ so use `TextStreamChatTransport` when calling this route with `useChat`.
@@ -45,7 +45,7 @@ The client side code is similar to the previous example, but the [tool call](/do
45
45
  You can stream UI components within other UI components. This allows you to create complex UIs that are built up from smaller, reusable components. In the example below, we pass a `historyChart` streamable as a prop to a `StockCard` component. The StockCard can render the `historyChart` streamable, and it will automatically update as the server responds with new data.
46
46
 
47
47
  ```tsx file='app/actions.tsx'
48
- async function getStockHistoryChart({ symbol: string }) {
48
+ async function getStockHistoryChart({ symbol }: { symbol: string }) {
49
49
  'use server';
50
50
 
51
51
  const ui = createStreamableUI(<Spinner />);
@@ -48,7 +48,7 @@ const text = generateText({
48
48
  }),
49
49
  execute: async ({ city, unit }) => {
50
50
  const weather = getWeather({ city, unit });
51
- const { temperature, unit, description, forecast } = weather;
51
+ const { temperature, description, forecast } = weather;
52
52
 
53
53
  return {
54
54
  temperature,
@@ -158,14 +158,14 @@ The **AI SDK RSC (`@ai-sdk/rsc`)** takes advantage of RSCs to solve the problem
158
158
  Rather than conditionally rendering user interfaces on the client based on the data returned by the language model, you can directly stream them from the server during a model generation.
159
159
 
160
160
  ```tsx highlight="3,22-31,38" filename="app/action.ts"
161
- import { createStreamableUI } from '@ai-sdk/rsc'
161
+ import { createStreamableUI } from '@ai-sdk/rsc';
162
162
 
163
163
  const uiStream = createStreamableUI();
164
164
 
165
165
  const text = generateText({
166
166
  model: __MODEL__,
167
- instructions: 'you are a friendly assistant'
168
- prompt: 'what is the weather in SF?'
167
+ instructions: 'you are a friendly assistant',
168
+ prompt: 'what is the weather in SF?',
169
169
  tools: {
170
170
  getWeather: {
171
171
  description: 'Get the weather for a location',
@@ -173,30 +173,30 @@ const text = generateText({
173
173
  city: z.string().describe('The city to get the weather for'),
174
174
  unit: z
175
175
  .enum(['C', 'F'])
176
- .describe('The unit to display the temperature in')
176
+ .describe('The unit to display the temperature in'),
177
177
  }),
178
178
  execute: async ({ city, unit }) => {
179
- const weather = getWeather({ city, unit })
180
- const { temperature, unit, description, forecast } = weather
179
+ const weather = getWeather({ city, unit });
180
+ const { temperature, description, forecast } = weather;
181
181
 
182
182
  uiStream.done(
183
183
  <WeatherCard
184
184
  weather={{
185
185
  temperature: 47,
186
186
  unit: 'F',
187
- description: 'sunny'
187
+ description: 'sunny',
188
188
  forecast,
189
189
  }}
190
- />
191
- )
192
- }
193
- }
194
- }
195
- })
190
+ />,
191
+ );
192
+ },
193
+ },
194
+ },
195
+ });
196
196
 
197
197
  return {
198
- display: uiStream.value
199
- }
198
+ display: uiStream.value,
199
+ };
200
200
  ```
201
201
 
202
202
  The [`createStreamableUI`](/docs/reference/ai-sdk-rsc/create-streamable-ui) function belongs to the `@ai-sdk/rsc` module and creates a stream that can send React components to the client.
@@ -84,7 +84,7 @@ Tool: bookFlight("BA123", "12th December", ["John Doe", "Jane Doe"])
84
84
  Model: Your flight has been booked!
85
85
  ```
86
86
 
87
- In the last tool call, the `bookFlight` tool does not include passenger details as it is not available in the application context. As a result, it requests the user to provide the passenger details before proceeding with the booking.
87
+ Before the last tool call, the passenger details needed by the `bookFlight` tool are not available in the application context. As a result, the model asks the user to provide the passenger details before proceeding with the booking.
88
88
 
89
89
  Looking up passenger information could've been another tool that the model could've called before calling the `bookFlight` tool assuming that the user is logged into the application. This way, the model does not have to ask the user for the passenger details and can proceed with the booking.
90
90
 
@@ -278,7 +278,7 @@ To see `generateText` in action, check out [these examples](#examples).
278
278
  {
279
279
  name: 'role',
280
280
  type: "'tool'",
281
- description: 'The role for the assistant message.',
281
+ description: 'The role for the tool message.',
282
282
  },
283
283
  {
284
284
  name: 'content',
@@ -476,7 +476,7 @@ To see `generateText` in action, check out [these examples](#examples).
476
476
  },
477
477
  {
478
478
  name: 'timeout',
479
- type: 'number | { totalMs?: number; stepMs?: number; toolMs?: number; tools?: { [toolName]Ms?: number } }',
479
+ type: 'number | { totalMs?: number; stepMs?: number; toolMs?: number; tools?: Partial<Record<`${toolName}Ms`, number>> }',
480
480
  isOptional: true,
481
481
  description:
482
482
  'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, toolMs, and/or tools properties. totalMs sets the total timeout for the entire call. stepMs sets the timeout for each individual step (LLM call). toolMs sets the default timeout for all tool executions. tools sets per-tool timeout overrides using the pattern {toolName}Ms (e.g. weatherMs, slowApiMs) that take precedence over toolMs - tool names are type-checked for autocomplete. If a tool takes longer than its timeout, it aborts and returns a tool-error so the model can respond or retry. Can be used alongside abortSignal.',
@@ -1199,9 +1199,9 @@ To see `generateText` in action, check out [these examples](#examples).
1199
1199
  },
1200
1200
  {
1201
1201
  name: 'timeout',
1202
- type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number } | undefined',
1202
+ type: 'number | { totalMs?: number; stepMs?: number; firstChunkMs?: number; chunkMs?: number; toolMs?: number; tools?: Partial<Record<`${toolName}Ms`, number>> } | undefined',
1203
1203
  description:
1204
- 'Timeout configuration for the generation. Can be a number (milliseconds) or an object with totalMs, stepMs, chunkMs.',
1204
+ 'Timeout configuration for the generation. Can be a number (milliseconds) or an object with totalMs, stepMs, firstChunkMs (streaming only), chunkMs, toolMs, and per-tool overrides via tools.',
1205
1205
  },
1206
1206
  {
1207
1207
  name: 'headers',
@@ -279,7 +279,7 @@ To see `streamText` in action, check out [these examples](#examples).
279
279
  {
280
280
  name: 'role',
281
281
  type: "'tool'",
282
- description: 'The role for the assistant message.',
282
+ description: 'The role for the tool message.',
283
283
  },
284
284
  {
285
285
  name: 'content',
@@ -484,7 +484,7 @@ To see `streamText` in action, check out [these examples](#examples).
484
484
  },
485
485
  {
486
486
  name: 'timeout',
487
- type: 'number | { totalMs?: number; stepMs?: number; firstChunkMs?: number; chunkMs?: number; toolMs?: number; tools?: { [toolName]Ms?: number } }',
487
+ type: 'number | { totalMs?: number; stepMs?: number; firstChunkMs?: number; chunkMs?: number; toolMs?: number; tools?: Partial<Record<`${toolName}Ms`, number>> }',
488
488
  isOptional: true,
489
489
  description:
490
490
  'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, firstChunkMs, chunkMs, toolMs, and/or tools properties. totalMs sets the total timeout for the entire call. stepMs sets the timeout for each individual step (LLM call). firstChunkMs sets the timeout until the first content-bearing output in each step; metadata, stream starts, empty deltas, raw chunks, and transport activity do not satisfy it. chunkMs sets the timeout between content-bearing output chunks after output has started; non-content chunks do not reset it. toolMs sets the default timeout for all tool executions. tools sets per-tool timeout overrides using the pattern {toolName}Ms (e.g. weatherMs, slowApiMs) that take precedence over toolMs - tool names are type-checked for autocomplete. If a tool takes longer than its timeout, it aborts and returns a tool-error so the model can respond or retry. Can be used alongside abortSignal.',
@@ -2213,9 +2213,9 @@ To see `streamText` in action, check out [these examples](#examples).
2213
2213
  },
2214
2214
  {
2215
2215
  name: 'timeout',
2216
- type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number } | undefined',
2216
+ type: 'number | { totalMs?: number; stepMs?: number; firstChunkMs?: number; chunkMs?: number; toolMs?: number; tools?: Partial<Record<`${toolName}Ms`, number>> } | undefined',
2217
2217
  description:
2218
- 'Timeout configuration for the generation. Can be a number (milliseconds) or an object with totalMs, stepMs, chunkMs.',
2218
+ 'Timeout configuration for the generation. Can be a number (milliseconds) or an object with totalMs, stepMs, firstChunkMs (streaming only), chunkMs, toolMs, and per-tool overrides via tools.',
2219
2219
  },
2220
2220
  {
2221
2221
  name: 'headers',
@@ -88,6 +88,13 @@ console.log(await result.text);
88
88
  description:
89
89
  'When true, the provider includes raw provider chunks in the stream as `raw` parts.',
90
90
  },
91
+ {
92
+ name: 'telemetry',
93
+ type: 'TelemetryOptions',
94
+ isOptional: true,
95
+ description:
96
+ 'Telemetry configuration. Experimental lifecycle callbacks use experimental_onStreamTranscriptionStart and experimental_onStreamTranscriptionEnd. The end event is emitted after the audio stream is consumed and includes the final input byte length.',
97
+ },
91
98
  ]}
92
99
  />
93
100
 
@@ -64,6 +64,13 @@ console.log(transcript);
64
64
  isOptional: true,
65
65
  description: 'Additional HTTP headers for the request.',
66
66
  },
67
+ {
68
+ name: 'telemetry',
69
+ type: 'TelemetryOptions',
70
+ isOptional: true,
71
+ description:
72
+ 'Telemetry configuration. Supports functionId, recordInputs, recordOutputs, isEnabled, and per-call integrations.',
73
+ },
67
74
  {
68
75
  name: 'download',
69
76
  type: '(options: { url: URL; abortSignal?: AbortSignal }) => Promise<{ data: Uint8Array; mediaType: string | undefined }>',
@@ -124,6 +124,13 @@ const { audio } = await generateSpeech({
124
124
  isOptional: true,
125
125
  description: 'Additional HTTP headers for the request.',
126
126
  },
127
+ {
128
+ name: 'telemetry',
129
+ type: 'TelemetryOptions',
130
+ isOptional: true,
131
+ description:
132
+ 'Telemetry configuration. Supports functionId, recordInputs, recordOutputs, isEnabled, and per-call integrations.',
133
+ },
127
134
  ]}
128
135
  />
129
136
 
@@ -5,9 +5,9 @@ description: API Reference for uploadFile.
5
5
 
6
6
  # `uploadFile()`
7
7
 
8
- Uploads a file to a provider and returns a `ProviderReference` that can be used in
9
- subsequent API calls, such as in message content parts passed to `generateText` or
10
- `streamText`.
8
+ Uploads a file to a provider and returns a result whose `providerReference` (a
9
+ `ProviderReference`) can be used in subsequent API calls, such as in message
10
+ content parts passed to `generateText` or `streamText`.
11
11
 
12
12
  ```ts
13
13
  import { uploadFile } from 'ai';
@@ -74,7 +74,7 @@ const { providerReference } = await uploadFile({
74
74
  type: 'ProviderOptions',
75
75
  isOptional: true,
76
76
  description:
77
- 'Additional provider-specific options. For example, OpenAI requires a `purpose` field.',
77
+ 'Additional provider-specific options. For example, OpenAI accepts a `purpose` field, which defaults to `"assistants"`.',
78
78
  },
79
79
  ]}
80
80
  />
@@ -5,7 +5,7 @@ description: API Reference for uploadSkill.
5
5
 
6
6
  # `uploadSkill()`
7
7
 
8
- Uploads a skill (a bundle of files) to a provider and returns a `ProviderReference` that can be used in subsequent inference calls.
8
+ Uploads a skill (a bundle of files) to a provider and returns a result whose `providerReference` (a `ProviderReference`) can be used in subsequent inference calls.
9
9
 
10
10
  ```ts
11
11
  import { uploadSkill } from 'ai';
@@ -174,7 +174,7 @@ export interface Agent<
174
174
 
175
175
  ## Method Parameters
176
176
 
177
- Both `generate()` and `stream()` accept an `AgentCallParameters<CALL_OPTIONS, TOOLS>` object with:
177
+ `generate()` accepts an `AgentCallParameters<CALL_OPTIONS, TOOLS>` object, and `stream()` accepts an `AgentStreamParameters<CALL_OPTIONS, TOOLS>` object, which extends `AgentCallParameters` with an optional `experimental_transform`. Both accept:
178
178
 
179
179
  - `prompt` (optional): A string prompt or array of `ModelMessage` objects
180
180
  - `messages` (optional): An array of `ModelMessage` objects (mutually exclusive with `prompt`)
@@ -29,13 +29,10 @@ const agent = new ToolLoopAgent({
29
29
  export async function POST(request: Request) {
30
30
  const { messages } = await request.json();
31
31
 
32
- // Optional: support cancellation (aborts on disconnect, etc.)
33
- const abortController = new AbortController();
34
-
35
32
  return createAgentUIStreamResponse({
36
33
  agent,
37
34
  uiMessages: messages,
38
- abortSignal: abortController.signal, // optional
35
+ abortSignal: request.signal, // optional: aborts when the client disconnects
39
36
  // experimental_sandbox, // optional: passed through to tool execution
40
37
  // ...other UIMessageStreamOptions like sendSources, experimental_transform, etc.
41
38
  });
@@ -20,7 +20,7 @@ import { z } from 'zod';
20
20
 
21
21
  export const customTool = dynamicTool({
22
22
  description: 'Execute a custom user-defined function',
23
- inputSchema: z.object({}),
23
+ inputSchema: z.object({ action: z.string(), parameters: z.unknown() }),
24
24
  // input is typed as 'unknown'
25
25
  execute: async input => {
26
26
  const { action, parameters } = input as any;
@@ -13,7 +13,7 @@ Creates a lightweight Model Context Protocol (MCP) client that connects to an MC
13
13
  - **Completions**: Methods to request autocompletion suggestions for prompt arguments and resource template variables
14
14
  - **Elicitation**: Support for handling server requests for additional input during tool execution
15
15
 
16
- It currently does not support accepting notifications from an MCP server, and custom configuration of the client.
16
+ It currently does not support accepting notifications from an MCP server.
17
17
 
18
18
  ## Import
19
19
 
@@ -228,7 +228,7 @@ export interface ToolResultPart {
228
228
  /**
229
229
  * Result of the tool call. This is a JSON-serializable object.
230
230
  */
231
- output: LanguageModelV4ToolResultOutput;
231
+ output: ToolResultOutput;
232
232
 
233
233
  /**
234
234
  Additional provider-specific metadata. They are passed through
@@ -239,7 +239,7 @@ export interface ToolResultPart {
239
239
  }
240
240
  ```
241
241
 
242
- ### `LanguageModelV4ToolResultOutput`
242
+ ### `ToolResultOutput`
243
243
 
244
244
  ```ts
245
245
  /**
@@ -60,7 +60,7 @@ A [LanguageModelMiddleware](/docs/ai-sdk-core/middleware) that:
60
60
 
61
61
  - Locates function tools with an `inputExamples` property.
62
62
  - Serializes each input example (by default as JSON, or using your custom formatter).
63
- - Prepends a section at the end of the tool description containing all formatted examples, prefixed by the `prefix`.
63
+ - Appends a section at the end of the tool description containing all formatted examples, prefixed by the `prefix`.
64
64
  - Removes the `inputExamples` property from the tool (unless `remove: false`).
65
65
  - Passes through all other tools (including those without examples) unchanged.
66
66
 
@@ -6,7 +6,7 @@ description: Stream transformer for smoothing text and reasoning output
6
6
  # `smoothStream()`
7
7
 
8
8
  `smoothStream` is a utility function that creates a TransformStream
9
- for the `streamText` `transform` option
9
+ for the `streamText` `experimental_transform` option
10
10
  to smooth out text and reasoning streaming by buffering and releasing complete chunks with configurable delays.
11
11
  This creates a more natural reading experience when streaming text and reasoning responses.
12
12
 
@@ -110,7 +110,7 @@ const screenshotTool = tool({
110
110
 
111
111
  const result = streamText({
112
112
  model: __MODEL__,
113
- messages: convertToModelMessages(messages, {
113
+ messages: await convertToModelMessages(messages, {
114
114
  tools: {
115
115
  screenshot: screenshotTool,
116
116
  },
@@ -134,6 +134,7 @@ import {
134
134
  createUIMessageStreamResponse,
135
135
  streamText,
136
136
  toUIMessageStream,
137
+ type UIMessage,
137
138
  } from 'ai';
138
139
 
139
140
  type CustomUIMessage = UIMessage<
@@ -149,7 +150,7 @@ export async function POST(req: Request) {
149
150
 
150
151
  const result = streamText({
151
152
  model: __MODEL__,
152
- messages: convertToModelMessages<CustomUIMessage>(messages, {
153
+ messages: await convertToModelMessages<CustomUIMessage>(messages, {
153
154
  convertDataPart: part => {
154
155
  // Convert URL attachments to text
155
156
  if (part.type === 'data-url') {
@@ -219,7 +220,7 @@ Only data parts for which you return a text or file model message part are inclu
219
220
  all other data parts are ignored.
220
221
 
221
222
  ```ts
222
- const result = convertToModelMessages<
223
+ const result = await convertToModelMessages<
223
224
  UIMessage<
224
225
  unknown,
225
226
  {
@@ -237,7 +238,7 @@ const result = convertToModelMessages<
237
238
  };
238
239
  }
239
240
 
240
- // data-code and data-node are ignored
241
+ // data-code and data-note are ignored
241
242
  },
242
243
  });
243
244
  ```
@@ -62,7 +62,8 @@ const stream = createUIMessageStream({
62
62
  }),
63
63
  );
64
64
  },
65
- onError: error => `Custom error: ${error.message}`,
65
+ onError: error =>
66
+ `Custom error: ${error instanceof Error ? error.message : String(error)}`,
66
67
  originalMessages: existingMessages,
67
68
  onEnd: ({ messages, isContinuation, outcome, responseMessage }) => {
68
69
  console.log('Stream ended with messages:', messages);
@@ -124,7 +125,7 @@ outcomes and call `setOutcome` once.
124
125
  name: 'onError',
125
126
  type: '(error: unknown) => string',
126
127
  description:
127
- 'A function that handles errors and returns an error message string. By default, it returns the error message.',
128
+ 'A function that handles errors and returns an error message string. By default, it returns `"An error occurred."` so server-side error details are not sent to the client.',
128
129
  },
129
130
  {
130
131
  name: 'originalMessages',
@@ -108,6 +108,13 @@ const response = createUIMessageStreamResponse({
108
108
  isOptional: true,
109
109
  description: 'Additional headers for the response.',
110
110
  },
111
+ {
112
+ name: 'keepAliveMs',
113
+ type: 'number',
114
+ isOptional: true,
115
+ description:
116
+ 'Interval in milliseconds for sending SSE keep-alive comments. When set, an opening comment is sent immediately and additional comments are sent after the stream has been idle for the configured interval.',
117
+ },
111
118
  {
112
119
  name: 'consumeSseStream',
113
120
  type: '(options: { stream: ReadableStream<string> }) => PromiseLike<void> | void',
@@ -66,6 +66,13 @@ await pipeUIMessageStreamToResponse({
66
66
  isOptional: true,
67
67
  description: 'Additional headers for the response.',
68
68
  },
69
+ {
70
+ name: 'keepAliveMs',
71
+ type: 'number',
72
+ isOptional: true,
73
+ description:
74
+ 'Interval in milliseconds for sending SSE keep-alive comments. When set, an opening comment is sent immediately and additional comments are sent after the stream has been idle for the configured interval.',
75
+ },
69
76
  {
70
77
  name: 'consumeSseStream',
71
78
  type: '({ stream }: { stream: ReadableStream<string> }) => PromiseLike<void> | void',