ai 7.0.145 → 7.0.147
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.
- package/CHANGELOG.md +22 -0
- package/dist/index.d.ts +16 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -9
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +10 -6
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index.js.map +1 -1
- package/docs/02-foundations/01-overview.mdx +1 -1
- package/docs/02-foundations/02-providers-and-models.mdx +2 -2
- package/docs/02-foundations/03-prompts.mdx +3 -3
- package/docs/02-foundations/04-tools.mdx +2 -2
- package/docs/02-getting-started/00-choosing-a-provider.mdx +1 -1
- package/docs/02-getting-started/02-nextjs-app-router.mdx +4 -4
- package/docs/02-getting-started/03-nextjs-pages-router.mdx +4 -4
- package/docs/02-getting-started/04-svelte.mdx +3 -3
- package/docs/02-getting-started/05-nuxt.mdx +3 -3
- package/docs/02-getting-started/06-nodejs.mdx +2 -2
- package/docs/02-getting-started/07-expo.mdx +4 -4
- package/docs/02-getting-started/08-tanstack-start.mdx +4 -4
- package/docs/03-ai-sdk-core/10-generating-structured-data.mdx +1 -1
- package/docs/03-ai-sdk-core/16-mcp-tools.mdx +29 -2
- package/docs/03-ai-sdk-core/18-tools.mdx +137 -0
- package/docs/03-ai-sdk-core/37-speech.mdx +1 -1
- package/docs/03-ai-sdk-core/41-skill-uploads.mdx +24 -10
- package/docs/03-ai-sdk-core/index.mdx +6 -0
- package/docs/03-ai-sdk-harnesses/02-harness-agent.mdx +1 -1
- package/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx +8 -8
- package/docs/03-ai-sdk-harnesses/06-workflow-utilities.mdx +12 -0
- package/docs/03-ai-sdk-harnesses/07-ui.mdx +2 -2
- package/docs/04-ai-sdk-ui/03-chatbot-tool-usage.mdx +2 -2
- package/docs/05-ai-sdk-rsc/01-overview.mdx +1 -1
- package/docs/05-ai-sdk-rsc/10-migrating-to-ui.mdx +1 -1
- package/docs/06-advanced/01-prompt-engineering.mdx +1 -1
- package/docs/06-advanced/03-backpressure.mdx +1 -1
- package/docs/06-advanced/10-vercel-deployment-guide.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/14-decide.mdx +18 -13
- package/docs/07-reference/01-ai-sdk-core/14-upload-skill.mdx +3 -3
- package/docs/07-reference/01-ai-sdk-core/22-dynamic-tool.mdx +1 -1
- package/docs/08-migration-guides/index.mdx +12 -12
- package/docs/09-troubleshooting/05-tool-invocation-missing-result.mdx +1 -1
- package/package.json +12 -12
- package/src/decide/decide-events.ts +6 -0
- package/src/decide/decide.ts +13 -0
- package/src/generate-text/output.ts +1 -1
- package/src/generate-text/prune-messages.ts +91 -32
- package/src/generate-text/tool-call.ts +1 -1
- package/src/generate-text/tool-error.ts +1 -1
- package/src/generate-text/tool-execution-events.ts +2 -2
- package/src/generate-text/tool-output-denied.ts +1 -1
- package/src/generate-text/tool-result.ts +1 -1
- package/src/ui/process-ui-message-stream.ts +1 -0
|
@@ -36,12 +36,12 @@ The AI SDK includes the following harness adapters:
|
|
|
36
36
|
| Adapter | Runtime location | Custom tools | Custom skills | Structured output | Built-in tool approval | Built-in tool filtering | Image input | History access |
|
|
37
37
|
| ------------------------------------------------------------ | ---------------- | ------------ | ------------- | ----------------- | ---------------------- | ---------------------------- | ----------- | -------------- |
|
|
38
38
|
| [Claude Code](/providers/ai-sdk-harnesses/claude-code) | Sandbox bridge | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> |
|
|
39
|
-
| [Cline](/providers/ai-sdk-harnesses/cline) | Host process | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <
|
|
40
|
-
| [Codex](/providers/ai-sdk-harnesses/codex) | Sandbox bridge | <Check /> | <Check /> | <Check /> | <Cross /> | <Cross /> | <
|
|
41
|
-
| [Cursor](/providers/ai-sdk-harnesses/cursor) | Sandbox via ACP | <Check /> | <Check /> | <Cross /> | <Cross /> | <Cross /> | <
|
|
42
|
-
| [Deep Agents](/providers/ai-sdk-harnesses/deepagents) | Sandbox bridge | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> via auto-rejection | <
|
|
39
|
+
| [Cline](/providers/ai-sdk-harnesses/cline) | Host process | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> |
|
|
40
|
+
| [Codex](/providers/ai-sdk-harnesses/codex) | Sandbox bridge | <Check /> | <Check /> | <Check /> | <Cross /> | <Cross /> | <Check /> | <Cross /> |
|
|
41
|
+
| [Cursor](/providers/ai-sdk-harnesses/cursor) | Sandbox via ACP | <Check /> | <Check /> | <Cross /> | <Cross /> | <Cross /> | <Check /> | <Cross /> |
|
|
42
|
+
| [Deep Agents](/providers/ai-sdk-harnesses/deepagents) | Sandbox bridge | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> via auto-rejection | <Check /> | <Cross /> |
|
|
43
43
|
| [fx](/providers/ai-sdk-harnesses/fx) | Host process | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> | <Cross /> |
|
|
44
|
-
| [GitHub Copilot](/providers/ai-sdk-harnesses/github-copilot) | Sandbox via ACP | <Check /> | <Check /> | <Cross /> | <Cross /> | <Cross /> | <
|
|
45
|
-
| [Grok Build](/providers/ai-sdk-harnesses/grok-build) | Sandbox via ACP | <Check /> | <Check /> | <Check /> | <Cross /> | <Cross /> | <
|
|
46
|
-
| [OpenCode](/providers/ai-sdk-harnesses/opencode) | Sandbox bridge | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <
|
|
47
|
-
| [Pi](/providers/ai-sdk-harnesses/pi) | Host process | <Check /> | <Check /> | <Cross /> | <Check /> | <Check /> | <
|
|
44
|
+
| [GitHub Copilot](/providers/ai-sdk-harnesses/github-copilot) | Sandbox via ACP | <Check /> | <Check /> | <Cross /> | <Cross /> | <Cross /> | <Check /> | <Cross /> |
|
|
45
|
+
| [Grok Build](/providers/ai-sdk-harnesses/grok-build) | Sandbox via ACP | <Check /> | <Check /> | <Check /> | <Cross /> | <Cross /> | <Check /> | <Cross /> |
|
|
46
|
+
| [OpenCode](/providers/ai-sdk-harnesses/opencode) | Sandbox bridge | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> |
|
|
47
|
+
| [Pi](/providers/ai-sdk-harnesses/pi) | Host process | <Check /> | <Check /> | <Cross /> | <Check /> | <Check /> | <Check /> | <Cross /> |
|
|
@@ -308,6 +308,18 @@ export async function POST(request: Request) {
|
|
|
308
308
|
}
|
|
309
309
|
```
|
|
310
310
|
|
|
311
|
+
If you use Next.js, wrap your config with `withWorkflow()` so the Workflow SDK
|
|
312
|
+
transforms `'use workflow'` and `'use step'` modules. Other frameworks have
|
|
313
|
+
their own Workflow SDK setup.
|
|
314
|
+
|
|
315
|
+
```js filename='next.config.js'
|
|
316
|
+
import { withWorkflow } from 'workflow/next';
|
|
317
|
+
|
|
318
|
+
const nextConfig = {};
|
|
319
|
+
|
|
320
|
+
export default withWorkflow(nextConfig);
|
|
321
|
+
```
|
|
322
|
+
|
|
311
323
|
The workflow state `sessionId` identifies the harness session. The step derives
|
|
312
324
|
`sandboxId` from it; otherwise, you must persist `sandboxSession.id` separately
|
|
313
325
|
to reattach across steps. Keep
|
|
@@ -93,7 +93,7 @@ export const agent = new HarnessAgent({
|
|
|
93
93
|
|
|
94
94
|
Persist the opaque resume state returned by `session.detach()`. If the
|
|
95
95
|
turn paused for approval or was otherwise interrupted, that resume state carries
|
|
96
|
-
the continuation state internally. The chat
|
|
96
|
+
the continuation state internally. The chat ID can also be the harness
|
|
97
97
|
`sessionId`. Here we derive a stable `sandboxId` from that known chat id. If
|
|
98
98
|
you do not derive one, persist the returned `sandboxSession.id` separately.
|
|
99
99
|
|
|
@@ -170,7 +170,7 @@ export async function POST(request: Request) {
|
|
|
170
170
|
} = await request.json();
|
|
171
171
|
|
|
172
172
|
if (!body.id) {
|
|
173
|
-
|
|
173
|
+
return new Response('Missing chat ID', { status: 400 });
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
const chatId = body.id;
|
|
@@ -16,12 +16,12 @@ The flow is as follows:
|
|
|
16
16
|
|
|
17
17
|
1. The user enters a message in the chat UI.
|
|
18
18
|
1. The message is sent to the API route.
|
|
19
|
-
1. In your server
|
|
19
|
+
1. In your server-side route, the language model generates tool calls during the `streamText` call.
|
|
20
20
|
1. All tool calls are forwarded to the client.
|
|
21
21
|
1. Server-side tools are executed using their `execute` method and their results are forwarded to the client.
|
|
22
22
|
1. Client-side tools that should be automatically executed are handled with the `onToolCall` callback.
|
|
23
23
|
You must call `addToolOutput` to provide the tool result.
|
|
24
|
-
1. Client-side
|
|
24
|
+
1. Client-side tools that require user interactions can be displayed in the UI.
|
|
25
25
|
The tool calls and results are available as tool invocation parts in the `parts` property of the last assistant message.
|
|
26
26
|
1. When the user interaction is done, `addToolOutput` can be used to add the tool result to the chat.
|
|
27
27
|
1. The chat can be configured to automatically submit when all tool results are available using `sendAutomaticallyWhen`.
|
|
@@ -16,7 +16,7 @@ description: An overview of AI SDK RSC.
|
|
|
16
16
|
Server Components.
|
|
17
17
|
</Note>
|
|
18
18
|
|
|
19
|
-
[React Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components) (RSC) allow you to write UI that can be rendered on the server and streamed to the client. RSCs enable [
|
|
19
|
+
[React Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components) (RSC) allow you to write UI that can be rendered on the server and streamed to the client. RSCs enable [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#with-client-components), a new way to call server-side code directly from the client just like any other function with end-to-end type-safety. This combination opens the door to a new way of building AI applications, allowing the large language model (LLM) to generate and stream UI directly from the server to the client.
|
|
20
20
|
|
|
21
21
|
## AI SDK RSC Functions
|
|
22
22
|
|
|
@@ -166,7 +166,7 @@ export default function Page() {
|
|
|
166
166
|
|
|
167
167
|
In AI SDK RSC, `streamUI` does not support parallel tool calls. You will have to use a combination of `streamText`, `createStreamableUI` and `createStreamableValue`.
|
|
168
168
|
|
|
169
|
-
With AI SDK UI, `useChat` comes with built-in support for parallel tool calls. You can define multiple tools in the `streamText` and have them called
|
|
169
|
+
With AI SDK UI, `useChat` comes with built-in support for parallel tool calls. You can define multiple tools in the `streamText` and have them called in parallel. The `useChat` hook will then handle the parallel tool calls for you automatically.
|
|
170
170
|
|
|
171
171
|
### Multi-Step Tool Calls
|
|
172
172
|
|
|
@@ -17,7 +17,7 @@ Prompts are the starting points for LLMs. They are the inputs that trigger the m
|
|
|
17
17
|
|
|
18
18
|
## Why is prompt engineering needed?
|
|
19
19
|
|
|
20
|
-
Prompt engineering currently plays a pivotal role in shaping the responses of LLMs. It allows us to tweak the model to respond more effectively to a broader range of queries. This includes the use of techniques like semantic search, command grammars, and the ReActive model architecture. The performance, context window, and cost of LLMs varies between models and model providers which adds further constraints to the mix. For example, the GPT-4 model is more expensive than GPT-3.5-turbo and significantly slower, but it can also be more effective at certain tasks. And so, like many things in software engineering, there is a trade-
|
|
20
|
+
Prompt engineering currently plays a pivotal role in shaping the responses of LLMs. It allows us to tweak the model to respond more effectively to a broader range of queries. This includes the use of techniques like semantic search, command grammars, and the ReActive model architecture. The performance, context window, and cost of LLMs varies between models and model providers which adds further constraints to the mix. For example, the GPT-4 model is more expensive than GPT-3.5-turbo and significantly slower, but it can also be more effective at certain tasks. And so, like many things in software engineering, there is a trade-off between cost and performance.
|
|
21
21
|
|
|
22
22
|
To assist with comparing and tweaking LLMs, we've built an AI playground that allows you to compare the performance of different models side-by-side online. When you're ready, you can even generate code with the AI SDK to quickly use your prompt and your selected model into your own applications.
|
|
23
23
|
|
|
@@ -120,7 +120,7 @@ function createStream(iterator) {
|
|
|
120
120
|
}
|
|
121
121
|
// Collect data from stream
|
|
122
122
|
async function run() {
|
|
123
|
-
// Set up a stream
|
|
123
|
+
// Set up a stream of integers
|
|
124
124
|
const stream = createStream(integers());
|
|
125
125
|
|
|
126
126
|
// Read values from our stream
|
|
@@ -16,7 +16,7 @@ Vercel allows for automatic deployments on every branch push and merges onto the
|
|
|
16
16
|
To follow along with this guide, you will need:
|
|
17
17
|
|
|
18
18
|
- a Vercel account
|
|
19
|
-
- an account with a Git provider (this tutorial will use [
|
|
19
|
+
- an account with a Git provider (this tutorial will use [GitHub](https://github.com))
|
|
20
20
|
- an OpenAI API key
|
|
21
21
|
|
|
22
22
|
This guide will teach you how to deploy the application you built in the Next.js (App Router) quickstart tutorial to Vercel. If you haven’t completed the quickstart guide, you can start with [this repo](https://github.com/vercel-labs/ai-sdk-deployment-guide).
|
|
@@ -7,7 +7,7 @@ description: API Reference for generateText.
|
|
|
7
7
|
|
|
8
8
|
Generates text and calls tools for a given prompt using a language model.
|
|
9
9
|
|
|
10
|
-
It is ideal for non-interactive use cases such as automation tasks where you need to write text (e.g. drafting
|
|
10
|
+
It is ideal for non-interactive use cases such as automation tasks where you need to write text (e.g. drafting emails or summarizing web pages) and for agents that use tools.
|
|
11
11
|
|
|
12
12
|
```ts
|
|
13
13
|
import { generateText } from 'ai';
|
|
@@ -14,19 +14,24 @@ state. See [Decisions](/docs/ai-sdk-core/decisions) for examples and semantics.
|
|
|
14
14
|
|
|
15
15
|
## Parameters
|
|
16
16
|
|
|
17
|
-
| Parameter | Type
|
|
18
|
-
| ----------------- |
|
|
19
|
-
| `model` | `Experimental_DecisionModel`
|
|
20
|
-
| `state` | `Experimental_DecisionState`
|
|
21
|
-
| `questions` | `Record<string, Experimental_DecisionQuestion>`
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
25
|
-
| `
|
|
26
|
-
| `
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
17
|
+
| Parameter | Type | Description |
|
|
18
|
+
| ----------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| `model` | `Experimental_DecisionModel` | Required experimental v4 model instance or a string ID resolved by Gateway or an explicitly configured decision-capable default provider. |
|
|
20
|
+
| `state` | `Experimental_DecisionState` | Required string, JSON object, or ordered array of text, file, and JSON parts. |
|
|
21
|
+
| `questions` | `Record<string, Experimental_DecisionQuestion>` | Required nonempty question map. |
|
|
22
|
+
| `maxOutputTokens` | `number` | Optional maximum output tokens, an integer >= 1. |
|
|
23
|
+
| `reasoning` | `'provider-default' \| 'none' \| 'minimal' \| 'low' \| 'medium' \| 'high' \| 'xhigh' \| 'max'` | Optional reasoning effort. Language-model adapters default to `'none'`. Native decision providers return an unsupported-setting warning. |
|
|
24
|
+
| `maxRetries` | `number` | Nonnegative integer; defaults to 2. |
|
|
25
|
+
| `abortSignal` | `AbortSignal` | Cancels the decisions request. |
|
|
26
|
+
| `headers` | `Record<string, string>` | Additional HTTP headers. |
|
|
27
|
+
| `providerOptions` | `ProviderOptions` | Provider-specific options. |
|
|
28
|
+
| `telemetry` | `TelemetryOptions` | Telemetry configuration, including per-call integrations, input/output recording, and a function ID. |
|
|
29
|
+
| `runtimeContext` | `Record<string, unknown>` | Context available to lifecycle callbacks and selectively included in telemetry with `telemetry.includeRuntimeContext`. |
|
|
30
|
+
| `onStart` | `(event: Experimental_DecideStartEvent) => void` | Called when the decision operation begins. |
|
|
31
|
+
| `onEnd` | `(event: Experimental_DecideEndEvent) => void` | Called when the decision operation completes successfully. |
|
|
32
|
+
|
|
33
|
+
Set `reasoning: 'provider-default'` to use the underlying language model's default
|
|
34
|
+
reasoning effort instead of the adapter's `'none'` default.
|
|
30
35
|
|
|
31
36
|
See [Lifecycle Callbacks](/docs/ai-sdk-core/lifecycle-callbacks#experimental_decide)
|
|
32
37
|
for the complete `onStart` and `onEnd` event fields.
|
|
@@ -17,7 +17,7 @@ const { providerReference } = await uploadSkill({
|
|
|
17
17
|
files: [
|
|
18
18
|
{
|
|
19
19
|
path: 'my-skill/SKILL.md',
|
|
20
|
-
|
|
20
|
+
data: readFileSync('./SKILL.md'),
|
|
21
21
|
},
|
|
22
22
|
],
|
|
23
23
|
displayTitle: 'My Skill',
|
|
@@ -42,9 +42,9 @@ const { providerReference } = await uploadSkill({
|
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
name: 'files',
|
|
45
|
-
type: '
|
|
45
|
+
type: 'UploadSkillFile[]',
|
|
46
46
|
description:
|
|
47
|
-
|
|
47
|
+
"The files that make up the skill. Each file must have a relative `path` and `data`. The `data` can be a string, a `Uint8Array`, or an object with `type: 'text'` and a string `text` value, or `type: 'data'` and a string `data` value.",
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
name: 'displayTitle',
|
|
@@ -224,7 +224,7 @@ When used with useChat (`UIMessage` format), dynamic tools appear as `dynamic-to
|
|
|
224
224
|
switch (part.type) {
|
|
225
225
|
case 'dynamic-tool':
|
|
226
226
|
return (
|
|
227
|
-
<div>
|
|
227
|
+
<div key={part.toolCallId}>
|
|
228
228
|
<h4>Tool: {part.toolName}</h4>
|
|
229
229
|
<pre>{JSON.stringify(part.input, null, 2)}</pre>
|
|
230
230
|
</div>
|
|
@@ -6,18 +6,18 @@ collapsed: true
|
|
|
6
6
|
|
|
7
7
|
# Migration Guides
|
|
8
8
|
|
|
9
|
-
- [
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
13
|
-
- [
|
|
14
|
-
- [
|
|
15
|
-
- [
|
|
16
|
-
- [
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
19
|
-
- [
|
|
9
|
+
- [Migrate AI SDK 6.x to 7.0](/docs/migration-guides/migration-guide-7-0)
|
|
10
|
+
- [Migrate AI SDK 5.x to 6.0](/docs/migration-guides/migration-guide-6-0)
|
|
11
|
+
- [Migrate AI SDK 4.x to 5.0](/docs/migration-guides/migration-guide-5-0)
|
|
12
|
+
- [Migrate your data to AI SDK 5.0](/docs/migration-guides/migration-guide-5-0-data)
|
|
13
|
+
- [Migrate AI SDK 4.1 to 4.2](/docs/migration-guides/migration-guide-4-2)
|
|
14
|
+
- [Migrate AI SDK 4.0 to 4.1](/docs/migration-guides/migration-guide-4-1)
|
|
15
|
+
- [Migrate AI SDK 3.4 to 4.0](/docs/migration-guides/migration-guide-4-0)
|
|
16
|
+
- [Migrate AI SDK 3.3 to 3.4](/docs/migration-guides/migration-guide-3-4)
|
|
17
|
+
- [Migrate AI SDK 3.2 to 3.3](/docs/migration-guides/migration-guide-3-3)
|
|
18
|
+
- [Migrate AI SDK 3.1 to 3.2](/docs/migration-guides/migration-guide-3-2)
|
|
19
|
+
- [Migrate AI SDK 3.0 to 3.1](/docs/migration-guides/migration-guide-3-1)
|
|
20
20
|
|
|
21
21
|
## Versioning
|
|
22
22
|
|
|
23
|
-
- [
|
|
23
|
+
- [Versioning](/docs/migration-guides/versioning)
|
|
@@ -38,7 +38,7 @@ const tools = {
|
|
|
38
38
|
};
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
2.
|
|
41
|
+
2. For client-side execution with `useChat` (omitting the `execute` function), you must provide results using `addToolOutput`:
|
|
42
42
|
|
|
43
43
|
```tsx
|
|
44
44
|
import { useChat } from '@ai-sdk/react';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.147",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -42,20 +42,20 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@ai-sdk/gateway": "4.0.
|
|
46
|
-
"@ai-sdk/provider": "4.0.
|
|
47
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
45
|
+
"@ai-sdk/gateway": "4.0.120",
|
|
46
|
+
"@ai-sdk/provider": "4.0.31",
|
|
47
|
+
"@ai-sdk/provider-utils": "5.0.64"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@ai-sdk/amazon-bedrock": "5.0.
|
|
51
|
-
"@ai-sdk/deepseek": "3.0.
|
|
52
|
-
"@ai-sdk/google": "4.0.
|
|
53
|
-
"@ai-sdk/groq": "4.0.
|
|
54
|
-
"@ai-sdk/huggingface": "2.0.
|
|
55
|
-
"@ai-sdk/moonshotai": "3.0.
|
|
56
|
-
"@ai-sdk/openai": "4.0.
|
|
50
|
+
"@ai-sdk/amazon-bedrock": "5.0.120",
|
|
51
|
+
"@ai-sdk/deepseek": "3.0.69",
|
|
52
|
+
"@ai-sdk/google": "4.0.101",
|
|
53
|
+
"@ai-sdk/groq": "4.0.66",
|
|
54
|
+
"@ai-sdk/huggingface": "2.0.74",
|
|
55
|
+
"@ai-sdk/moonshotai": "3.0.73",
|
|
56
|
+
"@ai-sdk/openai": "4.0.98",
|
|
57
57
|
"@ai-sdk/test-server": "2.0.4",
|
|
58
|
-
"@ai-sdk/xai": "5.0.
|
|
58
|
+
"@ai-sdk/xai": "5.0.26",
|
|
59
59
|
"@edge-runtime/vm": "^5.0.0",
|
|
60
60
|
"@smithy/eventstream-codec": "^4.3.3",
|
|
61
61
|
"@smithy/util-utf8": "^4.3.3",
|
|
@@ -34,6 +34,12 @@ export type DecideStartEvent<RUNTIME_CONTEXT extends Context = Context> = {
|
|
|
34
34
|
/** The questions to decide against the shared state. */
|
|
35
35
|
readonly questions: Readonly<Record<string, DecisionQuestion>>;
|
|
36
36
|
|
|
37
|
+
/** Maximum output tokens requested for the decision. */
|
|
38
|
+
readonly maxOutputTokens?: number;
|
|
39
|
+
|
|
40
|
+
/** Reasoning effort requested for the decision. */
|
|
41
|
+
readonly reasoning?: DecisionModelV4CallOptions['reasoning'];
|
|
42
|
+
|
|
37
43
|
/** Maximum number of retries for the decision model call. */
|
|
38
44
|
readonly maxRetries: number;
|
|
39
45
|
|
package/src/decide/decide.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
Experimental_DecisionRefusalError as DecisionRefusalError,
|
|
3
3
|
Experimental_DecisionUnsupportedQuestionTypeError as DecisionUnsupportedQuestionTypeError,
|
|
4
4
|
type Experimental_DecisionModelV4Question as DecisionQuestion,
|
|
5
|
+
type Experimental_DecisionModelV4CallOptions as DecisionCallOptions,
|
|
5
6
|
} from '@ai-sdk/provider';
|
|
6
7
|
import {
|
|
7
8
|
createIdGenerator,
|
|
@@ -16,6 +17,7 @@ import type { TelemetryOptions } from '../telemetry/telemetry-options';
|
|
|
16
17
|
import type { Callback } from '../util/callback';
|
|
17
18
|
import { notify } from '../util/notify';
|
|
18
19
|
import { prepareRetries } from '../util/prepare-retries';
|
|
20
|
+
import { prepareLanguageModelCallOptions } from '../prompt/prepare-language-model-call-options';
|
|
19
21
|
import { VERSION } from '../version';
|
|
20
22
|
import type { DecideEndEvent, DecideStartEvent } from './decide-events';
|
|
21
23
|
import type { DecisionModel, DecisionResult } from './decision-result';
|
|
@@ -38,6 +40,8 @@ export async function decide<
|
|
|
38
40
|
model: modelArg,
|
|
39
41
|
state,
|
|
40
42
|
questions,
|
|
43
|
+
maxOutputTokens,
|
|
44
|
+
reasoning,
|
|
41
45
|
maxRetries,
|
|
42
46
|
abortSignal,
|
|
43
47
|
headers,
|
|
@@ -52,6 +56,10 @@ export async function decide<
|
|
|
52
56
|
model: DecisionModel;
|
|
53
57
|
state: DecisionState;
|
|
54
58
|
questions: QUESTIONS;
|
|
59
|
+
/** Maximum output tokens for supported models. Must be an integer >= 1. */
|
|
60
|
+
maxOutputTokens?: number;
|
|
61
|
+
/** Reasoning effort for supported models. Language-model adapters default to none. */
|
|
62
|
+
reasoning?: DecisionCallOptions['reasoning'];
|
|
55
63
|
/** Maximum retries for transient provider failures. Defaults to 2. */
|
|
56
64
|
maxRetries?: number;
|
|
57
65
|
abortSignal?: AbortSignal;
|
|
@@ -72,6 +80,7 @@ export async function decide<
|
|
|
72
80
|
}): Promise<DecisionResult<QUESTIONS>> {
|
|
73
81
|
const model = resolveDecisionModel(modelArg);
|
|
74
82
|
|
|
83
|
+
prepareLanguageModelCallOptions({ maxOutputTokens });
|
|
75
84
|
validateDecisionInput({ state, questions });
|
|
76
85
|
|
|
77
86
|
for (const [questionId, question] of Object.entries(questions)) {
|
|
@@ -105,6 +114,8 @@ export async function decide<
|
|
|
105
114
|
modelId: model.modelId,
|
|
106
115
|
state,
|
|
107
116
|
questions,
|
|
117
|
+
maxOutputTokens,
|
|
118
|
+
reasoning,
|
|
108
119
|
maxRetries: resolvedMaxRetries,
|
|
109
120
|
headers,
|
|
110
121
|
providerOptions,
|
|
@@ -139,6 +150,8 @@ export async function decide<
|
|
|
139
150
|
return await model.doDecide({
|
|
140
151
|
state: preparedState,
|
|
141
152
|
questions,
|
|
153
|
+
maxOutputTokens,
|
|
154
|
+
reasoning,
|
|
142
155
|
abortSignal,
|
|
143
156
|
headers: withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`),
|
|
144
157
|
providerOptions,
|
|
@@ -491,7 +491,7 @@ function getArrayLengthValidationError({
|
|
|
491
491
|
|
|
492
492
|
/**
|
|
493
493
|
* Output specification for choice generation.
|
|
494
|
-
* When the model generates a text response, it will return
|
|
494
|
+
* When the model generates a text response, it will return one of the choice options.
|
|
495
495
|
*
|
|
496
496
|
* @param options - The available choices.
|
|
497
497
|
* @param name - Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name.
|
|
@@ -163,42 +163,101 @@ export function pruneMessages({
|
|
|
163
163
|
return message;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
166
|
+
const keepParts = message.content.map(part => {
|
|
167
|
+
// keep non-tool parts:
|
|
168
|
+
if (
|
|
169
|
+
part.type !== 'tool-call' &&
|
|
170
|
+
part.type !== 'tool-result' &&
|
|
171
|
+
part.type !== 'tool-approval-request' &&
|
|
172
|
+
part.type !== 'tool-approval-response'
|
|
173
|
+
) {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// keep parts that are associated with a tool call or approval that needs to be kept:
|
|
178
|
+
if (
|
|
179
|
+
((part.type === 'tool-call' || part.type === 'tool-result') &&
|
|
180
|
+
keptToolCallIds.has(part.toolCallId)) ||
|
|
181
|
+
((part.type === 'tool-approval-request' ||
|
|
182
|
+
part.type === 'tool-approval-response') &&
|
|
183
|
+
keptApprovalIds.has(part.approvalId))
|
|
184
|
+
) {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// keep parts that are not associated with a tool that should be removed:
|
|
189
|
+
const partToolName =
|
|
190
|
+
part.type === 'tool-call' || part.type === 'tool-result'
|
|
191
|
+
? part.toolName
|
|
192
|
+
: approvalIdToToolName.get(part.approvalId);
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
toolCall.tools != null &&
|
|
196
|
+
partToolName != null &&
|
|
197
|
+
!toolCall.tools.includes(partToolName)
|
|
198
|
+
);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Consecutive reasoning parts can belong to the same provider item.
|
|
202
|
+
// Remove the whole group when its following content was pruned.
|
|
203
|
+
if (message.role === 'assistant') {
|
|
204
|
+
for (
|
|
205
|
+
let reasoningIndex = 0;
|
|
206
|
+
reasoningIndex < message.content.length;
|
|
207
|
+
reasoningIndex++
|
|
208
|
+
) {
|
|
209
|
+
const part = message.content[reasoningIndex];
|
|
210
|
+
if (part.type !== 'reasoning' && part.type !== 'reasoning-file') {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
let reasoningEndIndex = reasoningIndex + 1;
|
|
215
|
+
while (reasoningEndIndex < message.content.length) {
|
|
216
|
+
const nextPart = message.content[reasoningEndIndex];
|
|
217
|
+
if (
|
|
218
|
+
nextPart.type !== 'reasoning' &&
|
|
219
|
+
nextPart.type !== 'reasoning-file'
|
|
220
|
+
) {
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
reasoningEndIndex++;
|
|
177
224
|
}
|
|
178
225
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
226
|
+
let followingPartIndex = reasoningEndIndex;
|
|
227
|
+
let hasFollowingPart = false;
|
|
228
|
+
let hasKeptFollowingPart = false;
|
|
229
|
+
|
|
230
|
+
while (followingPartIndex < message.content.length) {
|
|
231
|
+
const followingPart = message.content[followingPartIndex];
|
|
232
|
+
if (
|
|
233
|
+
followingPart.type === 'reasoning' ||
|
|
234
|
+
followingPart.type === 'reasoning-file'
|
|
235
|
+
) {
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
hasFollowingPart = true;
|
|
240
|
+
hasKeptFollowingPart ||= keepParts[followingPartIndex];
|
|
241
|
+
followingPartIndex++;
|
|
188
242
|
}
|
|
189
243
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
244
|
+
if (hasFollowingPart && !hasKeptFollowingPart) {
|
|
245
|
+
for (
|
|
246
|
+
let index = reasoningIndex;
|
|
247
|
+
index < reasoningEndIndex;
|
|
248
|
+
index++
|
|
249
|
+
) {
|
|
250
|
+
keepParts[index] = false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
reasoningIndex = followingPartIndex - 1;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
...message,
|
|
260
|
+
content: message.content.filter((_, index) => keepParts[index]),
|
|
202
261
|
} as AssistantModelMessage | ToolModelMessage;
|
|
203
262
|
});
|
|
204
263
|
}
|
|
@@ -18,7 +18,7 @@ type BaseToolCall = {
|
|
|
18
18
|
* with an `input` type inferred from that tool's input schema.
|
|
19
19
|
*/
|
|
20
20
|
export type StaticToolCall<TOOLS extends ToolSet> = ValueOf<{
|
|
21
|
-
[NAME in keyof TOOLS]
|
|
21
|
+
[NAME in keyof TOOLS]-?: BaseToolCall & {
|
|
22
22
|
toolName: NAME & string;
|
|
23
23
|
input: InferToolInput<TOOLS[NAME]>;
|
|
24
24
|
dynamic?: false | undefined;
|
|
@@ -4,7 +4,7 @@ import type { ProviderMetadata } from '../types';
|
|
|
4
4
|
import type { ValueOf } from '../util/value-of';
|
|
5
5
|
|
|
6
6
|
export type StaticToolError<TOOLS extends ToolSet> = ValueOf<{
|
|
7
|
-
[NAME in keyof TOOLS]
|
|
7
|
+
[NAME in keyof TOOLS]-?: {
|
|
8
8
|
type: 'tool-error';
|
|
9
9
|
toolCallId: string;
|
|
10
10
|
toolName: NAME & string;
|
|
@@ -36,7 +36,7 @@ type BaseToolExecutionStartFields = {
|
|
|
36
36
|
* validated `toolContext` type.
|
|
37
37
|
*/
|
|
38
38
|
type StaticToolExecutionStartEvent<TOOLS extends ToolSet> = ValueOf<{
|
|
39
|
-
[NAME in keyof TOOLS]
|
|
39
|
+
[NAME in keyof TOOLS]-?: BaseToolExecutionStartFields & {
|
|
40
40
|
readonly toolCall: Extract<StaticToolCall<TOOLS>, { toolName: NAME }>;
|
|
41
41
|
readonly toolContext: ToolContextFor<TOOLS[NAME]>;
|
|
42
42
|
};
|
|
@@ -93,7 +93,7 @@ type BaseToolExecutionEndFields = {
|
|
|
93
93
|
* corresponding validated `toolContext`, and the tool execution result.
|
|
94
94
|
*/
|
|
95
95
|
type StaticToolExecutionEndEvent<TOOLS extends ToolSet> = ValueOf<{
|
|
96
|
-
[NAME in keyof TOOLS]
|
|
96
|
+
[NAME in keyof TOOLS]-?: BaseToolExecutionEndFields & {
|
|
97
97
|
readonly toolCall: Extract<StaticToolCall<TOOLS>, { toolName: NAME }>;
|
|
98
98
|
readonly toolContext: ToolContextFor<TOOLS[NAME]>;
|
|
99
99
|
readonly toolOutput: ToolOutput<TOOLS>;
|
|
@@ -5,7 +5,7 @@ import type { ToolSet } from '@ai-sdk/provider-utils';
|
|
|
5
5
|
* Tool output when the tool execution has been denied (for static tools).
|
|
6
6
|
*/
|
|
7
7
|
export type StaticToolOutputDenied<TOOLS extends ToolSet> = ValueOf<{
|
|
8
|
-
[NAME in keyof TOOLS]
|
|
8
|
+
[NAME in keyof TOOLS]-?: {
|
|
9
9
|
type: 'tool-output-denied';
|
|
10
10
|
toolCallId: string;
|
|
11
11
|
toolName: NAME & string;
|
|
@@ -8,7 +8,7 @@ import type { ProviderMetadata } from '../types';
|
|
|
8
8
|
import type { ValueOf } from '../../src/util/value-of';
|
|
9
9
|
|
|
10
10
|
export type StaticToolResult<TOOLS extends ToolSet> = ValueOf<{
|
|
11
|
-
[NAME in keyof TOOLS]
|
|
11
|
+
[NAME in keyof TOOLS]-?: {
|
|
12
12
|
type: 'tool-result';
|
|
13
13
|
toolCallId: string;
|
|
14
14
|
toolName: NAME & string;
|
|
@@ -271,6 +271,7 @@ export function processUIMessageStream<UI_MESSAGE extends UIMessage>({
|
|
|
271
271
|
|
|
272
272
|
if (part != null) {
|
|
273
273
|
part.state = options.state;
|
|
274
|
+
anyPart.type = `tool-${options.toolName}`;
|
|
274
275
|
anyPart.input = anyOptions.input;
|
|
275
276
|
anyPart.output = anyOptions.output;
|
|
276
277
|
anyPart.errorText = anyOptions.errorText;
|