UNPKG

llmforge

Version:

One API, every AI model, instant switching. Change from GPT-4 to Gemini to local models with a single config update. LLMForge is the lightweight, TypeScript-first solution for multi-provider AI applications with zero vendor lock-in.

125 lines 5.08 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HttpClient = void 0; const types_1 = require("../types"); const expo_1 = require("../strategies/retry/expo"); const undici_1 = require("undici"); const stream_1 = require("stream"); const logger_1 = require("../utils/logger"); class HttpClient { constructor(config, baseUrl, retryHandler) { var _a, _b; this.config = { baseUrl: baseUrl, // 'https://generativelanguage.googleapis.com', timeout: 30000, ...config, }; this.retryHandler = retryHandler || new expo_1.RetryHandler({ maxRetries: (_a = this.config.retryConfig) === null || _a === void 0 ? void 0 : _a.maxRetries, retryDelay: (_b = this.config.retryConfig) === null || _b === void 0 ? void 0 : _b.retryDelay, }); } async request(options = {}, isStream = false, endPointPath) { const url = `${this.config.baseUrl}`; logger_1.logger.info('base url:', url); logger_1.logger.info('endpoint path: ', endPointPath); const undiciOptions = { path: endPointPath, method: options.method || 'POST', headers: Object.fromEntries(Object.entries({ 'Content-Type': 'application/json', ...options.headers, }).map(([k, v]) => [k, v === null || v === void 0 ? void 0 : v.toString()])), body: options.body, signal: this.createTimeoutSignal(this.config.timeout), }; logger_1.logger.info('undici options: ', JSON.stringify(undiciOptions, null, 2)); const operation = async () => { const { statusCode, body } = await (0, undici_1.request)(url, undiciOptions); logger_1.logger.debug('status of the response is :', statusCode); //REMOVE FROM HERE // const chunk2: Uint8Array[] = []; // for await (const chunk of body) { // chunk2.push(chunk); // } // const responseText2 = Buffer.concat(chunk2).toString(); // console.log("response text:", JSON.parse(responseText2) as T); //REMOVE TO HERE if (isStream) { logger_1.logger.info('streaming response'); if (body instanceof stream_1.Readable) { return body; } throw new types_1.NonRetryableError('Expected a Readable stream for streaming requests', statusCode, this.getStatusText(statusCode)); } const chunks = []; for await (const chunk of body) { chunks.push(chunk); } const responseText = Buffer.concat(chunks).toString(); return JSON.parse(responseText); }; return this.retryHandler.executeWithRetry(operation, `${options.method || 'POST'} `); } async streamRequest(options = {}, endPointPath) { logger_1.logger.info('endpoint path: ', endPointPath); return this.request(options, true, endPointPath); } async handleErrorResponse(statusCode, body) { let errorData; try { const chunks = []; for await (const chunk of body) { chunks.push(chunk); } const responseText = Buffer.concat(chunks).toString(); errorData = JSON.parse(responseText); } catch (_a) { errorData = { error: { code: statusCode, message: this.getStatusText(statusCode) || 'Unknown error', status: this.getStatusText(statusCode), }, }; } const { code, message, status, details } = errorData.error; const isRetryable = this.isRetryableStatusCode(code); const ErrorClass = isRetryable ? types_1.RetryableError : types_1.NonRetryableError; throw new ErrorClass(message, code, status, details); } isRetryableStatusCode(statusCode) { const retryableCodes = [429, 500, 502, 503, 504]; return retryableCodes.includes(statusCode); } getStatusText(statusCode) { const statusTexts = { 400: 'BAD_REQUEST', 401: 'UNAUTHORIZED', 403: 'FORBIDDEN', 404: 'NOT_FOUND', 429: 'RATE_LIMITED', 500: 'INTERNAL_SERVER_ERROR', 502: 'BAD_GATEWAY', 503: 'SERVICE_UNAVAILABLE', 504: 'GATEWAY_TIMEOUT', }; return statusTexts[statusCode] || 'UNKNOWN_ERROR'; } createTimeoutSignal(timeout) { const controller = new AbortController(); setTimeout(() => controller.abort(), timeout); return controller.signal; } updateConfig(newConfig) { this.config = { ...this.config, ...newConfig }; } getConfig() { return { ...this.config }; } } exports.HttpClient = HttpClient; //# sourceMappingURL=http-client.js.map