ai 7.0.124 → 7.0.127

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 (29) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/index.d.ts +62 -24
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +101 -31
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts.map +1 -1
  7. package/dist/internal/index.js +32 -12
  8. package/dist/internal/index.js.map +1 -1
  9. package/docs/03-ai-sdk-core/16-mcp-tools.mdx +25 -0
  10. package/docs/03-ai-sdk-core/19-tool-search.mdx +40 -4
  11. package/docs/03-ai-sdk-core/35-image-generation.mdx +5 -0
  12. package/docs/03-ai-sdk-core/36-transcription.mdx +42 -38
  13. package/docs/03-ai-sdk-core/37-speech.mdx +4 -0
  14. package/docs/04-ai-sdk-ui/02-chatbot.mdx +2 -1
  15. package/docs/07-reference/01-ai-sdk-core/17-create-agent-ui-stream.mdx +7 -0
  16. package/docs/07-reference/01-ai-sdk-core/18-create-agent-ui-stream-response.mdx +7 -0
  17. package/docs/07-reference/01-ai-sdk-core/18-pipe-agent-ui-stream-to-response.mdx +7 -0
  18. package/docs/07-reference/01-ai-sdk-core/23-tool-search.mdx +62 -6
  19. package/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx +13 -0
  20. package/docs/07-reference/04-ai-sdk-workflow/01-workflow-agent.mdx +60 -3
  21. package/package.json +4 -4
  22. package/src/agent/create-agent-ui-stream-response.ts +16 -4
  23. package/src/agent/create-agent-ui-stream.ts +16 -2
  24. package/src/agent/pipe-agent-ui-stream-to-response.ts +16 -4
  25. package/src/generate-text/validate-tool-approvals.ts +5 -1
  26. package/src/tool-search/prepare-tool-search.ts +49 -29
  27. package/src/tool-search/tool-search.ts +58 -4
  28. package/src/ui/chat.ts +36 -5
  29. package/src/ui-message-stream/create-ui-message-stream.ts +29 -4
@@ -178,6 +178,31 @@ transports by providing an `authProvider`.
178
178
 
179
179
  </Note>
180
180
 
181
+ ### Shared OAuth Credential Storage
182
+
183
+ When multiple MCP clients or replicas share OAuth credentials, a rotating refresh
184
+ token can be used concurrently. One refresh may save new tokens while another
185
+ receives `invalid_grant` for the old refresh token.
186
+
187
+ The optional `OAuthClientProvider.invalidateCredentials` method receives a
188
+ second argument identifying the tokens used by a failed refresh:
189
+
190
+ ```typescript
191
+ invalidateCredentials(
192
+ scope: 'all' | 'client' | 'tokens' | 'verifier',
193
+ context?: { tokens: OAuthTokens },
194
+ ): void | Promise<void>;
195
+ ```
196
+
197
+ For `scope === 'tokens'` with a context, delete the credential only if the stored
198
+ access and refresh tokens still match `context.tokens`. The comparison and
199
+ deletion must be atomic, using a conditional database operation or a transaction.
200
+ If they no longer match, leave the newer tokens in storage. The SDK retries
201
+ authorization and reads the stored tokens again.
202
+
203
+ The SDK also provides this context when invalidating stored tokens that lack an
204
+ authorization server pin. Other invalidations can omit the context.
205
+
181
206
  ### OAuth Authorization Server Validation
182
207
 
183
208
  When using MCP OAuth in server-side applications, the MCP server can advertise
@@ -11,8 +11,9 @@ search matches their names and descriptions and makes them available on the
11
11
  **next model step**.
12
12
 
13
13
  Use it with `generateText`, `streamText`, `ToolLoopAgent`, or `WorkflowAgent` from
14
- `@ai-sdk/workflow`. The factory takes no arguments; the model supplies a search
15
- query. `WorkflowAgent` supports direct tool calling; the other APIs also support
14
+ `@ai-sdk/workflow`. The model supplies a search query; the factory optionally
15
+ accepts an application-defined `search` callback and a `maxResults` limit.
16
+ `WorkflowAgent` supports direct tool calling; the other APIs also support
16
17
  cache-preserving code mode.
17
18
 
18
19
  ## Direct Tool Calling
@@ -73,10 +74,45 @@ The model first runs `tools.search({ query: 'weather forecast' })`. On the next
73
74
  step, it receives the updated capability catalog and can call
