ai 7.0.141 → 7.0.143

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 (31) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/index.d.ts +256 -203
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +220 -123
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +28 -16
  7. package/dist/internal/index.d.ts.map +1 -1
  8. package/dist/internal/index.js +1 -1
  9. package/docs/03-ai-sdk-core/17-mcp-events.mdx +50 -0
  10. package/docs/03-ai-sdk-core/32-decisions.mdx +2 -1
  11. package/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx +1 -1
  12. package/docs/04-ai-sdk-ui/50-stream-protocol.mdx +7 -0
  13. package/docs/07-reference/01-ai-sdk-core/02-stream-text-low-memory.mdx +107 -0
  14. package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +13 -0
  15. package/docs/07-reference/01-ai-sdk-core/14-decide.mdx +1 -1
  16. package/docs/07-reference/01-ai-sdk-core/24-mcp-events.mdx +9 -8
  17. package/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx +1 -1
  18. package/package.json +12 -12
  19. package/src/agent/tool-loop-agent.ts +7 -4
  20. package/src/decide/decision-result.ts +6 -1
  21. package/src/decide/validate-decision.ts +21 -1
  22. package/src/generate-text/stream-language-model-call.ts +32 -16
  23. package/src/generate-text/stream-text-result.ts +2 -0
  24. package/src/generate-text/stream-text-single-consumer-result.ts +75 -0
  25. package/src/generate-text/stream-text.ts +250 -37
  26. package/src/ui/chat.ts +9 -4
  27. package/src/ui/process-ui-message-stream.ts +29 -3
  28. package/src/ui/ui-messages.ts +4 -0
  29. package/src/ui/validate-ui-messages.ts +2 -0
  30. package/src/ui-message-stream/to-ui-message-chunk.ts +3 -0
  31. package/src/ui-message-stream/ui-message-chunks.ts +3 -0
@@ -225,6 +225,7 @@ export async function streamLanguageModelCall<
225
225
  generateId = originalGenerateId,
226
226
  generateCallId = originalGenerateCallId,
227
227
  now = originalNow,
228
+ collectContent = true,
228
229
  } = {},
229
230
  onStart,
230
231
  onLanguageModelCallStart,
@@ -258,6 +259,8 @@ export async function streamLanguageModelCall<
258
259
  generateId?: IdGenerator;
259
260
  generateCallId?: IdGenerator;
260
261
  now?: () => number;
262
+ /** Internal: content is only needed by collectors and full-content callbacks. */
263
+ collectContent?: boolean;
261
264
  };
262
265
  onLanguageModelCallStart?: Arrayable<OnLanguageModelCallStartCallback>;
263
266
  onLanguageModelCallEnd?: Arrayable<OnLanguageModelCallEndCallback<TOOLS>>;
@@ -383,6 +386,7 @@ export async function streamLanguageModelCall<
383
386
  now,
384
387
  callStartTimestampMs,
385
388
  onLanguageModelCallEnd,
389
+ collectContent,
386
390
  }),
387
391
  );
388
392
 
@@ -411,6 +415,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
411
415
  now,
412
416
  callStartTimestampMs,
413
417
  onLanguageModelCallEnd,
