ai 7.0.112 → 7.0.113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/index.d.ts +16 -0
  3. package/dist/index.js +315 -213
  4. package/dist/index.js.map +1 -1
  5. package/dist/internal/index.d.ts +2 -1
  6. package/dist/internal/index.js +105 -28
  7. package/dist/internal/index.js.map +1 -1
  8. package/docs/03-agents/06-tool-approvals.mdx +16 -0
  9. package/docs/03-ai-sdk-core/37-speech.mdx +2 -0
  10. package/docs/07-reference/01-ai-sdk-core/12-generate-speech.mdx +1 -1
  11. package/docs/07-reference/01-ai-sdk-core/32-validate-ui-messages.mdx +18 -0
  12. package/package.json +11 -11
  13. package/src/embed/embed-many.ts +18 -2
  14. package/src/generate-speech/generate-speech.ts +15 -4
  15. package/src/generate-speech/generated-audio-file.ts +0 -8
  16. package/src/generate-text/execute-tools-from-stream.ts +0 -2
  17. package/src/generate-text/generate-text.ts +1 -0
  18. package/src/generate-text/generated-file.ts +0 -8
  19. package/src/generate-text/invoke-tool-callbacks-from-stream.ts +9 -8
  20. package/src/generate-text/output.ts +0 -2
  21. package/src/generate-text/parse-tool-call.ts +38 -25
  22. package/src/generate-text/stream-text.ts +1 -0
  23. package/src/generate-text/to-response-messages.ts +7 -0
  24. package/src/generate-text/tool-call.ts +26 -0
  25. package/src/generate-text/validate-tool-approvals.ts +39 -3
  26. package/src/generate-video/generate-video.ts +0 -2
  27. package/src/middleware/extract-reasoning-middleware.ts +1 -1
  28. package/src/middleware/wrap-embedding-model.ts +9 -1
  29. package/src/model/get-embedding-model-provider-options-transformer.ts +17 -0
  30. package/src/prompt/content-part.ts +3 -0
  31. package/src/registry/custom-provider.ts +12 -5
  32. package/src/ui/chat.ts +108 -17
  33. package/src/ui/convert-to-model-messages.ts +8 -0
  34. package/src/ui/direct-chat-transport.ts +2 -0
  35. package/src/ui/process-ui-message-stream.ts +6 -0
  36. package/src/ui/ui-messages.ts +10 -0
  37. package/src/ui/validate-ui-messages.ts +98 -132
  38. package/src/ui-message-stream/to-ui-message-chunk.ts +7 -0
  39. package/src/ui-message-stream/ui-message-chunks.ts +2 -0
  40. package/src/util/write-to-server-response.ts +0 -2
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  type Experimental_EvaluationModelV4 as EvaluationModelV4,
3
3
  type EmbeddingModelV4,
4
+ type Experimental_VideoModelV3,
4
5
  type Experimental_VideoModelV4,
5
6
  type FilesV4,
6
7
  type ImageModelV4,
@@ -35,6 +36,12 @@ import type { SpeechModel } from '../types/speech-model';
35
36
  import type { TranscriptionModel } from '../types/transcription-model';
36
37
  import type { VideoModel } from '../types/video-model';
37
38
 
