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
package/dist/index.js CHANGED
@@ -1,8 +1,30 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { GatewayAuthenticationError, GatewayError, createGateway, gateway, gateway as gateway$1 } from "@ai-sdk/gateway";
3
- import { DEFAULT_MAX_DOWNLOAD_SIZE, DelayedPromise, DownloadError, DownloadError as DownloadError$1, EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL, EXPERIMENTAL_EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER, asArray, asSchema, asSchema as asSchema$1, cancelResponseBody, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertUint8ArrayToBase64, createIdGenerator, createIdGenerator as createIdGenerator$1, delay, detectMediaType, dynamicTool, executeTool, experimental_getToolCaller, experimental_toolCaller, fetchUntrustedUrl, filterNullable, generateId, generateId as generateId$1, getErrorMessage, getRuntimeEnvironmentUserAgent, getWebSocketConstructor, isAbortError, isArrayBuffer, isBuffer, isExecutableTool, isFullMediaType, isNonNullable, isProviderReference, isProviderStreamError, isUint8Array, isUrlSupported, jsonSchema, jsonSchema as jsonSchema$1, lazySchema, normalizeHeaders, parseJsonEventStream, parseJsonEventStream as parseJsonEventStream$1, readResponseWithSizeLimit, readWebSocketMessageText, resolve, retryWithExponentialBackoff, safeParseJSON, safeValidateTypes, toWebSocketUrl, tool, tool as tool$1, validateTypes, waitForWebSocketBufferDrain, withUserAgentSuffix, zodSchema, zodSchema as zodSchema$1 } from "@ai-sdk/provider-utils";
3
+ import { DEFAULT_MAX_DOWNLOAD_SIZE, DelayedPromise, DownloadError, DownloadError as DownloadError$1, EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL, EXPERIMENTAL_EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER, asArray, asSchema, asSchema as asSchema$1, cancelResponseBody, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertUint8ArrayToBase64, createIdGenerator, createIdGenerator as createIdGenerator$1, delay, detectMediaType, dynamicTool, executeTool, experimental_getToolCaller, experimental_toolCaller, fetchUntrustedUrl, filterNullable, generateId, generateId as generateId$1, getErrorMessage, getRuntimeEnvironmentUserAgent, getTopLevelMediaType, getWebSocketConstructor, isAbortError, isArrayBuffer, isBuffer, isExecutableTool, isFullMediaType, isNonNullable, isProviderReference, isProviderStreamError, isUint8Array, isUrlSupported, jsonSchema, jsonSchema as jsonSchema$1, lazySchema, normalizeHeaders, parseJsonEventStream, parseJsonEventStream as parseJsonEventStream$1, readResponseWithSizeLimit, readWebSocketMessageText, resolve, retryWithExponentialBackoff, safeParseJSON, safeValidateTypes, toWebSocketUrl, tool, tool as tool$1, validateTypes, waitForWebSocketBufferDrain, withUserAgentSuffix, zodSchema, zodSchema as zodSchema$1 } from "@ai-sdk/provider-utils";
4
4
  import { AISDKError, AISDKError as AISDKError$1, APICallError, APICallError as APICallError$1, EmptyResponseBodyError, EmptyResponseBodyError as EmptyResponseBodyError$1, Experimental_DecisionRefusalError, Experimental_DecisionRefusalError as Experimental_DecisionRefusalError$1, Experimental_DecisionUnsupportedQuestionTypeError, Experimental_DecisionUnsupportedQuestionTypeError as Experimental_DecisionUnsupportedQuestionTypeError$1, InvalidPromptError, InvalidPromptError as InvalidPromptError$1, InvalidResponseDataError, InvalidResponseDataError as InvalidResponseDataError$1, JSONParseError, JSONParseError as JSONParseError$1, LoadAPIKeyError, LoadSettingError, NoContentGeneratedError, NoSuchModelError, NoSuchModelError as NoSuchModelError$1, NoSuchProviderReferenceError, TooManyEmbeddingValuesForCallError, TypeValidationError, TypeValidationError as TypeValidationError$1, UnsupportedFunctionalityError, UnsupportedFunctionalityError as UnsupportedFunctionalityError$1, getErrorMessage as getErrorMessage$1, isJSONArray, isJSONObject } from "@ai-sdk/provider";
5
5
  import { array, boolean, custom, discriminatedUnion, enum as enum$1, instanceof as instanceof$1, lazy, literal, looseObject, never, null as null$1, number, object, record, string, union, unknown } from "zod/v4";
6
+ //#region src/telemetry/get-request-origin.ts
7
+ /** Remove credentials, paths, queries, and fragments before emitting telemetry. */
8
+ function getRequestOrigin(url) {
9
+ if (url == null) return void 0;
10
+ try {
11
+ const endpoint = new URL(url);
12
+ return endpoint.protocol === "http:" || endpoint.protocol === "https:" ? endpoint.origin : void 0;
13
+ } catch {
14
+ return;
15
+ }
16
+ }
17
+ /** Preserve request metadata while keeping unknown or sensitive URL fields out of results. */
18
+ function sanitizeRequestMetadata(request) {
19
+ if (request == null || !("url" in request)) return request;
20
+ const { url, ...rest } = request;
21
+ const origin = getRequestOrigin(url);
22
+ return {
23
+ ...rest,
24
+ ...origin != null ? { url: origin } : {}
25
+ };
26
+ }
27
+ //#endregion
6
28
  //#region src/error/invalid-argument-error.ts
7
29
  const name$23 = "AI_InvalidArgumentError";
8
30
  const marker$23 = `vercel.ai.error.${name$23}`;
@@ -937,6 +959,18 @@ function asTranscriptionModelV4(model) {
937
959
  const v3Model = model.specificationVersion === "v2" ? asTranscriptionModelV3(model) : model;
938
960
  return new Proxy(v3Model, { get(target, prop) {
939
961
  if (prop === "specificationVersion") return "v4";
962
+ if (prop === "doGenerate") return async ({ timestampGranularities, ...options }) => {
963
+ const result = await target.doGenerate.call(model, options);
964
+ if (!timestampGranularities?.length) return result;
965
+ return {
966
+ ...result,
967
+ warnings: [...result.warnings, {
968
+ type: "unsupported",
969
+ feature: "timestampGranularities",
970
+ details: `Shared timestamp granularities are not supported by ${model.specificationVersion} transcription models.`
971
+ }]
972
+ };
973
+ };
940
974
  return target[prop];
941
975
  } });
942
976
  }
@@ -1207,7 +1241,7 @@ function cloneValue(value, seen) {
1207
1241
  }
1208
1242
  //#endregion
1209
1243
  //#region src/version.ts
1210
- const VERSION = "7.0.162";
1244
+ const VERSION = "7.0.164";
1211
1245
  //#endregion
1212
1246
  //#region src/util/download/download.ts
