diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 509abc6f1f..a25f0a9b1c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "6.37.0" + ".": "6.38.0" } diff --git a/.stats.yml b/.stats.yml index ff6b893527..6359ad0608 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 232 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai/openai-371f497afe4d6070f6e252e5febbe8f453c7058a8dff0c26a01b4d88442a4ac2.yml -openapi_spec_hash: d39f46e8fda45f77096448105efd175a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai/openai-50d816559ef0935e64d07789ff936a2b762e26ab0714a2fa6bc06d06d4484294.yml +openapi_spec_hash: c5d8f37edbf66c1fef627d787b4c54fd config_hash: b64135fff1fe9cf4069b9ecf59ae8b07 diff --git a/CHANGELOG.md b/CHANGELOG.md index f940b22a14..8f3c742da8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 6.38.0 (2026-05-13) + +Full Changelog: [v6.37.0...v6.38.0](https://github.com/openai/openai-node/compare/v6.37.0...v6.38.0) + +### Features + +* **api:** add service_tier parameter to responses compact method ([423e838](https://github.com/openai/openai-node/commit/423e838c498bd1b77f3b732cfc43c54fc5d261df)) + ## 6.37.0 (2026-05-07) Full Changelog: [v6.36.0...v6.37.0](https://github.com/openai/openai-node/compare/v6.36.0...v6.37.0) diff --git a/README.md b/README.md index 26b0dfa9eb..68cebbcb32 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ For secure, automated environments like cloud-managed Kubernetes, Azure, and GCP The `workloadIdentity` parameter is mutually exclusive with `apiKey`. +The required fields are `identityProviderId`, `serviceAccountId`, and `provider`. + ### Kubernetes (service account tokens) ```ts @@ -83,7 +85,6 @@ import { k8sServiceAccountTokenProvider } from 'openai/auth'; const client = new OpenAI({ workloadIdentity: { - clientId: 'your-client-id', identityProviderId: 'idp-123', serviceAccountId: 'sa-456', provider: k8sServiceAccountTokenProvider('/var/run/secrets/kubernetes.io/serviceaccount/token'), @@ -104,7 +105,6 @@ import { azureManagedIdentityTokenProvider } from 'openai/auth'; const client = new OpenAI({ workloadIdentity: { - clientId: 'your-client-id', identityProviderId: 'idp-123', serviceAccountId: 'sa-456', provider: azureManagedIdentityTokenProvider(), @@ -120,7 +120,6 @@ import { gcpIDTokenProvider } from 'openai/auth'; const client = new OpenAI({ workloadIdentity: { - clientId: 'your-client-id', identityProviderId: 'idp-123', serviceAccountId: 'sa-456', provider: gcpIDTokenProvider(), @@ -135,7 +134,6 @@ import OpenAI from 'openai'; const client = new OpenAI({ workloadIdentity: { - clientId: 'your-client-id', identityProviderId: 'idp-123', serviceAccountId: 'sa-456', provider: { @@ -156,7 +154,6 @@ import { k8sServiceAccountTokenProvider } from 'openai/auth'; const client = new OpenAI({ workloadIdentity: { - clientId: 'your-client-id', identityProviderId: 'idp-123', serviceAccountId: 'sa-456', provider: k8sServiceAccountTokenProvider('/var/token'), diff --git a/jsr.json b/jsr.json index 2939a44dc6..5ba8b00e38 100644 --- a/jsr.json +++ b/jsr.json @@ -1,6 +1,6 @@ { "name": "@openai/openai", - "version": "6.37.0", + "version": "6.38.0", "exports": { ".": "./index.ts", "./helpers/zod": "./helpers/zod.ts", diff --git a/package.json b/package.json index a6afab3fa7..b6eee5755b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openai", - "version": "6.37.0", + "version": "6.38.0", "description": "The official TypeScript library for the OpenAI API", "author": "OpenAI ", "types": "dist/index.d.ts", diff --git a/src/auth/types.ts b/src/auth/types.ts index b94e062730..05dbd90ea5 100644 --- a/src/auth/types.ts +++ b/src/auth/types.ts @@ -4,8 +4,8 @@ export interface SubjectTokenProvider { } export interface WorkloadIdentity { - /**A unique string that identifies the client.*/ - clientId: string; + /**Optional client identifier for token exchange compatibility.*/ + clientId?: string; /**Identity provider resource id in WIFAPI.*/ identityProviderId: string; diff --git a/src/auth/workload-identity-auth.ts b/src/auth/workload-identity-auth.ts index 31946709f9..a1a78502af 100644 --- a/src/auth/workload-identity-auth.ts +++ b/src/auth/workload-identity-auth.ts @@ -8,7 +8,7 @@ interface CachedToken { expiresAt: number; } -const SUBJECT_TOKEN_TYPES: Record = { +const SUBJECT_TOKEN_TYPES: Record = { jwt: 'urn:ietf:params:oauth:token-type:jwt', id: 'urn:ietf:params:oauth:token-type:id_token', }; @@ -54,20 +54,24 @@ export class WorkloadIdentityAuth { private async refreshToken(): Promise { const subjectToken = await this.config.provider.getToken(); + const body: Record = { + grant_type: TOKEN_EXCHANGE_GRANT_TYPE, + subject_token: subjectToken, + subject_token_type: SUBJECT_TOKEN_TYPES[this.config.provider.tokenType], + identity_provider_id: this.config.identityProviderId, + service_account_id: this.config.serviceAccountId, + }; + + if (this.config.clientId) { + body['client_id'] = this.config.clientId; + } const response = await this.fetch(this.tokenExchangeUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ - grant_type: TOKEN_EXCHANGE_GRANT_TYPE, - client_id: this.config.clientId, - subject_token: subjectToken, - subject_token_type: SUBJECT_TOKEN_TYPES[this.config.provider.tokenType], - identity_provider_id: this.config.identityProviderId, - service_account_id: this.config.serviceAccountId, - }), + body: JSON.stringify(body), }); if (!response.ok) { diff --git a/src/resources/responses/responses.ts b/src/resources/responses/responses.ts index 937f10f7cd..6de563e0b3 100644 --- a/src/resources/responses/responses.ts +++ b/src/resources/responses/responses.ts @@ -8035,6 +8035,11 @@ export interface ResponseCompactParams { * How long to retain a prompt cache entry created by this request. */ prompt_cache_retention?: 'in_memory' | '24h' | null; + + /** + * The service tier to use for this request. + */ + service_tier?: 'auto' | 'default' | 'flex' | 'priority' | null; } Responses.InputItems = InputItems; diff --git a/src/version.ts b/src/version.ts index b381c68ffd..1422fd54f2 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '6.37.0'; // x-release-please-version +export const VERSION = '6.38.0'; // x-release-please-version diff --git a/tests/api-resources/responses/responses.test.ts b/tests/api-resources/responses/responses.test.ts index f9162f41ae..aeee41b717 100644 --- a/tests/api-resources/responses/responses.test.ts +++ b/tests/api-resources/responses/responses.test.ts @@ -94,6 +94,7 @@ describe('resource responses', () => { previous_response_id: 'resp_123', prompt_cache_key: 'prompt_cache_key', prompt_cache_retention: 'in_memory', + service_tier: 'auto', }); }); }); diff --git a/tests/auth/workload-identity-auth.test.ts b/tests/auth/workload-identity-auth.test.ts index 8048454648..b479b81eab 100644 --- a/tests/auth/workload-identity-auth.test.ts +++ b/tests/auth/workload-identity-auth.test.ts @@ -18,7 +18,6 @@ describe('WorkloadIdentityAuth', () => { let fetchCallCount = 0; const config: WorkloadIdentity = { - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: { @@ -59,7 +58,6 @@ describe('WorkloadIdentityAuth', () => { let fetchCallCount = 0; const config: WorkloadIdentity = { - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: { @@ -102,7 +100,6 @@ describe('WorkloadIdentityAuth', () => { let fetchCallCount = 0; const config: WorkloadIdentity = { - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: { @@ -142,7 +139,6 @@ describe('WorkloadIdentityAuth', () => { test('sends correct OAuth2 token exchange request', async () => { const config: WorkloadIdentity = { - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: { @@ -179,7 +175,7 @@ describe('WorkloadIdentityAuth', () => { const body = JSON.parse(capturedRequest!.body); expect(body.grant_type).toBe('urn:ietf:params:oauth:grant-type:token-exchange'); - expect(body.client_id).toBe('test-client-id'); + expect(body).not.toHaveProperty('client_id'); expect(body.subject_token).toBe('subject-token'); expect(body.subject_token_type).toBe('urn:ietf:params:oauth:token-type:jwt'); expect(body.identity_provider_id).toBe('test-identity-provider-id'); @@ -188,7 +184,6 @@ describe('WorkloadIdentityAuth', () => { test('includes all required fields in token exchange', async () => { const config: WorkloadIdentity = { - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: { @@ -219,12 +214,12 @@ describe('WorkloadIdentityAuth', () => { const body = JSON.parse(capturedBody!); expect(body.grant_type).toBe('urn:ietf:params:oauth:grant-type:token-exchange'); expect(body.subject_token_type).toBe('urn:ietf:params:oauth:token-type:jwt'); - expect(body.client_id).toBe('test-client-id'); + expect(body).not.toHaveProperty('client_id'); expect(body.identity_provider_id).toBe('test-identity-provider-id'); expect(body.service_account_id).toBe('test-service-account-id'); }); - test('throws OAuthError on failed token exchange', async () => { + test('includes client_id when clientId is provided', async () => { const config: WorkloadIdentity = { clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', @@ -235,6 +230,39 @@ describe('WorkloadIdentityAuth', () => { }, }; + let capturedBody: string | null = null; + + global.fetch = jest.fn(async (url: string, init?: RequestInit) => { + capturedBody = init?.body?.toString() || ''; + + return new Response( + JSON.stringify({ + access_token: 'access-token', + issued_token_type: 'urn:ietf:params:oauth:token-type:id_token', + token_type: 'Bearer', + expires_in: 3600, + }), + { status: 200 }, + ); + }) as typeof fetch; + + const auth = new WorkloadIdentityAuth(config); + await auth.getToken(); + + const body = JSON.parse(capturedBody!); + expect(body.client_id).toBe('test-client-id'); + }); + + test('throws OAuthError on failed token exchange', async () => { + const config: WorkloadIdentity = { + identityProviderId: 'test-identity-provider-id', + serviceAccountId: 'test-service-account-id', + provider: { + tokenType: 'jwt', + getToken: async () => 'subject-token', + }, + }; + global.fetch = jest.fn(async () => { return new Response( JSON.stringify({ @@ -253,7 +281,6 @@ describe('WorkloadIdentityAuth', () => { test('defaults to 3600 seconds when expires_in is missing', async () => { const config: WorkloadIdentity = { - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: { @@ -283,7 +310,6 @@ describe('WorkloadIdentityAuth', () => { let fetchCallCount = 0; const config: WorkloadIdentity = { - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: { @@ -319,7 +345,6 @@ describe('WorkloadIdentityAuth', () => { test('uses the configured fetch implementation for token exchange', async () => { const config: WorkloadIdentity = { - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: { diff --git a/tests/lib/workload-identity.test.ts b/tests/lib/workload-identity.test.ts index 15b770227b..c46514c952 100644 --- a/tests/lib/workload-identity.test.ts +++ b/tests/lib/workload-identity.test.ts @@ -5,7 +5,6 @@ import { OAuthError, SubjectTokenProviderError } from 'openai'; const originalFetch = global.fetch; const createTestWorkloadIdentity = () => ({ - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: { @@ -272,7 +271,6 @@ describe('OpenAI with Workload Identity', () => { test('propagates SubjectTokenProviderError', async () => { const client = new OpenAI({ workloadIdentity: { - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: { @@ -407,7 +405,6 @@ describe('OpenAI with Workload Identity', () => { const client = new OpenAI({ workloadIdentity: { - clientId: 'test-client-id', identityProviderId: 'test-identity-provider-id', serviceAccountId: 'test-service-account-id', provider: {