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
@@ -67,40 +67,40 @@ npx @ai-sdk/codemod v7/rename-system-to-instructions src/
67
67
 
68
68
  ## Codemod Table
69
69
 
70
- | Codemod Name | Description |
71
- | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
72
- | `remove-experimental-custom-provider` | Replaces `experimental_customProvider` with `customProvider` |
73
- | `remove-experimental-generate-image` | Replaces `experimental_generateImage` and `Experimental_GenerateImageResult` with stable names |
74
- | `replace-experimental-output-with-output` | Replaces `experimental_output` options and result access with `output` |
75
- | `remove-experimental-prepare-step` | Replaces `experimental_prepareStep` with `prepareStep` |
76
- | `replace-cached-input-tokens` | Replaces `usage.cachedInputTokens` with `usage.inputTokenDetails.cacheReadTokens` |
77
- | `replace-reasoning-tokens` | Replaces `usage.reasoningTokens` with `usage.outputTokenDetails.reasoningTokens` |
78
- | `remove-experimental-active-tools` | Replaces `experimental_activeTools` with `activeTools` |
79
- | `remove-tool-call-options-type` | Replaces the removed `ToolCallOptions` type with `ToolExecutionOptions` |
80
- | `remove-is-tool-or-dynamic-tool-uipart` | Replaces `isToolOrDynamicToolUIPart` with `isToolUIPart` |
81
- | `remove-media-content-part-type` | Replaces tool result content parts with `type: 'media'` with `type: 'file-data'` |
82
- | `replace-anthropic-cache-creation-input-tokens` | Replaces Anthropic `cacheCreationInputTokens` metadata access with standard usage fields |
83
- | `rename-experimental-transcribe` | Renames `experimental_transcribe` and `Experimental_TranscriptionResult` to stable names |
84
- | `rename-experimental-generate-speech` | Renames `experimental_generateSpeech` and `Experimental_SpeechResult` to stable names |
85
- | `rename-call-settings-type` | Replaces `CallSettings` with `LanguageModelCallOptions & Omit<RequestOptions, 'timeout'>` |
86
- | `rename-step-count-is` | Renames `stepCountIs` to `isStepCount` |
87
- | `rename-system-to-instructions` | Renames `system` prompt options, lifecycle fields, and repair-tool-call fields to `instructions` |
88
- | `rename-experimental-on-start-to-on-start` | Renames `experimental_onStart` to `onStart` |
89
- | `rename-experimental-on-step-start-to-on-step-start` | Renames `experimental_onStepStart` to `onStepStart` |
90
- | `rename-on-finish-to-on-end` | Renames `onFinish` callbacks to `onEnd` |
91
- | `rename-on-step-finish-to-on-step-end` | Renames `onStepFinish` callbacks to `onStepEnd` |
92
- | `rename-experimental-on-finish-to-on-end` | Renames `experimental_onFinish` callbacks to `onEnd` |
93
- | `rename-experimental-telemetry-to-telemetry` | Renames `experimental_telemetry` options to `telemetry` |
94
- | `rename-on-rerank-finish-to-on-rerank-end` | Renames telemetry `onRerankFinish` callbacks to `onRerankEnd` |
95
- | `rename-on-embed-finish-to-on-embed-end` | Renames telemetry `onEmbedFinish` callbacks to `onEmbedEnd` |
96
- | `rename-full-stream-to-stream` | Renames `streamText` result `fullStream` access to `stream` |
97
- | `move-include-raw-chunks-to-include` | Moves `includeRawChunks` into `include.rawChunks` |
98
- | `rename-experimental-include-to-include` | Renames `experimental_include` to `include` |
99
- | `rename-experimental-on-tool-call-start-to-on-tool-execution-start` | Renames `experimental_onToolCallStart` to `onToolExecutionStart` |
100
- | `rename-experimental-on-tool-call-finish-to-on-tool-execution-end` | Renames `experimental_onToolCallFinish` to `onToolExecutionEnd` |
101
- | `rename-experimental-context-to-context` | Renames tool callback `experimental_context` access to `context` |
102
- | `rename-google-generative-ai-to-google` | Renames Google provider types, classes, and functions that include `GoogleGenerativeAI` to `Google` |
103
- | `replace-image-message-part-with-file` | Replaces image message parts with file parts using `mediaType: 'image'` |
70
+ | Codemod Name | Description |
71
+ | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
72
+ | `remove-experimental-custom-provider` | Replaces `experimental_customProvider` with `customProvider` |
73
+ | `remove-experimental-generate-image` | Replaces `experimental_generateImage` and `Experimental_GenerateImageResult` with stable names |
74
+ | `replace-experimental-output-with-output` | Replaces `experimental_output` options and result access with `output` |
75
+ | `remove-experimental-prepare-step` | Replaces `experimental_prepareStep` with `prepareStep` |
76
+ | `replace-cached-input-tokens` | Replaces `usage.cachedInputTokens` with `usage.inputTokenDetails.cacheReadTokens` |
77
+ | `replace-reasoning-tokens` | Replaces `usage.reasoningTokens` with `usage.outputTokenDetails.reasoningTokens` |
78
+ | `remove-experimental-active-tools` | Replaces `experimental_activeTools` with `activeTools` |
79
+ | `remove-tool-call-options-type` | Replaces the removed `ToolCallOptions` type with `ToolExecutionOptions` |
80
+ | `remove-is-tool-or-dynamic-tool-uipart` | Replaces `isToolOrDynamicToolUIPart` with `isToolUIPart` |
81
+ | `remove-media-content-part-type` | Replaces tool result content parts with `type: 'media'` with `type: 'file-data'` |
82
+ | `replace-anthropic-cache-creation-input-tokens` | Replaces Anthropic `cacheCreationInputTokens` metadata access with standard usage fields |
83
+ | `rename-experimental-transcribe` | Renames `experimental_transcribe` and `Experimental_TranscriptionResult` to stable names |
84
+ | `rename-experimental-generate-speech` | Renames `experimental_generateSpeech` and `Experimental_SpeechResult` to stable names |
85
+ | `rename-call-settings-type` | Replaces `CallSettings` with `LanguageModelCallOptions & Omit<RequestOptions, 'timeout'>` |
86
+ | `rename-step-count-is` | Renames `stepCountIs` to `isStepCount` |
87
+ | `rename-system-to-instructions` | Renames `system` prompt options, lifecycle fields, and repair-tool-call fields to `instructions` |
88
+ | `rename-experimental-on-start-to-on-start` | Renames `experimental_onStart` to `onStart` |
89
+ | `rename-experimental-on-step-start-to-on-step-start` | Renames `experimental_onStepStart` to `onStepStart` |
90
+ | `rename-on-finish-to-on-end` | Renames `onFinish` callbacks to `onEnd` |
91
+ | `rename-on-step-finish-to-on-step-end` | Renames `onStepFinish` callbacks to `onStepEnd` |
92
+ | `rename-experimental-on-finish-to-on-end` | Renames `experimental_onFinish` callbacks to `onEnd` |
93
+ | `rename-experimental-telemetry-to-telemetry` | Renames `experimental_telemetry` options to `telemetry` |
94
+ | `rename-on-rerank-finish-to-on-rerank-end` | Renames telemetry `onRerankFinish` callbacks to `onRerankEnd` |
95
+ | `rename-on-embed-finish-to-on-embed-end` | Renames telemetry `onEmbedFinish` callbacks to `onEmbedEnd` |
96
+ | `rename-full-stream-to-stream` | Renames `streamText` result `fullStream` access to `stream` |
97
+ | `move-include-raw-chunks-to-include` | Moves `includeRawChunks` into `include.rawChunks` |
98
+ | `rename-experimental-include-to-include` | Renames `experimental_include` to `include` |
99
+ | `rename-experimental-on-tool-call-start-to-on-tool-execution-start` | Renames `experimental_onToolCallStart` to `onToolExecutionStart` |
100
+ | `rename-experimental-on-tool-call-finish-to-on-tool-execution-end` | Renames `experimental_onToolCallFinish` to `onToolExecutionEnd` |
101
+ | `rename-experimental-context-to-context` | Renames tool callback `experimental_context` access to `context` |
102
+ | `rename-google-generative-ai-to-google` | Migrates named Google imports and re-exports to the new API names while preserving local and exported names as aliases |
103
+ | `replace-image-message-part-with-file` | Replaces image message parts with file parts using `mediaType: 'image'` |
104
104
 
