ai 7.0.161 → 7.0.163

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 (72) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/dist/index.d.ts +210 -41
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +551 -114
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +87 -10
  7. package/dist/internal/index.d.ts.map +1 -1
  8. package/dist/internal/index.js +221 -26
  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-agents/06-tool-approvals.mdx +2 -0
  18. package/docs/03-ai-sdk-core/05-generating-text.mdx +1 -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 +85 -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-text/validate-tool-approvals.ts +21 -3
  47. package/src/generate-video/generate-video-result.ts +11 -2
  48. package/src/generate-video/generate-video.ts +26 -2
  49. package/src/model/as-transcription-model-v4.ts +25 -0
  50. package/src/prompt/convert-to-language-model-prompt.ts +86 -14
  51. package/src/realtime/index.ts +3 -0
  52. package/src/realtime/realtime-attempt.ts +1 -0
  53. package/src/realtime/realtime-session.ts +142 -21
  54. package/src/telemetry/create-telemetry-dispatcher.ts +8 -1
  55. package/src/telemetry/filter-telemetry-event.ts +165 -0
  56. package/src/telemetry/get-request-origin.ts +25 -0
  57. package/src/telemetry/index.ts +6 -1
  58. package/src/telemetry/telemetry.ts +62 -0
  59. package/src/telemetry/tracing-channel-publisher.ts +19 -4
  60. package/src/test/mock-transcription-model-v4.ts +4 -0
  61. package/src/transcribe/transcribe-result.ts +20 -0
  62. package/src/transcribe/transcribe.ts +107 -20
  63. package/src/transcribe/transcription-events.ts +28 -8
  64. package/src/types/language-model-request-metadata.ts +3 -0
  65. package/src/types/realtime-model.ts +9 -0
  66. package/src/ui/convert-to-model-messages.ts +36 -28
  67. package/src/ui/index.ts +1 -0
  68. package/src/ui/process-ui-message-stream.ts +10 -0
  69. package/src/ui/ui-messages.ts +20 -0
  70. package/src/ui/validate-ui-messages.ts +21 -0
  71. package/src/ui-message-stream/to-ui-message-chunk.ts +72 -1
  72. package/src/ui-message-stream/ui-message-chunks.ts +31 -0
@@ -1,4 +1,8 @@
1
- import type { JSONObject, SharedV4AudioFormat } from '@ai-sdk/provider';
1
+ import type {
2
+ JSONObject,
3
+ SharedV4AudioFormat,
4
+ TranscriptionModelV4TimestampGranularity,
5
+ } from '@ai-sdk/provider';
2
6
  import type { ProviderOptions } from '@ai-sdk/provider-utils';
3
7
  import type { ProviderMetadata } from '../types';
4
8
  import type { TranscriptionModelResponseMetadata } from '../types/transcription-model-response-metadata';
