Skip to content

Commit b623760

Browse files
committed
address feedback
1 parent 9086c73 commit b623760

File tree

5 files changed

+25
-47
lines changed

5 files changed

+25
-47
lines changed

src/azure.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export interface AzureClientOptions extends ClientOptions {
3838
export class AzureOpenAI extends OpenAI {
3939
deploymentName: string | undefined;
4040
apiVersion: string = '';
41+
override apiKey: string;
4142

4243
/**
4344
* API Client for interfacing with the Azure OpenAI API.
@@ -109,16 +110,15 @@ export class AzureOpenAI extends OpenAI {
109110
}
110111

111112
super({
112-
apiKey,
113+
apiKey: !azureADTokenProvider ? apiKey : async () => ({ token: await azureADTokenProvider() }),
113114
baseURL,
114-
tokenProvider:
115-
!azureADTokenProvider ? undefined : async () => ({ token: await azureADTokenProvider() }),
116115
...opts,
117116
...(dangerouslyAllowBrowser !== undefined ? { dangerouslyAllowBrowser } : {}),
118117
});
119118

120119
this.apiVersion = apiVersion;
121120
this.deploymentName = deployment;
121+
this.apiKey = apiKey ?? 'PLACEHOLDER_FOR_AZURE_AD_TOKEN_PROVIDER';
122122
}
123123

124124
override async buildRequest(

src/beta/realtime/websocket.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ export class OpenAIRealtimeWebSocket extends OpenAIRealtimeEmitter {
3939
const dangerouslyAllowBrowser =
4040
props.dangerouslyAllowBrowser ??
4141
(client as any)?._options?.dangerouslyAllowBrowser ??
42-
(client?.apiKey.startsWith('ek_') ? true : null);
43-
42+
(typeof (client as any)?._options?.apiKey === 'string' && client?.apiKey?.startsWith('ek_') ?
43+
true
44+
: null);
4445
if (!dangerouslyAllowBrowser && isRunningInBrowser()) {
4546
throw new OpenAIError(
4647
"It looks like you're running in a browser-like environment.\n\nThis is disabled by default, as it risks exposing your secret API credentials to attackers.\n\nYou can avoid this error by creating an ephemeral session token:\nhttps://platform.openai.com/docs/api-reference/realtime-sessions\n",
@@ -49,6 +50,10 @@ export class OpenAIRealtimeWebSocket extends OpenAIRealtimeEmitter {
4950

5051
client ??= new OpenAI({ dangerouslyAllowBrowser });
5152

53+
if (typeof (client as any)?._options?.apiKey !== 'string') {
54+
throw new Error('Call the create method instead to construct the client');
55+
}
56+
5257
this.url = buildRealtimeURL(client, props.model);
5358
props.onURL?.(this.url);
5459

src/beta/realtime/ws.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ export class OpenAIRealtimeWS extends OpenAIRealtimeEmitter {
1313
) {
1414
super();
1515
client ??= new OpenAI();
16-
16+
if (typeof (client as any)._options.apiKey !== 'string') {
17+
throw new Error('Call the create method instead to construct the client');
18+
}
1719
this.url = buildRealtimeURL(client, props.model);
1820
this.socket = new WS.WebSocket(this.url, {
1921
...props.options,

src/client.ts

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,7 @@ export interface ClientOptions {
215215
/**
216216
* Defaults to process.env['OPENAI_API_KEY'].
217217
*/
218-
apiKey?: string | undefined;
219-
/**
220-
* A function that returns a token to use for authentication.
221-
*/
222-
tokenProvider?: TokenProvider | undefined;
218+
apiKey?: string | TokenProvider | undefined;
223219
/**
224220
* Defaults to process.env['OPENAI_ORG_ID'].
225221
*/
@@ -330,7 +326,6 @@ export class OpenAI {
330326
#encoder: Opts.RequestEncoder;
331327
protected idempotencyHeader?: string;
332328
private _options: ClientOptions;
333-
private _tokenProvider: TokenProvider | undefined;
334329

335330
/**
336331
* API Client for interfacing with the OpenAI API.
@@ -354,18 +349,11 @@ export class OpenAI {
354349
organization = readEnv('OPENAI_ORG_ID') ?? null,
355350
project = readEnv('OPENAI_PROJECT_ID') ?? null,
356351
webhookSecret = readEnv('OPENAI_WEBHOOK_SECRET') ?? null,
357-
tokenProvider,
358352
...opts
359353
}: ClientOptions = {}) {
360-
if (apiKey === undefined && !tokenProvider) {
361-
throw new Errors.OpenAIError(
362-
'Missing credentials. Please pass one of `apiKey` and `tokenProvider`, or set the `OPENAI_API_KEY` environment variable.',
363-
);
364-
}
365-
366-
if (tokenProvider && apiKey) {
354+
if (apiKey === undefined) {
367355
throw new Errors.OpenAIError(
368-
'The `apiKey` and `tokenProvider` arguments are mutually exclusive; only one can be passed at a time.',
356+
'Missing credentials. Please pass an `apiKey`, or set the `OPENAI_API_KEY` environment variable.',
369357
);
370358
}
371359

@@ -374,7 +362,6 @@ export class OpenAI {
374362
organization,
375363
project,
376364
webhookSecret,
377-
tokenProvider,
378365
...opts,
379366
baseURL: baseURL || `https://api.openai.com/v1`,
380367
};
@@ -402,8 +389,7 @@ export class OpenAI {
402389

403390
this._options = options;
404391

405-
this.apiKey = apiKey ?? 'Missing Key';
406-
this._tokenProvider = tokenProvider;
392+
this.apiKey = typeof apiKey === 'string' ? apiKey : 'Missing Key';
407393
this.organization = organization;
408394
this.project = project;
409395
this.webhookSecret = webhookSecret;
@@ -423,7 +409,6 @@ export class OpenAI {
423409
fetch: this.fetch,
424410
fetchOptions: this.fetchOptions,
425411
apiKey: this.apiKey,
426-
tokenProvider: this._tokenProvider,
427412
organization: this.organization,
428413
project: this.project,
429414
webhookSecret: this.webhookSecret,
@@ -473,12 +458,13 @@ export class OpenAI {
473458
}
474459

475460
async _setToken(): Promise<boolean> {
476-
if (typeof this._tokenProvider === 'function') {
461+
const apiKey = this._options.apiKey;
462+
if (typeof apiKey === 'function') {
477463
try {
478-
const token = await this._tokenProvider();
464+
const token = await apiKey();
479465
if (!token || typeof token.token !== 'string') {
480466
throw new Errors.OpenAIError(
481-
`Expected 'tokenProvider' argument to return a string but it returned ${token}`,
467+
`Expected 'apiKey' function argument to return a string but it returned ${token}`,
482468
);
483469
}
484470
this.apiKey = token.token;
@@ -488,7 +474,7 @@ export class OpenAI {
488474
throw err;
489475
}
490476
throw new Errors.OpenAIError(
491-
`Failed to get token from 'tokenProvider' function: ${err.message}`,
477+
`Failed to get token from 'apiKey' function: ${err.message}`,
492478
// @ts-ignore
493479
{ cause: err },
494480
);

tests/index.test.ts

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ describe('retries', () => {
736736
};
737737
const client = new OpenAI({
738738
baseURL: 'http://localhost:5000/',
739-
tokenProvider: async () => ({ token: 'my token' }),
739+
apiKey: async () => ({ token: 'my token' }),
740740
fetch: testFetch,
741741
});
742742
expect(
@@ -763,12 +763,12 @@ describe('retries', () => {
763763
});
764764
};
765765
let counter = 0;
766-
async function tokenProvider() {
766+
async function apiKey() {
767767
return { token: `token-${counter++}` };
768768
}
769769
const client = new OpenAI({
770770
baseURL: 'http://localhost:5000/',
771-
tokenProvider,
771+
apiKey,
772772
fetch: testFetch,
773773
});
774774
expect(
@@ -783,21 +783,6 @@ describe('retries', () => {
783783
).toEqual('Bearer token-1');
784784
});
785785

786-
test('mutual exclusive', () => {
787-
try {
788-
new OpenAI({
789-
baseURL: 'http://localhost:5000/',
790-
tokenProvider: async () => ({ token: 'my token' }),
791-
apiKey: 'my api key',
792-
});
793-
} catch (error: any) {
794-
expect(error).toBeInstanceOf(Error);
795-
expect(error.message).toEqual(
796-
'The `apiKey` and `tokenProvider` arguments are mutually exclusive; only one can be passed at a time.',
797-
);
798-
}
799-
});
800-
801786
test('at least one', () => {
802787
try {
803788
new OpenAI({

0 commit comments

Comments
 (0)