ai 7.0.162 → 7.0.164

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 (69) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/dist/index.d.ts +166 -41
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +539 -112
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +43 -10
  7. package/dist/internal/index.d.ts.map +1 -1
  8. package/dist/internal/index.js +209 -24
  9. package/dist/internal/index.js.map +1 -1
  10. package/dist/test/index.d.ts +3 -1
  11. package/dist/test/index.d.ts.map +1 -1
  12. package/dist/test/index.js +2 -1
  13. package/dist/test/index.js.map +1 -1
  14. package/docs/02-foundations/02-providers-and-models.mdx +2 -0
  15. package/docs/03-agents/04-loop-control.mdx +34 -0
  16. package/docs/03-agents/06-memory.mdx +42 -0
  17. package/docs/03-ai-sdk-core/05-generating-text.mdx +1 -0
  18. package/docs/03-ai-sdk-core/16-mcp-tools.mdx +12 -0
  19. package/docs/03-ai-sdk-core/36-realtime.mdx +74 -1
  20. package/docs/03-ai-sdk-core/36-transcription.mdx +51 -4
  21. package/docs/03-ai-sdk-core/40-middleware.mdx +7 -2
  22. package/docs/03-ai-sdk-core/60-telemetry.mdx +37 -4
  23. package/docs/04-ai-sdk-ui/50-stream-protocol.mdx +13 -0
  24. package/docs/06-advanced/04-caching.mdx +13 -4
  25. package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +33 -28
  26. package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +58 -1
  27. package/docs/07-reference/01-ai-sdk-core/11-transcribe.mdx +17 -2
  28. package/docs/07-reference/01-ai-sdk-core/13-generate-video.mdx +8 -1
  29. package/docs/07-reference/01-ai-sdk-core/31-ui-message.mdx +23 -0
  30. package/docs/07-reference/02-ai-sdk-ui/05-use-realtime.mdx +37 -8
  31. package/docs/07-reference/04-ai-sdk-workflow/01-workflow-agent.mdx +1 -49
  32. package/docs/08-migration-guides/23-migration-guide-7-0.mdx +36 -34
  33. package/package.json +12 -12
  34. package/src/generate-object/generate-object.ts +2 -1
  35. package/src/generate-object/stream-object.ts +7 -3
  36. package/src/generate-text/generate-text.ts +23 -3
  37. package/src/generate-text/is-output-chunk.ts +1 -0
  38. package/src/generate-text/language-model-events.ts +3 -0
  39. package/src/generate-text/output.ts +90 -37
  40. package/src/generate-text/smooth-stream.ts +5 -0
  41. package/src/generate-text/steering.ts +5 -4
  42. package/src/generate-text/stream-language-model-call.ts +16 -1
  43. package/src/generate-text/stream-text-result.ts +29 -1
  44. package/src/generate-text/stream-text.ts +25 -1
  45. package/src/generate-text/to-response-messages.ts +6 -2
  46. package/src/generate-video/generate-video-result.ts +11 -2
  47. package/src/generate-video/generate-video.ts +26 -2
  48. package/src/model/as-transcription-model-v4.ts +25 -0
  49. package/src/prompt/convert-to-language-model-prompt.ts +86 -14
  50. package/src/realtime/index.ts +3 -0
  51. package/src/realtime/realtime-attempt.ts +1 -0
  52. package/src/realtime/realtime-session.ts +142 -21
  53. package/src/telemetry/create-telemetry-dispatcher.ts +8 -1
  54. package/src/telemetry/filter-telemetry-event.ts +165 -0
  55. package/src/telemetry/get-request-origin.ts +25 -0
  56. package/src/telemetry/tracing-channel-publisher.ts +19 -4
  57. package/src/test/mock-transcription-model-v4.ts +4 -0
  58. package/src/transcribe/transcribe-result.ts +20 -0
  59. package/src/transcribe/transcribe.ts +107 -20
  60. package/src/transcribe/transcription-events.ts +28 -8
  61. package/src/types/language-model-request-metadata.ts +3 -0
  62. package/src/types/realtime-model.ts +9 -0
  63. package/src/ui/convert-to-model-messages.ts +36 -28
  64. package/src/ui/index.ts +1 -0
  65. package/src/ui/process-ui-message-stream.ts +10 -0
  66. package/src/ui/ui-messages.ts +20 -0
  67. package/src/ui/validate-ui-messages.ts +21 -0
  68. package/src/ui-message-stream/to-ui-message-chunk.ts +72 -1
  69. package/src/ui-message-stream/ui-message-chunks.ts +31 -0