418
+ collectContent,
414
419
  }: {
415
420
  tools: TOOLS | undefined;
416
421
  instructions: Instructions | undefined;
@@ -426,6 +431,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
426
431
  now: () => number;
427
432
  callStartTimestampMs: number;
428
433
  onLanguageModelCallEnd?: Arrayable<OnLanguageModelCallEndCallback<TOOLS>>;
434
+ collectContent: boolean;
429
435
  }) {
430
436
  // keep track of parsed tool calls so provider-emitted approval requests can reference them
431
437
  // keep track of tool inputs for provider-side tool results
@@ -471,6 +477,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
471
477
 
472
478
  case 'text-start':
473
479
  upsertTextContentPart({
480
+ enabled: collectContent,
474
481
  content: modelCallContent,
475
482
  rawContent: rawModelCallContent,
476
483
  partIndexes: textPartIndexes,
@@ -484,6 +491,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
484
491
 
485
492
  case 'text-delta':
486
493
  upsertTextContentPart({
494
+ enabled: collectContent,
487
495
  content: modelCallContent,
488
496
  rawContent: rawModelCallContent,
489
497
  partIndexes: textPartIndexes,
@@ -503,6 +511,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
503
511
 
504
512
  case 'text-end':
505
513
  upsertTextContentPart({
514
+ enabled: collectContent,
506
515
  content: modelCallContent,
507
516
  rawContent: rawModelCallContent,
508
517
  partIndexes: textPartIndexes,
@@ -518,6 +527,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
518
527
 
519
528
  case 'reasoning-start':
520
529
  upsertTextContentPart({
530
+ enabled: collectContent,
521
531
  content: modelCallContent,
522
532
  rawContent: rawModelCallContent,
523
533
  partIndexes: reasoningPartIndexes,
@@ -531,6 +541,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
531
541
 
532
542
  case 'reasoning-delta':
533
543
  upsertTextContentPart({
544
+ enabled: collectContent,
534
545
  content: modelCallContent,
535
546
  rawContent: rawModelCallContent,
536
547
  partIndexes: reasoningPartIndexes,
@@ -550,6 +561,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
550
561
 
551
562
  case 'reasoning-end':
552
563
  upsertTextContentPart({
564
+ enabled: collectContent,
553
565
  content: modelCallContent,
554
566
  rawContent: rawModelCallContent,
555
567
  partIndexes: reasoningPartIndexes,
@@ -573,14 +585,15 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
573
585
  mediaType: chunk.mediaType,
574
586
  });
575
587
 
576
- modelCallContent.push({
577
- type: chunk.type,
578
- file,
579
- ...(chunk.providerMetadata != null
580
- ? { providerMetadata: chunk.providerMetadata }
581
- : {}),
582
- });
583
- rawModelCallContent.push(chunk);
588
+ if (collectContent)
589
+ modelCallContent.push({
590
+ type: chunk.type,
591
+ file,
592
+ ...(chunk.providerMetadata != null
593
+ ? { providerMetadata: chunk.providerMetadata }
594
+ : {}),
595
+ });
596
+ if (collectContent) rawModelCallContent.push(chunk);
584
597
 
585
598
  controller.enqueue({
586
599
  type: chunk.type,
@@ -689,7 +702,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
689
702
  }
690
703
 
691
704
  case 'tool-call': {
692
- rawModelCallContent.push(chunk);
705
+ if (collectContent) rawModelCallContent.push(chunk);
693
706
 
694
707
  try {
695
708
  const toolCall = await parseToolCall({
@@ -704,7 +717,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
704
717
 
705
718
  toolCallsByToolCallId.set(toolCall.toolCallId, toolCall);
706
719
  controller.enqueue(toolCall);
707
- modelCallContent.push(toolCall);
720
+ if (collectContent) modelCallContent.push(toolCall);
708
721
 
709
722
  if (toolCall.invalid) {
710
723
  if (!toolCall.providerExecuted) {
@@ -731,7 +744,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
731
744
  }
732
745
 
733
746
  case 'tool-approval-request': {
734
- rawModelCallContent.push(chunk);
747
+ if (collectContent) rawModelCallContent.push(chunk);
735
748
 
736
749
  const toolCall = toolCallsByToolCallId.get(chunk.toolCallId);
737
750
 
@@ -753,12 +766,12 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
753
766
  } as const;
754
767
 
755
768
  controller.enqueue(toolApprovalRequest);
756
- modelCallContent.push(toolApprovalRequest);
769
+ if (collectContent) modelCallContent.push(toolApprovalRequest);
757
770
  break;
758
771
  }
759
772
 
760
773
  case 'tool-result': {
761
- rawModelCallContent.push(chunk);
774
+ if (collectContent) rawModelCallContent.push(chunk);
762
775
 
763
776
  const toolName = chunk.toolName as keyof TOOLS & string;
764
777
  const toolCall = toolCallsByToolCallId.get(chunk.toolCallId);
@@ -796,7 +809,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
796
809
  } as TypedToolResult<TOOLS>);
797
810
 
798
811
  controller.enqueue(toolResultPart);
799
- modelCallContent.push(toolResultPart);
812
+ if (collectContent) modelCallContent.push(toolResultPart);
800
813
 
801
814
  break;
802
815
  }
@@ -836,8 +849,8 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
836
849
 
837
850
  default:
838
851
  if (chunk.type === 'custom' || chunk.type === 'source') {
839
- modelCallContent.push(chunk);
840
- rawModelCallContent.push(chunk);
852
+ if (collectContent) modelCallContent.push(chunk);
853
+ if (collectContent) rawModelCallContent.push(chunk);
841
854
  }
842
855
 
843
856
  controller.enqueue(chunk);
@@ -890,6 +903,7 @@ function calculateNearestRankPercentile(
890
903
  * Appends a text or reasoning content part into the content array and updates the part indexes.
891
904
  */
892
905
  function upsertTextContentPart<TOOLS extends ToolSet>({
906
+ enabled,
893
907
  content,
894
908
  rawContent,
895
909
  partIndexes,
@@ -899,6 +913,7 @@ function upsertTextContentPart<TOOLS extends ToolSet>({
899
913
  textDelta,
900
914
  providerMetadata,
901
915
  }: {
916
+ enabled: boolean;
902
917
  content: Array<ContentPart<TOOLS>>;
903
918
  rawContent: Array<LanguageModelV4Content>;
904
919
  partIndexes: Map<string, number>;
@@ -908,6 +923,7 @@ function upsertTextContentPart<TOOLS extends ToolSet>({
908
923
  textDelta?: string;
909
924
  providerMetadata?: ProviderMetadata;
910
925
  }) {
926
+ if (!enabled) return;
911
927
  let partIndex = partIndexes.get(id);
912
928
 
913
929
  if (partIndex == null) {
@@ -493,6 +493,8 @@ export type TextStreamToolInputStartPart = {
493
493
  type: 'tool-input-start';
494
494
  id: string;
495
495
  toolName: string;
496
+ /** Encoding of the input deltas. Defaults to JSON when omitted. */
497
+ inputEncoding?: 'json' | 'text';
496
498
  providerMetadata?: ProviderMetadata;
497
499
  toolMetadata?: JSONObject;
498
500
  providerExecuted?: boolean;
@@ -0,0 +1,75 @@
1
+ import type { Context, ToolSet } from '@ai-sdk/provider-utils';
2
+ import type { Output } from './output';
3
+ import type { StreamTextResult } from './stream-text-result';
4
+
5
+ /** A single-consumer view of a text generation, without replay or final content getters. */
6
+ export type StreamTextSingleConsumerResult<
7
+ TOOLS extends ToolSet,
8
+ RUNTIME_CONTEXT extends Context,
9
+ OUTPUT extends Output,
10
+ > = Pick<
11
+ StreamTextResult<TOOLS, RUNTIME_CONTEXT, OUTPUT>,
12
+ | 'textStream'
13
+ | 'stream'
14
+ | 'fullStream'
15
+ | 'partialOutputStream'
16
+ | 'elementStream'
17
+ | 'totalUsage'
18
+ | 'usage'
19
+ | 'finishReason'
20
+ | 'rawFinishReason'
21
+ | 'consumeStream'
22
+ | 'toUIMessageStream'
23
+ | 'toUIMessageStreamResponse'
24
+ | 'toTextStreamResponse'
25
+ | 'pipeUIMessageStreamToResponse'
26
+ | 'pipeTextStreamToResponse'
27
+ >;
28
+
29
+ /** Expose only the stream and completion metadata for a single consumer. */
30
+ export function createSingleConsumerStreamTextResult<
31
+ TOOLS extends ToolSet,
32
+ RUNTIME_CONTEXT extends Context,
33
+ OUTPUT extends Output,
34
+ >(
35
+ result: StreamTextResult<TOOLS, RUNTIME_CONTEXT, OUTPUT>,
36
+ ): StreamTextSingleConsumerResult<TOOLS, RUNTIME_CONTEXT, OUTPUT> {
37
+ // A concrete facade also prevents untyped callers from accidentally reading
38
+ // a final-content getter when no result collector was configured.
39
+ return {
40
+ get textStream() {
41
+ return result.textStream;
42
+ },
43
+ get stream() {
44
+ return result.stream;
45
+ },
46
+ get fullStream() {
47
+ return result.fullStream;
48
+ },
49
+ get partialOutputStream() {
50
+ return result.partialOutputStream;
51
+ },
52
+ get elementStream() {
53
+ return result.elementStream;
54
+ },
55
+ get totalUsage() {
56
+ return result.totalUsage;
57
+ },
58
+ get usage() {
59
+ return result.usage;
60
+ },
61
+ get finishReason() {
62
+ return result.finishReason;
63
+ },
64
+ get rawFinishReason() {
65
+ return result.rawFinishReason;
66
+ },
67
+ consumeStream: result.consumeStream.bind(result),
68
+ toUIMessageStream: result.toUIMessageStream.bind(result),
69
+ toUIMessageStreamResponse: result.toUIMessageStreamResponse.bind(result),
70
+ toTextStreamResponse: result.toTextStreamResponse.bind(result),
71
+ pipeUIMessageStreamToResponse:
72
+ result.pipeUIMessageStreamToResponse.bind(result),
73
+ pipeTextStreamToResponse: result.pipeTextStreamToResponse.bind(result),
74
+ };
75
+ }