ai 7.0.17 → 7.0.19

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 (50) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/index.d.ts +38 -3
  3. package/dist/index.js +160 -77
  4. package/dist/index.js.map +1 -1
  5. package/dist/internal/index.js +43 -31
  6. package/dist/internal/index.js.map +1 -1
  7. package/docs/02-foundations/02-providers-and-models.mdx +57 -52
  8. package/docs/02-getting-started/00-choosing-a-provider.mdx +1 -16
  9. package/docs/02-getting-started/01-navigating-the-library.mdx +12 -12
  10. package/docs/02-getting-started/02-nextjs-app-router.mdx +2 -36
  11. package/docs/02-getting-started/03-nextjs-pages-router.mdx +2 -36
  12. package/docs/02-getting-started/04-svelte.mdx +2 -34
  13. package/docs/02-getting-started/05-nuxt.mdx +2 -36
  14. package/docs/02-getting-started/06-nodejs.mdx +1 -18
  15. package/docs/02-getting-started/07-expo.mdx +3 -62
  16. package/docs/02-getting-started/08-tanstack-start.mdx +2 -36
  17. package/docs/02-getting-started/09-coding-agents.mdx +2 -32
  18. package/docs/03-ai-sdk-core/16-mcp-tools.mdx +44 -0
  19. package/docs/03-ai-sdk-core/30-embeddings.mdx +18 -18
  20. package/docs/03-ai-sdk-core/38-video-generation.mdx +22 -3
  21. package/docs/03-ai-sdk-harnesses/02-harness-agent.mdx +1 -28
  22. package/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx +7 -7
  23. package/docs/03-ai-sdk-harnesses/06-workflow-utilities.mdx +1 -16
  24. package/docs/03-ai-sdk-harnesses/08-terminal-ui.mdx +1 -28
  25. package/docs/04-ai-sdk-ui/01-overview.mdx +5 -5
  26. package/docs/04-ai-sdk-ui/08-object-generation.mdx +7 -10
  27. package/docs/07-reference/01-ai-sdk-core/13-generate-video.mdx +3 -2
  28. package/docs/07-reference/02-ai-sdk-ui/03-use-object.mdx +6 -9
  29. package/docs/07-reference/02-ai-sdk-ui/index.mdx +5 -5
  30. package/package.json +4 -4
  31. package/src/generate-text/collect-tool-approvals.ts +17 -4
  32. package/src/generate-text/execute-tool-call.ts +3 -2
  33. package/src/generate-text/execute-tools-from-stream.ts +2 -1
  34. package/src/generate-text/generate-text.ts +5 -4
  35. package/src/generate-text/index.ts +1 -0
  36. package/src/generate-text/invoke-tool-callbacks-from-stream.ts +6 -4
  37. package/src/generate-text/parse-tool-call.ts +5 -4
  38. package/src/generate-text/resolve-tool-approval.ts +9 -6
  39. package/src/generate-text/stream-language-model-call.ts +2 -1
  40. package/src/generate-text/stream-text.ts +3 -2
  41. package/src/generate-text/to-response-messages.ts +4 -3
  42. package/src/generate-text/tool-approval-signature.ts +4 -40
  43. package/src/generate-text/tool-fingerprint.ts +76 -0
  44. package/src/generate-text/validate-tool-approvals.ts +6 -1
  45. package/src/generate-video/generate-video.ts +96 -21
  46. package/src/ui/convert-to-model-messages.ts +3 -2
  47. package/src/ui/process-ui-message-stream.ts +3 -0
  48. package/src/ui/validate-ui-messages.ts +2 -1
  49. package/src/util/canonical-hash.ts +44 -0
  50. package/src/util/get-own.ts +18 -0
@@ -33,22 +33,7 @@ Once you've installed the `ai` package, you already have the full AI SDK documen
33
33
 
34
34
  Install the `ai` package if you haven't already:
35
35
 
36
- <div className="my-4">
37
- <Tabs items={['pnpm', 'npm', 'yarn', 'bun']}>
38
- <Tab>
39
- <Snippet text="pnpm add ai" dark />
40
- </Tab>
41
- <Tab>
42
- <Snippet text="npm install ai" dark />
43
- </Tab>
44
- <Tab>
45
- <Snippet text="yarn add ai" dark />
46
- </Tab>
47
- <Tab>
48
- <Snippet text="bun add ai" dark />
49
- </Tab>
50
- </Tabs>
51
- </div>
36
+ <InstallPackages packages="ai" />
52
37
 
53
38
  After installation, your agent can reference the bundled source code and documentation at paths like:
54
39
 
@@ -70,22 +55,7 @@ AI SDK DevTools gives you full visibility into your AI SDK calls during developm
70
55
 
71
56
  Install the DevTools package:
72
57
 
73
- <div className="my-4">
74
- <Tabs items={['pnpm', 'npm', 'yarn', 'bun']}>
75
- <Tab>
76
- <Snippet text="pnpm add @ai-sdk/devtools" dark />
77
- </Tab>
78
- <Tab>
79
- <Snippet text="npm install @ai-sdk/devtools" dark />
80
- </Tab>
81
- <Tab>
82
- <Snippet text="yarn add @ai-sdk/devtools" dark />
83
- </Tab>
84
- <Tab>
85
- <Snippet text="bun add @ai-sdk/devtools" dark />
86
- </Tab>
87
- </Tabs>
88
- </div>
58
+ <InstallPackages packages="@ai-sdk/devtools" />
89
59
 
90
60
  ### Register the integration
91
61
 
@@ -518,6 +518,50 @@ Your handler must return an object with an `action` field that can be one of:
518
518
  - `'decline'`: User chose not to provide the information.
519
519
  - `'cancel'`: User cancelled the operation entirely.
520
520
 
521
+ ## Detecting tool-definition drift ("rug pull")
522
+
523
+ An MCP server sends tool definitions (name, description, input schema) when your
524
+ app first connects, and you typically review and approve them at that point.
525
+ Nothing in the protocol prevents the server from later serving a _different_
526
+ definition for the same tool name — for example a description carrying injected
527
+ instructions, or an input schema widened with an extra field. Because the SDK
528
+ uses whatever tools you pass on each call, a mutated definition returned by a
529
+ later `mcpClient.tools()` fetch would be used without any comparison to what was
530
+ approved. This is the MCP ["rug pull"](https://invariantlabs.ai/blog/mcp-security-notification-tool-poisoning-attacks)
531
+ class of attack.
532
+
533
+ The AI SDK provides two functions to pin the approved definitions and detect
534
+ changes. `fingerprintTools` digests the server-controlled, security-relevant
535
+ fields of each tool (string `description`, resolved input schema, and `title`)
536
+ into a stable map of tool name to digest. `detectToolDrift` diffs two such maps.
537
+ Your app owns baseline storage and the response to drift (block, force
538
+ re-approval, or alert):
539
+
540
+ ```typescript
541
+ import { fingerprintTools, detectToolDrift } from 'ai';
542
+
543
+ // Trust time (first connect, human-reviewed): capture and persist the baseline.
544
+ const baseline = await fingerprintTools(await mcpClient.tools());
545
+
546
+ // Every later fetch, before handing tools to generateText:
547
+ const tools = await mcpClient.tools();
548
+ const drift = detectToolDrift(await fingerprintTools(tools), baseline);
549
+
550
+ if (drift.changed.length || drift.added.length) {
551
+ // A pinned definition changed, or a new tool appeared. Block, re-approve,
552
+ // or alert per your policy — do not silently pass `tools` to the model.
553
+ }
554
+ ```
555
+
556
+ <Note>
557
+ This detects mutation of a tool's description, input schema, or title — the
558
+ prompt-injection and schema-widening vectors. It cannot detect a
559
+ behavior/endpoint swap where the name, description, and schema are all
560
+ unchanged, because the tool runs remotely on the MCP server and that change is
561
+ invisible to the client. Core stays unopinionated: it does not persist
562
+ baselines or block calls — those are your app's responsibility.
563
+ </Note>
564
+
521
565
  ## Examples
522
566
 
523
567
  You can see MCP in action in the following examples:
@@ -219,21 +219,21 @@ const embeddingModelWithDefaults = wrapEmbeddingModel({
219
219
 
220
220
  Several providers offer embedding models:
221
221
 
222
- | Provider | Model | Embedding Dimensions | Multimodal |
223
- | ----------------------------------------------------------------------------- | ------------------------------- | -------------------- | ------------------- |
224
- | [OpenAI](/providers/ai-sdk-providers/openai#embedding-models) | `text-embedding-3-large` | 3072 | <Cross size={18} /> |
225
- | [OpenAI](/providers/ai-sdk-providers/openai#embedding-models) | `text-embedding-3-small` | 1536 | <Cross size={18} /> |
226
- | [OpenAI](/providers/ai-sdk-providers/openai#embedding-models) | `text-embedding-ada-002` | 1536 | <Cross size={18} /> |
227
- | [Google](/providers/ai-sdk-providers/google#embedding-models) | `gemini-embedding-001` | 3072 | <Cross size={18} /> |
228
- | [Google](/providers/ai-sdk-providers/google#embedding-models) | `gemini-embedding-2` | 3072 | <Check size={18} /> |
229
- | [Google](/providers/ai-sdk-providers/google#embedding-models) | `gemini-embedding-2-preview` | 3072 | <Check size={18} /> |
230
- | [Mistral](/providers/ai-sdk-providers/mistral#embedding-models) | `mistral-embed` | 1024 | <Cross size={18} /> |
231
- | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-v3.0` | 1024 | <Cross size={18} /> |
232
- | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-multilingual-v3.0` | 1024 | <Cross size={18} /> |
233
- | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-light-v3.0` | 384 | <Cross size={18} /> |
234
- | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-multilingual-light-v3.0` | 384 | <Cross size={18} /> |
235
- | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-v2.0` | 4096 | <Cross size={18} /> |
236
- | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-light-v2.0` | 1024 | <Cross size={18} /> |
237
- | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-multilingual-v2.0` | 768 | <Cross size={18} /> |
238
- | [Amazon Bedrock](/providers/ai-sdk-providers/amazon-bedrock#embedding-models) | `amazon.titan-embed-text-v1` | 1536 | <Cross size={18} /> |
239
- | [Amazon Bedrock](/providers/ai-sdk-providers/amazon-bedrock#embedding-models) | `amazon.titan-embed-text-v2:0` | 1024 | <Cross size={18} /> |
222
+ | Provider | Model | Embedding Dimensions | Multimodal |
223
+ | ----------------------------------------------------------------------------- | ------------------------------- | -------------------- | ---------- |
224
+ | [OpenAI](/providers/ai-sdk-providers/openai#embedding-models) | `text-embedding-3-large` | 3072 | <Cross /> |
225
+ | [OpenAI](/providers/ai-sdk-providers/openai#embedding-models) | `text-embedding-3-small` | 1536 | <Cross /> |
226
+ | [OpenAI](/providers/ai-sdk-providers/openai#embedding-models) | `text-embedding-ada-002` | 1536 | <Cross /> |
227
+ | [Google](/providers/ai-sdk-providers/google#embedding-models) | `gemini-embedding-001` | 3072 | <Cross /> |
228
+ | [Google](/providers/ai-sdk-providers/google#embedding-models) | `gemini-embedding-2` | 3072 | <Check /> |
229
+ | [Google](/providers/ai-sdk-providers/google#embedding-models) | `gemini-embedding-2-preview` | 3072 | <Check /> |
230
+ | [Mistral](/providers/ai-sdk-providers/mistral#embedding-models) | `mistral-embed` | 1024 | <Cross /> |
231
+ | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-v3.0` | 1024 | <Cross /> |
232
+ | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-multilingual-v3.0` | 1024 | <Cross /> |
233
+ | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-light-v3.0` | 384 | <Cross /> |
234
+ | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-multilingual-light-v3.0` | 384 | <Cross /> |
235
+ | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-v2.0` | 4096 | <Cross /> |
236
+ | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-light-v2.0` | 1024 | <Cross /> |
237
+ | [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-multilingual-v2.0` | 768 | <Cross /> |
238
+ | [Amazon Bedrock](/providers/ai-sdk-providers/amazon-bedrock#embedding-models) | `amazon.titan-embed-text-v1` | 1536 | <Cross /> |
239
+ | [Amazon Bedrock](/providers/ai-sdk-providers/amazon-bedrock#embedding-models) | `amazon.titan-embed-text-v2:0` | 1024 | <Cross /> |
@@ -194,11 +194,11 @@ const { video } = await generateVideo({
194
194
  });
195
195
  ```
196
196
 
197
- ### Reference Images
197
+ ### Reference Inputs
198
198
 
199
199
  Some video models support reference-to-video generation, where you provide one or
200
- more reference images that the model incorporates into the generated video. Use the `inputReferences` option to pass
201
- these images in a provider-agnostic way:
200
+ more reference images or videos that the model incorporates into the generated video. Use the `inputReferences` option to pass
201
+ these inputs in a provider-agnostic way:
202
202
 
203
203
  ```tsx highlight={"5-8"}
204
204
  const { video } = await generateVideo({
@@ -211,6 +211,25 @@ const { video } = await generateVideo({
211
211
  });
212
212
  ```
213
213
 
214
+ For URL-based video references, use the object form with an explicit `mediaType`:
215
+
216
+ ```tsx highlight={"5-10"}
217
+ const { video } = await generateVideo({
218
+ model: __VIDEO_MODEL__,
219
+ prompt: 'Match the motion in the reference clip',
220
+ inputReferences: [
221
+ {
222
+ data: 'https://example.com/reference.mp4',
223
+ mediaType: 'video/mp4',
224
+ },
225
+ ],
226
+ });
227
+ ```
228
+
229
+ Providers route each reference by its media type (image vs. video) and emit a
230
+ warning when a reference kind is unsupported (for example, providers that accept
231
+ only image references warn and ignore a video reference).
232
+
214
233
  ### Providing a Seed
215
234
 
216
235
  You can provide a seed to the `experimental_generateVideo` function to control the output of the video generation process.
@@ -13,34 +13,7 @@ results while a preconfigured harness powers these results.
13
13
 
14
14
  Install the core harness package, a harness adapter, and a sandbox provider:
15
15
 
16
- <div className="my-4">
17
- <Tabs items={['pnpm', 'npm', 'yarn', 'bun']}>
18
- <Tab>
19
- <Snippet
20
- text="pnpm add @ai-sdk/harness @ai-sdk/harness-claude-code @ai-sdk/sandbox-vercel"
21
- dark
22
- />
23
- </Tab>
24
- <Tab>
25
- <Snippet
26
- text="npm install @ai-sdk/harness @ai-sdk/harness-claude-code @ai-sdk/sandbox-vercel"
27
- dark
28
- />
29
- </Tab>
30
- <Tab>
31
- <Snippet
32
- text="yarn add @ai-sdk/harness @ai-sdk/harness-claude-code @ai-sdk/sandbox-vercel"
33
- dark
34
- />
35
- </Tab>
36
- <Tab>
37
- <Snippet
38
- text="bun add @ai-sdk/harness @ai-sdk/harness-claude-code @ai-sdk/sandbox-vercel"
39
- dark
40
- />
41
- </Tab>
42
- </Tabs>
43
- </div>
16
+ <InstallPackages packages="@ai-sdk/harness @ai-sdk/harness-claude-code @ai-sdk/sandbox-vercel" />
44
17
 
45
18
  Bridge-backed harnesses such as Claude Code and Codex require using real network sandbox
46
19
  like `@ai-sdk/sandbox-vercel`. Host-runtime harnesses such as Pi can also run with
@@ -28,10 +28,10 @@ The AI SDK includes the following harness adapters:
28
28
 
29
29
  ## Adapter Capabilities
30
30
 
31
- | Adapter | Runtime location | Custom tools | Custom skills | Built-in tool approval | Built-in tool filtering |
32
- | ------------------------------------------------------ | ---------------- | ------------------- | ------------------- | ---------------------- | -------------------------------------- |
33
- | [Claude Code](/providers/ai-sdk-harnesses/claude-code) | Sandbox bridge | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
34
- | [Codex](/providers/ai-sdk-harnesses/codex) | Sandbox bridge | <Check size={18} /> | <Check size={18} /> | <Cross size={18} /> | <Cross size={18} /> |
35
- | [Deep Agents](/providers/ai-sdk-harnesses/deepagents) | Sandbox bridge | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> via auto-rejection |
36
- | [OpenCode](/providers/ai-sdk-harnesses/opencode) | Sandbox bridge | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> via auto-rejection |
37
- | [Pi](/providers/ai-sdk-harnesses/pi) | Host process | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
31
+ | Adapter | Runtime location | Custom tools | Custom skills | Built-in tool approval | Built-in tool filtering |
32
+ | ------------------------------------------------------ | ---------------- | ------------ | ------------- | ---------------------- | ---------------------------- |
33
+ | [Claude Code](/providers/ai-sdk-harnesses/claude-code) | Sandbox bridge | <Check /> | <Check /> | <Check /> | <Check /> |
34
+ | [Codex](/providers/ai-sdk-harnesses/codex) | Sandbox bridge | <Check /> | <Check /> | <Cross /> | <Cross /> |
35
+ | [Deep Agents](/providers/ai-sdk-harnesses/deepagents) | Sandbox bridge | <Check /> | <Check /> | <Check /> | <Check /> via auto-rejection |
36
+ | [OpenCode](/providers/ai-sdk-harnesses/opencode) | Sandbox bridge | <Check /> | <Check /> | <Check /> | <Check /> via auto-rejection |
37
+ | [Pi](/providers/ai-sdk-harnesses/pi) | Host process | <Check /> | <Check /> | <Check /> | <Check /> |
@@ -18,22 +18,7 @@ integration.
18
18
 
19
19
  ## Installation
20
20
 
21
- <div className="my-4">
22
- <Tabs items={['pnpm', 'npm', 'yarn', 'bun']}>
23
- <Tab>
24
- <Snippet text="pnpm add @ai-sdk/workflow-harness workflow" dark />
25
- </Tab>
26
- <Tab>
27
- <Snippet text="npm install @ai-sdk/workflow-harness workflow" dark />
28
- </Tab>
29
- <Tab>
30
- <Snippet text="yarn add @ai-sdk/workflow-harness workflow" dark />
31
- </Tab>
32
- <Tab>
33
- <Snippet text="bun add @ai-sdk/workflow-harness workflow" dark />
34
- </Tab>
35
- </Tabs>
36
- </div>
21
+ <InstallPackages packages="@ai-sdk/workflow-harness workflow" />
37
22
 
38
23
  Install the core harness package, a harness adapter, and a sandbox provider as
39
24
  shown in [HarnessAgent](/docs/ai-sdk-harnesses/harness-agent).
@@ -12,34 +12,7 @@ session for the lifetime of the terminal UI.
12
12
 
13
13
  ## Installation
14
14
 
15
- <div className="my-4">
16
- <Tabs items={['pnpm', 'npm', 'yarn', 'bun']}>
17
- <Tab>
18
- <Snippet
19
- text="pnpm add @ai-sdk/tui @ai-sdk/harness @ai-sdk/harness-codex @ai-sdk/sandbox-vercel"
20
- dark
21
- />
22
- </Tab>
23
- <Tab>
24
- <Snippet
25
- text="npm install @ai-sdk/tui @ai-sdk/harness @ai-sdk/harness-codex @ai-sdk/sandbox-vercel"
26
- dark
27
- />
28
- </Tab>
29
- <Tab>
30
- <Snippet
31
- text="yarn add @ai-sdk/tui @ai-sdk/harness @ai-sdk/harness-codex @ai-sdk/sandbox-vercel"
32
- dark
33
- />
34
- </Tab>
35
- <Tab>
36
- <Snippet
37
- text="bun add @ai-sdk/tui @ai-sdk/harness @ai-sdk/harness-codex @ai-sdk/sandbox-vercel"
38
- dark
39
- />
40
- </Tab>
41
- </Tabs>
42
- </div>
15
+ <InstallPackages packages="@ai-sdk/tui @ai-sdk/harness @ai-sdk/harness-codex @ai-sdk/sandbox-vercel" />
43
16
 
44
17
  ## Example
45
18
 
@@ -24,11 +24,11 @@ Here is a comparison of the supported functions across these frameworks:
24
24
 
25
25
  | | [useChat](/docs/reference/ai-sdk-ui/use-chat) | [useCompletion](/docs/reference/ai-sdk-ui/use-completion) | [useObject](/docs/reference/ai-sdk-ui/use-object) | [MCP Apps](/docs/ai-sdk-core/mcp-apps) |
26
26
  | --------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------- | -------------------------------------- |
27
- | React `@ai-sdk/react` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
28
- | Vue.js `@ai-sdk/vue` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Cross size={18} /> |
29
- | Svelte `@ai-sdk/svelte` | <Check size={18} /> Chat | <Check size={18} /> Completion | <Check size={18} /> StructuredObject | <Cross size={18} /> |
30
- | Angular `@ai-sdk/angular` | <Check size={18} /> Chat | <Check size={18} /> Completion | <Check size={18} /> StructuredObject | <Cross size={18} /> |
31
- | [SolidJS](https://github.com/kodehort/ai-sdk-solid) (community) | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Cross size={18} /> |
27
+ | React `@ai-sdk/react` | <Check /> | <Check /> | <Check /> | <Check /> |
28
+ | Vue.js `@ai-sdk/vue` | <Check /> | <Check /> | <Check /> | <Cross /> |
29
+ | Svelte `@ai-sdk/svelte` | <Check /> Chat | <Check /> Completion | <Check /> StructuredObject | <Cross /> |
30
+ | Angular `@ai-sdk/angular` | <Check /> Chat | <Check /> Completion | <Check /> StructuredObject | <Cross /> |
31
+ | [SolidJS](https://github.com/kodehort/ai-sdk-solid) (community) | <Check /> | <Check /> | <Check /> | <Cross /> |
32
32
 
33
33
  ## Framework Examples
34
34
 
@@ -5,10 +5,7 @@ description: Learn how to use the useObject hook.
5
5
 
6
6
  # Object Generation
7
7
 
8
- <Note>
9
- `useObject` is an experimental feature and only available in React, Svelte,
10
- and Vue.
11
- </Note>
8
+ <Note>`useObject` is only available in React, Svelte, and Vue.</Note>
12
9
 
13
10
  The [`useObject`](/docs/reference/ai-sdk-ui/use-object) hook allows you to create interfaces that represent a structured JSON object that is being streamed.
14
11
 
@@ -46,7 +43,7 @@ Please note the code for handling `undefined` values in the JSX.
46
43
  ```tsx filename='app/page.tsx'
47
44
  'use client';
48
45
 
49
- import { experimental_useObject as useObject } from '@ai-sdk/react';
46
+ import { useObject } from '@ai-sdk/react';
50
47
  import { notificationSchema } from './api/notifications/schema';
51
48
 
52
49
  export default function Page() {
@@ -115,7 +112,7 @@ When using `useObject` with enum output mode, your schema must be an object with
115
112
  ```tsx filename='app/classify/page.tsx'
116
113
  'use client';
117
114
 
118
- import { experimental_useObject as useObject } from '@ai-sdk/react';
115
+ import { useObject } from '@ai-sdk/react';
119
116
  import { z } from 'zod';
120
117
 
121
118
  export default function ClassifyPage() {
@@ -174,7 +171,7 @@ purposes:
174
171
  ```tsx filename='app/page.tsx' highlight="6,13-20,24"
175
172
  'use client';
176
173
 
177
- import { experimental_useObject as useObject } from '@ai-sdk/react';
174
+ import { useObject } from '@ai-sdk/react';
178
175
 
179
176
  export default function Page() {
180
177
  const { isLoading, object, submit } = useObject({
@@ -211,7 +208,7 @@ The `stop` function can be used to stop the object generation process. This can
211
208
  ```tsx filename='app/page.tsx' highlight="6,14-16"
212
209
  'use client';
213
210
 
214
- import { experimental_useObject as useObject } from '@ai-sdk/react';
211
+ import { useObject } from '@ai-sdk/react';
215
212
 
216
213
  export default function Page() {
217
214
  const { isLoading, stop, object, submit } = useObject({
@@ -256,7 +253,7 @@ It can be used to display an error message, or to disable the submit button:
256
253
  ```tsx file="app/page.tsx" highlight="6,13"
257
254
  'use client';
258
255
 
259
- import { experimental_useObject as useObject } from '@ai-sdk/react';
256
+ import { useObject } from '@ai-sdk/react';
260
257
 
261
258
  export default function Page() {
262
259
  const { error, object, submit } = useObject({
@@ -295,7 +292,7 @@ These callbacks can be used to trigger additional actions, such as logging, anal
295
292
  ```tsx filename='app/page.tsx' highlight="10-20"
296
293
  'use client';
297
294
 
298
- import { experimental_useObject as useObject } from '@ai-sdk/react';
295
+ import { useObject } from '@ai-sdk/react';
299
296
  import { notificationSchema } from './api/notifications/schema';
300
297
 
301
298
  export default function Page() {
@@ -118,9 +118,10 @@ console.log(videos);
118
118
  },
119
119
  {
120
120
  name: 'inputReferences',
121
- type: 'Array<DataContent>',
121
+ type: 'Array<DataContent | { data: DataContent; mediaType?: string }>',
122
122
  isOptional: true,
123
- description: 'Reference image inputs for reference-to-video generation.',
123
+ description:
124
+ 'Reference image or video inputs for reference-to-video generation. Use the object form with an explicit mediaType for URL-based video references. Providers route each reference by its media type and warn when a reference kind is unsupported.',
124
125
  },
125
126
  {
126
127
  name: 'generateAudio',
@@ -3,12 +3,9 @@ title: useObject
3
3
  description: API reference for the useObject hook.
4
4
  ---
5
5
 
6
- # `experimental_useObject()`
6
+ # `useObject()`
7
7
 
8
- <Note>
9
- `useObject` is an experimental feature and only available in React, Svelte,
10
- and Vue.
11
- </Note>
8
+ <Note>`useObject` is only available in React, Svelte, and Vue.</Note>
12
9
 
13
10
  Allows you to consume text streams that represent a JSON object and parse them into a complete object based on a schema.
14
11
  You can use it together with [`streamText`](/docs/reference/ai-sdk-core/stream-text) and [`Output.object()`](/docs/reference/ai-sdk-core/output#output-object) in the backend.
@@ -16,7 +13,7 @@ You can use it together with [`streamText`](/docs/reference/ai-sdk-core/stream-t
16
13
  ```tsx
17
14
  'use client';
18
15
 
19
- import { experimental_useObject as useObject } from '@ai-sdk/react';
16
+ import { useObject } from '@ai-sdk/react';
20
17
 
21
18
  export default function Page() {
22
19
  const { object, submit } = useObject({
@@ -38,21 +35,21 @@ export default function Page() {
38
35
  <Tabs items={['React', 'Svelte', 'Vue']}>
39
36
  <Tab>
40
37
  <Snippet
41
- text="import { experimental_useObject as useObject } from '@ai-sdk/react'"
38
+ text="import { useObject } from '@ai-sdk/react'"
42
39
  dark
43
40
  prompt={false}
44
41
  />
45
42
  </Tab>
46
43
  <Tab>
47
44
  <Snippet
48
- text="import { Experimental_StructuredObject } from '@ai-sdk/svelte'"
45
+ text="import { StructuredObject } from '@ai-sdk/svelte'"
49
46
  dark
50
47
  prompt={false}
51
48
  />
52
49
  </Tab>
53
50
  <Tab>
54
51
  <Snippet
55
- text="import { experimental_useObject } from '@ai-sdk/vue'"
52
+ text="import { useObject } from '@ai-sdk/vue'"
56
53
  dark
57
54
  prompt={false}
58
55
  />
@@ -87,11 +87,11 @@ Here is a comparison of the supported functions across these frameworks:
87
87
 
88
88
  | | [useChat](/docs/reference/ai-sdk-ui/use-chat) | [useCompletion](/docs/reference/ai-sdk-ui/use-completion) | [useObject](/docs/reference/ai-sdk-ui/use-object) | [MCP Apps](/docs/ai-sdk-core/mcp-apps) |
89
89
  | --------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------- | -------------------------------------- |
90
- | React `@ai-sdk/react` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
91
- | Vue.js `@ai-sdk/vue` | <Check size={18} /> Chat | <Check size={18} /> | <Check size={18} /> | <Cross size={18} /> |
92
- | Svelte `@ai-sdk/svelte` | <Check size={18} /> Chat | <Check size={18} /> Completion | <Check size={18} /> StructuredObject | <Cross size={18} /> |
93
- | Angular `@ai-sdk/angular` | <Check size={18} /> Chat | <Check size={18} /> Completion | <Check size={18} /> StructuredObject | <Cross size={18} /> |
94
- | [SolidJS](https://github.com/kodehort/ai-sdk-solid) (community) | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Cross size={18} /> |
90
+ | React `@ai-sdk/react` | <Check /> | <Check /> | <Check /> | <Check /> |
91
+ | Vue.js `@ai-sdk/vue` | <Check /> Chat | <Check /> | <Check /> | <Cross /> |
92
+ | Svelte `@ai-sdk/svelte` | <Check /> Chat | <Check /> Completion | <Check /> StructuredObject | <Cross /> |
93
+ | Angular `@ai-sdk/angular` | <Check /> Chat | <Check /> Completion | <Check /> StructuredObject | <Cross /> |
94
+ | [SolidJS](https://github.com/kodehort/ai-sdk-solid) (community) | <Check /> | <Check /> | <Check /> | <Cross /> |
95
95
 
96
96
  <Note>
97
97
  [Contributions](https://github.com/vercel/ai/blob/main/CONTRIBUTING.md) are
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "7.0.17",
3
+ "version": "7.0.19",
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,9 +42,9 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
- "@ai-sdk/gateway": "4.0.13",
46
- "@ai-sdk/provider": "4.0.2",
47
- "@ai-sdk/provider-utils": "5.0.5"
45
+ "@ai-sdk/gateway": "4.0.15",
46
+ "@ai-sdk/provider": "4.0.3",
47
+ "@ai-sdk/provider-utils": "5.0.7"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@edge-runtime/vm": "^5.0.0",
@@ -36,8 +36,19 @@ export function collectToolApprovals<TOOLS extends ToolSet>({
36
36
  };
37
37
  }
38
38
 
39
- // gather tool calls and prepare lookup
40
- const toolCallsByToolCallId: Record<string, TypedToolCall<TOOLS>> = {};
39
+ // gather tool calls and prepare lookup.
40
+ //
41
+ // These maps are keyed by client-supplied ids (`toolCallId`, `approvalId`)
42
+ // from the message history. Using `Object.create(null)` gives them no
43
+ // prototype, so an id that matches an inherited object property (e.g.
44
+ // `toString`, `constructor`, `__proto__`) is treated as absent instead of
45
+ // resolving to a prototype value and slipping past the `== null` guards
46
+ // below (which would otherwise skip the InvalidToolApproval /
47
+ // ToolCallNotFound checks).
48
+ const toolCallsByToolCallId: Record<
49
+ string,
50
+ TypedToolCall<TOOLS>
51
+ > = Object.create(null);
41
52
  for (const message of messages) {
42
53
  if (message.role === 'assistant' && typeof message.content !== 'string') {
43
54
  const content = message.content;
@@ -51,7 +62,7 @@ export function collectToolApprovals<TOOLS extends ToolSet>({
51
62
 
52
63
  // gather approval responses and prepare lookup
53
64
  const toolApprovalRequestsByApprovalId: Record<string, ToolApprovalRequest> =
54
- {};
65
+ Object.create(null);
55
66
  for (const message of messages) {
56
67
  if (message.role === 'assistant' && typeof message.content !== 'string') {
57
68
  const content = message.content;
@@ -64,7 +75,9 @@ export function collectToolApprovals<TOOLS extends ToolSet>({
64
75
  }
65
76
 
66
77
  // gather tool results from the last tool message
67
- const toolResults: Record<string, TypedToolResult<TOOLS>> = {};
78
+ const toolResults: Record<string, TypedToolResult<TOOLS>> = Object.create(
79
+ null,
80
+ );
68
81
  for (const part of lastMessage.content) {
69
82
  if (part.type === 'tool-result') {
70
83
  toolResults[part.toolCallId] = part as TypedToolResult<TOOLS>;
@@ -13,6 +13,7 @@ import {
13
13
  type TimeoutConfiguration,
14
14
  } from '../prompt/request-options';
15
15
  import type { TelemetryDispatcher } from '../telemetry/telemetry';
16
+ import { getOwn } from '../util/get-own';
16
17
  import { mergeAbortSignals } from '../util/merge-abort-signals';
17
18
  import { notify } from '../util/notify';
18
19
  import { now } from '../util/now';
@@ -83,7 +84,7 @@ export async function executeToolCall<TOOLS extends ToolSet>({
83
84
  | undefined
84
85
  > {
85
86
  const { toolName, toolCallId, input } = toolCall;
86
- const tool = tools?.[toolName];
87
+ const tool = getOwn(tools, toolName);
87
88
 
88
89
  if (!isExecutableTool(tool)) {
89
90
  return undefined;
@@ -91,7 +92,7 @@ export async function executeToolCall<TOOLS extends ToolSet>({
91
92
 
92
93
  const context = await validateToolContext({
93
94
  toolName,
94
- context: toolsContext?.[toolName as keyof typeof toolsContext],
95
+ context: getOwn(toolsContext, toolName),
95
96
  contextSchema: tool.contextSchema,
96
97
  });
97
98
 
@@ -9,6 +9,7 @@ import type {
9
9
  } from '@ai-sdk/provider-utils';
10
10
  import type { TimeoutConfiguration } from '../prompt/request-options';
11
11
  import type { Telemetry, TelemetryDispatcher } from '../telemetry/telemetry';
12
+ import { getOwn } from '../util/get-own';
12
13
  import { executeToolCall } from './execute-tool-call';
13
14
  import { resolveToolApproval } from './resolve-tool-approval';
14
15
  import type { LanguageModelStreamPart } from './stream-language-model-call';
@@ -95,7 +96,7 @@ export function executeToolsFromStream<
95
96
  return;
96
97
  }
97
98
 
98
- const tool = tools?.[chunk.toolName];
99
+ const tool = getOwn(tools, chunk.toolName);
99
100
 
100
101
  if (tool == null) {
101
102
  // ignore tool calls for tools that are not available,
@@ -50,6 +50,7 @@ import {
50
50
  type LanguageModelUsage,
51
51
  } from '../types/usage';
52
52
  import type { DownloadFunction } from '../util/download/download-function';
53
+ import { getOwn } from '../util/get-own';
53
54
  import { mergeAbortSignals } from '../util/merge-abort-signals';
54
55
  import { mergeObjects } from '../util/merge-objects';
55
56
  import { now as originalNow } from '../util/now';
@@ -717,7 +718,7 @@ export async function generateText<
717
718
  const modelOutput = await createToolModelOutput({
718
719
  toolCallId: output.toolCallId,
719
720
  input: output.input,
720
- tool: tools?.[output.toolName],
721
+ tool: getOwn(tools, output.toolName),
721
722
  output:
722
723
  output.type === 'tool-result' ? output.output : output.error,
723
724
  errorMode: output.type === 'tool-error' ? 'text' : 'none',
@@ -1040,7 +1041,7 @@ export async function generateText<
1040
1041
  continue; // ignore invalid tool calls
1041
1042
  }
1042
1043
 
1043
- const tool = tools?.[toolCall.toolName];
1044
+ const tool = getOwn(tools, toolCall.toolName);
1044
1045
 
1045
1046
  if (tool == null) {
1046
1047
  // ignore tool calls for tools that are not available,
@@ -1234,7 +1235,7 @@ export async function generateText<
1234
1235
  // the client tool's result is sent back.
1235
1236
  for (const toolCall of stepToolCalls) {
1236
1237
  if (!toolCall.providerExecuted) continue;
1237
- const tool = tools?.[toolCall.toolName];
1238
+ const tool = getOwn(tools, toolCall.toolName);
1238
1239
  if (tool?.type === 'provider' && tool.supportsDeferredResults) {
1239
1240
  // Check if this tool call already has a result in the current response
1240
1241
  const hasResultInResponse = currentModelResponse.content.some(
@@ -1699,7 +1700,7 @@ function asContent<TOOLS extends ToolSet>({
1699
1700
  // result may be deferred to a later turn. In this case, there's no matching tool-call
1700
1701
  // in the current response.
1701
1702
  if (toolCall == null) {
1702
- const tool = tools?.[part.toolName];
1703
+ const tool = getOwn(tools, part.toolName);
1703
1704
  const supportsDeferredResults =
1704
1705
  tool?.type === 'provider' && tool.supportsDeferredResults;
1705
1706