1213
1247
  /**
@@ -1670,12 +1704,18 @@ async function downloadAssets(messages, download, supportedUrls) {
1670
1704
  if (message.role === "tool") for (const part of message.content) {
1671
1705
  if (part.type !== "tool-result") continue;
1672
1706
  if (part.output.type !== "content") continue;
1673
- for (const contentPart of part.output.value) if (contentPart.type === "file") downloadableFiles.push(contentPart);
1707
+ for (const contentPart of part.output.value) {
1708
+ const filePart = getDownloadableFilePart(contentPart);
1709
+ if (filePart != null) downloadableFiles.push(filePart);
1710
+ }
1674
1711
  }
1675
1712
  if (message.role === "assistant" && Array.isArray(message.content)) for (const part of message.content) {
1676
1713
  if (part.type !== "tool-result") continue;
1677
1714
  if (part.output.type !== "content") continue;
1678
- for (const contentPart of part.output.value) if (contentPart.type === "file") downloadableFiles.push(contentPart);
1715
+ for (const contentPart of part.output.value) {
1716
+ const filePart = getDownloadableFilePart(contentPart);
1717
+ if (filePart != null) downloadableFiles.push(filePart);
1718
+ }
1679
1719
  }
1680
1720
  }
1681
1721
  const plannedDownloads = downloadableFiles.map((part) => {
@@ -1700,6 +1740,57 @@ async function downloadAssets(messages, download, supportedUrls) {
1700
1740
  }]).filter((file) => file != null));
1701
1741
  }
1702
1742
  /**
1743
+ * Resolves the tool result content parts that point at a remote file to the
1744
+ * tagged file shape, including the deprecated `file-url` and `image-url`
1745
+ * types, so that they are downloaded and inlined exactly like their `file`
1746
+ * replacement. Returns `undefined` for content that is already inline or
1747
+ * provider-referenced.
1748
+ */
1749
+ function getDownloadableFilePart(contentPart) {
1750
+ switch (contentPart.type) {
1751
+ case "file": return contentPart;
1752
+ case "file-url": return {
1753
+ type: "file",
1754
+ data: {
1755
+ type: "url",
1756
+ url: new URL(contentPart.url)
1757
+ },
1758
+ mediaType: contentPart.mediaType ?? getMediaTypeFromUrl(contentPart.url),
1759
+ providerOptions: contentPart.providerOptions
1760
+ };
1761
+ case "image-url": return {
1762
+ type: "file",
1763
+ data: {
1764
+ type: "url",
1765
+ url: new URL(contentPart.url)
1766
+ },
1767
+ mediaType: "image",
1768
+ providerOptions: contentPart.providerOptions
1769
+ };
1770
+ default: return;
1771
+ }
1772
+ }
1773
+ /**
1774
+ * Resolves file data and media type for a remote tool result content part: the downloaded
1775
+ * bytes when the asset was fetched, otherwise the URL reference. `originalUrl`
1776
+ * is preserved when the URL string does not round-trip through `URL`.
1777
+ */
1778
+ function resolveDownloadedFile({ url, originalUrl, downloadedAssets, mediaType }) {
1779
+ const convertedPart = convertPartToLanguageModelPart({
1780
+ type: "file",
1781
+ data: {
1782
+ type: "url",
1783
+ url,
1784
+ ...url.toString() !== originalUrl ? { originalUrl } : {}
1785
+ },
1786
+ mediaType
1787
+ }, downloadedAssets);
1788
+ return {
1789
+ data: convertedPart.data,
1790
+ mediaType: convertedPart.mediaType
1791
+ };
1792
+ }
1793
+ /**
1703
1794
  * Convert part of a user message to a LanguageModelV4Part.
1704
1795
  *
1705
1796
  * @param part - The part to convert.
@@ -1784,12 +1875,12 @@ function mapToolResultOutput({ output, provider, warnings = [], downloadedAssets
1784
1875
  });
1785
1876
  return {
1786
1877
  type: "file",
1787
- data: {
1788
- type: "url",
1878
+ ...resolveDownloadedFile({
1789
1879
  url,
1790
- ...url.toString() !== item.url ? { originalUrl: item.url } : {}
1791
- },
1792
- mediaType,
1880
+ originalUrl: item.url,
1881
+ downloadedAssets,
1882
+ mediaType
1883
+ }),
1793
1884
  providerOptions: item.providerOptions
1794
1885
  };
1795
1886
  }
@@ -1850,12 +1941,12 @@ function mapToolResultOutput({ output, provider, warnings = [], downloadedAssets
1850
1941
  });
1851
1942
  return {
1852
1943
  type: "file",
1853
- data: {
1854
- type: "url",
1944
+ ...resolveDownloadedFile({
1855
1945
  url,
1856
- ...url.toString() !== item.url ? { originalUrl: item.url } : {}
1857
- },
1858
- mediaType: "image",
1946
+ originalUrl: item.url,
1947
+ downloadedAssets,
1948
+ mediaType: "image"
1949
+ }),
1859
1950
  providerOptions: item.providerOptions
1860
1951
  };
1861
1952
  }
@@ -3401,17 +3492,7 @@ const text = () => ({
3401
3492
  },
3402
3493
  createElementStreamTransform() {}
3403
3494
  });
3404
- /**
3405
- * Output specification for typed object generation using schemas.
3406
- * When the model generates a text response, it will return an object that matches the schema.
3407
- *
3408
- * @param schema - The schema of the object to generate.
3409
- * @param name - Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name.
3410
- * @param description - Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description.
3411
- *
3412
- * @returns An output specification for generating objects with the specified schema.
3413
- */
3414
- const object$1 = ({ schema: inputSchema, name, description }) => {
3495
+ function object$1({ schema: inputSchema, name, description }) {
3415
3496
  const schema = asSchema$1(inputSchema);
3416
3497
  return {
3417
3498
  name: "object",
@@ -3456,20 +3537,8 @@ const object$1 = ({ schema: inputSchema, name, description }) => {
3456
3537
  },
3457
3538
  createElementStreamTransform() {}
3458
3539
  };
3459
- };
3460
- /**
3461
- * Output specification for array generation.
3462
- * When the model generates a text response, it will return an array of elements.
3463
- *
3464
- * @param element - The schema of the array elements to generate.
3465
- * @param minItems - Optional minimum number of elements to generate.
3466
- * @param maxItems - Optional maximum number of elements to generate.
3467
- * @param name - Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name.
3468
- * @param description - Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description.
3469
- *
3470
- * @returns An output specification for generating an array of elements.
3471
- */
3472
- const array$1 = ({ element: inputElementSchema, minItems, maxItems, name, description }) => {
3540
+ }
3541
+ function array$1({ element: inputElementSchema, minItems, maxItems, name, description }) {
3473
3542
  validateArrayBound({
3474
3543
  name: "minItems",
3475
3544
  value: minItems
@@ -3599,7 +3668,7 @@ const array$1 = ({ element: inputElementSchema, minItems, maxItems, name, descri
3599
3668
  } });
3600
3669
  }
3601
3670
  };
3602
- };
3671
+ }
3603
3672
  function validateArrayBound({ name, value }) {
3604
3673
  if (value == null) return;
3605
3674
  if (!Number.isInteger(value)) throw new InvalidArgumentError({
@@ -4064,7 +4133,7 @@ function loadBuiltinModule(id) {
4064
4133
  * if tracing itself throws, and prevents falling back by calling `execute` a
4065
4134
  * second time.
4066
4135
  */
4067
- async function runWithTracingChannelSpan(message, execute) {
4136
+ async function runWithTracingChannelSpan(message, execute, recordResult = true) {
4068
4137
  const tracingChannel = (await loadDiagnosticsChannel())?.tracingChannel?.(AI_SDK_TELEMETRY_TRACING_CHANNEL);
4069
4138
  if (tracingChannel == null || tracingChannel.hasSubscribers === false) return await execute();
4070
4139
  let executePromise;
@@ -4087,10 +4156,13 @@ async function runWithTracingChannelSpan(message, execute) {
4087
4156
  hasExecutionError = true;
4088
4157
  throw error;
4089
4158
  });
4090
- return executePromise;
4159
+ return recordResult ? executePromise : executePromise.then(() => void 0, () => {
4160
+ throw new Error("AI SDK operation failed");
4161
+ });
4091
4162
  };
4092
4163
  try {
4093
- return await tracingChannel.tracePromise(tracedExecute, message);
4164
+ await tracingChannel.tracePromise(tracedExecute, message);
4165
+ return executionResult;
4094
4166
  } catch {
4095
4167
  if (hasExecutionError) throw executionError;
4096
4168
  if (hasExecutionResult) return executionResult;
@@ -4102,7 +4174,7 @@ async function runWithTracingChannelSpan(message, execute) {
4102
4174
  * Opens a long-lived tracing-channel span context and returns a runner that can
4103
4175
  * re-enter that context later without changing stream setup timing.
4104
4176
  */
4105
- function openTelemetryChannelSpanContext({ message, completion }) {
4177
+ function openTelemetryChannelSpanContext({ message, completion, recordResult = true }) {
4106
4178
  if (!isNodeRuntime()) {
4107
4179
  Promise.resolve(completion).catch(() => {});
4108
4180
  return;
@@ -4126,10 +4198,10 @@ function openTelemetryChannelSpanContext({ message, completion }) {
4126
4198
  if (asyncEndPublished) return;
4127
4199
  asyncEndPublished = true;
4128
4200
  if (error !== void 0) {
4129
- context.error = error;
4201
+ context.error = recordResult ? error : /* @__PURE__ */ new Error("AI SDK operation failed");
4130
4202
  safePublish(() => tracingChannel.error.publish(context));
4131
4203
  }
4132
- if (result !== void 0) context.result = result;
4204
+ if (recordResult && result !== void 0) context.result = result;
4133
4205
  safePublish(() => tracingChannel.asyncEnd.publish(context));
4134
4206
  };
4135
4207
  safePublish(() => {
@@ -4154,6 +4226,116 @@ function getGlobalTelemetryIntegrations() {
4154
4226
  return globalThis.AI_SDK_TELEMETRY_INTEGRATIONS ?? [];
4155
4227
  }
4156
4228
  //#endregion
4229
+ //#region src/telemetry/filter-telemetry-event.ts
4230
+ /**
4231
+ * Filters SDK-owned content fields on a copy. Only descend into SDK event
4232
+ * containers; user context has its own inclusion policy.
4233
+ */
4234
+ function filterTelemetryEvent(event, telemetry) {
4235
+ const hideInputs = telemetry.recordInputs === false;
4236
+ const hideOutputs = telemetry.recordOutputs === false;
4237
+ if (!hideInputs && !hideOutputs || event == null || typeof event !== "object") return event;
4238
+ const filtered = Object.assign(Object.create(Object.getPrototypeOf(event)), event);
4239
+ const replace = (fields) => {
4240
+ for (const [key, value] of Object.entries(fields)) if (Object.hasOwn(event, key)) filtered[key] = value;
4241
+ };
4242
+ const isSpeech = filtered.operationId === "ai.generateSpeech";
4243
+ if (hideInputs) {
4244
+ replace({
4245
+ instructions: void 0,
4246
+ system: void 0,
4247
+ prompt: void 0,
4248
+ messages: [],
4249
+ promptMessages: [],
4250
+ experimental_steeringMessages: [],
4251
+ tools: void 0,
4252
+ stepTools: void 0,
4253
+ schema: void 0,
4254
+ schemaName: void 0,
4255
+ schemaDescription: void 0,
4256
+ ...typeof filtered.output === "object" ? { output: void 0 } : {},
4257
+ providerOptions: {},
4258
+ value: "",
4259
+ values: [],
4260
+ query: "",
4261
+ documents: [],
4262
+ state: Array.isArray(filtered.state) ? [] : typeof filtered.state === "string" ? "" : {},
4263
+ questions: {},
4264
+ ...isSpeech ? { text: "" } : {}
4265
+ });
4266
+ if (filtered.toolCall != null) filtered.toolCall = {
4267
+ ...filtered.toolCall,
4268
+ input: void 0
4269
+ };
4270
+ if (filtered.toolOutput != null) filtered.toolOutput = {
4271
+ ...filtered.toolOutput,
4272
+ input: void 0
4273
+ };
4274
+ if (Array.isArray(filtered.ranking)) filtered.ranking = filtered.ranking.map((entry) => "document" in entry ? {
4275
+ ...entry,
4276
+ document: typeof entry.document === "string" ? "" : {}
4277
+ } : entry);
4278
+ }
4279
+ if (hideOutputs) {
4280
+ replace({
4281
+ content: [],
4282
+ ...!isSpeech ? { text: "" } : {},
4283
+ reasoning: Array.isArray(filtered.reasoning) ? [] : void 0,
4284
+ reasoningText: void 0,
4285
+ files: [],
4286
+ sources: [],
4287
+ toolCalls: [],
4288
+ staticToolCalls: [],
4289
+ dynamicToolCalls: [],
4290
+ toolResults: [],
4291
+ staticToolResults: [],
4292
+ dynamicToolResults: [],
4293
+ responseMessages: [],
4294
+ object: void 0,
4295
+ objectText: "",
4296
+ embedding: [],
4297
+ embeddings: [],
4298
+ ranking: [],
4299
+ answers: {},
4300
+ segments: []
4301
+ });
4302
+ if (filtered.toolOutput != null) filtered.toolOutput = {
4303
+ ...filtered.toolOutput,
4304
+ output: void 0,
4305
+ error: void 0
4306
+ };
4307
+ }
4308
+ replace({
4309
+ providerMetadata: void 0,
4310
+ error: filtered.error == null ? filtered.error : /* @__PURE__ */ new Error("AI SDK operation failed")
4311
+ });
4312
+ for (const key of ["toolCall", "toolOutput"]) {
4313
+ const toolEvent = filtered[key];
4314
+ if (toolEvent != null && typeof toolEvent === "object") filtered[key] = {
4315
+ ...toolEvent,
4316
+ providerMetadata: void 0,
4317
+ ..."error" in toolEvent ? { error: toolEvent.error == null ? toolEvent.error : /* @__PURE__ */ new Error("AI SDK operation failed") } : {}
4318
+ };
4319
+ }
4320
+ for (const key of ["request", "response"]) {
4321
+ const filterMetadata = (metadata) => {
4322
+ if (metadata == null || typeof metadata !== "object") return metadata;
4323
+ const filteredMetadata = { ...metadata };
4324
+ delete filteredMetadata.body;
4325
+ if (key === "request" ? hideInputs : hideOutputs) {
4326
+ if ("messages" in metadata) filteredMetadata.messages = [];
4327
+ if ("instructions" in metadata) filteredMetadata.instructions = void 0;
4328
+ }
4329
+ return filteredMetadata;
4330
+ };
4331
+ const metadata = filtered[key];
4332
+ if (metadata != null) filtered[key] = Array.isArray(metadata) ? metadata.map(filterMetadata) : filterMetadata(metadata);
4333
+ }
4334
+ if (Array.isArray(filtered.steps)) filtered.steps = filtered.steps.map((step) => filterTelemetryEvent(step, telemetry));
4335
+ if (Object.hasOwn(event, "finalStep")) filtered.finalStep = filterTelemetryEvent(filtered.finalStep, telemetry);
4336
+ return filtered;
4337
+ }
4338
+ //#endregion
4157
4339
  //#region src/telemetry/create-telemetry-dispatcher.ts
4158
4340
  function augmentEvent(event, telemetry, filterContext = false) {
4159
4341
  const augmentedEvent = Object.assign(Object.create(Object.getPrototypeOf(event)), event, {
@@ -4177,7 +4359,7 @@ function augmentEvent(event, telemetry, filterContext = false) {
4177
4359
  includeToolsContext: telemetry.includeToolsContext
4178
4360
  });
4179
4361
  }
4180
- return augmentedEvent;
4362
+ return filterTelemetryEvent(augmentedEvent, telemetry);
4181
4363
  }
4182
4364
  /**
4183
4365
  * Creates a telemetry dispatcher that sends telemetry events
@@ -4203,6 +4385,7 @@ function createTelemetryDispatcher({ telemetry }) {
4203
4385
  includeRuntimeContext: telemetry?.includeRuntimeContext,
4204
4386
  includeToolsContext: telemetry?.includeToolsContext
4205
4387
  };
4388
+ const recordResult = telemetry?.recordInputs !== false && telemetry?.recordOutputs !== false;
4206
4389
  const mergeTelemetryCallback = (key, deprecatedKey) => {
4207
4390
  const integrationCallbacks = integrations.map((integration) => {
4208
4391
  const callback = integration[key] ?? (deprecatedKey == null ? void 0 : integration[deprecatedKey]);
@@ -4222,13 +4405,14 @@ function createTelemetryDispatcher({ telemetry }) {
4222
4405
  runInTracingChannelSpan: async ({ type, event, execute }) => await runWithTracingChannelSpan({
4223
4406
  type,
4224
4407
  event: augmentEvent(event, telemetryMetadata, true)
4225
- }, execute),
4408
+ }, execute, recordResult),
4226
4409
  startTracingChannelContext: ({ type, event, completion }) => openTelemetryChannelSpanContext({
4227
4410
  message: {
4228
4411
  type,
4229
4412
  event: augmentEvent(event, telemetryMetadata, true)
4230
4413
  },
4231
- completion
4414
+ completion,
4415
+ recordResult
4232
4416
  }),
4233
4417
  onStart: mergeTelemetryCallback("onStart"),
4234
4418
  onStepStart: mergeTelemetryCallback("onStepStart"),
@@ -4270,7 +4454,7 @@ function createTelemetryDispatcher({ telemetry }) {
4270
4454
  return await runWithTracingChannelSpan({
4271
4455
  type: "languageModelCall",
4272
4456
  event: augmentedEvent
4273
- }, wrappedExecute);
4457
+ }, wrappedExecute, recordResult);
4274
4458
  },
4275
4459
  /**
4276
4460
  * Composes all `executeTool` wrappers around the original tool execution.
@@ -4559,7 +4743,10 @@ var DefaultSteering = class {
4559
4743
  message,
4560
4744
  sentMessages
4561
4745
  })) {
4562
- delivered.push(message);
4746
+ delivered.push({
4747
+ id,
4748
+ message
4749
+ });
4563
4750
  resolve({
4564
4751
  type: "delivered",
4565
4752
  id,
@@ -4722,7 +4909,7 @@ async function toResponseMessages({ content: inputContent, tools }) {
4722
4909
  for (const part of inputContent) {
4723
4910
  if (part.type === "source") continue;
4724
4911
  if ((part.type === "tool-result" || part.type === "tool-error") && !part.providerExecuted) continue;
4725
- if (part.type === "text" && part.text.length === 0) continue;
4912
+ if (part.type === "text" && part.text.length === 0 && part.providerMetadata == null) continue;
4726
4913
  switch (part.type) {
4727
4914
  case "text":
4728
4915
  content.push({
@@ -5472,10 +5659,10 @@ async function generateTextInternal({ model: modelArg, tools, toolChoice, instru
5472
5659
  messages: prepareStepResult?.messages ?? stepInputMessages,
5473
5660
  toolCallerMessages
5474
5661
  });
5475
- const deliveredSteeringMessages = steeringRun?.resolveTakenMessages({
5662
+ const deliveredSteeringMessages = (steeringRun?.resolveTakenMessages({
5476
5663
  stepNumber,
5477
5664
  sentMessages: stepMessages
5478
- }) ?? [];
5665
+ }) ?? []).map(({ message }) => message);
5479
5666
  const promptMessages = await convertToLanguageModelPrompt({
5480
5667
  prompt: {
5481
5668
  instructions: stepInstructions,
@@ -5557,6 +5744,7 @@ async function generateTextInternal({ model: modelArg, tools, toolChoice, instru
5557
5744
  };
5558
5745
  return {
5559
5746
  ...result,
5747
+ ...result.request != null ? { request: sanitizeRequestMetadata(result.request) } : {},
5560
5748
  response: responseData
5561
5749
  };
5562
5750
  });
@@ -5594,6 +5782,7 @@ async function generateTextInternal({ model: modelArg, tools, toolChoice, instru
5594
5782
  usage: stepUsage,
5595
5783
  content: modelCallContent,
5596
5784
  responseId: currentModelResponse.response.id,
5785
+ ...currentModelResponse.request?.url != null ? { request: { url: getRequestOrigin(currentModelResponse.request.url) } } : {},
5597
5786
  ...currentModelResponse.providerMetadata != null ? { providerMetadata: currentModelResponse.providerMetadata } : {},
5598
5787
  performance: {
5599
5788
  responseTimeMs,
@@ -6435,6 +6624,22 @@ const uiMessageChunkSchema = lazySchema(() => zodSchema$1(z.union([
6435
6624
  mediaType: z.string(),
6436
6625
  providerMetadata: providerMetadataSchema.optional()
6437
6626
  }),
6627
+ z.looseObject({
6628
+ type: z.literal("steering-message"),
6629
+ id: z.string(),
6630
+ parts: z.array(z.union([z.looseObject({
6631
+ type: z.literal("text"),
6632
+ text: z.string(),
6633
+ providerMetadata: providerMetadataSchema.optional()
6634
+ }), z.looseObject({
6635
+ type: z.literal("file"),
6636
+ mediaType: z.string(),
6637
+ url: z.string(),
6638
+ filename: z.string().optional(),
6639
+ providerReference: z.record(z.string(), z.string()).optional(),
6640
+ providerMetadata: providerMetadataSchema.optional()
6641
+ })]))
6642
+ }),
6438
6643
  z.looseObject({
6439
6644
  type: z.custom((value) => typeof value === "string" && value.startsWith("data-"), { message: "Type must start with \"data-\"" }),
6440
6645
  id: z.string().optional(),
@@ -7078,6 +7283,14 @@ function processUIMessageStream({ stream, messageMetadataSchema, dataPartSchemas
7078
7283
  write();
7079
7284
  break;
7080
7285
  }
7286
+ case "steering-message":
7287
+ state.message.parts.push({
7288
+ type: "steering-message",
7289
+ id: chunk.id,
7290
+ parts: chunk.parts
7291
+ });
7292
+ write();
7293
+ break;
7081
7294
  case "start-step":
7082
7295
  state.message.parts.push({ type: "step-start" });
7083
7296
  break;
@@ -7425,6 +7638,11 @@ function toUIMessageChunk(part, { tools, sendReasoning = true, sendSources = fal
7425
7638
  type: "error",
7426
7639
  errorText: onError(part.error)
7427
7640
  };
7641
+ case "steering-message": return {
7642
+ type: "steering-message",
7643
+ id: part.id,
7644
+ parts: convertUserMessageToUIParts(part.message)
7645
+ };
7428
7646
  case "start-step": return { type: "start-step" };
7429
7647
  case "finish-step": return { type: "finish-step" };
7430
7648
  case "start":
@@ -7443,10 +7661,53 @@ function toUIMessageChunk(part, { tools, sendReasoning = true, sendSources = fal
7443
7661
  };
7444
7662
  case "abort": return part;
7445
7663
  case "tool-input-end":
7664
+ case "ping":
7446
7665
  case "raw": return;
7447
7666
  default: throw new Error(`Unknown chunk type: ${partType}`);
7448
7667
  }
7449
7668
  }
7669
+ function convertUserMessageToUIParts(message) {
7670
+ if (typeof message.content === "string") return [{
7671
+ type: "text",
7672
+ text: message.content
7673
+ }];
7674
+ return message.content.map((part) => {
7675
+ const providerMetadata = part.providerOptions != null ? { providerMetadata: part.providerOptions } : {};
7676
+ if (part.type === "text") return {
7677
+ type: "text",
7678
+ text: part.text,
7679
+ ...providerMetadata
7680
+ };
7681
+ const { data, mediaType: dataUrlMediaType } = convertToLanguageModelV4FilePart(part.type === "image" ? part.image : part.data);
7682
+ const mediaType = dataUrlMediaType ?? part.mediaType ?? "image";
7683
+ const filename = part.type === "file" ? part.filename : void 0;
7684
+ const file = {
7685
+ type: "file",
7686
+ mediaType,
7687
+ ...filename != null ? { filename } : {},
7688
+ ...providerMetadata
7689
+ };
7690
+ switch (data.type) {
7691
+ case "url": return {
7692
+ ...file,
7693
+ url: data.url.toString()
7694
+ };
7695
+ case "data": return {
7696
+ ...file,
7697
+ url: `data:${mediaType};base64,${convertDataContentToBase64String(data.data)}`
7698
+ };
7699
+ case "text": return {
7700
+ ...file,
7701
+ url: `data:${mediaType};base64,${convertUint8ArrayToBase64(new TextEncoder().encode(data.text))}`
7702
+ };
7703
+ case "reference": return {
7704
+ ...file,
7705
+ url: "",
7706
+ providerReference: data.reference
7707
+ };
7708
+ }
7709
+ });
7710
+ }
7450
7711
  //#endregion
7451
7712
  //#region src/ui-message-stream/to-ui-message-stream.ts
7452
7713
  /**
@@ -7979,6 +8240,7 @@ const isOutputChunkType = {
7979
8240
  "model-call-response-metadata": false,
7980
8241
  "model-call-end": false,
7981
8242
  error: false,
8243
+ ping: false,
7982
8244
  raw: false
7983
8245
  };
7984
8246
  function isOutputChunk$1(chunk) {
@@ -8284,7 +8546,7 @@ async function streamLanguageModelCall({ model, tools, toolOrder, output, toolCh
8284
8546
  callbacks: onLanguageModelCallStart
8285
8547
  });
8286
8548
  const callStartTimestampMs = now$3();
8287
- const { stream: languageModelStream, response, request } = await executeLanguageModelCallInTelemetryContext({
8549
+ const { stream: languageModelStream, response, request: rawRequest } = await executeLanguageModelCallInTelemetryContext({
8288
8550
  ...languageModelCallStartEvent,
8289
8551
  execute: async () => await resolvedModel.doStream({
8290
8552
  ...callSettings,
@@ -8298,6 +8560,7 @@ async function streamLanguageModelCall({ model, tools, toolOrder, output, toolCh
8298
8560
  includeRawChunks
8299
8561
  })
8300
8562
  });
8563
+ const request = sanitizeRequestMetadata(rawRequest);
8301
8564
  return {
8302
8565
  stream: createAsyncIterableStream(languageModelStream.pipeThrough(createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({
8303
8566
  tools,
@@ -8313,6 +8576,7 @@ async function streamLanguageModelCall({ model, tools, toolOrder, output, toolCh
8313
8576
  generateId,
8314
8577
  now: now$3,
8315
8578
  callStartTimestampMs,
8579
+ request,
8316
8580
  onLanguageModelCallEnd,
8317
8581
  collectContent
8318
8582
  }))),
@@ -8320,7 +8584,7 @@ async function streamLanguageModelCall({ model, tools, toolOrder, output, toolCh
8320
8584
  request
8321
8585
  };
8322
8586
  }
8323
- function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({ tools, instructions, messages, repairToolCall, refineToolInput, abortSignal, callId, provider, modelId, toolChoice, generateId, now, callStartTimestampMs, onLanguageModelCallEnd, collectContent }) {
8587
+ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({ tools, instructions, messages, repairToolCall, refineToolInput, abortSignal, callId, provider, modelId, toolChoice, generateId, now, callStartTimestampMs, request, onLanguageModelCallEnd, collectContent }) {
8324
8588
  const toolCallsByToolCallId = /* @__PURE__ */ new Map();
8325
8589
  const modelCallContent = [];
8326
8590
  const rawModelCallContent = [];
@@ -8498,6 +8762,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({ too
8498
8762
  usage,
8499
8763
  content: modelCallContent,
8500
8764
  responseId,
8765
+ ...request?.url != null ? { request: { url: getRequestOrigin(request.url) } } : {},
8501
8766
  ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {},
8502
8767
  performance
8503
8768
  },
@@ -9792,10 +10057,20 @@ var DefaultStreamTextResult = class {
9792
10057
  toolCallerMessages
9793
10058
  });
9794
10059
  currentStepMessages = stepMessages;
9795
- currentStepSteeringMessages = steeringRun?.resolveTakenMessages({
10060
+ const deliveredSteeringMessages = steeringRun?.resolveTakenMessages({
9796
10061
  stepNumber: currentStep,
9797
10062
  sentMessages: stepMessages
9798
10063
  }) ?? [];
10064
+ currentStepSteeringMessages = deliveredSteeringMessages.map(({ message }) => message);
10065
+ if (deliveredSteeringMessages.length > 0) self.addStream(new ReadableStream({ start(controller) {
10066
+ for (const { id, message } of deliveredSteeringMessages) controller.enqueue({
10067
+ type: "steering-message",
10068
+ id,
10069
+ message,
10070
+ stepNumber: currentStep
10071
+ });
10072
+ controller.close();
10073
+ } }));
9799
10074
  const stepInstructions = prepareStepResult?.instructions ?? prepareStepResult?.system ?? instructionsForNextStep;
9800
10075
  instructionsForNextStep = stepInstructions;
9801
10076
  const stepProviderOptions = mergeObjects(providerOptions, prepareStepResult?.providerOptions);
@@ -9940,7 +10215,7 @@ var DefaultStreamTextResult = class {
9940
10215
  clearFirstChunkTimeout();
9941
10216
  resetChunkTimeout();
9942
10217
  }
9943
- if (shouldBufferToolParts && value.type !== "error" && (isToolPart || bufferedAttemptParts.length > 0)) {
10218
+ if (shouldBufferToolParts && value.type !== "error" && value.type !== "ping" && (isToolPart || bufferedAttemptParts.length > 0)) {
9944
10219
  bufferedAttemptParts.push(value);
9945
10220
  continue;
9946
10221
  }
@@ -10105,6 +10380,7 @@ var DefaultStreamTextResult = class {
10105
10380
  case "tool-input-end":
10106
10381
  case "tool-input-delta":
10107
10382
  case "tool-approval-request":
10383
+ case "ping":
10108
10384
  case "tool-output-denied":
10109
10385
  enqueueStepPart(controller, chunk);
10110
10386
  break;
@@ -11043,24 +11319,7 @@ async function convertToModelMessages(messages, options) {
11043
11319
  modelMessages.push({
11044
11320
  role: "user",
11045
11321
  content: message.parts.map((part) => {
11046
- if (isTextUIPart(part)) return {
11047
- type: "text",
11048
- text: part.text,
11049
- ...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
11050
- };
11051
- if (isFileUIPart(part)) return {
11052
- type: "file",
11053
- mediaType: part.mediaType,
11054
- filename: part.filename,
11055
- data: part.providerReference != null ? {
11056
- type: "reference",
11057
- reference: part.providerReference
11058
- } : {
11059
- type: "url",
11060
- url: new URL(part.url)
11061
- },
11062
- ...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
11063
- };
11322
+ if (isTextUIPart(part) || isFileUIPart(part)) return convertUserContentUIPart(part);
11064
11323
  if (isDataUIPart(part)) return options?.convertDataPart?.(part);
11065
11324
  }).filter(isNonNullable)
11066
11325
  });
@@ -11216,6 +11475,13 @@ async function convertToModelMessages(messages, options) {
11216
11475
  }
11217
11476
  for (const part of message.parts) if (isCustomContentUIPart(part) || isTextUIPart(part) || isReasoningUIPart(part) || isReasoningFileUIPart(part) || isFileUIPart(part) || isToolUIPart(part) || isDataUIPart(part)) block.push(part);
11218
11477
  else if (part.type === "step-start") await processBlock();
11478
+ else if (part.type === "steering-message") {
11479
+ await processBlock();
11480
+ modelMessages.push({
11481
+ role: "user",
11482
+ content: part.parts.map(convertUserContentUIPart)
11483
+ });
11484
+ }
11219
11485
  await processBlock();
11220
11486
  break;
11221
11487
  }
@@ -11230,6 +11496,26 @@ async function convertToModelMessages(messages, options) {
11230
11496
  }
11231
11497
  return modelMessages;
11232
11498
  }
11499
+ function convertUserContentUIPart(part) {
11500
+ if (part.type === "text") return {
11501
+ type: "text",
11502
+ text: part.text,
11503
+ ...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
11504
+ };
11505
+ return {
11506
+ type: "file",
11507
+ mediaType: part.mediaType,
11508
+ filename: part.filename,
11509
+ data: part.providerReference != null ? {
11510
+ type: "reference",
11511
+ reference: part.providerReference
11512
+ } : {
11513
+ type: "url",
11514
+ url: new URL(part.url)
11515
+ },
11516
+ ...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
11517
+ };
11518
+ }
11233
11519
  //#endregion
11234
11520
  //#region src/ui/validate-ui-messages.ts
11235
11521
  const toolMetadataSchema = z.record(z.string(), jsonValueSchema.optional());
@@ -11322,6 +11608,22 @@ const uiMessagesSchema = lazySchema(() => {
11322
11608
  url: z.string(),
11323
11609
  providerMetadata: providerMetadataSchema.optional()
11324
11610
  }),
11611
+ z.object({
11612
+ type: z.literal("steering-message"),
11613
+ id: z.string(),
11614
+ parts: z.array(z.union([z.object({
11615
+ type: z.literal("text"),
11616
+ text: z.string(),
11617
+ providerMetadata: providerMetadataSchema.optional()
11618
+ }), z.object({
11619
+ type: z.literal("file"),
11620
+ mediaType: z.string(),
11621
+ filename: z.string().optional(),
11622
+ url: z.string(),
11623
+ providerReference: providerReferenceSchema$1.optional(),
11624
+ providerMetadata: providerMetadataSchema.optional()
11625
+ })]))
11626
+ }),
11325
11627
  z.object({ type: z.literal("step-start") }),
11326
11628
  z.object({
11327
11629
  type: z.string().startsWith("data-"),
@@ -13864,7 +14166,7 @@ async function generateObject(options) {
13864
14166
  const usage = asLanguageModelUsage(generateResult.usage);
13865
14167
  const warnings = generateResult.warnings;
13866
14168
  const resultProviderMetadata = generateResult.providerMetadata;
13867
- const request = generateResult.request ?? {};
14169
+ const request = sanitizeRequestMetadata(generateResult.request) ?? {};
13868
14170
  const response = responseData;
13869
14171
  logWarnings({
13870
14172
  warnings,
@@ -14323,7 +14625,8 @@ var DefaultStreamObjectResult = class {
14323
14625
  }
14324
14626
  } };
14325
14627
  const startTimestampMs = now();
14326
- const { stream, response, request } = await retry(() => model.doStream(callOptions));
14628
+ const { stream, response, request: rawRequest } = await retry(() => model.doStream(callOptions));
14629
+ const request = sanitizeRequestMetadata(rawRequest);
14327
14630
  self._request.resolve(request ?? {});
14328
14631
  let warnings;
14329
14632
  let usage = createNullLanguageModelUsage();
@@ -15254,6 +15557,10 @@ function smoothStream({ delayInMs = 10, chunking = "word", _internal: { delay: d
15254
15557
  }
15255
15558
  }
15256
15559
  return new TransformStream({ async transform(chunk, controller) {
15560
+ if (chunk.type === "ping") {
15561
+ controller.enqueue(chunk);
15562
+ return;
15563
+ }
15257
15564
  if (chunk.type !== "text-delta" && chunk.type !== "reasoning-delta") {
15258
15565
  flushBuffer(controller);
15259
15566
  controller.enqueue(chunk);
@@ -15424,10 +15731,14 @@ async function experimental_generateVideo({ model: modelArg, prompt: promptArg,
15424
15731
  return retry(() => model.doGenerate(callOptions));
15425
15732
  }));
15426
15733
  const videos = [];
15734
+ let uploadedVideos = 0;
15427
15735
  const responses = [];
15428
15736
  const providerMetadata = {};
15429
15737
  for (const result of results) {
15430
15738
  for (const videoData of result.videos) switch (videoData.type) {
15739
+ case "uploaded":
15740
+ uploadedVideos++;
15741
+ break;
15431
15742
  case "url": {
15432
15743
  const { data, mediaType: downloadedMediaType } = await downloadFn({
15433
15744
  url: new URL(videoData.url),
@@ -15471,19 +15782,30 @@ async function experimental_generateVideo({ model: modelArg, prompt: promptArg,
15471
15782
  });
15472
15783
  if (result.providerMetadata != null) mergeProviderMetadata(providerMetadata, result.providerMetadata);
15473
15784
  }
15474
- if (videos.length === 0) throw new NoVideoGeneratedError({ responses });
15785
+ if (videos.length === 0 && uploadedVideos === 0) throw new NoVideoGeneratedError({ responses });
15475
15786
  if (warnings.length > 0) logWarnings({
15476
15787
  warnings,
15477
15788
  provider: model.provider,
15478
15789
  model: model.modelId
15479
15790
  });
15480
- return {
15791
+ const result = {
15481
15792
  video: videos[0],
15482
15793
  videos,
15794
+ uploadedVideos,
15483
15795
  warnings,
15484
15796
  responses,
15485
15797
  providerMetadata
15486
15798
  };
15799
+ if (videos.length === 0) Object.defineProperty(result, "video", {
15800
+ enumerable: false,
15801
+ get() {
15802
+ throw new NoVideoGeneratedError({
15803
+ message: "Videos were delivered to the upload destination. Use uploadedVideos instead of video.",
15804
+ responses
15805
+ });
15806
+ }
15807
+ });
15808
+ return result;
15487
15809
  }
15488
15810
  async function executeStartStatusFlow({ model, callOptions, poll: pollConfig, webhook: webhookFactory, maxRetries, retry }) {
15489
15811
  const earlyWarnings = [];
@@ -18039,6 +18361,7 @@ var BrowserRealtimeWebRTC = class {
18039
18361
  var RealtimeAttempt = class {
18040
18362
  constructor() {
18041
18363
  this.abort = new AbortController();
18364
+ this.reportedTransportErrors = /* @__PURE__ */ new WeakSet();
18042
18365
  this.timers = /* @__PURE__ */ new Map();
18043
18366
  this.active = true;
18044
18367
  this.ready = false;
@@ -18544,9 +18867,13 @@ var AbstractRealtimeSession = class {
18544
18867
  }
18545
18868
  validateConnection() {
18546
18869
  const { model, api } = this.options;
18547
- if ((!this.continuous || api.session != null) && this.options.maxPlaybackBufferSeconds != null) throw new Error("maxPlaybackBufferSeconds is supported only for continuous PCM sessions");
18548
- const connection = api.session != null ? "webrtc" : api.token != null ? "client-secret-websocket" : "server-websocket";
18549
- if (!(model.capabilities?.connections ?? ["client-secret-websocket"]).includes(connection) || model.capabilities?.transports != null && !model.capabilities.transports.includes(api.session != null ? "webrtc" : "websocket")) throw new Error(`Realtime model does not support ${connection}`);
18870
+ if ((!this.continuous || api.session != null || api.provider != null) && this.options.maxPlaybackBufferSeconds != null) throw new Error("maxPlaybackBufferSeconds is supported only for continuous PCM sessions");
18871
+ const connection = api.provider != null ? "provider" : api.session != null ? "webrtc" : api.token != null ? "client-secret-websocket" : "server-websocket";
18872
+ if (!(model.capabilities?.connections ?? ["client-secret-websocket"]).includes(connection) || api.provider == null && model.capabilities?.transports != null && !model.capabilities.transports.includes(api.session != null ? "webrtc" : "websocket")) throw new Error(`Realtime model does not support ${connection}`);
18873
+ if (api.provider != null) {
18874
+ if (model.createTransport == null) throw new Error("Realtime model does not support a provider transport");
18875
+ return;
18876
+ }
18550
18877
  if (api.session != null) {
18551
18878
  if (model.getWebRTCConfig == null) throw new Error("Realtime model does not support WebRTC configuration");
18552
18879
  return;
@@ -18570,7 +18897,7 @@ var AbstractRealtimeSession = class {
18570
18897
  if (connectOptions?.capture === false) this.stopAudioCapture();
18571
18898
  if (!current()) return;
18572
18899
  if (connectOptions?.stream != null && connectOptions.stream !== this.suppliedStream) {
18573
- if (this.captureRequested && !this.sessionLifecycle && !this.continuous && api.session == null) this.startAudioCapture(connectOptions.stream);
18900
+ if (this.captureRequested && !this.sessionLifecycle && !this.continuous && api.session == null && api.provider == null) this.startAudioCapture(connectOptions.stream);
18574
18901
  else this.suppliedStream = connectOptions.stream;
18575
18902
  }
18576
18903
  if (!current()) return;
@@ -18592,7 +18919,7 @@ var AbstractRealtimeSession = class {
18592
18919
  attempt.timer("startup", this.options.startupTimeoutMs ?? 3e4, () => {
18593
18920
  if (current()) this.fail(/* @__PURE__ */ new Error("Realtime session startup timed out"));
18594
18921
  });
18595
- const reportedTransportErrors = /* @__PURE__ */ new WeakSet();
18922
+ const reportedTransportErrors = attempt.reportedTransportErrors;
18596
18923
  const callbacks = {
18597
18924
  model,
18598
18925
  onEvent: async (event) => {
@@ -18600,7 +18927,7 @@ var AbstractRealtimeSession = class {
18600
18927
  try {
18601
18928
  await this.handleServerEvent(event, attempt);
18602
18929
  } catch (error) {
18603
- if (current()) this.fail(error, (this.rtc ?? this.pcm ?? this.transport)?.finish());
18930
+ if (current()) this.fail(error, (this.providerTransport ?? this.rtc ?? this.pcm ?? this.transport)?.finish());
18604
18931
  }
18605
18932
  },
18606
18933
  onError: (error) => {
@@ -18628,6 +18955,13 @@ var AbstractRealtimeSession = class {
18628
18955
  onClose: (error) => {
18629
18956
  if (!current()) return;
18630
18957
  const finalizationConfirmed = model.capabilities?.finalization === "session-close" && this.state.session?.finalization === "confirmed";
18958
+ if (api.provider != null && attempt.closing) {
18959
+ if (error != null && !finalizationConfirmed && !reportedTransportErrors.has(error)) {
18960
+ reportedTransportErrors.add(error);
18961
+ this.reportError(error, attempt);
18962
+ }
18963
+ return;
18964
+ }
18631
18965
  if (error != null && !finalizationConfirmed) this.fail(error, void 0, !reportedTransportErrors.has(error));
18632
18966
  else if (!attempt.ready && !finalizationConfirmed) this.fail(/* @__PURE__ */ new Error("Realtime connection closed before becoming ready"));
18633
18967
  else this.disconnect();
@@ -18645,7 +18979,21 @@ var AbstractRealtimeSession = class {
18645
18979
  });
18646
18980
  }
18647
18981
  };
18648
- if (api.session != null) {
18982
+ if (api.provider != null) {
18983
+ const transport = model.createTransport(callbacks);
18984
+ if (!current()) {
18985
+ transport.dispose();
18986
+ return;
18987
+ }
18988
+ this.providerTransport = transport;
18989
+ await transport.connect({
18990
+ api: api.provider,
18991
+ sessionConfig,
18992
+ stream: connectOptions?.stream,
18993
+ capture: connectOptions?.capture,
18994
+ abortSignal: attempt.abort.signal
18995
+ });
18996
+ } else if (api.session != null) {
18649
18997
  this.rtc = new BrowserRealtimeWebRTC({
18650
18998
  ...callbacks,
18651
18999
  disconnectTimeoutMs: this.options.rtcDisconnectTimeoutMs
@@ -18761,8 +19109,12 @@ var AbstractRealtimeSession = class {
18761
19109
  closeFailed(attempt, error) {
18762
19110
  if (this.attempt !== attempt || !attempt.active || attempt.transportClosing) return;
18763
19111
  attempt.clearTimer("close");
18764
- const transport = this.rtc ?? this.pcm ?? this.transport;
19112
+ const transport = this.providerTransport ?? this.rtc ?? this.pcm ?? this.transport;
18765
19113
  this.drainAttempt(attempt, transport?.finish());
19114
+ if (error instanceof Error) {
19115
+ if (attempt.reportedTransportErrors.has(error)) return;
19116
+ attempt.reportedTransportErrors.add(error);
19117
+ }
18766
19118
  this.reportError(error, attempt);
18767
19119
  }
18768
19120
  disconnect() {
@@ -18774,16 +19126,19 @@ var AbstractRealtimeSession = class {
18774
19126
  const audio = this.audio;
18775
19127
  const pcm = this.pcm;
18776
19128
  const rtc = this.rtc;
19129
+ const providerTransport = this.providerTransport;
18777
19130
  this.transport = void 0;
18778
19131
  this.audio = void 0;
18779
19132
  this.pcm = void 0;
18780
19133
  this.rtc = void 0;
19134
+ this.providerTransport = void 0;
18781
19135
  this.commands = void 0;
18782
19136
  attempt?.retire();
18783
19137
  transport?.dispose();
18784
19138
  audio?.dispose();
18785
19139
  pcm?.dispose();
18786
19140
  rtc?.dispose();
19141
+ providerTransport?.dispose();
18787
19142
  if (this.attempt !== attempt) return;
18788
19143
  const session = this.state.session;
18789
19144
  this.applyState({
@@ -18797,10 +19152,27 @@ var AbstractRealtimeSession = class {
18797
19152
  } } : {}
18798
19153
  });
18799
19154
  }
18800
- /** Wait for final usage when the model supports a session-close acknowledgement. */
19155
+ /** Wait for provider cleanup or supported session-close finalization. */
18801
19156
  close(options) {
18802
19157
  const attempt = this.attempt;
18803
19158
  if (attempt?.closePromise != null) return attempt.closePromise;
19159
+ const providerTransport = this.providerTransport;
19160
+ if (providerTransport != null && attempt?.active) {
19161
+ const promise = attempt.beginClose();
19162
+ attempt.clearTimer("startup");
19163
+ this.applyState({
19164
+ ...this.state,
19165
+ status: "closing"
19166
+ });
19167
+ if (this.attempt !== attempt || !attempt.active) return promise;
19168
+ this.stopAudioCapture();
19169
+ if (this.attempt !== attempt || !attempt.active) return promise;
19170
+ attempt.timer("close", this.options.closeTimeoutMs ?? 15e3, () => {
19171
+ if (this.attempt === attempt && attempt.active) this.fail(/* @__PURE__ */ new Error("Realtime provider session cleanup timed out"));
19172
+ });
19173
+ providerTransport.close().then(() => this.finishAttempt(attempt), (error) => this.closeFailed(attempt, error));
19174
+ return promise;
19175
+ }
18804
19176
  if (this.state.status !== "connected" || this.options.model.capabilities?.finalization !== "session-close" || attempt == null) {
18805
19177
  this.disconnect();
18806
19178
  return Promise.resolve();
@@ -18827,8 +19199,16 @@ var AbstractRealtimeSession = class {
18827
19199
  return promise;
18828
19200
  }
18829
19201
  sendTransport(event, guard, automaticAudio = false) {
18830
- const transport = this.rtc ?? this.pcm ?? this.transport;
19202
+ const transport = this.providerTransport ?? this.rtc ?? this.pcm ?? this.transport;
18831
19203
  if (transport == null) throw new Error("Realtime connection is not open");
19204
+ if (transport === this.providerTransport) {
19205
+ const attempt = this.attempt;
19206
+ const sent = transport.sendEvent(event, guard);
19207
+ sent.catch((error) => {
19208
+ if (attempt?.active && this.attempt === attempt) this.reportError(error, attempt);
19209
+ });
19210
+ return sent;
19211
+ }
18832
19212
  if (transport === this.transport) return this.transport.sendEvent(event, guard, automaticAudio);
18833
19213
  return transport.sendEvent(event, guard);
18834
19214
  }
@@ -18914,14 +19294,14 @@ var AbstractRealtimeSession = class {
18914
19294
  this.maybeRequestToolResponse();
18915
19295
  }
18916
19296
  maybeRequestToolResponse() {
18917
- if (this.state.status !== "connected" || this.attempt?.closing || !this.responseToolCallsClosed || this.toolCallsInResponse.size === 0 || [...this.toolCallsInResponse].some((id) => !this.submittedToolOutputs.has(id))) return;
19297
+ if (this.providerTransport != null || this.state.status !== "connected" || this.attempt?.closing || !this.responseToolCallsClosed || this.toolCallsInResponse.size === 0 || [...this.toolCallsInResponse].some((id) => !this.submittedToolOutputs.has(id))) return;
18918
19298
  this.sendEvent({ type: "response-create" });
18919
19299
  this.toolCallsInResponse.clear();
18920
19300
  this.submittedToolOutputs.clear();
18921
19301
  this.responseToolCallsClosed = false;
18922
19302
  }
18923
19303
  startAudioCapture(stream) {
18924
- const legacy = !this.sessionLifecycle && !this.continuous && this.options.api.session == null;
19304
+ const legacy = !this.sessionLifecycle && !this.continuous && this.options.api.session == null && this.options.api.provider == null;
18925
19305
  if (!legacy && this.state.status !== "connected") throw new Error("Realtime session is not accepting capture");
18926
19306
  if (this.attempt?.active && (this.attempt.closing || this.attempt.cause != null)) throw new Error("Realtime session is not accepting capture");
18927
19307
  this.suppliedStream = stream;
@@ -18940,6 +19320,7 @@ var AbstractRealtimeSession = class {
18940
19320
  const accepting = () => !this.attempt?.closing && this.attempt?.cause == null && (this.state.status === "connected" || !this.sessionLifecycle && this.state.status === "connecting");
18941
19321
  if (!accepting()) throw new Error("Realtime session is not accepting capture");
18942
19322
  this.captureRequested = true;
19323
+ if (this.providerTransport != null) return this.providerTransport.startCapture(this.suppliedStream);
18943
19324
  if (this.rtc != null) return this.rtc.startCapture(this.suppliedStream);
18944
19325
  if (this.pcm != null) return this.pcm.resumeCapture(this.suppliedStream);
18945
19326
  const audio = this.audio;
@@ -18961,7 +19342,11 @@ var AbstractRealtimeSession = class {
18961
19342
  const pcm = this.pcm;
18962
19343
  const audio = this.audio;
18963
19344
  const rtc = this.rtc;
19345
+ const providerTransport = this.providerTransport;
18964
19346
  const attempt = this.attempt;
19347
+ if (providerTransport != null) providerTransport.stopCapture().catch((error) => {
19348
+ if (attempt?.active && this.attempt === attempt) this.reportError(error, attempt);
19349
+ });
18965
19350
  if (rtc != null) rtc.stopCapture().catch((error) => {
18966
19351
  if (attempt?.active && this.attempt === attempt) this.reportError(error, attempt);
18967
19352
  });
@@ -18969,10 +19354,10 @@ var AbstractRealtimeSession = class {
18969
19354
  audio?.stopCapture();
18970
19355
  }
18971
19356
  stopPlayback() {
18972
- (this.rtc ?? this.pcm ?? this.audio)?.stopPlayback();
19357
+ (this.providerTransport ?? this.rtc ?? this.pcm ?? this.audio)?.stopPlayback();
18973
19358
  }
18974
19359
  async resumePlayback() {
18975
- await (this.rtc ?? this.pcm ?? this.audio)?.resumePlayback();
19360
+ await (this.providerTransport ?? this.rtc ?? this.pcm ?? this.audio)?.resumePlayback();
18976
19361
  }
18977
19362
  dispose() {
18978
19363
  this.disconnect();
@@ -19705,7 +20090,7 @@ const originalGenerateCallId$1 = createIdGenerator$1({
19705
20090
  * @returns A result object that contains the generated transcript.
19706
20091
  */
19707
20092
  const defaultDownload = createDownload();
19708
- async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxRetriesArg, abortSignal, headers, telemetry, download: downloadFn = defaultDownload, _internal: { generateCallId = originalGenerateCallId$1 } = {} }) {
20093
+ async function transcribe({ model, audio, providerOptions = {}, timestampGranularities, maxRetries: maxRetriesArg, abortSignal, headers, telemetry, download: downloadFn = defaultDownload, _internal: { generateCallId = originalGenerateCallId$1 } = {} }) {
19709
20094
  const resolvedModel = resolveTranscriptionModel(model);
19710
20095
  if (!resolvedModel) throw new Error("Model could not be resolved");
19711
20096
  const { maxRetries, retry } = prepareRetries({
@@ -19728,7 +20113,8 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19728
20113
  inputAudioFormat: void 0,
19729
20114
  maxRetries,
19730
20115
  headers,
19731
- providerOptions
20116
+ providerOptions,
20117
+ timestampGranularities
19732
20118
  });
19733
20119
  const executeWithStartEvent = async ({ startEvent, execute }) => await runInTracingChannelSpan({
19734
20120
  type: "transcribe",
@@ -19747,12 +20133,15 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19747
20133
  let downloadedMediaType;
19748
20134
  try {
19749
20135
  if (audio instanceof URL) {
19750
- const downloadResult = await downloadFn({
19751
- url: audio,
19752
- abortSignal
19753
- });
19754
- audioData = downloadResult.data;
19755
- downloadedMediaType = downloadResult.mediaType;
20136
+ if (resolvedModel.doGenerateFromUrl != null && downloadFn === defaultDownload && (audio.protocol === "https:" || audio.protocol === "http:")) audioData = audio;
20137
+ else {
20138
+ const downloadResult = await downloadFn({
20139
+ url: audio,
20140
+ abortSignal
20141
+ });
20142
+ audioData = downloadResult.data;
20143
+ downloadedMediaType = downloadResult.mediaType;
20144
+ }
19756
20145
  } else audioData = convertDataContentToUint8Array(audio);
19757
20146
  } catch (error) {
19758
20147
  preparationFailed = true;
@@ -19779,25 +20168,49 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19779
20168
  throw error;
19780
20169
  }
19781
20170
  }
19782
- const mediaType = downloadedMediaType ?? detectMediaType({
20171
+ let mediaType = audioData instanceof URL ? void 0 : getAudioMediaType(downloadedMediaType) ?? detectMediaType({
19783
20172
  data: audioData,
19784
20173
  topLevelType: "audio"
19785
20174
  }) ?? "audio/wav";
20175
+ let byteLength = audioData instanceof URL ? void 0 : audioData.byteLength;
19786
20176
  const startEvent = createStartEvent({
19787
- byteLength: audioData.byteLength,
20177
+ byteLength,
19788
20178
  mediaType
19789
20179
  });
19790
20180
  try {
19791
20181
  return await executeWithStartEvent({
19792
20182
  startEvent,
19793
20183
  execute: async () => {
19794
- const result = await retry(() => resolvedModel.doGenerate({
19795
- audio: audioData,
19796
- abortSignal,
19797
- headers: headersWithUserAgent,
19798
- providerOptions,
19799
- mediaType
19800
- }));
20184
+ const result = await retry(async () => {
20185
+ const callOptions = {
20186
+ abortSignal,
20187
+ headers: headersWithUserAgent,
20188
+ providerOptions,
20189
+ ...timestampGranularities != null ? { timestampGranularities } : {}
20190
+ };
20191
+ if (audioData instanceof URL) {
20192
+ const nativeResult = await resolvedModel.doGenerateFromUrl?.({
20193
+ ...callOptions,
20194
+ audio: audioData
20195
+ });
20196
+ if (nativeResult != null) return nativeResult;
20197
+ const downloaded = await downloadFn({
20198
+ url: audioData,
20199
+ abortSignal
20200
+ });
20201
+ audioData = downloaded.data;
20202
+ mediaType = getAudioMediaType(downloaded.mediaType) ?? detectMediaType({
20203
+ data: audioData,
20204
+ topLevelType: "audio"
20205
+ }) ?? "audio/wav";
20206
+ byteLength = audioData.byteLength;
20207
+ }
20208
+ return resolvedModel.doGenerate({
20209
+ ...callOptions,
20210
+ audio: audioData,
20211
+ mediaType: mediaType ?? "audio/wav"
20212
+ });
20213
+ });
19801
20214
  logWarnings({
19802
20215
  warnings: result.warnings,
19803
20216
  provider: resolvedModel.provider,
@@ -19811,11 +20224,12 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19811
20224
  provider: resolvedModel.provider,
19812
20225
  modelId: resolvedModel.modelId,
19813
20226
  audio: {
19814
- byteLength: audioData.byteLength,
20227
+ byteLength,
19815
20228
  mediaType
19816
20229
  },
19817
20230
  text: result.text,
19818
20231
  segments: result.segments,
20232
+ words: result.words,
19819
20233
  language: result.language,
19820
20234
  durationInSeconds: result.durationInSeconds,
19821
20235
  usage: result.usage,
@@ -19828,6 +20242,7 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19828
20242
  return new DefaultTranscriptionResult({
19829
20243
  text: result.text,
19830
20244
  segments: result.segments,
20245
+ words: result.words,
19831
20246
  language: result.language,
19832
20247
  durationInSeconds: result.durationInSeconds,
19833
20248
  warnings: result.warnings,
@@ -19844,10 +20259,22 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19844
20259
  throw error;
19845
20260
  }
19846
20261
  }
20262
+ /**
20263
+ * Normalizes a downloaded `Content-Type` header value and returns it only
20264
+ * when it is a full `audio/<subtype>` media type. Generic or mislabeled types
20265
+ * (e.g. `application/octet-stream`, `binary/octet-stream`, `text/plain`)
20266
+ * return `undefined` so that the media type is detected from the audio bytes
20267
+ * instead.
20268
+ */
20269
+ function getAudioMediaType(contentType) {
20270
+ const mediaType = contentType?.split(";")[0].trim().toLowerCase();
20271
+ return mediaType != null && getTopLevelMediaType(mediaType) === "audio" && isFullMediaType(mediaType) ? mediaType : void 0;
20272
+ }
19847
20273
  var DefaultTranscriptionResult = class {
19848
20274
  constructor(options) {
19849
20275
  this.text = options.text;
19850
20276
  this.segments = options.segments;
20277
+ this.words = options.words;
19851
20278
  this.language = options.language;
19852
20279
  this.durationInSeconds = options.durationInSeconds;
19853
20280
  this.warnings = options.warnings;