venice-dev-tools
Version:
unOfficial SDK for the Venice AI API
1,697 lines (1,665 loc) • 91.9 kB
JavaScript
"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