Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "6.37.0"
".": "6.38.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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'),
Expand All @@ -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(),
Expand All @@ -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(),
Expand All @@ -135,7 +134,6 @@ import OpenAI from 'openai';

const client = new OpenAI({
workloadIdentity: {
clientId: 'your-client-id',
identityProviderId: 'idp-123',
serviceAccountId: 'sa-456',
provider: {
Expand All @@ -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'),
Expand Down
2 changes: 1 addition & 1 deletion jsr.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@openai/openai",
"version": "6.37.0",
"version": "6.38.0",
"exports": {
".": "./index.ts",
"./helpers/zod": "./helpers/zod.ts",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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 <support@openai.com>",
"types": "dist/index.d.ts",
Expand Down
4 changes: 2 additions & 2 deletions src/auth/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
22 changes: 13 additions & 9 deletions src/auth/workload-identity-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface CachedToken {
expiresAt: number;
}

const SUBJECT_TOKEN_TYPES: Record<string, string> = {
const SUBJECT_TOKEN_TYPES: Record<WorkloadIdentity['provider']['tokenType'], string> = {
jwt: 'urn:ietf:params:oauth:token-type:jwt',
id: 'urn:ietf:params:oauth:token-type:id_token',
};
Expand Down Expand Up @@ -54,20 +54,24 @@ export class WorkloadIdentityAuth {

private async refreshToken(): Promise<string> {
const subjectToken = await this.config.provider.getToken();
const body: Record<string, string> = {
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) {
Expand Down
5 changes: 5 additions & 0 deletions src/resources/responses/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/version.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const VERSION = '6.37.0'; // x-release-please-version
export const VERSION = '6.38.0'; // x-release-please-version
1 change: 1 addition & 0 deletions tests/api-resources/responses/responses.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
});
});
});
47 changes: 36 additions & 11 deletions tests/auth/workload-identity-auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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');
Expand All @@ -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: {
Expand Down Expand Up @@ -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',
Expand All @@ -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({
Expand All @@ -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: {
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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: {
Expand Down
3 changes: 0 additions & 3 deletions tests/lib/workload-identity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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: {
Expand Down
Loading