Skip to content

Commit c770e34

Browse files
feat(api): add uploads endpoints (#946)
1 parent a56fdb8 commit c770e34

File tree

10 files changed

+377
-2
lines changed

10 files changed

+377
-2
lines changed

.stats.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
configured_endpoints: 64
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-518ca6c60061d3e8bc0971facf40d752f2aea62e3522cc168ad29a1f29cab3dd.yml
1+
configured_endpoints: 68
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-77cfff37114bc9f141c7e6107eb5f1b38d8cc99bc3d4ce03a066db2b6b649c69.yml

api.md

+22
Original file line numberDiff line numberDiff line change
@@ -388,3 +388,25 @@ Methods:
388388
- <code title="get /batches/{batch_id}">client.batches.<a href="./src/resources/batches.ts">retrieve</a>(batchId) -> Batch</code>
389389
- <code title="get /batches">client.batches.<a href="./src/resources/batches.ts">list</a>({ ...params }) -> BatchesPage</code>
390390
- <code title="post /batches/{batch_id}/cancel">client.batches.<a href="./src/resources/batches.ts">cancel</a>(batchId) -> Batch</code>
391+
392+
# Uploads
393+
394+
Types:
395+
396+
- <code><a href="./src/resources/uploads/uploads.ts">Upload</a></code>
397+
398+
Methods:
399+
400+
- <code title="post /uploads">client.uploads.<a href="./src/resources/uploads/uploads.ts">create</a>({ ...params }) -> Upload</code>
401+
- <code title="post /uploads/{upload_id}/cancel">client.uploads.<a href="./src/resources/uploads/uploads.ts">cancel</a>(uploadId) -> Upload</code>
402+
- <code title="post /uploads/{upload_id}/complete">client.uploads.<a href="./src/resources/uploads/uploads.ts">complete</a>(uploadId, { ...params }) -> Upload</code>
403+
404+
## Parts
405+
406+
Types:
407+
408+
- <code><a href="./src/resources/uploads/parts.ts">UploadPart</a></code>
409+
410+
Methods:
411+
412+
- <code title="post /uploads/{upload_id}/parts">client.uploads.parts.<a href="./src/resources/uploads/parts.ts">create</a>(uploadId, { ...params }) -> UploadPart</code>

src/index.ts

+6
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ export class OpenAI extends Core.APIClient {
164164
fineTuning: API.FineTuning = new API.FineTuning(this);
165165
beta: API.Beta = new API.Beta(this);
166166
batches: API.Batches = new API.Batches(this);
167+
uploads: API.Uploads = new API.Uploads(this);
167168

168169
protected override defaultQuery(): Core.DefaultQuery | undefined {
169170
return this._options.defaultQuery;
@@ -309,6 +310,11 @@ export namespace OpenAI {
309310
export import BatchCreateParams = API.BatchCreateParams;
310311
export import BatchListParams = API.BatchListParams;
311312

313+
export import Uploads = API.Uploads;
314+
export import Upload = API.Upload;
315+
export import UploadCreateParams = API.UploadCreateParams;
316+
export import UploadCompleteParams = API.UploadCompleteParams;
317+
312318
export import ErrorObject = API.ErrorObject;
313319
export import FunctionDefinition = API.FunctionDefinition;
314320
export import FunctionParameters = API.FunctionParameters;

src/resources/chat/completions.ts

+1
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,7 @@ export interface ChatCompletionCreateParamsBase {
820820
* exhausted.
821821
* - If set to 'default', the request will be processed using the default service
822822
* tier with a lower uptime SLA and no latency guarentee.
823+
* - When not set, the default behavior is 'auto'.
823824
*
824825
* When this parameter is set, the response body will include the `service_tier`
825826
* utilized.

src/resources/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,4 @@ export {
4343
} from './images';
4444
export { Model, ModelDeleted, ModelsPage, Models } from './models';
4545
export { Moderation, ModerationCreateResponse, ModerationCreateParams, Moderations } from './moderations';
46+
export { Upload, UploadCreateParams, UploadCompleteParams, Uploads } from './uploads/uploads';

src/resources/uploads/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
export { Upload, UploadCreateParams, UploadCompleteParams, Uploads } from './uploads';
4+
export { UploadPart, PartCreateParams, Parts } from './parts';

src/resources/uploads/parts.ts

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
import { APIResource } from '../../resource';
4+
import * as Core from '../../core';
5+
import * as PartsAPI from './parts';
6+
7+
export class Parts extends APIResource {
8+
/**
9+
* Adds a
10+
* [Part](https://platform.openai.com/docs/api-reference/uploads/part-object) to an
11+
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object.
12+
* A Part represents a chunk of bytes from the file you are trying to upload.
13+
*
14+
* Each Part can be at most 64 MB, and you can add Parts until you hit the Upload
15+
* maximum of 8 GB.
16+
*
17+
* It is possible to add multiple Parts in parallel. You can decide the intended
18+
* order of the Parts when you
19+
* [complete the Upload](https://platform.openai.com/docs/api-reference/uploads/complete).
20+
*/
21+
create(
22+
uploadId: string,
23+
body: PartCreateParams,
24+
options?: Core.RequestOptions,
25+
): Core.APIPromise<UploadPart> {
26+
return this._client.post(
27+
`/uploads/${uploadId}/parts`,
28+
Core.multipartFormRequestOptions({ body, ...options }),
29+
);
30+
}
31+
}
32+
33+
/**
34+
* The upload Part represents a chunk of bytes we can add to an Upload object.
35+
*/
36+
export interface UploadPart {
37+
/**
38+
* The upload Part unique identifier, which can be referenced in API endpoints.
39+
*/
40+
id: string;
41+
42+
/**
43+
* The Unix timestamp (in seconds) for when the Part was created.
44+
*/
45+
created_at: number;
46+
47+
/**
48+
* The object type, which is always `upload.part`.
49+
*/
50+
object: 'upload.part';
51+
52+
/**
53+
* The ID of the Upload object that this Part was added to.
54+
*/
55+
upload_id: string;
56+
}
57+
58+
export interface PartCreateParams {
59+
/**
60+
* The chunk of bytes for this Part.
61+
*/
62+
data: Core.Uploadable;
63+
}
64+
65+
export namespace Parts {
66+
export import UploadPart = PartsAPI.UploadPart;
67+
export import PartCreateParams = PartsAPI.PartCreateParams;
68+
}

src/resources/uploads/uploads.ts

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
import { APIResource } from '../../resource';
4+
import * as Core from '../../core';
5+
import * as UploadsAPI from './uploads';
6+
import * as FilesAPI from '../files';
7+
import * as PartsAPI from './parts';
8+
9+
export class Uploads extends APIResource {
10+
parts: PartsAPI.Parts = new PartsAPI.Parts(this._client);
11+
12+
/**
13+
* Creates an intermediate
14+
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object
15+
* that you can add
16+
* [Parts](https://platform.openai.com/docs/api-reference/uploads/part-object) to.
17+
* Currently, an Upload can accept at most 8 GB in total and expires after an hour
18+
* after you create it.
19+
*
20+
* Once you complete the Upload, we will create a
21+
* [File](https://platform.openai.com/docs/api-reference/files/object) object that
22+
* contains all the parts you uploaded. This File is usable in the rest of our
23+
* platform as a regular File object.
24+
*
25+
* For certain `purpose`s, the correct `mime_type` must be specified. Please refer
26+
* to documentation for the supported MIME types for your use case:
27+
*
28+
* - [Assistants](https://platform.openai.com/docs/assistants/tools/file-search/supported-files)
29+
*
30+
* For guidance on the proper filename extensions for each purpose, please follow
31+
* the documentation on
32+
* [creating a File](https://platform.openai.com/docs/api-reference/files/create).
33+
*/
34+
create(body: UploadCreateParams, options?: Core.RequestOptions): Core.APIPromise<Upload> {
35+
return this._client.post('/uploads', { body, ...options });
36+
}
37+
38+
/**
39+
* Cancels the Upload. No Parts may be added after an Upload is cancelled.
40+
*/
41+
cancel(uploadId: string, options?: Core.RequestOptions): Core.APIPromise<Upload> {
42+
return this._client.post(`/uploads/${uploadId}/cancel`, options);
43+
}
44+
45+
/**
46+
* Completes the
47+
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object).
48+
*
49+
* Within the returned Upload object, there is a nested
50+
* [File](https://platform.openai.com/docs/api-reference/files/object) object that
51+
* is ready to use in the rest of the platform.
52+
*
53+
* You can specify the order of the Parts by passing in an ordered list of the Part
54+
* IDs.
55+
*
56+
* The number of bytes uploaded upon completion must match the number of bytes
57+
* initially specified when creating the Upload object. No Parts may be added after
58+
* an Upload is completed.
59+
*/
60+
complete(
61+
uploadId: string,
62+
body: UploadCompleteParams,
63+
options?: Core.RequestOptions,
64+
): Core.APIPromise<Upload> {
65+
return this._client.post(`/uploads/${uploadId}/complete`, { body, ...options });
66+
}
67+
}
68+
69+
/**
70+
* The Upload object can accept byte chunks in the form of Parts.
71+
*/
72+
export interface Upload {
73+
/**
74+
* The Upload unique identifier, which can be referenced in API endpoints.
75+
*/
76+
id: string;
77+
78+
/**
79+
* The intended number of bytes to be uploaded.
80+
*/
81+
bytes: number;
82+
83+
/**
84+
* The Unix timestamp (in seconds) for when the Upload was created.
85+
*/
86+
created_at: number;
87+
88+
/**
89+
* The Unix timestamp (in seconds) for when the Upload was created.
90+
*/
91+
expires_at: number;
92+
93+
/**
94+
* The name of the file to be uploaded.
95+
*/
96+
filename: string;
97+
98+
/**
99+
* The object type, which is always "upload".
100+
*/
101+
object: 'upload';
102+
103+
/**
104+
* The intended purpose of the file.
105+
* [Please refer here](https://platform.openai.com/docs/api-reference/files/object#files/object-purpose)
106+
* for acceptable values.
107+
*/
108+
purpose: string;
109+
110+
/**
111+
* The status of the Upload.
112+
*/
113+
status: 'pending' | 'completed' | 'cancelled' | 'expired';
114+
115+
/**
116+
* The ready File object after the Upload is completed.
117+
*/
118+
file?: FilesAPI.FileObject | null;
119+
}
120+
121+
export interface UploadCreateParams {
122+
/**
123+
* The number of bytes in the file you are uploading.
124+
*/
125+
bytes: number;
126+
127+
/**
128+
* The name of the file to upload.
129+
*/
130+
filename: string;
131+
132+
/**
133+
* The MIME type of the file.
134+
*
135+
* This must fall within the supported MIME types for your file purpose. See the
136+
* supported MIME types for assistants and vision.
137+
*/
138+
mime_type: string;
139+
140+
/**
141+
* The intended purpose of the uploaded file.
142+
*
143+
* See the
144+
* [documentation on File purposes](https://platform.openai.com/docs/api-reference/files/create#files-create-purpose).
145+
*/
146+
purpose: 'assistants' | 'batch' | 'fine-tune' | 'vision';
147+
}
148+
149+
export interface UploadCompleteParams {
150+
/**
151+
* The ordered list of Part IDs.
152+
*/
153+
part_ids: Array<string>;
154+
155+
/**
156+
* The optional md5 checksum for the file contents to verify if the bytes uploaded
157+
* matches what you expect.
158+
*/
159+
md5?: string;
160+
}
161+
162+
export namespace Uploads {
163+
export import Upload = UploadsAPI.Upload;
164+
export import UploadCreateParams = UploadsAPI.UploadCreateParams;
165+
export import UploadCompleteParams = UploadsAPI.UploadCompleteParams;
166+
export import Parts = PartsAPI.Parts;
167+
export import UploadPart = PartsAPI.UploadPart;
168+
export import PartCreateParams = PartsAPI.PartCreateParams;
169+
}
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
import OpenAI, { toFile } from 'openai';
4+
import { Response } from 'node-fetch';
5+
6+
const openai = new OpenAI({
7+
apiKey: 'My API Key',
8+
baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
9+
});
10+
11+
describe('resource parts', () => {
12+
test('create: only required params', async () => {
13+
const responsePromise = openai.uploads.parts.create('upload_abc123', {
14+
data: await toFile(Buffer.from('# my file contents'), 'README.md'),
15+
});
16+
const rawResponse = await responsePromise.asResponse();
17+
expect(rawResponse).toBeInstanceOf(Response);
18+
const response = await responsePromise;
19+
expect(response).not.toBeInstanceOf(Response);
20+
const dataAndResponse = await responsePromise.withResponse();
21+
expect(dataAndResponse.data).toBe(response);
22+
expect(dataAndResponse.response).toBe(rawResponse);
23+
});
24+
25+
test('create: required and optional params', async () => {
26+
const response = await openai.uploads.parts.create('upload_abc123', {
27+
data: await toFile(Buffer.from('# my file contents'), 'README.md'),
28+
});
29+
});
30+
});

0 commit comments

Comments
 (0)