105
105
  ## All Packages
106
106
 
@@ -1881,6 +1881,8 @@ Every type, class, and function in `@ai-sdk/google` that contained `GoogleGenera
1881
1881
 
1882
1882
  The old names still work as deprecated aliases, but you should migrate to the new names, if you currently reference them.
1883
1883
 
1884
+ The `rename-google-generative-ai-to-google` codemod updates named imports and direct re-exports to the new API names. It preserves local binding names and application export names as aliases, so wrappers, property names, and shadowed variables keep working. Namespace member access remains unchanged.
1885
+
1884
1886
  The main entry point the `google` constant, remains unchanged, so if that's all you use from the provider, no changes are required.
1885
1887
 
1886
1888
  ## xAI Provider
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "7.0.162",
3
+ "version": "7.0.164",
4
4
  "type": "module",
5
5
  "description": "AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.",
6
6
  "license": "Apache-2.0",
@@ -42,20 +42,20 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
- "@ai-sdk/gateway": "4.0.135",
46
- "@ai-sdk/provider": "4.0.35",
47
- "@ai-sdk/provider-utils": "5.0.74"
45
+ "@ai-sdk/gateway": "4.0.137",
46
+ "@ai-sdk/provider": "4.0.36",
47
+ "@ai-sdk/provider-utils": "5.0.75"
48
48
  },
49
49
  "devDependencies": {
50
- "@ai-sdk/amazon-bedrock": "5.0.132",
51
- "@ai-sdk/deepseek": "3.0.79",
52
- "@ai-sdk/google": "4.0.111",
53
- "@ai-sdk/groq": "4.0.76",
54
- "@ai-sdk/huggingface": "2.0.84",
55
- "@ai-sdk/moonshotai": "3.0.84",
56
- "@ai-sdk/openai": "4.0.108",
50
+ "@ai-sdk/amazon-bedrock": "5.0.134",
51
+ "@ai-sdk/deepseek": "3.0.80",
52
+ "@ai-sdk/google": "4.0.113",
53
+ "@ai-sdk/groq": "4.0.77",
54
+ "@ai-sdk/huggingface": "2.0.86",
55
+ "@ai-sdk/moonshotai": "3.0.86",
56
+ "@ai-sdk/openai": "4.0.110",
57
57
  "@ai-sdk/test-server": "2.0.4",
58
- "@ai-sdk/xai": "5.0.38",
58
+ "@ai-sdk/xai": "5.0.39",
59
59
  "@edge-runtime/vm": "^5.0.0",
60
60
  "@smithy/eventstream-codec": "^4.3.3",
61
61
  "@smithy/util-utf8": "^4.3.3",
@@ -1,3 +1,4 @@
1
+ import { sanitizeRequestMetadata } from '../telemetry/get-request-origin';
1
2
  import type { JSONValue } from '@ai-sdk/provider';
2
3
  import {
3
4
  createIdGenerator,
@@ -447,7 +448,7 @@ export async function generateObject<
447
448
  const warnings = generateResult.warnings;
448
449
  const resultProviderMetadata = generateResult.providerMetadata;
449
450
  const request: Omit<LanguageModelRequestMetadata, 'messages'> =
450
- generateResult.request ?? {};
451
+ sanitizeRequestMetadata(generateResult.request) ?? {};
451
452
  const response: Omit<LanguageModelResponseMetadata, 'messages'> =
452
453
  responseData;
453
454
 
@@ -1,3 +1,4 @@
1
+ import { sanitizeRequestMetadata } from '../telemetry/get-request-origin';
1
2
  import type {
2
3
  JSONValue,
3
4
  LanguageModelV4FinishReason,
@@ -664,10 +665,13 @@ class DefaultStreamObjectResult<
664
665
  };
665
666
 
666
667
  const startTimestampMs = now();
667
- const { stream, response, request } = await retry(() =>
668
- model.doStream(callOptions),
669
- );
668
+ const {
669
+ stream,
670
+ response,
671
+ request: rawRequest,
672
+ } = await retry(() => model.doStream(callOptions));
670
673
 
674
+ const request = sanitizeRequestMetadata(rawRequest);
671
675
  self._request.resolve(request ?? {});
672
676
 
673
677
  let warnings: SharedV4Warning[] | undefined;
@@ -1,3 +1,7 @@
1
+ import {
2
+ getRequestOrigin,
3
+ sanitizeRequestMetadata,
4
+ } from '../telemetry/get-request-origin';
1
5
  import type {
2
6
  LanguageModelV4GenerateResult,
3
7
  LanguageModelV4ToolCall,
@@ -1116,11 +1120,12 @@ async function generateTextInternal<
1116
1120
 
1117
1121
  // steering messages are delivered when they are in the messages
1118
1122
  // that are sent to the model after prepareStep:
1119
- const deliveredSteeringMessages =
1123
+ const deliveredSteeringMessages = (
1120
1124
  steeringRun?.resolveTakenMessages({
1121
1125
  stepNumber,
1122
1126
  sentMessages: stepMessages,
1123
- }) ?? [];
1127
+ }) ?? []
1128
+ ).map(({ message }) => message);
1124
1129
 
1125
1130
  const promptMessages = await convertToLanguageModelPrompt({
1126
1131
  prompt: {
@@ -1230,7 +1235,13 @@ async function generateTextInternal<
1230
1235
  body: result.response?.body,
1231
1236
  };
1232
1237
 
1233
- return { ...result, response: responseData };
1238
+ return {
1239
+ ...result,
1240
+ ...(result.request != null
1241
+ ? { request: sanitizeRequestMetadata(result.request) }
1242
+ : {}),
1243
+ response: responseData,
1244
+ };
1234
1245
  });
1235
1246
  const responseTimeMs = now() - stepStartTimestampMs;
1236
1247
  const stepUsage = asLanguageModelUsage(
@@ -1298,6 +1309,15 @@ async function generateTextInternal<
1298
1309
  usage: stepUsage,
1299
1310
  content: modelCallContent,
1300
1311
  responseId: currentModelResponse.response.id,
1312
+ ...(currentModelResponse.request?.url != null
1313
+ ? {
1314
+ request: {
1315
+ url: getRequestOrigin(
1316
+ currentModelResponse.request.url,
1317
+ ),
1318
+ },
1319
+ }
1320
+ : {}),
1301
1321
  ...(currentModelResponse.providerMetadata != null
1302
1322
  ? {
1303
1323
  providerMetadata: currentModelResponse.providerMetadata,
@@ -30,6 +30,7 @@ const isOutputChunkType = {
30
30
  'model-call-response-metadata': false,
31
31
  'model-call-end': false,
32
32
  error: false,
33
+ ping: false,
33
34
  raw: false,
34
35
  } as const satisfies Record<
35
36
  Exclude<ExecuteToolsStreamPart, StreamRetryAttemptBoundaryPart>['type'],
@@ -59,6 +59,9 @@ export type LanguageModelCallEndEvent<TOOLS extends ToolSet = ToolSet> =
59
59
  /** Optional provider-specific metadata for this model call. */
60
60
  readonly providerMetadata?: ProviderMetadata;
61
61
 
62
+ /** HTTP origin reported by the provider, excluding URL credentials and path. */
63
+ readonly request?: { readonly url?: string };
64
+
62
65
  /** Performance metrics for the model call. */
63
66
  readonly performance: {
64
67
  /** Time spent waiting for the language model response in milliseconds. */
@@ -10,6 +10,7 @@ import {
10
10
  safeParseJSON,
11
11
  safeValidateTypes,
12
12
  type FlexibleSchema,
13
+ type InferSchema,
13
14
  } from '@ai-sdk/provider-utils';
14
15
  import { InvalidArgumentError } from '../error/invalid-argument-error';
15
16
  import { NoObjectGeneratedError } from '../error/no-object-generated-error';
@@ -81,6 +82,37 @@ export const text = (): Output<string, string, never> => ({
81
82
  },
82
83
  });
83
84
 
85
+ // pass through explicit `any` types for backward compat
86
+ type ValidatedSchema<SCHEMA> = 0 extends 1 & SCHEMA
87
+ ? never
88
+ : [SCHEMA] extends [FlexibleSchema]
89
+ ? SCHEMA
90
+ : never;
91
+
92
+ // The output type is the first type parameter so that an explicit output type
93
+ // (e.g. `typeof Output.object<Person>`) is preserved. Otherwise it is inferred
94
+ // from the schema.
95
+ type ResolveOutput<OUTPUT, SCHEMA> = [OUTPUT] extends [never]
96
+ ? InferSchema<SCHEMA>
97
+ : OUTPUT;
98
+
99
+ type ObjectOptions<SCHEMA> = {
100
+ /**
101
+ * The schema of the object to generate.
102
+ */
103
+ schema: SCHEMA;
104
+ /**
105
+ * Optional name of the output that should be generated.
106
+ * Used by some providers for additional LLM guidance, e.g. via tool or schema name.
107
+ */
108
+ name?: string;
109
+ /**
110
+ * Optional description of the output that should be generated.
111
+ * Used by some providers for additional LLM guidance, e.g. via tool or schema description.
112
+ */
113
+ description?: string;
114
+ };
115
+
84
116
  /**
85
117
  * Output specification for typed object generation using schemas.
86
118
  * When the model generates a text response, it will return an object that matches the schema.
@@ -91,23 +123,25 @@ export const text = (): Output<string, string, never> => ({
91
123
  *
92
124
  * @returns An output specification for generating objects with the specified schema.
93
125
  */
94
- export const object = <OBJECT>({
126
+ export function object<OBJECT>(
127
+ options: ObjectOptions<FlexibleSchema<OBJECT>>,
128
+ ): Output<OBJECT, DeepPartial<OBJECT>, never>;
129
+ export function object<OUTPUT = never, SCHEMA = FlexibleSchema<OUTPUT>>(
130
+ options: ObjectOptions<ValidatedSchema<SCHEMA>>,
131
+ ): Output<
132
+ ResolveOutput<OUTPUT, SCHEMA>,
133
+ DeepPartial<ResolveOutput<OUTPUT, SCHEMA>>,
134
+ never
135
+ >;
136
+ export function object<OBJECT>({
95
137
  schema: inputSchema,
96
138
  name,
97
139
  description,
98
- }: {
99
- schema: FlexibleSchema<OBJECT>;
100
- /**
101
- * Optional name of the output that should be generated.
102
- * Used by some providers for additional LLM guidance, e.g. via tool or schema name.
103
- */
104
- name?: string;
105
- /**
106
- * Optional description of the output that should be generated.
107
- * Used by some providers for additional LLM guidance, e.g. via tool or schema description.
108
- */
109
- description?: string;
110
- }): Output<OBJECT, DeepPartial<OBJECT>, never> => {
140
+ }: ObjectOptions<FlexibleSchema<OBJECT>>): Output<
141
+ OBJECT,
142
+ DeepPartial<OBJECT>,
143
+ never
144
+ > {
111
145
  const schema = asSchema(inputSchema);
112
146
 
113
147
  return {
@@ -183,28 +217,13 @@ export const object = <OBJECT>({
183
217
  return undefined;
184
218
  },
185
219
  };
186
- };
220
+ }
187
221
 
188
- /**
189
- * Output specification for array generation.
190
- * When the model generates a text response, it will return an array of elements.
191
- *
192
- * @param element - The schema of the array elements to generate.
193
- * @param minItems - Optional minimum number of elements to generate.
194
- * @param maxItems - Optional maximum number of elements to generate.
195
- * @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.
196
- * @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.
197
- *
198
- * @returns An output specification for generating an array of elements.
199
- */
200
- export const array = <ELEMENT>({
201
- element: inputElementSchema,
202
- minItems,
203
- maxItems,
204
- name,
205
- description,
206
- }: {
207
- element: FlexibleSchema<ELEMENT>;
222
+ type ArrayOptions<SCHEMA> = {
223
+ /**
224
+ * The schema of the array elements to generate.
225
+ */
226
+ element: SCHEMA;
208
227
  /**
209
228
  * Optional minimum number of elements to generate.
210
229
  */
@@ -223,7 +242,41 @@ export const array = <ELEMENT>({
223
242
  * Used by some providers for additional LLM guidance, e.g. via tool or schema description.
224
243
  */
225
244
  description?: string;
226
- }): Output<Array<ELEMENT>, Array<ELEMENT>, ELEMENT> => {
245
+ };
246
+
247
+ /**
248
+ * Output specification for array generation.
249
+ * When the model generates a text response, it will return an array of elements.
250
+ *
251
+ * @param element - The schema of the array elements to generate.
252
+ * @param minItems - Optional minimum number of elements to generate.
253
+ * @param maxItems - Optional maximum number of elements to generate.
254
+ * @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.
255
+ * @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.
256
+ *
257
+ * @returns An output specification for generating an array of elements.
258
+ */
259
+ export function array<ELEMENT>(
260
+ options: ArrayOptions<FlexibleSchema<ELEMENT>>,
261
+ ): Output<Array<ELEMENT>, Array<ELEMENT>, ELEMENT>;
262
+ export function array<OUTPUT = never, SCHEMA = FlexibleSchema<OUTPUT>>(
263
+ options: ArrayOptions<ValidatedSchema<SCHEMA>>,
264
+ ): Output<
265
+ Array<ResolveOutput<OUTPUT, SCHEMA>>,
266
+ Array<ResolveOutput<OUTPUT, SCHEMA>>,
267
+ ResolveOutput<OUTPUT, SCHEMA>
268
+ >;
269
+ export function array<ELEMENT>({
270
+ element: inputElementSchema,
271
+ minItems,
272
+ maxItems,
273
+ name,
274
+ description,
275
+ }: ArrayOptions<FlexibleSchema<ELEMENT>>): Output<
276
+ Array<ELEMENT>,
277
+ Array<ELEMENT>,
278
+ ELEMENT
279
+ > {
227
280
  validateArrayBound({ name: 'minItems', value: minItems });
228
281
  validateArrayBound({ name: 'maxItems', value: maxItems });
229
282
 
@@ -435,7 +488,7 @@ export const array = <ELEMENT>({
435
488
  });
436
489
  },
437
490
  };
438
- };
491
+ }
439
492
 
440
493
  function validateArrayBound({
441
494
  name,
@@ -140,6 +140,11 @@ export function smoothStream<TOOLS extends ToolSet>({
140
140
 
141
141
  return new TransformStream<TextStreamPart<TOOLS>, TextStreamPart<TOOLS>>({
142
142
  async transform(chunk, controller) {
143
+ if (chunk.type === 'ping') {
144
+ controller.enqueue(chunk);
145
+ return;
146
+ }
147
+
143
148
  // Handle non-smoothable chunks: flush buffer and pass through
144
149
  if (chunk.type !== 'text-delta' && chunk.type !== 'reasoning-delta') {
145
150
  flushBuffer(controller);
@@ -121,12 +121,13 @@ export type SteeringRun = {
121
121
 
122
122
  /**
123
123
  * Resolves the taken messages as delivered when they are part of the
124
- * messages that are sent to the model, and returns the delivered messages.
124
+ * messages that are sent to the model, and returns the delivered messages
125
+ * with their ids.
125
126
  */
126
127
  resolveTakenMessages(options: {
127
128
  stepNumber: number;
128
129
  sentMessages: ReadonlyArray<ModelMessage>;
129
- }): Array<UserModelMessage>;
130
+ }): Array<{ id: string; message: UserModelMessage }>;
130
131
 
131
132
  end(reason: SteeringNotDeliveredReason): void;
132
133
  };
@@ -235,11 +236,11 @@ class DefaultSteering implements Steering {
235
236
  const taken = this.taken;
236
237
  this.taken = [];
237
238
 
238
- const delivered: Array<UserModelMessage> = [];
239
+ const delivered: Array<{ id: string; message: UserModelMessage }> = [];
239
240
 
240
241
  for (const { id, message, resolve } of taken) {
241
242
  if (isSent({ message, sentMessages })) {
242
- delivered.push(message);
243
+ delivered.push({ id, message });
243
244
  resolve({ type: 'delivered', id, message, stepNumber });
244
245
  } else {
245
246
  resolve({
@@ -1,3 +1,7 @@
1
+ import {
2
+ getRequestOrigin,
3
+ sanitizeRequestMetadata,
4
+ } from '../telemetry/get-request-origin';
1
5
  import {
2
6
  getErrorMessage,
3
7
  type LanguageModelV4Content,
@@ -94,6 +98,7 @@ export type LanguageModelStreamPart<TOOLS extends ToolSet = ToolSet> =
94
98
  | 'tool-output-denied'
95
99
  | 'start-step'
96
100
  | 'finish-step'
101
+ | 'steering-message'
97
102
  | 'start'
98
103
  | 'abort';
99
104
  }
@@ -280,6 +285,8 @@ export async function streamLanguageModelCall<
280
285
  LanguageModelCallOptions): Promise<{
281
286
  stream: AsyncIterableStream<LanguageModelStreamPart<TOOLS>>;
282
287
  request?: {
288
+ /** Sanitized HTTP origin, when the provider reports an endpoint. */
289
+ url?: string;
283
290
  /**
284
291
  * Request HTTP body that was sent to the provider API.
285
292
  */
@@ -353,7 +360,7 @@ export async function streamLanguageModelCall<
353
360
  const {
354
361
  stream: languageModelStream,
355
362
  response,
356
- request,
363
+ request: rawRequest,
357
364
  } = await executeLanguageModelCallInTelemetryContext({
358
365
  ...languageModelCallStartEvent,
359
366
  execute: async () =>
@@ -370,6 +377,8 @@ export async function streamLanguageModelCall<
370
377
  }),
371
378
  });
372
379
 
380
+ const request = sanitizeRequestMetadata(rawRequest);
381
+
373
382
  const standardizedStream = languageModelStream.pipeThrough(
374
383
  createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({
375
384
  tools,
@@ -385,6 +394,7 @@ export async function streamLanguageModelCall<
385
394
  generateId,
386
395
  now,
387
396
  callStartTimestampMs,
397
+ request,
388
398
  onLanguageModelCallEnd,
389
399
  collectContent,
390
400
  }),
@@ -414,6 +424,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
414
424
  generateId,
415
425
  now,
416
426
  callStartTimestampMs,
427
+ request,
417
428
  onLanguageModelCallEnd,
418
429
  collectContent,
419
430
  }: {
@@ -430,6 +441,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
430
441
  generateId: IdGenerator;
431
442
  now: () => number;
432
443
  callStartTimestampMs: number;
444
+ request?: { url?: string };
433
445
  onLanguageModelCallEnd?: Arrayable<OnLanguageModelCallEndCallback<TOOLS>>;
434
446
  collectContent: boolean;
435
447
  }) {
@@ -661,6 +673,9 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform<
661
673
  usage,
662
674
  content: modelCallContent,
663
675
  responseId,
676
+ ...(request?.url != null
677
+ ? { request: { url: getRequestOrigin(request.url) } }
678
+ : {}),
664
679
  ...(chunk.providerMetadata != null
665
680
  ? { providerMetadata: chunk.providerMetadata }
666
681
  : {}),
@@ -1,6 +1,11 @@
1
1
  import type { Citation } from '../types/citation';
2
2
  import type { JSONObject } from '@ai-sdk/provider';
3
- import type { Context, IdGenerator, ToolSet } from '@ai-sdk/provider-utils';
3
+ import type {
4
+ Context,
5
+ IdGenerator,
6
+ ToolSet,
7
+ UserModelMessage,
8
+ } from '@ai-sdk/provider-utils';
4
9
  import type { ServerResponse } from 'node:http';
5
10
  import type {
6
11
  CallWarning,
@@ -551,6 +556,23 @@ export type TextStreamToolApprovalRequestPart<TOOLS extends ToolSet> =
551
556
  export type TextStreamToolApprovalResponsePart<TOOLS extends ToolSet> =
552
557
  ToolApprovalResponseOutput<TOOLS>;
553
558
 
559
+ /**
560
+ * Experimental. A steering message that was added to the run before the step
561
+ * with the given number. Streamed before the output of that step.
562
+ */
563
+ export type TextStreamSteeringMessagePart = {
564
+ type: 'steering-message';
565
+
566
+ /** The id of the steering message. */
567
+ id: string;
568
+
569
+ /** The user message that was added to the run. */
570
+ message: UserModelMessage;
571
+
572
+ /** The number of the step whose model call received the message. */
573
+ stepNumber: number;
574
+ };
575
+
554
576
  export type TextStreamStartStepPart = {
555
577
  type: 'start-step';
556
578
  request: LanguageModelRequestMetadata;
@@ -593,6 +615,10 @@ export type TextStreamRawPart = {
593
615
  rawValue: unknown;
594
616
  };
595
617
 
618
+ export type TextStreamPingPart = {
619
+ type: 'ping';
620
+ };
621
+
596
622
  export type TextStreamPart<TOOLS extends ToolSet> =
597
623
  | TextStreamTextStartPart
598
624
  | TextStreamTextEndPart
@@ -613,10 +639,12 @@ export type TextStreamPart<TOOLS extends ToolSet> =
613
639
  | TextStreamToolOutputDeniedPart<TOOLS>
614
640
  | TextStreamToolApprovalRequestPart<TOOLS>
615
641
  | TextStreamToolApprovalResponsePart<TOOLS>
642
+ | TextStreamSteeringMessagePart
616
643
  | TextStreamStartStepPart
617
644
  | TextStreamFinishStepPart
618
645
  | TextStreamStartPart
619
646
  | TextStreamFinishPart
620
647
  | TextStreamAbortPart
621
648
  | TextStreamErrorPart
649
+ | TextStreamPingPart
622
650
  | TextStreamRawPart;
@@ -2642,11 +2642,33 @@ class DefaultStreamTextResult<
2642
2642
 
2643
2643
  // steering messages are delivered when they are in the messages that
2644
2644
  // are sent to the model after prepareStep:
2645
- currentStepSteeringMessages =
2645
+ const deliveredSteeringMessages =
2646
2646
  steeringRun?.resolveTakenMessages({
2647
2647
  stepNumber: currentStep,
2648
2648
  sentMessages: stepMessages,
2649
2649
  }) ?? [];
2650
+ currentStepSteeringMessages = deliveredSteeringMessages.map(
2651
+ ({ message }) => message,
2652
+ );
2653
+
2654
+ // delivered steering messages are streamed before the step output:
2655
+ if (deliveredSteeringMessages.length > 0) {
2656
+ self.addStream(
2657
+ new ReadableStream<InternalTextStreamPart<TOOLS>>({
2658
+ start(controller) {
2659
+ for (const { id, message } of deliveredSteeringMessages) {
2660
+ controller.enqueue({
2661
+ type: 'steering-message',
2662
+ id,
2663
+ message,
2664
+ stepNumber: currentStep,
2665
+ });
2666
+ }
2667
+ controller.close();
2668
+ },
2669
+ }),
2670
+ );
2671
+ }
2650
2672
  const stepInstructions =
2651
2673
  prepareStepResult?.instructions ??
2652
2674
  prepareStepResult?.system ??
@@ -2863,6 +2885,7 @@ class DefaultStreamTextResult<
2863
2885
  if (
2864
2886
  shouldBufferToolParts &&
2865
2887
  value.type !== 'error' &&
2888
+ value.type !== 'ping' &&
2866
2889
  (isToolPart || bufferedAttemptParts.length > 0)
2867
2890
  ) {
2868
2891
  bufferedAttemptParts.push(value);
@@ -3130,6 +3153,7 @@ class DefaultStreamTextResult<
3130
3153
  case 'tool-input-end':
3131
3154
  case 'tool-input-delta':
3132
3155
  case 'tool-approval-request':
3156
+ case 'ping':
3133
3157
  case 'tool-output-denied': {
3134
3158
  enqueueStepPart(controller, chunk);
3135
3159
  break;