ai 7.0.89 → 7.0.91
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 +19 -0
- package/dist/index.d.ts +42 -4
- package/dist/index.js +401 -81
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +3 -1
- package/dist/internal/index.js +9 -7
- package/dist/internal/index.js.map +1 -1
- package/docs/02-foundations/02-providers-and-models.mdx +6 -0
- package/docs/03-agents/06-policy-tool-approvals.mdx +2 -1
- package/docs/03-agents/06-tool-approvals.mdx +7 -4
- package/docs/03-agents/07-workflow-agent.mdx +15 -0
- package/docs/03-ai-sdk-core/50-error-handling.mdx +83 -6
- package/docs/06-advanced/11-secure-url-fetching.mdx +7 -1
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +9 -2
- package/package.json +11 -11
- package/src/generate-text/execute-tools-from-stream.ts +18 -4
- package/src/generate-text/index.ts +2 -0
- package/src/generate-text/invoke-tool-callbacks-from-stream.ts +14 -2
- package/src/generate-text/stream-retry-attempt-boundary.ts +29 -0
- package/src/generate-text/stream-text.ts +635 -156
- package/src/util/prepare-retries.ts +9 -5
|
@@ -145,6 +145,7 @@ Here are the capabilities of popular models:
|
|
|
145
145
|
| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5-codex` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
146
146
|
| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5-chat-latest` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
147
147
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-sonnet-5` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
148
|
+
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-fable-5-1` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
148
149
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-fable-5` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
149
150
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-opus-4-8` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
150
151
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-opus-4-7` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
@@ -154,6 +155,11 @@ Here are the capabilities of popular models:
|
|
|
154
155
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-opus-4-1` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
155
156
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-opus-4-0` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
156
157
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-sonnet-4-0` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
158
|
+
| [Google](/providers/ai-sdk-providers/google) | `gemini-3.8-flash` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
159
|
+
| [Google](/providers/ai-sdk-providers/google) | `gemini-3.1-pro-preview` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
160
|
+
| [Google](/providers/ai-sdk-providers/google) | `gemini-3-pro-preview` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
161
|
+
| [Google](/providers/ai-sdk-providers/google) | `gemini-2.5-pro` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
162
|
+
| [Google](/providers/ai-sdk-providers/google) | `gemini-2.5-flash` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
157
163
|
| [Mistral](/providers/ai-sdk-providers/mistral) | `pixtral-large-latest` | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
158
164
|
| [Mistral](/providers/ai-sdk-providers/mistral) | `mistral-large-latest` | <Cross /> | <Check /> | <Check /> | <Check /> |
|
|
159
165
|
| [Mistral](/providers/ai-sdk-providers/mistral) | `mistral-medium-latest` | <Cross /> | <Check /> | <Check /> | <Check /> |
|
|
@@ -156,9 +156,10 @@ Run with `opa test policy.rego policy_test.rego`.
|
|
|
156
156
|
### Errors fail closed
|
|
157
157
|
|
|
158
158
|
- If the backend errors (server unreachable, WASM fault, misbuilt bundle), `opaPolicy` returns `denied` with the error message as the reason.
|
|
159
|
+
- If the backend returns a present but unrecognized decision, such as an unknown `decision` value or a non-boolean legacy `allow` value, `opaPolicy` returns `denied`.
|
|
159
160
|
- The error never rejects out of the callback and never aborts the run.
|
|
160
161
|
- A backend outage blocks the affected call rather than silently allowing it.
|
|
161
|
-
- This is distinct from a rule that returns no match
|
|
162
|
+
- This is distinct from a rule that returns no match: `null` or `undefined` normalizes to `not-applicable` (allow). Use a `default ... deny` rule if you want unmatched calls denied too.
|
|
162
163
|
|
|
163
164
|
## Loading the policy
|
|
164
165
|
|
|
@@ -284,14 +284,17 @@ If your tools perform sensitive operations (modifying data, spending money, call
|
|
|
284
284
|
|
|
285
285
|
### Signing approvals with `experimental_toolApprovalSecret`
|
|
286
286
|
|
|
287
|
-
When you provide a secret, the server HMAC-signs each approval request at issuance and verifies the signature when the approval is replayed. A forged or tampered approval is rejected before the tool executes.
|
|
287
|
+
When you provide a secret, the server HMAC-signs each approval request at issuance and verifies the signature when the approval is replayed. A forged or tampered approval is rejected before the tool executes. Configure the secret on `ToolLoopAgent` (or pass it directly to `generateText` or `streamText`).
|
|
288
288
|
|
|
289
|
-
```ts highlight="
|
|
290
|
-
const
|
|
289
|
+
```ts highlight="6"
|
|
290
|
+
const agent = new ToolLoopAgent({
|
|
291
291
|
model: __MODEL__,
|
|
292
292
|
tools: { deleteFile, runQuery },
|
|
293
293
|
toolApproval: { deleteFile: 'user-approval', runQuery: 'user-approval' },
|
|
294
294
|
experimental_toolApprovalSecret: process.env.TOOL_APPROVAL_SECRET,
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const result = await agent.generate({
|
|
295
298
|
messages,
|
|
296
299
|
});
|
|
297
300
|
```
|
|
@@ -308,7 +311,7 @@ The signature binds the approval to the exact tool name, tool call ID, and input
|
|
|
308
311
|
```
|
|
309
312
|
TOOL_APPROVAL_SECRET=your-generated-secret-here
|
|
310
313
|
```
|
|
311
|
-
3. Pass it to `generateText
|
|
314
|
+
3. Pass it to `ToolLoopAgent`, `generateText`, or `streamText` via `experimental_toolApprovalSecret`.
|
|
312
315
|
|
|
313
316
|
Every serverless instance that might handle a request needs the same secret, since one instance signs the approval and a different instance may verify it on the next turn.
|
|
314
317
|
|
|
@@ -613,6 +613,21 @@ const agent = new WorkflowAgent({
|
|
|
613
613
|
});
|
|
614
614
|
```
|
|
615
615
|
|
|
616
|
+
Tool input callbacks (`onInputStart`, `onInputDelta`, and
|
|
617
|
+
`onInputAvailable`) are also preserved by `WorkflowAgent`. The model call runs
|
|
618
|
+
inside a durable step, while callback functions remain in the workflow
|
|
619
|
+
context because arbitrary functions cannot cross the step boundary. As a
|
|
620
|
+
result, `WorkflowAgent` records the callback events during the model step and
|
|
621
|
+
replays them in order immediately after that step completes, before tool
|
|
622
|
+
execution and step lifecycle callbacks. They do not run concurrently with
|
|
623
|
+
model generation and cannot provide in-flight cancellation or backpressure.
|
|
624
|
+
Each callback receives its tool's `toolsContext` entry after
|
|
625
|
+
`contextSchema` validation.
|
|
626
|
+
|
|
627
|
+
For highly fragmented tool inputs, `onInputDelta` replay data is part of the
|
|
628
|
+
durable model-step result. Only configure `onInputDelta` when each generated
|
|
629
|
+
delta is needed; omit it to avoid retaining delta replay data.
|
|
630
|
+
|
|
616
631
|
The deprecated `experimental_onStart` and `experimental_onStepStart` names
|
|
617
632
|
remain available for backwards compatibility. When both the stable and
|
|
618
633
|
experimental name are provided in the same constructor or `stream()` call, the
|
|
@@ -101,12 +101,89 @@ try {
|
|
|
101
101
|
}
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
## Retrying provider errors after streaming starts
|
|
105
|
+
|
|
106
|
+
`maxRetries` retries failures that happen while starting a model call. To retry
|
|
107
|
+
well-formed provider error events received after response streaming has begun,
|
|
108
|
+
set `streamRetries`:
|
|
109
|
+
|
|
110
|
+
```ts highlight="7"
|
|
111
|
+
import { streamText } from 'ai';
|
|
112
|
+
__PROVIDER_IMPORT__;
|
|
113
|
+
|
|
114
|
+
const { textStream } = streamText({
|
|
115
|
+
model: __MODEL__,
|
|
116
|
+
prompt: 'Write a vegetarian lasagna recipe for 4 people.',
|
|
117
|
+
streamRetries: 2,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
for await (const textPart of textStream) {
|
|
121
|
+
process.stdout.write(textPart);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Stream retries rerun only the failed model step with the same accumulated
|
|
126
|
+
conversation and generation context. Earlier completed steps, including their
|
|
127
|
+
tool calls and tool results, are not replayed. Tool input, tool calls, approval
|
|
128
|
+
requests, tool callbacks, and client-side tool execution from a failed attempt
|
|
129
|
+
are discarded. They are only exposed or executed after an attempt reaches a
|
|
130
|
+
successful model-call finish.
|
|
131
|
+
|
|
132
|
+
Well-formed provider error events are normalized into
|
|
133
|
+
[`StreamProviderError`](/docs/reference/ai-sdk-errors/ai-stream-provider-error)
|
|
134
|
+
instances. The same instance is supplied to `onError` and, if recovery is not
|
|
135
|
+
requested or retries are exhausted, to the `error` part in the full stream. Use
|
|
136
|
+
its `isRetryable` metadata when deciding whether to request recovery.
|
|
137
|
+
|
|
138
|
+
A retry remains part of the same logical step. `onStepStart` runs once for that
|
|
139
|
+
step. `onLanguageModelCallStart` runs for each provider call attempt, while
|
|
140
|
+
`onLanguageModelCallEnd` runs only for attempts that reach a model-call finish.
|
|
141
|
+
|
|
142
|
+
You can also decide dynamically in `onError`. Set `streamRetries` explicitly to
|
|
143
|
+
enable stream recovery; use `0` when a single retry should only be
|
|
144
|
+
callback-directed:
|
|
145
|
+
|
|
146
|
+
```ts highlight="7-12"
|
|
147
|
+
const result = streamText({
|
|
148
|
+
model: __MODEL__,
|
|
149
|
+
prompt: 'Write a vegetarian lasagna recipe for 4 people.',
|
|
150
|
+
streamRetries: 0,
|
|
151
|
+
onError: ({ error }) => {
|
|
152
|
+
if (isTransientProviderError(error)) {
|
|
153
|
+
return { retry: true };
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Callback-directed recovery is limited to one retry per logical step. When
|
|
160
|
+
automatic retries are configured, `onError` can request one additional retry
|
|
161
|
+
after the automatic retry budget is exhausted. This bounds the total number of
|
|
162
|
+
recovery calls for a step to `streamRetries + 1`.
|
|
163
|
+
|
|
164
|
+
When `streamRetries` is omitted, all stream retry behavior is disabled and an
|
|
165
|
+
existing logging-only `onError` callback retains incremental tool streaming.
|
|
166
|
+
An `onError` return value other than `{ retry: true }` keeps its previous
|
|
167
|
+
behavior and does not request recovery. Provider error events that are
|
|
168
|
+
recovered are not emitted as final `error` parts.
|
|
169
|
+
|
|
170
|
+
<Note type="warning">
|
|
171
|
+
Non-tool output emitted before a provider error cannot be retracted. A retried
|
|
172
|
+
model step may therefore append repeated or divergent partial text, reasoning,
|
|
173
|
+
files, or sources to consumer streams. Open text and reasoning parts are ended
|
|
174
|
+
before recovered output begins so UI consumers do not retain them in a
|
|
175
|
+
streaming state. Failed-attempt output is excluded from the recovered step
|
|
176
|
+
result, structured output parsing, response messages, and subsequent model
|
|
177
|
+
steps. Final request and response metadata come from the recovered attempt.
|
|
178
|
+
Retries also add latency and may incur additional provider usage and cost.
|
|
179
|
+
</Note>
|
|
180
|
+
|
|
181
|
+
<Note type="warning">
|
|
182
|
+
Failed-attempt isolation prevents AI SDK client-side tools from executing, but
|
|
183
|
+
it cannot undo work already performed by provider-executed tools. Retrying a
|
|
184
|
+
step after provider-side work may repeat that work or its cost. Use
|
|
185
|
+
idempotency controls for provider-executed side effects.
|
|
186
|
+
</Note>
|
|
110
187
|
|
|
111
188
|
## Handling stream aborts
|
|
112
189
|
|
|
@@ -17,6 +17,11 @@ To prevent that, the SDK validates every response-supplied URL before fetching
|
|
|
17
17
|
it. This happens automatically inside the provider packages — you don't need to
|
|
18
18
|
configure anything.
|
|
19
19
|
|
|
20
|
+
For authenticated task-status polling, providers can construct the first URL
|
|
21
|
+
from the configured API endpoint. The SDK trusts that configured origin for the
|
|
22
|
+
initial request, but manually follows and validates every redirect away from it.
|
|
23
|
+
MiniMax, Kling AI, and ByteDance video polling use this protected path.
|
|
24
|
+
|
|
20
25
|
## What the SDK protects against
|
|
21
26
|
|
|
22
27
|
When the SDK fetches a URL taken from a provider response, it:
|
|
@@ -45,7 +50,8 @@ A blocked URL surfaces as a `DownloadError`.
|
|
|
45
50
|
URLs that are same-origin with the provider endpoint **you configured** (e.g. a
|
|
46
51
|
custom `baseURL` pointing at a self-hosted or `localhost` deployment) are
|
|
47
52
|
exempt from these checks — they target exactly the host you told the SDK to
|
|
48
|
-
talk to. Any redirect off that origin
|
|
53
|
+
talk to. This also applies to task-status polling. Any redirect off that origin
|
|
54
|
+
is still validated before the redirected request is sent.
|
|
49
55
|
|
|
50
56
|
## DNS validation across runtimes
|
|
51
57
|
|
|
@@ -468,6 +468,13 @@ To see `streamText` in action, check out [these examples](#examples).
|
|
|
468
468
|
description:
|
|
469
469
|
'Maximum number of retries. Set to 0 to disable retries. Default: 2.',
|
|
470
470
|
},
|
|
471
|
+
{
|
|
472
|
+
name: 'streamRetries',
|
|
473
|
+
type: 'number',
|
|
474
|
+
isOptional: true,
|
|
475
|
+
description:
|
|
476
|
+
'Maximum number of automatic retries for provider error events received after response streaming begins. Retries rerun only the current model step and preserve completed earlier steps and their tool results. Tool-related output and client-side tool work from failed attempts are discarded; other output already emitted cannot be retracted, but is excluded from the recovered step result, structured output parsing, response messages, and subsequent model steps. Final request and response metadata come from the recovered attempt. Open text and reasoning parts are ended before recovered output begins. onStepStart runs once for the logical step, onLanguageModelCallStart runs for each attempt, and onLanguageModelCallEnd runs for attempts that reach a model-call finish. Provider-executed tool work cannot be undone and may repeat. Set to 0 to disable automatic retries while allowing onError to request one callback-directed retry. With automatic retries configured, onError can request at most one additional retry after they are exhausted, bounding total recovery calls to streamRetries + 1. Omit to disable all stream retry behavior and preserve incremental tool streaming for existing onError observers. Default: 0.',
|
|
477
|
+
},
|
|
471
478
|
{
|
|
472
479
|
name: 'abortSignal',
|
|
473
480
|
type: 'AbortSignal',
|
|
@@ -1184,10 +1191,10 @@ To see `streamText` in action, check out [these examples](#examples).
|
|
|
1184
1191
|
},
|
|
1185
1192
|
{
|
|
1186
1193
|
name: 'onError',
|
|
1187
|
-
type: '
|
|
1194
|
+
type: 'StreamTextOnErrorCallback | StreamTextOnErrorRetryCallback',
|
|
1188
1195
|
isOptional: true,
|
|
1189
1196
|
description:
|
|
1190
|
-
'Callback that is called when an error occurs during streaming. Well-formed mid-stream provider error events are exposed as StreamProviderError instances.',
|
|
1197
|
+
'Callback that is called when an error occurs during streaming. StreamTextOnErrorCallback preserves the existing PromiseLike<void> | void observer contract. StreamTextOnErrorRetryCallback additionally types `{ retry: true }` results for retry-capable handlers. Well-formed mid-stream provider error events are exposed as StreamProviderError instances. When streamRetries is explicitly configured, return `{ retry: true }` to request one callback-directed retry for the current model step after automatic retries are exhausted. Other return values do not request a retry.',
|
|
1191
1198
|
properties: [
|
|
1192
1199
|
{
|
|
1193
1200
|
type: 'OnErrorResult',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.91",
|
|
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.
|
|
45
|
+
"@ai-sdk/gateway": "4.0.73",
|
|
46
46
|
"@ai-sdk/provider": "4.0.10",
|
|
47
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
47
|
+
"@ai-sdk/provider-utils": "5.0.36"
|
|
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.73",
|
|
51
|
+
"@ai-sdk/deepseek": "3.0.39",
|
|
52
|
+
"@ai-sdk/google": "4.0.63",
|
|
53
|
+
"@ai-sdk/groq": "4.0.37",
|
|
54
|
+
"@ai-sdk/huggingface": "2.0.43",
|
|
55
|
+
"@ai-sdk/moonshotai": "3.0.45",
|
|
56
|
+
"@ai-sdk/openai": "4.0.57",
|
|
57
57
|
"@ai-sdk/test-server": "2.0.1",
|
|
58
|
-
"@ai-sdk/xai": "4.0.
|
|
58
|
+
"@ai-sdk/xai": "4.0.54",
|
|
59
59
|
"@edge-runtime/vm": "^5.0.0",
|
|
60
60
|
"@smithy/eventstream-codec": "^4.3.3",
|
|
61
61
|
"@smithy/util-utf8": "^4.3.3",
|
|
@@ -14,6 +14,10 @@ import { executeToolCall } from './execute-tool-call';
|
|
|
14
14
|
import { isToolExecutionAllowedFinishReason } from './is-tool-execution-allowed-finish-reason';
|
|
15
15
|
import { resolveToolApproval } from './resolve-tool-approval';
|
|
16
16
|
import type { LanguageModelStreamPart } from './stream-language-model-call';
|
|
17
|
+
import {
|
|
18
|
+
isStreamRetryAttemptBoundaryPart,
|
|
19
|
+
type StreamRetryAttemptBoundaryPart,
|
|
20
|
+
} from './stream-retry-attempt-boundary';
|
|
17
21
|
import { maybeSignApproval } from './tool-approval-signature';
|
|
18
22
|
import type { ToolApprovalConfiguration } from './tool-approval-configuration';
|
|
19
23
|
import type { TypedToolCall } from './tool-call';
|
|
@@ -30,7 +34,12 @@ export type ToolExecutionEndStreamPart = {
|
|
|
30
34
|
|
|
31
35
|
export type ExecuteToolsStreamPart<TOOLS extends ToolSet = ToolSet> =
|
|
32
36
|
| LanguageModelStreamPart<TOOLS>
|
|
33
|
-
| ToolExecutionEndStreamPart
|
|
37
|
+
| ToolExecutionEndStreamPart
|
|
38
|
+
| StreamRetryAttemptBoundaryPart;
|
|
39
|
+
|
|
40
|
+
type ExecuteToolsInputStreamPart<TOOLS extends ToolSet> =
|
|
41
|
+
| LanguageModelStreamPart<TOOLS>
|
|
42
|
+
| StreamRetryAttemptBoundaryPart;
|
|
34
43
|
|
|
35
44
|
export function executeToolsFromStream<
|
|
36
45
|
TOOLS extends ToolSet,
|
|
@@ -53,7 +62,7 @@ export function executeToolsFromStream<
|
|
|
53
62
|
executeToolInTelemetryContext,
|
|
54
63
|
runInTracingChannelSpan,
|
|
55
64
|
}: {
|
|
56
|
-
stream: ReadableStream<
|
|
65
|
+
stream: ReadableStream<ExecuteToolsInputStreamPart<TOOLS>>;
|
|
57
66
|
tools: TOOLS | undefined;
|
|
58
67
|
callId: string;
|
|
59
68
|
messages: ModelMessage[];
|
|
@@ -77,11 +86,11 @@ export function executeToolsFromStream<
|
|
|
77
86
|
// forward stream
|
|
78
87
|
return stream.pipeThrough(
|
|
79
88
|
new TransformStream<
|
|
80
|
-
|
|
89
|
+
ExecuteToolsInputStreamPart<TOOLS>,
|
|
81
90
|
ExecuteToolsStreamPart<TOOLS>
|
|
82
91
|
>({
|
|
83
92
|
async transform(
|
|
84
|
-
chunk:
|
|
93
|
+
chunk: ExecuteToolsInputStreamPart<TOOLS>,
|
|
85
94
|
controller: TransformStreamDefaultController<
|
|
86
95
|
ExecuteToolsStreamPart<TOOLS>
|
|
87
96
|
>,
|
|
@@ -89,6 +98,11 @@ export function executeToolsFromStream<
|
|
|
89
98
|
// immediately forward all chunks
|
|
90
99
|
controller.enqueue(chunk);
|
|
91
100
|
|
|
101
|
+
if (isStreamRetryAttemptBoundaryPart(chunk)) {
|
|
102
|
+
toolCallsToExecute.length = 0;
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
92
106
|
const chunkType = chunk.type;
|
|
93
107
|
|
|
94
108
|
switch (chunkType) {
|
|
@@ -2,6 +2,14 @@ import type { Context, ModelMessage, ToolSet } from '@ai-sdk/provider-utils';
|
|
|
2
2
|
import { createIdMap } from '../util/create-id-map';
|
|
3
3
|
import { getOwn } from '../util/get-own';
|
|
4
4
|
import type { LanguageModelStreamPart } from './stream-language-model-call';
|
|
5
|
+
import {
|
|
6
|
+
isStreamRetryAttemptBoundaryPart,
|
|
7
|
+
type StreamRetryAttemptBoundaryPart,
|
|
8
|
+
} from './stream-retry-attempt-boundary';
|
|
9
|
+
|
|
10
|
+
type ToolCallbackStreamPart<TOOLS extends ToolSet> =
|
|
11
|
+
| LanguageModelStreamPart<TOOLS>
|
|
12
|
+
| StreamRetryAttemptBoundaryPart;
|
|
5
13
|
|
|
6
14
|
export function invokeToolCallbacksFromStream<
|
|
7
15
|
TOOLS extends ToolSet,
|
|
@@ -13,12 +21,12 @@ export function invokeToolCallbacksFromStream<
|
|
|
13
21
|
abortSignal,
|
|
14
22
|
runtimeContext,
|
|
15
23
|
}: {
|
|
16
|
-
stream: ReadableStream<
|
|
24
|
+
stream: ReadableStream<ToolCallbackStreamPart<TOOLS>>;
|
|
17
25
|
tools: TOOLS | undefined;
|
|
18
26
|
stepInputMessages: Array<ModelMessage>;
|
|
19
27
|
abortSignal: AbortSignal | undefined;
|
|
20
28
|
runtimeContext: RUNTIME_CONTEXT;
|
|
21
|
-
}): ReadableStream<
|
|
29
|
+
}): ReadableStream<ToolCallbackStreamPart<TOOLS>> {
|
|
22
30
|
if (tools == null) return stream;
|
|
23
31
|
|
|
24
32
|
const ongoingToolCallToolNames: Record<string, string> = createIdMap();
|
|
@@ -28,6 +36,10 @@ export function invokeToolCallbacksFromStream<
|
|
|
28
36
|
async transform(chunk, controller) {
|
|
29
37
|
controller.enqueue(chunk);
|
|
30
38
|
|
|
39
|
+
if (isStreamRetryAttemptBoundaryPart(chunk)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
31
43
|
switch (chunk.type) {
|
|
32
44
|
case 'tool-input-start': {
|
|
33
45
|
ongoingToolCallToolNames[chunk.id] = chunk.toolName;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SharedV4Warning } from '@ai-sdk/provider';
|
|
2
|
+
|
|
3
|
+
const streamRetryAttemptBoundarySymbol = Symbol('streamRetryAttemptBoundary');
|
|
4
|
+
|
|
5
|
+
export type StreamRetryAttemptBoundaryPart = {
|
|
6
|
+
[streamRetryAttemptBoundarySymbol]: true;
|
|
7
|
+
warnings: Array<SharedV4Warning>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function createStreamRetryAttemptBoundaryPart({
|
|
11
|
+
warnings,
|
|
12
|
+
}: {
|
|
13
|
+
warnings: Array<SharedV4Warning>;
|
|
14
|
+
}): StreamRetryAttemptBoundaryPart {
|
|
15
|
+
return {
|
|
16
|
+
[streamRetryAttemptBoundarySymbol]: true,
|
|
17
|
+
warnings,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isStreamRetryAttemptBoundaryPart(
|
|
22
|
+
part: unknown,
|
|
23
|
+
): part is StreamRetryAttemptBoundaryPart {
|
|
24
|
+
return (
|
|
25
|
+
typeof part === 'object' &&
|
|
26
|
+
part != null &&
|
|
27
|
+
streamRetryAttemptBoundarySymbol in part
|
|
28
|
+
);
|
|
29
|
+
}
|