@@ -191,12 +191,20 @@ import {
191
191
} from './internal/utils/log' ;
192
192
import { isEmptyObj } from './internal/utils/values' ;
193
193
194
+ export interface AccessToken {
195
+ token : string ;
196
+ }
197
+ export type TokenProvider = ( ) => Promise < AccessToken > ;
198
+
194
199
export interface ClientOptions {
195
200
/**
196
201
* Defaults to process.env['OPENAI_API_KEY'].
197
202
*/
198
203
apiKey ?: string | undefined ;
199
-
204
+ /**
205
+ * A function that returns a token to use for authentication.
206
+ */
207
+ tokenProvider ?: TokenProvider | undefined ;
200
208
/**
201
209
* Defaults to process.env['OPENAI_ORG_ID'].
202
210
*/
@@ -307,6 +315,7 @@ export class OpenAI {
307
315
#encoder: Opts . RequestEncoder ;
308
316
protected idempotencyHeader ?: string ;
309
317
private _options : ClientOptions ;
318
+ private _tokenProvider : TokenProvider | undefined ;
310
319
311
320
/**
312
321
* API Client for interfacing with the OpenAI API.
@@ -330,11 +339,18 @@ export class OpenAI {
330
339
organization = readEnv ( 'OPENAI_ORG_ID' ) ?? null ,
331
340
project = readEnv ( 'OPENAI_PROJECT_ID' ) ?? null ,
332
341
webhookSecret = readEnv ( 'OPENAI_WEBHOOK_SECRET' ) ?? null ,
342
+ tokenProvider,
333
343
...opts
334
344
} : ClientOptions = { } ) {
335
- if ( apiKey === undefined ) {
345
+ if ( apiKey === undefined && ! tokenProvider ) {
346
+ throw new Errors . OpenAIError (
347
+ 'Missing credentials. Please pass one of `apiKey` and `tokenProvider`, or set the `OPENAI_API_KEY` environment variable.' ,
348
+ ) ;
349
+ }
350
+
351
+ if ( tokenProvider && apiKey ) {
336
352
throw new Errors . OpenAIError (
337
- " The OPENAI_API_KEY environment variable is missing or empty; either provide it, or instantiate the OpenAI client with an apiKey option, like new OpenAI({ apiKey: 'My API Key' })." ,
353
+ ' The `apiKey` and `tokenProvider` arguments are mutually exclusive; only one can be passed at a time.' ,
338
354
) ;
339
355
}
340
356
@@ -343,6 +359,7 @@ export class OpenAI {
343
359
organization,
344
360
project,
345
361
webhookSecret,
362
+ tokenProvider,
346
363
...opts ,
347
364
baseURL : baseURL || `https://api.openai.com/v1` ,
348
365
} ;
@@ -370,7 +387,8 @@ export class OpenAI {
370
387
371
388
this . _options = options ;
372
389
373
- this . apiKey = apiKey ;
390
+ this . apiKey = apiKey ?? 'Missing Key' ;
391
+ this . _tokenProvider = tokenProvider ;
374
392
this . organization = organization ;
375
393
this . project = project ;
376
394
this . webhookSecret = webhookSecret ;
@@ -390,6 +408,7 @@ export class OpenAI {
390
408
fetch : this . fetch ,
391
409
fetchOptions : this . fetchOptions ,
392
410
apiKey : this . apiKey ,
411
+ tokenProvider : this . _tokenProvider ,
393
412
organization : this . organization ,
394
413
project : this . project ,
395
414
webhookSecret : this . webhookSecret ,
@@ -438,6 +457,31 @@ export class OpenAI {
438
457
return Errors . APIError . generate ( status , error , message , headers ) ;
439
458
}
440
459
460
+ async _setToken ( ) : Promise < boolean > {
461
+ if ( typeof this . _tokenProvider === 'function' ) {
462
+ try {
463
+ const token = await this . _tokenProvider ( ) ;
464
+ if ( ! token || typeof token . token !== 'string' ) {
465
+ throw new Errors . OpenAIError (
466
+ `Expected 'tokenProvider' argument to return a string but it returned ${ token } ` ,
467
+ ) ;
468
+ }
469
+ this . apiKey = token . token ;
470
+ return true ;
471
+ } catch ( err : any ) {
472
+ if ( err instanceof Errors . OpenAIError ) {
473
+ throw err ;
474
+ }
475
+ throw new Errors . OpenAIError (
476
+ `Failed to get token from 'tokenProvider' function: ${ err . message } ` ,
477
+ // @ts -ignore
478
+ { cause : err } ,
479
+ ) ;
480
+ }
481
+ }
482
+ return false ;
483
+ }
484
+
441
485
buildURL (
442
486
path : string ,
443
487
query : Record < string , unknown > | null | undefined ,
@@ -464,7 +508,9 @@ export class OpenAI {
464
508
/**
465
509
* Used as a callback for mutating the given `FinalRequestOptions` object.
466
510
*/
467
- protected async prepareOptions ( options : FinalRequestOptions ) : Promise < void > { }
511
+ protected async prepareOptions ( options : FinalRequestOptions ) : Promise < void > {
512
+ await this . _setToken ( ) ;
513
+ }
468
514
469
515
/**
470
516
* Used as a callback for mutating the given `RequestInit` object.
0 commit comments