@@ -148,34 +148,8 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
148
148
  role: 'user',
149
149
  content: message.parts
150
150
  .map((part): TextPart | FilePart | undefined => {
151
- // Process text parts
152
- if (isTextUIPart(part)) {
153
- return {
154
- type: 'text' as const,
155
- text: part.text,
156
- ...(part.providerMetadata != null
157
- ? { providerOptions: part.providerMetadata }
158
- : {}),
159
- };
160
- }
161
-
162
- // Process file parts
163
- if (isFileUIPart(part)) {
164
- return {
165
- type: 'file' as const,
166
- mediaType: part.mediaType,
167
- filename: part.filename,
168
- data:
169
- part.providerReference != null
170
- ? {
171
- type: 'reference' as const,
172
- reference: part.providerReference,
173
- }
174
- : { type: 'url' as const, url: new URL(part.url) },
175
- ...(part.providerMetadata != null
176
- ? { providerOptions: part.providerMetadata }
177
- : {}),
178
- };
151
+ if (isTextUIPart(part) || isFileUIPart(part)) {
152
+ return convertUserContentUIPart(part);
179
153
  }
180
154
 
181
155
  // Process data parts with converter if provided
@@ -481,6 +455,13 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
481
455
  block.push(part as (typeof block)[number]);
482
456
  } else if (part.type === 'step-start') {
483
457
  await processBlock();
458
+ } else if (part.type === 'steering-message') {
459
+ // steering messages were added to the run between two steps:
460
+ await processBlock();
461
+ modelMessages.push({
462
+ role: 'user',
463
+ content: part.parts.map(convertUserContentUIPart),
464
+ });
484
465
  }
485
466
  }
486
467
 
@@ -504,3 +485,30 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
504
485
 
505
486
  return modelMessages;
506
487
  }
