@@ -191,12 +191,20 @@ import {
191191} from './internal/utils/log' ;
192192import { isEmptyObj } from './internal/utils/values' ;
193193
194+ export interface AccessToken {
195+ token : string ;
196+ }
197+ export type TokenProvider = ( ) => Promise < AccessToken > ;
198+
194199export interface ClientOptions {
195200 /**
196201 * Defaults to process.env['OPENAI_API_KEY'].
197202 */
198203 apiKey ?: string | undefined ;
199-
204+ /**
205+ * A function that returns a token to use for authentication.
206+ */
207+ tokenProvider ?: TokenProvider | undefined ;
200208 /**
201209 * Defaults to process.env['OPENAI_ORG_ID'].
202210 */
@@ -307,6 +315,7 @@ export class OpenAI {
307315 #encoder: Opts . RequestEncoder ;
308316 protected idempotencyHeader ?: string ;
309317 private _options : ClientOptions ;
318+ private _tokenProvider : TokenProvider | undefined ;
310319
311320 /**
312321 * API Client for interfacing with the OpenAI API.
@@ -330,11 +339,18 @@ export class OpenAI {
330339 organization = readEnv ( 'OPENAI_ORG_ID' ) ?? null ,
331340 project = readEnv ( 'OPENAI_PROJECT_ID' ) ?? null ,
332341 webhookSecret = readEnv ( 'OPENAI_WEBHOOK_SECRET' ) ?? null ,
342+ tokenProvider,
333343 ...opts
334344 } : 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 ) {
336352 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.' ,
338354 ) ;
339355 }
340356
@@ -343,6 +359,7 @@ export class OpenAI {
343359 organization,
344360 project,
345361 webhookSecret,
362+ tokenProvider,
346363 ...opts ,
347364 baseURL : baseURL || `https://api.openai.com/v1` ,
348365 } ;
@@ -370,7 +387,8 @@ export class OpenAI {
370387
371388 this . _options = options ;
372389
373- this . apiKey = apiKey ;
390+ this . apiKey = apiKey ?? 'Missing Key' ;
391+ this . _tokenProvider = tokenProvider ;
374392 this . organization = organization ;
375393 this . project = project ;
376394 this . webhookSecret = webhookSecret ;
@@ -390,6 +408,7 @@ export class OpenAI {
390408 fetch : this . fetch ,
391409 fetchOptions : this . fetchOptions ,
392410 apiKey : this . apiKey ,
411+ tokenProvider : this . _tokenProvider ,
393412 organization : this . organization ,
394413 project : this . project ,
395414 webhookSecret : this . webhookSecret ,
@@ -438,6 +457,31 @@ export class OpenAI {
438457 return Errors . APIError . generate ( status , error , message , headers ) ;
439458 }
440459
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+
441485 buildURL (
442486 path : string ,
443487 query : Record < string , unknown > | null | undefined ,
@@ -464,7 +508,9 @@ export class OpenAI {
464508 /**
465509 * Used as a callback for mutating the given `FinalRequestOptions` object.
466510 */
467- protected async prepareOptions ( options : FinalRequestOptions ) : Promise < void > { }
511+ protected async prepareOptions ( options : FinalRequestOptions ) : Promise < void > {
512+ await this . _setToken ( ) ;
513+ }
468514
469515 /**
470516 * Used as a callback for mutating the given `RequestInit` object.
0 commit comments