ai 7.0.135 → 7.0.137
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 +14 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +26 -16
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +2 -2
- package/dist/internal/index.js +1 -1
- package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +1 -1
- package/docs/03-ai-sdk-core/17-mcp-events.mdx +6 -2
- package/docs/03-ai-sdk-core/25-settings.mdx +4 -2
- package/docs/03-ai-sdk-core/32-decisions.mdx +3 -2
- package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +2 -2
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +2 -2
- package/docs/07-reference/01-ai-sdk-core/16-tool-loop-agent.mdx +5 -5
- package/docs/07-reference/01-ai-sdk-core/23-create-mcp-client.mdx +2 -2
- package/docs/07-reference/01-ai-sdk-core/24-mcp-events.mdx +123 -5
- package/package.json +2 -2
- package/src/generate-text/stream-text.ts +31 -24
- package/src/prompt/request-options.ts +2 -2
- package/src/ui-message-stream/read-ui-message-stream.ts +1 -0
package/dist/internal/index.d.ts
CHANGED
|
@@ -606,9 +606,9 @@ type LanguageModelCallOptions = {
|
|
|
606
606
|
* Timeout configuration for API calls. Can be specified as:
|
|
607
607
|
* - A number representing milliseconds
|
|
608
608
|
* - An object with `totalMs` property for the total timeout in milliseconds
|
|
609
|
-
* - An object with `stepMs` property for the timeout of each step in milliseconds
|
|
609
|
+
* - An object with `stepMs` property for the timeout of each complete step, including model generation, retries, and local tool execution, in milliseconds
|
|
610
610
|
* - An object with `firstChunkMs` property for the timeout until the first content chunk of each step (streaming only)
|
|
611
|
-
* - An object with `chunkMs` property for the timeout between
|
|
611
|
+
* - An object with `chunkMs` property for the timeout between meaningful model output chunks, starting with the first output and ending when the model response ends (streaming only)
|
|
612
612
|
* - An object with `toolMs` property for the default timeout for all tool executions
|
|
613
613
|
* - An object with `tools` property for per-tool timeout overrides using `{toolName}Ms` keys
|
|
614
614
|
*/
|
package/dist/internal/index.js
CHANGED
|
@@ -400,7 +400,7 @@ You can also combine multiple conditions in an array or create custom conditions
|
|
|
400
400
|
results.
|
|
401
401
|
</Note>
|
|
402
402
|
|
|
403
|
-
By default, when you use `generateText` or `streamText`, it triggers a single generation. This works well for many use cases where you can rely on the model's training data to generate a response. However, when you provide tools, the model now has the choice to either generate a normal text response, or generate a tool call. If the model generates a tool call,
|
|
403
|
+
By default, when you use `generateText` or `streamText`, it triggers a single generation. This works well for many use cases where you can rely on the model's training data to generate a response. However, when you provide tools, the model now has the choice to either generate a normal text response, or generate a tool call. A step includes one model generation and the execution of any local tools requested by that generation. If the model generates a tool call, the model generation finishes first; the step finishes after its local tool execution completes.
|
|
404
404
|
|
|
405
405
|
You may want the model to generate text after the tool has been executed, either to summarize the tool results in the context of the users query. In many cases, you may also want the model to use multiple tools in a single response. This is where multi-step calls come in.
|
|
406
406
|
|
|
@@ -19,8 +19,12 @@ endpoint receives the events.
|
|
|
19
19
|
## Choose who manages subscriptions
|
|
20
20
|
|
|
21
21
|
Use `experimental_events: { adapter }` when a backend manages subscriptions,
|
|
22
|
-
webhook delivery and renewal.
|
|
23
|
-
|
|
22
|
+
webhook delivery and renewal. Supply an adapter whose
|
|
23
|
+
`createAdapter({ transport })` receives the MCP transport type and URL
|
|
24
|
+
(or just the type for custom transports) and returns bound
|
|
25
|
+
managed watch operations. No AI SDK event store is required. A backend SDK helper can
|
|
26
|
+
return this adapter directly, so callers do not need an inline `createAdapter`
|
|
27
|
+
wrapper. See [managed subscriptions](/docs/reference/ai-sdk-core/mcp-events#managed-subscriptions).
|
|
24
28
|
|
|
25
29
|
Use `experimental_events: { store }` when your application directly registers
|
|
26
30
|
MCP webhooks, persists their secrets and schedules renewal. The following flow
|
|
@@ -142,12 +142,14 @@ This is a convenience parameter that creates an abort signal internally. It can
|
|
|
142
142
|
You can specify the timeout either as a number (milliseconds) or as an object with the following properties:
|
|
143
143
|
|
|
144
144
|
- `totalMs`: The total timeout for the entire call including all steps.
|
|
145
|
-
- `stepMs`: The timeout for each
|
|
145
|
+
- `stepMs`: The timeout for each complete step, including model generation, retries, and local tool execution. The budget is cumulative across provider attempts within the step.
|
|
146
146
|
- `firstChunkMs`: The timeout until the first content-bearing output of each step (streaming only). Text deltas, reasoning deltas, tool-input deltas, generated files, and tool calls satisfy the timeout. Response metadata, stream starts, empty deltas, raw chunks, and transport activity do not satisfy or reset it.
|
|
147
|
-
- `chunkMs`: The timeout between
|
|
147
|
+
- `chunkMs`: The timeout between meaningful model output chunks after output has started (streaming only). It starts with the first meaningful output; it does not limit the wait for that first output. Non-content chunks do not reset it. This is useful for detecting streams that stall after generation begins.
|
|
148
148
|
- `toolMs`: The default timeout for all tool executions. If a tool takes longer, it aborts and returns a tool-error so the model can respond or retry.
|
|
149
149
|
- `tools`: Per-tool timeout overrides using `{toolName}Ms` keys (e.g. `weatherMs`, `slowApiMs`). Takes precedence over `toolMs`. Tool names are type-checked for autocomplete.
|
|
150
150
|
|
|
151
|
+
The `firstChunkMs` and `chunkMs` timers stop when the model response finishes, errors, closes, or is cancelled. Each provider retry or later model call gets fresh output timeout budgets. Retry backoff and local tool execution are outside these budgets. Provider-executed tools remain within the model response. The `stepMs` and `totalMs` budgets remain active across retries and local tool execution.
|
|
152
|
+
|
|
151
153
|
#### Example: 5 second timeout (number format)
|
|
152
154
|
|
|
153
155
|
```ts
|
|
@@ -82,8 +82,9 @@ from `ai`. A part has one of these shapes:
|
|
|
82
82
|
- JSON: `{ type: 'json', value: JSONValue }`.
|
|
83
83
|
|
|
84
84
|
Language-model decision adapters accept image files only. The underlying model
|
|
85
|
-
must support the file data form. Gateway
|
|
86
|
-
|
|
85
|
+
must support the file data form. Gateway forwards image files to the routed
|
|
86
|
+
decision model, which must support image input. TypeSafe AI accepts text and
|
|
87
|
+
JSON state only.
|
|
87
88
|
|
|
88
89
|
Arrays passed directly as `state` contain parts. To send a JSON array, put it
|
|
89
90
|
inside an object (`state: { records }`) or a JSON part
|
|
@@ -479,7 +479,7 @@ To see `generateText` in action, check out [these examples](#examples).
|
|
|
479
479
|
type: 'number | { totalMs?: number; stepMs?: number; toolMs?: number; tools?: Partial<Record<`${toolName}Ms`, number>> }',
|
|
480
480
|
isOptional: true,
|
|
481
481
|
description:
|
|
482
|
-
'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, toolMs, and/or tools properties. totalMs sets the total timeout for the entire call. stepMs sets the timeout for each
|
|
482
|
+
'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, toolMs, and/or tools properties. totalMs sets the total timeout for the entire call. stepMs sets the timeout for each complete step, including model generation, retries, and local tool execution. toolMs sets the default timeout for all tool executions. tools sets per-tool timeout overrides using the pattern {toolName}Ms (e.g. weatherMs, slowApiMs) that take precedence over toolMs - tool names are type-checked for autocomplete. If a tool takes longer than its timeout, it aborts and returns a tool-error so the model can respond or retry. Can be used alongside abortSignal.',
|
|
483
483
|
},
|
|
484
484
|
{
|
|
485
485
|
name: 'headers',
|
|
@@ -1251,7 +1251,7 @@ To see `generateText` in action, check out [these examples](#examples).
|
|
|
1251
1251
|
type: '(event: GenerateTextStepStartEvent) => PromiseLike<void> | void',
|
|
1252
1252
|
isOptional: true,
|
|
1253
1253
|
description:
|
|
1254
|
-
'Callback that is called when a step
|
|
1254
|
+
'Callback that is called when a step begins, before the provider is called. Errors thrown in this callback are silently caught and do not break the generation flow.',
|
|
1255
1255
|
properties: [
|
|
1256
1256
|
{
|
|
1257
1257
|
type: 'GenerateTextStepStartEvent',
|
|
@@ -487,7 +487,7 @@ To see `streamText` in action, check out [these examples](#examples).
|
|
|
487
487
|
type: 'number | { totalMs?: number; stepMs?: number; firstChunkMs?: number; chunkMs?: number; toolMs?: number; tools?: Partial<Record<`${toolName}Ms`, number>> }',
|
|
488
488
|
isOptional: true,
|
|
489
489
|
description:
|
|
490
|
-
'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, firstChunkMs, chunkMs, toolMs, and/or tools properties. totalMs sets the total timeout for the entire call. stepMs sets the timeout for each
|
|
490
|
+
'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, firstChunkMs, chunkMs, toolMs, and/or tools properties. totalMs sets the total timeout for the entire call. stepMs sets the timeout for each complete step, including model generation, retries, and local tool execution. firstChunkMs sets the timeout until the first content-bearing output in each step; metadata, stream starts, empty deltas, raw chunks, and transport activity do not satisfy it. chunkMs starts with the first meaningful model output and limits gaps between subsequent meaningful model output chunks. Both output timers stop when the model response finishes and start fresh for each retry or later model call. Local tool results, including preliminary results, do not reset them; local tool execution is outside their scope. Provider-executed tools remain within the model response. toolMs sets the default timeout for all tool executions. tools sets per-tool timeout overrides using the pattern {toolName}Ms (e.g. weatherMs, slowApiMs) that take precedence over toolMs - tool names are type-checked for autocomplete. If a tool takes longer than its timeout, it aborts and returns a tool-error so the model can respond or retry. Can be used alongside abortSignal.',
|
|
491
491
|
},
|
|
492
492
|
{
|
|
493
493
|
name: 'headers',
|
|
@@ -2265,7 +2265,7 @@ To see `streamText` in action, check out [these examples](#examples).
|
|
|
2265
2265
|
type: '(event: GenerateTextStepStartEvent) => PromiseLike<void> | void',
|
|
2266
2266
|
isOptional: true,
|
|
2267
2267
|
description:
|
|
2268
|
-
'Callback that is called when a step
|
|
2268
|
+
'Callback that is called when a step begins, before the provider is called. Errors thrown in this callback are silently caught and do not break the generation flow.',
|
|
2269
2269
|
properties: [
|
|
2270
2270
|
{
|
|
2271
2271
|
type: 'GenerateTextStepStartEvent',
|
|
@@ -306,7 +306,7 @@ To see `ToolLoopAgent` in action, check out [these examples](#examples).
|
|
|
306
306
|
type: 'GenerateTextOnStepStartCallback',
|
|
307
307
|
isOptional: true,
|
|
308
308
|
description:
|
|
309
|
-
'Callback that is called when a step
|
|
309
|
+
'Callback that is called when a step begins, before the provider is called. Each step includes a model generation and any associated local tool execution; provider retries remain within the same step. If also specified in `generate()` or `stream()`, both callbacks are called (constructor first).',
|
|
310
310
|
properties: [
|
|
311
311
|
{
|
|
312
312
|
type: 'GenerateTextStepStartEvent',
|
|
@@ -726,7 +726,7 @@ const result = await agent.generate({
|
|
|
726
726
|
type: 'number | { totalMs?: number; stepMs?: number; firstChunkMs?: number; chunkMs?: number }',
|
|
727
727
|
isOptional: true,
|
|
728
728
|
description:
|
|
729
|
-
'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, firstChunkMs, and/or chunkMs properties. firstChunkMs and chunkMs have no effect on generate(); they are streaming-only and are enforced by stream(). Can be used alongside abortSignal.',
|
|
729
|
+
'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, firstChunkMs, and/or chunkMs properties. stepMs limits each complete step, including model generation, retries, and local tool execution. firstChunkMs and chunkMs have no effect on generate(); they are streaming-only and are enforced by stream(). Can be used alongside abortSignal.',
|
|
730
730
|
},
|
|
731
731
|
{
|
|
732
732
|
name: 'experimental_sandbox',
|
|
@@ -754,7 +754,7 @@ const result = await agent.generate({
|
|
|
754
754
|
type: 'GenerateTextOnStepStartCallback',
|
|
755
755
|
isOptional: true,
|
|
756
756
|
description:
|
|
757
|
-
'Callback that is called when a step
|
|
757
|
+
'Callback that is called when a step begins, before the provider is called. If also specified in the constructor, both callbacks are called (constructor first).',
|
|
758
758
|
},
|
|
759
759
|
{
|
|
760
760
|
name: 'onToolExecutionStart',
|
|
@@ -842,7 +842,7 @@ for await (const chunk of stream.textStream) {
|
|
|
842
842
|
type: 'number | { totalMs?: number; stepMs?: number; firstChunkMs?: number; chunkMs?: number }',
|
|
843
843
|
isOptional: true,
|
|
844
844
|
description:
|
|
845
|
-
'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, firstChunkMs, and/or chunkMs properties. firstChunkMs limits the wait for the first content-bearing output in each model-call step. chunkMs limits gaps between
|
|
845
|
+
'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, firstChunkMs, and/or chunkMs properties. stepMs limits each complete step, including model generation, retries, and local tool execution. firstChunkMs limits the wait for the first content-bearing output in each model-call step. chunkMs starts with the first meaningful model output and limits gaps between subsequent meaningful model output chunks. Both output timers stop when the model response finishes and start fresh for each retry or later model call; they exclude retry backoff and local tool execution. Tool results, including preliminary results, do not reset them. Provider-executed tools remain within the model response. Can be used alongside abortSignal.',
|
|
846
846
|
},
|
|
847
847
|
{
|
|
848
848
|
name: 'experimental_sandbox',
|
|
@@ -877,7 +877,7 @@ for await (const chunk of stream.textStream) {
|
|
|
877
877
|
type: 'GenerateTextOnStepStartCallback',
|
|
878
878
|
isOptional: true,
|
|
879
879
|
description:
|
|
880
|
-
'Callback that is called when a step
|
|
880
|
+
'Callback that is called when a step begins, before the provider is called. If also specified in the constructor, both callbacks are called (constructor first).',
|
|
881
881
|
},
|
|
882
882
|
{
|
|
883
883
|
name: 'onToolExecutionStart',
|
|
@@ -59,10 +59,10 @@ experimental webhook delivery, see the [MCP Events guide](/docs/ai-sdk-core/mcp-
|
|
|
59
59
|
},
|
|
60
60
|
{
|
|
61
61
|
name: 'adapter',
|
|
62
|
-
type: '
|
|
62
|
+
type: 'Experimental_MCPEventAdapter',
|
|
63
63
|
isOptional: true,
|
|
64
64
|
description:
|
|
65
|
-
|
|
65
|
+
"Required in managed mode. Creates bound subscription operations once before transport startup, receiving transport metadata: { type, url } for HTTP/SSE or { type: 'custom' } for custom transports. Cannot be combined with store or validateArguments. No local event store or refresh loop is required.",
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
name: 'validateArguments',
|
|
@@ -99,9 +99,11 @@ for the definition fields. Pagination is explicit; this method does not fetch al
|
|
|
99
99
|
## Managed Subscriptions
|
|
100
100
|
|
|
101
101
|
Configure `experimental_events: { adapter }` to delegate subscription lifecycle
|
|
102
|
-
operations to a backend. The adapter
|
|
103
|
-
from `@ai-sdk/mcp
|
|
104
|
-
|
|
102
|
+
operations to a backend. The `adapter` configuration requires an
|
|
103
|
+
`Experimental_MCPEventAdapter` from `@ai-sdk/mcp`. Its
|
|
104
|
+
`createAdapter({ transport })` method returns `Experimental_MCPEventOperations` bound
|
|
105
|
+
to the authorized account, endpoint and destination by your application or
|
|
106
|
+
integration package.
|
|
105
107
|
|
|
106
108
|
```ts
|
|
107
109
|
import { createMCPClient } from '@ai-sdk/mcp';
|
|
@@ -143,7 +145,123 @@ try {
|
|
|
143
145
|
Use the same authorized account for discovery and subscription management.
|
|
144
146
|
Never derive account identity, destination or authorization from model arguments.
|
|
145
147
|
|
|
146
|
-
### Adapter
|
|
148
|
+
### Using an Adapter Helper
|
|
149
|
+
|
|
150
|
+
A backend SDK or application helper can return `Experimental_MCPEventAdapter`
|
|
151
|
+
directly. Pass the helper's result as `adapter`; you do not need another object
|
|
152
|
+
wrapper or an inline `createAdapter` callback:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import { createMCPClient } from '@ai-sdk/mcp';
|
|
156
|
+
import { createBackendEventsAdapter } from './my-events-adapter';
|
|
157
|
+
|
|
158
|
+
const client = await createMCPClient({
|
|
159
|
+
transport: { type: 'http', url: 'https://service.example/mcp' },
|
|
160
|
+
experimental_events: {
|
|
161
|
+
adapter: createBackendEventsAdapter({
|
|
162
|
+
accountId: authenticatedUser.id,
|
|
163
|
+
destination: { path: '/hooks' },
|
|
164
|
+
}),
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The helper holds the authorized account and delivery configuration. AI SDK supplies
|
|
170
|
+
the transport type and URL to its `createAdapter` method internally, so the application
|
|
171
|
+
configures that URL only once. When a backend SDK exports this helper, import it
|
|
172
|
+
from that SDK instead of an application module. Use the same authorized account
|
|
173
|
+
for the MCP transport and the backend's subscription operations.
|
|
174
|
+
|
|
175
|
+
### Implementing an Adapter Helper
|
|
176
|
+
|
|
177
|
+
Backend integration authors implement `createAdapter` inside their helper:
|
|
178
|
+
|
|
179
|
+
```ts filename="my-events-adapter.ts"
|
|
180
|
+
import type { Experimental_MCPEventAdapter } from '@ai-sdk/mcp';
|
|
181
|
+
import { createBackendEventOperations } from './my-events-backend';
|
|
182
|
+
|
|
183
|
+
type BackendEventsConfig = {
|
|
184
|
+
accountId: string;
|
|
185
|
+
destination: { path: string };
|
|
186
|
+
mcpUrl?: string;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export function createBackendEventsAdapter(
|
|
190
|
+
config: BackendEventsConfig,
|
|
191
|
+
): Experimental_MCPEventAdapter {
|
|
192
|
+
return {
|
|
193
|
+
createAdapter({ transport }) {
|
|
194
|
+
return createBackendEventOperations({
|
|
195
|
+
...config,
|
|
196
|
+
mcpUrl:
|
|
197
|
+
config.mcpUrl ??
|
|
198
|
+
(transport.type === 'custom' ? undefined : transport.url),
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
These helpers and `BackendEventsConfig` are illustrative application or backend
|
|
206
|
+
SDK code, not AI SDK exports. `createBackendEventOperations` returns
|
|
207
|
+
`Experimental_MCPEventOperations` bound to the authorized account, endpoint
|
|
208
|
+
and destination. The helper above lets an explicit `mcpUrl` override the transport
|
|
209
|
+
URL for backend operations; it does not change the MCP client's transport or
|
|
210
|
+
catalog discovery. The backend still authorizes the selected endpoint.
|
|
211
|
+
|
|
212
|
+
The AI SDK adapter contract is:
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
interface MCPEventAdapter {
|
|
216
|
+
createAdapter(context: {
|
|
217
|
+
transport: { type: 'http' | 'sse'; url: string } | { type: 'custom' };
|
|
218
|
+
}): MCPEventOperations;
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The interface is exported as `Experimental_MCPEventAdapter`. The client
|
|
223
|
+
calls `createAdapter` once, before starting the transport, and uses the returned
|
|
224
|
+
operations for managed subscriptions. The return value must be an object with
|
|
225
|
+
callable `subscribe`, `getSubscription`, `listSubscriptions`, and `unsubscribe`
|
|
226
|
+
methods. Nullish values, missing or non-callable methods, and Promise/thenable
|
|
227
|
+
results reject `createMCPClient` with `MCPClientError` before the transport starts.
|
|
228
|
+
Errors thrown by `createAdapter` also reject initialization without starting the
|
|
229
|
+
transport. Bound operations are no longer accepted directly in
|
|
230
|
+
`experimental_events.adapter`. To migrate existing subscription operations, wrap them explicitly:
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
experimental_events: {
|
|
234
|
+
adapter: {
|
|
235
|
+
createAdapter: () => existingOperations,
|
|
236
|
+
},
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Only reuse bound operations when their account, endpoint and destination are correct
|
|
241
|
+
for every client using them. The former subscription operations interface is now
|
|
242
|
+
exported as `Experimental_MCPEventOperations`; `Experimental_MCPEventAdapter`
|
|
243
|
+
names the configured integration with `createAdapter`.
|
|
244
|
+
|
|
245
|
+
For HTTP and SSE transport configurations, the context contains a fresh
|
|
246
|
+
`transport: { type, url }` object. `url` is the configured string, including its
|
|
247
|
+
path and query, not a resolved redirect target. Custom `MCPTransport` instances
|
|
248
|
+
receive `transport: { type: 'custom' }`, with no `url` property; arbitrary
|
|
249
|
+
properties on the instance are not inspected.
|
|
250
|
+
|
|
251
|
+
This is a description of the transport, not the full configuration or live
|
|
252
|
+
instance. Headers, auth providers, fetch functions, session callbacks and
|
|
253
|
+
`start`/`send`/`close` methods are not passed to the adapter. The `transport`
|
|
254
|
+
grouping leaves room for other client context without mixing it with transport
|
|
255
|
+
metadata. No negotiated protocol version is supplied before initialization.
|
|
256
|
+
|
|
257
|
+
Return separately bound operations for each client instead of mutating shared
|
|
258
|
+
endpoint state. Adapters may prefer their own explicit endpoint override or
|
|
259
|
+
resolve a configured endpoint when `transport.type` is `'custom'`. That policy belongs to
|
|
260
|
+
the adapter; it does not change the client's transport or catalog discovery.
|
|
261
|
+
The managed backend must still authorize an endpoint before sending credentials
|
|
262
|
+
there. Receiving the transport URL does not grant that authorization.
|
|
263
|
+
|
|
264
|
+
### Managed Operations Contract
|
|
147
265
|
|
|
148
266
|
```ts
|
|
149
267
|
import type { JSONObject } from '@ai-sdk/provider';
|
|
@@ -184,7 +302,7 @@ These types are exported as `Experimental_ManagedSubscription` and
|
|
|
184
302
|
a positive `ttlMs`, an ISO deadline in `expiresAt`, or `expiresAt: null` to
|
|
185
303
|
monitor until stopped. The backend validates these values and enforces its limits.
|
|
186
304
|
|
|
187
|
-
`
|
|
305
|
+
`Experimental_MCPEventOperations` has four operations:
|
|
188
306
|
|
|
189
307
|
| Operation | Input | Result |
|
|
190
308
|
| ------------------- | ------------------------------------------------- | ---------------------------------- |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.137",
|
|
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,7 +42,7 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@ai-sdk/gateway": "4.0.
|
|
45
|
+
"@ai-sdk/gateway": "4.0.110",
|
|
46
46
|
"@ai-sdk/provider": "4.0.26",
|
|
47
47
|
"@ai-sdk/provider-utils": "5.0.58"
|
|
48
48
|
},
|
|
@@ -2275,6 +2275,9 @@ class DefaultStreamTextResult<
|
|
|
2275
2275
|
if (chunkTimeoutId != null) {
|
|
2276
2276
|
clearTimeout(chunkTimeoutId);
|
|
2277
2277
|
}
|
|
2278
|
+
if (abortSignal?.aborted) {
|
|
2279
|
+
return;
|
|
2280
|
+
}
|
|
2278
2281
|
chunkTimeoutId = setAbortTimeout({
|
|
2279
2282
|
abortController: chunkAbortController,
|
|
2280
2283
|
label: 'Chunk',
|
|
@@ -2289,6 +2292,11 @@ class DefaultStreamTextResult<
|
|
|
2289
2292
|
}
|
|
2290
2293
|
}
|
|
2291
2294
|
|
|
2295
|
+
function clearModelOutputTimeouts() {
|
|
2296
|
+
clearFirstChunkTimeout();
|
|
2297
|
+
clearChunkTimeout();
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2292
2300
|
function clearStepTimeout() {
|
|
2293
2301
|
if (stepTimeoutId != null) {
|
|
2294
2302
|
clearTimeout(stepTimeoutId);
|
|
@@ -2297,8 +2305,7 @@ class DefaultStreamTextResult<
|
|
|
2297
2305
|
|
|
2298
2306
|
function clearStepTimeouts() {
|
|
2299
2307
|
clearStepTimeout();
|
|
2300
|
-
|
|
2301
|
-
clearChunkTimeout();
|
|
2308
|
+
clearModelOutputTimeouts();
|
|
2302
2309
|
}
|
|
2303
2310
|
|
|
2304
2311
|
function cleanupStepTimeouts() {
|
|
@@ -2509,7 +2516,6 @@ class DefaultStreamTextResult<
|
|
|
2509
2516
|
let automaticStreamRetryCount = 0;
|
|
2510
2517
|
let callbackStreamRetryCount = 0;
|
|
2511
2518
|
let bufferedAttemptParts: LanguageModelStreamPart<TOOLS>[] = [];
|
|
2512
|
-
const outputChunksHandledBeforeBuffering = new WeakSet<object>();
|
|
2513
2519
|
const openTextParts = new Set<string>();
|
|
2514
2520
|
const openReasoningParts = new Set<string>();
|
|
2515
2521
|
let enqueueStreamRetryAttemptBoundary = false;
|
|
@@ -2561,7 +2567,16 @@ class DefaultStreamTextResult<
|
|
|
2561
2567
|
};
|
|
2562
2568
|
|
|
2563
2569
|
while (true) {
|
|
2564
|
-
|
|
2570
|
+
let result: ReadableStreamReadResult<
|
|
2571
|
+
LanguageModelStreamPart<TOOLS>
|
|
2572
|
+
>;
|
|
2573
|
+
try {
|
|
2574
|
+
result = await languageModelStreamReader.read();
|
|
2575
|
+
} catch (error) {
|
|
2576
|
+
clearModelOutputTimeouts();
|
|
2577
|
+
throw error;
|
|
2578
|
+
}
|
|
2579
|
+
const { done, value } = result;
|
|
2565
2580
|
|
|
2566
2581
|
if (enqueueStreamRetryAttemptBoundary) {
|
|
2567
2582
|
controller.enqueue(
|
|
@@ -2576,6 +2591,7 @@ class DefaultStreamTextResult<
|
|
|
2576
2591
|
}
|
|
2577
2592
|
|
|
2578
2593
|
if (done) {
|
|
2594
|
+
clearModelOutputTimeouts();
|
|
2579
2595
|
flushBufferedAttemptParts();
|
|
2580
2596
|
controller.close();
|
|
2581
2597
|
return;
|
|
@@ -2592,22 +2608,24 @@ class DefaultStreamTextResult<
|
|
|
2592
2608
|
value.type === 'tool-error';
|
|
2593
2609
|
|
|
2594
2610
|
if (value.type === 'model-call-end') {
|
|
2611
|
+
clearModelOutputTimeouts();
|
|
2595
2612
|
flushBufferedAttemptParts();
|
|
2596
2613
|
enqueueAttemptPart(value);
|
|
2597
2614
|
return;
|
|
2598
2615
|
}
|
|
2599
2616
|
|
|
2617
|
+
// Observe model output before buffering and tool processing.
|
|
2618
|
+
// Replaying buffered parts must not re-arm finished timers.
|
|
2619
|
+
if (isOutputChunk(value)) {
|
|
2620
|
+
clearFirstChunkTimeout();
|
|
2621
|
+
resetChunkTimeout();
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2600
2624
|
if (
|
|
2601
2625
|
shouldBufferToolParts &&
|
|
2602
2626
|
value.type !== 'error' &&
|
|
2603
2627
|
(isToolPart || bufferedAttemptParts.length > 0)
|
|
2604
2628
|
) {
|
|
2605
|
-
if (isOutputChunk(value)) {
|
|
2606
|
-
clearFirstChunkTimeout();
|
|
2607
|
-
resetChunkTimeout();
|
|
2608
|
-
outputChunksHandledBeforeBuffering.add(value);
|
|
2609
|
-
}
|
|
2610
|
-
|
|
2611
2629
|
bufferedAttemptParts.push(value);
|
|
2612
2630
|
continue;
|
|
2613
2631
|
}
|
|
@@ -2617,6 +2635,7 @@ class DefaultStreamTextResult<
|
|
|
2617
2635
|
return;
|
|
2618
2636
|
}
|
|
2619
2637
|
|
|
2638
|
+
clearModelOutputTimeouts();
|
|
2620
2639
|
await notify({
|
|
2621
2640
|
event: { chunk: value },
|
|
2622
2641
|
callbacks: onChunk,
|
|
@@ -2677,10 +2696,12 @@ class DefaultStreamTextResult<
|
|
|
2677
2696
|
response = retryLanguageModelCall.response;
|
|
2678
2697
|
languageModelStreamReader =
|
|
2679
2698
|
retryLanguageModelCall.stream.getReader();
|
|
2699
|
+
startFirstChunkTimeout();
|
|
2680
2700
|
enqueueStreamRetryAttemptBoundary = true;
|
|
2681
2701
|
}
|
|
2682
2702
|
},
|
|
2683
2703
|
cancel(reason) {
|
|
2704
|
+
clearModelOutputTimeouts();
|
|
2684
2705
|
return languageModelStreamReader.cancel(reason);
|
|
2685
2706
|
},
|
|
2686
2707
|
});
|
|
@@ -2857,21 +2878,7 @@ class DefaultStreamTextResult<
|
|
|
2857
2878
|
const chunkType = chunk.type;
|
|
2858
2879
|
|
|
2859
2880
|
if (isOutputChunk(chunk)) {
|
|
2860
|
-
const timeoutHandledBeforeBuffering =
|
|
2861
|
-
outputChunksHandledBeforeBuffering.has(chunk);
|
|
2862
|
-
|
|
2863
|
-
if (
|
|
2864
|
-
!hasReceivedOutputChunk &&
|
|
2865
|
-
!timeoutHandledBeforeBuffering
|
|
2866
|
-
) {
|
|
2867
|
-
// Clear before forwarding the first output so a timeout
|
|
2868
|
-
// cannot race with already-visible generated content.
|
|
2869
|
-
clearFirstChunkTimeout();
|
|
2870
|
-
}
|
|
2871
2881
|
hasReceivedOutputChunk = true;
|
|
2872
|
-
if (!timeoutHandledBeforeBuffering) {
|
|
2873
|
-
resetChunkTimeout();
|
|
2874
|
-
}
|
|
2875
2882
|
}
|
|
2876
2883
|
|
|
2877
2884
|
switch (chunkType) {
|
|
@@ -4,9 +4,9 @@ import type { ToolSet } from '@ai-sdk/provider-utils';
|
|
|
4
4
|
* Timeout configuration for API calls. Can be specified as:
|
|
5
5
|
* - A number representing milliseconds
|
|
6
6
|
* - An object with `totalMs` property for the total timeout in milliseconds
|
|
7
|
-
* - An object with `stepMs` property for the timeout of each step in milliseconds
|
|
7
|
+
* - An object with `stepMs` property for the timeout of each complete step, including model generation, retries, and local tool execution, in milliseconds
|
|
8
8
|
* - An object with `firstChunkMs` property for the timeout until the first content chunk of each step (streaming only)
|
|
9
|
-
* - An object with `chunkMs` property for the timeout between
|
|
9
|
+
* - An object with `chunkMs` property for the timeout between meaningful model output chunks, starting with the first output and ending when the model response ends (streaming only)
|
|
10
10
|
* - An object with `toolMs` property for the default timeout for all tool executions
|
|
11
11
|
* - An object with `tools` property for per-tool timeout overrides using `{toolName}Ms` keys
|
|
12
12
|
*/
|
|
@@ -95,6 +95,7 @@ export function readUIMessageStream<UI_MESSAGE extends UIMessage>({
|
|
|
95
95
|
consumeStream({
|
|
96
96
|
stream: processUIMessageStream({
|
|
97
97
|
stream,
|
|
98
|
+
resetStateOnMessageIdChange: true,
|
|
98
99
|
runUpdateMessageJob(
|
|
99
100
|
job: (options: {
|
|
100
101
|
state: StreamingUIMessageState<UI_MESSAGE>;
|