-
Notifications
You must be signed in to change notification settings - Fork 1.2k
add support for token provider #1587
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
9086c73
0307ed5
b6102b3
577ebc6
390c131
ff7cdff
878679e
4033c6a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -206,12 +206,21 @@ import { | |
} from './internal/utils/log'; | ||
import { isEmptyObj } from './internal/utils/values'; | ||
|
||
export type ApiKeySetter = () => Promise<string>; | ||
|
||
export interface ClientOptions { | ||
/** | ||
* Defaults to process.env['OPENAI_API_KEY']. | ||
* API key used for authentication. | ||
* | ||
* - Accepts either a static string or an async function that resolves to a string. | ||
* - Defaults to process.env['OPENAI_API_KEY']. | ||
* - When a function is provided, it is invoked before each request so you can rotate | ||
* or refresh credentials at runtime. | ||
* - The function must return a non-empty string; otherwise an OpenAIError is thrown. | ||
* - If the function throws, the error is wrapped in an OpenAIError with the original | ||
* error available as `cause`. | ||
*/ | ||
apiKey?: string | undefined; | ||
|
||
apiKey?: string | ApiKeySetter | undefined; | ||
/** | ||
* Defaults to process.env['OPENAI_ORG_ID']. | ||
*/ | ||
|
@@ -349,7 +358,7 @@ export class OpenAI { | |
}: ClientOptions = {}) { | ||
if (apiKey === undefined) { | ||
throw new Errors.OpenAIError( | ||
"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' }).", | ||
'Missing credentials. Please pass an `apiKey`, or set the `OPENAI_API_KEY` environment variable.', | ||
); | ||
} | ||
|
||
|
@@ -385,7 +394,7 @@ export class OpenAI { | |
|
||
this._options = options; | ||
|
||
this.apiKey = apiKey; | ||
this.apiKey = typeof apiKey === 'string' ? apiKey : 'Missing Key'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: should probably be something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually, we should move There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is only used once here so I am not sure if there is value to have it in a constant var. |
||
this.organization = organization; | ||
this.project = project; | ||
this.webhookSecret = webhookSecret; | ||
|
@@ -453,6 +462,31 @@ export class OpenAI { | |
return Errors.APIError.generate(status, error, message, headers); | ||
} | ||
|
||
async _callApiKey(): Promise<boolean> { | ||
const apiKey = this._options.apiKey; | ||
if (typeof apiKey !== 'function') return false; | ||
|
||
let token: unknown; | ||
try { | ||
token = await apiKey(); | ||
} catch (err: any) { | ||
if (err instanceof Errors.OpenAIError) throw err; | ||
throw new Errors.OpenAIError( | ||
`Failed to get token from 'apiKey' function: ${err.message}`, | ||
// @ts-ignore | ||
{ cause: err }, | ||
); | ||
} | ||
|
||
if (typeof token !== 'string' || !token) { | ||
throw new Errors.OpenAIError( | ||
`Expected 'apiKey' function argument to return a string but it returned ${token}`, | ||
); | ||
} | ||
this.apiKey = token; | ||
return true; | ||
} | ||
|
||
buildURL( | ||
path: string, | ||
query: Record<string, unknown> | null | undefined, | ||
|
@@ -479,7 +513,9 @@ export class OpenAI { | |
/** | ||
* Used as a callback for mutating the given `FinalRequestOptions` object. | ||
*/ | ||
protected async prepareOptions(options: FinalRequestOptions): Promise<void> {} | ||
protected async prepareOptions(options: FinalRequestOptions): Promise<void> { | ||
await this._callApiKey(); | ||
} | ||
|
||
/** | ||
* Used as a callback for mutating the given `RequestInit` object. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docstring should mention the new function behaviour
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, addressed in 577ebc6.