ai 7.0.128 → 7.0.129

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 (44) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/index.d.ts +18 -3
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +148 -32
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +10 -2
  7. package/dist/internal/index.d.ts.map +1 -1
  8. package/dist/internal/index.js +68 -16
  9. package/dist/internal/index.js.map +1 -1
  10. package/docs/02-foundations/06-provider-options.mdx +11 -10
  11. package/docs/03-agents/02-building-agents.mdx +16 -11
  12. package/docs/03-agents/07-workflow-agent.mdx +3 -3
  13. package/docs/03-ai-sdk-core/17-runtime-and-tool-context.mdx +18 -14
  14. package/docs/03-ai-sdk-core/25-settings.mdx +3 -2
  15. package/docs/03-ai-sdk-core/26-reasoning.mdx +12 -5
  16. package/docs/03-ai-sdk-core/32-decisions.mdx +17 -20
  17. package/docs/03-ai-sdk-core/35-image-generation.mdx +2 -0
  18. package/docs/04-ai-sdk-ui/21-error-handling.mdx +28 -3
  19. package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +2 -2
  20. package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +2 -2
  21. package/package.json +15 -15
  22. package/src/generate-object/generate-object.ts +10 -0
  23. package/src/generate-object/stream-object.ts +10 -0
  24. package/src/generate-speech/index.ts +13 -1
  25. package/src/generate-text/generate-text.ts +3 -1
  26. package/src/generate-text/tool-approval-signature.ts +7 -4
  27. package/src/global.ts +2 -1
  28. package/src/logger/deprecations.ts +72 -0
  29. package/src/logger/log-warnings.ts +25 -3
  30. package/src/model/as-language-model-v3.ts +4 -0
  31. package/src/prompt/convert-to-language-model-prompt.ts +7 -1
  32. package/src/realtime/encode-realtime-frame.ts +7 -2
  33. package/src/transcribe/index.ts +13 -1
  34. package/src/types/index.ts +1 -0
  35. package/src/types/language-model.ts +9 -1
  36. package/src/types/usage.ts +21 -0
  37. package/src/ui/chat.ts +16 -8
  38. package/src/ui/convert-to-model-messages.ts +40 -8
  39. package/src/ui/http-chat-transport.ts +5 -3
  40. package/src/ui/process-text-stream.ts +5 -1
  41. package/src/ui/text-stream-chat-transport.ts +3 -1
  42. package/src/ui/ui-messages.ts +8 -0
  43. package/src/ui/unavailable-tool.ts +17 -0
  44. package/src/ui/validate-ui-messages.ts +10 -2
