CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes48downloads
client.mjs527 linesDownload Raw Back to openai
1// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.2var _OpenAI_instances, _a, _OpenAI_encoder, _OpenAI_baseURLOverridden;3import { __classPrivateFieldGet, __classPrivateFieldSet } from "./internal/tslib.mjs";4import { uuid4 } from "./internal/utils/uuid.mjs";5import { validatePositiveInteger, isAbsoluteURL, safeJSON } from "./internal/utils/values.mjs";6import { sleep } from "./internal/utils/sleep.mjs";7import { castToError, isAbortError } from "./internal/errors.mjs";8import { getPlatformHeaders } from "./internal/detect-platform.mjs";9import * as Shims from "./internal/shims.mjs";10import * as Opts from "./internal/request-options.mjs";11import * as qs from "./internal/qs/index.mjs";12import { VERSION } from "./version.mjs";13import * as Errors from "./core/error.mjs";14import * as Pagination from "./core/pagination.mjs";15import * as Uploads from "./core/uploads.mjs";16import * as API from "./resources/index.mjs";17import { APIPromise } from "./core/api-promise.mjs";18import { Batches, } from "./resources/batches.mjs";19import { Completions, } from "./resources/completions.mjs";20import { Embeddings, } from "./resources/embeddings.mjs";21import { Files, } from "./resources/files.mjs";22import { Images, } from "./resources/images.mjs";23import { Models } from "./resources/models.mjs";24import { Moderations, } from "./resources/moderations.mjs";25import { Webhooks } from "./resources/webhooks.mjs";26import { Audio } from "./resources/audio/audio.mjs";27import { Beta } from "./resources/beta/beta.mjs";28import { Chat } from "./resources/chat/chat.mjs";29import { Containers, } from "./resources/containers/containers.mjs";30import { Evals, } from "./resources/evals/evals.mjs";31import { FineTuning } from "./resources/fine-tuning/fine-tuning.mjs";32import { Graders } from "./resources/graders/graders.mjs";33import { Responses } from "./resources/responses/responses.mjs";34import { Uploads as UploadsAPIUploads, } from "./resources/uploads/uploads.mjs";35import { VectorStores, } from "./resources/vector-stores/vector-stores.mjs";36import { isRunningInBrowser } from "./internal/detect-platform.mjs";37import { buildHeaders } from "./internal/headers.mjs";38import { readEnv } from "./internal/utils/env.mjs";39import { formatRequestDetails, loggerFor, parseLogLevel, } from "./internal/utils/log.mjs";40import { isEmptyObj } from "./internal/utils/values.mjs";41/**42 * API Client for interfacing with the OpenAI API.43 */44export class OpenAI {45    /**46     * API Client for interfacing with the OpenAI API.47     *48     * @param {string | undefined} [opts.apiKey=process.env['OPENAI_API_KEY'] ?? undefined]49     * @param {string | null | undefined} [opts.organization=process.env['OPENAI_ORG_ID'] ?? null]50     * @param {string | null | undefined} [opts.project=process.env['OPENAI_PROJECT_ID'] ?? null]51     * @param {string | null | undefined} [opts.webhookSecret=process.env['OPENAI_WEBHOOK_SECRET'] ?? null]52     * @param {string} [opts.baseURL=process.env['OPENAI_BASE_URL'] ?? https://api.openai.com/v1] - Override the default base URL for the API.53     * @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.54     * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.55     * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.56     * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.57     * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.58     * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.59     * @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.60     */61    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 } = {}) {62        _OpenAI_instances.add(this);63        _OpenAI_encoder.set(this, void 0);64        this.completions = new API.Completions(this);65        this.chat = new API.Chat(this);66        this.embeddings = new API.Embeddings(this);67        this.files = new API.Files(this);68        this.images = new API.Images(this);69        this.audio = new API.Audio(this);70        this.moderations = new API.Moderations(this);71        this.models = new API.Models(this);72        this.fineTuning = new API.FineTuning(this);73        this.graders = new API.Graders(this);74        this.vectorStores = new API.VectorStores(this);75        this.webhooks = new API.Webhooks(this);76        this.beta = new API.Beta(this);77        this.batches = new API.Batches(this);78        this.uploads = new API.Uploads(this);79        this.responses = new API.Responses(this);80        this.evals = new API.Evals(this);81        this.containers = new API.Containers(this);82        if (apiKey === undefined) {83            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' }).");84        }85        const options = {86            apiKey,87            organization,88            project,89            webhookSecret,90            ...opts,91            baseURL: baseURL || `https://api.openai.com/v1`,92        };93        if (!options.dangerouslyAllowBrowser && isRunningInBrowser()) {94            throw new Errors.OpenAIError("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.\nIf you understand the risks and have appropriate mitigations in place,\nyou can set the `dangerouslyAllowBrowser` option to `true`, e.g.,\n\nnew OpenAI({ apiKey, dangerouslyAllowBrowser: true });\n\nhttps://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety\n");95        }96        this.baseURL = options.baseURL;97        this.timeout = options.timeout ?? _a.DEFAULT_TIMEOUT /* 10 minutes */;98        this.logger = options.logger ?? console;99        const defaultLogLevel = 'warn';100        // Set default logLevel early so that we can log a warning in parseLogLevel.101        this.logLevel = defaultLogLevel;102        this.logLevel =103            parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ??104                parseLogLevel(readEnv('OPENAI_LOG'), "process.env['OPENAI_LOG']", this) ??105                defaultLogLevel;106        this.fetchOptions = options.fetchOptions;107        this.maxRetries = options.maxRetries ?? 2;108        this.fetch = options.fetch ?? Shims.getDefaultFetch();109        __classPrivateFieldSet(this, _OpenAI_encoder, Opts.FallbackEncoder, "f");110        this._options = options;111        this.apiKey = apiKey;112        this.organization = organization;113        this.project = project;114        this.webhookSecret = webhookSecret;115    }116    /**117     * Create a new client instance re-using the same options given to the current client with optional overriding.118     */119    withOptions(options) {120        const client = new this.constructor({121            ...this._options,122            baseURL: this.baseURL,123            maxRetries: this.maxRetries,124            timeout: this.timeout,125            logger: this.logger,126            logLevel: this.logLevel,127            fetch: this.fetch,128            fetchOptions: this.fetchOptions,129            apiKey: this.apiKey,130            organization: this.organization,131            project: this.project,132            webhookSecret: this.webhookSecret,133            ...options,134        });135        return client;136    }137    defaultQuery() {138        return this._options.defaultQuery;139    }140    validateHeaders({ values, nulls }) {141        return;142    }143    async authHeaders(opts) {144        return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]);145    }146    stringifyQuery(query) {147        return qs.stringify(query, { arrayFormat: 'brackets' });148    }149    getUserAgent() {150        return `${this.constructor.name}/JS ${VERSION}`;151    }152    defaultIdempotencyKey() {153        return `stainless-node-retry-${uuid4()}`;154    }155    makeStatusError(status, error, message, headers) {156        return Errors.APIError.generate(status, error, message, headers);157    }158    buildURL(path, query, defaultBaseURL) {159        const baseURL = (!__classPrivateFieldGet(this, _OpenAI_instances, "m", _OpenAI_baseURLOverridden).call(this) && defaultBaseURL) || this.baseURL;160        const url = isAbsoluteURL(path) ?161            new URL(path)162            : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));163        const defaultQuery = this.defaultQuery();164        if (!isEmptyObj(defaultQuery)) {165            query = { ...defaultQuery, ...query };166        }167        if (typeof query === 'object' && query && !Array.isArray(query)) {168            url.search = this.stringifyQuery(query);169        }170        return url.toString();171    }172    /**173     * Used as a callback for mutating the given `FinalRequestOptions` object.174     */175    async prepareOptions(options) { }176    /**177     * Used as a callback for mutating the given `RequestInit` object.178     *179     * This is useful for cases where you want to add certain headers based off of180     * the request properties, e.g. `method` or `url`.181     */182    async prepareRequest(request, { url, options }) { }183    get(path, opts) {184        return this.methodRequest('get', path, opts);185    }186    post(path, opts) {187        return this.methodRequest('post', path, opts);188    }189    patch(path, opts) {190        return this.methodRequest('patch', path, opts);191    }192    put(path, opts) {193        return this.methodRequest('put', path, opts);194    }195    delete(path, opts) {196        return this.methodRequest('delete', path, opts);197    }198    methodRequest(method, path, opts) {199        return this.request(Promise.resolve(opts).then((opts) => {200            return { method, path, ...opts };201        }));202    }203    request(options, remainingRetries = null) {204        return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined));205    }206    async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) {207        const options = await optionsInput;208        const maxRetries = options.maxRetries ?? this.maxRetries;209        if (retriesRemaining == null) {210            retriesRemaining = maxRetries;211        }212        await this.prepareOptions(options);213        const { req, url, timeout } = await this.buildRequest(options, {214            retryCount: maxRetries - retriesRemaining,215        });216        await this.prepareRequest(req, { url, options });217        /** Not an API request ID, just for correlating local log entries. */218        const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0');219        const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`;220        const startTime = Date.now();221        loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({222            retryOfRequestLogID,223            method: options.method,224            url,225            options,226            headers: req.headers,227        }));228        if (options.signal?.aborted) {229            throw new Errors.APIUserAbortError();230        }231        const controller = new AbortController();232        const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);233        const headersTime = Date.now();234        if (response instanceof Error) {235            const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;236            if (options.signal?.aborted) {237                throw new Errors.APIUserAbortError();238            }239            // detect native connection timeout errors240            // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)"241            // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)"242            // others do not provide enough information to distinguish timeouts from other connection errors243            const isTimeout = isAbortError(response) ||244                /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''));245            if (retriesRemaining) {246                loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`);247                loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({248                    retryOfRequestLogID,249                    url,250                    durationMs: headersTime - startTime,251                    message: response.message,252                }));253                return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);254            }255            loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`);256            loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({257                retryOfRequestLogID,258                url,259                durationMs: headersTime - startTime,260                message: response.message,261            }));262            if (isTimeout) {263                throw new Errors.APIConnectionTimeoutError();264            }265            throw new Errors.APIConnectionError({ cause: response });266        }267        const specialHeaders = [...response.headers.entries()]268            .filter(([name]) => name === 'x-request-id')269            .map(([name, value]) => ', ' + name + ': ' + JSON.stringify(value))270            .join('');271        const responseInfo = `[${requestLogID}${retryLogStr}${specialHeaders}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`;272        if (!response.ok) {273            const shouldRetry = await this.shouldRetry(response);274            if (retriesRemaining && shouldRetry) {275                const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;276                // We don't need the body of this response.277                await Shims.CancelReadableStream(response.body);278                loggerFor(this).info(`${responseInfo} - ${retryMessage}`);279                loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({280                    retryOfRequestLogID,281                    url: response.url,282                    status: response.status,283                    headers: response.headers,284                    durationMs: headersTime - startTime,285                }));286                return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID, response.headers);287            }288            const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;289            loggerFor(this).info(`${responseInfo} - ${retryMessage}`);290            const errText = await response.text().catch((err) => castToError(err).message);291            const errJSON = safeJSON(errText);292            const errMessage = errJSON ? undefined : errText;293            loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({294                retryOfRequestLogID,295                url: response.url,296                status: response.status,297                headers: response.headers,298                message: errMessage,299                durationMs: Date.now() - startTime,300            }));301            const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);302            throw err;303        }304        loggerFor(this).info(responseInfo);305        loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({306            retryOfRequestLogID,307            url: response.url,308            status: response.status,309            headers: response.headers,310            durationMs: headersTime - startTime,311        }));312        return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };313    }314    getAPIList(path, Page, opts) {315        return this.requestAPIList(Page, { method: 'get', path, ...opts });316    }317    requestAPIList(Page, options) {318        const request = this.makeRequest(options, null, undefined);319        return new Pagination.PagePromise(this, request, Page);320    }321    async fetchWithTimeout(url, init, ms, controller) {322        const { signal, method, ...options } = init || {};323        if (signal)324            signal.addEventListener('abort', () => controller.abort());325        const timeout = setTimeout(() => controller.abort(), ms);326        const isReadableBody = (globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream) ||327            (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);328        const fetchOptions = {329            signal: controller.signal,330            ...(isReadableBody ? { duplex: 'half' } : {}),331            method: 'GET',332            ...options,333        };334        if (method) {335            // Custom methods like 'patch' need to be uppercased336            // See https://github.com/nodejs/undici/issues/2294337            fetchOptions.method = method.toUpperCase();338        }339        try {340            // use undefined this binding; fetch errors if bound to something else in browser/cloudflare341            return await this.fetch.call(undefined, url, fetchOptions);342        }343        finally {344            clearTimeout(timeout);345        }346    }347    async shouldRetry(response) {348        // Note this is not a standard header.349        const shouldRetryHeader = response.headers.get('x-should-retry');350        // If the server explicitly says whether or not to retry, obey.351        if (shouldRetryHeader === 'true')352            return true;353        if (shouldRetryHeader === 'false')354            return false;355        // Retry on request timeouts.356        if (response.status === 408)357            return true;358        // Retry on lock timeouts.359        if (response.status === 409)360            return true;361        // Retry on rate limits.362        if (response.status === 429)363            return true;364        // Retry internal errors.365        if (response.status >= 500)366            return true;367        return false;368    }369    async retryRequest(options, retriesRemaining, requestLogID, responseHeaders) {370        let timeoutMillis;371        // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it.372        const retryAfterMillisHeader = responseHeaders?.get('retry-after-ms');373        if (retryAfterMillisHeader) {374            const timeoutMs = parseFloat(retryAfterMillisHeader);375            if (!Number.isNaN(timeoutMs)) {376                timeoutMillis = timeoutMs;377            }378        }379        // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After380        const retryAfterHeader = responseHeaders?.get('retry-after');381        if (retryAfterHeader && !timeoutMillis) {382            const timeoutSeconds = parseFloat(retryAfterHeader);383            if (!Number.isNaN(timeoutSeconds)) {384                timeoutMillis = timeoutSeconds * 1000;385            }386            else {387                timeoutMillis = Date.parse(retryAfterHeader) - Date.now();388            }389        }390        // If the API asks us to wait a certain amount of time (and it's a reasonable amount),391        // just do what it says, but otherwise calculate a default392        if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) {393            const maxRetries = options.maxRetries ?? this.maxRetries;394            timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);395        }396        await sleep(timeoutMillis);397        return this.makeRequest(options, retriesRemaining - 1, requestLogID);398    }399    calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) {400        const initialRetryDelay = 0.5;401        const maxRetryDelay = 8.0;402        const numRetries = maxRetries - retriesRemaining;403        // Apply exponential backoff, but not more than the max.404        const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);405        // Apply some jitter, take up to at most 25 percent of the retry time.406        const jitter = 1 - Math.random() * 0.25;407        return sleepSeconds * jitter * 1000;408    }409    async buildRequest(inputOptions, { retryCount = 0 } = {}) {410        const options = { ...inputOptions };411        const { method, path, query, defaultBaseURL } = options;412        const url = this.buildURL(path, query, defaultBaseURL);413        if ('timeout' in options)414            validatePositiveInteger('timeout', options.timeout);415        options.timeout = options.timeout ?? this.timeout;416        const { bodyHeaders, body } = this.buildBody({ options });417        const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });418        const req = {419            method,420            headers: reqHeaders,421            ...(options.signal && { signal: options.signal }),422            ...(globalThis.ReadableStream &&423                body instanceof globalThis.ReadableStream && { duplex: 'half' }),424            ...(body && { body }),425            ...(this.fetchOptions ?? {}),426            ...(options.fetchOptions ?? {}),427        };428        return { req, url, timeout: options.timeout };429    }430    async buildHeaders({ options, method, bodyHeaders, retryCount, }) {431        let idempotencyHeaders = {};432        if (this.idempotencyHeader && method !== 'get') {433            if (!options.idempotencyKey)434                options.idempotencyKey = this.defaultIdempotencyKey();435            idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey;436        }437        const headers = buildHeaders([438            idempotencyHeaders,439            {440                Accept: 'application/json',441                'User-Agent': this.getUserAgent(),442                'X-Stainless-Retry-Count': String(retryCount),443                ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),444                ...getPlatformHeaders(),445                'OpenAI-Organization': this.organization,446                'OpenAI-Project': this.project,447            },448            await this.authHeaders(options),449            this._options.defaultHeaders,450            bodyHeaders,451            options.headers,452        ]);453        this.validateHeaders(headers);454        return headers.values;455    }456    buildBody({ options: { body, headers: rawHeaders } }) {457        if (!body) {458            return { bodyHeaders: undefined, body: undefined };459        }460        const headers = buildHeaders([rawHeaders]);461        if (462        // Pass raw type verbatim463        ArrayBuffer.isView(body) ||464            body instanceof ArrayBuffer ||465            body instanceof DataView ||466            (typeof body === 'string' &&467                // Preserve legacy string encoding behavior for now468                headers.values.has('content-type')) ||469            // `Blob` is superset of `File`470            body instanceof Blob ||471            // `FormData` -> `multipart/form-data`472            body instanceof FormData ||473            // `URLSearchParams` -> `application/x-www-form-urlencoded`474            body instanceof URLSearchParams ||475            // Send chunked stream (each chunk has own `length`)476            (globalThis.ReadableStream && body instanceof globalThis.ReadableStream)) {477            return { bodyHeaders: undefined, body: body };478        }479        else if (typeof body === 'object' &&480            (Symbol.asyncIterator in body ||481                (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) {482            return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body) };483        }484        else {485            return __classPrivateFieldGet(this, _OpenAI_encoder, "f").call(this, { body, headers });486        }487    }488}489_a = OpenAI, _OpenAI_encoder = new WeakMap(), _OpenAI_instances = new WeakSet(), _OpenAI_baseURLOverridden = function _OpenAI_baseURLOverridden() {490    return this.baseURL !== 'https://api.openai.com/v1';491};492OpenAI.OpenAI = _a;493OpenAI.DEFAULT_TIMEOUT = 600000; // 10 minutes494OpenAI.OpenAIError = Errors.OpenAIError;495OpenAI.APIError = Errors.APIError;496OpenAI.APIConnectionError = Errors.APIConnectionError;497OpenAI.APIConnectionTimeoutError = Errors.APIConnectionTimeoutError;498OpenAI.APIUserAbortError = Errors.APIUserAbortError;499OpenAI.NotFoundError = Errors.NotFoundError;500OpenAI.ConflictError = Errors.ConflictError;501OpenAI.RateLimitError = Errors.RateLimitError;502OpenAI.BadRequestError = Errors.BadRequestError;503OpenAI.AuthenticationError = Errors.AuthenticationError;504OpenAI.InternalServerError = Errors.InternalServerError;505OpenAI.PermissionDeniedError = Errors.PermissionDeniedError;506OpenAI.UnprocessableEntityError = Errors.UnprocessableEntityError;507OpenAI.InvalidWebhookSignatureError = Errors.InvalidWebhookSignatureError;508OpenAI.toFile = Uploads.toFile;509OpenAI.Completions = Completions;510OpenAI.Chat = Chat;511OpenAI.Embeddings = Embeddings;512OpenAI.Files = Files;513OpenAI.Images = Images;514OpenAI.Audio = Audio;515OpenAI.Moderations = Moderations;516OpenAI.Models = Models;517OpenAI.FineTuning = FineTuning;518OpenAI.Graders = Graders;519OpenAI.VectorStores = VectorStores;520OpenAI.Webhooks = Webhooks;521OpenAI.Beta = Beta;522OpenAI.Batches = Batches;523OpenAI.Uploads = UploadsAPIUploads;524OpenAI.Responses = Responses;525OpenAI.Evals = Evals;526OpenAI.Containers = Containers;527//# sourceMappingURL=client.mjs.map
basant307/AI_Governance_Project · CoolFace