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.
- package/CHANGELOG.md +23 -0
- package/dist/index.d.ts +62 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +101 -31
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +32 -12
- package/dist/internal/index.js.map +1 -1
- package/docs/03-ai-sdk-core/16-mcp-tools.mdx +25 -0
- package/docs/03-ai-sdk-core/19-tool-search.mdx +40 -4
- package/docs/03-ai-sdk-core/35-image-generation.mdx +5 -0
- package/docs/03-ai-sdk-core/36-transcription.mdx +42 -38
- package/docs/03-ai-sdk-core/37-speech.mdx +4 -0
- package/docs/04-ai-sdk-ui/02-chatbot.mdx +2 -1
- package/docs/07-reference/01-ai-sdk-core/17-create-agent-ui-stream.mdx +7 -0
- package/docs/07-reference/01-ai-sdk-core/18-create-agent-ui-stream-response.mdx +7 -0
- package/docs/07-reference/01-ai-sdk-core/18-pipe-agent-ui-stream-to-response.mdx +7 -0
- package/docs/07-reference/01-ai-sdk-core/23-tool-search.mdx +62 -6
- package/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx +13 -0
- package/docs/07-reference/04-ai-sdk-workflow/01-workflow-agent.mdx +60 -3
- package/package.json +4 -4
- package/src/agent/create-agent-ui-stream-response.ts +16 -4
- package/src/agent/create-agent-ui-stream.ts +16 -2
- package/src/agent/pipe-agent-ui-stream-to-response.ts +16 -4
- package/src/generate-text/validate-tool-approvals.ts +5 -1
- package/src/tool-search/prepare-tool-search.ts +49 -29
- package/src/tool-search/tool-search.ts +58 -4
- package/src/ui/chat.ts +36 -5
- 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
|
|
15
|
-
|
|
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`
|
|
77
|
-
routing, and keeps discovered tools available for the rest of the
|
|
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.
|
|
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
|
|
347
|
-
| [Azure
|
|
348
|
-
| [Azure
|
|
349
|
-
| [
|
|
350
|
-
| [
|
|
351
|
-
| [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `
|
|
352
|
-
| [
|
|
353
|
-
| [
|
|
354
|
-
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `
|
|
355
|
-
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `
|
|
356
|
-
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova
|
|
357
|
-
| [
|
|
358
|
-
| [
|
|
359
|
-
| [
|
|
360
|
-
| [
|
|
361
|
-
| [
|
|
362
|
-
| [
|
|
363
|
-
| [
|
|
364
|
-
| [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `
|
|
365
|
-
| [
|
|
366
|
-
| [
|
|
367
|
-
| [
|
|
368
|
-
| [
|
|
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,
|
|
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
|
|
9
|
-
|
|
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
|
|
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.
|
|
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
|
|
48
|
-
descriptions. They do not include schemas. No matches returns
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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<
|
|
53
|
-
|
|
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({
|