74
75
  `tools.weather({ city: 'Bangalore' })`.
75
76
 
76
- In both modes, search loads up to five matches, respects `activeTools` and caller
77
- routing, and keeps discovered tools available for the rest of the generation.
77
+ In both modes, search loads up to five matches by default, respects `activeTools`
78
+ and caller routing, and keeps discovered tools available for the rest of the
79
+ generation.
78
80
  MCP client tools work too: add `deferLoading: true` to the tools returned by
79
81
  `client.tools()`.
80
82
 
83
+ Set `maxResults` to change the number of matching tools loaded per search:
84
+
85
+ ```ts
86
+ const search = toolSearch({ maxResults: 10 });
87
+ ```
88
+
89
+ `maxResults` must be a positive safe integer. A larger limit can load related
90
+ tools in one search, but also adds more tool definitions to the model context.
91
+ It does not change keyword matching or ranking.
92
+
93
+ ## Custom Search
94
+
95
+ Provide a `search` callback when your application needs different matching or
96
+ ranking. It receives the query and all eligible deferred tool names and resolved
97
+ descriptions, and returns ranked names. It can be synchronous or asynchronous.
98
+
99
+ ```ts
100
+ const search = toolSearch({
101
+ search: ({ query, tools }) => {
102
+ // Discover related Gmail actions together, in the application's preferred order.
103
+ const preferred = /\bgmail\b/i.test(query)
104
+ ? ['gmail_list_messages', 'gmail_get_message']
105
+ : [];
106
+ return preferred.filter(name => tools.some(tool => tool.name === name));
107
+ },
108
+ });
109
+ ```
110
+
111
+ The SDK filters unknown names and duplicates before keeping the first `maxResults`
112
+ valid results (five by default). Tools excluded by `activeTools` or caller routing
113
+ remain unavailable.
114
+ Discovery still takes effect on the next model step. Without a callback, search
115
+ keeps its default keyword matching and ranking.
116
+
81
117
  See the [`toolSearch()` reference](/docs/reference/ai-sdk-core/tool-search) for
82
118
  input, output, and matching details.
