ai 7.0.18 → 7.0.20

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 (56) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/index.d.ts +58 -5
  3. package/dist/index.js +168 -79
  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-agents/07-workflow-agent.mdx +1 -1
  19. package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +3 -12
  20. package/docs/03-ai-sdk-core/16-mcp-tools.mdx +44 -0
  21. package/docs/03-ai-sdk-core/30-embeddings.mdx +18 -18
  22. package/docs/03-ai-sdk-core/38-video-generation.mdx +22 -3
  23. package/docs/03-ai-sdk-harnesses/02-harness-agent.mdx +1 -28
  24. package/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx +7 -7
  25. package/docs/03-ai-sdk-harnesses/06-workflow-utilities.mdx +1 -16
  26. package/docs/03-ai-sdk-harnesses/08-terminal-ui.mdx +1 -28
  27. package/docs/04-ai-sdk-ui/01-overview.mdx +5 -5
  28. package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +1 -1
  29. package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +1 -1
  30. package/docs/07-reference/01-ai-sdk-core/13-generate-video.mdx +3 -2
  31. package/docs/07-reference/01-ai-sdk-core/16-tool-loop-agent.mdx +1 -1
  32. package/docs/07-reference/02-ai-sdk-ui/index.mdx +5 -5
  33. package/docs/07-reference/04-ai-sdk-workflow/01-workflow-agent.mdx +2 -2
  34. package/package.json +4 -4
  35. package/src/agent/tool-loop-agent-settings.ts +7 -0
  36. package/src/generate-text/collect-tool-approvals.ts +17 -4
  37. package/src/generate-text/execute-tool-call.ts +3 -2
  38. package/src/generate-text/execute-tools-from-stream.ts +2 -1
  39. package/src/generate-text/generate-text.ts +14 -5
  40. package/src/generate-text/index.ts +1 -0
  41. package/src/generate-text/invoke-tool-callbacks-from-stream.ts +6 -4
  42. package/src/generate-text/parse-tool-call.ts +5 -4
  43. package/src/generate-text/resolve-tool-approval.ts +9 -6
  44. package/src/generate-text/stream-language-model-call.ts +2 -1
  45. package/src/generate-text/stream-text.ts +12 -3
  46. package/src/generate-text/to-response-messages.ts +4 -3
  47. package/src/generate-text/tool-approval-signature.ts +4 -40
  48. package/src/generate-text/tool-fingerprint.ts +76 -0
  49. package/src/generate-text/validate-tool-approvals.ts +6 -1
  50. package/src/generate-video/generate-video.ts +96 -21
  51. package/src/ui/convert-to-model-messages.ts +3 -2
  52. package/src/ui/process-ui-message-stream.ts +3 -0
  53. package/src/ui/validate-ui-messages.ts +2 -1
  54. package/src/util/canonical-hash.ts +44 -0
  55. package/src/util/get-own.ts +18 -0
  56. package/src/util/write-to-server-response.ts +9 -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
 