39
+ type ProviderWithOptionalVideoModel = {
40
+ videoModel?: (
41
+ modelId: string,
42
+ ) => Experimental_VideoModelV3 | Experimental_VideoModelV4;
43
+ };
44
+
38
45
  /**
39
46
  * Creates a custom provider with specified language models, text embedding models, image models, transcription models, speech models, file APIs, skill APIs, and an optional fallback provider.
40
47
  *
@@ -247,11 +254,11 @@ export function customProvider<
247
254
  return resolveVideoModel(videoModels[modelId]);
248
255
  }
249
256
 
250
- // TODO AI SDK v7
251
- // @ts-expect-error - videoModel support is experimental
252
- const videoModel = fallbackProvider?.videoModel;
253
- if (videoModel) {
254
- return videoModel(modelId);
257
+ const provider = fallbackProviderArg as
258
+ | ProviderWithOptionalVideoModel
259
+ | undefined;
260
+ if (provider?.videoModel) {
261
+ return resolveVideoModel(provider.videoModel(modelId));
255
262
  }
256
263
 
257
264
  throw new NoSuchModelError({ modelId, modelType: 'videoModel' });
package/src/ui/chat.ts CHANGED
@@ -260,6 +260,7 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
260
260
  private sendAutomaticallyWhen?: ChatInit<UI_MESSAGE>['sendAutomaticallyWhen'];
261
261
 
262
262
  private pendingMessagePreparations = new Set<AbortController>();
263
+ private pendingApprovalMessageId: string | undefined;
263
264
  private activeResponse: ActiveResponse<UI_MESSAGE> | undefined = undefined;
264
265
  private activeResumeRequest: ActiveResumeRequest | undefined = undefined;
265
266
  private jobExecutor = new SerialJobExecutor();
@@ -362,9 +363,37 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
362
363
  options?: ChatRequestOptions,
363
364
  ): Promise<void> => {
364
365
  if (message == null) {
365
- await this.makeRequest({
366
- trigger: 'submit-message',
367
- messageId: this.lastMessage?.id,
366
+ let messageId = this.pendingApprovalMessageId;
367
+
368
+ if (messageId == null) {
369
+ messageId = this.lastMessage?.id;
370
+
371
+ // When hydrating a chat with an already-responded approval, continue
372
+ // the most recent matching assistant message so result chunks can
373
+ // resolve its tool invocation.
374
+ for (let i = this.state.messages.length - 1; i >= 0; i--) {
375
+ const candidate = this.state.messages[i];
376
+ if (
377
+ candidate.role === 'assistant' &&
378
+ candidate.parts.some(
379
+ part => isToolUIPart(part) && part.state === 'approval-responded',
380
+ )
381
+ ) {
382
+ messageId = candidate.id;
383
+ break;
384
+ }
385
+ }
386
+ }
387
+
388
+ const consumesPendingApproval =
389
+ messageId != null && messageId === this.pendingApprovalMessageId;
390
+ const pendingApprovalMessageIndex = consumesPendingApproval
391
+ ? this.state.messages.findIndex(message => message.id === messageId)
392
+ : -1;
393
+
394
+ await this.makeRequestForToolApproval({
395
+ messageId,
396
+ messageIndex: pendingApprovalMessageIndex,
368
397
  ...options,
369
398
  });
370
399
  return;
@@ -512,7 +541,6 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
512
541
  }) =>
513
542
  this.jobExecutor.run(async () => {
514
543
  const messages = this.state.messages;
515
- const lastMessage = messages[messages.length - 1];
516
544
 
517
545
  const updatePart = (
518
546
  part: UIMessagePart<UIDataTypes, UITools>,
@@ -527,11 +555,25 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
527
555
  }
528
556
  : part;
529
557
 
530
- // update the message to trigger an immediate UI update
531
- this.state.replaceMessage(messages.length - 1, {
532
- ...lastMessage,
533
- parts: lastMessage.parts.map(updatePart),
534
- });
558
+ const messageIndex = messages.findIndex(message =>
559
+ message.parts.some(
560
+ part =>
561
+ isToolUIPart(part) &&
562
+ part.state === 'approval-requested' &&
563
+ part.approval.id === id,
564
+ ),
565
+ );
566
+
567
+ if (messageIndex !== -1) {
568
+ const message = messages[messageIndex];
569
+
570
+ // update the message to trigger an immediate UI update
571
+ this.state.replaceMessage(messageIndex, {
572
+ ...message,
573
+ parts: message.parts.map(updatePart),
574
+ });
575
+ this.pendingApprovalMessageId = message.id;
576
+ }
535
577
 
536
578
  // update the active response if it exists
537
579
  if (this.activeResponse) {
@@ -548,9 +590,14 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
548
590
  this.shouldSendAutomatically().then(shouldSend => {
549
591
  if (shouldSend) {
550
592
  // no await to avoid deadlocking
551
- this.makeRequest({
552
- trigger: 'submit-message',
553
- messageId: this.lastMessage?.id,
593
+ const messageId =
594
+ messageIndex === -1
595
+ ? this.lastMessage?.id
596
+ : messages[messageIndex].id;
597
+
598
+ this.makeRequestForToolApproval({
599
+ messageId,
600
+ messageIndex,
554
601
  ...options,
555
602
  });
556
603
  }
@@ -636,6 +683,36 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
636
683
  return result as boolean;
637
684
  }
638
685
 
686
+ private async makeRequestForToolApproval({
687
+ messageId,
688
+ messageIndex,
689
+ ...options
690
+ }: {
691
+ messageId?: string;
692
+ messageIndex: number;
693
+ } & ChatRequestOptions) {
694
+ const consumesPendingApproval =
695
+ messageId != null && messageId === this.pendingApprovalMessageId;
696
+ if (consumesPendingApproval) {
697
+ this.pendingApprovalMessageId = undefined;
698
+ }
699
+
700
+ await this.makeRequest({
701
+ trigger: 'submit-message',
702
+ messageId,
703
+ ...options,
704
+ });
705
+
706
+ if (
707
+ consumesPendingApproval &&
708
+ this.status === 'error' &&
709
+ this.pendingApprovalMessageId == null
710
+ ) {
711
+ this.pendingApprovalMessageId =
712
+ this.state.messages[messageIndex]?.id ?? messageId;
713
+ }
714
+ }
715
+
639
716
  private async makeRequest({
640
717
  trigger,
641
718
  metadata,
@@ -723,6 +800,18 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
723
800
  this.setStatus({ status: 'submitted', error: undefined });
724
801
 
725
802
  const lastMessage = this.lastMessage;
803
+ const responseMessageIndex =
804
+ trigger === 'submit-message' && messageId != null
805
+ ? this.state.messages.findIndex(message => message.id === messageId)
806
+ : this.state.messages.length - 1;
807
+ const responseMessage =
808
+ responseMessageIndex === -1
809
+ ? lastMessage
810
+ : this.state.messages[responseMessageIndex];
811
+ const usesEarlierAssistantMessage =
812
+ responseMessageIndex !== -1 &&
813
+ responseMessageIndex < this.state.messages.length - 1 &&
814
+ responseMessage?.role === 'assistant';
726
815
 
727
816
  let isAbort = false;
728
817
  let isDisconnect = false;
@@ -735,7 +824,7 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
735
824
  lastMessage:
736
825
  trigger === 'resume-stream' || trigger === 'regenerate-message'
737
826
  ? undefined
738
- : this.state.snapshot(lastMessage),
827
+ : this.state.snapshot(responseMessage),
739
828
  messageId: this.generateId(),
740
829
  }),
741
830
  abortController,
@@ -789,10 +878,12 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
789
878
  this.setStatus({ status: 'streaming' });
790
879
  }
791
880
 
792
- const replaceLastMessage =
793
- response.state.message.id === this.lastMessage?.id;
794
-
795
- if (replaceLastMessage) {
881
+ if (usesEarlierAssistantMessage) {
882
+ this.state.replaceMessage(
883
+ responseMessageIndex,
884
+ response.state.message,
885
+ );
886
+ } else if (response.state.message.id === this.lastMessage?.id) {
796
887
  this.state.replaceMessage(
797
888
  this.state.messages.length - 1,
798
889
  response.state.message,
@@ -245,6 +245,14 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
245
245
  ...(part.approval.requestReason != null
246
246
  ? { reason: part.approval.requestReason }
247
247
  : {}),
248
+ ...(Object.prototype.hasOwnProperty.call(
249
+ part.approval,
250
+ 'inputSchemaInput',
251
+ )
252
+ ? {
253
+ inputSchemaInput: part.approval.inputSchemaInput,
254
+ }
255
+ : {}),
248
256
  ...(part.approval.signature != null
249
257
  ? { signature: part.approval.signature }
250
258
  : {}),
@@ -124,6 +124,8 @@ export class DirectChatTransport<
124
124
  // Return the UI message stream
125
125
  return toUIMessageStream({
126
126
  ...this.uiMessageStreamOptions,
127
+ originalMessages:
128
+ this.uiMessageStreamOptions.originalMessages ?? validatedMessages,
127
129
  stream: result.stream,
128
130
  tools: this.agent.tools,
129
131
  });
@@ -755,6 +755,12 @@ export function processUIMessageStream<UI_MESSAGE extends UIMessage>({
755
755
  ...(chunk.approvalDescriptor != null
756
756
  ? { descriptor: chunk.approvalDescriptor }
757
757
  : {}),
758
+ ...(Object.prototype.hasOwnProperty.call(
759
+ chunk,
760
+ 'inputSchemaInput',
761
+ )
762
+ ? { inputSchemaInput: chunk.inputSchemaInput }
763
+ : {}),
758
764
  ...(chunk.reason != null
759
765
  ? { requestReason: chunk.reason }
760
766
  : {}),
@@ -324,6 +324,7 @@ export type UIToolInvocation<TOOL extends UITool | Tool> = {
324
324
  reason?: never;
325
325
  isAutomatic?: boolean;
326
326
  signature?: string;
327
+ inputSchemaInput?: unknown;
327
328
  };
328
329
  }
329
330
  | {
@@ -340,6 +341,7 @@ export type UIToolInvocation<TOOL extends UITool | Tool> = {
340
341
  reason?: string;
341
342
  isAutomatic?: boolean;
342
343
  signature?: string;
344
+ inputSchemaInput?: unknown;
343
345
  };
344
346
  }
345
347
  | {
@@ -358,6 +360,7 @@ export type UIToolInvocation<TOOL extends UITool | Tool> = {
358
360
  reason?: string;
359
361
  isAutomatic?: boolean;
360
362
  signature?: string;
363
+ inputSchemaInput?: unknown;
361
364
  };
362
365
  }
363
366
  | {
@@ -380,6 +383,7 @@ export type UIToolInvocation<TOOL extends UITool | Tool> = {
380
383
  reason?: string;
381
384
  isAutomatic?: boolean;
382
385
  signature?: string;
386
+ inputSchemaInput?: unknown;
383
387
  };
384
388
  }
385
389
  | {
@@ -396,6 +400,7 @@ export type UIToolInvocation<TOOL extends UITool | Tool> = {
396
400
  reason?: string;
397
401
  isAutomatic?: boolean;
398
402
  signature?: string;
403
+ inputSchemaInput?: unknown;
399
404
  };
400
405
  }
401
406
  );
@@ -456,6 +461,7 @@ export type DynamicToolUIPart = {
456
461
  reason?: never;
457
462
  isAutomatic?: boolean;
458
463
  signature?: string;
464
+ inputSchemaInput?: unknown;
459
465
  };
460
466
  }
461
467
  | {
@@ -472,6 +478,7 @@ export type DynamicToolUIPart = {
472
478
  reason?: string;
473
479
  isAutomatic?: boolean;
474
480
  signature?: string;
481
+ inputSchemaInput?: unknown;
475
482
  };
476
483
  }
477
484
  | {
@@ -490,6 +497,7 @@ export type DynamicToolUIPart = {
490
497
  reason?: string;
491
498
  isAutomatic?: boolean;
492
499
  signature?: string;
500
+ inputSchemaInput?: unknown;
493
501
  };
494
502
  }
495
503
  | {
@@ -507,6 +515,7 @@ export type DynamicToolUIPart = {
507
515
  reason?: string;
508
516
  isAutomatic?: boolean;
509
517
  signature?: string;
518
+ inputSchemaInput?: unknown;
510
519
  };
511
520
  }
512
521
  | {
@@ -523,6 +532,7 @@ export type DynamicToolUIPart = {
523
532
  reason?: string;
524
533
  isAutomatic?: boolean;
525
534
  signature?: string;
535
+ inputSchemaInput?: unknown;
526
536
  };
527
537
  }
528
538
  );