ai 7.0.88 → 7.0.90
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 +27 -5
- package/dist/index.js +32 -13
- package/dist/index.js.map +1 -1
- package/dist/internal/index.js +1 -1
- package/docs/02-foundations/02-providers-and-models.mdx +1 -0
- package/docs/03-agents/07-workflow-agent.mdx +15 -0
- package/docs/03-ai-sdk-core/39-file-uploads.mdx +25 -0
- package/docs/06-advanced/11-secure-url-fetching.mdx +7 -1
- package/docs/07-reference/01-ai-sdk-core/14-upload-file.mdx +37 -4
- package/package.json +12 -12
- package/src/upload-file/upload-file-result.ts +12 -0
- package/src/upload-file/upload-file.ts +63 -22
package/dist/internal/index.js
CHANGED
|
@@ -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 /> |
|
|
@@ -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
|
|
@@ -94,6 +94,31 @@ const { providerReference } = await uploadFile({
|
|
|
94
94
|
});
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
## Streaming Uploads
|
|
98
|
+
|
|
99
|
+
Providers that support streaming uploads (e.g. OpenAI, xAI) accept a tagged
|
|
100
|
+
`{ type: 'stream', stream }` shape, sending the bytes without buffering the
|
|
101
|
+
full file in memory. Providers without streaming support reject stream data
|
|
102
|
+
with an `UnsupportedFunctionalityError`.
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
const { providerReference } = await uploadFile({
|
|
106
|
+
api: openai.files(),
|
|
107
|
+
data: { type: 'stream', stream: fileStream },
|
|
108
|
+
mediaType: 'application/jsonl',
|
|
109
|
+
filename: 'batch.jsonl',
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The provider consumes the stream: any failed upload — including validation
|
|
114
|
+
failures before a request is made — cancels it, and it must not be reused. Stream data cannot be sniffed, so `mediaType` defaults to
|
|
115
|
+
`application/octet-stream` when omitted, and multipart-based providers default
|
|
116
|
+
the filename to `"blob"`.
|
|
117
|
+
|
|
118
|
+
Uploads can be cancelled with `abortSignal` and carry request-specific
|
|
119
|
+
`headers`. Results include `byteSize`, `createdAt`, and `expiresAt` (the
|
|
120
|
+
provider-applied retention expiry) when the provider reports them.
|
|
121
|
+
|
|
97
122
|
## Provider References
|
|
98
123
|
|
|
99
124
|
A `ProviderReference` is a `Record<string, string>` that maps provider names to
|
|
@@ -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
|
|
|
@@ -39,22 +39,35 @@ const { providerReference } = await uploadFile({
|
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
name: 'data',
|
|
42
|
-
type: 'DataContent',
|
|
42
|
+
type: 'DataContent | { type: "stream"; stream: ReadableStream<Uint8Array> }',
|
|
43
43
|
description:
|
|
44
|
-
'The file data to upload. Can be a `Uint8Array`, a base64-encoded string, an `ArrayBuffer`, or a `
|
|
44
|
+
'The file data to upload. Can be a `Uint8Array`, a base64-encoded string, an `ArrayBuffer`, a `Buffer`, or a tagged `{ type: "stream", stream }` shape for providers that support streaming uploads (sent without buffering; other providers reject with an `UnsupportedFunctionalityError`). The provider consumes the stream — any failed upload (including validation failures before a request is made) cancels it, and it must not be reused. URLs are not supported — fetch the content first and pass the bytes.',
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
name: 'mediaType',
|
|
48
48
|
type: 'string',
|
|
49
49
|
isOptional: true,
|
|
50
50
|
description:
|
|
51
|
-
'IANA media type of the file (e.g. `image/png`, `application/pdf`). Auto-detected from the file bytes if not provided
|
|
51
|
+
'IANA media type of the file (e.g. `image/png`, `application/pdf`). Auto-detected from the file bytes if not provided; stream data cannot be sniffed and defaults to `application/octet-stream`.',
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
name: 'filename',
|
|
55
55
|
type: 'string',
|
|
56
56
|
isOptional: true,
|
|
57
|
-
description:
|
|
57
|
+
description:
|
|
58
|
+
'Filename for the uploaded file. Multipart-based providers default it to `"blob"` when omitted.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'abortSignal',
|
|
62
|
+
type: 'AbortSignal',
|
|
63
|
+
isOptional: true,
|
|
64
|
+
description: 'Signal to cancel the upload.',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: 'headers',
|
|
68
|
+
type: 'Record<string, string>',
|
|
69
|
+
isOptional: true,
|
|
70
|
+
description: 'Additional HTTP headers to send with the request.',
|
|
58
71
|
},
|
|
59
72
|
{
|
|
60
73
|
name: 'providerOptions',
|
|
@@ -76,6 +89,26 @@ const { providerReference } = await uploadFile({
|
|
|
76
89
|
description:
|
|
77
90
|
'A `Record<string, string>` mapping provider names to provider-specific file identifiers. Pass this as the `data` or `image` field in message content parts.',
|
|
78
91
|
},
|
|
92
|
+
{
|
|
93
|
+
name: 'byteSize',
|
|
94
|
+
type: 'number',
|
|
95
|
+
isOptional: true,
|
|
96
|
+
description:
|
|
97
|
+
'Size of the uploaded file in bytes, if reported by the provider.',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'createdAt',
|
|
101
|
+
type: 'Date',
|
|
102
|
+
isOptional: true,
|
|
103
|
+
description: 'When the file was created, if reported by the provider.',
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'expiresAt',
|
|
107
|
+
type: 'Date',
|
|
108
|
+
isOptional: true,
|
|
109
|
+
description:
|
|
110
|
+
'When the provider will delete the file (retention expiry, e.g. from a requested upload TTL), if reported by the provider.',
|
|
111
|
+
},
|
|
79
112
|
{
|
|
80
113
|
name: 'providerMetadata',
|
|
81
114
|
type: 'ProviderMetadata',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.90",
|
|
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.72",
|
|
46
|
+
"@ai-sdk/provider": "4.0.10",
|
|
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.72",
|
|
51
|
+
"@ai-sdk/deepseek": "3.0.39",
|
|
52
|
+
"@ai-sdk/google": "4.0.62",
|
|
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.56",
|
|
57
57
|
"@ai-sdk/test-server": "2.0.1",
|
|
58
|
-
"@ai-sdk/xai": "4.0.
|
|
58
|
+
"@ai-sdk/xai": "4.0.53",
|
|
59
59
|
"@edge-runtime/vm": "^5.0.0",
|
|
60
60
|
"@smithy/eventstream-codec": "^4.3.3",
|
|
61
61
|
"@smithy/util-utf8": "^4.3.3",
|
|
@@ -6,6 +6,18 @@ export interface UploadFileResult {
|
|
|
6
6
|
readonly providerReference: ProviderReference;
|
|
7
7
|
readonly mediaType?: string;
|
|
8
8
|
readonly filename?: string;
|
|
9
|
+
/**
|
|
10
|
+
* The size of the uploaded file in bytes, if reported by the provider.
|
|
11
|
+
*/
|
|
12
|
+
readonly byteSize?: number;
|
|
13
|
+
/**
|
|
14
|
+
* When the file was created, if reported by the provider.
|
|
15
|
+
*/
|
|
16
|
+
readonly createdAt?: Date;
|
|
17
|
+
/**
|
|
18
|
+
* When the provider will delete the file (retention expiry), if reported.
|
|
19
|
+
*/
|
|
20
|
+
readonly expiresAt?: Date;
|
|
9
21
|
readonly providerMetadata?: ProviderMetadata;
|
|
10
22
|
readonly warnings: Array<Warning>;
|
|
11
23
|
}
|
|
@@ -16,19 +16,31 @@ import type { UploadFileResult } from './upload-file-result';
|
|
|
16
16
|
* Uploads a file using a files API interface.
|
|
17
17
|
*
|
|
18
18
|
* @param api - The Files API interface to use for uploading.
|
|
19
|
-
* @param data - The file data to upload (tagged `{ type: 'data' | 'text' }`).
|
|
19
|
+
* @param data - The file data to upload (tagged `{ type: 'data' | 'text' | 'stream' }`).
|
|
20
|
+
* Stream data is sent without buffering by providers that support streaming
|
|
21
|
+
* uploads (others reject with `UnsupportedFunctionalityError`); the provider
|
|
22
|
+
* consumes the stream — any failed upload, including validation failures
|
|
23
|
+
* before a request is made, cancels it. Do not reuse it.
|
|
20
24
|
* @param mediaType - Optional IANA media type. Auto-detected from file bytes
|
|
21
|
-
* when omitted (falls back to `text/plain` for the `text` variant
|
|
22
|
-
*
|
|
25
|
+
* when omitted (falls back to `text/plain` for the `text` variant and
|
|
26
|
+
* `application/octet-stream` for the `stream` variant, which cannot be sniffed).
|
|
27
|
+
* @param filename - Optional filename for the uploaded file. Multipart-based
|
|
28
|
+
* providers default it to `"blob"` when omitted.
|
|
29
|
+
* @param abortSignal - Optional signal to cancel the upload.
|
|
30
|
+
* @param headers - Optional additional HTTP headers for the request.
|
|
23
31
|
* @param providerOptions - Additional provider-specific options.
|
|
24
32
|
*
|
|
25
|
-
* @returns A result object containing the provider reference
|
|
33
|
+
* @returns A result object containing the provider reference, optional
|
|
34
|
+
* metadata, and — when reported by the provider — `byteSize`, `createdAt`,
|
|
35
|
+
* and `expiresAt` (the provider-applied retention expiry).
|
|
26
36
|
*/
|
|
27
37
|
export async function uploadFile({
|
|
28
38
|
api,
|
|
29
39
|
data: dataArg,
|
|
30
40
|
mediaType: mediaTypeArg,
|
|
31
41
|
filename,
|
|
42
|
+
abortSignal,
|
|
43
|
+
headers,
|
|
32
44
|
providerOptions,
|
|
33
45
|
}: {
|
|
34
46
|
/**
|
|
@@ -54,35 +66,55 @@ export async function uploadFile({
|
|
|
54
66
|
? { type: 'data', data: dataArg }
|
|
55
67
|
: dataArg;
|
|
56
68
|
|
|
69
|
+
// stream data cannot be sniffed without consuming it
|
|
57
70
|
const mediaType =
|
|
58
71
|
mediaTypeArg ??
|
|
59
72
|
(data.type === 'text'
|
|
60
73
|
? 'text/plain'
|
|
61
|
-
:
|
|
62
|
-
|
|
74
|
+
: data.type === 'stream'
|
|
75
|
+
? 'application/octet-stream'
|
|
76
|
+
: (detectMediaType({ data: data.data }) ??
|
|
77
|
+
(isLikelyText(data.data)
|
|
78
|
+
? 'text/plain'
|
|
79
|
+
: 'application/octet-stream')));
|
|
63
80
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
? api
|
|
69
|
-
:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
81
|
+
let result;
|
|
82
|
+
try {
|
|
83
|
+
const filesApi: FilesV4 =
|
|
84
|
+
'uploadFile' in api
|
|
85
|
+
? api
|
|
86
|
+
: typeof api.files === 'function'
|
|
87
|
+
? api.files()
|
|
88
|
+
: (() => {
|
|
89
|
+
throw new Error(
|
|
90
|
+
'The provider does not support file uploads. Make sure it exposes a files() method.',
|
|
91
|
+
);
|
|
92
|
+
})();
|
|
74
93
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
94
|
+
result = await filesApi.uploadFile({
|
|
95
|
+
data,
|
|
96
|
+
mediaType,
|
|
97
|
+
filename,
|
|
98
|
+
abortSignal,
|
|
99
|
+
headers,
|
|
100
|
+
providerOptions,
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
// ownership guarantee: a failed upload releases the stream, even when
|
|
104
|
+
// the provider rejected before (or without) consuming it
|
|
105
|
+
if (data.type === 'stream') {
|
|
106
|
+
await data.stream.cancel(error).catch(() => {});
|
|
107
|
+
}
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
81
110
|
|
|
82
111
|
return new DefaultUploadFileResult({
|
|
83
112
|
providerReference: result.providerReference,
|
|
84
113
|
mediaType: result.mediaType,
|
|
85
114
|
filename: result.filename,
|
|
115
|
+
byteSize: result.byteSize,
|
|
116
|
+
createdAt: result.createdAt,
|
|
117
|
+
expiresAt: result.expiresAt,
|
|
86
118
|
providerMetadata: result.providerMetadata,
|
|
87
119
|
warnings: result.warnings,
|
|
88
120
|
});
|
|
@@ -92,6 +124,9 @@ class DefaultUploadFileResult implements UploadFileResult {
|
|
|
92
124
|
readonly providerReference: ProviderReference;
|
|
93
125
|
readonly mediaType?: string;
|
|
94
126
|
readonly filename?: string;
|
|
127
|
+
readonly byteSize?: number;
|
|
128
|
+
readonly createdAt?: Date;
|
|
129
|
+
readonly expiresAt?: Date;
|
|
95
130
|
readonly providerMetadata?: ProviderMetadata;
|
|
96
131
|
readonly warnings: Array<Warning>;
|
|
97
132
|
|
|
@@ -99,12 +134,18 @@ class DefaultUploadFileResult implements UploadFileResult {
|
|
|
99
134
|
providerReference: ProviderReference;
|
|
100
135
|
mediaType?: string;
|
|
101
136
|
filename?: string;
|
|
137
|
+
byteSize?: number;
|
|
138
|
+
createdAt?: Date;
|
|
139
|
+
expiresAt?: Date;
|
|
102
140
|
providerMetadata?: ProviderMetadata;
|
|
103
141
|
warnings: Array<Warning>;
|
|
104
142
|
}) {
|
|
105
143
|
this.providerReference = options.providerReference;
|
|
106
144
|
this.mediaType = options.mediaType;
|
|
107
145
|
this.filename = options.filename;
|
|
146
|
+
this.byteSize = options.byteSize;
|
|
147
|
+
this.createdAt = options.createdAt;
|
|
148
|
+
this.expiresAt = options.expiresAt;
|
|
108
149
|
this.providerMetadata = options.providerMetadata;
|
|
109
150
|
this.warnings = options.warnings;
|
|
110
151
|
}
|