@discomedia/utils 1.0.65 → 1.0.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index-frontend.cjs +188 -11
- package/dist/index-frontend.cjs.map +1 -1
- package/dist/index-frontend.mjs +188 -11
- package/dist/index-frontend.mjs.map +1 -1
- package/dist/index.cjs +234 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +234 -63
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +6 -6
- package/dist/test.js +236 -65
- package/dist/test.js.map +1 -1
- package/dist/types/alpaca-market-data-api.d.ts +10 -0
- package/dist/types/alpaca-market-data-api.d.ts.map +1 -1
- package/dist/types-frontend/alpaca-market-data-api.d.ts +10 -0
- package/dist/types-frontend/alpaca-market-data-api.d.ts.map +1 -1
- package/package.json +6 -6
package/dist/index-frontend.cjs
CHANGED
|
@@ -211,6 +211,37 @@ class InvalidWebhookSignatureError extends Error {
|
|
|
211
211
|
super(message);
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Error thrown by the API server during OAuth token exchange.
|
|
216
|
+
* Can have status codes 400, 401, or 403.
|
|
217
|
+
* Other status codes from OAuth endpoints are raised as normal APIError types.
|
|
218
|
+
*/
|
|
219
|
+
class OAuthError extends APIError {
|
|
220
|
+
constructor(status, error, headers) {
|
|
221
|
+
let finalMessage = 'OAuth2 authentication error';
|
|
222
|
+
let error_code = undefined;
|
|
223
|
+
if (error && typeof error === 'object') {
|
|
224
|
+
const errorData = error;
|
|
225
|
+
error_code = errorData['error'];
|
|
226
|
+
const description = errorData['error_description'];
|
|
227
|
+
if (description && typeof description === 'string') {
|
|
228
|
+
finalMessage = description;
|
|
229
|
+
}
|
|
230
|
+
else if (error_code) {
|
|
231
|
+
finalMessage = error_code;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
super(status, error, finalMessage, headers);
|
|
235
|
+
this.error_code = error_code;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
class SubjectTokenProviderError extends OpenAIError {
|
|
239
|
+
constructor(message, provider, cause) {
|
|
240
|
+
super(message);
|
|
241
|
+
this.provider = provider;
|
|
242
|
+
this.cause = cause;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
214
245
|
|
|
215
246
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
216
247
|
// https://url.spec.whatwg.org/#url-scheme-string
|
|
@@ -263,7 +294,7 @@ const safeJSON = (text) => {
|
|
|
263
294
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
264
295
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
265
296
|
|
|
266
|
-
const VERSION = '6.
|
|
297
|
+
const VERSION = '6.34.0'; // x-release-please-version
|
|
267
298
|
|
|
268
299
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
269
300
|
const isRunningInBrowser = () => {
|
|
@@ -1644,6 +1675,91 @@ class ConversationCursorPage extends AbstractPage {
|
|
|
1644
1675
|
}
|
|
1645
1676
|
}
|
|
1646
1677
|
|
|
1678
|
+
const SUBJECT_TOKEN_TYPES = {
|
|
1679
|
+
jwt: 'urn:ietf:params:oauth:token-type:jwt',
|
|
1680
|
+
id: 'urn:ietf:params:oauth:token-type:id_token',
|
|
1681
|
+
};
|
|
1682
|
+
const TOKEN_EXCHANGE_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:token-exchange';
|
|
1683
|
+
class WorkloadIdentityAuth {
|
|
1684
|
+
constructor(config, fetch) {
|
|
1685
|
+
this.cachedToken = null;
|
|
1686
|
+
this.refreshPromise = null;
|
|
1687
|
+
this.tokenExchangeUrl = 'https://auth.openai.com/oauth/token';
|
|
1688
|
+
this.config = config;
|
|
1689
|
+
this.fetch = fetch ?? getDefaultFetch();
|
|
1690
|
+
}
|
|
1691
|
+
async getToken() {
|
|
1692
|
+
if (!this.cachedToken || this.isTokenExpired(this.cachedToken)) {
|
|
1693
|
+
if (this.refreshPromise) {
|
|
1694
|
+
return await this.refreshPromise;
|
|
1695
|
+
}
|
|
1696
|
+
this.refreshPromise = this.refreshToken();
|
|
1697
|
+
try {
|
|
1698
|
+
const token = await this.refreshPromise;
|
|
1699
|
+
return token;
|
|
1700
|
+
}
|
|
1701
|
+
finally {
|
|
1702
|
+
this.refreshPromise = null;
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
if (this.needsRefresh(this.cachedToken) && !this.refreshPromise) {
|
|
1706
|
+
this.refreshPromise = this.refreshToken().finally(() => {
|
|
1707
|
+
this.refreshPromise = null;
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
return this.cachedToken.token;
|
|
1711
|
+
}
|
|
1712
|
+
async refreshToken() {
|
|
1713
|
+
const subjectToken = await this.config.provider.getToken();
|
|
1714
|
+
const response = await this.fetch(this.tokenExchangeUrl, {
|
|
1715
|
+
method: 'POST',
|
|
1716
|
+
headers: {
|
|
1717
|
+
'Content-Type': 'application/json',
|
|
1718
|
+
},
|
|
1719
|
+
body: JSON.stringify({
|
|
1720
|
+
grant_type: TOKEN_EXCHANGE_GRANT_TYPE,
|
|
1721
|
+
client_id: this.config.clientId,
|
|
1722
|
+
subject_token: subjectToken,
|
|
1723
|
+
subject_token_type: SUBJECT_TOKEN_TYPES[this.config.provider.tokenType],
|
|
1724
|
+
identity_provider_id: this.config.identityProviderId,
|
|
1725
|
+
service_account_id: this.config.serviceAccountId,
|
|
1726
|
+
}),
|
|
1727
|
+
});
|
|
1728
|
+
if (!response.ok) {
|
|
1729
|
+
const errorText = await response.text();
|
|
1730
|
+
let body = undefined;
|
|
1731
|
+
try {
|
|
1732
|
+
body = JSON.parse(errorText);
|
|
1733
|
+
}
|
|
1734
|
+
catch { }
|
|
1735
|
+
if (response.status === 400 || response.status === 401 || response.status === 403) {
|
|
1736
|
+
throw new OAuthError(response.status, body, response.headers);
|
|
1737
|
+
}
|
|
1738
|
+
throw APIError.generate(response.status, body, `Token exchange failed with status ${response.status}`, response.headers);
|
|
1739
|
+
}
|
|
1740
|
+
const tokenResponse = (await response.json());
|
|
1741
|
+
const expiresIn = tokenResponse.expires_in || 3600;
|
|
1742
|
+
const expiresAt = Date.now() + expiresIn * 1000;
|
|
1743
|
+
this.cachedToken = {
|
|
1744
|
+
token: tokenResponse.access_token,
|
|
1745
|
+
expiresAt,
|
|
1746
|
+
};
|
|
1747
|
+
return tokenResponse.access_token;
|
|
1748
|
+
}
|
|
1749
|
+
isTokenExpired(cachedToken) {
|
|
1750
|
+
return Date.now() >= cachedToken.expiresAt;
|
|
1751
|
+
}
|
|
1752
|
+
needsRefresh(cachedToken) {
|
|
1753
|
+
const bufferSeconds = this.config.refreshBufferSeconds ?? 1200;
|
|
1754
|
+
const bufferMs = bufferSeconds * 1000;
|
|
1755
|
+
return Date.now() >= cachedToken.expiresAt - bufferMs;
|
|
1756
|
+
}
|
|
1757
|
+
invalidateToken() {
|
|
1758
|
+
this.cachedToken = null;
|
|
1759
|
+
this.refreshPromise = null;
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1647
1763
|
const checkFileSupport = () => {
|
|
1648
1764
|
if (typeof File === 'undefined') {
|
|
1649
1765
|
const { process } = globalThis;
|
|
@@ -6949,6 +7065,7 @@ _Webhooks_instances = new WeakSet(), _Webhooks_validateSecret = function _Webhoo
|
|
|
6949
7065
|
|
|
6950
7066
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
6951
7067
|
var _OpenAI_instances, _a$1, _OpenAI_encoder, _OpenAI_baseURLOverridden;
|
|
7068
|
+
const WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER = 'workload-identity-auth';
|
|
6952
7069
|
/**
|
|
6953
7070
|
* API Client for interfacing with the OpenAI API.
|
|
6954
7071
|
*/
|
|
@@ -6969,7 +7086,7 @@ class OpenAI {
|
|
|
6969
7086
|
* @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.
|
|
6970
7087
|
* @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
|
|
6971
7088
|
*/
|
|
6972
|
-
constructor({ baseURL = readEnv('OPENAI_BASE_URL'), apiKey = readEnv('OPENAI_API_KEY'), organization = readEnv('OPENAI_ORG_ID') ?? null, project = readEnv('OPENAI_PROJECT_ID') ?? null, webhookSecret = readEnv('OPENAI_WEBHOOK_SECRET') ?? null, ...opts } = {}) {
|
|
7089
|
+
constructor({ baseURL = readEnv('OPENAI_BASE_URL'), apiKey = readEnv('OPENAI_API_KEY'), organization = readEnv('OPENAI_ORG_ID') ?? null, project = readEnv('OPENAI_PROJECT_ID') ?? null, webhookSecret = readEnv('OPENAI_WEBHOOK_SECRET') ?? null, workloadIdentity, ...opts } = {}) {
|
|
6973
7090
|
_OpenAI_instances.add(this);
|
|
6974
7091
|
_OpenAI_encoder.set(this, void 0);
|
|
6975
7092
|
/**
|
|
@@ -7024,14 +7141,21 @@ class OpenAI {
|
|
|
7024
7141
|
this.containers = new Containers(this);
|
|
7025
7142
|
this.skills = new Skills(this);
|
|
7026
7143
|
this.videos = new Videos(this);
|
|
7027
|
-
if (
|
|
7028
|
-
|
|
7144
|
+
if (workloadIdentity) {
|
|
7145
|
+
if (apiKey && apiKey !== WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER) {
|
|
7146
|
+
throw new OpenAIError('The `apiKey` and `workloadIdentity` arguments are mutually exclusive; only one can be passed at a time.');
|
|
7147
|
+
}
|
|
7148
|
+
apiKey = WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER;
|
|
7149
|
+
}
|
|
7150
|
+
else if (apiKey === undefined) {
|
|
7151
|
+
throw new OpenAIError('Missing credentials. Please pass an `apiKey`, `workloadIdentity`, or set the `OPENAI_API_KEY` environment variable.');
|
|
7029
7152
|
}
|
|
7030
7153
|
const options = {
|
|
7031
7154
|
apiKey,
|
|
7032
7155
|
organization,
|
|
7033
7156
|
project,
|
|
7034
7157
|
webhookSecret,
|
|
7158
|
+
workloadIdentity,
|
|
7035
7159
|
...opts,
|
|
7036
7160
|
baseURL: baseURL || `https://api.openai.com/v1`,
|
|
7037
7161
|
};
|
|
@@ -7053,6 +7177,9 @@ class OpenAI {
|
|
|
7053
7177
|
this.fetch = options.fetch ?? getDefaultFetch();
|
|
7054
7178
|
__classPrivateFieldSet(this, _OpenAI_encoder, FallbackEncoder);
|
|
7055
7179
|
this._options = options;
|
|
7180
|
+
if (workloadIdentity) {
|
|
7181
|
+
this._workloadIdentityAuth = new WorkloadIdentityAuth(workloadIdentity, this.fetch);
|
|
7182
|
+
}
|
|
7056
7183
|
this.apiKey = typeof apiKey === 'string' ? apiKey : 'Missing Key';
|
|
7057
7184
|
this.organization = organization;
|
|
7058
7185
|
this.project = project;
|
|
@@ -7072,6 +7199,7 @@ class OpenAI {
|
|
|
7072
7199
|
fetch: this.fetch,
|
|
7073
7200
|
fetchOptions: this.fetchOptions,
|
|
7074
7201
|
apiKey: this.apiKey,
|
|
7202
|
+
workloadIdentity: this._options.workloadIdentity,
|
|
7075
7203
|
organization: this.organization,
|
|
7076
7204
|
project: this.project,
|
|
7077
7205
|
webhookSecret: this.webhookSecret,
|
|
@@ -7198,7 +7326,7 @@ class OpenAI {
|
|
|
7198
7326
|
throw new APIUserAbortError();
|
|
7199
7327
|
}
|
|
7200
7328
|
const controller = new AbortController();
|
|
7201
|
-
const response = await this.
|
|
7329
|
+
const response = await this.fetchWithAuth(url, req, timeout, controller).catch(castToError);
|
|
7202
7330
|
const headersTime = Date.now();
|
|
7203
7331
|
if (response instanceof globalThis.Error) {
|
|
7204
7332
|
const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
|
|
@@ -7228,6 +7356,9 @@ class OpenAI {
|
|
|
7228
7356
|
durationMs: headersTime - startTime,
|
|
7229
7357
|
message: response.message,
|
|
7230
7358
|
}));
|
|
7359
|
+
if (response instanceof OAuthError || response instanceof SubjectTokenProviderError) {
|
|
7360
|
+
throw response;
|
|
7361
|
+
}
|
|
7231
7362
|
if (isTimeout) {
|
|
7232
7363
|
throw new APIConnectionTimeoutError();
|
|
7233
7364
|
}
|
|
@@ -7239,6 +7370,20 @@ class OpenAI {
|
|
|
7239
7370
|
.join('');
|
|
7240
7371
|
const responseInfo = `[${requestLogID}${retryLogStr}${specialHeaders}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`;
|
|
7241
7372
|
if (!response.ok) {
|
|
7373
|
+
if (response.status === 401 &&
|
|
7374
|
+
this._workloadIdentityAuth &&
|
|
7375
|
+
!options.__metadata?.['hasStreamingBody'] &&
|
|
7376
|
+
!options.__metadata?.['workloadIdentityTokenRefreshed']) {
|
|
7377
|
+
await CancelReadableStream(response.body);
|
|
7378
|
+
this._workloadIdentityAuth.invalidateToken();
|
|
7379
|
+
return this.makeRequest({
|
|
7380
|
+
...options,
|
|
7381
|
+
__metadata: {
|
|
7382
|
+
...options.__metadata,
|
|
7383
|
+
workloadIdentityTokenRefreshed: true,
|
|
7384
|
+
},
|
|
7385
|
+
}, retriesRemaining, retryOfRequestLogID ?? requestLogID);
|
|
7386
|
+
}
|
|
7242
7387
|
const shouldRetry = await this.shouldRetry(response);
|
|
7243
7388
|
if (retriesRemaining && shouldRetry) {
|
|
7244
7389
|
const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
|
|
@@ -7289,6 +7434,18 @@ class OpenAI {
|
|
|
7289
7434
|
const request = this.makeRequest(options, null, undefined);
|
|
7290
7435
|
return new PagePromise(this, request, Page);
|
|
7291
7436
|
}
|
|
7437
|
+
async fetchWithAuth(url, init, timeout, controller) {
|
|
7438
|
+
if (this._workloadIdentityAuth) {
|
|
7439
|
+
const headers = init.headers;
|
|
7440
|
+
const authHeader = headers.get('Authorization');
|
|
7441
|
+
if (!authHeader || authHeader === `Bearer ${WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER}`) {
|
|
7442
|
+
const token = await this._workloadIdentityAuth.getToken();
|
|
7443
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
7444
|
+
}
|
|
7445
|
+
}
|
|
7446
|
+
const response = await this.fetchWithTimeout(url, init, timeout, controller);
|
|
7447
|
+
return response;
|
|
7448
|
+
}
|
|
7292
7449
|
async fetchWithTimeout(url, init, ms, controller) {
|
|
7293
7450
|
const { signal, method, ...options } = init || {};
|
|
7294
7451
|
const abort = this._makeAbort(controller);
|
|
@@ -7385,7 +7542,13 @@ class OpenAI {
|
|
|
7385
7542
|
if ('timeout' in options)
|
|
7386
7543
|
validatePositiveInteger('timeout', options.timeout);
|
|
7387
7544
|
options.timeout = options.timeout ?? this.timeout;
|
|
7388
|
-
const { bodyHeaders, body } = this.buildBody({ options });
|
|
7545
|
+
const { bodyHeaders, body, isStreamingBody } = this.buildBody({ options });
|
|
7546
|
+
if (isStreamingBody) {
|
|
7547
|
+
inputOptions.__metadata = {
|
|
7548
|
+
...inputOptions.__metadata,
|
|
7549
|
+
hasStreamingBody: true,
|
|
7550
|
+
};
|
|
7551
|
+
}
|
|
7389
7552
|
const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });
|
|
7390
7553
|
const req = {
|
|
7391
7554
|
method,
|
|
@@ -7432,9 +7595,18 @@ class OpenAI {
|
|
|
7432
7595
|
}
|
|
7433
7596
|
buildBody({ options: { body, headers: rawHeaders } }) {
|
|
7434
7597
|
if (!body) {
|
|
7435
|
-
return { bodyHeaders: undefined, body: undefined };
|
|
7598
|
+
return { bodyHeaders: undefined, body: undefined, isStreamingBody: false };
|
|
7436
7599
|
}
|
|
7437
7600
|
const headers = buildHeaders([rawHeaders]);
|
|
7601
|
+
const isReadableStream = typeof globalThis.ReadableStream !== 'undefined' &&
|
|
7602
|
+
body instanceof globalThis.ReadableStream;
|
|
7603
|
+
const isRetryableBody = !isReadableStream &&
|
|
7604
|
+
(typeof body === 'string' ||
|
|
7605
|
+
body instanceof ArrayBuffer ||
|
|
7606
|
+
ArrayBuffer.isView(body) ||
|
|
7607
|
+
(typeof globalThis.Blob !== 'undefined' && body instanceof globalThis.Blob) ||
|
|
7608
|
+
body instanceof URLSearchParams ||
|
|
7609
|
+
body instanceof FormData);
|
|
7438
7610
|
if (
|
|
7439
7611
|
// Pass raw type verbatim
|
|
7440
7612
|
ArrayBuffer.isView(body) ||
|
|
@@ -7450,23 +7622,28 @@ class OpenAI {
|
|
|
7450
7622
|
// `URLSearchParams` -> `application/x-www-form-urlencoded`
|
|
7451
7623
|
body instanceof URLSearchParams ||
|
|
7452
7624
|
// Send chunked stream (each chunk has own `length`)
|
|
7453
|
-
|
|
7454
|
-
return { bodyHeaders: undefined, body: body };
|
|
7625
|
+
isReadableStream) {
|
|
7626
|
+
return { bodyHeaders: undefined, body: body, isStreamingBody: !isRetryableBody };
|
|
7455
7627
|
}
|
|
7456
7628
|
else if (typeof body === 'object' &&
|
|
7457
7629
|
(Symbol.asyncIterator in body ||
|
|
7458
7630
|
(Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) {
|
|
7459
|
-
return {
|
|
7631
|
+
return {
|
|
7632
|
+
bodyHeaders: undefined,
|
|
7633
|
+
body: ReadableStreamFrom(body),
|
|
7634
|
+
isStreamingBody: true,
|
|
7635
|
+
};
|
|
7460
7636
|
}
|
|
7461
7637
|
else if (typeof body === 'object' &&
|
|
7462
7638
|
headers.values.get('content-type') === 'application/x-www-form-urlencoded') {
|
|
7463
7639
|
return {
|
|
7464
7640
|
bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
7465
7641
|
body: this.stringifyQuery(body),
|
|
7642
|
+
isStreamingBody: false,
|
|
7466
7643
|
};
|
|
7467
7644
|
}
|
|
7468
7645
|
else {
|
|
7469
|
-
return __classPrivateFieldGet(this, _OpenAI_encoder, "f").call(this, { body, headers });
|
|
7646
|
+
return { ...__classPrivateFieldGet(this, _OpenAI_encoder, "f").call(this, { body, headers }), isStreamingBody: false };
|
|
7470
7647
|
}
|
|
7471
7648
|
}
|
|
7472
7649
|
}
|