ai 6.0.288 → 6.0.290
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 +35 -0
- package/dist/index.d.mts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +377 -281
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +314 -213
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +20 -5
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +20 -5
- package/dist/internal/index.mjs.map +1 -1
- package/docs/03-ai-sdk-core/16-mcp-tools.mdx +57 -0
- package/docs/03-ai-sdk-core/40-middleware.mdx +92 -7
- package/docs/04-ai-sdk-ui/03-chatbot-tool-usage.mdx +7 -0
- package/package.json +5 -4
- package/src/embed/embed-many.ts +19 -3
- package/src/generate-speech/generated-audio-file.ts +0 -8
- package/src/generate-text/generated-file.ts +0 -4
- package/src/generate-text/parse-tool-call.ts +30 -23
- package/src/generate-text/run-tools-transformation.ts +37 -3
- package/src/generate-text/stream-text.ts +9 -28
- package/src/generate-text/to-response-messages.ts +7 -0
- package/src/generate-text/tool-call.ts +26 -0
- package/src/generate-text/validate-tool-approvals.ts +20 -2
- package/src/middleware/extract-reasoning-middleware.ts +1 -1
- package/src/middleware/wrap-embedding-model.ts +12 -2
- package/src/model/get-embedding-model-provider-options-transformer.ts +17 -0
- package/src/prompt/content-part.ts +2 -0
- package/src/prompt/convert-to-language-model-prompt.ts +7 -2
- package/src/prompt/data-content.ts +11 -2
- package/src/ui/chat.ts +108 -17
- package/src/ui/convert-to-model-messages.ts +8 -0
- package/src/ui/http-chat-transport.ts +1 -1
- package/src/ui/last-assistant-message-is-complete-with-approval-responses.ts +1 -1
- package/src/ui/last-assistant-message-is-complete-with-tool-calls.ts +2 -1
- package/src/ui/process-ui-message-stream.ts +6 -0
- package/src/ui/ui-messages.ts +10 -0
- package/src/ui/validate-ui-messages.ts +79 -114
- package/src/ui-message-stream/ui-message-chunks.ts +2 -0
- package/src/util/write-to-server-response.ts +0 -2
|
@@ -201,6 +201,8 @@ export const toolApprovalRequestSchema: z.ZodType<ToolApprovalRequest> =
|
|
|
201
201
|
type: z.literal('tool-approval-request'),
|
|
202
202
|
approvalId: z.string(),
|
|
203
203
|
toolCallId: z.string(),
|
|
204
|
+
signature: z.string().optional(),
|
|
205
|
+
inputSchemaInput: z.unknown().optional(),
|
|
204
206
|
});
|
|
205
207
|
|
|
206
208
|
/**
|
|
@@ -492,8 +492,11 @@ function convertPartToLanguageModelPart(
|
|
|
492
492
|
throw new Error(`Unsupported part type: ${type}`);
|
|
493
493
|
}
|
|
494
494
|
|
|
495
|
-
const {
|
|
496
|
-
|
|
495
|
+
const {
|
|
496
|
+
data: convertedData,
|
|
497
|
+
mediaType: convertedMediaType,
|
|
498
|
+
originalUrl,
|
|
499
|
+
} = convertToLanguageModelV3DataContent(originalData);
|
|
497
500
|
|
|
498
501
|
let mediaType: string | undefined = convertedMediaType ?? part.mediaType;
|
|
499
502
|
let data: Uint8Array | string | URL = convertedData; // binary | base64 | url
|
|
@@ -525,6 +528,7 @@ function convertPartToLanguageModelPart(
|
|
|
525
528
|
mediaType: mediaType ?? 'image/*', // any image
|
|
526
529
|
filename: undefined,
|
|
527
530
|
data,
|
|
531
|
+
...(data instanceof URL && originalUrl != null ? { originalUrl } : {}),
|
|
528
532
|
providerOptions: part.providerOptions,
|
|
529
533
|
};
|
|
530
534
|
}
|
|
@@ -540,6 +544,7 @@ function convertPartToLanguageModelPart(
|
|
|
540
544
|
mediaType,
|
|
541
545
|
filename: part.filename,
|
|
542
546
|
data,
|
|
547
|
+
...(data instanceof URL && originalUrl != null ? { originalUrl } : {}),
|
|
543
548
|
providerOptions: part.providerOptions,
|
|
544
549
|
};
|
|
545
550
|
}
|
|
@@ -28,7 +28,10 @@ export function convertToLanguageModelV3DataContent(
|
|
|
28
28
|
): {
|
|
29
29
|
data: LanguageModelV3DataContent;
|
|
30
30
|
mediaType: string | undefined;
|
|
31
|
+
originalUrl?: string;
|
|
31
32
|
} {
|
|
33
|
+
let originalUrl: string | undefined;
|
|
34
|
+
|
|
32
35
|
// Buffer & Uint8Array:
|
|
33
36
|
if (content instanceof Uint8Array) {
|
|
34
37
|
return { data: content, mediaType: undefined };
|
|
@@ -43,7 +46,9 @@ export function convertToLanguageModelV3DataContent(
|
|
|
43
46
|
// is not a URL and likely some other sort of data.
|
|
44
47
|
if (typeof content === 'string') {
|
|
45
48
|
try {
|
|
46
|
-
|
|
49
|
+
const url = new URL(content);
|
|
50
|
+
originalUrl = url.toString() !== content ? content : undefined;
|
|
51
|
+
content = url;
|
|
47
52
|
} catch (error) {
|
|
48
53
|
// ignored
|
|
49
54
|
}
|
|
@@ -65,7 +70,11 @@ export function convertToLanguageModelV3DataContent(
|
|
|
65
70
|
return { data: base64Content, mediaType: dataUrlMediaType };
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
return {
|
|
73
|
+
return {
|
|
74
|
+
data: content,
|
|
75
|
+
mediaType: undefined,
|
|
76
|
+
...(originalUrl != null ? { originalUrl } : {}),
|
|
77
|
+
};
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
/**
|
package/src/ui/chat.ts
CHANGED
|
@@ -259,6 +259,7 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
259
259
|
private onData?: ChatInit<UI_MESSAGE>['onData'];
|
|
260
260
|
private sendAutomaticallyWhen?: ChatInit<UI_MESSAGE>['sendAutomaticallyWhen'];
|
|
261
261
|
|
|
262
|
+
private pendingApprovalMessageId: string | undefined;
|
|
262
263
|
private activeResponse: ActiveResponse<UI_MESSAGE> | undefined = undefined;
|
|
263
264
|
private activeResumeRequest: ActiveResumeRequest | undefined = undefined;
|
|
264
265
|
private jobExecutor = new SerialJobExecutor();
|
|
@@ -361,9 +362,37 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
361
362
|
options?: ChatRequestOptions,
|
|
362
363
|
): Promise<void> => {
|
|
363
364
|
if (message == null) {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
365
|
+
let messageId = this.pendingApprovalMessageId;
|
|
366
|
+
|
|
367
|
+
if (messageId == null) {
|
|
368
|
+
messageId = this.lastMessage?.id;
|
|
369
|
+
|
|
370
|
+
// When hydrating a chat with an already-responded approval, continue
|
|
371
|
+
// the most recent matching assistant message so result chunks can
|
|
372
|
+
// resolve its tool invocation.
|
|
373
|
+
for (let i = this.state.messages.length - 1; i >= 0; i--) {
|
|
374
|
+
const candidate = this.state.messages[i];
|
|
375
|
+
if (
|
|
376
|
+
candidate.role === 'assistant' &&
|
|
377
|
+
candidate.parts.some(
|
|
378
|
+
part => isToolUIPart(part) && part.state === 'approval-responded',
|
|
379
|
+
)
|
|
380
|
+
) {
|
|
381
|
+
messageId = candidate.id;
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const consumesPendingApproval =
|
|
388
|
+
messageId != null && messageId === this.pendingApprovalMessageId;
|
|
389
|
+
const pendingApprovalMessageIndex = consumesPendingApproval
|
|
390
|
+
? this.state.messages.findIndex(message => message.id === messageId)
|
|
391
|
+
: -1;
|
|
392
|
+
|
|
393
|
+
await this.makeRequestForToolApproval({
|
|
394
|
+
messageId,
|
|
395
|
+
messageIndex: pendingApprovalMessageIndex,
|
|
367
396
|
...options,
|
|
368
397
|
});
|
|
369
398
|
return;
|
|
@@ -489,7 +518,6 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
489
518
|
}) =>
|
|
490
519
|
this.jobExecutor.run(async () => {
|
|
491
520
|
const messages = this.state.messages;
|
|
492
|
-
const lastMessage = messages[messages.length - 1];
|
|
493
521
|
|
|
494
522
|
const updatePart = (
|
|
495
523
|
part: UIMessagePart<UIDataTypes, UITools>,
|
|
@@ -504,11 +532,25 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
504
532
|
}
|
|
505
533
|
: part;
|
|
506
534
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
535
|
+
const messageIndex = messages.findIndex(message =>
|
|
536
|
+
message.parts.some(
|
|
537
|
+
part =>
|
|
538
|
+
isToolUIPart(part) &&
|
|
539
|
+
part.state === 'approval-requested' &&
|
|
540
|
+
part.approval.id === id,
|
|
541
|
+
),
|
|
542
|
+
);
|
|
543
|
+
|
|
544
|
+
if (messageIndex !== -1) {
|
|
545
|
+
const message = messages[messageIndex];
|
|
546
|
+
|
|
547
|
+
// update the message to trigger an immediate UI update
|
|
548
|
+
this.state.replaceMessage(messageIndex, {
|
|
549
|
+
...message,
|
|
550
|
+
parts: message.parts.map(updatePart),
|
|
551
|
+
});
|
|
552
|
+
this.pendingApprovalMessageId = message.id;
|
|
553
|
+
}
|
|
512
554
|
|
|
513
555
|
// update the active response if it exists
|
|
514
556
|
if (this.activeResponse) {
|
|
@@ -525,9 +567,14 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
525
567
|
this.shouldSendAutomatically().then(shouldSend => {
|
|
526
568
|
if (shouldSend) {
|
|
527
569
|
// no await to avoid deadlocking
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
570
|
+
const messageId =
|
|
571
|
+
messageIndex === -1
|
|
572
|
+
? this.lastMessage?.id
|
|
573
|
+
: messages[messageIndex].id;
|
|
574
|
+
|
|
575
|
+
this.makeRequestForToolApproval({
|
|
576
|
+
messageId,
|
|
577
|
+
messageIndex,
|
|
531
578
|
...options,
|
|
532
579
|
});
|
|
533
580
|
}
|
|
@@ -610,6 +657,36 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
610
657
|
return result as boolean;
|
|
611
658
|
}
|
|
612
659
|
|
|
660
|
+
private async makeRequestForToolApproval({
|
|
661
|
+
messageId,
|
|
662
|
+
messageIndex,
|
|
663
|
+
...options
|
|
664
|
+
}: {
|
|
665
|
+
messageId?: string;
|
|
666
|
+
messageIndex: number;
|
|
667
|
+
} & ChatRequestOptions) {
|
|
668
|
+
const consumesPendingApproval =
|
|
669
|
+
messageId != null && messageId === this.pendingApprovalMessageId;
|
|
670
|
+
if (consumesPendingApproval) {
|
|
671
|
+
this.pendingApprovalMessageId = undefined;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
await this.makeRequest({
|
|
675
|
+
trigger: 'submit-message',
|
|
676
|
+
messageId,
|
|
677
|
+
...options,
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
if (
|
|
681
|
+
consumesPendingApproval &&
|
|
682
|
+
this.status === 'error' &&
|
|
683
|
+
this.pendingApprovalMessageId == null
|
|
684
|
+
) {
|
|
685
|
+
this.pendingApprovalMessageId =
|
|
686
|
+
this.state.messages[messageIndex]?.id ?? messageId;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
613
690
|
private async makeRequest({
|
|
614
691
|
trigger,
|
|
615
692
|
metadata,
|
|
@@ -697,6 +774,18 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
697
774
|
this.setStatus({ status: 'submitted', error: undefined });
|
|
698
775
|
|
|
699
776
|
const lastMessage = this.lastMessage;
|
|
777
|
+
const responseMessageIndex =
|
|
778
|
+
trigger === 'submit-message' && messageId != null
|
|
779
|
+
? this.state.messages.findIndex(message => message.id === messageId)
|
|
780
|
+
: this.state.messages.length - 1;
|
|
781
|
+
const responseMessage =
|
|
782
|
+
responseMessageIndex === -1
|
|
783
|
+
? lastMessage
|
|
784
|
+
: this.state.messages[responseMessageIndex];
|
|
785
|
+
const usesEarlierAssistantMessage =
|
|
786
|
+
responseMessageIndex !== -1 &&
|
|
787
|
+
responseMessageIndex < this.state.messages.length - 1 &&
|
|
788
|
+
responseMessage?.role === 'assistant';
|
|
700
789
|
|
|
701
790
|
let isAbort = false;
|
|
702
791
|
let isDisconnect = false;
|
|
@@ -709,7 +798,7 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
709
798
|
lastMessage:
|
|
710
799
|
trigger === 'resume-stream' || trigger === 'regenerate-message'
|
|
711
800
|
? undefined
|
|
712
|
-
: this.state.snapshot(
|
|
801
|
+
: this.state.snapshot(responseMessage),
|
|
713
802
|
messageId: this.generateId(),
|
|
714
803
|
}),
|
|
715
804
|
abortController,
|
|
@@ -763,10 +852,12 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
763
852
|
this.setStatus({ status: 'streaming' });
|
|
764
853
|
}
|
|
765
854
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
855
|
+
if (usesEarlierAssistantMessage) {
|
|
856
|
+
this.state.replaceMessage(
|
|
857
|
+
responseMessageIndex,
|
|
858
|
+
response.state.message,
|
|
859
|
+
);
|
|
860
|
+
} else if (response.state.message.id === this.lastMessage?.id) {
|
|
770
861
|
this.state.replaceMessage(
|
|
771
862
|
this.state.messages.length - 1,
|
|
772
863
|
response.state.message,
|
|
@@ -204,6 +204,14 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
|
|
|
204
204
|
type: 'tool-approval-request' as const,
|
|
205
205
|
approvalId: part.approval.id,
|
|
206
206
|
toolCallId: part.toolCallId,
|
|
207
|
+
...(Object.prototype.hasOwnProperty.call(
|
|
208
|
+
part.approval,
|
|
209
|
+
'inputSchemaInput',
|
|
210
|
+
)
|
|
211
|
+
? {
|
|
212
|
+
inputSchemaInput: part.approval.inputSchemaInput,
|
|
213
|
+
}
|
|
214
|
+
: {}),
|
|
207
215
|
...(part.approval.signature != null
|
|
208
216
|
? { signature: part.approval.signature }
|
|
209
217
|
: {}),
|
|
@@ -35,7 +35,7 @@ export function lastAssistantMessageIsCompleteWithApprovalResponses({
|
|
|
35
35
|
// all tool approvals must have a response
|
|
36
36
|
lastStepToolInvocations.every(
|
|
37
37
|
part =>
|
|
38
|
-
part.state === 'output-available' ||
|
|
38
|
+
(part.state === 'output-available' && part.preliminary !== true) ||
|
|
39
39
|
part.state === 'output-error' ||
|
|
40
40
|
part.state === 'output-denied' ||
|
|
41
41
|
part.state === 'approval-responded',
|
|
@@ -33,7 +33,8 @@ export function lastAssistantMessageIsCompleteWithToolCalls({
|
|
|
33
33
|
lastStepToolInvocations.length > 0 &&
|
|
34
34
|
lastStepToolInvocations.every(
|
|
35
35
|
part =>
|
|
36
|
-
part.state === 'output-available'
|
|
36
|
+
(part.state === 'output-available' && part.preliminary !== true) ||
|
|
37
|
+
part.state === 'output-error',
|
|
37
38
|
)
|
|
38
39
|
);
|
|
39
40
|
}
|
|
@@ -721,6 +721,12 @@ export function processUIMessageStream<UI_MESSAGE extends UIMessage>({
|
|
|
721
721
|
...(chunk.approvalDescriptor != null
|
|
722
722
|
? { descriptor: chunk.approvalDescriptor }
|
|
723
723
|
: {}),
|
|
724
|
+
...(Object.prototype.hasOwnProperty.call(
|
|
725
|
+
chunk,
|
|
726
|
+
'inputSchemaInput',
|
|
727
|
+
)
|
|
728
|
+
? { inputSchemaInput: chunk.inputSchemaInput }
|
|
729
|
+
: {}),
|
|
724
730
|
...(chunk.signature != null
|
|
725
731
|
? { signature: chunk.signature }
|
|
726
732
|
: {}),
|
package/src/ui/ui-messages.ts
CHANGED
|
@@ -263,6 +263,7 @@ export type UIToolInvocation<TOOL extends UITool | Tool> = {
|
|
|
263
263
|
descriptor?: unknown;
|
|
264
264
|
reason?: never;
|
|
265
265
|
signature?: string;
|
|
266
|
+
inputSchemaInput?: unknown;
|
|
266
267
|
};
|
|
267
268
|
}
|
|
268
269
|
| {
|
|
@@ -277,6 +278,7 @@ export type UIToolInvocation<TOOL extends UITool | Tool> = {
|
|
|
277
278
|
descriptor?: unknown;
|
|
278
279
|
reason?: string;
|
|
279
280
|
signature?: string;
|
|
281
|
+
inputSchemaInput?: unknown;
|
|
280
282
|
};
|
|
281
283
|
}
|
|
282
284
|
| {
|
|
@@ -293,6 +295,7 @@ export type UIToolInvocation<TOOL extends UITool | Tool> = {
|
|
|
293
295
|
descriptor?: unknown;
|
|
294
296
|
reason?: string;
|
|
295
297
|
signature?: string;
|
|
298
|
+
inputSchemaInput?: unknown;
|
|
296
299
|
};
|
|
297
300
|
}
|
|
298
301
|
| {
|
|
@@ -309,6 +312,7 @@ export type UIToolInvocation<TOOL extends UITool | Tool> = {
|
|
|
309
312
|
descriptor?: unknown;
|
|
310
313
|
reason?: string;
|
|
311
314
|
signature?: string;
|
|
315
|
+
inputSchemaInput?: unknown;
|
|
312
316
|
};
|
|
313
317
|
}
|
|
314
318
|
| {
|
|
@@ -323,6 +327,7 @@ export type UIToolInvocation<TOOL extends UITool | Tool> = {
|
|
|
323
327
|
descriptor?: unknown;
|
|
324
328
|
reason?: string;
|
|
325
329
|
signature?: string;
|
|
330
|
+
inputSchemaInput?: unknown;
|
|
326
331
|
};
|
|
327
332
|
}
|
|
328
333
|
);
|
|
@@ -381,6 +386,7 @@ export type DynamicToolUIPart = {
|
|
|
381
386
|
descriptor?: unknown;
|
|
382
387
|
reason?: never;
|
|
383
388
|
signature?: string;
|
|
389
|
+
inputSchemaInput?: unknown;
|
|
384
390
|
};
|
|
385
391
|
}
|
|
386
392
|
| {
|
|
@@ -395,6 +401,7 @@ export type DynamicToolUIPart = {
|
|
|
395
401
|
descriptor?: unknown;
|
|
396
402
|
reason?: string;
|
|
397
403
|
signature?: string;
|
|
404
|
+
inputSchemaInput?: unknown;
|
|
398
405
|
};
|
|
399
406
|
}
|
|
400
407
|
| {
|
|
@@ -411,6 +418,7 @@ export type DynamicToolUIPart = {
|
|
|
411
418
|
descriptor?: unknown;
|
|
412
419
|
reason?: string;
|
|
413
420
|
signature?: string;
|
|
421
|
+
inputSchemaInput?: unknown;
|
|
414
422
|
};
|
|
415
423
|
}
|
|
416
424
|
| {
|
|
@@ -426,6 +434,7 @@ export type DynamicToolUIPart = {
|
|
|
426
434
|
descriptor?: unknown;
|
|
427
435
|
reason?: string;
|
|
428
436
|
signature?: string;
|
|
437
|
+
inputSchemaInput?: unknown;
|
|
429
438
|
};
|
|
430
439
|
}
|
|
431
440
|
| {
|
|
@@ -440,6 +449,7 @@ export type DynamicToolUIPart = {
|
|
|
440
449
|
descriptor?: unknown;
|
|
441
450
|
reason?: string;
|
|
442
451
|
signature?: string;
|
|
452
|
+
inputSchemaInput?: unknown;
|
|
443
453
|
};
|
|
444
454
|
}
|
|
445
455
|
);
|