488
+
489
+ function convertUserContentUIPart(
490
+ part: TextUIPart | FileUIPart,
491
+ ): TextPart | FilePart {
492
+ if (part.type === 'text') {
493
+ return {
494
+ type: 'text',
495
+ text: part.text,
496
+ ...(part.providerMetadata != null
497
+ ? { providerOptions: part.providerMetadata }
498
+ : {}),
499
+ };
500
+ }
501
+
502
+ return {
503
+ type: 'file',
504
+ mediaType: part.mediaType,
505
+ filename: part.filename,
506
+ data:
507
+ part.providerReference != null
508
+ ? { type: 'reference', reference: part.providerReference }
509
+ : { type: 'url', url: new URL(part.url) },
510
+ ...(part.providerMetadata != null
511
+ ? { providerOptions: part.providerMetadata }
512
+ : {}),
513
+ };
514
+ }
package/src/ui/index.ts CHANGED
@@ -69,6 +69,7 @@ export {
69
69
  type ReasoningUIPart,
70
70
  type SourceDocumentUIPart,
71
71
  type SourceUrlUIPart,
72
+ type SteeringMessageUIPart as Experimental_SteeringMessageUIPart,
72
73
  type StepStartUIPart,
73
74
  type TextUIPart,
74
75
  type ToolOutputErrorUIPart,
@@ -961,6 +961,16 @@ export function processUIMessageStream<UI_MESSAGE extends UIMessage>({
961
961
  break;
962
962
  }
963
963
 
964
+ case 'steering-message': {
965
+ state.message.parts.push({
966
+ type: 'steering-message',
967
+ id: chunk.id,
968
+ parts: chunk.parts,
969
+ });
970
+ write();
971
+ break;
972
+ }
973
+
964
974
  case 'start-step': {
965
975
  // add a step boundary part to the message
966
976
  state.message.parts.push({ type: 'step-start' });
@@ -89,6 +89,7 @@ export type UIMessagePart<
89
89
  | FileUIPart
90
90
  | ReasoningFileUIPart
91
91
  | DataUIPart<DATA_TYPES>
92
+ | SteeringMessageUIPart
92
93
  | StepStartUIPart;
93
94
 
94
95
  /**
@@ -252,6 +253,25 @@ export type ReasoningFileUIPart = {
252
253
  providerMetadata?: ProviderMetadata;
253
254
  };
254
255
 
256
+ /**
257
+ * Experimental. A user message that was added to the run with steering while
258
+ * the assistant message was generated. It is placed before the output of the
259
+ * step that received it.
260
+ */
261
+ export type SteeringMessageUIPart = {
262
+ type: 'steering-message';
263
+
264
+ /**
265
+ * The id of the steering message.
266
+ */
267
+ id: string;
268
+
269
+ /**
270
+ * The content of the user message.
271
+ */
272
+ parts: Array<TextUIPart | FileUIPart>;
273
+ };
274
+
255
275
  /**
256
276
  * A step boundary part of a message.
257
277
  */
@@ -141,6 +141,27 @@ const uiMessagesSchema = lazySchema(() => {
141
141
  url: z.string(),
142
142
  providerMetadata: providerMetadataSchema.optional(),
143
143
  }),
144
+ z.object({
145
+ type: z.literal('steering-message'),
146
+ id: z.string(),
147
+ parts: z.array(
148
+ z.union([
149
+ z.object({
150
+ type: z.literal('text'),
151
+ text: z.string(),
152
+ providerMetadata: providerMetadataSchema.optional(),
153
+ }),
154
+ z.object({
155
+ type: z.literal('file'),
156
+ mediaType: z.string(),
157
+ filename: z.string().optional(),
158
+ url: z.string(),
159
+ providerReference: providerReferenceSchema.optional(),
160
+ providerMetadata: providerMetadataSchema.optional(),
161
+ }),
162
+ ]),
163
+ ),
164
+ }),
144
165
  z.object({
145
166
  type: z.literal('step-start'),
146
167
  }),
@@ -1,9 +1,17 @@
1
- import type { ToolSet } from '@ai-sdk/provider-utils';
1
+ import {
2
+ convertUint8ArrayToBase64,
3
+ type ToolSet,
4
+ type UserModelMessage,
5
+ } from '@ai-sdk/provider-utils';
2
6
  import type { TextStreamPart } from '../generate-text/stream-text-result';
3
7
  import { getToolCallInputSchemaInput } from '../generate-text/tool-call';
8
+ import { convertDataContentToBase64String } from '../prompt/data-content';
9
+ import { convertToLanguageModelV4FilePart } from '../prompt/file-part-data';
4
10
  import type {
11
+ FileUIPart,
5
12
  InferUIMessageData,
6
13
  InferUIMessageMetadata,
14
+ TextUIPart,
7
15
  UIMessage,
8
16
  } from '../ui/ui-messages';
9
17
  import { isDeepEqualData } from '../util/is-deep-equal-data';
@@ -352,6 +360,14 @@ export function toUIMessageChunk<
352
360
  };
353
361
  }
354
362
 
363
+ case 'steering-message': {
364
+ return {
365
+ type: 'steering-message',
366
+ id: part.id,
367
+ parts: convertUserMessageToUIParts(part.message),
368
+ };
369
+ }
370
+
355
371
  case 'start-step': {
356
372
  return { type: 'start-step' };
357
373
  }
@@ -395,6 +411,7 @@ export function toUIMessageChunk<
395
411
  }
396
412
 
397
413
  case 'tool-input-end':
414
+ case 'ping':
398
415
  case 'raw': {
399
416
  return undefined;
400
417
  }
@@ -405,3 +422,57 @@ export function toUIMessageChunk<
405
422
  }
406
423
  }
407
424
  }
