ai 7.0.91 → 7.0.92

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.
@@ -2069,11 +2069,24 @@ To see `streamText` in action, check out [these examples](#examples).
2069
2069
  {
2070
2070
  type: 'OnAbortResult',
2071
2071
  parameters: [
2072
+ {
2073
+ name: 'callId',
2074
+ type: 'string',
2075
+ description:
2076
+ 'Unique identifier for this generation call, used to correlate events.',
2077
+ },
2072
2078
  {
2073
2079
  name: 'steps',
2074
2080
  type: 'Array<StepResult>',
2075
2081
  description: 'Details for all previously finished steps.',
2076
2082
  },
2083
+ {
2084
+ name: 'reason',
2085
+ type: 'unknown',
2086
+ isOptional: true,
2087
+ description:
2088
+ 'The raw abort reason from the AbortSignal, when one is available.',
2089
+ },
2077
2090
  ],
2078
2091
  },
2079
2092
  ],
@@ -3979,10 +3992,10 @@ To see `streamText` in action, check out [these examples](#examples).
3979
3992
  },
3980
3993
  {
3981
3994
  name: 'reason',
3982
- type: 'unknown',
3995
+ type: 'string',
3983
3996
  isOptional: true,
3984
3997
  description:
3985
- 'Optional abort reason (from AbortSignal.reason) when the stream is aborted.',
3998
+ 'Optional serialized abort reason when the stream is aborted.',
3986
3999
  },
3987
4000
  ],
3988
4001
  },
@@ -38,7 +38,7 @@ const result = streamText({
38
38
  type: 'number | null',
39
39
  isOptional: true,
40
40
  description:
41
- 'The delay in milliseconds between outputting each chunk. Defaults to 10ms. Set to `null` to disable delays.',
41
+ 'The delay in milliseconds between outputting each chunk. Defaults to 10ms. Set to `null` to disable delays. The delay is skipped while the document is hidden (e.g. browser background tabs), where timer throttling would otherwise stall the stream.',
42
42
  },
43
43
  {
44
44
  name: 'chunking',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "7.0.91",
3
+ "version": "7.0.92",
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,18 +42,18 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
- "@ai-sdk/gateway": "4.0.73",
45
+ "@ai-sdk/gateway": "4.0.74",
46
46
  "@ai-sdk/provider": "4.0.10",
47
47
  "@ai-sdk/provider-utils": "5.0.36"
48
48
  },
49
49
  "devDependencies": {
50
- "@ai-sdk/amazon-bedrock": "5.0.73",
50
+ "@ai-sdk/amazon-bedrock": "5.0.74",
51
51
  "@ai-sdk/deepseek": "3.0.39",
52
52
  "@ai-sdk/google": "4.0.63",
53
53
  "@ai-sdk/groq": "4.0.37",
54
54
  "@ai-sdk/huggingface": "2.0.43",
55
55
  "@ai-sdk/moonshotai": "3.0.45",
56
- "@ai-sdk/openai": "4.0.57",
56
+ "@ai-sdk/openai": "4.0.58",
57
57
  "@ai-sdk/test-server": "2.0.1",
58
58
  "@ai-sdk/xai": "4.0.54",
59
59
  "@edge-runtime/vm": "^5.0.0",
@@ -294,7 +294,7 @@ export type GenerateTextEndEvent<
294
294
  };
295
295
 
296
296
  /**
297
- * Event passed to the telemetry `onAbort` callback.
297
+ * Event passed to an `onAbort` callback for text generation.
298
298
  *
299
299
  * Called when a streaming text generation operation is aborted before it
300
300
  * completes.
@@ -10,6 +10,15 @@ const CHUNKING_REGEXPS = {
10
10
  line: /\n+/m,
11
11
  };
12
12
 
13
+ // Browsers heavily throttle timers in hidden documents (e.g. background tabs),
14
+ // which would stall the smoothing delay and, through backpressure, the entire
15
+ // stream. Smoothing has no visual purpose there, so the delay is skipped.
16
+ function isDocumentHidden(): boolean {
17
+ return (
18
+ typeof document !== 'undefined' && document.visibilityState === 'hidden'
19
+ );
20
+ }
21
+
13
22
  /**
14
23
  * Detects the first chunk in a buffer.
15
24
  *
@@ -22,7 +31,7 @@ export type ChunkDetector = (buffer: string) => string | undefined | null;
22
31
  /**
23
32
  * Smooths text and reasoning streaming output.
24
33
  *
25
- * @param delayInMs - The delay in milliseconds between each chunk. Defaults to 10ms. Can be set to `null` to skip the delay.
34
+ * @param delayInMs - The delay in milliseconds between each chunk. Defaults to 10ms. Can be set to `null` to skip the delay. The delay is skipped while the document is hidden (e.g. browser background tabs), where timer throttling would otherwise stall the stream.
26
35
  * @param chunking - Controls how the text is chunked for streaming. Use "word" to stream word by word (default), "line" to stream line by line, provide a custom RegExp pattern that does not match the empty string for custom chunking, provide an Intl.Segmenter for locale-aware word segmentation (recommended for CJK languages), or provide a custom ChunkDetector function.
27
36
  *
28
37
  * @returns A transform stream that smooths text streaming output.
@@ -126,7 +135,10 @@ export function smoothStream<TOOLS extends ToolSet>({
126
135
  function flushBuffer(
127
136
  controller: TransformStreamDefaultController<TextStreamPart<TOOLS>>,
128
137
  ) {
129
- if (buffer.length > 0 && type !== undefined) {
138
+ if (
139
+ type !== undefined &&
140
+ (buffer.length > 0 || providerMetadata != null)
141
+ ) {
130
142
  controller.enqueue({
131
143
  type,
132
144
  text: buffer,
@@ -148,7 +160,10 @@ export function smoothStream<TOOLS extends ToolSet>({
148
160
  }
149
161
 
150
162
  // Flush buffer when type or id changes
151
- if ((chunk.type !== type || chunk.id !== id) && buffer.length > 0) {
163
+ if (
164
+ (chunk.type !== type || chunk.id !== id) &&
165
+ (buffer.length > 0 || providerMetadata != null)
166
+ ) {
152
167
  flushBuffer(controller);
153
168
  }
154
169
 
@@ -167,7 +182,7 @@ export function smoothStream<TOOLS extends ToolSet>({
167
182
  controller.enqueue({ type, text: match, id });
168
183
  buffer = buffer.slice(match.length);
169
184
 
170
- await delay(delayInMs);
185
+ await delay(isDocumentHidden() ? null : delayInMs);
171
186
  }
172
187
  },
173
188
  });
@@ -95,6 +95,7 @@ import {
95
95
  type ActiveToolSubset,
96
96
  } from './filter-active-tools';
97
97
  import type {
98
+ GenerateTextAbortEvent,
98
99
  GenerateTextEndEvent,
99
100
  GenerateTextOnStartCallback,
100
101
  GenerateTextOnStepEndCallback,
@@ -329,12 +330,7 @@ export type StreamTextOnEndCallback<
329
330
  export type StreamTextOnAbortCallback<
330
331
  TOOLS extends ToolSet,
331
332
  RUNTIME_CONTEXT extends Context,
332
- > = Callback<{
333
- /**
334
- * Details for all previously finished steps.
335
- */
336
- readonly steps: StepResult<TOOLS, RUNTIME_CONTEXT>[];
337
- }>;
333
+ > = Callback<GenerateTextAbortEvent<TOOLS, RUNTIME_CONTEXT>>;
338
334
 
