diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7f5d28dff..fb1cbfe23 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.44.0" + ".": "4.45.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index ecdbfdb14..149d41da9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 4.45.0 (2024-05-11) + +Full Changelog: [v4.44.0...v4.45.0](https://github.com/openai/openai-node/compare/v4.44.0...v4.45.0) + +### Features + +* **azure:** batch api ([#839](https://github.com/openai/openai-node/issues/839)) ([e279f8c](https://github.com/openai/openai-node/commit/e279f8c51aa80cb913ccb6df647407bea1f2f071)) + + +### Chores + +* **dependency:** bumped Next.js version ([#836](https://github.com/openai/openai-node/issues/836)) ([babb140](https://github.com/openai/openai-node/commit/babb1404751059bdd171b792d03fd21272dd8f8b)) +* **docs:** add SECURITY.md ([#838](https://github.com/openai/openai-node/issues/838)) ([6e556d9](https://github.com/openai/openai-node/commit/6e556d9e12341155cc13fe226ab110d63858370e)) + ## 4.44.0 (2024-05-09) Full Changelog: [v4.43.0...v4.44.0](https://github.com/openai/openai-node/compare/v4.43.0...v4.44.0) diff --git a/README.md b/README.md index 397bb2185..e81093bbe 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.44.0/mod.ts'; +import OpenAI from 'https://deno.land/x/openai@v4.45.0/mod.ts'; ``` diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..c54acaf33 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,29 @@ +# Security Policy + +## Reporting Security Issues + +This SDK is generated by [Stainless Software Inc](http://stainlessapi.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. + +To report a security issue, please contact the Stainless team at security@stainlessapi.com. + +## Responsible Disclosure + +We appreciate the efforts of security researchers and individuals who help us maintain the security of +SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible +disclosure practices by allowing us a reasonable amount of time to investigate and address the issue +before making any information public. + +## Reporting Non-SDK Related Security Issues + +If you encounter security issues that are not directly related to SDKs but pertain to the services +or products provided by OpenAI please follow the respective company's security reporting guidelines. + +### OpenAI Terms and Policies + +Our Security Policy can be found at [Security Policy URL](https://openai.com/policies/coordinated-vulnerability-disclosure-policy). + +Please contact disclosure@openai.com for any questions or concerns regarding security of our services. + +--- + +Thank you for helping us keep the SDKs and systems they interact with secure. diff --git a/ecosystem-tests/vercel-edge/package-lock.json b/ecosystem-tests/vercel-edge/package-lock.json index fdfe2952d..bc820a010 100644 --- a/ecosystem-tests/vercel-edge/package-lock.json +++ b/ecosystem-tests/vercel-edge/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "dependencies": { "ai": "2.1.34", - "next": "13.5.6", + "next": "14.1.1", "react": "18.2.0", "react-dom": "18.2.0" }, @@ -1180,14 +1180,14 @@ } }, "node_modules/@next/env": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.6.tgz", - "integrity": "sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==" + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.1.tgz", + "integrity": "sha512-7CnQyD5G8shHxQIIg3c7/pSeYFeMhsNbpU/bmvH7ZnDql7mNRgg8O2JZrhrc/soFnfBnKP4/xXNiiSIPn2w8gA==" }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz", - "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.1.tgz", + "integrity": "sha512-yDjSFKQKTIjyT7cFv+DqQfW5jsD+tVxXTckSe1KIouKk75t1qZmj/mV3wzdmFb0XHVGtyRjDMulfVG8uCKemOQ==", "cpu": [ "arm64" ], @@ -1200,9 +1200,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz", - "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.1.tgz", + "integrity": "sha512-KCQmBL0CmFmN8D64FHIZVD9I4ugQsDBBEJKiblXGgwn7wBCSe8N4Dx47sdzl4JAg39IkSN5NNrr8AniXLMb3aw==", "cpu": [ "x64" ], @@ -1215,9 +1215,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz", - "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.1.tgz", + "integrity": "sha512-YDQfbWyW0JMKhJf/T4eyFr4b3tceTorQ5w2n7I0mNVTFOvu6CGEzfwT3RSAQGTi/FFMTFcuspPec/7dFHuP7Eg==", "cpu": [ "arm64" ], @@ -1230,9 +1230,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz", - "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.1.tgz", + "integrity": "sha512-fiuN/OG6sNGRN/bRFxRvV5LyzLB8gaL8cbDH5o3mEiVwfcMzyE5T//ilMmaTrnA8HLMS6hoz4cHOu6Qcp9vxgQ==", "cpu": [ "arm64" ], @@ -1245,9 +1245,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz", - "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.1.tgz", + "integrity": "sha512-rv6AAdEXoezjbdfp3ouMuVqeLjE1Bin0AuE6qxE6V9g3Giz5/R3xpocHoAi7CufRR+lnkuUjRBn05SYJ83oKNQ==", "cpu": [ "x64" ], @@ -1260,9 +1260,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz", - "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.1.tgz", + "integrity": "sha512-YAZLGsaNeChSrpz/G7MxO3TIBLaMN8QWMr3X8bt6rCvKovwU7GqQlDu99WdvF33kI8ZahvcdbFsy4jAFzFX7og==", "cpu": [ "x64" ], @@ -1275,9 +1275,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz", - "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.1.tgz", + "integrity": "sha512-1L4mUYPBMvVDMZg1inUYyPvFSduot0g73hgfD9CODgbr4xiTYe0VOMTZzaRqYJYBA9mana0x4eaAaypmWo1r5A==", "cpu": [ "arm64" ], @@ -1290,9 +1290,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz", - "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.1.tgz", + "integrity": "sha512-jvIE9tsuj9vpbbXlR5YxrghRfMuG0Qm/nZ/1KDHc+y6FpnZ/apsgh+G6t15vefU0zp3WSpTMIdXRUsNl/7RSuw==", "cpu": [ "ia32" ], @@ -1305,9 +1305,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz", - "integrity": "sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.1.tgz", + "integrity": "sha512-S6K6EHDU5+1KrBDLko7/c1MNy/Ya73pIAmvKeFwsF4RmBFJSO7/7YeD4FnZ4iBdzE69PpQ4sOMU9ORKeNuxe8A==", "cpu": [ "x64" ], @@ -2566,9 +2566,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001524", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz", - "integrity": "sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA==", + "version": "1.0.30001617", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001617.tgz", + "integrity": "sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==", "funding": [ { "type": "opencollective", @@ -3780,11 +3780,6 @@ "node": ">= 6" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" - }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -5066,34 +5061,34 @@ "dev": true }, "node_modules/next": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/next/-/next-13.5.6.tgz", - "integrity": "sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/next/-/next-14.1.1.tgz", + "integrity": "sha512-McrGJqlGSHeaz2yTRPkEucxQKe5Zq7uPwyeHNmJaZNY4wx9E9QdxmTp310agFRoMuIYgQrCrT3petg13fSVOww==", "dependencies": { - "@next/env": "13.5.6", + "@next/env": "14.1.1", "@swc/helpers": "0.5.2", "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001406", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", "postcss": "8.4.31", - "styled-jsx": "5.1.1", - "watchpack": "2.4.0" + "styled-jsx": "5.1.1" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=16.14.0" + "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.5.6", - "@next/swc-darwin-x64": "13.5.6", - "@next/swc-linux-arm64-gnu": "13.5.6", - "@next/swc-linux-arm64-musl": "13.5.6", - "@next/swc-linux-x64-gnu": "13.5.6", - "@next/swc-linux-x64-musl": "13.5.6", - "@next/swc-win32-arm64-msvc": "13.5.6", - "@next/swc-win32-ia32-msvc": "13.5.6", - "@next/swc-win32-x64-msvc": "13.5.6" + "@next/swc-darwin-arm64": "14.1.1", + "@next/swc-darwin-x64": "14.1.1", + "@next/swc-linux-arm64-gnu": "14.1.1", + "@next/swc-linux-arm64-musl": "14.1.1", + "@next/swc-linux-x64-gnu": "14.1.1", + "@next/swc-linux-x64-musl": "14.1.1", + "@next/swc-win32-arm64-msvc": "14.1.1", + "@next/swc-win32-ia32-msvc": "14.1.1", + "@next/swc-win32-x64-msvc": "14.1.1" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -6554,18 +6549,6 @@ "makeerror": "1.0.12" } }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/web-vitals": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-0.2.4.tgz", diff --git a/ecosystem-tests/vercel-edge/package.json b/ecosystem-tests/vercel-edge/package.json index 48223796c..4c75dd4fd 100644 --- a/ecosystem-tests/vercel-edge/package.json +++ b/ecosystem-tests/vercel-edge/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "ai": "2.1.34", - "next": "13.5.6", + "next": "14.1.1", "react": "18.2.0", "react-dom": "18.2.0" }, diff --git a/examples/package.json b/examples/package.json index 3b27b221f..04ed507b9 100644 --- a/examples/package.json +++ b/examples/package.json @@ -7,7 +7,7 @@ "private": true, "dependencies": { "express": "^4.18.2", - "next": "^13.5.5", + "next": "^14.1.1", "openai": "file:..", "zod-to-json-schema": "^3.21.4" }, diff --git a/package.json b/package.json index e70c0fd09..c51375344 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openai", - "version": "4.44.0", + "version": "4.45.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 015d307ea..0461f0f3f 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.44.0/mod.ts"; +import OpenAI from "https://deno.land/x/openai@v4.45.0/mod.ts"; const client = new OpenAI(); \`\`\` diff --git a/src/index.ts b/src/index.ts index b146a7bab..f5c8a0fe1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -346,6 +346,7 @@ export interface AzureClientOptions extends ClientOptions { /** API Client for interfacing with the Azure OpenAI API. */ export class AzureOpenAI extends OpenAI { private _azureADTokenProvider: (() => Promise) | undefined; + private _deployment: string | undefined; apiVersion: string = ''; /** * API Client for interfacing with the Azure OpenAI API. @@ -412,11 +413,7 @@ export class AzureOpenAI extends OpenAI { ); } - if (deployment) { - baseURL = `${endpoint}/openai/deployments/${deployment}`; - } else { - baseURL = `${endpoint}/openai`; - } + baseURL = `${endpoint}/openai`; } else { if (endpoint) { throw new Errors.OpenAIError('baseURL and endpoint are mutually exclusive'); @@ -432,6 +429,7 @@ export class AzureOpenAI extends OpenAI { this._azureADTokenProvider = azureADTokenProvider; this.apiVersion = apiVersion; + this._deployment = deployment; } override buildRequest(options: Core.FinalRequestOptions): { @@ -443,7 +441,7 @@ export class AzureOpenAI extends OpenAI { if (!Core.isObj(options.body)) { throw new Error('Expected request body to be an object'); } - const model = options.body['model']; + const model = this._deployment || options.body['model']; delete options.body['model']; if (model !== undefined && !this.baseURL.includes('/deployments')) { options.path = `/deployments/${model}${options.path}`; @@ -494,6 +492,7 @@ const _deployments_endpoints = new Set([ '/audio/translations', '/audio/speech', '/images/generations', + '/batches', ]); const API_KEY_SENTINEL = ''; diff --git a/src/version.ts b/src/version.ts index 4ebba76ed..2ebf697cb 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '4.44.0'; // x-release-please-version +export const VERSION = '4.45.0'; // x-release-please-version diff --git a/tests/lib/azure.test.ts b/tests/lib/azure.test.ts index 4895273be..32b59ae33 100644 --- a/tests/lib/azure.test.ts +++ b/tests/lib/azure.test.ts @@ -4,6 +4,8 @@ import { Headers } from 'openai/core'; import defaultFetch, { Response, type RequestInit, type RequestInfo } from 'node-fetch'; const apiVersion = '2024-02-15-preview'; +const deployment = 'deployment'; +const model = 'unused model'; describe('instantiate azure client', () => { const env = process.env; @@ -275,6 +277,278 @@ describe('instantiate azure client', () => { describe('azure request building', () => { const client = new AzureOpenAI({ baseURL: 'https://example.com', apiKey: 'My API Key', apiVersion }); + describe('model to deployment mapping', function () { + const testFetch = async (url: RequestInfo): Promise => { + return new Response(JSON.stringify({ url }), { headers: { 'content-type': 'application/json' } }); + }; + describe('with client-level deployment', function () { + const client = new AzureOpenAI({ + endpoint: 'https://example.com', + apiKey: 'My API Key', + apiVersion, + deployment, + fetch: testFetch, + }); + + test('handles Batch', async () => { + expect( + await client.batches.create({ + completion_window: '24h', + endpoint: '/v1/chat/completions', + input_file_id: 'file-id', + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/batches?api-version=${apiVersion}`, + }); + }); + + test('handles completions', async () => { + expect( + await client.completions.create({ + model, + prompt: 'prompt', + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/completions?api-version=${apiVersion}`, + }); + }); + + test('handles chat completions', async () => { + expect( + await client.chat.completions.create({ + model, + messages: [{ role: 'system', content: 'Hello' }], + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/chat/completions?api-version=${apiVersion}`, + }); + }); + + test('handles embeddings', async () => { + expect( + await client.embeddings.create({ + model, + input: 'input', + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/embeddings?api-version=${apiVersion}`, + }); + }); + + test('handles audio translations', async () => { + expect( + await client.audio.translations.create({ + model, + file: { url: 'https://example.com', blob: () => 0 as any }, + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/audio/translations?api-version=${apiVersion}`, + }); + }); + + test('handles audio transcriptions', async () => { + expect( + await client.audio.transcriptions.create({ + model, + file: { url: 'https://example.com', blob: () => 0 as any }, + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/audio/transcriptions?api-version=${apiVersion}`, + }); + }); + + test('handles text to speech', async () => { + expect( + await ( + await client.audio.speech.create({ + model, + input: '', + voice: 'alloy', + }) + ).json(), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/audio/speech?api-version=${apiVersion}`, + }); + }); + + test('handles image generation', async () => { + expect( + await client.images.generate({ + model, + prompt: 'prompt', + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/images/generations?api-version=${apiVersion}`, + }); + }); + + test('handles assistants', async () => { + expect( + await client.beta.assistants.create({ + model, + }), + ).toStrictEqual({ + url: `https://example.com/openai/assistants?api-version=${apiVersion}`, + }); + }); + + test('handles files', async () => { + expect( + await client.files.create({ + file: { url: 'https://example.com', blob: () => 0 as any }, + purpose: 'assistants', + }), + ).toStrictEqual({ + url: `https://example.com/openai/files?api-version=${apiVersion}`, + }); + }); + + test('handles fine tuning', async () => { + expect( + await client.fineTuning.jobs.create({ + model, + training_file: '', + }), + ).toStrictEqual({ + url: `https://example.com/openai/fine_tuning/jobs?api-version=${apiVersion}`, + }); + }); + }); + + describe('with no client-level deployment', function () { + const client = new AzureOpenAI({ + endpoint: 'https://example.com', + apiKey: 'My API Key', + apiVersion, + fetch: testFetch, + }); + + test('Batch is not handled', async () => { + expect( + await client.batches.create({ + completion_window: '24h', + endpoint: '/v1/chat/completions', + input_file_id: 'file-id', + }), + ).toStrictEqual({ + url: `https://example.com/openai/batches?api-version=${apiVersion}`, + }); + }); + + test('handles completions', async () => { + expect( + await client.completions.create({ + model: deployment, + prompt: 'prompt', + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/completions?api-version=${apiVersion}`, + }); + }); + + test('handles chat completions', async () => { + expect( + await client.chat.completions.create({ + model: deployment, + messages: [{ role: 'system', content: 'Hello' }], + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/chat/completions?api-version=${apiVersion}`, + }); + }); + + test('handles embeddings', async () => { + expect( + await client.embeddings.create({ + model: deployment, + input: 'input', + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/embeddings?api-version=${apiVersion}`, + }); + }); + + test('Audio translations is not handled', async () => { + expect( + await client.audio.translations.create({ + model: deployment, + file: { url: 'https://example.com', blob: () => 0 as any }, + }), + ).toStrictEqual({ + url: `https://example.com/openai/audio/translations?api-version=${apiVersion}`, + }); + }); + + test('Audio transcriptions is not handled', async () => { + expect( + await client.audio.transcriptions.create({ + model: deployment, + file: { url: 'https://example.com', blob: () => 0 as any }, + }), + ).toStrictEqual({ + url: `https://example.com/openai/audio/transcriptions?api-version=${apiVersion}`, + }); + }); + + test('handles text to speech', async () => { + expect( + await ( + await client.audio.speech.create({ + model: deployment, + input: '', + voice: 'alloy', + }) + ).json(), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/audio/speech?api-version=${apiVersion}`, + }); + }); + + test('handles image generation', async () => { + expect( + await client.images.generate({ + model: deployment, + prompt: 'prompt', + }), + ).toStrictEqual({ + url: `https://example.com/openai/deployments/${deployment}/images/generations?api-version=${apiVersion}`, + }); + }); + + test('handles assistants', async () => { + expect( + await client.beta.assistants.create({ + model, + }), + ).toStrictEqual({ + url: `https://example.com/openai/assistants?api-version=${apiVersion}`, + }); + }); + + test('handles files', async () => { + expect( + await client.files.create({ + file: { url: 'https://example.com', blob: () => 0 as any }, + purpose: 'assistants', + }), + ).toStrictEqual({ + url: `https://example.com/openai/files?api-version=${apiVersion}`, + }); + }); + + test('handles fine tuning', async () => { + expect( + await client.fineTuning.jobs.create({ + model, + training_file: '', + }), + ).toStrictEqual({ + url: `https://example.com/openai/fine_tuning/jobs?api-version=${apiVersion}`, + }); + }); + }); + }); + describe('Content-Length', () => { test('handles multi-byte characters', () => { const { req } = client.buildRequest({ path: '/foo', method: 'post', body: { value: '—' } });