425
+
426
+ function convertUserMessageToUIParts(
427
+ message: UserModelMessage,
428
+ ): Array<TextUIPart | FileUIPart> {
429
+ if (typeof message.content === 'string') {
430
+ return [{ type: 'text', text: message.content }];
431
+ }
432
+
433
+ return message.content.map((part): TextUIPart | FileUIPart => {
434
+ const providerMetadata =
435
+ part.providerOptions != null
436
+ ? { providerMetadata: part.providerOptions }
437
+ : {};
438
+
439
+ if (part.type === 'text') {
440
+ return { type: 'text', text: part.text, ...providerMetadata };
441
+ }
442
+
443
+ const { data, mediaType: dataUrlMediaType } =
444
+ convertToLanguageModelV4FilePart(
445
+ part.type === 'image' ? part.image : part.data,
446
+ );
447
+ const mediaType = dataUrlMediaType ?? part.mediaType ?? 'image';
448
+ const filename = part.type === 'file' ? part.filename : undefined;
449
+ const file = {
450
+ type: 'file' as const,
451
+ mediaType,
452
+ ...(filename != null ? { filename } : {}),
453
+ ...providerMetadata,
454
+ };
455
+
456
+ switch (data.type) {
457
+ case 'url': {
458
+ return { ...file, url: data.url.toString() };
459
+ }
460
+ case 'data': {
461
+ return {
462
+ ...file,
463
+ url: `data:${mediaType};base64,${convertDataContentToBase64String(data.data)}`,
464
+ };
465
+ }
466
+ case 'text': {
467
+ return {
468
+ ...file,
469
+ url: `data:${mediaType};base64,${convertUint8ArrayToBase64(new TextEncoder().encode(data.text))}`,
470
+ };
471
+ }
472
+ case 'reference': {
473
+ // the provider reference takes precedence over the url in model messages:
474
+ return { ...file, url: '', providerReference: data.reference };
475
+ }
476
+ }
477
+ });
478
+ }
@@ -7,8 +7,10 @@ import {
7
7
  import { jsonValueSchema } from '../types/json-value';
8
8
  import type { FinishReason } from '../types/language-model';
9
9
  import type {
10
+ FileUIPart,
10
11
  InferUIMessageData,
11
12
  InferUIMessageMetadata,
13
+ TextUIPart,
12
14
  UIDataTypes,
13
15
  UIMessage,
14
16
  } from '../ui/ui-messages';
@@ -173,6 +175,27 @@ export const uiMessageChunkSchema = lazySchema(() =>
173
175
  mediaType: z.string(),
174
176
  providerMetadata: providerMetadataSchema.optional(),
175
177
  }),
178
+ z.looseObject({
179
+ type: z.literal('steering-message'),
180
+ id: z.string(),
181
+ parts: z.array(
182
+ z.union([
183
+ z.looseObject({
184
+ type: z.literal('text'),
185
+ text: z.string(),
186
+ providerMetadata: providerMetadataSchema.optional(),
187
+ }),
188
+ z.looseObject({
189
+ type: z.literal('file'),
190
+ mediaType: z.string(),
191
+ url: z.string(),
192
+ filename: z.string().optional(),
193
+ providerReference: z.record(z.string(), z.string()).optional(),
194
+ providerMetadata: providerMetadataSchema.optional(),
195
+ }),
196
+ ]),
197
+ ),
198
+ }),
176
199
  z.looseObject({
177
200
  type: z.custom<`data-${string}`>(
178
201
  (value): value is `data-${string}` =>
@@ -388,6 +411,14 @@ export type UIMessageChunk<
388
411
  providerMetadata?: ProviderMetadata;
389
412
  }
390
413
  | DataUIMessageChunk<DATA_TYPES>
414
+ | {
415
+ /**
416
+ * Experimental. A user message that was added to the run with steering.
417
+ */
418
+ type: 'steering-message';
419
+ id: string;
420
+ parts: Array<TextUIPart | FileUIPart>;
421
+ }
391
422
  | {
392
423
  type: 'start-step';
393
424
  }