@@ -702,7 +702,7 @@ For persistence, store `UIMessage[]` as your source of truth and call [`convertT
702
702
 
703
703
  ### Everything else
704
704
 
705
- Other options carry over with the same names: `prepareStep`, `onStepEnd`, `onEnd`, `onError`, `toolChoice`, `activeTools`, `timeout`, `experimental_repairToolCall`, `experimental_sandbox`, and the usual generation settings (`temperature`, `maxOutputTokens`, `topP`, …). `WorkflowAgent` additionally adds `prepareCall` (runs once before the loop) and the `experimental_onStart` / `experimental_onStepStart` / `onToolExecutionStart` / `onToolExecutionEnd` lifecycle callbacks documented above.
705
+ Other options carry over with the same names: `prepareStep`, `onStepEnd`, `onEnd`, `onError`, `toolChoice`, `activeTools`, `timeout`, `repairToolCall`, `experimental_sandbox`, and the usual generation settings (`temperature`, `maxOutputTokens`, `topP`, …). `WorkflowAgent` additionally adds `prepareCall` (runs once before the loop) and the `experimental_onStart` / `experimental_onStepStart` / `onToolExecutionStart` / `onToolExecutionEnd` lifecycle callbacks documented above.
706
706
 
707
707
  ## Next Steps
708
708
 
@@ -1207,10 +1207,6 @@ return createUIMessageStreamResponse({
1207
1207
 
1208
1208
  ## Tool Call Repair
1209
1209
 
1210
- <Note type="warning">
1211
- The tool call repair feature is experimental and may change in the future.
1212
- </Note>
1213
-
1214
1210
  Language models sometimes fail to generate valid tool calls,
1215
1211
  especially when the input schema is complex or the model is smaller.
1216
1212
 
@@ -1219,7 +1215,7 @@ in the next step to give it an opportunity to fix it.
1219
1215
  However, you may want to control how invalid tool calls are repaired without requiring
1220
1216
  additional steps that pollute the message history.
1221
1217
 
1222
- You can use the `experimental_repairToolCall` function to attempt to repair the tool call
1218
+ You can use the `repairToolCall` function to attempt to repair the tool call
1223
1219
  with a custom function.
1224
1220
 
1225
1221
  You can use different strategies to repair the tool call:
@@ -1239,12 +1235,7 @@ const result = await generateText({
1239
1235
  tools,
1240
1236
  prompt,
1241
1237
 
1242
- experimental_repairToolCall: async ({
1243
- toolCall,
1244
- tools,
1245
- inputSchema,
1246
- error,
1247
- }) => {
1238
+ repairToolCall: async ({ toolCall, tools, inputSchema, error }) => {
1248
1239
  if (NoSuchToolError.isInstance(error)) {
1249
1240
  return null; // do not attempt to fix invalid tool names
1250
1241
  }
@@ -1280,7 +1271,7 @@ const result = await generateText({
1280
1271
  tools,
1281
1272
  prompt,
1282
1273
 
1283
- experimental_repairToolCall: async ({
1274
+ repairToolCall: async ({
1284
1275
  toolCall,
1285
1276
  tools,
1286
1277
  error,
@@ -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
 
@@ -811,7 +811,7 @@ To see `generateText` in action, check out [these examples](#examples).
811
811
  ],
812
812
  },
813
813
  {
814
- name: 'experimental_repairToolCall',
814
+ name: 'repairToolCall',
815
815
  type: '(options: ToolCallRepairOptions) => Promise<LanguageModelV4ToolCall | null>',
816
816
  isOptional: true,
817
817
  description:
@@ -855,7 +855,7 @@ To see `streamText` in action, check out [these examples](#examples).
855
855
  ],
856
856
  },
857
857
  {
858
- name: 'experimental_repairToolCall',
858
+ name: 'repairToolCall',
859
859
  type: '(options: ToolCallRepairOptions) => Promise<LanguageModelV4ToolCall | null>',
860
860
  isOptional: true,
861
861
  description:
@@ -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',
@@ -133,7 +133,7 @@ To see `ToolLoopAgent` in action, check out [these examples](#examples).
133
133
  'Settings for controlling what data is included in step results. requestBody, requestMessages, and responseBody apply to generate(); requestBody, requestMessages, and rawChunks apply to stream().',
134
134
  },
135
135
  {
136
- name: 'experimental_repairToolCall',
136
+ name: 'repairToolCall',
137
137
  type: 'ToolCallRepairFunction',
138
138
  isOptional: true,
139
139
  description:
@@ -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
@@ -116,7 +116,7 @@ To see `WorkflowAgent` in action, check out [these examples](#examples).
116
116
  'Default structured output specification. Per-stream values override this default.',
117
117
  },
118
118
  {
119
- name: 'experimental_repairToolCall',
119
+ name: 'repairToolCall',
120
120
  type: 'ToolCallRepairFunction',
121
121
  isOptional: true,
122
122
  description:
@@ -528,7 +528,7 @@ const result = await agent.stream({
528
528
  description: 'Include raw, unprocessed chunks from the provider in the stream. Default: false.',
529
529
  },
530
530
  {
531
- name: 'experimental_repairToolCall',
531
+ name: 'repairToolCall',
532
532
  type: 'ToolCallRepairFunction',
533
533
  isOptional: true,
534
534
  description: 'Callback to attempt automatic recovery when a tool call cannot be parsed.',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "7.0.18",
3
+ "version": "7.0.20",
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.14",
46
- "@ai-sdk/provider": "4.0.2",
47
- "@ai-sdk/provider-utils": "5.0.6"
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",
@@ -142,6 +142,13 @@ export type ToolLoopAgentSettings<
142
142
  /**
143
143
  * A function that attempts to repair a tool call that failed to parse.
144
144
  */
145
+ repairToolCall?: ToolCallRepairFunction<NoInfer<TOOLS>>;
146
+
147
+ /**
148
+ * A function that attempts to repair a tool call that failed to parse.
149
+ *
150
+ * @deprecated Use `repairToolCall` instead.
151
+ */
145
152
  experimental_repairToolCall?: ToolCallRepairFunction<NoInfer<TOOLS>>;
146
153
 
147
154
  /**
@@ -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,