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
@@ -0,0 +1,165 @@
1
+ import type { TelemetryOptions } from './telemetry-options';
2
+
3
+ /**
4
+ * Filters SDK-owned content fields on a copy. Only descend into SDK event
5
+ * containers; user context has its own inclusion policy.
6
+ */
7
+ export function filterTelemetryEvent<EVENT>(
8
+ event: EVENT,
9
+ telemetry: Pick<TelemetryOptions, 'recordInputs' | 'recordOutputs'>,
10
+ ): EVENT {
11
+ const hideInputs = telemetry.recordInputs === false;
12
+ const hideOutputs = telemetry.recordOutputs === false;
13
+ if (
14
+ (!hideInputs && !hideOutputs) ||
15
+ event == null ||
16
+ typeof event !== 'object'
17
+ ) {
18
+ return event;
19
+ }
20
+
21
+ const filtered = Object.assign(
22
+ Object.create(Object.getPrototypeOf(event)),
23
+ event,
24
+ ) as Record<string, unknown>;
25
+ const replace = (fields: Record<string, unknown>) => {
26
+ for (const [key, value] of Object.entries(fields)) {
27
+ if (Object.hasOwn(event, key)) {
28
+ filtered[key] = value;
29
+ }
30
+ }
31
+ };
32
+
33
+ const isSpeech = filtered.operationId === 'ai.generateSpeech';
34
+ if (hideInputs) {
35
+ replace({
36
+ instructions: undefined,
37
+ system: undefined,
38
+ prompt: undefined,
39
+ messages: [],
40
+ promptMessages: [],
41
+ experimental_steeringMessages: [],
42
+ tools: undefined,
43
+ stepTools: undefined,
44
+ schema: undefined,
45
+ schemaName: undefined,
46
+ schemaDescription: undefined,
47
+ ...(typeof filtered.output === 'object' ? { output: undefined } : {}),
48
+ providerOptions: {},
49
+ value: '',
50
+ values: [],
51
+ query: '',
52
+ documents: [],
53
+ state: Array.isArray(filtered.state)
54
+ ? []
55
+ : typeof filtered.state === 'string'
56
+ ? ''
57
+ : {},
58
+ questions: {},
59
+ ...(isSpeech ? { text: '' } : {}),
60
+ });
61
+ if (filtered.toolCall != null) {
62
+ filtered.toolCall = { ...filtered.toolCall, input: undefined };
63
+ }
64
+ if (filtered.toolOutput != null) {
65
+ filtered.toolOutput = { ...filtered.toolOutput, input: undefined };
66
+ }
67
+ if (Array.isArray(filtered.ranking)) {
68
+ filtered.ranking = filtered.ranking.map(entry =>
69
+ 'document' in entry
70
+ ? { ...entry, document: typeof entry.document === 'string' ? '' : {} }
71
+ : entry,
72
+ );
73
+ }
74
+ }
75
+
76
+ if (hideOutputs) {
77
+ replace({
78
+ content: [],
79
+ ...(!isSpeech ? { text: '' } : {}),
80
+ reasoning: Array.isArray(filtered.reasoning) ? [] : undefined,
81
+ reasoningText: undefined,
82
+ files: [],
83
+ sources: [],
84
+ toolCalls: [],
85
+ staticToolCalls: [],
86
+ dynamicToolCalls: [],
87
+ toolResults: [],
88
+ staticToolResults: [],
89
+ dynamicToolResults: [],
90
+ responseMessages: [],
91
+ object: undefined,
92
+ objectText: '',
93
+ embedding: [],
94
+ embeddings: [],
95
+ ranking: [],
96
+ answers: {},
97
+ segments: [],
98
+ });
99
+ if (filtered.toolOutput != null) {
100
+ filtered.toolOutput = {
101
+ ...filtered.toolOutput,
102
+ output: undefined,
103
+ error: undefined,
104
+ };
105
+ }
106
+ }
107
+
108
+ // Raw provider payloads and errors can contain either inputs or outputs.
109
+ replace({
110
+ providerMetadata: undefined,
111
+ error:
112
+ filtered.error == null
113
+ ? filtered.error
114
+ : new Error('AI SDK operation failed'),
115
+ });
116
+ for (const key of ['toolCall', 'toolOutput'] as const) {
117
+ const toolEvent = filtered[key];
118
+ if (toolEvent != null && typeof toolEvent === 'object') {
119
+ filtered[key] = {
120
+ ...toolEvent,
121
+ providerMetadata: undefined,
122
+ ...('error' in toolEvent
123
+ ? {
124
+ error:
125
+ toolEvent.error == null
126
+ ? toolEvent.error
127
+ : new Error('AI SDK operation failed'),
128
+ }
129
+ : {}),
130
+ };
131
+ }
132
+ }
133
+ for (const key of ['request', 'response'] as const) {
134
+ const filterMetadata = (metadata: unknown) => {
135
+ if (metadata == null || typeof metadata !== 'object') {
136
+ return metadata;
137
+ }
138
+ const filteredMetadata: Record<string, unknown> = { ...metadata };
139
+ delete filteredMetadata.body;
140
+ if (key === 'request' ? hideInputs : hideOutputs) {
141
+ if ('messages' in metadata) filteredMetadata.messages = [];
142
+ if ('instructions' in metadata)
143
+ filteredMetadata.instructions = undefined;
144
+ }
145
+ return filteredMetadata;
146
+ };
147
+ const metadata = filtered[key];
148
+ if (metadata != null) {
149
+ filtered[key] = Array.isArray(metadata)
150
+ ? metadata.map(filterMetadata)
151
+ : filterMetadata(metadata);
152
+ }
153
+ }
154
+
155
+ if (Array.isArray(filtered.steps)) {
156
+ filtered.steps = filtered.steps.map(step =>
157
+ filterTelemetryEvent(step, telemetry),
158
+ );
159
+ }
160
+ if (Object.hasOwn(event, 'finalStep')) {
161
+ filtered.finalStep = filterTelemetryEvent(filtered.finalStep, telemetry);
162
+ }
163
+
164
+ return filtered as EVENT;
165
+ }
@@ -0,0 +1,25 @@
1
+ import type { LanguageModelV4GenerateResult } from '@ai-sdk/provider';
2
+
3
+ /** Remove credentials, paths, queries, and fragments before emitting telemetry. */
4
+ export function getRequestOrigin(url: string | undefined): string | undefined {
5
+ if (url == null) return undefined;
6
+
7
+ try {
8
+ const endpoint = new URL(url);
9
+ return endpoint.protocol === 'http:' || endpoint.protocol === 'https:'
10
+ ? endpoint.origin
11
+ : undefined;
12
+ } catch {
13
+ return undefined;
14
+ }
15
+ }
16
+
17
+ /** Preserve request metadata while keeping unknown or sensitive URL fields out of results. */
18
+ export function sanitizeRequestMetadata(
19
+ request: LanguageModelV4GenerateResult['request'],
20
+ ): LanguageModelV4GenerateResult['request'] {
21
+ if (request == null || !('url' in request)) return request;
22
+ const { url, ...rest } = request;
23
+ const origin = getRequestOrigin(url);
24
+ return { ...rest, ...(origin != null ? { url: origin } : {}) };
25
+ }
@@ -66,6 +66,7 @@ function loadBuiltinModule<T>(id: string): T | undefined {
66
66
  export async function runWithTracingChannelSpan<T>(
67
67
  message: TelemetryTracingChannelMessage,
68
68
  execute: () => PromiseLike<T>,
69
+ recordResult = true,
69
70
  ): Promise<T> {
70
71
  const diagnosticsChannel = await loadDiagnosticsChannel();
71
72
  const tracingChannel = diagnosticsChannel?.tracingChannel?.(
@@ -102,11 +103,21 @@ export async function runWithTracingChannelSpan<T>(
102
103
  },
103
104
  );
104
105
 
105
- return executePromise;
106
+ // tracePromise publishes its resolved value on the channel. Keep the
107
+ // application's result separately when content recording is disabled.
108
+ return recordResult
109
+ ? executePromise
110
+ : executePromise.then(
111
+ () => undefined,
112
+ () => {
113
+ throw new Error('AI SDK operation failed');
114
+ },
115
+ );
106
116
  };
107
117
 
108
118
  try {
109
- return await tracingChannel.tracePromise(tracedExecute, message);
119
+ await tracingChannel.tracePromise(tracedExecute, message);
120
+ return executionResult as T;
110
121
  } catch {
111
122
  if (hasExecutionError) {
112
123
  throw executionError;
@@ -131,9 +142,11 @@ export async function runWithTracingChannelSpan<T>(
131
142
  export function openTelemetryChannelSpanContext({
132
143
  message,
133
144
  completion,
145
+ recordResult = true,
134
146
  }: {
135
147
  message: TelemetryTracingChannelMessage;
136
148
  completion: PromiseLike<unknown>;
149
+ recordResult?: boolean;
137
150
  }): TracingChannelContext | undefined {
138
151
  if (!isNodeRuntime()) {
139
152
  Promise.resolve(completion).catch(() => {});
@@ -186,11 +199,13 @@ export function openTelemetryChannelSpanContext({
186
199
  asyncEndPublished = true;
187
200
 
188
201
  if (error !== undefined) {
189
- context.error = error;
202
+ context.error = recordResult
203
+ ? error
204
+ : new Error('AI SDK operation failed');
190
205
  safePublish(() => tracingChannel.error.publish(context));
191
206
  }
192
207
 
193
- if (result !== undefined) {
208
+ if (recordResult && result !== undefined) {
194
209
  context.result = result;
195
210
  }
196
211
 
@@ -8,21 +8,25 @@ export class MockTranscriptionModelV4 implements TranscriptionModelV4 {
8
8
 
9
9
  doGenerate: TranscriptionModelV4['doGenerate'];
10
10
  doStream: TranscriptionModelV4['doStream'];
11
+ doGenerateFromUrl: TranscriptionModelV4['doGenerateFromUrl'];
11
12
 
12
13
  constructor({
13
14
  provider = 'mock-provider',
14
15
  modelId = 'mock-model-id',
15
16
  doGenerate = notImplemented,
16
17
  doStream,
18
+ doGenerateFromUrl,
17
19
  }: {
18
20
  provider?: TranscriptionModelV4['provider'];
19
21
  modelId?: TranscriptionModelV4['modelId'];
20
22
  doGenerate?: TranscriptionModelV4['doGenerate'];
21
23
  doStream?: TranscriptionModelV4['doStream'];
24
+ doGenerateFromUrl?: TranscriptionModelV4['doGenerateFromUrl'];
22
25
  } = {}) {
23
26
  this.provider = provider;
24
27
  this.modelId = modelId;
25
28
  this.doGenerate = doGenerate;
26
29
  this.doStream = doStream;
30
+ this.doGenerateFromUrl = doGenerateFromUrl;
27
31
  }
28
32
  }
@@ -15,6 +15,7 @@ export interface TranscriptionResult {
15
15
  /**
16
16
  * Array of transcript segments with timing information.
17
17
  * Each segment represents a portion of the transcribed text with start and end times.
18
+ * Segments retain the provider's behavior and may represent individual words.
18
19
  */
19
20
  readonly segments: Array<{
20
21
  /**
@@ -31,6 +32,25 @@ export interface TranscriptionResult {
31
32
  readonly endSecond: number;
32
33
  }>;
33
34
 
35
+ /**
36
+ * Word-level timings returned by the provider, whether explicitly requested
37
+ * or returned by default. Undefined when the provider does not return them.
38
+ */
39
+ readonly words?: Array<{
40
+ /**
41
+ * The text of this word.
42
+ */
43
+ readonly text: string;
44
+ /**
45
+ * The start time of this word in seconds.
46
+ */
47
+ readonly startSecond: number;
48
+ /**
49
+ * The end time of this word in seconds.
50
+ */
51
+ readonly endSecond: number;
52
+ }>;
53
+
34
54
  /**
35
55
  * The detected language of the audio content, as an ISO-639-1 code (e.g., 'en' for English).
36
56
  * May be undefined if the language couldn't be detected.
@@ -1,7 +1,12 @@
1
- import type { JSONObject } from '@ai-sdk/provider';
1
+ import type {
2
+ JSONObject,
3
+ TranscriptionModelV4TimestampGranularity,
4
+ } from '@ai-sdk/provider';
2
5
  import {
3
6
  createIdGenerator,
4
7
  detectMediaType,
8
+ getTopLevelMediaType,
9
+ isFullMediaType,
5
10
  withUserAgentSuffix,
6
11
  type ProviderOptions,
7
12
  } from '@ai-sdk/provider-utils';
@@ -49,6 +54,7 @@ export async function transcribe({
49
54
  model,
50
55
  audio,
51
56
  providerOptions = {},
57
+ timestampGranularities,
52
58
  maxRetries: maxRetriesArg,
53
59
  abortSignal,
54
60
  headers,
@@ -82,6 +88,16 @@ export async function transcribe({
82
88
  */
83
89
  providerOptions?: ProviderOptions;
84
90
 
91
+ /**
92
+ * Word and segment timings to request.
93
+ *
94
+ * Supported adapters map this onto the provider's native control when the
95
+ * matching provider option is omitted. An explicit provider option wins.
96
+ * Supported adapters warn when they cannot return a requested granularity.
97
+ * An empty array requests no shared timing granularity; provider defaults may vary.
98
+ */
99
+ timestampGranularities?: Array<TranscriptionModelV4TimestampGranularity>;
100
+
85
101
  /**
86
102
  * Maximum number of retries per transcript model call. Set to 0 to disable retries.
87
103
  *
@@ -107,6 +123,8 @@ export async function transcribe({
107
123
 
108
124
  /**
109
125
  * Custom download function for fetching audio from URLs.
126
+ * Providing this option forces local downloading even when the provider
127
+ * supports native URL transcription.
110
128
  * Use `createDownload()` from `ai` to create a download function with custom size limits.
111
129
  *
112
130
  * @default createDownload() (2 GiB limit)
@@ -164,6 +182,7 @@ export async function transcribe({
164
182
  maxRetries,
165
183
  headers,
166
184
  providerOptions,
185
+ timestampGranularities,
167
186
  });
168
187
 
169
188
  const executeWithStartEvent = async <T>({
@@ -188,14 +207,22 @@ export async function transcribe({
188
207
 
189
208
  let preparationError: unknown;
190
209
  let preparationFailed = false;
191
- let audioData: Uint8Array;
210
+ let audioData: Uint8Array | URL;
192
211
  let downloadedMediaType: string | undefined;
193
212
 
194
213
  try {
195
214
  if (audio instanceof URL) {
196
- const downloadResult = await downloadFn({ url: audio, abortSignal });
197
- audioData = downloadResult.data;
198
- downloadedMediaType = downloadResult.mediaType;
215
+ if (
216
+ resolvedModel.doGenerateFromUrl != null &&
217
+ downloadFn === defaultDownload &&
218
+ (audio.protocol === 'https:' || audio.protocol === 'http:')
219
+ ) {
220
+ audioData = audio;
221
+ } else {
222
+ const downloadResult = await downloadFn({ url: audio, abortSignal });
223
+ audioData = downloadResult.data;
224
+ downloadedMediaType = downloadResult.mediaType;
225
+ }
199
226
  } else {
200
227
  audioData = convertDataContentToUint8Array(audio);
201
228
  }
@@ -224,15 +251,18 @@ export async function transcribe({
224
251
  }
225
252
  }
226
253
 
227
- const mediaType =
228
- downloadedMediaType ??
229
- detectMediaType({
230
- data: audioData,
231
- topLevelType: 'audio',
232
- }) ??
233
- 'audio/wav';
254
+ let mediaType =
255
+ audioData instanceof URL
256
+ ? undefined
257
+ : (getAudioMediaType(downloadedMediaType) ??
258
+ detectMediaType({
259
+ data: audioData,
260
+ topLevelType: 'audio',
261
+ }) ??
262
+ 'audio/wav');
263
+ let byteLength = audioData instanceof URL ? undefined : audioData.byteLength;
234
264
  const startEvent = createStartEvent({
235
- byteLength: audioData.byteLength,
265
+ byteLength,
236
266
  mediaType,
237
267
  });
238
268
 
@@ -240,15 +270,41 @@ export async function transcribe({
240
270
  return await executeWithStartEvent({
241
271
  startEvent,
242
272
  execute: async () => {
243
- const result = await retry(() =>
244
- resolvedModel.doGenerate({
245
- audio: audioData,
273
+ const result = await retry(async () => {
274
+ const callOptions = {
246
275
  abortSignal,
247
276
  headers: headersWithUserAgent,
248
277
  providerOptions,
249
- mediaType,
250
- }),
251
- );
278
+ ...(timestampGranularities != null
279
+ ? { timestampGranularities }
280
+ : {}),
281
+ };
282
+ if (audioData instanceof URL) {
283
+ const nativeResult = await resolvedModel.doGenerateFromUrl?.({
284
+ ...callOptions,
285
+ audio: audioData,
286
+ });
287
+ if (nativeResult != null) return nativeResult;
288
+
289
+ // A capable provider can decline an unsupported URL (for example,
290
+ // a redirect). Keep the existing secure download and file path.
291
+ const downloaded = await downloadFn({
292
+ url: audioData,
293
+ abortSignal,
294
+ });
295
+ audioData = downloaded.data;
296
+ mediaType =
297
+ getAudioMediaType(downloaded.mediaType) ??
298
+ detectMediaType({ data: audioData, topLevelType: 'audio' }) ??
299
+ 'audio/wav';
300
+ byteLength = audioData.byteLength;
301
+ }
302
+ return resolvedModel.doGenerate({
303
+ ...callOptions,
304
+ audio: audioData,
305
+ mediaType: mediaType ?? 'audio/wav',
306
+ });
307
+ });
252
308
 
253
309
  logWarnings({
254
310
  warnings: result.warnings,
@@ -268,11 +324,12 @@ export async function transcribe({
268
324
  provider: resolvedModel.provider,
269
325
  modelId: resolvedModel.modelId,
270
326
  audio: {
271
- byteLength: audioData.byteLength,
327
+ byteLength,
272
328
  mediaType,
273
329
  },
274
330
  text: result.text,
275
331
  segments: result.segments,
332
+ words: result.words,
276
333
  language: result.language,
277
334
  durationInSeconds: result.durationInSeconds,
278
335
  usage: result.usage,
@@ -289,6 +346,7 @@ export async function transcribe({
289
346
  return new DefaultTranscriptionResult({
290
347
  text: result.text,
291
348
  segments: result.segments,
349
+ words: result.words,
292
350
  language: result.language,
293
351
  durationInSeconds: result.durationInSeconds,
294
352
  warnings: result.warnings,
@@ -303,6 +361,24 @@ export async function transcribe({
303
361
  }
304
362
  }
305
363
 
364
+ /**
365
+ * Normalizes a downloaded `Content-Type` header value and returns it only
366
+ * when it is a full `audio/<subtype>` media type. Generic or mislabeled types
367
+ * (e.g. `application/octet-stream`, `binary/octet-stream`, `text/plain`)
368
+ * return `undefined` so that the media type is detected from the audio bytes
369
+ * instead.
370
+ */
371
+ function getAudioMediaType(
372
+ contentType: string | undefined,
373
+ ): string | undefined {
374
+ const mediaType = contentType?.split(';')[0].trim().toLowerCase();
375
+ return mediaType != null &&
376
+ getTopLevelMediaType(mediaType) === 'audio' &&
377
+ isFullMediaType(mediaType)
378
+ ? mediaType
379
+ : undefined;
380
+ }
381
+
306
382
  class DefaultTranscriptionResult implements TranscriptionResult {
307
383
  readonly text: string;
308
384
  readonly segments: Array<{
@@ -310,6 +386,11 @@ class DefaultTranscriptionResult implements TranscriptionResult {
310
386
  startSecond: number;
311
387
  endSecond: number;
312
388
  }>;
389
+ readonly words?: Array<{
390
+ text: string;
391
+ startSecond: number;
392
+ endSecond: number;
393
+ }>;
313
394
  readonly language: string | undefined;
314
395
  readonly durationInSeconds: number | undefined;
315
396
  readonly warnings: Array<Warning>;
@@ -323,6 +404,11 @@ class DefaultTranscriptionResult implements TranscriptionResult {
323
404
  startSecond: number;
324
405
  endSecond: number;
325
406
  }>;
407
+ words?: Array<{
408
+ text: string;
409
+ startSecond: number;
410
+ endSecond: number;
411
+ }>;
326
412
  language: string | undefined;
327
413
  durationInSeconds: number | undefined;
328
414
  warnings: Array<Warning>;
@@ -331,6 +417,7 @@ class DefaultTranscriptionResult implements TranscriptionResult {
331
417
  }) {
332
418
  this.text = options.text;
333
419
  this.segments = options.segments;
420
+ this.words = options.words;
334
421
  this.language = options.language;
335
422
  this.durationInSeconds = options.durationInSeconds;
336
423
  this.warnings = options.warnings;
@@ -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;