@@ -0,0 +1,72 @@
1
+ // These codes are stable identifiers. Do not rename or reuse an existing code.
2
+ const deprecationCodes = new Map<string, string>([
3
+ ['generateObject', 'AISDK_DEP_GENERATE_OBJECT'],
4
+ ['streamObject', 'AISDK_DEP_STREAM_OBJECT'],
5
+ ['experimental_generateSpeech', 'AISDK_DEP_EXPERIMENTAL_GENERATE_SPEECH'],
6
+ ['experimental_transcribe', 'AISDK_DEP_EXPERIMENTAL_TRANSCRIBE'],
7
+ ['"image" content part', 'AISDK_DEP_IMAGE_CONTENT_PART'],
8
+ [
9
+ '"tool-result" content of type "file-data"',
10
+ 'AISDK_DEP_TOOL_RESULT_FILE_DATA',
11
+ ],
12
+ [
13
+ '"tool-result" content of type "file-url"',
14
+ 'AISDK_DEP_TOOL_RESULT_FILE_URL',
15
+ ],
16
+ ['"tool-result" content of type "file-id"', 'AISDK_DEP_TOOL_RESULT_FILE_ID'],
17
+ [
18
+ '"tool-result" content of type "file-reference"',
19
+ 'AISDK_DEP_TOOL_RESULT_FILE_REFERENCE',
20
+ ],
21
+ [
22
+ '"tool-result" content of type "image-data"',
23
+ 'AISDK_DEP_TOOL_RESULT_IMAGE_DATA',
24
+ ],
25
+ [
26
+ '"tool-result" content of type "image-url"',
27
+ 'AISDK_DEP_TOOL_RESULT_IMAGE_URL',
28
+ ],
29
+ [
30
+ '"tool-result" content of type "image-file-id"',
31
+ 'AISDK_DEP_TOOL_RESULT_IMAGE_FILE_ID',
32
+ ],
33
+ [
34
+ '"tool-result" content of type "image-file-reference"',
35
+ 'AISDK_DEP_TOOL_RESULT_IMAGE_FILE_REFERENCE',
36
+ ],
37
+ [
38
+ 'rawInput in output-error UI message parts',
39
+ 'AISDK_DEP_UI_MESSAGE_RAW_INPUT',
40
+ ],
41
+ ]);
42
+
43
+ /**
44
+ * Escape punctuation and UTF-16 code units without losing case or collapsing
45
+ * distinct settings. Underscores are escaped too, so `__` separates code parts.
46
+ */
47
+ function encodeCodePart(value: string): string {
48
+ return value.replace(
49
+ /[^a-zA-Z0-9]/g,
50
+ character =>
51
+ `_${character.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}`,
52
+ );
53
+ }
54
+
55
+ export function getDeprecationCode({
56
+ setting,
57
+ provider,
58
+ }: {
59
+ setting: string;
60
+ provider?: string;
61
+ }): string {
62
+ if (provider == null) {
63
+ return (
64
+ deprecationCodes.get(setting) ??
65
+ `AISDK_DEP_SETTING_${encodeCodePart(setting)}`
66
+ );
67
+ }
68
+
69
+ // Provider codes are scoped to the provider, but not to a particular model or
70
+ // message. This works for third-party providers without changing their spec.
71
+ return `AISDK_DEP_PROVIDER_${encodeCodePart(provider)}__${encodeCodePart(setting)}`;
72
+ }
@@ -1,4 +1,5 @@
1
1
  import type { Warning } from '../types';
2
+ import { getDeprecationCode } from './deprecations';
2
3
 
3
4
  /**
4
5
  * A function for logging warnings.
@@ -87,21 +88,24 @@ export const FIRST_WARNING_INFO_MESSAGE =
87
88
  'AI SDK Warning System: To turn off warning logging, set the AI_SDK_LOG_WARNINGS global to false.';
88
89
 
89
90
  let hasLoggedBefore = false;
91
+ const emittedDeprecationCodes = new Set<string>();
90
92
 
91
93
  function emitWarning({
92
94
  message,
93
95
  type,
96
+ code,
94
97
  }: {
95
98
  message: string;
96
99
  type: 'DeprecationWarning' | 'Warning';
100
+ code?: string;
97
101
  }) {
98
102
  if (
99
103
  typeof process !== 'undefined' &&
100
104
  typeof process.emitWarning === 'function'
101
105
  ) {
102
- process.emitWarning(message, { type });
106
+ process.emitWarning(message, code == null ? { type } : { type, code });
103
107
  } else {
104
- console.warn(message);
108
+ console.warn(code == null ? message : `[${code}] ${message}`);
105
109
  }
106
110
  }
107
111
 
@@ -111,7 +115,9 @@ function emitWarning({
111
115
  * The behavior can be customized via the `AI_SDK_LOG_WARNINGS` global variable:
112
116
  * - If set to `false`, warnings are suppressed.
113
117
  * - If set to a function, that function is called with the warnings.
114
- * - Otherwise, warnings are logged to the console using `console.warn`.
118
+ * - Otherwise, warnings use `process.emitWarning` when available, falling back
119
+ * to `console.warn`. Deprecations have stable codes and are emitted once per
120
+ * code by the default logger. Custom loggers receive every warning.
115
121
  *
116
122
  * @param options - The options containing warnings and context.
117
123
  * @param options.warnings - The warnings to log.
@@ -148,6 +154,20 @@ export const logWarnings: LogWarningsFunction = options => {
148
154
 
149
155
  // default behavior: log warnings via process.emitWarning if available, otherwise console.warn
150
156
  for (const warning of options.warnings) {
157
+ const code =
158
+ warning.type === 'deprecated'
159
+ ? getDeprecationCode({
160
+ setting: warning.setting,
161
+ provider: options.provider,
162
+ })
163
+ : undefined;
164
+ if (code != null) {
165
+ if (emittedDeprecationCodes.has(code)) {
166
+ continue;
167
+ }
168
+ emittedDeprecationCodes.add(code);
169
+ }
170
+
151
171
  const message = formatWarning({
152
172
  warning,
153
173
  provider: options.provider,
@@ -156,6 +176,7 @@ export const logWarnings: LogWarningsFunction = options => {
156
176
  emitWarning({
157
177
  message,
158
178
  type: warning.type === 'deprecated' ? 'DeprecationWarning' : 'Warning',
179
+ code,
159
180
  });
160
181
  }
161
182
  };
@@ -165,4 +186,5 @@ export const logWarnings: LogWarningsFunction = options => {
165
186
  */
