ai 7.0.91 → 7.0.93
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 +27 -0
- package/dist/index.d.ts +178 -159
- package/dist/index.js +143 -25
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal/index.js +2 -2
- package/dist/internal/index.js.map +1 -1
- package/docs/02-foundations/02-providers-and-models.mdx +1 -0
- package/docs/03-agents/04-loop-control.mdx +5 -3
- package/docs/03-agents/07-workflow-agent.mdx +27 -6
- package/docs/03-ai-sdk-core/10-generating-structured-data.mdx +15 -3
- package/docs/03-ai-sdk-core/16-mcp-tools.mdx +64 -1
- package/docs/03-ai-sdk-core/35-image-generation.mdx +7 -0
- package/docs/03-ai-sdk-core/36-transcription.mdx +36 -35
- package/docs/03-ai-sdk-harnesses/02-harness-agent.mdx +36 -0
- package/docs/04-ai-sdk-ui/20-streaming-data.mdx +11 -6
- package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +14 -0
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +30 -3
- package/docs/07-reference/01-ai-sdk-core/28-output.mdx +27 -1
- package/docs/07-reference/01-ai-sdk-core/80-smooth-stream.mdx +1 -1
- package/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx +1 -1
- package/docs/07-reference/02-ai-sdk-ui/40-create-ui-message-stream.mdx +4 -0
- package/docs/07-reference/02-ai-sdk-ui/41-create-ui-message-stream-response.mdx +6 -1
- package/docs/07-reference/04-ai-sdk-workflow/01-workflow-agent.mdx +42 -28
- package/docs/07-reference/05-ai-sdk-errors/ai-no-image-generated-error.mdx +7 -0
- package/package.json +6 -6
- package/src/agent/tool-loop-agent-settings.ts +15 -0
- package/src/embed/embed-many.ts +27 -2
- package/src/error/no-image-generated-error.ts +9 -0
- package/src/generate-image/generate-image.ts +1 -1
- package/src/generate-text/generate-text-events.ts +1 -1
- package/src/generate-text/output.ts +111 -1
- package/src/generate-text/smooth-stream.ts +19 -4
- package/src/generate-text/stream-text.ts +2 -6
- package/src/ui/call-completion-api.ts +1 -1
- package/src/ui/chat.ts +1 -1
- package/src/ui/convert-to-model-messages.ts +8 -2
- package/src/ui/http-chat-transport.ts +2 -2
- package/src/ui/validate-ui-messages.ts +14 -0
- package/src/util/async-iterable-stream.ts +1 -1
- package/src/util/data-url.ts +1 -1
- package/src/util/merge-abort-signals.ts +1 -1
|
@@ -122,6 +122,7 @@ Here are the capabilities of popular models:
|
|
|
122
122
|
| [xAI Grok](/providers/ai-sdk-providers/xai) | `grok-4` | <Cross /> | <Check /> | <Check /> | <Check /> |
|
|
123
123
|
| [xAI Grok](/providers/ai-sdk-providers/xai) | `grok-3` | <Cross /> | <Check /> | <Check /> | <Check /> |
|
|
124
124
|
| [xAI Grok](/providers/ai-sdk-providers/xai) | `grok-3-mini` | <Cross /> | <Check /> | <Check /> | <Check /> |
|
|
125
|
+
| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-6-astra` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
125
126
|
| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.6` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
126
127
|
| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.6-luna` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
127
128
|
| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.6-sol` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
@@ -16,7 +16,9 @@ The AI SDK provides built-in loop control through two parameters: `stopWhen` for
|
|
|
16
16
|
|
|
17
17
|
## Stop Conditions
|
|
18
18
|
|
|
19
|
-
The `stopWhen` parameter controls when to stop execution when there are tool results in the last step. By default,
|
|
19
|
+
The `stopWhen` parameter controls when to stop execution when there are tool results in the last step. By default, `ToolLoopAgent` stops after 20 steps using `isStepCount(20)`. This default is a safety measure to prevent runaway loops that could result in excessive API calls and costs.
|
|
20
|
+
|
|
21
|
+
`WorkflowAgent` does not apply a default step limit. It continues until the model stops calling tools or another natural termination condition is met. Configure an explicit condition such as `isStepCount(20)` when you need to bound its model calls. See [WorkflowAgent Loop Control](/docs/agents/workflow-agent#loop-control) for details.
|
|
20
22
|
|
|
21
23
|
When you provide `stopWhen`, the agent continues executing after tool calls until a stopping condition is met. When the condition is an array, execution stops when any of the conditions are met.
|
|
22
24
|
|
|
@@ -39,7 +41,7 @@ const agent = new ToolLoopAgent({
|
|
|
39
41
|
tools: {
|
|
40
42
|
// your tools
|
|
41
43
|
},
|
|
42
|
-
stopWhen: isStepCount(50), //
|
|
44
|
+
stopWhen: isStepCount(50), // Increase ToolLoopAgent's default from 20 to 50.
|
|
43
45
|
});
|
|
44
46
|
|
|
45
47
|
const result = await agent.generate({
|
|
@@ -49,7 +51,7 @@ const result = await agent.generate({
|
|
|
49
51
|
|
|
50
52
|
### Run Until Finished
|
|
51
53
|
|
|
52
|
-
If you want
|
|
54
|
+
If you want a `ToolLoopAgent` to run until the model naturally stops making tool calls, use `isLoopFinished()`. This removes its default step limit:
|
|
53
55
|
|
|
54
56
|
```ts
|
|
55
57
|
import { ToolLoopAgent, isLoopFinished } from 'ai';
|
|
@@ -399,6 +399,16 @@ The stream-level value overrides the constructor default.
|
|
|
399
399
|
|
|
400
400
|
## Loop Control
|
|
401
401
|
|
|
402
|
+
Unlike `ToolLoopAgent`, `WorkflowAgent` does not apply a default step limit.
|
|
403
|
+
When `stopWhen` is omitted, it continues until the model stops calling tools or
|
|
404
|
+
another natural termination condition is met.
|
|
405
|
+
|
|
406
|
+
<Note>
|
|
407
|
+
A model that repeatedly calls tools can make an unlimited number of model
|
|
408
|
+
calls. Configure an explicit stop condition when you need to bound execution
|
|
409
|
+
time and cost.
|
|
410
|
+
</Note>
|
|
411
|
+
|
|
402
412
|
Control how many steps the agent can take:
|
|
403
413
|
|
|
404
414
|
```ts
|
|
@@ -410,7 +420,8 @@ const result = await agent.stream({
|
|
|
410
420
|
});
|
|
411
421
|
```
|
|
412
422
|
|
|
413
|
-
|
|
423
|
+
Omitting `stopWhen` already lets `WorkflowAgent` continue until it has finished
|
|
424
|
+
calling tools. You can make that intent explicit with `isLoopFinished()`:
|
|
414
425
|
|
|
415
426
|
```ts
|
|
416
427
|
import { isLoopFinished } from 'ai';
|
|
@@ -421,9 +432,10 @@ const result = await agent.stream({
|
|
|
421
432
|
});
|
|
422
433
|
```
|
|
423
434
|
|
|
424
|
-
`isLoopFinished()`
|
|
425
|
-
|
|
426
|
-
|
|
435
|
+
`isLoopFinished()` is equivalent to omitting `stopWhen` for `WorkflowAgent`.
|
|
436
|
+
Use it with caution because a model that keeps calling tools can run
|
|
437
|
+
indefinitely and incur significant costs. See
|
|
438
|
+
[`isLoopFinished()`](/docs/reference/ai-sdk-core/loop-finished).
|
|
427
439
|
|
|
428
440
|
## Structured Output
|
|
429
441
|
|
|
@@ -599,8 +611,11 @@ const agent = new WorkflowAgent({
|
|
|
599
611
|
console.log(`Calling tool: ${toolCall.toolName}`);
|
|
600
612
|
},
|
|
601
613
|
|
|
602
|
-
onToolExecutionEnd({ toolCall,
|
|
603
|
-
console.log(`Tool finished: ${toolCall.toolName}
|
|
614
|
+
onToolExecutionEnd({ toolCall, success, durationMs }) {
|
|
615
|
+
console.log(`Tool finished: ${toolCall.toolName}`, {
|
|
616
|
+
success,
|
|
617
|
+
durationMs,
|
|
618
|
+
});
|
|
604
619
|
},
|
|
605
620
|
|
|
606
621
|
onStepEnd({ usage, finishReason }) {
|
|
@@ -613,6 +628,12 @@ const agent = new WorkflowAgent({
|
|
|
613
628
|
});
|
|
614
629
|
```
|
|
615
630
|
|
|
631
|
+
For concrete tool sets, `WorkflowAgentToolExecutionStartEvent` and
|
|
632
|
+
`WorkflowAgentToolExecutionEndEvent` preserve the relationship between each
|
|
633
|
+
tool name and its input, context, and output types. TypeScript narrows the
|
|
634
|
+
nested `toolCall` directly, but use `Extract` or a user-defined type guard when
|
|
635
|
+
you need to narrow the correlated `toolContext` or `output` fields by tool name.
|
|
636
|
+
|
|
616
637
|
Tool input callbacks (`onInputStart`, `onInputDelta`, and
|
|
617
638
|
`onInputAvailable`) are also preserved by `WorkflowAgent`. The model call runs
|
|
618
639
|
inside a durable step, while callback functions remain in the workflow
|
|
@@ -177,7 +177,9 @@ const { output } = await generateText({
|
|
|
177
177
|
|
|
178
178
|
### `Output.array()`
|
|
179
179
|
|
|
180
|
-
Use `Output.array({ element })` to specify that you expect
|
|
180
|
+
Use `Output.array({ element, minItems, maxItems })` to specify that you expect
|
|
181
|
+
an array of typed objects from the model. Each element must conform to the
|
|
182
|
+
`element` schema, and the optional bounds constrain the number of elements.
|
|
181
183
|
|
|
182
184
|
```ts
|
|
183
185
|
import { generateText, Output } from 'ai';
|
|
@@ -191,6 +193,8 @@ const { output } = await generateText({
|
|
|
191
193
|
temperature: z.number(),
|
|
192
194
|
condition: z.string(),
|
|
193
195
|
}),
|
|
196
|
+
minItems: 2,
|
|
197
|
+
maxItems: 2,
|
|
194
198
|
}),
|
|
195
199
|
prompt: 'List the weather for San Francisco and Paris.',
|
|
196
200
|
});
|
|
@@ -201,6 +205,11 @@ const { output } = await generateText({
|
|
|
201
205
|
// ]
|
|
202
206
|
```
|
|
203
207
|
|
|
208
|
+
`minItems` and `maxItems` must be non-negative integers, and `minItems` cannot
|
|
209
|
+
be greater than `maxItems`. Use the same value for both options to require an
|
|
210
|
+
exact length. The bounds are sent to providers as part of the structured output
|
|
211
|
+
schema when supported, and the AI SDK independently validates the final output.
|
|
212
|
+
|
|
204
213
|
When streaming arrays with `streamText`, you can use `elementStream` to receive each completed element as it is generated:
|
|
205
214
|
|
|
206
215
|
```ts
|
|
@@ -227,7 +236,10 @@ for await (const hero of elementStream) {
|
|
|
227
236
|
<Note>
|
|
228
237
|
Each element emitted by `elementStream` is complete and validated against your
|
|
229
238
|
element schema. This differs from `partialOutputStream`, which streams the
|
|
230
|
-
entire partial array including incomplete elements.
|
|
239
|
+
entire partial array including incomplete elements. If the model generates
|
|
240
|
+
more than `maxItems`, `elementStream` errors before emitting the first excess
|
|
241
|
+
element. This does not automatically abort provider generation, and the final
|
|
242
|
+
`output` promise rejects.
|
|
231
243
|
</Note>
|
|
232
244
|
|
|
233
245
|
### `Output.choice()`
|
|
@@ -378,7 +390,7 @@ const { output } = await generateText({
|
|
|
378
390
|
This works with all output types that support structured generation:
|
|
379
391
|
|
|
380
392
|
- `Output.object({ name, description, schema })`
|
|
381
|
-
- `Output.array({ name, description, element })`
|
|
393
|
+
- `Output.array({ name, description, element, minItems, maxItems })`
|
|
382
394
|
- `Output.choice({ name, description, options })`
|
|
383
395
|
- `Output.json({ name, description })`
|
|
384
396
|
|
|
@@ -320,6 +320,67 @@ const tools = await mcpClient.tools();
|
|
|
320
320
|
|
|
321
321
|
This approach is simpler to implement and automatically stays in sync with server changes. However, you won't have TypeScript type safety during development, and all tools from the server will be loaded
|
|
322
322
|
|
|
323
|
+
### Tool Annotations and Approval
|
|
324
|
+
|
|
325
|
+
MCP servers can describe tool behavior with annotations such as
|
|
326
|
+
`readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint`. The
|
|
327
|
+
MCP client exposes these annotations on each tool's `metadata.annotations` and
|
|
328
|
+
on the resulting tool call's `toolMetadata.annotations`.
|
|
329
|
+
|
|
330
|
+
Annotations are untrusted, server-provided hints. The MCP client does not turn
|
|
331
|
+
them into an approval policy automatically. Applications should combine them
|
|
332
|
+
with deterministic controls such as tool allowlists, scoped credentials, and
|
|
333
|
+
their own [`toolApproval`](/docs/agents/tool-approvals) policy.
|
|
334
|
+
|
|
335
|
+
The following conservative policy allows tools to run automatically only when
|
|
336
|
+
the server explicitly marks them as read-only. Tools with `readOnlyHint: false`
|
|
337
|
+
or no `readOnlyHint` require user approval:
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { type McpProviderMetadata } from '@ai-sdk/mcp';
|
|
341
|
+
|
|
342
|
+
const result = streamText({
|
|
343
|
+
model: __MODEL__,
|
|
344
|
+
tools,
|
|
345
|
+
toolApproval: ({ toolCall }) => {
|
|
346
|
+
const annotations = (
|
|
347
|
+
toolCall.toolMetadata as McpProviderMetadata | undefined
|
|
348
|
+
)?.annotations;
|
|
349
|
+
|
|
350
|
+
return annotations?.readOnlyHint === true
|
|
351
|
+
? 'not-applicable'
|
|
352
|
+
: {
|
|
353
|
+
type: 'user-approval',
|
|
354
|
+
reason:
|
|
355
|
+
annotations?.destructiveHint === true
|
|
356
|
+
? 'The MCP server marks this tool as destructive.'
|
|
357
|
+
: 'The MCP server does not mark this tool as read-only.',
|
|
358
|
+
};
|
|
359
|
+
},
|
|
360
|
+
prompt,
|
|
361
|
+
});
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
See the
|
|
365
|
+
[local tool annotations example](https://github.com/vercel/ai/tree/main/examples/mcp/src/tool-annotations)
|
|
366
|
+
for a complete annotated MCP server and application-layer approval
|
|
367
|
+
configuration. Start the server and client in separate terminals:
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
cd examples/mcp
|
|
371
|
+
pnpm server:tool-annotations
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
cd examples/mcp
|
|
376
|
+
pnpm client:tool-annotations
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Ask the client to read, delete, or create a note. The read-only tool executes
|
|
380
|
+
immediately. The destructive and unannotated tools prompt for approval; after
|
|
381
|
+
you enter `y` or `n`, the client sends the decision back and prints the model's
|
|
382
|
+
response.
|
|
383
|
+
|
|
323
384
|
### Schema Definition
|
|
324
385
|
|
|
325
386
|
For better type safety and control, you can define the tools and their input schemas explicitly in your client code:
|
|
@@ -347,7 +408,7 @@ This approach provides full TypeScript type safety and IDE autocompletion, letti
|
|
|
347
408
|
|
|
348
409
|
### Typed Tool Outputs
|
|
349
410
|
|
|
350
|
-
When MCP servers return `structuredContent` (per the [MCP specification](https://modelcontextprotocol.io/specification/
|
|
411
|
+
When MCP servers return `structuredContent` (per the [MCP specification](https://modelcontextprotocol.io/specification/2026-07-28/server/tools#structured-content)), you can define an `outputSchema` to get typed tool results:
|
|
351
412
|
|
|
352
413
|
```typescript
|
|
353
414
|
import { z } from 'zod';
|
|
@@ -384,6 +445,8 @@ When `outputSchema` is provided:
|
|
|
384
445
|
|
|
385
446
|
If the server doesn't return `structuredContent`, the client falls back to parsing JSON from the text content. If neither is available or validation fails, an error is thrown.
|
|
386
447
|
|
|
448
|
+
If a server returns `structuredContent` without the backwards-compatible `content` field, the client adds a text content block containing the serialized JSON before returning the result. This compatibility behavior handles servers that omit the text mirror recommended by the MCP specification.
|
|
449
|
+
|
|
387
450
|
<Note>
|
|
388
451
|
Without `outputSchema`, the tool returns the raw `CallToolResult` object
|
|
389
452
|
containing `content` and optional `isError` fields.
|
|
@@ -230,6 +230,7 @@ This error occurs when the AI provider fails to generate an image. It can arise
|
|
|
230
230
|
|
|
231
231
|
The error preserves the following information to help you log the issue:
|
|
232
232
|
|
|
233
|
+
- `calls`: Results from the underlying image model calls, including generated images, provider metadata, response metadata, warnings, and usage.
|
|
233
234
|
- `responses`: Metadata about the image model responses, including timestamp, model, and headers.
|
|
234
235
|
- `cause`: The cause of the error. You can use this for more detailed error handling
|
|
235
236
|
|
|
@@ -243,6 +244,12 @@ try {
|
|
|
243
244
|
console.log('NoImageGeneratedError');
|
|
244
245
|
console.log('Cause:', error.cause);
|
|
245
246
|
console.log('Responses:', error.responses);
|
|
247
|
+
|
|
248
|
+
for (const call of error.calls ?? []) {
|
|
249
|
+
console.log('Provider metadata:', call.providerMetadata);
|
|
250
|
+
console.log('Warnings:', call.warnings);
|
|
251
|
+
console.log('Usage:', call.usage);
|
|
252
|
+
}
|
|
246
253
|
}
|
|
247
254
|
}
|
|
248
255
|
```
|
|
@@ -293,40 +293,41 @@ try {
|
|
|
293
293
|
|
|
294
294
|
## Transcription Models
|
|
295
295
|
|
|
296
|
-
| Provider | Model
|
|
297
|
-
| ----------------------------------------------------------------------------------- |
|
|
298
|
-
| [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `whisper-1`
|
|
299
|
-
| [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-transcribe`
|
|
300
|
-
| [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-mini-transcribe`
|
|
301
|
-
| [
|
|
302
|
-
| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `
|
|
303
|
-
| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `
|
|
304
|
-
| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#
|
|
305
|
-
| [
|
|
306
|
-
| [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3`
|
|
307
|
-
| [
|
|
308
|
-
| [
|
|
309
|
-
| [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `
|
|
310
|
-
| [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-
|
|
311
|
-
| [
|
|
312
|
-
| [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `
|
|
313
|
-
| [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `
|
|
314
|
-
| [
|
|
315
|
-
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `
|
|
316
|
-
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `
|
|
317
|
-
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova
|
|
318
|
-
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova-
|
|
319
|
-
| [
|
|
320
|
-
| [
|
|
321
|
-
| [AssemblyAI](/providers/ai-sdk-providers/assemblyai#transcription-models) | `universal-3-pro`
|
|
322
|
-
| [
|
|
323
|
-
| [Fal](/providers/ai-sdk-providers/fal#transcription-models) | `
|
|
324
|
-
| [
|
|
325
|
-
| [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `
|
|
326
|
-
| [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `
|
|
327
|
-
| [
|
|
328
|
-
| [
|
|
329
|
-
| [Cartesia](/providers/ai-sdk-providers/cartesia#
|
|
330
|
-
| [
|
|
296
|
+
| Provider | Model |
|
|
297
|
+
| ----------------------------------------------------------------------------------- | --------------------------- |
|
|
298
|
+
| [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `whisper-1` |
|
|
299
|
+
| [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-transcribe` |
|
|
300
|
+
| [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-mini-transcribe` |
|
|
301
|
+
| [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-transcribe-diarize` |
|
|
302
|
+
| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v1` |
|
|
303
|
+
| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v1_experimental` |
|
|
304
|
+
| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v2` |
|
|
305
|
+
| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#streaming-transcription-models) | `scribe_v2_realtime` |
|
|
306
|
+
| [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3-turbo` |
|
|
307
|
+
| [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3` |
|
|
308
|
+
| [Mistral](/providers/ai-sdk-providers/mistral#transcription-models) | `voxtral-mini-latest` |
|
|
309
|
+
| [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `whisper-1` |
|
|
310
|
+
| [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-transcribe` |
|
|
311
|
+
| [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-mini-transcribe` |
|
|
312
|
+
| [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `machine` |
|
|
313
|
+
| [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `low_cost` |
|
|
314
|
+
| [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `fusion` |
|
|
315
|
+
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `base` (+ variants) |
|
|
316
|
+
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `enhanced` (+ variants) |
|
|
317
|
+
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova` (+ variants) |
|
|
318
|
+
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova-2` (+ variants) |
|
|
319
|
+
| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova-3` (+ variants) |
|
|
320
|
+
| [Gladia](/providers/ai-sdk-providers/gladia#transcription-models) | `default` |
|
|
321
|
+
| [AssemblyAI](/providers/ai-sdk-providers/assemblyai#transcription-models) | `universal-3-5-pro` |
|
|
322
|
+
| [AssemblyAI](/providers/ai-sdk-providers/assemblyai#transcription-models) | `universal-3-pro` |
|
|
323
|
+
| [Fal](/providers/ai-sdk-providers/fal#transcription-models) | `whisper` |
|
|
324
|
+
| [Fal](/providers/ai-sdk-providers/fal#transcription-models) | `wizper` |
|
|
325
|
+
| [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `chirp_2` |
|
|
326
|
+
| [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `chirp_3` |
|
|
327
|
+
| [Google Vertex](/providers/ai-sdk-providers/google-vertex#transcription-models) | `telephony` |
|
|
328
|
+
| [xAI](/providers/ai-sdk-providers/xai#transcription-models) | `default` |
|
|
329
|
+
| [Cartesia](/providers/ai-sdk-providers/cartesia#transcription-models) | `ink-whisper` |
|
|
330
|
+
| [Cartesia](/providers/ai-sdk-providers/cartesia#streaming-transcription-models) | `ink-2` |
|
|
331
|
+
| [Fish Audio](/providers/ai-sdk-providers/fish-audio#transcription-models) | `transcribe-1` |
|
|
331
332
|
|
|
332
333
|
Above are a small subset of the transcription models supported by the AI SDK providers. For more, see the respective provider documentation.
|
|
@@ -98,6 +98,39 @@ try {
|
|
|
98
98
|
}
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
+
## Lifecycle Callbacks
|
|
102
|
+
|
|
103
|
+
Configure lifecycle callbacks on `HarnessAgent` to observe agent calls, model
|
|
104
|
+
steps, and tool executions:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
const agent = new HarnessAgent({
|
|
108
|
+
harness: claudeCode,
|
|
109
|
+
sandbox,
|
|
110
|
+
tools: { weather },
|
|
111
|
+
onStart: event => console.log('call started', event.callId),
|
|
112
|
+
onStepStart: event => console.log('step started', event.stepNumber),
|
|
113
|
+
onLanguageModelCallStart: event =>
|
|
114
|
+
console.log('model call started', event.modelId),
|
|
115
|
+
onLanguageModelCallEnd: event =>
|
|
116
|
+
console.log('model call ended', event.finishReason),
|
|
117
|
+
onToolExecutionStart: event =>
|
|
118
|
+
console.log('tool started', event.toolCall.toolName),
|
|
119
|
+
onToolExecutionEnd: event => console.log('tool ended', event.toolOutput.type),
|
|
120
|
+
onStepEnd: step => console.log('step ended', step.stepNumber),
|
|
121
|
+
onEnd: event => console.log('call ended', event.finishReason),
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Callbacks configured on individual `generate()` and `stream()` calls are
|
|
126
|
+
invoked in addition to settings callbacks, with settings callbacks invoked
|
|
127
|
+
first. Callback errors are ignored and do not change agent execution.
|
|
128
|
+
|
|
129
|
+
Harness runtimes execute their built-in tools internally. For those tools,
|
|
130
|
+
`onToolExecutionStart` and `onToolExecutionEnd` describe the logical tool
|
|
131
|
+
lifecycle after the runtime reports the result. The callbacks are still
|
|
132
|
+
delivered before the tool result is published to the result stream.
|
|
133
|
+
|
|
101
134
|
## Generate Structured Output
|
|
102
135
|
|
|
103
136
|
Set `output` when constructing `HarnessAgent` to require the same typed output
|
|
@@ -510,6 +543,9 @@ console.log(preparation.identity);
|
|
|
510
543
|
- `id`: optional stable agent identifier.
|
|
511
544
|
- `instructions`: instructions appended to the runtime's system or developer
|
|
512
545
|
prompt when supported, or prepended to the user prompt otherwise.
|
|
546
|
+
- `headers`: additional headers sent with model requests. Headers are fixed at
|
|
547
|
+
construction time. `authorization`, `x-api-key`, `user-agent`, and
|
|
548
|
+
`x-client-app` are not allowed.
|
|
513
549
|
- `callOptionsSchema` and `prepareCall`: validate custom call options and derive
|
|
514
550
|
model, skills, instructions, and tools for each new turn.
|
|
515
551
|
- `output`: typed output specification applied to every turn.
|
|
@@ -63,14 +63,17 @@ export async function POST(req: Request) {
|
|
|
63
63
|
|
|
64
64
|
const stream = createUIMessageStream<MyUIMessage>({
|
|
65
65
|
execute: ({ writer }) => {
|
|
66
|
-
// 1.
|
|
66
|
+
// 1. Start the assistant message before writing any message parts.
|
|
67
|
+
writer.write({ type: 'start' });
|
|
68
|
+
|
|
69
|
+
// 2. Send initial status (transient - won't be added to message history)
|
|
67
70
|
writer.write({
|
|
68
71
|
type: 'data-notification',
|
|
69
72
|
data: { message: 'Processing your request...', level: 'info' },
|
|
70
73
|
transient: true, // This part won't be added to message history
|
|
71
74
|
});
|
|
72
75
|
|
|
73
|
-
//
|
|
76
|
+
// 3. Send sources (useful for RAG use cases)
|
|
74
77
|
writer.write({
|
|
75
78
|
type: 'source',
|
|
76
79
|
value: {
|
|
@@ -82,7 +85,7 @@ export async function POST(req: Request) {
|
|
|
82
85
|
},
|
|
83
86
|
});
|
|
84
87
|
|
|
85
|
-
//
|
|
88
|
+
// 4. Send data parts with loading state
|
|
86
89
|
writer.write({
|
|
87
90
|
type: 'data-weather',
|
|
88
91
|
id: 'weather-1',
|
|
@@ -93,7 +96,7 @@ export async function POST(req: Request) {
|
|
|
93
96
|
model: __MODEL__,
|
|
94
97
|
messages: await convertToModelMessages(messages),
|
|
95
98
|
onEnd() {
|
|
96
|
-
//
|
|
99
|
+
// 5. Update the same data part (reconciliation)
|
|
97
100
|
writer.write({
|
|
98
101
|
type: 'data-weather',
|
|
99
102
|
id: 'weather-1', // Same ID = update existing part
|
|
@@ -104,7 +107,7 @@ export async function POST(req: Request) {
|
|
|
104
107
|
},
|
|
105
108
|
});
|
|
106
109
|
|
|
107
|
-
//
|
|
110
|
+
// 6. Send completion notification (transient)
|
|
108
111
|
writer.write({
|
|
109
112
|
type: 'data-notification',
|
|
110
113
|
data: { message: 'Request completed', level: 'info' },
|
|
@@ -113,7 +116,9 @@ export async function POST(req: Request) {
|
|
|
113
116
|
},
|
|
114
117
|
});
|
|
115
118
|
|
|
116
|
-
writer.merge(
|
|
119
|
+
writer.merge(
|
|
120
|
+
toUIMessageStream({ stream: result.stream, sendStart: false }),
|
|
121
|
+
);
|
|
117
122
|
},
|
|
118
123
|
});
|
|
119
124
|
|
|
@@ -996,6 +996,20 @@ To see `generateText` in action, check out [these examples](#examples).
|
|
|
996
996
|
description:
|
|
997
997
|
'The schema of the array elements to generate.',
|
|
998
998
|
},
|
|
999
|
+
{
|
|
1000
|
+
name: 'minItems',
|
|
1001
|
+
type: 'number',
|
|
1002
|
+
isOptional: true,
|
|
1003
|
+
description:
|
|
1004
|
+
'Optional minimum number of array elements. Must be a non-negative integer.',
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
name: 'maxItems',
|
|
1008
|
+
type: 'number',
|
|
1009
|
+
isOptional: true,
|
|
1010
|
+
description:
|
|
1011
|
+
'Optional maximum number of array elements. Must be a non-negative integer and greater than or equal to minItems.',
|
|
1012
|
+
},
|
|
999
1013
|
{
|
|
1000
1014
|
name: 'name',
|
|
1001
1015
|
type: 'string',
|
|
@@ -1272,6 +1272,20 @@ To see `streamText` in action, check out [these examples](#examples).
|
|
|
1272
1272
|
description:
|
|
1273
1273
|
'The schema of the array elements to generate.',
|
|
1274
1274
|
},
|
|
1275
|
+
{
|
|
1276
|
+
name: 'minItems',
|
|
1277
|
+
type: 'number',
|
|
1278
|
+
isOptional: true,
|
|
1279
|
+
description:
|
|
1280
|
+
'Optional minimum number of array elements. Must be a non-negative integer.',
|
|
1281
|
+
},
|
|
1282
|
+
{
|
|
1283
|
+
name: 'maxItems',
|
|
1284
|
+
type: 'number',
|
|
1285
|
+
isOptional: true,
|
|
1286
|
+
description:
|
|
1287
|
+
'Optional maximum number of array elements. Must be a non-negative integer and greater than or equal to minItems.',
|
|
1288
|
+
},
|
|
1275
1289
|
{
|
|
1276
1290
|
name: 'name',
|
|
1277
1291
|
type: 'string',
|
|
@@ -2069,11 +2083,24 @@ To see `streamText` in action, check out [these examples](#examples).
|
|
|
2069
2083
|
{
|
|
2070
2084
|
type: 'OnAbortResult',
|
|
2071
2085
|
parameters: [
|
|
2086
|
+
{
|
|
2087
|
+
name: 'callId',
|
|
2088
|
+
type: 'string',
|
|
2089
|
+
description:
|
|
2090
|
+
'Unique identifier for this generation call, used to correlate events.',
|
|
2091
|
+
},
|
|
2072
2092
|
{
|
|
2073
2093
|
name: 'steps',
|
|
2074
2094
|
type: 'Array<StepResult>',
|
|
2075
2095
|
description: 'Details for all previously finished steps.',
|
|
2076
2096
|
},
|
|
2097
|
+
{
|
|
2098
|
+
name: 'reason',
|
|
2099
|
+
type: 'unknown',
|
|
2100
|
+
isOptional: true,
|
|
2101
|
+
description:
|
|
2102
|
+
'The raw abort reason from the AbortSignal, when one is available.',
|
|
2103
|
+
},
|
|
2077
2104
|
],
|
|
2078
2105
|
},
|
|
2079
2106
|
],
|
|
@@ -3979,10 +4006,10 @@ To see `streamText` in action, check out [these examples](#examples).
|
|
|
3979
4006
|
},
|
|
3980
4007
|
{
|
|
3981
4008
|
name: 'reason',
|
|
3982
|
-
type: '
|
|
4009
|
+
type: 'string',
|
|
3983
4010
|
isOptional: true,
|
|
3984
4011
|
description:
|
|
3985
|
-
'Optional abort reason
|
|
4012
|
+
'Optional serialized abort reason when the stream is aborted.',
|
|
3986
4013
|
},
|
|
3987
4014
|
],
|
|
3988
4015
|
},
|
|
@@ -4004,7 +4031,7 @@ To see `streamText` in action, check out [these examples](#examples).
|
|
|
4004
4031
|
name: 'elementStream',
|
|
4005
4032
|
type: 'AsyncIterableStream<ELEMENT_OUTPUT>',
|
|
4006
4033
|
description:
|
|
4007
|
-
'A stream of individual array elements as they complete. Only available when using `output: Output.array()`. Each element is complete and validated against the element schema. AsyncIterableStream is defined as AsyncIterable<T> & ReadableStream<T>.',
|
|
4034
|
+
'A stream of individual array elements as they complete. Only available when using `output: Output.array()`. Each element is complete and validated against the element schema. When `maxItems` is set, the stream errors before emitting the first excess element. AsyncIterableStream is defined as AsyncIterable<T> & ReadableStream<T>.',
|
|
4008
4035
|
},
|
|
4009
4036
|
{
|
|
4010
4037
|
name: 'output',
|
|
@@ -135,6 +135,8 @@ const { output } = await generateText({
|
|
|
135
135
|
temperature: z.number(),
|
|
136
136
|
condition: z.string(),
|
|
137
137
|
}),
|
|
138
|
+
minItems: 2,
|
|
139
|
+
maxItems: 2,
|
|
138
140
|
}),
|
|
139
141
|
prompt: 'List the weather for San Francisco and Paris.',
|
|
140
142
|
});
|
|
@@ -151,6 +153,20 @@ const { output } = await generateText({
|
|
|
151
153
|
description:
|
|
152
154
|
'The schema that defines the structure of each array element. Supports Zod schemas, Valibot schemas, or JSON schemas.',
|
|
153
155
|
},
|
|
156
|
+
{
|
|
157
|
+
name: 'minItems',
|
|
158
|
+
type: 'number',
|
|
159
|
+
isOptional: true,
|
|
160
|
+
description:
|
|
161
|
+
'The minimum number of elements to generate. Must be a non-negative integer.',
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: 'maxItems',
|
|
165
|
+
type: 'number',
|
|
166
|
+
isOptional: true,
|
|
167
|
+
description:
|
|
168
|
+
'The maximum number of elements to generate. Must be a non-negative integer and greater than or equal to minItems.',
|
|
169
|
+
},
|
|
154
170
|
{
|
|
155
171
|
name: 'name',
|
|
156
172
|
type: 'string',
|
|
@@ -173,8 +189,15 @@ const { output } = await generateText({
|
|
|
173
189
|
An `Output<Array<ELEMENT>, Array<ELEMENT>>` specification where:
|
|
174
190
|
|
|
175
191
|
- Complete output is an array with all elements validated
|
|
192
|
+
- Complete output is validated against `minItems` and `maxItems`
|
|
176
193
|
- Partial output contains only fully validated elements (incomplete elements are excluded)
|
|
177
194
|
|
|
195
|
+
Set `minItems` and `maxItems` to the same value to require an exact number of
|
|
196
|
+
elements. The bounds are included in the provider-facing schema when the
|
|
197
|
+
provider supports them. The AI SDK also validates the completed output, so
|
|
198
|
+
providers that ignore these schema keywords cannot return an out-of-bounds
|
|
199
|
+
result.
|
|
200
|
+
|
|
178
201
|
#### Streaming with `elementStream`
|
|
179
202
|
|
|
180
203
|
When using `streamText` with `Output.array()`, you can iterate over elements as they are generated using `elementStream`:
|
|
@@ -202,7 +225,10 @@ for await (const hero of elementStream) {
|
|
|
202
225
|
|
|
203
226
|
<Note>
|
|
204
227
|
Each element emitted by `elementStream` is complete and validated against your
|
|
205
|
-
element schema, ensuring type safety for each item as it is generated.
|
|
228
|
+
element schema, ensuring type safety for each item as it is generated. If the
|
|
229
|
+
model generates more than `maxItems`, `elementStream` errors before emitting
|
|
230
|
+
the first excess element. Provider generation is not aborted automatically,
|
|
231
|
+
and the final `output` promise also rejects.
|
|
206
232
|
</Note>
|
|
207
233
|
|
|
208
234
|
---
|
|
@@ -38,7 +38,7 @@ const result = streamText({
|
|
|
38
38
|
type: 'number | null',
|
|
39
39
|
isOptional: true,
|
|
40
40
|
description:
|
|
41
|
-
'The delay in milliseconds between outputting each chunk. Defaults to 10ms. Set to `null` to disable delays.',
|
|
41
|
+
'The delay in milliseconds between outputting each chunk. Defaults to 10ms. Set to `null` to disable delays. The delay is skipped while the document is hidden (e.g. browser background tabs), where timer throttling would otherwise stall the stream.',
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
name: 'chunking',
|
|
@@ -408,7 +408,7 @@ Allows you to easily create a conversational user interface for your chatbot app
|
|
|
408
408
|
name: 'sendMessage',
|
|
409
409
|
type: '(message?: { text: string; files?: FileList | FileUIPart[]; metadata?; messageId?: string } | CreateUIMessage, options?: ChatRequestOptions) => Promise<void>',
|
|
410
410
|
description:
|
|
411
|
-
'Function to send a new message to the chat. This will trigger an API call to generate the assistant response. If a messageId is provided, the message will be replaced (useful for editing). If no message is provided, resubmits the current messages (useful after adding tool outputs).',
|
|
411
|
+
'Function to send a new message to the chat. This will trigger an API call to generate the assistant response. If a messageId is provided, the message will be replaced (useful for editing). When replacing with a CreateUIMessage, provide its id to assign a new ID to the replacement. If no message is provided, resubmits the current messages (useful after adding tool outputs).',
|
|
412
412
|
properties: [
|
|
413
413
|
{
|
|
414
414
|
type: 'ChatRequestOptions',
|
|
@@ -20,6 +20,9 @@ const existingMessages: UIMessage[] = [
|
|
|
20
20
|
|
|
21
21
|
const stream = createUIMessageStream({
|
|
22
22
|
async execute({ writer }) {
|
|
23
|
+
// The outer stream owns the assistant message lifecycle.
|
|
24
|
+
writer.write({ type: 'start' });
|
|
25
|
+
|
|
23
26
|
// Start a text message
|
|
24
27
|
// Note: The id must be consistent across text-start, text-delta, and text-end steps
|
|
25
28
|
// This allows the system to correctly identify they belong to the same text block
|
|
@@ -50,6 +53,7 @@ const stream = createUIMessageStream({
|
|
|
50
53
|
writer.merge(
|
|
51
54
|
toUIMessageStream({
|
|
52
55
|
stream: result.stream,
|
|
56
|
+
sendStart: false,
|
|
53
57
|
onEnd: ({ outcome }) => {
|
|
54
58
|
// The composer decides that the model stream outcome is also the
|
|
55
59
|
// aggregate stream outcome.
|