@@ -21,8 +25,9 @@ type TranscriptionStartEventFor<OPERATION_ID extends string> = {
21
25
  readonly modelId: string;
22
26
 
23
27
  /**
24
- * Metadata about the input audio. The byte length is known immediately for
25
- * non-streaming transcription and is reported on the end event for streams.
28
+ * Metadata about the input audio. Native URL transcription does not inspect
29
+ * the audio, so its byte length and media type are unknown. Streaming byte
30
+ * length is reported on the end event after consuming the stream.
26
31
  */
27
32
  readonly audio: {
28
33
  readonly byteLength: number | undefined;
@@ -47,7 +52,10 @@ type TranscriptionStartEventFor<OPERATION_ID extends string> = {
47
52
  };
48
53
 
49
54
  export type TranscriptionStartEvent =
50
- TranscriptionStartEventFor<'ai.transcribe'>;
55
+ TranscriptionStartEventFor<'ai.transcribe'> & {
56
+ /** Requested shared timing granularities, when specified. */
57
+ readonly timestampGranularities?: Array<TranscriptionModelV4TimestampGranularity>;
58
+ };
51
59
 
52
60
  export type StreamTranscriptionStartEvent =
53
61
  TranscriptionStartEventFor<'ai.streamTranscribe'>;
@@ -72,14 +80,18 @@ type TranscriptionEndEventFor<OPERATION_ID extends string> = {
72
80
 
73
81
  /** Metadata about the input audio. */
74
82
  readonly audio: {
75
- readonly byteLength: number;
76
- readonly mediaType: string;
83
+ readonly byteLength: OPERATION_ID extends 'ai.transcribe'
84
+ ? number | undefined
85
+ : number;
86
+ readonly mediaType: OPERATION_ID extends 'ai.transcribe'
87
+ ? string | undefined
88
+ : string;
77
89
  };
78
90
 
79
91
  /** The complete transcript. */
80
92
  readonly text: string;
81
93
 
82
- /** Transcript segments with timing information. */
94
+ /** Transcript segments with timing information, retaining provider behavior. */
83
95
  readonly segments: Array<{
84
96
  readonly text: string;
85
97
  readonly startSecond: number;
@@ -105,7 +117,15 @@ type TranscriptionEndEventFor<OPERATION_ID extends string> = {
105
117
  readonly response: TranscriptionModelResponseMetadata;
106
118
  };
107
119
 
108
- export type TranscriptionEndEvent = TranscriptionEndEventFor<'ai.transcribe'>;
120
+ export type TranscriptionEndEvent =
121
+ TranscriptionEndEventFor<'ai.transcribe'> & {
122
+ /** Word timings returned by the provider, whether requested or returned by default. */
123
+ readonly words?: Array<{
124
+ readonly text: string;
125
+ readonly startSecond: number;
126
+ readonly endSecond: number;
127
+ }>;
128
+ };
109
129
 
110
130
  export type StreamTranscriptionEndEvent =
111
131
  TranscriptionEndEventFor<'ai.streamTranscribe'>;
@@ -4,6 +4,9 @@ import type { ModelMessage } from '@ai-sdk/provider-utils';
4
4
  * Metadata for a language model request.
5
5
  */
6
6
  export type LanguageModelRequestMetadata = {
7
+ /** HTTP origin used for this request, without URL credentials, paths, queries or fragments. */
8
+ readonly url?: string;
9
+
7
10
  /**
8
11
  * The input messages that were sent to the model for this step.
9
12
  */
@@ -4,9 +4,12 @@ import type {
4
4
  Experimental_RealtimeFactoryV4GetTokenResult as RealtimeFactoryV4GetTokenResult,
5
5
  Experimental_RealtimeModelV4 as RealtimeModelV4,
6
6
  Experimental_RealtimeModelV4ClientEvent as RealtimeModelV4ClientEvent,
7
+ Experimental_RealtimeModelV4ServerConnection as RealtimeModelV4ServerConnection,
7
8
  Experimental_RealtimeModelV4ServerEvent as RealtimeModelV4ServerEvent,
8
9
  Experimental_RealtimeModelV4SessionConfig as RealtimeModelV4SessionConfig,
10
+ Experimental_RealtimeModelV4SessionIntent as RealtimeModelV4SessionIntent,
9
11
  Experimental_RealtimeModelV4ToolDefinition as RealtimeModelV4ToolDefinition,
12
+ Experimental_RealtimeModelV4Usage as RealtimeModelV4Usage,
10
13
  } from '@ai-sdk/provider';
11
14
 
12
15
  export type RealtimeFactory = RealtimeFactoryV4;
@@ -19,8 +22,14 @@ export type RealtimeModel = RealtimeModelV4;
19
22
 
20
23
  export type RealtimeClientEvent = RealtimeModelV4ClientEvent;
21
24
 
25
+ export type RealtimeServerConnection = RealtimeModelV4ServerConnection;
26
+
22
27
  export type RealtimeServerEvent = RealtimeModelV4ServerEvent;
23
28
 
24
29
  export type RealtimeSessionConfig = RealtimeModelV4SessionConfig;
25
30
 
31
+ export type RealtimeSessionIntent = RealtimeModelV4SessionIntent;
32
+
26
33
  export type RealtimeToolDefinition = RealtimeModelV4ToolDefinition;
34
+
35
+ export type RealtimeUsage = RealtimeModelV4Usage;
@@ -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
  }