166
187
  export const resetLogWarningsState = () => {
167
188
  hasLoggedBefore = false;
189
+ emittedDeprecationCodes.clear();
168
190
  };
@@ -99,5 +99,9 @@ function convertV2UsageToV3(usage: LanguageModelV2Usage): LanguageModelV3Usage {
99
99
  text: undefined,
100
100
  reasoning: usage.reasoningTokens,
101
101
  },
102
+ raw:
103
+ usage.totalTokens == null
104
+ ? undefined
105
+ : { totalTokens: usage.totalTokens },
102
106
  };
103
107
  }
@@ -123,7 +123,13 @@ export async function convertToLanguageModelPrompt({
123
123
  }
124
124
 
125
125
  lastCombinedMessage.content.push(...message.content);
126
- lastCombinedMessage.providerOptions = message.providerOptions;
126
+ lastCombinedMessage.providerOptions =
127
+ lastContentPart == null
128
+ ? mergeObjects(
129
+ lastCombinedMessage.providerOptions,
130
+ message.providerOptions,
131
+ )
132
+ : message.providerOptions;
127
133
  } else {
128
134
  combinedMessages.push(message);
129
135
  }
@@ -3,14 +3,19 @@ export const REALTIME_MAX_FRAME_BYTES = 128 * 1024;
3
3
  export const REALTIME_MAX_BUFFERED_BYTES = 128 * 1024;
4
4
 
5
5
  export type EncodedRealtimeFrame = {
6
- data: string | ArrayBuffer | ArrayBufferView | Blob;
6
+ data: string | ArrayBuffer | ArrayBufferView<ArrayBuffer> | Blob;
7
7
  byteLength: number;
8
8
  };
9
9
 
10
10
  /** Serialize once, measuring the exact payload passed to the browser. */
