ai 7.0.120 → 7.0.123
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 +38 -0
- package/dist/index.d.ts +7423 -7247
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19263 -22470
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +2044 -2004
- package/dist/internal/index.d.ts.map +1 -0
- package/dist/internal/index.js +3255 -3921
- package/dist/internal/index.js.map +1 -1
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/test/index.d.ts +294 -273
- package/dist/test/index.d.ts.map +1 -0
- package/dist/test/index.js +325 -469
- package/dist/test/index.js.map +1 -1
- package/docs/02-foundations/03-prompts.mdx +3 -1
- package/docs/02-foundations/06-provider-options.mdx +1 -1
- package/docs/02-getting-started/06-nodejs.mdx +4 -4
- package/docs/02-getting-started/08-tanstack-start.mdx +1 -1
- package/docs/03-agents/05-configuring-call-options.mdx +1 -1
- package/docs/03-ai-sdk-core/10-generating-structured-data.mdx +1 -1
- package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +3 -0
- package/docs/03-ai-sdk-core/17-mcp-apps.mdx +5 -5
- package/docs/03-ai-sdk-core/37-speech.mdx +1 -1
- package/docs/03-ai-sdk-core/42-batch.mdx +1 -1
- package/docs/03-ai-sdk-core/60-telemetry.mdx +2 -2
- package/docs/03-ai-sdk-harnesses/02-harness-agent.mdx +24 -0
- package/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx +12 -12
- package/docs/04-ai-sdk-ui/02-chatbot.mdx +9 -0
- package/docs/04-ai-sdk-ui/03-chatbot-message-persistence.mdx +17 -7
- package/docs/04-ai-sdk-ui/03-chatbot-resume-streams.mdx +12 -5
- package/docs/04-ai-sdk-ui/03-chatbot-tool-usage.mdx +17 -10
- package/docs/04-ai-sdk-ui/05-completion.mdx +1 -1
- package/docs/04-ai-sdk-ui/50-stream-protocol.mdx +2 -2
- package/docs/05-ai-sdk-rsc/03-generative-ui-state.mdx +8 -7
- package/docs/05-ai-sdk-rsc/04-multistep-interfaces.mdx +1 -1
- package/docs/05-ai-sdk-rsc/06-loading-state.mdx +19 -10
- package/docs/05-ai-sdk-rsc/08-error-handling.mdx +2 -0
- package/docs/05-ai-sdk-rsc/10-migrating-to-ui.mdx +4 -3
- package/docs/06-advanced/02-stopping-streams.mdx +2 -2
- package/docs/06-advanced/04-caching.mdx +9 -5
- package/docs/06-advanced/05-multiple-streamables.mdx +1 -1
- package/docs/06-advanced/07-rendering-ui-with-language-models.mdx +16 -16
- package/docs/06-advanced/09-multistep-interfaces.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +4 -4
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +5 -5
- package/docs/07-reference/01-ai-sdk-core/14-upload-file.mdx +4 -4
- package/docs/07-reference/01-ai-sdk-core/14-upload-skill.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/15-agent.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/18-create-agent-ui-stream-response.mdx +1 -4
- package/docs/07-reference/01-ai-sdk-core/22-dynamic-tool.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/23-create-mcp-client.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/30-model-message.mdx +2 -2
- package/docs/07-reference/01-ai-sdk-core/69-add-tool-input-examples-middleware.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/80-smooth-stream.mdx +1 -1
- package/docs/07-reference/02-ai-sdk-ui/31-convert-to-model-messages.mdx +5 -4
- package/docs/07-reference/02-ai-sdk-ui/40-create-ui-message-stream.mdx +3 -2
- package/docs/07-reference/02-ai-sdk-ui/41-create-ui-message-stream-response.mdx +7 -0
- package/docs/07-reference/02-ai-sdk-ui/42-pipe-ui-message-stream-to-response.mdx +7 -0
- package/docs/07-reference/02-ai-sdk-ui/50-direct-chat-transport.mdx +2 -2
- package/docs/07-reference/03-ai-sdk-rsc/01-stream-ui.mdx +2 -2
- package/docs/07-reference/04-ai-sdk-workflow/01-workflow-agent.mdx +1 -1
- package/docs/08-migration-guides/25-migration-guide-5-0-data.mdx +4 -5
- package/docs/08-migration-guides/26-migration-guide-5-0.mdx +2 -1
- package/docs/08-migration-guides/29-migration-guide-4-0.mdx +9 -9
- package/docs/08-migration-guides/37-migration-guide-3-3.mdx +1 -1
- package/docs/08-migration-guides/38-migration-guide-3-2.mdx +1 -1
- package/docs/08-migration-guides/39-migration-guide-3-1.mdx +1 -1
- package/docs/09-troubleshooting/12-use-chat-an-error-occurred.mdx +8 -6
- package/docs/09-troubleshooting/50-react-maximum-update-depth-exceeded.mdx +6 -6
- package/docs/09-troubleshooting/70-high-memory-usage-with-images.mdx +1 -1
- package/package.json +17 -17
- package/src/agent/create-agent-ui-stream-response.ts +3 -0
- package/src/agent/pipe-agent-ui-stream-to-response.ts +3 -0
- package/src/embed/embed-many.ts +5 -3
- package/src/generate-image/generate-image.ts +8 -3
- package/src/generate-text/prune-messages.ts +1 -1
- package/src/generate-text/smooth-stream.ts +24 -9
- package/src/generate-text/stream-text-result.ts +5 -0
- package/src/generate-video/generate-video.ts +6 -4
- package/src/middleware/extract-reasoning-middleware.ts +27 -11
- package/src/registry/provider-registry.ts +1 -1
- package/src/ui/chat.ts +13 -4
- package/src/ui/convert-to-model-messages.ts +18 -6
- package/src/ui/http-chat-transport.ts +19 -3
- package/src/ui/last-assistant-message-is-complete-with-tool-calls.ts +15 -3
- package/src/ui/process-ui-message-stream.ts +51 -14
- package/src/ui/ui-messages.ts +14 -0
- package/src/ui/validate-ui-messages.ts +2 -0
- package/src/ui-message-stream/create-sse-stream-with-keep-alive.ts +89 -0
- package/src/ui-message-stream/create-ui-message-stream-response.ts +7 -1
- package/src/ui-message-stream/pipe-ui-message-stream-to-response.ts +7 -1
- package/src/ui-message-stream/to-ui-message-chunk.ts +9 -1
- package/src/ui-message-stream/to-ui-message-stream.ts +1 -1
- package/src/ui-message-stream/ui-message-stream-response-init.ts +7 -0
- package/src/util/set-own.ts +16 -0
|
@@ -208,7 +208,7 @@ To see `streamUI` in action, check out [these examples](#examples).
|
|
|
208
208
|
{
|
|
209
209
|
name: 'role',
|
|
210
210
|
type: "'tool'",
|
|
211
|
-
description: 'The role for the
|
|
211
|
+
description: 'The role for the tool message.',
|
|
212
212
|
},
|
|
213
213
|
{
|
|
214
214
|
name: 'content',
|
|
@@ -364,7 +364,7 @@ To see `streamUI` in action, check out [these examples](#examples).
|
|
|
364
364
|
{
|
|
365
365
|
name: 'generate',
|
|
366
366
|
isOptional: true,
|
|
367
|
-
type: '(
|
|
367
|
+
type: '(parameters) => ReactNode | Promise<ReactNode> | Generator<ReactNode, ReactNode, void> | AsyncGenerator<ReactNode, ReactNode, void>',
|
|
368
368
|
description:
|
|
369
369
|
'A function or a generator function that is called with the arguments from the tool call and yields React nodes as the UI.',
|
|
370
370
|
},
|
|
@@ -127,6 +127,7 @@ type V4FilePart = Extract<V4Part, { type: 'file' }>;
|
|
|
127
127
|
// Type guards
|
|
128
128
|
function isV4Message(msg: V4Message | MyUIMessage): msg is V4Message {
|
|
129
129
|
return (
|
|
130
|
+
msg?.parts == null ||
|
|
130
131
|
'toolInvocations' in msg ||
|
|
131
132
|
(msg?.parts?.some(p => p.type === 'tool-invocation') ?? false) ||
|
|
132
133
|
msg?.role === 'data' ||
|
|
@@ -465,9 +466,8 @@ export async function POST(req: Request) {
|
|
|
465
466
|
message: convertV5MessageToV4(message), // convert to v4
|
|
466
467
|
});
|
|
467
468
|
|
|
468
|
-
// Load
|
|
469
|
-
const
|
|
470
|
-
const messages = [...previousMessages, message];
|
|
469
|
+
// Load all messages, including the one just saved (already in v5 format)
|
|
470
|
+
const messages = await loadChat(chatId);
|
|
471
471
|
|
|
472
472
|
const result = streamText({
|
|
473
473
|
model: __MODEL__,
|
|
@@ -827,8 +827,7 @@ export async function POST(req: Request) {
|
|
|
827
827
|
message,
|
|
828
828
|
});
|
|
829
829
|
|
|
830
|
-
const
|
|
831
|
-
const messages = [...previousMessages, message];
|
|
830
|
+
const messages = await loadChat(chatId);
|
|
832
831
|
|
|
833
832
|
const result = streamText({
|
|
834
833
|
model: __MODEL__,
|
|
@@ -723,7 +723,8 @@ const runtimeTool = dynamicTool({
|
|
|
723
723
|
inputSchema: z.object({}),
|
|
724
724
|
execute: async input => {
|
|
725
725
|
// Input and output are typed as 'unknown'
|
|
726
|
-
|
|
726
|
+
const { query } = input as { query: string };
|
|
727
|
+
return { result: `Processed: ${query}` };
|
|
727
728
|
},
|
|
728
729
|
});
|
|
729
730
|
```
|
|
@@ -27,8 +27,8 @@ description: Learn how to upgrade AI SDK 3.4 to 4.0.
|
|
|
27
27
|
You need to update the following packages to the following versions in your `package.json` file(s):
|
|
28
28
|
|
|
29
29
|
- `ai` package: `4.0.*`
|
|
30
|
-
-
|
|
31
|
-
-
|
|
30
|
+
- `@ai-sdk/provider-utils` package: `2.0.*`
|
|
31
|
+
- `@ai-sdk/*` packages: `1.0.*` (other `@ai-sdk/*` packages)
|
|
32
32
|
|
|
33
33
|
## Codemods
|
|
34
34
|
|
|
@@ -440,7 +440,7 @@ const result = streamText({
|
|
|
440
440
|
|
|
441
441
|
result.toDataStream();
|
|
442
442
|
result.pipeDataStreamToResponse(response);
|
|
443
|
-
result.
|
|
443
|
+
result.toDataStreamResponse();
|
|
444
444
|
```
|
|
445
445
|
|
|
446
446
|
### Renamed "formatStreamPart" to "formatDataStreamPart"
|
|
@@ -518,7 +518,7 @@ import { Provider } from 'ai';
|
|
|
518
518
|
providers](/docs/reference/ai-sdk-core/provider-registry#setup) instead.
|
|
519
519
|
</Note>
|
|
520
520
|
|
|
521
|
-
#### Removed `
|
|
521
|
+
#### Removed `experimental_createModelRegistry` function
|
|
522
522
|
|
|
523
523
|
The `experimental_createModelRegistry` function has been removed.
|
|
524
524
|
Please use the `experimental_createProviderRegistry` function instead.
|
|
@@ -573,7 +573,7 @@ const result = await streamText({
|
|
|
573
573
|
// ...
|
|
574
574
|
});
|
|
575
575
|
|
|
576
|
-
result.
|
|
576
|
+
result.pipeDataStreamToResponse(response, {
|
|
577
577
|
init: {
|
|
578
578
|
headers: {
|
|
579
579
|
'X-Custom-Header': 'value',
|
|
@@ -588,7 +588,7 @@ const result = streamText({
|
|
|
588
588
|
// ...
|
|
589
589
|
});
|
|
590
590
|
|
|
591
|
-
result.
|
|
591
|
+
result.pipeDataStreamToResponse(response, {
|
|
592
592
|
headers: {
|
|
593
593
|
'X-Custom-Header': 'value',
|
|
594
594
|
},
|
|
@@ -621,7 +621,7 @@ const { text, response } = await generateText({
|
|
|
621
621
|
const responseMessages = response.messages;
|
|
622
622
|
```
|
|
623
623
|
|
|
624
|
-
### Removed `
|
|
624
|
+
### Removed `experimental_continuationSteps` option
|
|
625
625
|
|
|
626
626
|
The `experimental_continuationSteps` option has been removed from the `generateText` function.
|
|
627
627
|
Please use the `experimental_continueSteps` option instead.
|
|
@@ -710,7 +710,7 @@ const warnings = await result.warnings;
|
|
|
710
710
|
code manually.
|
|
711
711
|
</Note>
|
|
712
712
|
|
|
713
|
-
The `simulateReadableStream` function from `ai/test` has been renamed to `chunks`.
|
|
713
|
+
The `values` option of the `simulateReadableStream` function from `ai/test` has been renamed to `chunks`.
|
|
714
714
|
|
|
715
715
|
```ts filename="AI SDK 3.4"
|
|
716
716
|
import { simulateReadableStream } from 'ai/test';
|
|
@@ -965,7 +965,7 @@ return AssistantResponse(
|
|
|
965
965
|
);
|
|
966
966
|
```
|
|
967
967
|
|
|
968
|
-
#### Removed `
|
|
968
|
+
#### Removed `experimental_AssistantResponse` export
|
|
969
969
|
|
|
970
970
|
<Note type="warning">
|
|
971
971
|
There is no codemod available for this change. Please review and update your
|
|
@@ -18,7 +18,7 @@ introducing significant improvements and new features across the AI SDK and its
|
|
|
18
18
|
|
|
19
19
|
## New Features
|
|
20
20
|
|
|
21
|
-
###
|
|
21
|
+
### OpenTelemetry Support
|
|
22
22
|
|
|
23
23
|
- Added experimental [OpenTelemetry support](/docs/ai-sdk-core/telemetry) for all [AI SDK Core functions](/docs/ai-sdk-core/overview#ai-sdk-core-functions), enabling better observability and tracing capabilities.
|
|
24
24
|
|
|
@@ -23,7 +23,7 @@ This guide will help you upgrade to AI SDK 3.2:
|
|
|
23
23
|
|
|
24
24
|
To update to AI SDK version 3.2, run the following command using your preferred package manager:
|
|
25
25
|
|
|
26
|
-
<Snippet text="pnpm add ai@
|
|
26
|
+
<Snippet text="pnpm add ai@3.2" />
|
|
27
27
|
|
|
28
28
|
## Removed Functionality
|
|
29
29
|
|
|
@@ -49,14 +49,16 @@ return createUIMessageStreamResponse({
|
|
|
49
49
|
});
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
In case you are using `
|
|
52
|
+
In case you are using `createUIMessageStream`, you can pass the `onError` function to it:
|
|
53
53
|
|
|
54
54
|
```tsx
|
|
55
|
-
const response =
|
|
56
|
-
|
|
57
|
-
async execute(dataStream) {
|
|
55
|
+
const response = createUIMessageStreamResponse({
|
|
56
|
+
stream: createUIMessageStream({
|
|
58
57
|
// ...
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
async execute({ writer }) {
|
|
59
|
+
// ...
|
|
60
|
+
},
|
|
61
|
+
onError: errorHandler,
|
|
62
|
+
}),
|
|
61
63
|
});
|
|
62
64
|
```
|
|
@@ -23,17 +23,17 @@ Use the `throttle` option to throttle the UI updates:
|
|
|
23
23
|
### `useChat`
|
|
24
24
|
|
|
25
25
|
```tsx filename="page.tsx" highlight="2-3"
|
|
26
|
-
const { messages
|
|
26
|
+
const { messages } = useChat({
|
|
27
27
|
// Throttle the messages and data updates to 50ms:
|
|
28
|
-
throttle: 50
|
|
29
|
-
})
|
|
28
|
+
throttle: 50,
|
|
29
|
+
});
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
### `useCompletion`
|
|
33
33
|
|
|
34
34
|
```tsx filename="page.tsx" highlight="2-3"
|
|
35
|
-
const { completion
|
|
35
|
+
const { completion } = useCompletion({
|
|
36
36
|
// Throttle the completion and data updates to 50ms:
|
|
37
|
-
throttle: 50
|
|
38
|
-
})
|
|
37
|
+
throttle: 50,
|
|
38
|
+
});
|
|
39
39
|
```
|
|
@@ -17,7 +17,7 @@ This is especially noticeable when using `experimental_download` to process imag
|
|
|
17
17
|
|
|
18
18
|
## Background
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
When enabled with the `include` option, the AI SDK includes the full request messages plus request and response bodies in the step results. When processing images, the request messages and request body can contain base64-encoded image data, which can be very large (a single image can be 1MB+ when base64 encoded). If you process many images and keep references to the results, this data accumulates in memory.
|
|
21
21
|
|
|
22
22
|
For example, processing 100 images of 500KB each would include ~50MB+ of request body data in memory.
|
|
23
23
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.123",
|
|
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.101",
|
|
46
|
+
"@ai-sdk/provider": "4.0.20",
|
|
47
|
+
"@ai-sdk/provider-utils": "5.0.52"
|
|
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.
|
|
57
|
-
"@ai-sdk/test-server": "2.0.
|
|
58
|
-
"@ai-sdk/xai": "5.0.
|
|
50
|
+
"@ai-sdk/amazon-bedrock": "5.0.102",
|
|
51
|
+
"@ai-sdk/deepseek": "3.0.57",
|
|
52
|
+
"@ai-sdk/google": "4.0.86",
|
|
53
|
+
"@ai-sdk/groq": "4.0.53",
|
|
54
|
+
"@ai-sdk/huggingface": "2.0.60",
|
|
55
|
+
"@ai-sdk/moonshotai": "3.0.61",
|
|
56
|
+
"@ai-sdk/openai": "4.0.82",
|
|
57
|
+
"@ai-sdk/test-server": "2.0.3",
|
|
58
|
+
"@ai-sdk/xai": "5.0.13",
|
|
59
59
|
"@edge-runtime/vm": "^5.0.0",
|
|
60
60
|
"@smithy/eventstream-codec": "^4.3.3",
|
|
61
61
|
"@smithy/util-utf8": "^4.3.3",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"@types/node": "22.19.19",
|
|
64
64
|
"@vercel/ai-tsconfig": "0.0.0",
|
|
65
65
|
"esbuild": "^0.28.1",
|
|
66
|
-
"
|
|
66
|
+
"tsdown": "^0.23.0",
|
|
67
67
|
"tsx": "4.23.12",
|
|
68
68
|
"typescript": "5.8.3",
|
|
69
69
|
"zod": "3.25.76"
|
|
@@ -113,9 +113,9 @@
|
|
|
113
113
|
"grok"
|
|
114
114
|
],
|
|
115
115
|
"scripts": {
|
|
116
|
-
"build": "pnpm clean &&
|
|
117
|
-
"build:watch": "pnpm clean &&
|
|
118
|
-
"clean": "del-cli
|
|
116
|
+
"build": "pnpm clean && tsdown",
|
|
117
|
+
"build:watch": "pnpm clean && tsdown --watch",
|
|
118
|
+
"clean": "del-cli docs *.tsbuildinfo",
|
|
119
119
|
"type-check": "tsc --build",
|
|
120
120
|
"test": "pnpm test:node && pnpm test:edge",
|
|
121
121
|
"test:update": "pnpm test:node -u",
|
|
@@ -33,6 +33,7 @@ import { createAgentUIStream } from './create-agent-ui-stream';
|
|
|
33
33
|
* @param headers - Additional headers for the response. Optional.
|
|
34
34
|
* @param status - The status code for the response. Optional.
|
|
35
35
|
* @param statusText - The status text for the response. Optional.
|
|
36
|
+
* @param keepAliveMs - Optional interval for sending SSE keep-alive comments.
|
|
36
37
|
* @param consumeSseStream - Whether to consume the SSE stream. Optional.
|
|
37
38
|
*
|
|
38
39
|
* @returns The response object.
|
|
@@ -47,6 +48,7 @@ export async function createAgentUIStreamResponse<
|
|
|
47
48
|
headers,
|
|
48
49
|
status,
|
|
49
50
|
statusText,
|
|
51
|
+
keepAliveMs,
|
|
50
52
|
consumeSseStream,
|
|
51
53
|
...options
|
|
52
54
|
}: {
|
|
@@ -68,6 +70,7 @@ export async function createAgentUIStreamResponse<
|
|
|
68
70
|
headers,
|
|
69
71
|
status,
|
|
70
72
|
statusText,
|
|
73
|
+
keepAliveMs,
|
|
71
74
|
consumeSseStream,
|
|
72
75
|
stream: await createAgentUIStream(options),
|
|
73
76
|
});
|
|
@@ -35,6 +35,7 @@ import { createAgentUIStream } from './create-agent-ui-stream';
|
|
|
35
35
|
* @param headers - Additional headers for the response. Optional.
|
|
36
36
|
* @param status - The status code for the response. Optional.
|
|
37
37
|
* @param statusText - The status text for the response. Optional.
|
|
38
|
+
* @param keepAliveMs - Optional interval for sending SSE keep-alive comments.
|
|
38
39
|
* @param consumeSseStream - Whether to consume the SSE stream. Optional.
|
|
39
40
|
*/
|
|
40
41
|
export async function pipeAgentUIStreamToResponse<
|
|
@@ -48,6 +49,7 @@ export async function pipeAgentUIStreamToResponse<
|
|
|
48
49
|
headers,
|
|
49
50
|
status,
|
|
50
51
|
statusText,
|
|
52
|
+
keepAliveMs,
|
|
51
53
|
consumeSseStream,
|
|
52
54
|
...options
|
|
53
55
|
}: {
|
|
@@ -71,6 +73,7 @@ export async function pipeAgentUIStreamToResponse<
|
|
|
71
73
|
headers,
|
|
72
74
|
status,
|
|
73
75
|
statusText,
|
|
76
|
+
keepAliveMs,
|
|
74
77
|
consumeSseStream,
|
|
75
78
|
stream: await createAgentUIStream(options),
|
|
76
79
|
});
|
package/src/embed/embed-many.ts
CHANGED
|
@@ -14,6 +14,8 @@ import type { TelemetryOptions } from '../telemetry/telemetry-options';
|
|
|
14
14
|
import type { Embedding, EmbeddingModel, ProviderMetadata } from '../types';
|
|
15
15
|
import type { Warning } from '../types/warning';
|
|
16
16
|
import type { Callback } from '../util/callback';
|
|
17
|
+
import { getOwn } from '../util/get-own';
|
|
18
|
+
import { setOwn } from '../util/set-own';
|
|
17
19
|
import { notify } from '../util/notify';
|
|
18
20
|
import { prepareRetries } from '../util/prepare-retries';
|
|
19
21
|
import { splitArray } from '../util/split-array';
|
|
@@ -427,10 +429,10 @@ export async function embedMany<RUNTIME_CONTEXT extends Context = Context>({
|
|
|
427
429
|
for (const [providerName, metadata] of Object.entries(
|
|
428
430
|
result.providerMetadata,
|
|
429
431
|
)) {
|
|
430
|
-
providerMetadata
|
|
431
|
-
...providerMetadata
|
|
432
|
+
setOwn(providerMetadata, providerName, {
|
|
433
|
+
...getOwn(providerMetadata, providerName),
|
|
432
434
|
...metadata,
|
|
433
|
-
};
|
|
435
|
+
});
|
|
434
436
|
}
|
|
435
437
|
}
|
|
436
438
|
}
|
|
@@ -25,6 +25,8 @@ import type { ImageModel } from '../types/image-model';
|
|
|
25
25
|
import type { ImageModelResponseMetadata } from '../types/image-model-response-metadata';
|
|
26
26
|
import { addImageModelUsage, type ImageModelUsage } from '../types/usage';
|
|
27
27
|
import type { Warning } from '../types/warning';
|
|
28
|
+
import { getOwn } from '../util/get-own';
|
|
29
|
+
import { setOwn } from '../util/set-own';
|
|
28
30
|
import { prepareRetries } from '../util/prepare-retries';
|
|
29
31
|
import { RetryError } from '../util/retry-error';
|
|
30
32
|
import { VERSION } from '../version';
|
|
@@ -324,8 +326,11 @@ export async function generateImage({
|
|
|
324
326
|
.images;
|
|
325
327
|
}
|
|
326
328
|
} else {
|
|
327
|
-
providerMetadata
|
|
328
|
-
|
|
329
|
+
const currentEntry = getOwn(providerMetadata, providerName) ?? {
|
|
330
|
+
images: [],
|
|
331
|
+
};
|
|
332
|
+
currentEntry.images.push(...metadata.images);
|
|
333
|
+
setOwn(providerMetadata, providerName, currentEntry);
|
|
329
334
|
}
|
|
330
335
|
}
|
|
331
336
|
}
|
|
@@ -395,7 +400,7 @@ export function getImageProviderMetadata(
|
|
|
395
400
|
const value = metadata.images?.[imageIndex];
|
|
396
401
|
|
|
397
402
|
if (isJSONObject(value) && !Array.isArray(value)) {
|
|
398
|
-
(imageMetadata ??= {})
|
|
403
|
+
setOwn((imageMetadata ??= {}), providerName, value);
|
|
399
404
|
}
|
|
400
405
|
}
|
|
401
406
|
|
|
@@ -82,7 +82,7 @@ export function pruneMessages({
|
|
|
82
82
|
const keptToolCallIds: Set<string> = new Set();
|
|
83
83
|
const keptApprovalIds: Set<string> = new Set();
|
|
84
84
|
|
|
85
|
-
if (keepLastMessagesCount != null) {
|
|
85
|
+
if (keepLastMessagesCount != null && keepLastMessagesCount !== 0) {
|
|
86
86
|
for (const message of messages.slice(-keepLastMessagesCount)) {
|
|
87
87
|
if (
|
|
88
88
|
(message.role === 'assistant' || message.role === 'tool') &&
|
|
@@ -159,10 +159,20 @@ export function smoothStream<TOOLS extends ToolSet>({
|
|
|
159
159
|
return;
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
if (chunk.text.length === 0 && chunk.providerMetadata != null) {
|
|
163
|
+
flushBuffer(controller);
|
|
164
|
+
controller.enqueue(chunk);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Flush at metadata boundaries because one output part cannot preserve
|
|
169
|
+
// metadata from multiple input deltas.
|
|
163
170
|
if (
|
|
164
|
-
|
|
165
|
-
(
|
|
171
|
+
buffer.length > 0 &&
|
|
172
|
+
(chunk.type !== type ||
|
|
173
|
+
chunk.id !== id ||
|
|
174
|
+
providerMetadata != null ||
|
|
175
|
+
chunk.providerMetadata != null)
|
|
166
176
|
) {
|
|
167
177
|
flushBuffer(controller);
|
|
168
178
|
}
|
|
@@ -170,20 +180,25 @@ export function smoothStream<TOOLS extends ToolSet>({
|
|
|
170
180
|
buffer += chunk.text;
|
|
171
181
|
id = chunk.id;
|
|
172
182
|
type = chunk.type;
|
|
173
|
-
|
|
174
|
-
// Preserve providerMetadata (e.g., Anthropic thinking signatures)
|
|
175
|
-
if (chunk.providerMetadata != null) {
|
|
176
|
-
providerMetadata = chunk.providerMetadata;
|
|
177
|
-
}
|
|
183
|
+
providerMetadata = chunk.providerMetadata;
|
|
178
184
|
|
|
179
185
|
let match;
|
|
180
186
|
|
|
181
187
|
while ((match = detectChunk(buffer)) != null) {
|
|
182
|
-
controller.enqueue({
|
|
188
|
+
controller.enqueue({
|
|
189
|
+
type,
|
|
190
|
+
text: match,
|
|
191
|
+
id,
|
|
192
|
+
...(providerMetadata != null ? { providerMetadata } : {}),
|
|
193
|
+
});
|
|
183
194
|
buffer = buffer.slice(match.length);
|
|
184
195
|
|
|
185
196
|
await delay(isDocumentHidden() ? null : delayInMs);
|
|
186
197
|
}
|
|
198
|
+
|
|
199
|
+
if (buffer.length === 0) {
|
|
200
|
+
providerMetadata = undefined;
|
|
201
|
+
}
|
|
187
202
|
},
|
|
188
203
|
});
|
|
189
204
|
};
|
|
@@ -104,6 +104,11 @@ export type UIMessageStreamOptions<UI_MESSAGE extends UIMessage> = {
|
|
|
104
104
|
/**
|
|
105
105
|
* Process an error, e.g. to log it. Default to `() => 'An error occurred.'`.
|
|
106
106
|
*
|
|
107
|
+
* Tool execution errors marked `providerExecuted: true` bypass this callback.
|
|
108
|
+
* Their strings pass through unchanged; other values are JSON-stringified to
|
|
109
|
+
* preserve provider error data for model-message round trips and harness
|
|
110
|
+
* runtime error messages. Stream errors and invalid tool calls still use it.
|
|
111
|
+
*
|
|
107
112
|
* @returns error message to include in the data stream.
|
|
108
113
|
*/
|
|
109
114
|
onError?: (error: unknown) => string;
|
|
@@ -29,6 +29,8 @@ import { resolveVideoModel } from '../model/resolve-model';
|
|
|
29
29
|
import type { VideoModel } from '../types/video-model';
|
|
30
30
|
import type { VideoModelResponseMetadata } from '../types/video-model-response-metadata';
|
|
31
31
|
import type { Warning } from '../types/warning';
|
|
32
|
+
import { getOwn } from '../util/get-own';
|
|
33
|
+
import { setOwn } from '../util/set-own';
|
|
32
34
|
import { createDownload } from '../util/download/create-download';
|
|
33
35
|
import { prepareRetries } from '../util/prepare-retries';
|
|
34
36
|
import { VERSION } from '../version';
|
|
@@ -697,17 +699,17 @@ function mergeProviderMetadata(
|
|
|
697
699
|
source: SharedV4ProviderMetadata,
|
|
698
700
|
): void {
|
|
699
701
|
for (const [providerName, metadataValue] of Object.entries(source)) {
|
|
700
|
-
const existingMetadata = target
|
|
702
|
+
const existingMetadata = getOwn(target, providerName);
|
|
701
703
|
if (
|
|
702
704
|
existingMetadata != null &&
|
|
703
705
|
typeof existingMetadata === 'object' &&
|
|
704
706
|
metadataValue != null &&
|
|
705
707
|
typeof metadataValue === 'object'
|
|
706
708
|
) {
|
|
707
|
-
target
|
|
709
|
+
setOwn(target, providerName, {
|
|
708
710
|
...existingMetadata,
|
|
709
711
|
...metadataValue,
|
|
710
|
-
};
|
|
712
|
+
});
|
|
711
713
|
|
|
712
714
|
if (
|
|
713
715
|
'videos' in existingMetadata &&
|
|
@@ -721,7 +723,7 @@ function mergeProviderMetadata(
|
|
|
721
723
|
];
|
|
722
724
|
}
|
|
723
725
|
} else {
|
|
724
|
-
target
|
|
726
|
+
setOwn(target, providerName, metadataValue);
|
|
725
727
|
}
|
|
726
728
|
}
|
|
727
729
|
}
|
|
@@ -116,20 +116,15 @@ export function extractReasoningMiddleware({
|
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
if (
|
|
120
|
-
chunk.type === 'text-end' &&
|
|
121
|
-
delayedTextStarts[chunk.id] != null
|
|
122
|
-
) {
|
|
123
|
-
controller.enqueue(delayedTextStarts[chunk.id]);
|
|
124
|
-
delete delayedTextStarts[chunk.id];
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (chunk.type !== 'text-delta') {
|
|
119
|
+
if (chunk.type !== 'text-delta' && chunk.type !== 'text-end') {
|
|
128
120
|
controller.enqueue(chunk);
|
|
129
121
|
return;
|
|
130
122
|
}
|
|
131
123
|
|
|
132
|
-
if (
|
|
124
|
+
if (
|
|
125
|
+
chunk.type === 'text-delta' &&
|
|
126
|
+
reasoningExtractions[chunk.id] == null
|
|
127
|
+
) {
|
|
133
128
|
reasoningExtractions[chunk.id] = {
|
|
134
129
|
isFirstReasoning: true,
|
|
135
130
|
isFirstText: true,
|
|
@@ -143,7 +138,14 @@ export function extractReasoningMiddleware({
|
|
|
143
138
|
|
|
144
139
|
const activeExtraction = reasoningExtractions[chunk.id];
|
|
145
140
|
|
|
146
|
-
activeExtraction
|
|
141
|
+
if (activeExtraction == null) {
|
|
142
|
+
if (delayedTextStarts[chunk.id] != null) {
|
|
143
|
+
controller.enqueue(delayedTextStarts[chunk.id]);
|
|
144
|
+
delete delayedTextStarts[chunk.id];
|
|
145
|
+
}
|
|
146
|
+
controller.enqueue(chunk);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
147
149
|
|
|
148
150
|
function getReasoningId() {
|
|
149
151
|
return (activeExtraction.reasoningId ??= `reasoning-${reasoningIdCounter++}`);
|
|
@@ -199,6 +201,20 @@ export function extractReasoningMiddleware({
|
|
|
199
201
|
}
|
|
200
202
|
}
|
|
201
203
|
|
|
204
|
+
if (chunk.type === 'text-end') {
|
|
205
|
+
publish(activeExtraction.buffer);
|
|
206
|
+
activeExtraction.buffer = '';
|
|
207
|
+
|
|
208
|
+
if (delayedTextStarts[chunk.id] != null) {
|
|
209
|
+
controller.enqueue(delayedTextStarts[chunk.id]);
|
|
210
|
+
delete delayedTextStarts[chunk.id];
|
|
211
|
+
}
|
|
212
|
+
controller.enqueue(chunk);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
activeExtraction.buffer += chunk.delta;
|
|
217
|
+
|
|
202
218
|
do {
|
|
203
219
|
const nextTag = activeExtraction.isReasoning
|
|
204
220
|
? closingTag
|
|
@@ -213,7 +213,7 @@ class DefaultProviderRegistry<
|
|
|
213
213
|
keyof PROVIDERS,
|
|
214
214
|
ProviderV4 & ProviderWithOptionalVideoModel & EvaluationProvider
|
|
215
215
|
>
|
|
216
|
-
> =
|
|
216
|
+
> = Object.create(null);
|
|
217
217
|
private separator: SEPARATOR;
|
|
218
218
|
private languageModelMiddleware?:
|
|
219
219
|
| LanguageModelMiddleware
|
package/src/ui/chat.ts
CHANGED
|
@@ -818,6 +818,14 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
818
818
|
responseMessageIndex === -1
|
|
819
819
|
? lastMessage
|
|
820
820
|
: this.state.messages[responseMessageIndex];
|
|
821
|
+
const resumableResponseMessage =
|
|
822
|
+
trigger === 'resume-stream' &&
|
|
823
|
+
responseMessage?.role === 'assistant' &&
|
|
824
|
+
responseMessage.parts.some(
|
|
825
|
+
part => isToolUIPart(part) && part.state === 'input-streaming',
|
|
826
|
+
)
|
|
827
|
+
? this.state.snapshot(responseMessage)
|
|
828
|
+
: undefined;
|
|
821
829
|
const usesEarlierAssistantMessage =
|
|
822
830
|
responseMessageIndex !== -1 &&
|
|
823
831
|
responseMessageIndex < this.state.messages.length - 1 &&
|
|
@@ -835,10 +843,11 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
835
843
|
? this.resumableStreamState
|
|
836
844
|
: createStreamingUIMessageState({
|
|
837
845
|
lastMessage:
|
|
838
|
-
trigger === 'resume-stream'
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
846
|
+
trigger === 'resume-stream'
|
|
847
|
+
? resumableResponseMessage
|
|
848
|
+
: trigger === 'regenerate-message'
|
|
849
|
+
? undefined
|
|
850
|
+
: this.state.snapshot(responseMessage),
|
|
842
851
|
messageId: this.generateId(),
|
|
843
852
|
}),
|
|
844
853
|
abortController,
|
|
@@ -59,16 +59,28 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
|
|
|
59
59
|
|
|
60
60
|
warnIfUIMessageHasDeprecatedRawInput(messages);
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
// A later user message supersedes unresolved approval requests. Keeping
|
|
63
|
+
// those requests would leave unmatched tool calls at the user boundary.
|
|
64
|
+
const lastUserMessageIndex = messages.reduce(
|
|
65
|
+
(lastIndex, message, index) =>
|
|
66
|
+
message.role === 'user' ? index : lastIndex,
|
|
67
|
+
-1,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
if (options?.ignoreIncompleteToolCalls || lastUserMessageIndex > 0) {
|
|
71
|
+
messages = messages.map((message, messageIndex) => ({
|
|
64
72
|
...message,
|
|
65
73
|
parts: message.parts.filter(
|
|
66
74
|
part =>
|
|
67
75
|
!isToolUIPart(part) ||
|
|
68
|
-
part.state
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
((part.state !== 'approval-requested' ||
|
|
77
|
+
messageIndex >= lastUserMessageIndex) &&
|
|
78
|
+
(!options?.ignoreIncompleteToolCalls ||
|
|
79
|
+
part.state === 'approval-responded' ||
|
|
80
|
+
(part.state === 'output-available' &&
|
|
81
|
+
part.preliminary !== true) ||
|
|
82
|
+
part.state === 'output-error' ||
|
|
83
|
+
part.state === 'output-denied')),
|
|
72
84
|
),
|
|
73
85
|
}));
|
|
74
86
|
}
|