ai 7.0.88 → 7.0.89

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.
@@ -91,7 +91,7 @@ import {
91
91
  } from "@ai-sdk/provider-utils";
92
92
 
93
93
  // src/version.ts
94
- var VERSION = true ? "7.0.88" : "0.0.0-test";
94
+ var VERSION = true ? "7.0.89" : "0.0.0-test";
95
95
 
96
96
  // src/util/download/download.ts
97
97
  var download = async ({
@@ -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
@@ -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 `Buffer`. URLs are not supported — fetch the content first and pass the bytes.',
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: 'Filename for the uploaded file.',
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.88",
3
+ "version": "7.0.89",
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.70",
46
- "@ai-sdk/provider": "4.0.9",
47
- "@ai-sdk/provider-utils": "5.0.34"
45
+ "@ai-sdk/gateway": "4.0.71",
46
+ "@ai-sdk/provider": "4.0.10",
47
+ "@ai-sdk/provider-utils": "5.0.35"
48
48
  },
49
49
  "devDependencies": {
50
- "@ai-sdk/amazon-bedrock": "5.0.70",
51
- "@ai-sdk/deepseek": "3.0.37",
52
- "@ai-sdk/google": "4.0.60",
53
- "@ai-sdk/groq": "4.0.35",
54
- "@ai-sdk/huggingface": "2.0.41",
55
- "@ai-sdk/moonshotai": "3.0.43",
56
- "@ai-sdk/openai": "4.0.54",
50
+ "@ai-sdk/amazon-bedrock": "5.0.71",
51
+ "@ai-sdk/deepseek": "3.0.38",
52
+ "@ai-sdk/google": "4.0.61",
53
+ "@ai-sdk/groq": "4.0.36",
54
+ "@ai-sdk/huggingface": "2.0.42",
55
+ "@ai-sdk/moonshotai": "3.0.44",
56
+ "@ai-sdk/openai": "4.0.55",
57
57
  "@ai-sdk/test-server": "2.0.1",
58
- "@ai-sdk/xai": "4.0.51",
58
+ "@ai-sdk/xai": "4.0.52",
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
- * @param filename - Optional filename for the uploaded file.
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 and optional metadata.
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
- : (detectMediaType({ data: data.data }) ??
62
- (isLikelyText(data.data) ? 'text/plain' : 'application/octet-stream')));
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
- const filesApi: FilesV4 =
65
- 'uploadFile' in api
66
- ? api
67
- : typeof api.files === 'function'
68
- ? api.files()
69
- : (() => {
70
- throw new Error(
71
- 'The provider does not support file uploads. Make sure it exposes a files() method.',
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
- const result = await filesApi.uploadFile({
76
- data,
77
- mediaType,
78
- filename,
79
- providerOptions,
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
  }