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
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.161";
1244
+ const VERSION = "7.0.163";
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({
@@ -4973,9 +5160,19 @@ async function validateApprovedToolApprovals({ approvedToolApprovals, tools, too
4973
5160
  const approved = [];
4974
5161
  const denied = [];
4975
5162
  const invalid = [];
4976
- for (const approval of approvedToolApprovals) {
5163
+ for (const collectedApproval of approvedToolApprovals) {
5164
+ const tool = getOwn(tools, collectedApproval.toolCall.toolName);
5165
+ const { toolMetadata: _toolMetadata, dynamic: _dynamic, ...toolCallFromHistory } = collectedApproval.toolCall;
5166
+ const approval = {
5167
+ ...collectedApproval,
5168
+ toolCall: {
5169
+ ...toolCallFromHistory,
5170
+ ...tool?.metadata != null ? { toolMetadata: tool.metadata } : {},
5171
+ ...tool?.type === "dynamic" ? { dynamic: true } : {},
5172
+ title: tool?.title
5173
+ }
5174
+ };
4977
5175
  const { approvalRequest, toolCall } = approval;
4978
- const tool = getOwn(tools, toolCall.toolName);
4979
5176
  if (toolApprovalSecret != null) {
4980
5177
  if (approvalRequest.signature == null) throw new InvalidToolApprovalSignatureError({
4981
5178
  approvalId: approvalRequest.approvalId,
@@ -5462,10 +5659,10 @@ async function generateTextInternal({ model: modelArg, tools, toolChoice, instru
5462
5659
  messages: prepareStepResult?.messages ?? stepInputMessages,
5463
5660
  toolCallerMessages
5464
5661
  });
5465
- const deliveredSteeringMessages = steeringRun?.resolveTakenMessages({
5662
+ const deliveredSteeringMessages = (steeringRun?.resolveTakenMessages({
5466
5663
  stepNumber,
5467
5664
  sentMessages: stepMessages
5468
- }) ?? [];
5665
+ }) ?? []).map(({ message }) => message);
5469
5666
  const promptMessages = await convertToLanguageModelPrompt({
5470
5667
  prompt: {
5471
5668
  instructions: stepInstructions,
@@ -5547,6 +5744,7 @@ async function generateTextInternal({ model: modelArg, tools, toolChoice, instru
5547
5744
  };
5548
5745
  return {
5549
5746
  ...result,
5747
+ ...result.request != null ? { request: sanitizeRequestMetadata(result.request) } : {},
5550
5748
  response: responseData
5551
5749
  };
5552
5750
  });
@@ -5584,6 +5782,7 @@ async function generateTextInternal({ model: modelArg, tools, toolChoice, instru
5584
5782
  usage: stepUsage,
5585
5783
  content: modelCallContent,
5586
5784
  responseId: currentModelResponse.response.id,
5785
+ ...currentModelResponse.request?.url != null ? { request: { url: getRequestOrigin(currentModelResponse.request.url) } } : {},
5587
5786
  ...currentModelResponse.providerMetadata != null ? { providerMetadata: currentModelResponse.providerMetadata } : {},
5588
5787
  performance: {
5589
5788
  responseTimeMs,
@@ -6425,6 +6624,22 @@ const uiMessageChunkSchema = lazySchema(() => zodSchema$1(z.union([
6425
6624
  mediaType: z.string(),
6426
6625
  providerMetadata: providerMetadataSchema.optional()
6427
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
+ }),
6428
6643
  z.looseObject({
6429
6644
  type: z.custom((value) => typeof value === "string" && value.startsWith("data-"), { message: "Type must start with \"data-\"" }),
6430
6645
  id: z.string().optional(),
@@ -7068,6 +7283,14 @@ function processUIMessageStream({ stream, messageMetadataSchema, dataPartSchemas
7068
7283
  write();
7069
7284
  break;
7070
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;
7071
7294
  case "start-step":
7072
7295
  state.message.parts.push({ type: "step-start" });
7073
7296
  break;
@@ -7415,6 +7638,11 @@ function toUIMessageChunk(part, { tools, sendReasoning = true, sendSources = fal
7415
7638
  type: "error",
7416
7639
  errorText: onError(part.error)
7417
7640
  };
7641
+ case "steering-message": return {
7642
+ type: "steering-message",
7643
+ id: part.id,
7644
+ parts: convertUserMessageToUIParts(part.message)
7645
+ };
7418
7646
  case "start-step": return { type: "start-step" };
7419
7647
  case "finish-step": return { type: "finish-step" };
7420
7648
  case "start":
@@ -7433,10 +7661,53 @@ function toUIMessageChunk(part, { tools, sendReasoning = true, sendSources = fal
7433
7661
  };
7434
7662
  case "abort": return part;
7435
7663
  case "tool-input-end":
7664
+ case "ping":
7436
7665
  case "raw": return;
7437
7666
  default: throw new Error(`Unknown chunk type: ${partType}`);
7438
7667
  }
7439
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
+ }
7440
7711
  //#endregion
7441
7712
  //#region src/ui-message-stream/to-ui-message-stream.ts
7442
7713
  /**
@@ -7969,6 +8240,7 @@ const isOutputChunkType = {
7969
8240
  "model-call-response-metadata": false,
7970
8241
  "model-call-end": false,
7971
8242
  error: false,
8243
+ ping: false,
7972
8244
  raw: false
7973
8245
  };
7974
8246
  function isOutputChunk$1(chunk) {
@@ -8274,7 +8546,7 @@ async function streamLanguageModelCall({ model, tools, toolOrder, output, toolCh
8274
8546
  callbacks: onLanguageModelCallStart
8275
8547
  });
8276
8548
  const callStartTimestampMs = now$3();
8277
- const { stream: languageModelStream, response, request } = await executeLanguageModelCallInTelemetryContext({
8549
+ const { stream: languageModelStream, response, request: rawRequest } = await executeLanguageModelCallInTelemetryContext({
8278
8550
  ...languageModelCallStartEvent,
8279
8551
  execute: async () => await resolvedModel.doStream({
8280
8552
  ...callSettings,
@@ -8288,6 +8560,7 @@ async function streamLanguageModelCall({ model, tools, toolOrder, output, toolCh
8288
8560
  includeRawChunks
8289
8561
  })
8290
8562
  });
8563
+ const request = sanitizeRequestMetadata(rawRequest);
8291
8564
  return {
8292
8565
  stream: createAsyncIterableStream(languageModelStream.pipeThrough(createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({
8293
8566
  tools,
@@ -8303,6 +8576,7 @@ async function streamLanguageModelCall({ model, tools, toolOrder, output, toolCh
8303
8576
  generateId,
8304
8577
  now: now$3,
8305
8578
  callStartTimestampMs,
8579
+ request,
8306
8580
  onLanguageModelCallEnd,
8307
8581
  collectContent
8308
8582
  }))),
@@ -8310,7 +8584,7 @@ async function streamLanguageModelCall({ model, tools, toolOrder, output, toolCh
8310
8584
  request
8311
8585
  };
8312
8586
  }
8313
- 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 }) {
8314
8588
  const toolCallsByToolCallId = /* @__PURE__ */ new Map();
8315
8589
  const modelCallContent = [];
8316
8590
  const rawModelCallContent = [];
@@ -8488,6 +8762,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({ too
8488
8762
  usage,
8489
8763
  content: modelCallContent,
8490
8764
  responseId,
8765
+ ...request?.url != null ? { request: { url: getRequestOrigin(request.url) } } : {},
8491
8766
  ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {},
8492
8767
  performance
8493
8768
  },
@@ -9782,10 +10057,20 @@ var DefaultStreamTextResult = class {
9782
10057
  toolCallerMessages
9783
10058
  });
9784
10059
  currentStepMessages = stepMessages;
9785
- currentStepSteeringMessages = steeringRun?.resolveTakenMessages({
10060
+ const deliveredSteeringMessages = steeringRun?.resolveTakenMessages({
9786
10061
  stepNumber: currentStep,
9787
10062
  sentMessages: stepMessages
9788
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
+ } }));
9789
10074
  const stepInstructions = prepareStepResult?.instructions ?? prepareStepResult?.system ?? instructionsForNextStep;
9790
10075
  instructionsForNextStep = stepInstructions;
9791
10076
  const stepProviderOptions = mergeObjects(providerOptions, prepareStepResult?.providerOptions);
@@ -9930,7 +10215,7 @@ var DefaultStreamTextResult = class {
9930
10215
  clearFirstChunkTimeout();
9931
10216
  resetChunkTimeout();
9932
10217
  }
9933
- if (shouldBufferToolParts && value.type !== "error" && (isToolPart || bufferedAttemptParts.length > 0)) {
10218
+ if (shouldBufferToolParts && value.type !== "error" && value.type !== "ping" && (isToolPart || bufferedAttemptParts.length > 0)) {
9934
10219
  bufferedAttemptParts.push(value);
9935
10220
  continue;
9936
10221
  }
@@ -10095,6 +10380,7 @@ var DefaultStreamTextResult = class {
10095
10380
  case "tool-input-end":
10096
10381
  case "tool-input-delta":
10097
10382
  case "tool-approval-request":
10383
+ case "ping":
10098
10384
  case "tool-output-denied":
10099
10385
  enqueueStepPart(controller, chunk);
10100
10386
  break;
@@ -11033,24 +11319,7 @@ async function convertToModelMessages(messages, options) {
11033
11319
  modelMessages.push({
11034
11320
  role: "user",
11035
11321
  content: message.parts.map((part) => {
11036
- if (isTextUIPart(part)) return {
11037
- type: "text",
11038
- text: part.text,
11039
- ...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
11040
- };
11041
- if (isFileUIPart(part)) return {
11042
- type: "file",
11043
- mediaType: part.mediaType,
11044
- filename: part.filename,
11045
- data: part.providerReference != null ? {
11046
- type: "reference",
11047
- reference: part.providerReference
11048
- } : {
11049
- type: "url",
11050
- url: new URL(part.url)
11051
- },
11052
- ...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
11053
- };
11322
+ if (isTextUIPart(part) || isFileUIPart(part)) return convertUserContentUIPart(part);
11054
11323
  if (isDataUIPart(part)) return options?.convertDataPart?.(part);
11055
11324
  }).filter(isNonNullable)
11056
11325
  });
@@ -11206,6 +11475,13 @@ async function convertToModelMessages(messages, options) {
11206
11475
  }
11207
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);
11208
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
+ }
11209
11485
  await processBlock();
11210
11486
  break;
11211
11487
  }
@@ -11220,6 +11496,26 @@ async function convertToModelMessages(messages, options) {
11220
11496
  }
11221
11497
  return modelMessages;
11222
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
+ }
11223
11519
  //#endregion
11224
11520
  //#region src/ui/validate-ui-messages.ts
11225
11521
  const toolMetadataSchema = z.record(z.string(), jsonValueSchema.optional());
@@ -11312,6 +11608,22 @@ const uiMessagesSchema = lazySchema(() => {
11312
11608
  url: z.string(),
11313
11609
  providerMetadata: providerMetadataSchema.optional()
11314
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
+ }),
11315
11627
  z.object({ type: z.literal("step-start") }),
11316
11628
  z.object({
11317
11629
  type: z.string().startsWith("data-"),
@@ -13854,7 +14166,7 @@ async function generateObject(options) {
13854
14166
  const usage = asLanguageModelUsage(generateResult.usage);
13855
14167
  const warnings = generateResult.warnings;
13856
14168
  const resultProviderMetadata = generateResult.providerMetadata;
13857
- const request = generateResult.request ?? {};
14169
+ const request = sanitizeRequestMetadata(generateResult.request) ?? {};
13858
14170
  const response = responseData;
13859
14171
  logWarnings({
13860
14172
  warnings,
@@ -14313,7 +14625,8 @@ var DefaultStreamObjectResult = class {
14313
14625
  }
14314
14626
  } };
14315
14627
  const startTimestampMs = now();
14316
- 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);
14317
14630
  self._request.resolve(request ?? {});
14318
14631
  let warnings;
14319
14632
  let usage = createNullLanguageModelUsage();
@@ -15244,6 +15557,10 @@ function smoothStream({ delayInMs = 10, chunking = "word", _internal: { delay: d
15244
15557
  }
15245
15558
  }
15246
15559
  return new TransformStream({ async transform(chunk, controller) {
15560
+ if (chunk.type === "ping") {
15561
+ controller.enqueue(chunk);
15562
+ return;
15563
+ }
15247
15564
  if (chunk.type !== "text-delta" && chunk.type !== "reasoning-delta") {
15248
15565
  flushBuffer(controller);
15249
15566
  controller.enqueue(chunk);
@@ -15414,10 +15731,14 @@ async function experimental_generateVideo({ model: modelArg, prompt: promptArg,
15414
15731
  return retry(() => model.doGenerate(callOptions));
15415
15732
  }));
15416
15733
  const videos = [];
15734
+ let uploadedVideos = 0;
15417
15735
  const responses = [];
15418
15736
  const providerMetadata = {};
15419
15737
  for (const result of results) {
15420
15738
  for (const videoData of result.videos) switch (videoData.type) {
15739
+ case "uploaded":
15740
+ uploadedVideos++;
15741
+ break;
15421
15742
  case "url": {
15422
15743
  const { data, mediaType: downloadedMediaType } = await downloadFn({
15423
15744
  url: new URL(videoData.url),
@@ -15461,19 +15782,30 @@ async function experimental_generateVideo({ model: modelArg, prompt: promptArg,
15461
15782
  });
15462
15783
  if (result.providerMetadata != null) mergeProviderMetadata(providerMetadata, result.providerMetadata);
15463
15784
  }
15464
- if (videos.length === 0) throw new NoVideoGeneratedError({ responses });
15785
+ if (videos.length === 0 && uploadedVideos === 0) throw new NoVideoGeneratedError({ responses });
15465
15786
  if (warnings.length > 0) logWarnings({
15466
15787
  warnings,
15467
15788
  provider: model.provider,
15468
15789
  model: model.modelId
15469
15790
  });
15470
- return {
15791
+ const result = {
15471
15792
  video: videos[0],
15472
15793
  videos,
15794
+ uploadedVideos,
15473
15795
  warnings,
15474
15796
  responses,
15475
15797
  providerMetadata
15476
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;
15477
15809
  }
15478
15810
  async function executeStartStatusFlow({ model, callOptions, poll: pollConfig, webhook: webhookFactory, maxRetries, retry }) {
15479
15811
  const earlyWarnings = [];
@@ -18029,6 +18361,7 @@ var BrowserRealtimeWebRTC = class {
18029
18361
  var RealtimeAttempt = class {
18030
18362
  constructor() {
18031
18363
  this.abort = new AbortController();
18364
+ this.reportedTransportErrors = /* @__PURE__ */ new WeakSet();
18032
18365
  this.timers = /* @__PURE__ */ new Map();
18033
18366
  this.active = true;
18034
18367
  this.ready = false;
@@ -18534,9 +18867,13 @@ var AbstractRealtimeSession = class {
18534
18867
  }
18535
18868
  validateConnection() {
18536
18869
  const { model, api } = this.options;
18537
- if ((!this.continuous || api.session != null) && this.options.maxPlaybackBufferSeconds != null) throw new Error("maxPlaybackBufferSeconds is supported only for continuous PCM sessions");
18538
- const connection = api.session != null ? "webrtc" : api.token != null ? "client-secret-websocket" : "server-websocket";
18539
- 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
+ }
18540
18877
  if (api.session != null) {
18541
18878
  if (model.getWebRTCConfig == null) throw new Error("Realtime model does not support WebRTC configuration");
18542
18879
  return;
@@ -18560,7 +18897,7 @@ var AbstractRealtimeSession = class {
18560
18897
  if (connectOptions?.capture === false) this.stopAudioCapture();
18561
18898
  if (!current()) return;
18562
18899
  if (connectOptions?.stream != null && connectOptions.stream !== this.suppliedStream) {
18563
- 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);
18564
18901
  else this.suppliedStream = connectOptions.stream;
18565
18902
  }
18566
18903
  if (!current()) return;
@@ -18582,7 +18919,7 @@ var AbstractRealtimeSession = class {
18582
18919
  attempt.timer("startup", this.options.startupTimeoutMs ?? 3e4, () => {
18583
18920
  if (current()) this.fail(/* @__PURE__ */ new Error("Realtime session startup timed out"));
18584
18921
  });
18585
- const reportedTransportErrors = /* @__PURE__ */ new WeakSet();
18922
+ const reportedTransportErrors = attempt.reportedTransportErrors;
18586
18923
  const callbacks = {
18587
18924
  model,
18588
18925
  onEvent: async (event) => {
@@ -18590,7 +18927,7 @@ var AbstractRealtimeSession = class {
18590
18927
  try {
18591
18928
  await this.handleServerEvent(event, attempt);
18592
18929
  } catch (error) {
18593
- 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());
18594
18931
  }
18595
18932
  },
18596
18933
  onError: (error) => {
@@ -18618,6 +18955,13 @@ var AbstractRealtimeSession = class {
18618
18955
  onClose: (error) => {
18619
18956
  if (!current()) return;
18620
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
+ }
18621
18965
  if (error != null && !finalizationConfirmed) this.fail(error, void 0, !reportedTransportErrors.has(error));
18622
18966
  else if (!attempt.ready && !finalizationConfirmed) this.fail(/* @__PURE__ */ new Error("Realtime connection closed before becoming ready"));
18623
18967
  else this.disconnect();
@@ -18635,7 +18979,21 @@ var AbstractRealtimeSession = class {
18635
18979
  });
18636
18980
  }
18637
18981
  };
18638
- 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) {
18639
18997
  this.rtc = new BrowserRealtimeWebRTC({
18640
18998
  ...callbacks,
18641
18999
  disconnectTimeoutMs: this.options.rtcDisconnectTimeoutMs
@@ -18751,8 +19109,12 @@ var AbstractRealtimeSession = class {
18751
19109
  closeFailed(attempt, error) {
18752
19110
  if (this.attempt !== attempt || !attempt.active || attempt.transportClosing) return;
18753
19111
  attempt.clearTimer("close");
18754
- const transport = this.rtc ?? this.pcm ?? this.transport;
19112
+ const transport = this.providerTransport ?? this.rtc ?? this.pcm ?? this.transport;
18755
19113
  this.drainAttempt(attempt, transport?.finish());
19114
+ if (error instanceof Error) {
19115
+ if (attempt.reportedTransportErrors.has(error)) return;
19116
+ attempt.reportedTransportErrors.add(error);
19117
+ }
18756
19118
  this.reportError(error, attempt);
18757
19119
  }
18758
19120
  disconnect() {
@@ -18764,16 +19126,19 @@ var AbstractRealtimeSession = class {
18764
19126
  const audio = this.audio;
18765
19127
  const pcm = this.pcm;
18766
19128
  const rtc = this.rtc;
19129
+ const providerTransport = this.providerTransport;
18767
19130
  this.transport = void 0;
18768
19131
  this.audio = void 0;
18769
19132
  this.pcm = void 0;
18770
19133
  this.rtc = void 0;
19134
+ this.providerTransport = void 0;
18771
19135
  this.commands = void 0;
18772
19136
  attempt?.retire();
18773
19137
  transport?.dispose();
18774
19138
  audio?.dispose();
18775
19139
  pcm?.dispose();
18776
19140
  rtc?.dispose();
19141
+ providerTransport?.dispose();
18777
19142
  if (this.attempt !== attempt) return;
18778
19143
  const session = this.state.session;
18779
19144
  this.applyState({
@@ -18787,10 +19152,27 @@ var AbstractRealtimeSession = class {
18787
19152
  } } : {}
18788
19153
  });
18789
19154
  }
18790
- /** Wait for final usage when the model supports a session-close acknowledgement. */
19155
+ /** Wait for provider cleanup or supported session-close finalization. */
18791
19156
  close(options) {
18792
19157
  const attempt = this.attempt;
18793
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
+ }
18794
19176
  if (this.state.status !== "connected" || this.options.model.capabilities?.finalization !== "session-close" || attempt == null) {
18795
19177
  this.disconnect();
18796
19178
  return Promise.resolve();
@@ -18817,8 +19199,16 @@ var AbstractRealtimeSession = class {
18817
19199
  return promise;
18818
19200
  }
18819
19201
  sendTransport(event, guard, automaticAudio = false) {
18820
- const transport = this.rtc ?? this.pcm ?? this.transport;
19202
+ const transport = this.providerTransport ?? this.rtc ?? this.pcm ?? this.transport;
18821
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
+ }
18822
19212
  if (transport === this.transport) return this.transport.sendEvent(event, guard, automaticAudio);
18823
19213
  return transport.sendEvent(event, guard);
18824
19214
  }
@@ -18904,14 +19294,14 @@ var AbstractRealtimeSession = class {
18904
19294
  this.maybeRequestToolResponse();
18905
19295
  }
18906
19296
  maybeRequestToolResponse() {
18907
- 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;
18908
19298
  this.sendEvent({ type: "response-create" });
18909
19299
  this.toolCallsInResponse.clear();
18910
19300
  this.submittedToolOutputs.clear();
18911
19301
  this.responseToolCallsClosed = false;
18912
19302
  }
18913
19303
  startAudioCapture(stream) {
18914
- 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;
18915
19305
  if (!legacy && this.state.status !== "connected") throw new Error("Realtime session is not accepting capture");
18916
19306
  if (this.attempt?.active && (this.attempt.closing || this.attempt.cause != null)) throw new Error("Realtime session is not accepting capture");
18917
19307
  this.suppliedStream = stream;
@@ -18930,6 +19320,7 @@ var AbstractRealtimeSession = class {
18930
19320
  const accepting = () => !this.attempt?.closing && this.attempt?.cause == null && (this.state.status === "connected" || !this.sessionLifecycle && this.state.status === "connecting");
18931
19321
  if (!accepting()) throw new Error("Realtime session is not accepting capture");
18932
19322
  this.captureRequested = true;
19323
+ if (this.providerTransport != null) return this.providerTransport.startCapture(this.suppliedStream);
18933
19324
  if (this.rtc != null) return this.rtc.startCapture(this.suppliedStream);
18934
19325
  if (this.pcm != null) return this.pcm.resumeCapture(this.suppliedStream);
18935
19326
  const audio = this.audio;
@@ -18951,7 +19342,11 @@ var AbstractRealtimeSession = class {
18951
19342
  const pcm = this.pcm;
18952
19343
  const audio = this.audio;
18953
19344
  const rtc = this.rtc;
19345
+ const providerTransport = this.providerTransport;
18954
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
+ });
18955
19350
  if (rtc != null) rtc.stopCapture().catch((error) => {
18956
19351
  if (attempt?.active && this.attempt === attempt) this.reportError(error, attempt);
18957
19352
  });
@@ -18959,10 +19354,10 @@ var AbstractRealtimeSession = class {
18959
19354
  audio?.stopCapture();
18960
19355
  }
18961
19356
  stopPlayback() {
18962
- (this.rtc ?? this.pcm ?? this.audio)?.stopPlayback();
19357
+ (this.providerTransport ?? this.rtc ?? this.pcm ?? this.audio)?.stopPlayback();
18963
19358
  }
18964
19359
  async resumePlayback() {
18965
- await (this.rtc ?? this.pcm ?? this.audio)?.resumePlayback();
19360
+ await (this.providerTransport ?? this.rtc ?? this.pcm ?? this.audio)?.resumePlayback();
18966
19361
  }
18967
19362
  dispose() {
18968
19363
  this.disconnect();
@@ -19695,7 +20090,7 @@ const originalGenerateCallId$1 = createIdGenerator$1({
19695
20090
  * @returns A result object that contains the generated transcript.
19696
20091
  */
19697
20092
  const defaultDownload = createDownload();
19698
- 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 } = {} }) {
19699
20094
  const resolvedModel = resolveTranscriptionModel(model);
19700
20095
  if (!resolvedModel) throw new Error("Model could not be resolved");
19701
20096
  const { maxRetries, retry } = prepareRetries({
@@ -19718,7 +20113,8 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19718
20113
  inputAudioFormat: void 0,
19719
20114
  maxRetries,
19720
20115
  headers,
19721
- providerOptions
20116
+ providerOptions,
20117
+ timestampGranularities
19722
20118
  });
19723
20119
  const executeWithStartEvent = async ({ startEvent, execute }) => await runInTracingChannelSpan({
19724
20120
  type: "transcribe",
@@ -19737,12 +20133,15 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19737
20133
  let downloadedMediaType;
19738
20134
  try {
19739
20135
  if (audio instanceof URL) {
19740
- const downloadResult = await downloadFn({
19741
- url: audio,
19742
- abortSignal
19743
- });
19744
- audioData = downloadResult.data;
19745
- 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
+ }
19746
20145
  } else audioData = convertDataContentToUint8Array(audio);
19747
20146
  } catch (error) {
19748
20147
  preparationFailed = true;
@@ -19769,25 +20168,49 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19769
20168
  throw error;
19770
20169
  }
19771
20170
  }
19772
- const mediaType = downloadedMediaType ?? detectMediaType({
20171
+ let mediaType = audioData instanceof URL ? void 0 : getAudioMediaType(downloadedMediaType) ?? detectMediaType({
19773
20172
  data: audioData,
19774
20173
  topLevelType: "audio"
19775
20174
  }) ?? "audio/wav";
20175
+ let byteLength = audioData instanceof URL ? void 0 : audioData.byteLength;
19776
20176
  const startEvent = createStartEvent({
19777
- byteLength: audioData.byteLength,
20177
+ byteLength,
19778
20178
  mediaType
19779
20179
  });
19780
20180
  try {
19781
20181
  return await executeWithStartEvent({
19782
20182
  startEvent,
19783
20183
  execute: async () => {
19784
- const result = await retry(() => resolvedModel.doGenerate({
19785
- audio: audioData,
19786
- abortSignal,
19787
- headers: headersWithUserAgent,
19788
- providerOptions,
19789
- mediaType
19790
- }));
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
+ });
19791
20214
  logWarnings({
19792
20215
  warnings: result.warnings,
19793
20216
  provider: resolvedModel.provider,
@@ -19801,11 +20224,12 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19801
20224
  provider: resolvedModel.provider,
19802
20225
  modelId: resolvedModel.modelId,
19803
20226
  audio: {
19804
- byteLength: audioData.byteLength,
20227
+ byteLength,
19805
20228
  mediaType
19806
20229
  },
19807
20230
  text: result.text,
19808
20231
  segments: result.segments,
20232
+ words: result.words,
19809
20233
  language: result.language,
19810
20234
  durationInSeconds: result.durationInSeconds,
19811
20235
  usage: result.usage,
@@ -19818,6 +20242,7 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19818
20242
  return new DefaultTranscriptionResult({
19819
20243
  text: result.text,
19820
20244
  segments: result.segments,
20245
+ words: result.words,
19821
20246
  language: result.language,
19822
20247
  durationInSeconds: result.durationInSeconds,
19823
20248
  warnings: result.warnings,
@@ -19834,10 +20259,22 @@ async function transcribe({ model, audio, providerOptions = {}, maxRetries: maxR
19834
20259
  throw error;
19835
20260
  }
19836
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
+ }
19837
20273
  var DefaultTranscriptionResult = class {
19838
20274
  constructor(options) {
19839
20275
  this.text = options.text;
19840
20276
  this.segments = options.segments;
20277
+ this.words = options.words;
19841
20278
  this.language = options.language;
19842
20279
  this.durationInSeconds = options.durationInSeconds;
19843
20280
  this.warnings = options.warnings;