UNPKG

venice-dev-tools

Version:

unOfficial SDK for the Venice AI API

1,697 lines (1,665 loc) 91.9 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { ApiEndpoint: () => ApiEndpoint, BaseHttpClient: () => BaseHttpClient, CharactersEndpoint: () => CharactersEndpoint, ChatEndpoint: () => ChatEndpoint, ChatStreamEndpoint: () => ChatStreamEndpoint, ConfigManager: () => ConfigManager, EndpointManager: () => EndpointManager, EndpointRegistry: () => EndpointManager, ErrorFactory: () => ErrorFactory, ErrorHandler: () => ErrorHandler, EventManager: () => EventManager, HttpClient: () => HttpClient, HttpClientFactory: () => HttpClientFactory, ImageGenerationEndpoint: () => ImageGenerationEndpoint, ImageStylesEndpoint: () => ImageStylesEndpoint, ImageUpscaleEndpoint: () => ImageUpscaleEndpoint, ImagesEndpoint: () => ImagesEndpoint, KeysEndpoint: () => KeysEndpoint, LegacyBaseHttpClient: () => BaseHttpClient2, LogLevel: () => LogLevel, ModelsEndpoint: () => ModelsEndpoint, StandardHttpClient: () => StandardHttpClient, StreamingHttpClient: () => StreamingHttpClient, VeniceAI: () => VeniceAI, VeniceApiError: () => VeniceApiError, VeniceAuthError: () => VeniceAuthError, VeniceCapacityError: () => VeniceCapacityError, VeniceClient: () => VeniceClient, VeniceError: () => VeniceError, VeniceNetworkError: () => VeniceNetworkError, VenicePaymentRequiredError: () => VenicePaymentRequiredError, VeniceRateLimitError: () => VeniceRateLimitError, VeniceStreamError: () => VeniceStreamError, VeniceTimeoutError: () => VeniceTimeoutError, VeniceValidationError: () => VeniceValidationError, createRequestInterceptor: () => createRequestInterceptor, createResponseInterceptor: () => createResponseInterceptor, createStreamRequest: () => createStreamRequest, default: () => index_default, handleError: () => handleError, handleRequestError: () => handleRequestError, handleStreamError: () => handleStreamError, isVeniceError: () => isVeniceError, processStreamResponse: () => processStreamResponse, sanitizeData: () => sanitizeData, sanitizeHeaders: () => sanitizeHeaders }); module.exports = __toCommonJS(index_exports); // src/errors/types/base-error.ts var VeniceError = class _VeniceError extends Error { /** * Create a new Venice SDK error. * @param message - The error message. * @param options - Additional error options. */ constructor(message, options) { super(message, options); this.name = "VeniceError"; Object.setPrototypeOf(this, _VeniceError.prototype); } }; // src/errors/types/api-error.ts var VeniceApiError = class _VeniceApiError extends VeniceError { /** * Create a new API error. * @param message - The error message. * @param status - The HTTP status code. * @param details - Additional error details. */ constructor(message, status, details) { super(message); this.name = "VeniceApiError"; this.status = status; this.details = details; Object.setPrototypeOf(this, _VeniceApiError.prototype); } }; // src/errors/types/auth-error.ts var VeniceAuthError = class _VeniceAuthError extends VeniceApiError { /** * Create a new authentication error. * @param message - The error message. */ constructor(message = "Authentication failed") { super(message, 401); this.name = "VeniceAuthError"; Object.setPrototypeOf(this, _VeniceAuthError.prototype); } }; // src/errors/types/payment-required-error.ts var VenicePaymentRequiredError = class _VenicePaymentRequiredError extends VeniceApiError { /** * Create a new payment required error. * @param message - The error message. */ constructor(message = "Insufficient USD or VCU balance to complete request") { super(message, 402); this.name = "VenicePaymentRequiredError"; Object.setPrototypeOf(this, _VenicePaymentRequiredError.prototype); } }; // src/errors/types/rate-limit-error.ts var VeniceRateLimitError = class _VeniceRateLimitError extends VeniceApiError { /** * Create a new rate limit error. * @param message - The error message. */ constructor(message = "Rate limit exceeded") { super(message, 429); this.name = "VeniceRateLimitError"; Object.setPrototypeOf(this, _VeniceRateLimitError.prototype); } }; // src/errors/types/capacity-error.ts var VeniceCapacityError = class _VeniceCapacityError extends VeniceApiError { /** * Create a new model capacity error. * @param message - The error message. */ constructor(message = "The model is at capacity. Please try again later.") { super(message, 503); this.name = "VeniceCapacityError"; Object.setPrototypeOf(this, _VeniceCapacityError.prototype); } }; // src/errors/types/network-error.ts var VeniceNetworkError = class _VeniceNetworkError extends VeniceError { /** * Create a new network error. * @param message - The error message. * @param options - Additional error options. */ constructor(message = "Network error occurred", options) { super(message, options); this.name = "VeniceNetworkError"; Object.setPrototypeOf(this, _VeniceNetworkError.prototype); } }; // src/errors/types/timeout-error.ts var VeniceTimeoutError = class _VeniceTimeoutError extends VeniceError { /** * Create a new timeout error. * @param message - The error message. */ constructor(message = "Request timed out") { super(message); this.name = "VeniceTimeoutError"; Object.setPrototypeOf(this, _VeniceTimeoutError.prototype); } }; // src/errors/types/validation-error.ts var VeniceValidationError = class _VeniceValidationError extends VeniceError { /** * Create a new validation error. * @param message - The error message. * @param details - Additional validation details. */ constructor(message, details) { super(message); this.name = "VeniceValidationError"; this.details = details; Object.setPrototypeOf(this, _VeniceValidationError.prototype); } }; // src/errors/types/stream-error.ts var VeniceStreamError = class _VeniceStreamError extends VeniceError { /** * Create a new stream error. * @param message - The error message. * @param options - Additional error options. */ constructor(message = "Stream processing error", options) { super(message, options); this.name = "VeniceStreamError"; Object.setPrototypeOf(this, _VeniceStreamError.prototype); } }; // src/errors/factory/error-factory.ts var ErrorFactory = class { /** * Create an error from an API response. * @param status - The HTTP status code. * @param message - The error message. * @param details - Additional error details. * @returns A Venice SDK error. */ createFromResponse(status, message, details) { switch (status) { case 401: return new VeniceAuthError(message); case 402: return new VenicePaymentRequiredError(message); case 429: return new VeniceRateLimitError(message); case 503: return new VeniceCapacityError(message); default: return new VeniceApiError(message, status, details); } } /** * Create an error from an Axios error. * @param error - The Axios error. * @returns A Venice SDK error. */ createFromAxiosError(error) { if (error.response) { const responseData = error.response.data || {}; const errorMessage = responseData.error || "API request failed"; const details = responseData.details; return this.createFromResponse(error.response.status, errorMessage, details); } else if (error.request) { if (error.code === "ECONNABORTED") { return new VeniceTimeoutError("Request timed out"); } return new VeniceNetworkError("Network error", { cause: error }); } else { return new VeniceError(error.message || "Request setup error", { cause: error }); } } /** * Create an error from a fetch response. * @param response - The fetch response. * @returns A promise that resolves to a Venice SDK error. */ async createFromFetchResponse(response) { try { const errorData = await response.json().catch(() => ({ error: `HTTP error ${response.status}` })); return this.createFromResponse( response.status, errorData.error || "API request failed", errorData.details ); } catch (error) { return new VeniceApiError(`HTTP error ${response.status}`, response.status); } } /** * Create an error from a stream error. * @param error - The error that occurred during streaming. * @returns A Venice SDK error. */ createFromStreamError(error) { if (error instanceof VeniceError) { return error; } if (error instanceof Error && error.name === "AbortError") { return new VeniceError("Request was aborted", { cause: error }); } return new VeniceStreamError("Stream request failed", { cause: error }); } /** * Create a validation error. * @param message - The error message. * @param details - Additional validation details. * @returns A Venice validation error. */ createValidationError(message, details) { return new VeniceValidationError(message, details); } /** * Create a generic error from any error. * @param error - The error to convert. * @returns A Venice SDK error. */ createFromError(error) { if (error instanceof VeniceError) { return error; } if (error instanceof Error) { return new VeniceError(error.message, { cause: error }); } return new VeniceError(String(error)); } }; // src/errors/index.ts var errorFactory = new ErrorFactory(); function isVeniceError(error) { return error instanceof VeniceError; } function handleError(error) { return errorFactory.createFromError(error); } // src/config/config-manager.ts var ConfigManager = class { /** * Create a new configuration manager. * @param initialConfig - The initial configuration. */ constructor(initialConfig = {}) { this.config = { baseUrl: "https://api.venice.ai/api/v1", timeout: 3e4, headers: {}, ...initialConfig }; } /** * Get the current configuration. * @returns The current configuration. */ getConfig() { return { ...this.config }; } /** * Set the API key for authentication. * @param apiKey - The Venice API key. * @throws VeniceAuthError if the API key is empty. */ setApiKey(apiKey) { if (!apiKey) { throw new VeniceAuthError("API key cannot be empty"); } this.config.apiKey = apiKey; } /** * Get the current API key. * @returns The current API key or undefined if not set. */ getApiKey() { return this.config.apiKey; } /** * Get the current API key, throwing an error if not set. * @returns The current API key. * @throws VeniceAuthError if no API key is set. */ getRequiredApiKey() { const apiKey = this.getApiKey(); if (!apiKey) { throw new VeniceAuthError("No API key set. Use setApiKey() to set your API key."); } return apiKey; } /** * Set a custom header for API requests. * @param name - The header name. * @param value - The header value. */ setHeader(name, value) { if (this.config.headers) { this.config.headers[name] = value; } else { this.config.headers = { [name]: value }; } } /** * Get the base URL for API requests. * @returns The base URL. */ getBaseUrl() { return this.config.baseUrl || "https://api.venice.ai/api/v1"; } /** * Get the request timeout in milliseconds. * @returns The timeout in milliseconds. */ getTimeout() { return this.config.timeout || 3e4; } /** * Get the headers for API requests. * @returns The headers. */ getHeaders() { return this.config.headers || {}; } }; // src/events/event-manager.ts var import_eventemitter3 = require("eventemitter3"); var EventManager = class { /** * Create a new event manager. */ constructor() { this.events = new import_eventemitter3.EventEmitter(); } /** * Subscribe to an event. * @param event - The event name. * @param listener - The event listener. * @returns This event manager instance. */ on(event, listener) { this.events.on(event, listener); return this; } /** * Subscribe to an event for one-time execution. * @param event - The event name. * @param listener - The event listener. * @returns This event manager instance. */ once(event, listener) { this.events.once(event, listener); return this; } /** * Unsubscribe from an event. * @param event - The event name. * @param listener - The event listener. * @returns This event manager instance. */ off(event, listener) { this.events.off(event, listener); return this; } /** * Emit an event. * @param event - The event name. * @param args - The event arguments. * @returns Whether the event had listeners. */ emit(event, ...args) { return this.events.emit(event, ...args); } /** * Remove all listeners for an event. * @param event - The event name (optional, if not provided, removes all listeners). * @returns This event manager instance. */ removeAllListeners(event) { this.events.removeAllListeners(event); return this; } /** * Get the number of listeners for an event. * @param event - The event name. * @returns The number of listeners. */ listenerCount(event) { return this.events.listenerCount(event); } }; // src/http/components/base-client.ts var import_axios = __toESM(require("axios")); // src/types/common.ts var LogLevel = /* @__PURE__ */ ((LogLevel2) => { LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG"; LogLevel2[LogLevel2["INFO"] = 1] = "INFO"; LogLevel2[LogLevel2["WARN"] = 2] = "WARN"; LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR"; LogLevel2[LogLevel2["NONE"] = 4] = "NONE"; return LogLevel2; })(LogLevel || {}); // src/utils/logger.ts var Logger = class { /** * Creates a new logger. * * @param options - Logger options */ constructor(options = {}) { this.level = options.level ?? 1 /* INFO */; this.handlers = options.handlers ?? [this.defaultHandler.bind(this)]; } /** * Sets the log level. * * @param level - The log level */ setLevel(level) { this.level = level; } /** * Adds a log handler. * * @param handler - The log handler */ addHandler(handler) { this.handlers.push(handler); } /** * Logs a debug message. * * @param message - The message to log * @param data - Additional data to log */ debug(message, data) { this.log(0 /* DEBUG */, message, data); } /** * Logs an info message. * * @param message - The message to log * @param data - Additional data to log */ info(message, data) { this.log(1 /* INFO */, message, data); } /** * Logs a warning message. * * @param message - The message to log * @param data - Additional data to log */ warn(message, data) { this.log(2 /* WARN */, message, data); } /** * Logs an error message. * * @param message - The message to log * @param data - Additional data to log */ error(message, data) { this.log(3 /* ERROR */, message, data); } /** * Logs a message at the specified level. * * @param level - The log level * @param message - The message to log * @param data - Additional data to log */ log(level, message, data) { if (level < this.level) return; const entry = { level, message, timestamp: (/* @__PURE__ */ new Date()).toISOString(), data }; for (const handler of this.handlers) { handler(entry); } } /** * Default log handler. * * @param entry - The log entry */ defaultHandler(entry) { const levelNames = ["DEBUG", "INFO", "WARN", "ERROR"]; const levelName = levelNames[entry.level] || "UNKNOWN"; let logMessage = `[${entry.timestamp}] ${levelName}: ${entry.message}`; if (entry.data !== void 0) { try { const dataStr = typeof entry.data === "string" ? entry.data : JSON.stringify(entry.data, null, 2); logMessage += ` ${dataStr}`; } catch (e) { logMessage += "\n[Unable to stringify data]"; } } if (typeof process !== "undefined" && process.stdout) { const stream = entry.level >= 3 /* ERROR */ ? process.stderr : process.stdout; stream.write(`${logMessage} `); } else { const method = entry.level >= 3 /* ERROR */ ? "error" : entry.level === 2 /* WARN */ ? "warn" : entry.level === 1 /* INFO */ ? "info" : "debug"; console[method](logMessage); } } }; // src/http/components/sanitizer.ts function sanitizeHeaders(headers) { if (!headers) return headers; const sanitized = { ...headers }; if (sanitized.Authorization) { sanitized.Authorization = "Bearer [REDACTED]"; } if (sanitized.authorization) { sanitized.authorization = "Bearer [REDACTED]"; } Object.keys(sanitized).forEach((key) => { if (key.toLowerCase() === "authorization") { sanitized[key] = "Bearer [REDACTED]"; } }); return sanitized; } function sanitizeData(data) { if (!data) return data; if (typeof data === "object" && data !== null) { const sanitized = { ...data }; if (sanitized.apiKey) { sanitized.apiKey = "[REDACTED]"; } if (sanitized.api_key) { sanitized.api_key = "[REDACTED]"; } if (sanitized.password) { sanitized.password = "[REDACTED]"; } if (sanitized.token) { sanitized.token = "[REDACTED]"; } if (sanitized.secret) { sanitized.secret = "[REDACTED]"; } Object.keys(sanitized).forEach((key) => { if (typeof sanitized[key] === "object" && sanitized[key] !== null) { sanitized[key] = sanitizeData(sanitized[key]); } }); return sanitized; } return data; } // src/http/components/interceptors.ts function generateRequestId() { return Math.random().toString(36).substring(2, 15); } function createRequestInterceptor(logger) { return { /** * Handle outgoing requests * @param config - The Axios request config * @returns The modified config */ onRequest: (config) => { const requestId = generateRequestId(); config.headers = config.headers || {}; config.headers["X-Request-ID"] = requestId; logger.debug(`Request ${requestId}: ${config.method?.toUpperCase()} ${config.url}`, { headers: sanitizeHeaders(config.headers), params: config.params, data: sanitizeData(config.data) }); return config; }, /** * Handle request errors * @param error - The error that occurred * @returns A rejected promise with the error */ onRequestError: (error) => { logger.error("Request setup error", { error: error.message }); return Promise.reject(error); } }; } function createResponseInterceptor(logger) { return { /** * Handle successful responses * @param response - The Axios response * @returns The response */ onResponse: (response) => { const requestId = response.config.headers?.["X-Request-ID"] || "unknown"; logger.debug(`Response ${requestId}: ${response.status} ${response.statusText}`, { headers: sanitizeHeaders(response.headers), data: sanitizeData(response.data) }); return response; }, /** * Handle response errors * @param error - The error that occurred * @returns A rejected promise with the error */ onResponseError: (error) => { const requestId = error.config?.headers?.["X-Request-ID"] || "unknown"; if (error.response) { logger.error(`Response ${requestId}: ${error.response.status} ${error.response.statusText}`, { headers: sanitizeHeaders(error.response.headers), data: sanitizeData(error.response.data) }); } else if (error.request) { logger.error(`Response ${requestId}: No response received`, { error: error.message }); } else { logger.error(`Request ${requestId} error: ${error.message}`); } return Promise.reject(error); } }; } // src/http/components/error-handler.ts function handleRequestError(error, logger, timeout) { if (error.response) { const responseData = error.response.data || {}; const errorMessage = responseData.error || "API request failed"; const details = responseData.details; logger.error(`API error: ${errorMessage}`, { status: error.response.status, details }); throw new VeniceApiError(errorMessage, error.response.status, details); } else if (error.request) { if (error.code === "ECONNABORTED") { logger.error(`Request timed out after ${timeout}ms`); throw new VeniceTimeoutError("Request timed out"); } logger.error("Network error", { message: error.message, code: error.code }); throw new VeniceNetworkError("Network error", { cause: error }); } else { logger.error("Request setup error", { message: error.message }); throw new Error(error.message || "Request setup error"); } } function handleStreamError(error, logger, requestId) { if (error instanceof VeniceApiError) { throw error; } if (error.name === "AbortError") { logger.warn(`Stream request ${requestId} aborted`); throw new Error("Request was aborted"); } logger.error(`Stream request ${requestId} failed`, { error: error.message }); throw new VeniceNetworkError("Stream request failed", { cause: error }); } // src/http/components/streaming.ts async function createStreamRequest(baseUrl, path, body, options = {}, logger) { const url = `${baseUrl}${path}`; const headers = { "Content-Type": "application/json", ...options.headers }; const requestId = Math.random().toString(36).substring(2, 15); logger.debug(`Stream request ${requestId}: POST ${path}`, { headers: sanitizeHeaders(headers), body: sanitizeData(body) }); try { const response = await fetch(url, { method: "POST", headers, body: JSON.stringify(body), signal: options.signal }); if (!response.ok) { const errorData = await response.json().catch(() => ({ error: `HTTP error ${response.status}` })); logger.error(`Stream response ${requestId} error: ${response.status}`, { error: errorData.error, details: errorData.details }); throw new VeniceApiError(errorData.error || "Stream request failed", response.status, errorData.details); } logger.debug(`Stream response ${requestId}: ${response.status} ${response.statusText}`); return response; } catch (error) { return handleStreamError(error, logger, requestId); } } async function processStreamResponse(response, onChunk, logger) { const reader = response.body?.getReader(); if (!reader) { logger.error("Stream response has no readable body"); throw new Error("Stream response has no readable body"); } const decoder = new TextDecoder(); try { while (true) { const { done, value } = await reader.read(); if (done) { break; } const chunk = decoder.decode(value, { stream: true }); onChunk(chunk); } } catch (error) { logger.error("Error processing stream", { error: error.message }); throw error; } finally { reader.releaseLock(); } } // src/http/components/base-client.ts var BaseHttpClient = class { /** * Create a new HTTP client * @param config - Configuration options */ constructor(config = {}) { this.baseUrl = config.baseUrl || "https://api.venice.ai/api/v1"; this.timeout = config.timeout || 3e4; this.logger = config.logger || new Logger({ level: 1 /* INFO */ }); this.logger.debug("Initializing HTTP client", { baseUrl: this.baseUrl, timeout: this.timeout }); this.client = import_axios.default.create({ baseURL: this.baseUrl, timeout: this.timeout, headers: { "Content-Type": "application/json", ...config.headers } }); const requestInterceptor = createRequestInterceptor(this.logger); this.client.interceptors.request.use( requestInterceptor.onRequest, requestInterceptor.onRequestError ); const responseInterceptor = createResponseInterceptor(this.logger); this.client.interceptors.response.use( responseInterceptor.onResponse, responseInterceptor.onResponseError ); } /** * Set an authorization header with a bearer token * @param token - The API key or token */ setAuthToken(token) { this.logger.debug("Setting authorization token"); this.client.defaults.headers.common["Authorization"] = `Bearer ${token}`; } /** * Set a custom header for future requests * @param name - The header name * @param value - The header value */ setHeader(name, value) { this.logger.debug(`Setting header: ${name}`); this.client.defaults.headers.common[name] = value; } /** * Get all headers currently set on the client * @returns The headers object */ getHeaders() { return this.client.defaults.headers.common; } /** * Make an HTTP request * @param path - The API path (will be appended to the base URL) * @param options - Request options * @returns The response data */ async request(path, options = {}) { try { const { method = "GET", headers = {}, body, query, timeout, responseType = "json", signal } = options; const config = { method, url: path, headers, params: query, data: body, responseType, signal }; if (timeout) { config.timeout = timeout; } const response = await this.client.request(config); return { data: response.data, status: response.status, statusText: response.statusText, headers: response.headers }; } catch (error) { return handleRequestError(error, this.logger, this.timeout); } } /** * Make a GET request * @param path - The API path * @param options - Request options * @returns The response data */ async get(path, options = {}) { return this.request(path, { ...options, method: "GET" }); } /** * Make a POST request * @param path - The API path * @param body - The request body * @param options - Additional request options * @returns The response data */ async post(path, body, options = {}) { return this.request(path, { ...options, method: "POST", body }); } /** * Make a DELETE request * @param path - The API path * @param options - Request options * @returns The response data */ async delete(path, options = {}) { return this.request(path, { ...options, method: "DELETE" }); } /** * Create a new stream request * @param path - The API path * @param body - The request body * @param options - Additional request options * @returns A fetch response for streaming */ async stream(path, body, options = {}) { const authHeader = this.client.defaults.headers.common["Authorization"]; const headers = { ...authHeader ? { "Authorization": authHeader } : {}, ...options.headers }; return createStreamRequest( this.baseUrl, path, body, { headers, signal: options.signal }, this.logger ); } }; // src/http/client.ts var HttpClient = class extends BaseHttpClient { /** * Create a new HTTP client * @param baseUrl - The base URL for the API * @param headers - Additional headers to include in requests * @param timeout - Request timeout in milliseconds * @param logger - Optional logger instance */ constructor(baseUrl = "https://api.venice.ai/api/v1", headers = {}, timeout = 3e4, logger) { super({ baseUrl, headers, timeout, logger }); } /** * Get the headers currently set on the client * @returns The headers object */ getHeaders() { return super.getHeaders(); } }; // src/http/base/base-http-client.ts var BaseHttpClient2 = class { /** * Create a new HTTP client. * @param baseUrl - The base URL for the API. * @param headers - Additional headers to include in requests. * @param timeout - Request timeout in milliseconds. */ constructor(baseUrl = "https://api.venice.ai/api/v1", headers = {}, timeout = 3e4) { this.baseUrl = baseUrl; this.headers = { "Content-Type": "application/json", ...headers }; this.timeout = timeout; } /** * Set an authorization header with a bearer token. * @param token - The API key or token. */ setAuthToken(token) { this.headers["Authorization"] = `Bearer ${token}`; } /** * Set a custom header for future requests. * @param name - The header name. * @param value - The header value. */ setHeader(name, value) { this.headers[name] = value; } /** * Get the current headers. * @returns The current headers. */ getHeaders() { return { ...this.headers }; } /** * Get the base URL. * @returns The base URL. */ getBaseUrl() { return this.baseUrl; } /** * Get the timeout. * @returns The timeout in milliseconds. */ getTimeout() { return this.timeout; } /** * Set the timeout. * @param timeout - The timeout in milliseconds. */ setTimeout(timeout) { this.timeout = timeout; } }; // src/http/standard/standard-http-client.ts var import_axios2 = __toESM(require("axios")); // src/http/error/error-handler.ts var ErrorHandler = class { /** * Create a new error handler. * @param errorFactory - The error factory to use. */ constructor(errorFactory2 = new ErrorFactory()) { this.errorFactory = errorFactory2; } /** * Handle API request errors from standard HTTP requests. * @param error - The Axios error. * @throws A Venice SDK error. */ handleRequestError(error) { throw this.errorFactory.createFromAxiosError(error); } /** * Handle API stream errors from streaming HTTP requests. * @param error - The error that occurred during streaming. * @throws A Venice SDK error. */ handleStreamError(error) { throw this.errorFactory.createFromStreamError(error); } /** * Handle errors from response parsing. * @param response - The fetch response. * @throws A Venice SDK error if the response is not OK. */ async handleResponseError(response) { if (!response.ok) { throw await this.errorFactory.createFromFetchResponse(response); } } }; // src/http/standard/standard-http-client.ts var StandardHttpClient = class extends BaseHttpClient2 { /** * Create a new standard HTTP client. * @param baseUrl - The base URL for the API. * @param headers - Additional headers to include in requests. * @param timeout - Request timeout in milliseconds. * @param errorHandler - The error handler to use. * @param rateLimiter - Optional rate limiter for controlling request concurrency. * @param logger - Optional logger for logging events and errors. */ constructor(baseUrl = "https://api.venice.ai/api/v1", headers = {}, timeout = 3e4, errorHandler = new ErrorHandler(), rateLimiter, logger) { super(baseUrl, headers, timeout); this.errorHandler = errorHandler; this.rateLimiter = rateLimiter; this.logger = logger; if (this.logger) { this.logger.debug("Initializing standard HTTP client", { baseUrl, timeout }); } this.client = import_axios2.default.create({ baseURL: baseUrl, timeout, headers: this.headers }); } /** * Set an authorization header with a bearer token. * @param token - The API key or token. */ setAuthToken(token) { super.setAuthToken(token); this.client.defaults.headers.common["Authorization"] = `Bearer ${token}`; } /** * Set a custom header for future requests. * @param name - The header name. * @param value - The header value. */ setHeader(name, value) { super.setHeader(name, value); this.client.defaults.headers.common[name] = value; } /** * Make an HTTP request. * @param path - The API path (will be appended to the base URL). * @param options - Request options. * @returns The response data. */ async request(path, options = {}) { const { method = "GET", headers = {}, body, query, timeout, responseType = "json", signal } = options; const config = { method, url: path, headers, params: query, data: body, responseType, signal }; if (timeout) { config.timeout = timeout; } if (this.logger) { this.logger.debug(`Preparing ${method} request to ${path}`, { params: query, headers }); } const makeRequest = async () => { try { const response = await this.client.request(config); if (this.logger) { this.logger.debug(`${method} request to ${path} succeeded`, { status: response.status }); } return { data: response.data, status: response.status, statusText: response.statusText, headers: response.headers }; } catch (error) { if (this.logger) { this.logger.error(`${method} request to ${path} failed`, { error: error.message }); } return this.errorHandler.handleRequestError(error); } }; if (this.rateLimiter) { if (this.logger) { this.logger.debug(`Rate limiting ${method} request to ${path}`); } return this.rateLimiter.add(makeRequest); } else { return makeRequest(); } } /** * Make a GET request. * @param path - The API path. * @param options - Request options. * @returns The response data. */ async get(path, options = {}) { return this.request(path, { ...options, method: "GET" }); } /** * Make a POST request. * @param path - The API path. * @param body - The request body. * @param options - Additional request options. * @returns The response data. */ async post(path, body, options = {}) { return this.request(path, { ...options, method: "POST", body }); } /** * Make a DELETE request. * @param path - The API path. * @param options - Request options. * @returns The response data. */ async delete(path, options = {}) { return this.request(path, { ...options, method: "DELETE" }); } }; // src/http/streaming/streaming-http-client.ts var StreamingHttpClient = class extends BaseHttpClient2 { /** * Create a new streaming HTTP client. * @param baseUrl - The base URL for the API. * @param headers - Additional headers to include in requests. * @param timeout - Request timeout in milliseconds. * @param errorHandler - The error handler to use. * @param rateLimiter - Optional rate limiter for controlling request concurrency. * @param logger - Optional logger for logging events and errors. */ constructor(baseUrl = "https://api.venice.ai/api/v1", headers = {}, timeout = 3e4, errorHandler = new ErrorHandler(), rateLimiter, logger) { super(baseUrl, headers, timeout); this.errorHandler = errorHandler; this.rateLimiter = rateLimiter; this.logger = logger; if (this.logger) { this.logger.debug("Initializing streaming HTTP client", { baseUrl, timeout }); } } /** * Create a new stream request. * @param path - The API path. * @param body - The request body. * @param options - Additional request options. * @returns A fetch response for streaming. */ async stream(path, body, options = {}) { const url = `${this.baseUrl}${path}`; const authHeader = this.headers["Authorization"]; const headers = { "Content-Type": "application/json", ...this.headers, ...options.headers }; if (this.logger) { this.logger.debug(`Preparing streaming request to ${path}`, { headers: { ...headers, Authorization: authHeader ? "Bearer [REDACTED]" : void 0 } }); } const makeRequest = async () => { try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), options.timeout || this.timeout); if (this.logger) { this.logger.debug(`Sending streaming request to ${path}`); } const response = await fetch(url, { method: "POST", headers, body: JSON.stringify(body), signal: options.signal || controller.signal }); clearTimeout(timeoutId); if (this.logger) { this.logger.debug(`Streaming request to ${path} received response`, { status: response.status, statusText: response.statusText }); } await this.errorHandler.handleResponseError(response); return response; } catch (error) { if (this.logger) { this.logger.error(`Streaming request to ${path} failed`, { error: error.message }); } return this.errorHandler.handleStreamError(error); } }; if (this.rateLimiter) { if (this.logger) { this.logger.debug(`Rate limiting streaming request to ${path}`); } return this.rateLimiter.add(makeRequest); } else { return makeRequest(); } } /** * Process a stream response as a readable stream of events. * @param response - The fetch response. * @param onEvent - Callback for each event. * @param onComplete - Callback when the stream completes. * @param onError - Callback when an error occurs. */ async processStream(response, onEvent, onComplete, onError) { if (this.logger) { this.logger.debug("Processing stream response"); } try { const reader = response.body?.getReader(); if (!reader) { const errorMsg = "Response body is not readable"; if (this.logger) { this.logger.error(errorMsg); } throw new Error(errorMsg); } const decoder = new TextDecoder(); let buffer = ""; let eventCount = 0; if (this.logger) { this.logger.debug("Starting to read stream"); } while (true) { const { done, value } = await reader.read(); if (done) { if (buffer.trim()) { try { const event = JSON.parse(buffer); onEvent(event); eventCount++; } catch (e) { if (this.logger) { this.logger.debug("Ignoring parsing error for incomplete data at stream end"); } } } break; } buffer += decoder.decode(value, { stream: true }); let newlineIndex; while ((newlineIndex = buffer.indexOf("\n")) !== -1) { const line = buffer.slice(0, newlineIndex).trim(); buffer = buffer.slice(newlineIndex + 1); if (line) { try { const event = JSON.parse(line); onEvent(event); eventCount++; if (this.logger && eventCount % 10 === 0) { this.logger.debug(`Processed ${eventCount} stream events`); } } catch (e) { const errorMsg = `Failed to parse event: ${line}`; if (this.logger) { this.logger.error(errorMsg); } if (onError) { onError(new Error(errorMsg)); } } } } } if (this.logger) { this.logger.debug(`Stream processing complete, processed ${eventCount} events`); } if (onComplete) { onComplete(); } } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); if (this.logger) { this.logger.error(`Stream processing error: ${errorMsg}`); } if (onError) { onError(error instanceof Error ? error : new Error(String(error))); } else { throw error; } } } }; // src/http/factory/http-client-factory.ts var HttpClientFactory = class { /** * Create a new HTTP client factory. * @param baseUrl - The base URL for the API. * @param headers - Additional headers to include in requests. * @param timeout - Request timeout in milliseconds. * @param rateLimiter - Optional rate limiter for controlling request concurrency. * @param logger - Optional logger for logging events and errors. */ constructor(baseUrl = "https://api.venice.ai/api/v1", headers = {}, timeout = 3e4, rateLimiter, logger) { this.baseUrl = baseUrl; this.headers = headers; this.timeout = timeout; this.errorHandler = new ErrorHandler(); this.rateLimiter = rateLimiter; this.logger = logger; if (this.logger) { this.logger.debug("Initializing HTTP client factory", { baseUrl, timeout }); } } /** * Create a standard HTTP client. * @returns A new standard HTTP client. */ createStandardClient() { if (this.logger) { this.logger.debug("Creating standard HTTP client"); } return new StandardHttpClient( this.baseUrl, this.headers, this.timeout, this.errorHandler, this.rateLimiter, this.logger ); } /** * Create a streaming HTTP client. * @returns A new streaming HTTP client. */ createStreamingClient() { if (this.logger) { this.logger.debug("Creating streaming HTTP client"); } return new StreamingHttpClient( this.baseUrl, this.headers, this.timeout, this.errorHandler, this.rateLimiter, this.logger ); } /** * Set the base URL for all created clients. * @param baseUrl - The base URL. */ setBaseUrl(baseUrl) { this.baseUrl = baseUrl; } /** * Set headers for all created clients. * @param headers - The headers. */ setHeaders(headers) { this.headers = headers; } /** * Set a specific header for all created clients. * @param name - The header name. * @param value - The header value. */ setHeader(name, value) { this.headers[name] = value; } /** * Set the timeout for all created clients. * @param timeout - The timeout in milliseconds. */ setTimeout(timeout) { this.timeout = timeout; } /** * Set the authorization token for all created clients. * @param token - The API key or token. */ setAuthToken(token) { this.headers["Authorization"] = `Bearer ${token}`; } }; // src/utils/rate-limiter.ts var RateLimiter = class { /** * Creates a new rate limiter. * * @param maxConcurrent - Maximum number of concurrent requests * @param requestsPerMinute - Maximum requests per minute */ constructor(maxConcurrent = 5, requestsPerMinute = 60) { /** * Queue of pending requests. */ this.queue = []; /** * Number of currently running requests. */ this.running = 0; /** * Timestamps of recent requests for rate limiting. */ this.requestTimestamps = []; this.maxConcurrent = maxConcurrent; this.requestsPerMinute = requestsPerMinute; } /** * Adds a request to the rate limiter. * * @param fn - The request function to execute * @returns A promise resolving to the request result * @throws {VeniceRateLimitError} If the rate limit is exceeded */ async add(fn) { this.enforceRateLimit(); if (this.running >= this.maxConcurrent) { return new Promise((resolve, reject) => { this.queue.push(async () => { try { const result = await fn(); resolve(result); } catch (error) { reject(error); } }); }); } this.running++; try { const result = await fn(); this.recordRequest(); return result; } finally { this.running--; this.processQueue(); } } /** * Processes the next request in the queue. */ processQueue() { if (this.queue.length > 0 && this.running < this.maxConcurrent) { const next = this.queue.shift(); if (next) { this.running++; next().finally(() => { this.running--; this.processQueue(); }); } } } /** * Records a request for rate limiting. */ recordRequest() { const now = Date.now(); this.requestTimestamps.push(now); const oneMinuteAgo = now - 6e4; this.requestTimestamps = this.requestTimestamps.filter((t) => t > oneMinuteAgo); } /** * Enforces the rate limit. * * @throws {VeniceRateLimitError} If the rate limit is exceeded */ enforceRateLimit() { const now = Date.now(); const oneMinuteAgo = now - 6e4; this.requestTimestamps = this.requestTimestamps.filter((t) => t > oneMinuteAgo); if (this.requestTimestamps.length >= this.requestsPerMinute) { const oldestTimestamp = this.requestTimestamps[0]; const waitTime = 6e4 - (now - oldestTimestamp); throw new VeniceRateLimitError( `Rate limit exceeded. Try again in ${Math.ceil(waitTime / 1e3)} seconds.` ); } } }; // src/client.ts var VeniceClient = class { /** * Create a new Venice API client. * @param config - The client configuration. */ constructor(config = {}) { this.configManager = new ConfigManager(config); this.eventManager = new EventManager(); this.logger = new Logger({ level: config.logLevel || 1 /* INFO */ }); if (config.logLevel !== 4 /* NONE */) { this.logger.info("Initializing Venice AI client", { baseUrl: config.baseUrl || "https://api.venice.ai/api/v1", timeout: config.timeout || 3e4 }); } this.rateLimiter = new RateLimiter( config.maxConcurrent || 5, config.requestsPerMinute || 60 ); this.logger.debug("Rate limiter initialized", { maxConcurrent: config.maxConcurrent || 5, requestsPerMinute: config.requestsPerMinute || 60 }); this.httpClientFactory = new HttpClientFactory( this.configManager.getBaseUrl(), this.configManager.getHeaders(), this.configManager.getTimeout(), this.rateLimiter, this.logger ); this.standardHttpClient = this.httpClientFactory.createStandardClient(); this.streamingHttpClient = this.httpClientFactory.createStreamingClient(); const apiKey = this.configManager.getApiKey(); if (apiKey) { this.setApiKey(apiKey); this.logger.debug("API key set from config"); } } /** * Set the API key for authentication. * @param apiKey - The Venice API key. */ setApiKey(apiKey) { this.logger.debug("Setting API key"); try { this.configManager.setApiKey(apiKey); this.httpClientFactory.setAuthToken(apiKey); this.standardHttpClient.setAuthToken(apiKey); this.streamingHttpClient.setAuthToken(apiKey); this.logger.debug("API key set successfully"); } catch (error) { this.logger.error("Failed to set API key", { error }); throw error; } } /** * Get the current API key. * @returns The current API key or undefined if not set. */ getApiKey() { return this.configManager.getApiKey(); } /** * Set a custom header for API requests. * @param name - The header name. * @param value - The header value. */ setHeader(name, value) { this.logger.debug(`Setting header: ${name}`); this.configManager.setHeader(name, value); this.httpClientFactory.setHeader(name, value); this.logger.debug(`Header set: ${name}`); } /** * Get the standard HTTP client for making API requests. * @returns The standard HTTP client. */ getStandardHttpClient() { return this.standardHttpClient; } /** * Get the streaming HTTP client for making streaming API requests. * @returns The streaming HTTP client. */ getStreamingHttpClient() { return this.streamingHttpClient; } /** * Subscribe to a client event. * @param event - The event name. * @param