@@ -400,6 +400,11 @@ for (const file of result.files) {
400
400
  | [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1.1-pro` | 512x512, 768x768, 1024x1024 |
401
401
  | [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1-pro` | 512x512, 768x768, 1024x1024 |
402
402
  | [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1-schnell-Free` | 512x512, 768x768, 1024x1024 |
403
+ | [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-2-pro` | From 3:7 (portrait) to 7:3 (landscape) |
404
+ | [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-2-max` | From 3:7 (portrait) to 7:3 (landscape) |
405
+ | [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-2-flex` | From 3:7 (portrait) to 7:3 (landscape) |
406
+ | [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-2-klein-9b` | From 3:7 (portrait) to 7:3 (landscape) |
407
+ | [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-2-klein-4b` | From 3:7 (portrait) to 7:3 (landscape) |
403
408
  | [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-kontext-pro` | From 3:7 (portrait) to 7:3 (landscape) |
404
409
  | [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-kontext-max` | From 3:7 (portrait) to 7:3 (landscape) |
405
410
  | [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-pro-1.1-ultra` | From 3:7 (portrait) to 7:3 (landscape) |
@@ -138,7 +138,9 @@ The `audio` stream must contain raw audio chunks. `Uint8Array` chunks are raw by
138
138
  OpenAI streaming transcription uses `openai.transcription('gpt-realtime-whisper')`.
139
139
  Cartesia uses `cartesia.transcription('ink-2')` for streaming-only Ink 2
140
140
  transcription. ElevenLabs uses
141
- `elevenLabs.transcription('scribe_v2_realtime')` for Scribe v2 Realtime. xAI
141
+ `elevenLabs.transcription('scribe_v2_realtime')` for Scribe v2 Realtime. Azure
142
+ uses `azure.transcription('mai-transcribe-2-streaming')` for streaming-only
143
+ MAI-Transcribe-2-Streaming. xAI
142
144
  uses the same `xai.transcription()` model for request/response and streaming
143
145
  transcription; `experimental_streamTranscribe` selects the provider's
144
146
  WebSocket STT transport.
@@ -329,42 +331,44 @@ try {
329
331
 
330
332
  ## Transcription Models
331
333
 
332
- | Provider | Model |
333
- | ----------------------------------------------------------------------------------- | --------------------------- |
334
- | [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `whisper-1` |
335
- | [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-transcribe` |
336
- | [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-mini-transcribe` |
337
- | [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-transcribe-diarize` |
338
- | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v1` |
339
- | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v1_experimental` |
340
- | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v2` |
341
- | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#streaming-transcription-models) | `scribe_v2_realtime` |
342
- | [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3-turbo` |
343
- | [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3` |
344
- | [Mistral](/providers/ai-sdk-providers/mistral#transcription-models) | `voxtral-mini-latest` |
345
- | [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `whisper-1` |
346
- | [Azure Speech](/providers/ai-sdk-providers/azure#mai-transcribe-2) | `mai-transcribe-2` |
347
- | [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-transcribe` |
348
- | [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-mini-transcribe` |
349
- | [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `machine` |
350
- | [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `low_cost` |
351
- | [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `fusion` |
352
- | [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `base` (+ variants) |
353
- | [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `enhanced` (+ variants) |
354
- | [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova` (+ variants) |
355
- | [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova-2` (+ variants) |
356
- | [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova-3` (+ variants) |
357
- | [Gladia](/providers/ai-sdk-providers/gladia#transcription-models) | `default` |
358
- | [AssemblyAI](/providers/ai-sdk-providers/assemblyai#transcription-models) | `universal-3-5-pro` |
359
- | [AssemblyAI](/providers/ai-sdk-providers/assemblyai#transcription-models) | `universal-3-pro` |
360
- | [Fal](/providers/ai-sdk-providers/fal#transcription-models) | `whisper` |
361
- | [Fal](/providers/ai-sdk-providers/fal#transcription-models) | `wizper` |
362
- | [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `chirp_2` |
363
- | [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `chirp_3` |
364
- | [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `telephony` |
365
- | [xAI](/providers/ai-sdk-providers/xai#transcription-models) | `default` |
366
- | [Cartesia](/providers/ai-sdk-providers/cartesia#transcription-models) | `ink-whisper` |
367
- | [Cartesia](/providers/ai-sdk-providers/cartesia#streaming-transcription-models) | `ink-2` |
368
- | [Fish Audio](/providers/ai-sdk-providers/fish-audio#transcription-models) | `transcribe-1` |
334
+ | Provider | Model |
335
+ | ----------------------------------------------------------------------------------- | ---------------------------- |
336
+ | [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `whisper-1` |
337
+ | [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-transcribe` |
338
+ | [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-mini-transcribe` |
339
+ | [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-transcribe-diarize` |
340
+ | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v1` |
341
+ | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v1_experimental` |
342
+ | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v2` |
343
+ | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#streaming-transcription-models) | `scribe_v2_realtime` |
344
+ | [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3-turbo` |
345
+ | [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3` |
346
+ | [Mistral](/providers/ai-sdk-providers/mistral#transcription-models) | `voxtral-mini-latest` |
347
+ | [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `whisper-1` |
348
+ | [Azure Speech](/providers/ai-sdk-providers/azure#mai-transcribe) | `mai-transcribe-2` |
349
+ | [Azure Speech](/providers/ai-sdk-providers/azure#mai-transcribe) | `mai-transcribe-1.5` |
350
+ | [Azure MAI](/providers/ai-sdk-providers/azure#mai-transcribe-2-streaming) | `mai-transcribe-2-streaming` |
351
+ | [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-transcribe` |
352
+ | [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-mini-transcribe` |
353
+ | [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `machine` |
354
+ | [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `low_cost` |
355
+ | [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `fusion` |
356
+ | [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `base` (+ variants) |
357
+ | [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `enhanced` (+ variants) |
358
+ | [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova` (+ variants) |
359
+ | [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova-2` (+ variants) |
360
+ | [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova-3` (+ variants) |
361
+ | [Gladia](/providers/ai-sdk-providers/gladia#transcription-models) | `default` |
362
+ | [AssemblyAI](/providers/ai-sdk-providers/assemblyai#transcription-models) | `universal-3-5-pro` |
363
+ | [AssemblyAI](/providers/ai-sdk-providers/assemblyai#transcription-models) | `universal-3-pro` |
364
+ | [Fal](/providers/ai-sdk-providers/fal#transcription-models) | `whisper` |
365
+ | [Fal](/providers/ai-sdk-providers/fal#transcription-models) | `wizper` |
366
+ | [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `chirp_2` |
367
+ | [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `chirp_3` |
368
+ | [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `telephony` |
369
+ | [xAI](/providers/ai-sdk-providers/xai#transcription-models) | `default` |
370
+ | [Cartesia](/providers/ai-sdk-providers/cartesia#transcription-models) | `ink-whisper` |
371
+ | [Cartesia](/providers/ai-sdk-providers/cartesia#streaming-transcription-models) | `ink-2` |
372
+ | [Fish Audio](/providers/ai-sdk-providers/fish-audio#transcription-models) | `transcribe-1` |
369
373
 
370
374
  Above are a small subset of the transcription models supported by the AI SDK providers. For more, see the respective provider documentation.
@@ -158,6 +158,10 @@ try {
158
158
  | [OpenAI](/providers/ai-sdk-providers/openai#speech-models) | `tts-1-hd` |
159
159
  | [OpenAI](/providers/ai-sdk-providers/openai#speech-models) | `gpt-4o-mini-tts` |
160
160
  | [Mistral](/providers/ai-sdk-providers/mistral#speech-models) | `voxtral-mini-tts-2603` |
161
+ | [Azure Speech](/providers/ai-sdk-providers/azure#mai-voice) | `mai-voice-2.1-flash` |
162
+ | [Azure Speech](/providers/ai-sdk-providers/azure#mai-voice) | `mai-voice-2.1` |
163
+ | [Azure Speech](/providers/ai-sdk-providers/azure#mai-voice) | `mai-voice-2-flash` |
164
+ | [Azure Speech](/providers/ai-sdk-providers/azure#mai-voice) | `mai-voice-2` |
161
165
  | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#speech-models) | `eleven_v3` |
162
166
  | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#speech-models) | `eleven_multilingual_v2` |
163
167
  | [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#speech-models) | `eleven_flash_v2_5` |
@@ -323,7 +323,8 @@ When the user clicks the "Regenerate" button, the AI provider will regenerate th
323
323
 
324
324
  ### Throttling UI Updates
325
325
 
326
- By default, the `useChat` hook will trigger a render every time a new chunk is received.
326
+ By default, `useChat` publishes message updates as each chunk is processed.
327
+ React may batch multiple updates into a single render.
327
328
  React and Vue applications can throttle reactive message updates with the `throttle` option.
328
329
  Stream processing and event callbacks remain immediate, and the latest messages are published before the chat enters a terminal `ready` or `error` status.
329
330
 
@@ -59,6 +59,13 @@ export async function* streamAgent(
59
59
  description:
60
60
  'Array of input UI message objects (e.g., user/assistant/chat history). These will be validated and converted for the agent.',
61
61
  },
62
+ {
63
+ name: 'convertDataPart',
64
+ type: '(part: DataUIPart) => TextPart | FilePart | undefined',
65
+ isRequired: false,
66
+ description:
67
+ 'Converts custom UI data parts into text or file parts for the model. Data parts are ignored when this callback is omitted or returns undefined.',
68
+ },
62
69
  {
63
70
  name: 'abortSignal',
64
71
  type: 'AbortSignal',
@@ -57,6 +57,13 @@ export async function POST(request: Request) {
57
57
  description:
58
58
  'Array of input UI messages provided to the agent (e.g., user and assistant messages).',
59
59
  },
60
+ {
61
+ name: 'convertDataPart',
62
+ type: '(part: DataUIPart) => TextPart | FilePart | undefined',
63
+ isRequired: false,
64
+ description:
65
+ 'Converts custom UI data parts into text or file parts for the model. Data parts are ignored when this callback is omitted or returns undefined.',
66
+ },
60
67
  {
61
68
  name: 'abortSignal',
62
69
  type: 'AbortSignal',
@@ -61,6 +61,13 @@ export async function handler(req, res) {
61
61
  description:
62
62
  'Array of input UI messages sent to the agent (such as user/assistant message objects).',
63
63
  },
64
+ {
65
+ name: 'convertDataPart',
66
+ type: '(part: DataUIPart) => TextPart | FilePart | undefined',
67
+ isRequired: false,
68
+ description:
69
+ 'Converts custom UI data parts into text or file parts for the model. Data parts are ignored when this callback is omitted or returns undefined.',
70
+ },
64
71
  {
65
72
  name: 'abortSignal',
66
73
  type: 'AbortSignal',
@@ -5,8 +5,8 @@ description: Search deferred tools and load their definitions on demand for dire
5
5
 
6
6
  # `toolSearch()`
7
7
 
8
- Creates a tool that searches the surrounding generation's deferred tools by name
9
- and description. The factory takes no arguments. Use it with `generateText`,
8
+ Creates a tool that searches the surrounding generation's deferred tools, using
9
+ keyword matching by default or a custom search callback. Use it with `generateText`,
10
10
  `streamText`, `ToolLoopAgent`, or `WorkflowAgent` from `@ai-sdk/workflow`.
11
11
  `WorkflowAgent` supports direct tool calling. The other APIs also support code
12
12
  mode configured with `toolDiscovery: 'conversation'`.
@@ -20,6 +20,60 @@ const search = toolSearch();
20
20
  See the [Tool Search guide](/docs/ai-sdk-core/tool-search) for direct-calling and
21
21
  code mode examples, including how code mode preserves the tool-definition cache.
22
22
 
23
+ ## Options
24
+
25
+ Pass an optional configuration object to control the result limit:
26
+
27
+ ```ts
28
+ const search = toolSearch({ maxResults: 10 });
29
+ ```
30
+
31
+ `maxResults` is the maximum number of matching tools returned and discovered per
32
+ search. It defaults to `5` and must be a positive safe integer. Invalid values
33
+ throw `InvalidArgumentError` when creating the search tool. The model-facing
34
+ description reflects the configured limit.
35
+
36
+ The limit applies to both default keyword search and custom search callbacks,
37
+ without changing their matching or ranking. Discovered tools accumulate across
38
+ searches, so this is not a limit on the total number of tools loaded during a
39
+ generation.
40
+
41
+ Pass a `search` callback to select and rank tools using your application's search
42
+ logic. The callback can return synchronously or asynchronously:
43
+
44
+ ```ts
45
+ const search = toolSearch({
46
+ search: ({ query, tools }) => {
47
+ const preferred = /\bgmail\b/i.test(query)
48
+ ? ['gmail_list_messages', 'gmail_get_message']
49
+ : [];
50
+ return preferred.filter(name => tools.some(tool => tool.name === name));
51
+ },
52
+ });
53
+ ```
54
+
55
+ The callback has this signature:
56
+
57
+ ```ts
58
+ search?: (options: {
59
+ query: string;
60
+ tools: Array<{ name: string; description?: string }>;
61
+ }) => string[] | PromiseLike<string[]>;
62
+ ```
63
+
64
+ `tools` contains all eligible deferred tools, before keyword matching or ranking.
65
+ Eligibility respects `activeTools` and caller routing. Descriptions are resolved
66
+ using the current tool context and sandbox; schemas are not included.
67
+
68
+ Return tool names in ranked order. The SDK ignores unknown or ineligible names,
69
+ removes duplicates while preserving order, and keeps the first `maxResults` valid
70
+ names (five by default). Returned descriptions come from the SDK's candidate
71
+ catalog. An empty array
72
+ discovers no tools. Callback errors follow normal tool-execution error handling;
73
+ the SDK does not fall back to keyword search.
74
+
75
+ Without a callback, `toolSearch()` uses the default keyword search described below.
76
+
23
77
  ## Model Input
24
78
 
25
79
  The model supplies the following input to the search tool:
@@ -28,11 +82,12 @@ The model supplies the following input to the search tool:
28
82
  { "query": "weather forecast" }
29
83
  ```
30
84
 
31
- `query` is a required, nonempty string of search keywords. Search is local and
85
+ `query` is a required, nonempty string. By default, search is local and
32
86
  case-insensitive, matching words in tool names and descriptions. Camel-case names
33
87
  are split into words. Name matches rank above description matches; equal scores
34
88
  preserve registration order. Function descriptions are resolved with the current
35
- tool context and sandbox. No embedding service or additional model call is used.
89
+ tool context and sandbox. The default search uses no embedding service or
90
+ additional model call. A custom callback can use either.
36
91
 
37
92
  ## Output
38
93
 
@@ -44,8 +99,9 @@ tool context and sandbox. No embedding service or additional model call is used.
44
99
  }
45
100
  ```
46
101
 
47
- Results contain at most five matching tools, with their names and optional
48
- descriptions. They do not include schemas. No matches returns `{ tools: [] }`.
102
+ Results contain at most `maxResults` matching tools (five by default), with their
103
+ names and optional descriptions. They do not include schemas. No matches returns
104
+ `{ tools: [] }`.
49
105
  Every returned match is queued for discovery. Newly discovered tools can only be
50
106
  called on the next model step, after their definitions have been provided. A
51
107
  parallel call in the same response as the search cannot use a newly discovered
@@ -486,6 +486,19 @@ Allows you to easily create a conversational user interface for your chatbot app
486
486
  ]}
487
487
  />
488
488
 
489
+ ## React rendering and shared Chat instances
490
+
491
+ In React, `messages`, `status`, and `error` describe the snapshot for the current render.
492
+ The underlying `Chat` updates as stream chunks are processed. React may batch updates,
493
+ and `throttle` can delay message rendering without delaying stream processing or callbacks.
494
+ Status and error updates include the latest messages, so a completed or failed response
495
+ is rendered with its final message snapshot.
496
+
497
+ Each `useChat({ chat })` call subscribes independently. Consumers sharing a `Chat`
498
+ can display different message snapshots when they use different throttle intervals.
499
+ A functional `setMessages` updater receives the Chat's latest messages, which may be
500
+ newer than the messages in the current render.
501
+
489
502
  ## Learn more
490
503
 
491
504
  - [Chatbot](/docs/ai-sdk-ui/chatbot)
@@ -120,7 +120,7 @@ To see `WorkflowAgent` in action, check out [these examples](#examples).
120
120
  type: 'ToolCallRepairFunction',
121
121
  isOptional: true,
122
122
  description:
123
- 'Default function to repair tool calls that fail to parse. Per-stream values override this default.',
123
+ "Default function to repair tool calls that fail to parse. Mark the function with 'use step' when used in a workflow. Per-stream values override this default.",
124
124
  },
125
125
  {
126
126
  name: 'experimental_download',
@@ -573,13 +573,13 @@ const result = await agent.stream({
573
573
  name: 'repairToolCall',
574
574
  type: 'ToolCallRepairFunction',
575
575
  isOptional: true,
576
- description: 'Callback to attempt automatic recovery when a tool call cannot be parsed.',
576
+ description: "Callback to attempt automatic recovery when a tool call cannot be parsed. Mark the function with 'use step' when used in a workflow.",
577
577
  },
578
578
  {
579
579
  name: 'experimental_transform',
580
580
  type: 'StreamTextTransform | Array<StreamTextTransform>',
581
581
  isOptional: true,
582
- description: 'Stream transformations applied in order. Must maintain the stream structure.',
582
+ description: "Factories for stream transformations, applied in order to raw provider events before model processing and writable output. Each factory must return a TransformStream synchronously and maintain the stream structure. Mark each factory with 'use step' when used in a workflow.",
583
583
  },
584
584
  {
585
585
  name: 'experimental_download',
@@ -750,6 +750,63 @@ Returns a `Promise<WorkflowAgentStreamResult>` with the following properties:
750
750
  ]}
751
751
  />
752
752
 
753
+ ### `repairToolCall` in a workflow
754
+
755
+ `repairToolCall` runs inside the model step. When you use it in a workflow,
756
+ define the callback as a function with a `'use step'` directive. You can set
757
+ it on the constructor or pass it to `stream()`.
758
+
759
+ Workflow saves a reference to the registered function and loads its
760
+ implementation inside the model step. Keep any values captured by the
761
+ function serializable. An ordinary inline callback causes a serialization
762
+ error when it crosses this step boundary.
763
+
764
+ The callback can be asynchronous. Return the repaired tool call, or `null`
765
+ if the repair cannot be completed. See [tool call repair](/docs/ai-sdk-core/tools-and-tool-calling#tool-call-repair)
766
+ for repair strategies.
767
+
768
+ ### `experimental_transform` in a workflow
769
+
770
+ Pass a transform factory, or an array of factories, to `stream()`.
771
+ Mark each factory with `'use step'` so Workflow can load it inside the model
772
+ step. The factory must return a `TransformStream` synchronously. Keep any
773
+ captured values serializable.
774
+
775
+ ```ts
776
+ import type { LanguageModelV4StreamPart } from '@ai-sdk/provider';
777
+ import { WorkflowAgent } from '@ai-sdk/workflow';
778
+ import { getWritable } from 'workflow';
779
+
780
+ function uppercaseText() {
781
+ 'use step';
782
+
783
+ return new TransformStream<
784
+ LanguageModelV4StreamPart,
785
+ LanguageModelV4StreamPart
786
+ >({
787
+ transform(part, controller) {
788
+ controller.enqueue(
789
+ part.type === 'text-delta'
790
+ ? { ...part, delta: part.delta.toUpperCase() }
791
+ : part,
792
+ );
793
+ },
794
+ });
795
+ }
796
+
797
+ export async function uppercaseWorkflow() {
798
+ 'use workflow';
799
+
800
+ const agent = new WorkflowAgent({ model: 'openai/gpt-5' });
801
+
802
+ return agent.stream({
803
+ messages: [{ role: 'user', content: 'Write a short greeting.' }],
804
+ writable: getWritable(),
805
+ experimental_transform: uppercaseText,
806
+ });
807
+ }
808
+ ```
809
+
753
810
  ## Utilities
754
811
 
755
812
  ### `createModelCallToUIChunkTransform(options?)`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "7.0.124",
3
+ "version": "7.0.127",
4
4
  "type": "module",
5
5
  "description": "AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.",
6
6
  "license": "Apache-2.0",
@@ -42,16 +42,16 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
- "@ai-sdk/gateway": "4.0.102",
45
+ "@ai-sdk/gateway": "4.0.103",
46
46
  "@ai-sdk/provider": "4.0.21",
47
47
  "@ai-sdk/provider-utils": "5.0.53"
48
48
  },
49
49
  "devDependencies": {
50
- "@ai-sdk/amazon-bedrock": "5.0.103",
50
+ "@ai-sdk/amazon-bedrock": "5.0.105",
51
51
  "@ai-sdk/deepseek": "3.0.58",
52
52
  "@ai-sdk/google": "4.0.87",
53
53
  "@ai-sdk/groq": "4.0.54",
54
- "@ai-sdk/huggingface": "2.0.61",
54
+ "@ai-sdk/huggingface": "2.0.62",
55
55
  "@ai-sdk/moonshotai": "3.0.62",
56
56
  "@ai-sdk/openai": "4.0.83",
57
57
  "@ai-sdk/test-server": "2.0.3",
@@ -14,8 +14,9 @@ import type { UIMessageStreamOptions } from '../generate-text/stream-text-result
14
14
  import type { TimeoutConfiguration } from '../prompt/request-options';
15
15
  import { createUIMessageStreamResponse } from '../ui-message-stream';
16
16
  import type { UIMessageStreamResponseInit } from '../ui-message-stream/ui-message-stream-response-init';
17
- import type { InferUITools, UIMessage } from '../ui/ui-messages';
17
+ import type { InferUITools, UIMessage, UIDataTypes } from '../ui/ui-messages';
18
18
  import type { Agent } from './agent';
19
+ import type { convertToModelMessages } from '../ui/convert-to-model-messages';
19
20
  import { createAgentUIStream } from './create-agent-ui-stream';
20
21
 
21
22
  /**
@@ -23,6 +24,7 @@ import { createAgentUIStream } from './create-agent-ui-stream';
23
24
  *
24
25
  * @param agent - The agent to run.
25
26
  * @param uiMessages - The input UI messages.
27
+ * @param convertDataPart - Optional function to convert custom data parts to text or file model message parts.
26
28
  * @param abortSignal - Abort signal. Optional.
27
29
  * @param timeout - Timeout in milliseconds. Optional.
28
30
  * @param experimental_sandbox - The sandbox environment that is passed through to tool execution. Optional.
@@ -44,6 +46,11 @@ export async function createAgentUIStreamResponse<
44
46
  RUNTIME_CONTEXT extends Context = Context,
45
47
  OUTPUT extends Output = never,
46
48
  MESSAGE_METADATA = unknown,
49
+ UI_MESSAGE extends UIMessage<
50
+ MESSAGE_METADATA,
51
+ UIDataTypes,
52
+ InferUITools<TOOLS>
53
+ > = UIMessage<MESSAGE_METADATA, UIDataTypes, InferUITools<TOOLS>>,
47
54
  >({
48
55
  headers,
49
56
  status,
@@ -54,6 +61,13 @@ export async function createAgentUIStreamResponse<
54
61
  }: {
55
62
  agent: Agent<CALL_OPTIONS, TOOLS, RUNTIME_CONTEXT, OUTPUT>;
56
63
  uiMessages: unknown[];
64
+ /**
65
+ * Converts custom UI data parts to text or file model message parts.
66
+ * Data parts are ignored when omitted or when the callback returns undefined.
67
+ */
68
+ convertDataPart?: NonNullable<
69
+ Parameters<typeof convertToModelMessages<UI_MESSAGE>>[1]
70
+ >['convertDataPart'];
57
71
  abortSignal?: AbortSignal;
58
72
  timeout?: TimeoutConfiguration<TOOLS>;
59
73
  experimental_sandbox?: SandboxSession;
@@ -63,9 +77,7 @@ export async function createAgentUIStreamResponse<
63
77
  /** @deprecated Use `onStepEnd` instead. */
64
78
  onStepFinish?: GenerateTextOnStepFinishCallback<TOOLS>;
65
79
  } & UIMessageStreamResponseInit &
66
- UIMessageStreamOptions<
67
- UIMessage<MESSAGE_METADATA, never, InferUITools<TOOLS>>
68
- >): Promise<Response> {
80
+ UIMessageStreamOptions<UI_MESSAGE>): Promise<Response> {
69
81
  return createUIMessageStreamResponse({
70
82
  headers,
71
83
  status,
@@ -20,6 +20,7 @@ import type {
20
20
  InferUIMessageTools,
21
21
  InferUITools,
22
22
  UIMessage,
23
+ UIDataTypes,
23
24
  } from '../ui/ui-messages';
24
25
  import { validateUIMessagesForAgent } from '../ui/validate-ui-messages';
25
26
  import {
@@ -33,6 +34,7 @@ import type { Agent } from './agent';
33
34
  *
34
35
  * @param agent - The agent to run.
35
36
  * @param uiMessages - The input UI messages.
37
+ * @param convertDataPart - Optional function to convert custom data parts to text or file model message parts.
36
38
  * @param abortSignal - The abort signal. Optional.
37
39
  * @param timeout - Timeout in milliseconds. Optional.
38
40
  * @param experimental_sandbox - The sandbox environment that is passed through to tool execution. Optional.
@@ -49,11 +51,15 @@ export async function createAgentUIStream<
49
51
  RUNTIME_CONTEXT extends Context = Context,
50
52
  OUTPUT extends Output = never,
51
53
  MESSAGE_METADATA = unknown,
52
- UI_MESSAGE extends UIMessage<MESSAGE_METADATA, never, InferUITools<TOOLS>> =
53
- UIMessage<MESSAGE_METADATA, never, InferUITools<TOOLS>>,
54
+ UI_MESSAGE extends UIMessage<
55
+ MESSAGE_METADATA,
56
+ UIDataTypes,
57
+ InferUITools<TOOLS>
58
+ > = UIMessage<MESSAGE_METADATA, UIDataTypes, InferUITools<TOOLS>>,
54
59
  >({
55
60
  agent,
56
61
  uiMessages,
62
+ convertDataPart,
57
63
  options,
58
64
  abortSignal,
59
65
  timeout,
@@ -65,6 +71,13 @@ export async function createAgentUIStream<
65
71
  }: {
66
72
  agent: Agent<CALL_OPTIONS, TOOLS, RUNTIME_CONTEXT, OUTPUT>;
67
73
  uiMessages: unknown[];
74
+ /**
75
+ * Converts custom UI data parts to text or file model message parts.
76
+ * Data parts are ignored when omitted or when the callback returns undefined.
77
+ */
78
+ convertDataPart?: NonNullable<
79
+ Parameters<typeof convertToModelMessages<UI_MESSAGE>>[1]
80
+ >['convertDataPart'];
68
81
  abortSignal?: AbortSignal;
69
82
  timeout?: TimeoutConfiguration<TOOLS>;
70
83
  experimental_sandbox?: SandboxSession;
@@ -91,6 +104,7 @@ export async function createAgentUIStream<
91
104
 
92
105
  const modelMessages = await convertToModelMessages(validatedMessages, {
93
106
  tools: agent.tools,
107
+ convertDataPart,
94
108
  });
95
109
 
96
110
  const result = await agent.stream({