Skip to content

Commit

Permalink
feat(api): add uploads endpoints (#946)
Browse files Browse the repository at this point in the history
  • Loading branch information
stainless-app[bot] authored and Stainless Bot committed Jul 22, 2024
1 parent 7ac10dd commit 8709ceb
Show file tree
Hide file tree
Showing 10 changed files with 377 additions and 2 deletions.
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
configured_endpoints: 64
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-518ca6c60061d3e8bc0971facf40d752f2aea62e3522cc168ad29a1f29cab3dd.yml
configured_endpoints: 68
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-77cfff37114bc9f141c7e6107eb5f1b38d8cc99bc3d4ce03a066db2b6b649c69.yml
22 changes: 22 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,25 @@ Methods:
- <code title="get /batches/{batch_id}">client.batches.<a href="./src/resources/batches.ts">retrieve</a>(batchId) -> Batch</code>
- <code title="get /batches">client.batches.<a href="./src/resources/batches.ts">list</a>({ ...params }) -> BatchesPage</code>
- <code title="post /batches/{batch_id}/cancel">client.batches.<a href="./src/resources/batches.ts">cancel</a>(batchId) -> Batch</code>

# Uploads

Types:

- <code><a href="./src/resources/uploads/uploads.ts">Upload</a></code>

Methods:

- <code title="post /uploads">client.uploads.<a href="./src/resources/uploads/uploads.ts">create</a>({ ...params }) -> Upload</code>
- <code title="post /uploads/{upload_id}/cancel">client.uploads.<a href="./src/resources/uploads/uploads.ts">cancel</a>(uploadId) -> Upload</code>
- <code title="post /uploads/{upload_id}/complete">client.uploads.<a href="./src/resources/uploads/uploads.ts">complete</a>(uploadId, { ...params }) -> Upload</code>

## Parts

Types:

- <code><a href="./src/resources/uploads/parts.ts">UploadPart</a></code>

Methods:

- <code title="post /uploads/{upload_id}/parts">client.uploads.parts.<a href="./src/resources/uploads/parts.ts">create</a>(uploadId, { ...params }) -> UploadPart</code>
6 changes: 6 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export class OpenAI extends Core.APIClient {
fineTuning: API.FineTuning = new API.FineTuning(this);
beta: API.Beta = new API.Beta(this);
batches: API.Batches = new API.Batches(this);
uploads: API.Uploads = new API.Uploads(this);

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

export import Uploads = API.Uploads;
export import Upload = API.Upload;
export import UploadCreateParams = API.UploadCreateParams;
export import UploadCompleteParams = API.UploadCompleteParams;

export import ErrorObject = API.ErrorObject;
export import FunctionDefinition = API.FunctionDefinition;
export import FunctionParameters = API.FunctionParameters;
Expand Down
1 change: 1 addition & 0 deletions src/resources/chat/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,7 @@ export interface ChatCompletionCreateParamsBase {
* exhausted.
* - If set to 'default', the request will be processed using the default service
* tier with a lower uptime SLA and no latency guarentee.
* - When not set, the default behavior is 'auto'.
*
* When this parameter is set, the response body will include the `service_tier`
* utilized.
Expand Down
1 change: 1 addition & 0 deletions src/resources/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ export {
} from './images';
export { Model, ModelDeleted, ModelsPage, Models } from './models';
export { Moderation, ModerationCreateResponse, ModerationCreateParams, Moderations } from './moderations';
export { Upload, UploadCreateParams, UploadCompleteParams, Uploads } from './uploads/uploads';
4 changes: 4 additions & 0 deletions src/resources/uploads/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

export { Upload, UploadCreateParams, UploadCompleteParams, Uploads } from './uploads';
export { UploadPart, PartCreateParams, Parts } from './parts';
68 changes: 68 additions & 0 deletions src/resources/uploads/parts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

import { APIResource } from '../../resource';
import * as Core from '../../core';
import * as PartsAPI from './parts';

export class Parts extends APIResource {
/**
* Adds a
* [Part](https://platform.openai.com/docs/api-reference/uploads/part-object) to an
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object.
* A Part represents a chunk of bytes from the file you are trying to upload.
*
* Each Part can be at most 64 MB, and you can add Parts until you hit the Upload
* maximum of 8 GB.
*
* It is possible to add multiple Parts in parallel. You can decide the intended
* order of the Parts when you
* [complete the Upload](https://platform.openai.com/docs/api-reference/uploads/complete).
*/
create(
uploadId: string,
body: PartCreateParams,
options?: Core.RequestOptions,
): Core.APIPromise<UploadPart> {
return this._client.post(
`/uploads/${uploadId}/parts`,
Core.multipartFormRequestOptions({ body, ...options }),
);
}
}

/**
* The upload Part represents a chunk of bytes we can add to an Upload object.
*/
export interface UploadPart {
/**
* The upload Part unique identifier, which can be referenced in API endpoints.
*/
id: string;

/**
* The Unix timestamp (in seconds) for when the Part was created.
*/
created_at: number;

/**
* The object type, which is always `upload.part`.
*/
object: 'upload.part';

/**
* The ID of the Upload object that this Part was added to.
*/
upload_id: string;
}

export interface PartCreateParams {
/**
* The chunk of bytes for this Part.
*/
data: Core.Uploadable;
}

export namespace Parts {
export import UploadPart = PartsAPI.UploadPart;
export import PartCreateParams = PartsAPI.PartCreateParams;
}
169 changes: 169 additions & 0 deletions src/resources/uploads/uploads.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

import { APIResource } from '../../resource';
import * as Core from '../../core';
import * as UploadsAPI from './uploads';
import * as FilesAPI from '../files';
import * as PartsAPI from './parts';

export class Uploads extends APIResource {
parts: PartsAPI.Parts = new PartsAPI.Parts(this._client);

/**
* Creates an intermediate
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object
* that you can add
* [Parts](https://platform.openai.com/docs/api-reference/uploads/part-object) to.
* Currently, an Upload can accept at most 8 GB in total and expires after an hour
* after you create it.
*
* Once you complete the Upload, we will create a
* [File](https://platform.openai.com/docs/api-reference/files/object) object that
* contains all the parts you uploaded. This File is usable in the rest of our
* platform as a regular File object.
*
* For certain `purpose`s, the correct `mime_type` must be specified. Please refer
* to documentation for the supported MIME types for your use case:
*
* - [Assistants](https://platform.openai.com/docs/assistants/tools/file-search/supported-files)
*
* For guidance on the proper filename extensions for each purpose, please follow
* the documentation on
* [creating a File](https://platform.openai.com/docs/api-reference/files/create).
*/
create(body: UploadCreateParams, options?: Core.RequestOptions): Core.APIPromise<Upload> {
return this._client.post('/uploads', { body, ...options });
}

/**
* Cancels the Upload. No Parts may be added after an Upload is cancelled.
*/
cancel(uploadId: string, options?: Core.RequestOptions): Core.APIPromise<Upload> {
return this._client.post(`/uploads/${uploadId}/cancel`, options);
}

/**
* Completes the
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object).
*
* Within the returned Upload object, there is a nested
* [File](https://platform.openai.com/docs/api-reference/files/object) object that
* is ready to use in the rest of the platform.
*
* You can specify the order of the Parts by passing in an ordered list of the Part
* IDs.
*
* The number of bytes uploaded upon completion must match the number of bytes
* initially specified when creating the Upload object. No Parts may be added after
* an Upload is completed.
*/
complete(
uploadId: string,
body: UploadCompleteParams,
options?: Core.RequestOptions,
): Core.APIPromise<Upload> {
return this._client.post(`/uploads/${uploadId}/complete`, { body, ...options });
}
}

/**
* The Upload object can accept byte chunks in the form of Parts.
*/
export interface Upload {
/**
* The Upload unique identifier, which can be referenced in API endpoints.
*/
id: string;

/**
* The intended number of bytes to be uploaded.
*/
bytes: number;

/**
* The Unix timestamp (in seconds) for when the Upload was created.
*/
created_at: number;

/**
* The Unix timestamp (in seconds) for when the Upload was created.
*/
expires_at: number;

/**
* The name of the file to be uploaded.
*/
filename: string;

/**
* The object type, which is always "upload".
*/
object: 'upload';

/**
* The intended purpose of the file.
* [Please refer here](https://platform.openai.com/docs/api-reference/files/object#files/object-purpose)
* for acceptable values.
*/
purpose: string;

/**
* The status of the Upload.
*/
status: 'pending' | 'completed' | 'cancelled' | 'expired';

/**
* The ready File object after the Upload is completed.
*/
file?: FilesAPI.FileObject | null;
}

export interface UploadCreateParams {
/**
* The number of bytes in the file you are uploading.
*/
bytes: number;

/**
* The name of the file to upload.
*/
filename: string;

/**
* The MIME type of the file.
*
* This must fall within the supported MIME types for your file purpose. See the
* supported MIME types for assistants and vision.
*/
mime_type: string;

/**
* The intended purpose of the uploaded file.
*
* See the
* [documentation on File purposes](https://platform.openai.com/docs/api-reference/files/create#files-create-purpose).
*/
purpose: 'assistants' | 'batch' | 'fine-tune' | 'vision';
}

export interface UploadCompleteParams {
/**
* The ordered list of Part IDs.
*/
part_ids: Array<string>;

/**
* The optional md5 checksum for the file contents to verify if the bytes uploaded
* matches what you expect.
*/
md5?: string;
}

export namespace Uploads {
export import Upload = UploadsAPI.Upload;
export import UploadCreateParams = UploadsAPI.UploadCreateParams;
export import UploadCompleteParams = UploadsAPI.UploadCompleteParams;
export import Parts = PartsAPI.Parts;
export import UploadPart = PartsAPI.UploadPart;
export import PartCreateParams = PartsAPI.PartCreateParams;
}
30 changes: 30 additions & 0 deletions tests/api-resources/uploads/parts.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

import OpenAI, { toFile } from 'openai';
import { Response } from 'node-fetch';

const openai = new OpenAI({
apiKey: 'My API Key',
baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
});

describe('resource parts', () => {
test('create: only required params', async () => {
const responsePromise = openai.uploads.parts.create('upload_abc123', {
data: await toFile(Buffer.from('# my file contents'), 'README.md'),
});
const rawResponse = await responsePromise.asResponse();
expect(rawResponse).toBeInstanceOf(Response);
const response = await responsePromise;
expect(response).not.toBeInstanceOf(Response);
const dataAndResponse = await responsePromise.withResponse();
expect(dataAndResponse.data).toBe(response);
expect(dataAndResponse.response).toBe(rawResponse);
});

test('create: required and optional params', async () => {
const response = await openai.uploads.parts.create('upload_abc123', {
data: await toFile(Buffer.from('# my file contents'), 'README.md'),
});
});
});
Loading

0 comments on commit 8709ceb

Please sign in to comment.