11
11
  export function encodeRealtimeFrame(value: unknown): EncodedRealtimeFrame {
12
- if (value instanceof ArrayBuffer || ArrayBuffer.isView(value))
12
+ if (value instanceof ArrayBuffer)
13
13
  return { data: value, byteLength: value.byteLength };
14
+ if (ArrayBuffer.isView(value))
15
+ return {
16
+ data: value as ArrayBufferView<ArrayBuffer>,
17
+ byteLength: value.byteLength,
18
+ };
14
19
  if (value instanceof Blob) return { data: value, byteLength: value.size };
15
20
  const data = typeof value === 'string' ? value : JSON.stringify(value);
16
21
  if (data === undefined)
@@ -1,5 +1,6 @@
1
1
  import type { TranscriptionResult } from './transcribe-result';
2
2
  import { transcribe } from './transcribe';
3
+ import { logWarnings } from '../logger/log-warnings';
3
4
 
4
5
  export { transcribe } from './transcribe';
5
6
  export { streamTranscribe as experimental_streamTranscribe } from './stream-transcribe';
@@ -20,7 +21,18 @@ export type {
20
21
  /**
21
22
  * @deprecated Use `transcribe` instead.
22
23
  */
23
- const experimental_transcribe = transcribe;
24
+ const experimental_transcribe: typeof transcribe = options => {
25
+ logWarnings({
26
+ warnings: [
27
+ {
28
+ type: 'deprecated',
29
+ setting: 'experimental_transcribe',
30
+ message: 'Use transcribe instead.',
31
+ },
32
+ ],
33
+ });
34
+ return transcribe(options);
35
+ };
24
36
  export { experimental_transcribe };
25
37
 
26
38
  /**
@@ -7,6 +7,7 @@ export type { ImageModelResponseMetadata } from './image-model-response-metadata
7
7
  export type { JSONValue } from './json-value';
8
8
  export type {
9
9
  CallWarning,
10
+ CallWarningRegistry,
10
11
  FinishReason,
11
12
  LanguageModel,
12
13
  ToolChoice,
@@ -80,11 +80,19 @@ export type FinishReason =
80
80
  | 'error'
81
81
  | 'other';
82
82
 
83
+ /**
84
+ * Registry for call warning variants. Packages that expose additional warning
85
+ * protocols can augment this interface.
86
+ */
87
+ export interface CallWarningRegistry {
88
+ sharedV4: SharedV4Warning;
89
+ }
90
+
83
91
  /**
84
92
  * Warning from the model provider for this call. The call will proceed, but e.g.
85
93
  * some settings might not be supported, which can lead to suboptimal results.
86
94
  */
87
- export type CallWarning = SharedV4Warning;
95
+ export type CallWarning = CallWarningRegistry[keyof CallWarningRegistry];
88
96
 
89
97
  /**
90
98
  * A source that has been used as input to generate the response.
@@ -123,6 +123,12 @@ export function addLanguageModelUsage(
123
123
  usage1: LanguageModelUsage,
124
124
  usage2: LanguageModelUsage,
125
125
  ): LanguageModelUsage {
126
+ const raw = isNullLanguageModelUsage(usage1)
127
+ ? usage2.raw
128
+ : isNullLanguageModelUsage(usage2)
129
+ ? usage1.raw
130
+ : undefined;
131
+
126
132
  return {
127
133
  inputTokens: addTokenCounts(usage1.inputTokens, usage2.inputTokens),
128
134
  inputTokenDetails: {
@@ -151,9 +157,24 @@ export function addLanguageModelUsage(
151
157
  ),
152
158
  },
153
159
  totalTokens: addTokenCounts(usage1.totalTokens, usage2.totalTokens),
160
+ ...(raw == null ? {} : { raw }),
154
161
  };
155
162
  }
156
163
 
164
+ function isNullLanguageModelUsage(usage: LanguageModelUsage): boolean {
165
+ return (
166
+ usage.inputTokens == null &&
167
+ usage.inputTokenDetails?.noCacheTokens == null &&
168
+ usage.inputTokenDetails?.cacheReadTokens == null &&
169
+ usage.inputTokenDetails?.cacheWriteTokens == null &&
170
+ usage.outputTokens == null &&
171
+ usage.outputTokenDetails?.textTokens == null &&
172
+ usage.outputTokenDetails?.reasoningTokens == null &&
173
+ usage.totalTokens == null &&
174
+ usage.raw == null
175
+ );
176
+ }
177
+
157
178
  function addTokenCounts(
158
179
  tokenCount1: number | undefined,
159
180
  tokenCount2: number | undefined,
package/src/ui/chat.ts CHANGED
@@ -315,7 +315,12 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
315
315
  status: ChatStatus;
316
316
  error?: Error;
317
317
  }) {
318
- if (this.status === status) return;
318
+ if (this.status === status) {
319
+ if (this.error !== error) {
320
+ this.state.error = error;
321
+ }
322
+ return;
323
+ }
319
324
 
320
325
  this.state.status = status;
321
326
  this.state.error = error;
@@ -1010,13 +1015,16 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
1010
1015
 
1011
1016
  isError = true;
1012
1017
 
1013
- // Network errors such as disconnected, timeout, etc.
1014
- if (
1015
- err instanceof TypeError &&
1016
- (err.message.toLowerCase().includes('fetch') ||
1017
- err.message.toLowerCase().includes('network'))
1018
- ) {
1019
- isDisconnect = true;
1018
+ if (err instanceof TypeError) {
1019
+ const message = err.message.toLowerCase();
1020
+
1021
+ isDisconnect =
1022
+ // Chromium request failures; Node.js fetch failures.
1023
+ message.includes('fetch') ||
1024
+ // Firefox request failures; Chromium response-body failures.
1025
+ message.includes('network') ||
1026
+ // Safari/WebKit request and response-body failures.
1027
+ message === 'load failed';
1020
1028
  }
1021
1029
 
1022
1030
  if (isDisconnect) {
@@ -33,6 +33,7 @@ import {
33
33
  type ToolUIPart,
34
34
  type UIMessage,
35
35
  } from './ui-messages';
36
+ import { isToolPartFromUnavailableTool } from './unavailable-tool';
36
37
  import { warnIfUIMessageHasDeprecatedRawInput } from './warn-if-ui-message-has-deprecated-raw-input';
37
38
  /**
38
39
  * Converts an array of UI messages from useChat into an array of ModelMessages that can be used
@@ -85,6 +86,39 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
85
86
  }));
86
87
  }
87
88
 
89
+ async function createModelOutput({
90
+ toolPart,
91
+ toolName,
92
+ output,
93
+ errorMode,
94
+ }: {
95
+ toolPart: ToolUIPart<InferUIMessageTools<UI_MESSAGE>> | DynamicToolUIPart;
96
+ toolName: string;
97
+ output: unknown;
98
+ errorMode: 'none' | 'text' | 'json';
99
+ }) {
100
+ const tool = getOwn(options?.tools, toolName);
101
+
102
+ if (
103
+ errorMode === 'none' &&
104
+ tool == null &&
105
+ isToolPartFromUnavailableTool(toolPart)
106
+ ) {
107
+ return {
108
+ type: 'text' as const,
109
+ value: 'Tool output omitted because the tool is no longer available.',
110
+ };
111
+ }
112
+
113
+ return createToolModelOutput({
114
+ toolCallId: toolPart.toolCallId,
115
+ input: toolPart.input,
116
+ output,
117
+ tool,
118
+ errorMode,
119
+ });
120
+ }
121
+
88
122
  for (const message of messages) {
89
123
  switch (message.role) {
90
124
  case 'system': {
@@ -284,14 +318,13 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
284
318
  type: 'tool-result',
285
319
  toolCallId: part.toolCallId,
286
320
  toolName,
287
- output: await createToolModelOutput({
288
- toolCallId: part.toolCallId,
289
- input: part.input,
321
+ output: await createModelOutput({
322
+ toolPart: part,
323
+ toolName,
290
324
  output:
291
325
  part.state === 'output-error'
292
326
  ? part.errorText
293
327
  : part.output,
294
- tool: getOwn(options?.tools, toolName),
295
328
  errorMode:
296
329
  part.state === 'output-error' ? 'json' : 'none',
297
330
  }),
@@ -403,14 +436,13 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
403
436
  type: 'tool-result',
404
437
  toolCallId: toolPart.toolCallId,
405
438
  toolName,
406
- output: await createToolModelOutput({
407
- toolCallId: toolPart.toolCallId,
408
- input: toolPart.input,
439
+ output: await createModelOutput({
440
+ toolPart,
441
+ toolName,
409
442
  output:
410
443
  toolPart.state === 'output-error'
411
444
  ? toolPart.errorText
412
445
  : toolPart.output,
413
- tool: getOwn(options?.tools, toolName),
414
446
  errorMode:
415
447
  toolPart.state === 'output-error' ? 'text' : 'none',
416
448
  }),
@@ -13,10 +13,12 @@ import type { UIMessage } from './ui-messages';
13
13
 
14
14
  function appendPathToUrl(url: string, path: string): string {
15
15
  const queryOrFragmentStart = url.search(/[?#]/);
16
+ const urlPath =
17
+ queryOrFragmentStart === -1 ? url : url.slice(0, queryOrFragmentStart);
18
+ const suffix =
19
+ queryOrFragmentStart === -1 ? '' : url.slice(queryOrFragmentStart);
16
20
 
17
- return queryOrFragmentStart === -1
18
- ? `${url}${path}`
19
- : `${url.slice(0, queryOrFragmentStart)}${path}${url.slice(queryOrFragmentStart)}`;
21
+ return `${urlPath.endsWith('/') && path.startsWith('/') ? urlPath.slice(0, -1) : urlPath}${path}${suffix}`;
20
22
  }
21
23
 
22
24
  export type PrepareSendMessagesRequest<UI_MESSAGE extends UIMessage> = (
@@ -5,7 +5,11 @@ export async function processTextStream({
5
5
  stream: ReadableStream<Uint8Array>;
6
6
  onTextPart: (chunk: string) => Promise<void> | void;
7
7
  }): Promise<void> {
8
- const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
8
+ const reader = stream
9
+ .pipeThrough(
10
+ new TextDecoderStream() as ReadableWritablePair<string, Uint8Array>,
11
+ )
12
+ .getReader();
9
13
  while (true) {
10
14
  const { done, value } = await reader.read();
11
15
  if (done) {
@@ -17,7 +17,9 @@ export class TextStreamChatTransport<
17
17
  stream: ReadableStream<Uint8Array<ArrayBufferLike>>,
18
18
  ): ReadableStream<UIMessageChunk> {
19
19
  return transformTextToUiMessageStream({
20
- stream: stream.pipeThrough(new TextDecoderStream()),
20
+ stream: stream.pipeThrough(
21
+ new TextDecoderStream() as ReadableWritablePair<string, Uint8Array>,
22
+ ),
21
23
  });
22
24
  }
23
25
  }
@@ -421,6 +421,14 @@ export type ToolUIPart<TOOLS extends UITools = UITools> = ValueOf<{
421
421
  export type DynamicToolUIPart = {
422
422
  type: 'dynamic-tool';
423
423
 
424
+ /**
425
+ * `false` when a static tool part was normalized to a dynamic tool part
426
+ * because its current tool schema was unavailable or incompatible.
427
+ *
428
+ * This preserves its static origin across persistence boundaries.
429
+ */
430
+ dynamic?: false;
431
+
424
432
  /**
425
433
  * Name of the tool that is being called.
426
434
  */
@@ -0,0 +1,17 @@
1
+ import type { DynamicToolUIPart, ToolUIPart } from './ui-messages';
2
+
3
+ export function markToolPartAsUnavailable(
4
+ part: DynamicToolUIPart,
5
+ ): DynamicToolUIPart {
6
+ // Preserve the static tool's provenance across persistence boundaries so
7
+ // model-message conversion never falls back to its unfiltered raw output.
8
+ part.dynamic = false;
9
+
10
+ return part;
11
+ }
12
+
13
+ export function isToolPartFromUnavailableTool(
14
+ part: ToolUIPart | DynamicToolUIPart,
15
+ ): boolean {
16
+ return part.type === 'dynamic-tool' && part.dynamic === false;
17
+ }
@@ -22,6 +22,7 @@ import type {
22
22
  ToolUIPart,
23
23
  UIMessage,
24
24
  } from './ui-messages';
25
+ import { markToolPartAsUnavailable } from './unavailable-tool';
25
26
  import { warnIfUIMessageHasDeprecatedRawInput } from './warn-if-ui-message-has-deprecated-raw-input';
26
27
 
27
28
  const toolMetadataSchema: ZodType<JSONObject> = z.record(
@@ -43,11 +44,11 @@ function isEmptyObject(value: unknown): value is Record<string, never> {
43
44
  function asDynamicToolPart(toolPart: ToolUIPart): DynamicToolUIPart {
44
45
  const { type, ...part } = toolPart;
45
46
 
46
- return {
47
+ return markToolPartAsUnavailable({
47
48
  ...part,
48
49
  type: 'dynamic-tool',
49
50
  toolName: type.slice(5),
50
- } as DynamicToolUIPart;
51
+ } as DynamicToolUIPart);
51
52
  }
52
53
 
53
54
  function getToolPartInputSchemaInput(
@@ -148,6 +149,7 @@ const uiMessagesSchema = lazySchema(() => {
148
149
  }),
149
150
  z.object({
150
151
  type: z.literal('dynamic-tool'),
152
+ dynamic: z.literal(false).optional(),
151
153
  toolName: z.string(),
152
154
  toolCallId: z.string(),
153
155
  title: z.string().optional(),
@@ -163,6 +165,7 @@ const uiMessagesSchema = lazySchema(() => {
163
165
  }),
164
166
  z.object({
165
167
  type: z.literal('dynamic-tool'),
168
+ dynamic: z.literal(false).optional(),
166
169
  toolName: z.string(),
167
170
  toolCallId: z.string(),
168
171
  title: z.string().optional(),
@@ -177,6 +180,7 @@ const uiMessagesSchema = lazySchema(() => {
177
180
  }),
178
181
  z.object({
179
182
  type: z.literal('dynamic-tool'),
183
+ dynamic: z.literal(false).optional(),
180
184
  toolName: z.string(),
181
185
  toolCallId: z.string(),
182
186
  title: z.string().optional(),
@@ -191,6 +195,7 @@ const uiMessagesSchema = lazySchema(() => {
191
195
  }),
192
196
  z.object({
193
197
  type: z.literal('dynamic-tool'),
198
+ dynamic: z.literal(false).optional(),
194
199
  toolName: z.string(),
195
200
  toolCallId: z.string(),
196
201
  title: z.string().optional(),
@@ -205,6 +210,7 @@ const uiMessagesSchema = lazySchema(() => {
205
210
  }),
206
211
  z.object({
207
212
  type: z.literal('dynamic-tool'),
213
+ dynamic: z.literal(false).optional(),
208
214
  toolName: z.string(),
209
215
  toolCallId: z.string(),
210
216
  title: z.string().optional(),
@@ -221,6 +227,7 @@ const uiMessagesSchema = lazySchema(() => {
221
227
  }),
222
228
  z.object({
223
229
  type: z.literal('dynamic-tool'),
230
+ dynamic: z.literal(false).optional(),
224
231
  toolName: z.string(),
225
232
  toolCallId: z.string(),
226
233
  title: z.string().optional(),
@@ -237,6 +244,7 @@ const uiMessagesSchema = lazySchema(() => {
237
244
  }),
238
245
  z.object({
239
246
  type: z.literal('dynamic-tool'),
247
+ dynamic: z.literal(false).optional(),
240
248
  toolName: z.string(),
241
249
  toolCallId: z.string(),
242
250
  title: z.string().optional(),