ai 7.0.92 → 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 +16 -0
- package/dist/index.d.ts +176 -152
- package/dist/index.js +132 -16
- package/dist/index.js.map +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 +15 -1
- package/docs/07-reference/01-ai-sdk-core/28-output.mdx +27 -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/output.ts +111 -1
- package/src/ui/chat.ts +1 -1
- package/src/ui/convert-to-model-messages.ts +8 -2
- package/src/ui/validate-ui-messages.ts +14 -0
- package/src/util/data-url.ts +1 -1
- package/src/util/merge-abort-signals.ts +1 -1
|
@@ -99,7 +99,7 @@ To see `WorkflowAgent` in action, check out [these examples](#examples).
|
|
|
99
99
|
type: 'StopCondition | StopCondition[]',
|
|
100
100
|
isOptional: true,
|
|
101
101
|
description:
|
|
102
|
-
'Default stop condition for the agent loop.
|
|
102
|
+
'Default stop condition for the agent loop. When omitted, WorkflowAgent has no maximum step count and continues until natural completion. Use `isStepCount()` to bound execution. Per-stream values override this default.',
|
|
103
103
|
},
|
|
104
104
|
{
|
|
105
105
|
name: 'activeTools',
|
|
@@ -268,24 +268,24 @@ To see `WorkflowAgent` in action, check out [these examples](#examples).
|
|
|
268
268
|
},
|
|
269
269
|
{
|
|
270
270
|
name: 'onToolExecutionStart',
|
|
271
|
-
type: '
|
|
271
|
+
type: 'WorkflowAgentOnToolExecutionStartCallback',
|
|
272
272
|
isOptional: true,
|
|
273
273
|
description:
|
|
274
274
|
"Callback called right before a tool's execute function runs. If also specified in `stream()`, both callbacks fire (constructor first). Experimental (can break in patch releases).",
|
|
275
275
|
properties: [
|
|
276
276
|
{
|
|
277
|
-
type: '
|
|
277
|
+
type: 'WorkflowAgentToolExecutionStartEvent',
|
|
278
278
|
parameters: [
|
|
279
279
|
{
|
|
280
|
-
name: '
|
|
281
|
-
type: 'string',
|
|
280
|
+
name: 'toolCall',
|
|
281
|
+
type: '{ type: "tool-call"; toolCallId: string; toolName: string; input: unknown }',
|
|
282
282
|
description:
|
|
283
|
-
'
|
|
283
|
+
'The tool call being executed. For concrete tool sets, the tool name and input are correlated.',
|
|
284
284
|
},
|
|
285
285
|
{
|
|
286
|
-
name: '
|
|
287
|
-
type: '
|
|
288
|
-
description: 'The
|
|
286
|
+
name: 'stepNumber',
|
|
287
|
+
type: 'number',
|
|
288
|
+
description: 'The current step number, starting at zero.',
|
|
289
289
|
},
|
|
290
290
|
{
|
|
291
291
|
name: 'messages',
|
|
@@ -295,9 +295,9 @@ To see `WorkflowAgent` in action, check out [these examples](#examples).
|
|
|
295
295
|
},
|
|
296
296
|
{
|
|
297
297
|
name: 'toolContext',
|
|
298
|
-
type: 'InferToolContext<TOOLS[
|
|
298
|
+
type: 'InferToolContext<TOOLS[NAME]> | undefined',
|
|
299
299
|
description:
|
|
300
|
-
'
|
|
300
|
+
'The validated context for the tool call. For concrete tool sets, each event union member pairs it with the corresponding tool name.',
|
|
301
301
|
},
|
|
302
302
|
],
|
|
303
303
|
},
|
|
@@ -305,24 +305,24 @@ To see `WorkflowAgent` in action, check out [these examples](#examples).
|
|
|
305
305
|
},
|
|
306
306
|
{
|
|
307
307
|
name: 'onToolExecutionEnd',
|
|
308
|
-
type: '
|
|
308
|
+
type: 'WorkflowAgentOnToolExecutionEndCallback',
|
|
309
309
|
isOptional: true,
|
|
310
310
|
description:
|
|
311
|
-
"Callback called right after a tool's execute function completes or errors.
|
|
311
|
+
"Callback called right after a tool's execute function completes or errors. Check `success` to determine whether `output` or `error` is available. If also specified in `stream()`, both callbacks fire (constructor first). Experimental (can break in patch releases).",
|
|
312
312
|
properties: [
|
|
313
313
|
{
|
|
314
|
-
type: '
|
|
314
|
+
type: 'WorkflowAgentToolExecutionEndEvent',
|
|
315
315
|
parameters: [
|
|
316
316
|
{
|
|
317
|
-
name: '
|
|
318
|
-
type: 'string',
|
|
317
|
+
name: 'toolCall',
|
|
318
|
+
type: '{ type: "tool-call"; toolCallId: string; toolName: string; input: unknown }',
|
|
319
319
|
description:
|
|
320
|
-
'
|
|
320
|
+
'The tool call that was executed. For concrete tool sets, the tool name and input are correlated.',
|
|
321
321
|
},
|
|
322
322
|
{
|
|
323
|
-
name: '
|
|
324
|
-
type: '
|
|
325
|
-
description: 'The
|
|
323
|
+
name: 'stepNumber',
|
|
324
|
+
type: 'number',
|
|
325
|
+
description: 'The current step number, starting at zero.',
|
|
326
326
|
},
|
|
327
327
|
{
|
|
328
328
|
name: 'durationMs',
|
|
@@ -338,15 +338,29 @@ To see `WorkflowAgent` in action, check out [these examples](#examples).
|
|
|
338
338
|
},
|
|
339
339
|
{
|
|
340
340
|
name: 'toolContext',
|
|
341
|
-
type: 'InferToolContext<TOOLS[
|
|
341
|
+
type: 'InferToolContext<TOOLS[NAME]> | undefined',
|
|
342
|
+
description:
|
|
343
|
+
'The validated context for the tool call. For concrete tool sets, each event union member pairs it with the corresponding tool name.',
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
name: 'success',
|
|
347
|
+
type: 'boolean',
|
|
348
|
+
description:
|
|
349
|
+
'Whether the tool execution succeeded. Discriminates between the output and error event variants.',
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
name: 'output',
|
|
353
|
+
type: 'InferToolOutput<TOOLS[NAME]>',
|
|
354
|
+
isOptional: true,
|
|
342
355
|
description:
|
|
343
|
-
'
|
|
356
|
+
'The tool output. Available when `success` is `true` and correlated with the configured tool.',
|
|
344
357
|
},
|
|
345
358
|
{
|
|
346
|
-
name: '
|
|
347
|
-
type: '
|
|
359
|
+
name: 'error',
|
|
360
|
+
type: 'unknown',
|
|
361
|
+
isOptional: true,
|
|
348
362
|
description:
|
|
349
|
-
|
|
363
|
+
'The tool execution error. Available when `success` is `false`.',
|
|
350
364
|
},
|
|
351
365
|
],
|
|
352
366
|
},
|
|
@@ -509,7 +523,7 @@ const result = await agent.stream({
|
|
|
509
523
|
name: 'stopWhen',
|
|
510
524
|
type: 'StopCondition | StopCondition[]',
|
|
511
525
|
isOptional: true,
|
|
512
|
-
description: 'Condition(s) for ending the agent loop.
|
|
526
|
+
description: 'Condition(s) for ending the agent loop. When omitted and no constructor-level condition is configured, WorkflowAgent has no maximum step count and continues until natural completion. Use `isStepCount()` to bound execution.',
|
|
513
527
|
},
|
|
514
528
|
|
|
515
529
|
{
|
|
@@ -644,14 +658,14 @@ const result = await agent.stream({
|
|
|
644
658
|
},
|
|
645
659
|
{
|
|
646
660
|
name: 'onToolExecutionStart',
|
|
647
|
-
type: '
|
|
661
|
+
type: 'WorkflowAgentOnToolExecutionStartCallback',
|
|
648
662
|
isOptional: true,
|
|
649
663
|
description:
|
|
650
664
|
'Per-call onToolExecutionStart callback. If also specified in the constructor, both fire (constructor first).',
|
|
651
665
|
},
|
|
652
666
|
{
|
|
653
667
|
name: 'onToolExecutionEnd',
|
|
654
|
-
type: '
|
|
668
|
+
type: 'WorkflowAgentOnToolExecutionEndCallback',
|
|
655
669
|
isOptional: true,
|
|
656
670
|
description:
|
|
657
671
|
'Per-call onToolExecutionEnd callback. If also specified in the constructor, both fire (constructor first).',
|
|
@@ -14,6 +14,7 @@ It can arise due to the following reasons:
|
|
|
14
14
|
## Properties
|
|
15
15
|
|
|
16
16
|
- `message`: The error message (optional, defaults to `'No image generated.'`).
|
|
17
|
+
- `calls`: Results from the underlying image model calls, including generated images, provider metadata, response metadata, warnings, and usage (optional).
|
|
17
18
|
- `responses`: Metadata about the image model responses, including timestamp, model, and headers (optional).
|
|
18
19
|
- `cause`: The cause of the error. You can use this for more detailed error handling (optional).
|
|
19
20
|
|
|
@@ -31,6 +32,12 @@ try {
|
|
|
31
32
|
console.log('NoImageGeneratedError');
|
|
32
33
|
console.log('Cause:', error.cause);
|
|
33
34
|
console.log('Responses:', error.responses);
|
|
35
|
+
|
|
36
|
+
for (const call of error.calls ?? []) {
|
|
37
|
+
console.log('Provider metadata:', call.providerMetadata);
|
|
38
|
+
console.log('Warnings:', call.warnings);
|
|
39
|
+
console.log('Usage:', call.usage);
|
|
40
|
+
}
|
|
34
41
|
}
|
|
35
42
|
}
|
|
36
43
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.93",
|
|
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,18 +42,18 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@ai-sdk/gateway": "4.0.
|
|
45
|
+
"@ai-sdk/gateway": "4.0.75",
|
|
46
46
|
"@ai-sdk/provider": "4.0.10",
|
|
47
47
|
"@ai-sdk/provider-utils": "5.0.36"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@ai-sdk/amazon-bedrock": "5.0.
|
|
50
|
+
"@ai-sdk/amazon-bedrock": "5.0.75",
|
|
51
51
|
"@ai-sdk/deepseek": "3.0.39",
|
|
52
|
-
"@ai-sdk/google": "4.0.
|
|
52
|
+
"@ai-sdk/google": "4.0.64",
|
|
53
53
|
"@ai-sdk/groq": "4.0.37",
|
|
54
|
-
"@ai-sdk/huggingface": "2.0.
|
|
54
|
+
"@ai-sdk/huggingface": "2.0.44",
|
|
55
55
|
"@ai-sdk/moonshotai": "3.0.45",
|
|
56
|
-
"@ai-sdk/openai": "4.0.
|
|
56
|
+
"@ai-sdk/openai": "4.0.59",
|
|
57
57
|
"@ai-sdk/test-server": "2.0.1",
|
|
58
58
|
"@ai-sdk/xai": "4.0.54",
|
|
59
59
|
"@edge-runtime/vm": "^5.0.0",
|
|
@@ -17,6 +17,10 @@ import type {
|
|
|
17
17
|
GenerateTextOnStepStartCallback,
|
|
18
18
|
} from '../generate-text/generate-text-events';
|
|
19
19
|
import type { GenerateTextInclude } from '../generate-text/generate-text';
|
|
20
|
+
import type {
|
|
21
|
+
OnLanguageModelCallEndCallback,
|
|
22
|
+
OnLanguageModelCallStartCallback,
|
|
23
|
+
} from '../generate-text/language-model-events';
|
|
20
24
|
import type { Output } from '../generate-text/output';
|
|
21
25
|
import type { PrepareStepFunction } from '../generate-text/prepare-step';
|
|
22
26
|
import type { StopCondition } from '../generate-text/stop-condition';
|
|
@@ -212,6 +216,17 @@ export type ToolLoopAgentSettings<
|
|
|
212
216
|
NoInfer<OUTPUT>
|
|
213
217
|
>;
|
|
214
218
|
|
|
219
|
+
/**
|
|
220
|
+
* Callback that is called immediately before the provider model call begins.
|
|
221
|
+
*/
|
|
222
|
+
onLanguageModelCallStart?: OnLanguageModelCallStartCallback;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Callback that is called after the model response has been normalized and parsed,
|
|
226
|
+
* but before any client-side tool execution begins.
|
|
227
|
+
*/
|
|
228
|
+
onLanguageModelCallEnd?: OnLanguageModelCallEndCallback<NoInfer<TOOLS>>;
|
|
229
|
+
|
|
215
230
|
/**
|
|
216
231
|
* Callback that is called before each tool execution begins.
|
|
217
232
|
*/
|
package/src/embed/embed-many.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { InvalidResponseDataError } from '@ai-sdk/provider';
|
|
1
2
|
import {
|
|
2
3
|
createIdGenerator,
|
|
3
4
|
withUserAgentSuffix,
|
|
@@ -264,6 +265,8 @@ export async function embedMany({
|
|
|
264
265
|
};
|
|
265
266
|
});
|
|
266
267
|
|
|
268
|
+
validateEmbeddingCount({ embeddings, values });
|
|
269
|
+
|
|
267
270
|
logWarnings({
|
|
268
271
|
warnings,
|
|
269
272
|
provider: model.provider,
|
|
@@ -325,8 +328,8 @@ export async function embedMany({
|
|
|
325
328
|
|
|
326
329
|
for (const parallelChunk of parallelChunks) {
|
|
327
330
|
const results = await Promise.all(
|
|
328
|
-
parallelChunk.map(chunk => {
|
|
329
|
-
|
|
331
|
+
parallelChunk.map(async chunk => {
|
|
332
|
+
const result = await retry(async () => {
|
|
330
333
|
const embedCallId = generateCallId();
|
|
331
334
|
|
|
332
335
|
await notify({
|
|
@@ -373,6 +376,13 @@ export async function embedMany({
|
|
|
373
376
|
response: modelResponse.response,
|
|
374
377
|
};
|
|
375
378
|
});
|
|
379
|
+
|
|
380
|
+
validateEmbeddingCount({
|
|
381
|
+
embeddings: result.embeddings,
|
|
382
|
+
values: chunk,
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
return result;
|
|
376
386
|
}),
|
|
377
387
|
);
|
|
378
388
|
|
|
@@ -436,6 +446,21 @@ export async function embedMany({
|
|
|
436
446
|
});
|
|
437
447
|
}
|
|
438
448
|
|
|
449
|
+
function validateEmbeddingCount({
|
|
450
|
+
embeddings,
|
|
451
|
+
values,
|
|
452
|
+
}: {
|
|
453
|
+
embeddings: Array<Embedding>;
|
|
454
|
+
values: Array<string>;
|
|
455
|
+
}) {
|
|
456
|
+
if (embeddings.length !== values.length) {
|
|
457
|
+
throw new InvalidResponseDataError({
|
|
458
|
+
data: embeddings,
|
|
459
|
+
message: `Expected ${values.length} embeddings, but received ${embeddings.length}.`,
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
439
464
|
const textEncoder = new TextEncoder();
|
|
440
465
|
|
|
441
466
|
function splitByEmbeddingLimits({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AISDKError } from '@ai-sdk/provider';
|
|
2
|
+
import type { GenerateImageCall } from '../generate-image/generate-image-result';
|
|
2
3
|
import type { ImageModelResponseMetadata } from '../types/image-model-response-metadata';
|
|
3
4
|
|
|
4
5
|
const name = 'AI_NoImageGeneratedError';
|
|
@@ -14,6 +15,11 @@ const symbol = Symbol.for(marker);
|
|
|
14
15
|
export class NoImageGeneratedError extends AISDKError {
|
|
15
16
|
private readonly [symbol] = true; // used in isInstance
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* The results of the underlying image model calls.
|
|
20
|
+
*/
|
|
21
|
+
readonly calls: Array<GenerateImageCall> | undefined;
|
|
22
|
+
|
|
17
23
|
/**
|
|
18
24
|
* The response metadata for each call.
|
|
19
25
|
*/
|
|
@@ -22,14 +28,17 @@ export class NoImageGeneratedError extends AISDKError {
|
|
|
22
28
|
constructor({
|
|
23
29
|
message = 'No image generated.',
|
|
24
30
|
cause,
|
|
31
|
+
calls,
|
|
25
32
|
responses,
|
|
26
33
|
}: {
|
|
27
34
|
message?: string;
|
|
28
35
|
cause?: Error;
|
|
36
|
+
calls?: Array<GenerateImageCall>;
|
|
29
37
|
responses?: Array<ImageModelResponseMetadata>;
|
|
30
38
|
}) {
|
|
31
39
|
super({ name, message, cause });
|
|
32
40
|
|
|
41
|
+
this.calls = calls;
|
|
33
42
|
this.responses = responses;
|
|
34
43
|
}
|
|
35
44
|
|
|
@@ -295,7 +295,7 @@ export async function generateImage({
|
|
|
295
295
|
logWarnings({ warnings, provider: model.provider, model: model.modelId });
|
|
296
296
|
|
|
297
297
|
if (!images.length) {
|
|
298
|
-
throw new NoImageGeneratedError({ responses });
|
|
298
|
+
throw new NoImageGeneratedError({ calls, responses });
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
return new DefaultGenerateImageResult({
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
safeValidateTypes,
|
|
12
12
|
type FlexibleSchema,
|
|
13
13
|
} from '@ai-sdk/provider-utils';
|
|
14
|
+
import { InvalidArgumentError } from '../error/invalid-argument-error';
|
|
14
15
|
import { NoObjectGeneratedError } from '../error/no-object-generated-error';
|
|
15
16
|
import type { FinishReason } from '../types/language-model';
|
|
16
17
|
import type { LanguageModelResponseMetadata } from '../types/language-model-response-metadata';
|
|
@@ -189,6 +190,8 @@ export const object = <OBJECT>({
|
|
|
189
190
|
* When the model generates a text response, it will return an array of elements.
|
|
190
191
|
*
|
|
191
192
|
* @param element - The schema of the array elements to generate.
|
|
193
|
+
* @param minItems - Optional minimum number of elements to generate.
|
|
194
|
+
* @param maxItems - Optional maximum number of elements to generate.
|
|
192
195
|
* @param name - Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name.
|
|
193
196
|
* @param description - Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description.
|
|
194
197
|
*
|
|
@@ -196,10 +199,20 @@ export const object = <OBJECT>({
|
|
|
196
199
|
*/
|
|
197
200
|
export const array = <ELEMENT>({
|
|
198
201
|
element: inputElementSchema,
|
|
202
|
+
minItems,
|
|
203
|
+
maxItems,
|
|
199
204
|
name,
|
|
200
205
|
description,
|
|
201
206
|
}: {
|
|
202
207
|
element: FlexibleSchema<ELEMENT>;
|
|
208
|
+
/**
|
|
209
|
+
* Optional minimum number of elements to generate.
|
|
210
|
+
*/
|
|
211
|
+
minItems?: number;
|
|
212
|
+
/**
|
|
213
|
+
* Optional maximum number of elements to generate.
|
|
214
|
+
*/
|
|
215
|
+
maxItems?: number;
|
|
203
216
|
/**
|
|
204
217
|
* Optional name of the output that should be generated.
|
|
205
218
|
* Used by some providers for additional LLM guidance, e.g. via tool or schema name.
|
|
@@ -211,6 +224,17 @@ export const array = <ELEMENT>({
|
|
|
211
224
|
*/
|
|
212
225
|
description?: string;
|
|
213
226
|
}): Output<Array<ELEMENT>, Array<ELEMENT>, ELEMENT> => {
|
|
227
|
+
validateArrayBound({ name: 'minItems', value: minItems });
|
|
228
|
+
validateArrayBound({ name: 'maxItems', value: maxItems });
|
|
229
|
+
|
|
230
|
+
if (minItems != null && maxItems != null && minItems > maxItems) {
|
|
231
|
+
throw new InvalidArgumentError({
|
|
232
|
+
parameter: 'minItems',
|
|
233
|
+
value: minItems,
|
|
234
|
+
message: 'minItems must be less than or equal to maxItems',
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
214
238
|
const elementSchema = asSchema(inputElementSchema);
|
|
215
239
|
|
|
216
240
|
return {
|
|
@@ -236,7 +260,12 @@ export const array = <ELEMENT>({
|
|
|
236
260
|
...($defs != null && { $defs }),
|
|
237
261
|
type: 'object',
|
|
238
262
|
properties: {
|
|
239
|
-
elements: {
|
|
263
|
+
elements: {
|
|
264
|
+
type: 'array',
|
|
265
|
+
items: itemSchema,
|
|
266
|
+
...(minItems != null && { minItems }),
|
|
267
|
+
...(maxItems != null && { maxItems }),
|
|
268
|
+
},
|
|
240
269
|
},
|
|
241
270
|
required: ['elements'],
|
|
242
271
|
additionalProperties: false,
|
|
@@ -288,6 +317,23 @@ export const array = <ELEMENT>({
|
|
|
288
317
|
});
|
|
289
318
|
}
|
|
290
319
|
|
|
320
|
+
const lengthValidationError = getArrayLengthValidationError({
|
|
321
|
+
value: outerValue.elements,
|
|
322
|
+
minItems,
|
|
323
|
+
maxItems,
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
if (lengthValidationError != null) {
|
|
327
|
+
throw new NoObjectGeneratedError({
|
|
328
|
+
message: 'No object generated: response did not match schema.',
|
|
329
|
+
cause: lengthValidationError,
|
|
330
|
+
text,
|
|
331
|
+
response: context.response,
|
|
332
|
+
usage: context.usage,
|
|
333
|
+
finishReason: context.finishReason,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
291
337
|
const validatedElements: Array<ELEMENT> = [];
|
|
292
338
|
for (const element of outerValue.elements) {
|
|
293
339
|
const validationResult = await safeValidateTypes({
|
|
@@ -372,6 +418,16 @@ export const array = <ELEMENT>({
|
|
|
372
418
|
publishedElements < partialOutput.length;
|
|
373
419
|
publishedElements++
|
|
374
420
|
) {
|
|
421
|
+
if (maxItems != null && publishedElements >= maxItems) {
|
|
422
|
+
controller.error(
|
|
423
|
+
getArrayLengthValidationError({
|
|
424
|
+
value: partialOutput,
|
|
425
|
+
maxItems,
|
|
426
|
+
}),
|
|
427
|
+
);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
375
431
|
controller.enqueue(partialOutput[publishedElements]);
|
|
376
432
|
}
|
|
377
433
|
}
|
|
@@ -381,6 +437,60 @@ export const array = <ELEMENT>({
|
|
|
381
437
|
};
|
|
382
438
|
};
|
|
383
439
|
|
|
440
|
+
function validateArrayBound({
|
|
441
|
+
name,
|
|
442
|
+
value,
|
|
443
|
+
}: {
|
|
444
|
+
name: 'minItems' | 'maxItems';
|
|
445
|
+
value: number | undefined;
|
|
446
|
+
}) {
|
|
447
|
+
if (value == null) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (!Number.isInteger(value)) {
|
|
452
|
+
throw new InvalidArgumentError({
|
|
453
|
+
parameter: name,
|
|
454
|
+
value,
|
|
455
|
+
message: `${name} must be an integer`,
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (value < 0) {
|
|
460
|
+
throw new InvalidArgumentError({
|
|
461
|
+
parameter: name,
|
|
462
|
+
value,
|
|
463
|
+
message: `${name} must be greater than or equal to 0`,
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function getArrayLengthValidationError({
|
|
469
|
+
value,
|
|
470
|
+
minItems,
|
|
471
|
+
maxItems,
|
|
472
|
+
}: {
|
|
473
|
+
value: Array<unknown>;
|
|
474
|
+
minItems?: number;
|
|
475
|
+
maxItems?: number;
|
|
476
|
+
}): TypeValidationError | undefined {
|
|
477
|
+
if (minItems != null && value.length < minItems) {
|
|
478
|
+
return new TypeValidationError({
|
|
479
|
+
value,
|
|
480
|
+
cause: `elements array must contain at least ${minItems} items`,
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (maxItems != null && value.length > maxItems) {
|
|
485
|
+
return new TypeValidationError({
|
|
486
|
+
value,
|
|
487
|
+
cause: `elements array must contain at most ${maxItems} items`,
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return undefined;
|
|
492
|
+
}
|
|
493
|
+
|
|
384
494
|
/**
|
|
385
495
|
* Output specification for choice generation.
|
|
386
496
|
* When the model generates a text response, it will return a one of the choice options.
|
package/src/ui/chat.ts
CHANGED
|
@@ -420,8 +420,8 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
420
420
|
|
|
421
421
|
// update the message with the new content
|
|
422
422
|
this.state.replaceMessage(messageIndex, {
|
|
423
|
-
...uiMessage,
|
|
424
423
|
id: message.messageId,
|
|
424
|
+
...uiMessage,
|
|
425
425
|
role: uiMessage.role ?? 'user',
|
|
426
426
|
metadata: message.metadata,
|
|
427
427
|
} as UI_MESSAGE);
|
|
@@ -212,6 +212,12 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
|
|
|
212
212
|
const toolName = getToolName(part);
|
|
213
213
|
|
|
214
214
|
if (part.state !== 'input-streaming') {
|
|
215
|
+
const callProviderMetadata =
|
|
216
|
+
part.callProviderMetadata ??
|
|
217
|
+
(part.state === 'output-error'
|
|
218
|
+
? part.resultProviderMetadata
|
|
219
|
+
: undefined);
|
|
220
|
+
|
|
215
221
|
content.push({
|
|
216
222
|
type: 'tool-call' as const,
|
|
217
223
|
toolCallId: part.toolCallId,
|
|
@@ -222,8 +228,8 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
|
|
|
222
228
|
('rawInput' in part ? part.rawInput : undefined))
|
|
223
229
|
: part.input,
|
|
224
230
|
providerExecuted: part.providerExecuted,
|
|
225
|
-
...(
|
|
226
|
-
? { providerOptions:
|
|
231
|
+
...(callProviderMetadata != null
|
|
232
|
+
? { providerOptions: callProviderMetadata }
|
|
227
233
|
: {}),
|
|
228
234
|
});
|
|
229
235
|
|
|
@@ -117,6 +117,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
117
117
|
type: z.literal('dynamic-tool'),
|
|
118
118
|
toolName: z.string(),
|
|
119
119
|
toolCallId: z.string(),
|
|
120
|
+
title: z.string().optional(),
|
|
120
121
|
toolMetadata: toolMetadataSchema.optional(),
|
|
121
122
|
state: z.literal('input-streaming'),
|
|
122
123
|
input: z.unknown().optional(),
|
|
@@ -130,6 +131,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
130
131
|
type: z.literal('dynamic-tool'),
|
|
131
132
|
toolName: z.string(),
|
|
132
133
|
toolCallId: z.string(),
|
|
134
|
+
title: z.string().optional(),
|
|
133
135
|
toolMetadata: toolMetadataSchema.optional(),
|
|
134
136
|
state: z.literal('input-available'),
|
|
135
137
|
input: z.unknown(),
|
|
@@ -143,6 +145,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
143
145
|
type: z.literal('dynamic-tool'),
|
|
144
146
|
toolName: z.string(),
|
|
145
147
|
toolCallId: z.string(),
|
|
148
|
+
title: z.string().optional(),
|
|
146
149
|
toolMetadata: toolMetadataSchema.optional(),
|
|
147
150
|
state: z.literal('approval-requested'),
|
|
148
151
|
input: z.unknown(),
|
|
@@ -164,6 +167,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
164
167
|
type: z.literal('dynamic-tool'),
|
|
165
168
|
toolName: z.string(),
|
|
166
169
|
toolCallId: z.string(),
|
|
170
|
+
title: z.string().optional(),
|
|
167
171
|
toolMetadata: toolMetadataSchema.optional(),
|
|
168
172
|
state: z.literal('approval-responded'),
|
|
169
173
|
input: z.unknown(),
|
|
@@ -185,6 +189,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
185
189
|
type: z.literal('dynamic-tool'),
|
|
186
190
|
toolName: z.string(),
|
|
187
191
|
toolCallId: z.string(),
|
|
192
|
+
title: z.string().optional(),
|
|
188
193
|
toolMetadata: toolMetadataSchema.optional(),
|
|
189
194
|
state: z.literal('output-available'),
|
|
190
195
|
input: z.unknown(),
|
|
@@ -210,6 +215,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
210
215
|
type: z.literal('dynamic-tool'),
|
|
211
216
|
toolName: z.string(),
|
|
212
217
|
toolCallId: z.string(),
|
|
218
|
+
title: z.string().optional(),
|
|
213
219
|
toolMetadata: toolMetadataSchema.optional(),
|
|
214
220
|
state: z.literal('output-error'),
|
|
215
221
|
input: z.unknown().optional(),
|
|
@@ -235,6 +241,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
235
241
|
type: z.literal('dynamic-tool'),
|
|
236
242
|
toolName: z.string(),
|
|
237
243
|
toolCallId: z.string(),
|
|
244
|
+
title: z.string().optional(),
|
|
238
245
|
toolMetadata: toolMetadataSchema.optional(),
|
|
239
246
|
state: z.literal('output-denied'),
|
|
240
247
|
input: z.unknown(),
|
|
@@ -255,6 +262,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
255
262
|
z.object({
|
|
256
263
|
type: z.string().startsWith('tool-'),
|
|
257
264
|
toolCallId: z.string(),
|
|
265
|
+
title: z.string().optional(),
|
|
258
266
|
toolMetadata: toolMetadataSchema.optional(),
|
|
259
267
|
state: z.literal('input-streaming'),
|
|
260
268
|
providerExecuted: z.boolean().optional(),
|
|
@@ -267,6 +275,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
267
275
|
z.object({
|
|
268
276
|
type: z.string().startsWith('tool-'),
|
|
269
277
|
toolCallId: z.string(),
|
|
278
|
+
title: z.string().optional(),
|
|
270
279
|
toolMetadata: toolMetadataSchema.optional(),
|
|
271
280
|
state: z.literal('input-available'),
|
|
272
281
|
providerExecuted: z.boolean().optional(),
|
|
@@ -279,6 +288,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
279
288
|
z.object({
|
|
280
289
|
type: z.string().startsWith('tool-'),
|
|
281
290
|
toolCallId: z.string(),
|
|
291
|
+
title: z.string().optional(),
|
|
282
292
|
toolMetadata: toolMetadataSchema.optional(),
|
|
283
293
|
state: z.literal('approval-requested'),
|
|
284
294
|
input: z.unknown(),
|
|
@@ -299,6 +309,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
299
309
|
z.object({
|
|
300
310
|
type: z.string().startsWith('tool-'),
|
|
301
311
|
toolCallId: z.string(),
|
|
312
|
+
title: z.string().optional(),
|
|
302
313
|
toolMetadata: toolMetadataSchema.optional(),
|
|
303
314
|
state: z.literal('approval-responded'),
|
|
304
315
|
input: z.unknown(),
|
|
@@ -319,6 +330,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
319
330
|
z.object({
|
|
320
331
|
type: z.string().startsWith('tool-'),
|
|
321
332
|
toolCallId: z.string(),
|
|
333
|
+
title: z.string().optional(),
|
|
322
334
|
toolMetadata: toolMetadataSchema.optional(),
|
|
323
335
|
state: z.literal('output-available'),
|
|
324
336
|
providerExecuted: z.boolean().optional(),
|
|
@@ -343,6 +355,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
343
355
|
z.object({
|
|
344
356
|
type: z.string().startsWith('tool-'),
|
|
345
357
|
toolCallId: z.string(),
|
|
358
|
+
title: z.string().optional(),
|
|
346
359
|
toolMetadata: toolMetadataSchema.optional(),
|
|
347
360
|
state: z.literal('output-error'),
|
|
348
361
|
providerExecuted: z.boolean().optional(),
|
|
@@ -367,6 +380,7 @@ const uiMessagesSchema = lazySchema(() =>
|
|
|
367
380
|
z.object({
|
|
368
381
|
type: z.string().startsWith('tool-'),
|
|
369
382
|
toolCallId: z.string(),
|
|
383
|
+
title: z.string().optional(),
|
|
370
384
|
toolMetadata: toolMetadataSchema.optional(),
|
|
371
385
|
state: z.literal('output-denied'),
|
|
372
386
|
providerExecuted: z.boolean().optional(),
|
package/src/util/data-url.ts
CHANGED