diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 7a0305307..541459357 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "4.62.1"
+ ".": "4.63.0"
}
diff --git a/.stats.yml b/.stats.yml
index 2fc39385e..0151c5a10 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,2 +1,2 @@
configured_endpoints: 68
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-ff407aa10917e62f2b0c12d1ad2c4f1258ed083bd45753c70eaaf5b1cf8356ae.yml
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-de1981b64ac229493473670d618500c6362c195f1057eb7de00bd1bc9184fbd5.yml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cdf113343..a9677f6d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## 4.63.0 (2024-09-20)
+
+Full Changelog: [v4.62.1...v4.63.0](https://github.com/openai/openai-node/compare/v4.62.1...v4.63.0)
+
+### Features
+
+* **client:** send retry count header ([#1087](https://github.com/openai/openai-node/issues/1087)) ([7bcebc0](https://github.com/openai/openai-node/commit/7bcebc0e3965c2decd1dffb1e67f5197260ca89e))
+
+
+### Chores
+
+* **types:** improve type name for embedding models ([#1089](https://github.com/openai/openai-node/issues/1089)) ([d6966d9](https://github.com/openai/openai-node/commit/d6966d9872a14b7fbee85a7bb1fae697852b8ce0))
+
## 4.62.1 (2024-09-18)
Full Changelog: [v4.62.0...v4.62.1](https://github.com/openai/openai-node/compare/v4.62.0...v4.62.1)
diff --git a/README.md b/README.md
index 55e6c291d..b2a3bc4b4 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ You can import in Deno via:
```ts
-import OpenAI from 'https://deno.land/x/openai@v4.62.1/mod.ts';
+import OpenAI from 'https://deno.land/x/openai@v4.63.0/mod.ts';
```
diff --git a/api.md b/api.md
index 7fb8f86a6..f38ab69be 100644
--- a/api.md
+++ b/api.md
@@ -64,6 +64,7 @@ Types:
- CreateEmbeddingResponse
- Embedding
+- EmbeddingModel
Methods:
diff --git a/package.json b/package.json
index 146f1e6f9..831169e2d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "openai",
- "version": "4.62.1",
+ "version": "4.63.0",
"description": "The official TypeScript library for the OpenAI API",
"author": "OpenAI ",
"types": "dist/index.d.ts",
diff --git a/scripts/build-deno b/scripts/build-deno
index ef51b1e45..f006e3f3f 100755
--- a/scripts/build-deno
+++ b/scripts/build-deno
@@ -16,7 +16,7 @@ This is a build produced from https://github.com/openai/openai-node – please g
Usage:
\`\`\`ts
-import OpenAI from "https://deno.land/x/openai@v4.62.1/mod.ts";
+import OpenAI from "https://deno.land/x/openai@v4.63.0/mod.ts";
const client = new OpenAI();
\`\`\`
diff --git a/src/core.ts b/src/core.ts
index 90714d3ce..877ae8de1 100644
--- a/src/core.ts
+++ b/src/core.ts
@@ -308,7 +308,10 @@ export abstract class APIClient {
return null;
}
- buildRequest(options: FinalRequestOptions): { req: RequestInit; url: string; timeout: number } {
+ buildRequest(
+ options: FinalRequestOptions,
+ { retryCount = 0 }: { retryCount?: number } = {},
+ ): { req: RequestInit; url: string; timeout: number } {
const { method, path, query, headers: headers = {} } = options;
const body =
@@ -340,7 +343,7 @@ export abstract class APIClient {
headers[this.idempotencyHeader] = options.idempotencyKey;
}
- const reqHeaders = this.buildHeaders({ options, headers, contentLength });
+ const reqHeaders = this.buildHeaders({ options, headers, contentLength, retryCount });
const req: RequestInit = {
method,
@@ -359,10 +362,12 @@ export abstract class APIClient {
options,
headers,
contentLength,
+ retryCount,
}: {
options: FinalRequestOptions;
headers: Record;
contentLength: string | null | undefined;
+ retryCount: number;
}): Record {
const reqHeaders: Record = {};
if (contentLength) {
@@ -378,6 +383,8 @@ export abstract class APIClient {
delete reqHeaders['content-type'];
}
+ reqHeaders['x-stainless-retry-count'] = String(retryCount);
+
this.validateHeaders(reqHeaders, headers);
return reqHeaders;
@@ -429,13 +436,14 @@ export abstract class APIClient {
retriesRemaining: number | null,
): Promise {
const options = await optionsInput;
+ const maxRetries = options.maxRetries ?? this.maxRetries;
if (retriesRemaining == null) {
- retriesRemaining = options.maxRetries ?? this.maxRetries;
+ retriesRemaining = maxRetries;
}
await this.prepareOptions(options);
- const { req, url, timeout } = this.buildRequest(options);
+ const { req, url, timeout } = this.buildRequest(options, { retryCount: maxRetries - retriesRemaining });
await this.prepareRequest(req, { url, options });
diff --git a/src/index.ts b/src/index.ts
index b52406f6c..7fed1dc8c 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -276,6 +276,7 @@ export namespace OpenAI {
export import Embeddings = API.Embeddings;
export import CreateEmbeddingResponse = API.CreateEmbeddingResponse;
export import Embedding = API.Embedding;
+ export import EmbeddingModel = API.EmbeddingModel;
export import EmbeddingCreateParams = API.EmbeddingCreateParams;
export import Files = API.Files;
diff --git a/src/resources/embeddings.ts b/src/resources/embeddings.ts
index f72b9308a..6d8e670a7 100644
--- a/src/resources/embeddings.ts
+++ b/src/resources/embeddings.ts
@@ -77,6 +77,8 @@ export interface Embedding {
object: 'embedding';
}
+export type EmbeddingModel = 'text-embedding-ada-002' | 'text-embedding-3-small' | 'text-embedding-3-large';
+
export interface EmbeddingCreateParams {
/**
* Input text to embed, encoded as a string or array of tokens. To embed multiple
@@ -96,7 +98,7 @@ export interface EmbeddingCreateParams {
* [Model overview](https://platform.openai.com/docs/models/overview) for
* descriptions of them.
*/
- model: (string & {}) | 'text-embedding-ada-002' | 'text-embedding-3-small' | 'text-embedding-3-large';
+ model: (string & {}) | EmbeddingModel;
/**
* The number of dimensions the resulting output embeddings should have. Only
@@ -121,5 +123,6 @@ export interface EmbeddingCreateParams {
export namespace Embeddings {
export import CreateEmbeddingResponse = EmbeddingsAPI.CreateEmbeddingResponse;
export import Embedding = EmbeddingsAPI.Embedding;
+ export import EmbeddingModel = EmbeddingsAPI.EmbeddingModel;
export import EmbeddingCreateParams = EmbeddingsAPI.EmbeddingCreateParams;
}
diff --git a/src/resources/index.ts b/src/resources/index.ts
index a78808584..68bd88a31 100644
--- a/src/resources/index.ts
+++ b/src/resources/index.ts
@@ -22,7 +22,13 @@ export {
CompletionCreateParamsStreaming,
Completions,
} from './completions';
-export { CreateEmbeddingResponse, Embedding, EmbeddingCreateParams, Embeddings } from './embeddings';
+export {
+ CreateEmbeddingResponse,
+ Embedding,
+ EmbeddingModel,
+ EmbeddingCreateParams,
+ Embeddings,
+} from './embeddings';
export {
FileContent,
FileDeleted,
diff --git a/src/version.ts b/src/version.ts
index 1cfad9ed4..ee209cb0e 100644
--- a/src/version.ts
+++ b/src/version.ts
@@ -1 +1 @@
-export const VERSION = '4.62.1'; // x-release-please-version
+export const VERSION = '4.63.0'; // x-release-please-version
diff --git a/tests/index.test.ts b/tests/index.test.ts
index cd5f2a0a9..a6fa97199 100644
--- a/tests/index.test.ts
+++ b/tests/index.test.ts
@@ -241,6 +241,31 @@ describe('retries', () => {
expect(count).toEqual(3);
});
+ test('retry count header', async () => {
+ let count = 0;
+ let capturedRequest: RequestInit | undefined;
+ const testFetch = async (url: RequestInfo, init: RequestInit = {}): Promise => {
+ count++;
+ if (count <= 2) {
+ return new Response(undefined, {
+ status: 429,
+ headers: {
+ 'Retry-After': '0.1',
+ },
+ });
+ }
+ capturedRequest = init;
+ return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
+ };
+
+ const client = new OpenAI({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 });
+
+ expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 });
+
+ expect((capturedRequest!.headers as Headers)['x-stainless-retry-count']).toEqual('2');
+ expect(count).toEqual(3);
+ });
+
test('retry on 429 with retry-after', async () => {
let count = 0;
const testFetch = async (url: RequestInfo, { signal }: RequestInit = {}): Promise => {