339
335
  /**
340
336
  * Generate a text and call tools for a given prompt using a language model.
@@ -76,7 +76,7 @@ export async function callCompletionApi({
76
76
 
77
77
  if (!response.ok) {
78
78
  throw new Error(
79
- (await response.text()) ?? 'Failed to fetch the chat response.',
79
+ (await response.text()) || 'Failed to fetch the chat response.',
80
80
  );
81
81
  }
82
82
 
@@ -201,7 +201,7 @@ export abstract class HttpChatTransport<
201
201
 
202
202
  if (!response.ok) {
203
203
  throw new Error(
204
- (await response.text()) ?? 'Failed to fetch the chat response.',
204
+ (await response.text()) || 'Failed to fetch the chat response.',
205
205
  );
206
206
  }
207
207
 
@@ -257,7 +257,7 @@ export abstract class HttpChatTransport<
257
257
 
258
258
  if (!response.ok) {
259
259
  throw new Error(
260
- (await response.text()) ?? 'Failed to fetch the chat response.',
260
+ (await response.text()) || 'Failed to fetch the chat response.',
261
261
  );
262
262
  }
263
263
 
@@ -43,7 +43,7 @@ export function asAsyncIterableStream<T>(
43
43
  * Implements the async iterator protocol for the stream.
44
44
  * Ensures proper cleanup (cancelling and releasing the reader) on completion, early exit, or error.
45
45
  */
46
- (stream as AsyncIterableStream<T>)[Symbol.asyncIterator] = function (
46
+ (stream as unknown as AsyncIterable<T>)[Symbol.asyncIterator] = function (
47
47
  this: ReadableStream<T>,
48
48
  ): AsyncIterator<T> {
49
49
  const reader = this.getReader();