litellm-js
Version:
Universal JavaScript client for LLM APIs
1 lines • 61.1 kB
Source Map (JSON)
{"version":3,"file":"litellm.mjs","sources":["../src/types.js","../src/client.js","../src/provider.js","../src/providers/openai.js","../src/providers/anthropic.js","../src/litellm.js"],"sourcesContent":["/**\n * @typedef {Object} LLMMessage\n * @property {string} role - The role of the message sender (system, user, assistant)\n * @property {string} content - The content of the message\n */\n\n/**\n * @typedef {Object} CompletionOptions\n * @property {string} model - The name of the model to use\n * @property {Array<LLMMessage>} messages - Array of messages to generate completions for\n * @property {number} [temperature=0.7] - Sampling temperature\n * @property {number} [max_tokens] - Maximum number of tokens to generate\n * @property {boolean} [stream=false] - Whether to stream the response\n * @property {Object} [additional_params] - Any additional provider-specific parameters\n */\n\n/**\n * @typedef {Object} LLMProvider\n * @property {string} name - Provider name\n * @property {string} baseUrl - Base URL for the provider's API\n * @property {Array<string>} models - List of supported models\n */\n\n/**\n * @typedef {Object} ProxyConfig\n * @property {string} name - The name of the proxy configuration\n * @property {Array<string>} models - List of models to route through this proxy\n * @property {string} url - The proxy URL\n * @property {Object} headers - Headers to include with requests to this proxy\n */\n\nexport const PROVIDER_TYPES = {\n OPENAI: 'openai',\n ANTHROPIC: 'anthropic',\n AZURE: 'azure',\n GOOGLE: 'google',\n COHERE: 'cohere',\n HUGGINGFACE: 'huggingface'\n};\n\nexport const MODEL_PREFIXES = {\n 'gpt': PROVIDER_TYPES.OPENAI,\n 'claude': PROVIDER_TYPES.ANTHROPIC,\n 'azure': PROVIDER_TYPES.AZURE,\n 'gemini': PROVIDER_TYPES.GOOGLE,\n 'palm': PROVIDER_TYPES.GOOGLE,\n 'command': PROVIDER_TYPES.COHERE\n};","import fetch from 'cross-fetch';\n\n/**\n * Universal HTTP client for making requests to LLM APIs\n */\nclass LiteLLMClient {\n /**\n * Make a request to an LLM API\n * \n * @param {string} url - The API endpoint\n * @param {Object} options - Request options\n * @param {Object} options.headers - HTTP headers\n * @param {string} options.method - HTTP method (GET, POST, etc.)\n * @param {Object|null} options.body - Request body (for POST, PUT, etc.)\n * @param {AbortSignal|null} options.signal - AbortController signal\n * @returns {Promise<Object>} - The API response\n */\n async request(url, options = {}) {\n const { headers = {}, method = 'GET', body = null, signal = null, stream = false } = options;\n \n const requestOptions = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers\n },\n signal\n };\n\n if (body) {\n requestOptions.body = JSON.stringify(body);\n }\n\n try {\n const response = await fetch(url, requestOptions);\n \n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new LiteLLMError(\n `API request failed with status ${response.status}`,\n response.status,\n errorData\n );\n }\n\n // If streaming is requested, return the raw response\n if (stream) {\n return response;\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof LiteLLMError) {\n throw error;\n }\n \n throw new LiteLLMError(\n `Request failed: ${error.message}`,\n 500,\n { originalError: error }\n );\n }\n }\n}\n\n/**\n * Custom error class for LiteLLM errors\n */\nclass LiteLLMError extends Error {\n constructor(message, status, data = {}) {\n super(message);\n this.name = 'LiteLLMError';\n this.status = status;\n this.data = data;\n }\n}\n\nexport default new LiteLLMClient();\nexport { LiteLLMClient, LiteLLMError };","import client from './client.js';\n\n/**\n * Base provider class for all LLM providers\n */\nclass Provider {\n /**\n * Initialize a new provider\n * \n * @param {Object} options - Provider options\n * @param {string} options.apiKey - API key for the provider\n * @param {string} [options.baseUrl] - Base URL for the provider's API\n * @param {Object} [options.defaultParams={}] - Default parameters for all requests\n */\n constructor(options = {}) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl || this.constructor.defaultBaseUrl;\n this.defaultParams = options.defaultParams || {};\n }\n\n /**\n * Generate a completion for the given messages\n * \n * @param {CompletionOptions} options - Completion options\n * @returns {Promise<Object>} - The completion response\n */\n async completion(options) {\n throw new Error('Not implemented');\n }\n\n /**\n * Generate a streaming completion for the given messages\n * \n * @param {CompletionOptions} options - Completion options\n * @returns {AsyncGenerator} - An async generator that yields completion chunks\n */\n async *streamCompletion(options) {\n throw new Error('Not implemented');\n }\n\n /**\n * Make a request to the provider's API\n * \n * @param {string} path - API path\n * @param {Object} options - Request options\n * @returns {Promise<Object>} - The API response\n */\n async makeRequest(path, options = {}) {\n const url = `${this.baseUrl}${path}`;\n const headers = {\n ...this._getAuthHeaders(),\n ...options.headers\n };\n\n return await client.request(url, {\n ...options,\n headers\n });\n }\n\n /**\n * Get authentication headers for the provider\n * \n * @returns {Object} - Authentication headers\n */\n _getAuthHeaders() {\n throw new Error('Not implemented');\n }\n\n /**\n * Transform messages to provider-specific format\n * \n * @param {Array<LLMMessage>} messages - Messages to transform\n * @returns {Array<Object>} - Transformed messages\n */\n _transformMessages(messages) {\n return messages;\n }\n\n /**\n * Transform options to provider-specific format\n * \n * @param {CompletionOptions} options - Options to transform\n * @returns {Object} - Transformed options\n */\n _transformOptions(options) {\n return {\n ...this.defaultParams,\n ...options,\n messages: this._transformMessages(options.messages)\n };\n }\n\n /**\n * Check if the provider supports the given model\n * \n * @param {string} model - Model name to check\n * @returns {boolean} - True if the provider supports the model\n */\n supportsModel(model) {\n return false;\n }\n}\n\nexport default Provider;","import Provider from '../provider.js';\nimport { PROVIDER_TYPES } from '../types.js';\n\nclass OpenAIProvider extends Provider {\n static defaultBaseUrl = 'https://api.openai.com/v1';\n static providerType = PROVIDER_TYPES.OPENAI;\n \n /**\n * Initialize a new OpenAI provider\n * \n * @param {Object} options - Provider options\n * @param {string} options.apiKey - OpenAI API key\n * @param {string} [options.baseUrl] - Base URL for the OpenAI API\n * @param {Object} [options.defaultParams={}] - Default parameters for all requests\n */\n constructor(options = {}) {\n super(options);\n }\n\n /**\n * Generate a completion for the given messages\n * \n * @param {CompletionOptions} options - Completion options\n * @returns {Promise<Object>} - The completion response\n */\n async completion(options) {\n const transformedOptions = this._transformOptions(options);\n \n return await this.makeRequest('/chat/completions', {\n method: 'POST',\n body: transformedOptions\n });\n }\n\n /**\n * Generate a streaming completion for the given messages\n * \n * @param {CompletionOptions} options - Completion options\n * @returns {AsyncGenerator} - An async generator that yields completion chunks\n */\n async *streamCompletion(options) {\n const transformedOptions = this._transformOptions({\n ...options,\n stream: true\n });\n \n const response = await this.makeRequest('/chat/completions', {\n method: 'POST',\n body: transformedOptions,\n stream: true\n });\n\n // Handle streaming in a way that works in both Node.js and browser environments\n if (typeof response.body === 'object' && response.body !== null) {\n // Browser environment or Node.js with fetch that supports ReadableStream\n if (typeof response.body.getReader === 'function') {\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8');\n \n try {\n while (true) {\n const { done, value } = await reader.read();\n \n if (done) {\n break;\n }\n \n const chunk = decoder.decode(value);\n yield* this._processChunk(chunk);\n }\n } finally {\n reader.releaseLock();\n }\n } \n // Node.js environment with response.body as a Node.js Readable stream\n else if (typeof response.body.on === 'function') {\n const chunks = [];\n for await (const chunk of response.body) {\n const strChunk = new TextDecoder('utf-8').decode(chunk);\n yield* this._processChunk(strChunk);\n }\n }\n } else if (typeof response.text === 'function') {\n // Fallback for environments where we can't directly access the stream\n const text = await response.text();\n yield* this._processChunk(text);\n }\n }\n\n /**\n * Process a text chunk from a stream\n * \n * @private\n * @param {string} chunk - The text chunk to process\n * @returns {Array} - Array of parsed JSON objects from the chunk\n */\n *_processChunk(chunk) {\n const lines = chunk\n .split('\\n')\n .filter(line => line.trim().startsWith('data:'))\n .map(line => line.replace(/^data: /, '').trim());\n \n for (const line of lines) {\n if (line === '[DONE]') {\n return;\n }\n \n try {\n if (line) {\n const parsed = JSON.parse(line);\n yield parsed;\n }\n } catch (e) {\n console.error('Error parsing SSE line:', line, e);\n }\n }\n }\n\n /**\n * Get authentication headers for OpenAI\n * \n * @returns {Object} - OpenAI authentication headers\n */\n _getAuthHeaders() {\n return {\n 'Authorization': `Bearer ${this.apiKey}`\n };\n }\n\n /**\n * Check if OpenAI supports the given model\n * \n * @param {string} model - Model name to check\n * @returns {boolean} - True if OpenAI supports the model\n */\n supportsModel(model) {\n return model.startsWith('gpt-') || \n model.startsWith('text-') ||\n model === 'dall-e-3';\n }\n}\n\nexport default OpenAIProvider;","import Provider from '../provider.js';\nimport { PROVIDER_TYPES } from '../types.js';\n\nclass AnthropicProvider extends Provider {\n static defaultBaseUrl = 'https://api.anthropic.com/v1';\n static providerType = PROVIDER_TYPES.ANTHROPIC;\n \n /**\n * Initialize a new Anthropic provider\n * \n * @param {Object} options - Provider options\n * @param {string} options.apiKey - Anthropic API key\n * @param {string} [options.baseUrl] - Base URL for the Anthropic API\n * @param {Object} [options.defaultParams={}] - Default parameters for all requests\n */\n constructor(options = {}) {\n super(options);\n this.defaultVersion = options.version || '2023-06-01';\n }\n\n /**\n * Generate a completion for the given messages\n * \n * @param {CompletionOptions} options - Completion options\n * @returns {Promise<Object>} - The completion response\n */\n async completion(options) {\n const transformedOptions = this._transformOptions(options);\n \n const response = await this.makeRequest('/messages', {\n method: 'POST',\n body: transformedOptions\n });\n \n // Convert Anthropic response format to OpenAI format\n return this._convertResponseToOpenAIFormat(response, options);\n }\n\n /**\n * Generate a streaming completion for the given messages\n * \n * @param {CompletionOptions} options - Completion options\n * @returns {AsyncGenerator} - An async generator that yields completion chunks\n */\n async *streamCompletion(options) {\n const transformedOptions = this._transformOptions({\n ...options,\n stream: true\n });\n \n const response = await this.makeRequest('/messages', {\n method: 'POST',\n body: transformedOptions,\n stream: true\n });\n\n // Handle streaming in a way that works in both Node.js and browser environments\n if (typeof response.body === 'object' && response.body !== null) {\n // Browser environment or Node.js with fetch that supports ReadableStream\n if (typeof response.body.getReader === 'function') {\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8');\n \n try {\n while (true) {\n const { done, value } = await reader.read();\n \n if (done) {\n break;\n }\n \n const chunk = decoder.decode(value);\n const processedChunks = this._processChunk(chunk);\n \n for (const processedChunk of processedChunks) {\n // Convert each Anthropic chunk to OpenAI format\n yield this._convertStreamChunkToOpenAIFormat(processedChunk, options);\n }\n }\n } finally {\n reader.releaseLock();\n }\n } \n // Node.js environment with response.body as a Node.js Readable stream\n else if (typeof response.body.on === 'function') {\n for await (const chunk of response.body) {\n const strChunk = new TextDecoder('utf-8').decode(chunk);\n const processedChunks = this._processChunk(strChunk);\n \n for (const processedChunk of processedChunks) {\n // Convert each Anthropic chunk to OpenAI format\n yield this._convertStreamChunkToOpenAIFormat(processedChunk, options);\n }\n }\n }\n } else if (typeof response.text === 'function') {\n // Fallback for environments where we can't directly access the stream\n const text = await response.text();\n const processedChunks = this._processChunk(text);\n \n for (const processedChunk of processedChunks) {\n // Convert each Anthropic chunk to OpenAI format\n yield this._convertStreamChunkToOpenAIFormat(processedChunk, options);\n }\n }\n }\n\n /**\n * Process a text chunk from a stream\n * \n * @private\n * @param {string} chunk - The text chunk to process\n * @returns {Array} - Array of parsed JSON objects from the chunk\n */\n _processChunk(chunk) {\n const result = [];\n const lines = chunk\n .split('\\n')\n .filter(line => line.trim().startsWith('data:'))\n .map(line => line.replace(/^data: /, '').trim());\n \n for (const line of lines) {\n if (line === '[DONE]') {\n continue;\n }\n \n try {\n if (line) {\n const parsed = JSON.parse(line);\n result.push(parsed);\n }\n } catch (e) {\n console.error('Error parsing SSE line:', line, e);\n }\n }\n \n return result;\n }\n\n /**\n * Convert Anthropic stream chunk to OpenAI format\n * \n * @private\n * @param {Object} chunk - Anthropic format chunk\n * @param {Object} options - Original request options\n * @returns {Object} - OpenAI format chunk\n */\n _convertStreamChunkToOpenAIFormat(chunk, options) {\n // Generate a unique ID if needed\n const id = `chatcmpl-${Date.now().toString(36)}${Math.random().toString(36).substr(2, 5)}`;\n \n // Default structure for OpenAI format\n const openAIFormat = {\n id: id,\n object: 'chat.completion.chunk',\n created: Math.floor(Date.now() / 1000),\n model: options.model,\n choices: [\n {\n index: 0,\n delta: {},\n finish_reason: null\n }\n ]\n };\n\n // Handle different Anthropic SSE event types\n if (chunk.type === 'content_block_start') {\n // Content block start doesn't contain actual content yet\n return openAIFormat;\n } \n else if (chunk.type === 'content_block_delta') {\n if (chunk.delta.type === 'text_delta' && chunk.delta.text) {\n openAIFormat.choices[0].delta.content = chunk.delta.text;\n }\n // Handle tool calls in streaming mode\n else if (chunk.delta.type === 'tool_use') {\n // For tool_use, we need to convert to function_call format\n openAIFormat.choices[0].delta.function_call = {\n name: chunk.delta.name || '',\n arguments: chunk.delta.input ? JSON.stringify(chunk.delta.input) : ''\n };\n openAIFormat.choices[0].finish_reason = 'function_call';\n }\n } \n else if (chunk.type === 'content_block_stop') {\n // End of a content block\n openAIFormat.choices[0].finish_reason = 'stop';\n }\n else if (chunk.type === 'message_stop') {\n // End of the entire message\n openAIFormat.choices[0].finish_reason = 'stop';\n }\n \n return openAIFormat;\n }\n\n /**\n * Convert complete Anthropic response to OpenAI format\n * \n * @private\n * @param {Object} response - Anthropic format response\n * @param {Object} options - Original request options\n * @returns {Object} - OpenAI format response\n */\n _convertResponseToOpenAIFormat(response, options) {\n // Generate a unique ID if needed\n const id = `chatcmpl-${Date.now().toString(36)}${Math.random().toString(36).substr(2, 5)}`;\n \n // Extract content and handle different content types\n let content = null;\n let functionCall = null;\n \n if (response.content && Array.isArray(response.content)) {\n // Process different types of content blocks\n for (const block of response.content) {\n if (block.type === 'text') {\n content = block.text;\n } \n else if (block.type === 'tool_use') {\n // Convert tool_use to function_call\n functionCall = {\n name: block.name,\n arguments: JSON.stringify(block.input)\n };\n }\n }\n }\n \n // Map Anthropic stop_reason to OpenAI finish_reason\n let finishReason = 'stop';\n if (response.stop_reason === 'tool_use') {\n finishReason = 'function_call';\n } else if (response.stop_reason === 'max_tokens') {\n finishReason = 'length';\n }\n \n // Build message object\n const message = {\n role: 'assistant',\n content: content\n };\n \n // Add function_call if present\n if (functionCall) {\n message.function_call = functionCall;\n message.content = null; // OpenAI sets content to null when there's a function call\n }\n \n // Create OpenAI-format response\n return {\n id: id,\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: options.model,\n choices: [\n {\n index: 0,\n message: message,\n finish_reason: finishReason\n }\n ],\n usage: {\n prompt_tokens: response.usage?.input_tokens || 0,\n completion_tokens: response.usage?.output_tokens || 0,\n total_tokens: (response.usage?.input_tokens || 0) + (response.usage?.output_tokens || 0)\n }\n };\n }\n\n /**\n * Get authentication headers for Anthropic\n * \n * @returns {Object} - Anthropic authentication headers\n */\n _getAuthHeaders() {\n return {\n 'X-API-Key': this.apiKey,\n 'anthropic-version': this.defaultVersion\n };\n }\n\n /**\n * Transform messages to Anthropic-specific format\n * \n * @param {Array<LLMMessage>} messages - Messages to transform\n * @returns {Array<Object>} - Transformed messages\n */\n _transformMessages(messages) {\n if (!messages || !Array.isArray(messages)) {\n return [];\n }\n \n // Anthropic uses a different format for messages\n // Extract system message if present\n let systemMessage = '';\n const formattedMessages = [];\n \n for (const message of messages) {\n if (message.role === 'system') {\n systemMessage = message.content;\n } else if (message.role === 'user' || message.role === 'assistant') {\n formattedMessages.push({\n role: message.role,\n content: message.content\n });\n \n // Handle function calls from user (tool results)\n if (message.role === 'user' && message.function_call_result) {\n formattedMessages.push({\n role: 'tool',\n name: message.function_call_result.name,\n content: message.function_call_result.content\n });\n }\n \n // Handle function calls from assistant\n if (message.role === 'assistant' && message.function_call) {\n // Anthropic expects tool_use inside the content array\n formattedMessages.push({\n role: 'assistant',\n content: [{\n type: 'tool_use',\n name: message.function_call.name,\n input: JSON.parse(message.function_call.arguments)\n }]\n });\n }\n }\n }\n \n return formattedMessages;\n }\n\n /**\n * Transform options to Anthropic-specific format\n * \n * @param {CompletionOptions} options - Options to transform\n * @returns {Object} - Transformed options for Anthropic\n */\n _transformOptions(options) {\n const messages = this._transformMessages(options.messages);\n \n const transformed = {\n ...this.defaultParams,\n model: options.model,\n messages: messages,\n stream: options.stream || false,\n };\n \n // Extract all system messages and combine them if there are multiple\n const systemMessages = options.messages?.filter(m => m.role === 'system') || [];\n if (systemMessages.length > 1) {\n // Multiple system messages, combine them into a single system message\n const combinedContent = systemMessages.map(m => m.content).join('\\n');\n transformed.system = combinedContent;\n\n // Remove all system messages and add a single combined one\n options.messages = options.messages.filter(m => m.role !== 'system');\n }\n\n // Add completion parameters\n // max_tokens is required for Anthropic\n transformed.max_tokens = options.max_tokens || 2048;\n transformed.stop = options.stop || ['stop', 'max_tokens'];\n if (options.temperature !== undefined) {\n transformed.temperature = options.temperature;\n }\n\n if (options.tools || options.functions) {\n // Convert OpenAI functions/tools to Anthropic tools\n const tools = options.tools || \n (options.functions ? [{ type: 'function', functions: options.functions }] : []);\n \n transformed.tools = tools.map(tool => {\n if (tool.type === 'function') {\n return {\n name: tool.function.name,\n description: tool.function.description,\n input_schema: tool.function.parameters\n };\n }\n return tool;\n });\n }\n\n if (options.additional_params) {\n Object.assign(transformed, options.additional_params);\n }\n\n return transformed;\n }\n\n /**\n * Check if Anthropic supports the given model\n * \n * @param {string} model - Model name to check\n * @returns {boolean} - True if Anthropic supports the model\n */\n supportsModel(model) {\n return model.startsWith('claude-');\n }\n}\n\nexport default AnthropicProvider;","import { MODEL_PREFIXES, PROVIDER_TYPES } from './types.js';\nimport OpenAIProvider from './providers/openai.js';\nimport AnthropicProvider from './providers/anthropic.js';\nimport { LiteLLMError } from './client.js';\n\n/**\n * LiteLLM class for unified access to various LLM providers\n */\nclass LiteLLM {\n /**\n * Initialize a new LiteLLM instance\n */\n constructor() {\n this.providers = {};\n this.proxies = [];\n }\n\n /**\n * Parse model string to extract provider and actual model name\n * Supports formats: \"provider/model\" and \"model\"\n * \n * @param {string} modelString - The model string to parse\n * @returns {Object} - Object with provider and model properties\n */\n parseModelString(modelString) {\n if (!modelString || typeof modelString !== 'string') {\n return { provider: null, model: modelString };\n }\n\n const parts = modelString.split('/');\n if (parts.length === 2 && parts[0] && parts[1]) {\n return {\n provider: parts[0].toLowerCase(),\n model: parts[1]\n };\n }\n\n return {\n provider: null,\n model: modelString\n };\n }\n\n /**\n * Register a provider for use with LiteLLM\n * \n * @param {string} type - Provider type (e.g., 'openai', 'anthropic')\n * @param {Object} options - Provider options\n * @returns {Provider} - The registered provider\n */\n registerProvider(type, options) {\n const providerType = type.toLowerCase();\n let provider;\n \n switch (providerType) {\n case PROVIDER_TYPES.OPENAI:\n provider = new OpenAIProvider(options);\n break;\n case PROVIDER_TYPES.ANTHROPIC:\n provider = new AnthropicProvider(options);\n break;\n // Add other providers here\n default:\n throw new LiteLLMError(`Unsupported provider type: ${type}`, 400);\n }\n \n this.providers[providerType] = provider;\n return provider;\n }\n\n /**\n * Register a proxy configuration\n * \n * @param {ProxyConfig} proxyConfig - Proxy configuration\n */\n registerProxy(proxyConfig) {\n this.proxies.push(proxyConfig);\n }\n\n /**\n * Determine the provider type from a model name\n * \n * @param {string} model - Model name\n * @returns {string|null} - Provider type or null if unknown\n */\n getProviderTypeForModel(model) {\n for (const [prefix, providerType] of Object.entries(MODEL_PREFIXES)) {\n if (model.startsWith(prefix)) {\n return providerType;\n }\n }\n return null;\n }\n\n /**\n * Get the appropriate proxy for a model\n * \n * @param {string} modelString - Model string (can be \"provider/model\" or just \"model\")\n * @returns {Object|null} - Proxy provider and model name or null if not found\n */\n getProxyForModel(modelString) {\n const { provider, model } = this.parseModelString(modelString);\n \n // Check if any proxy handles this model\n for (const proxy of this.proxies) {\n if (proxy.models.includes(model) || \n proxy.models.includes(modelString) || \n proxy.models.includes('*')) {\n return { \n provider: proxy.provider,\n actualModel: proxy.proxyModel || model\n };\n }\n }\n return null;\n }\n\n /**\n * Get the appropriate provider for a model\n * \n * @param {string} modelString - Model string (can be \"provider/model\" or just \"model\")\n * @returns {Object} - Object with provider and actualModel properties\n */\n getProviderForModel(modelString) {\n const { provider: explicitProvider, model: actualModel } = this.parseModelString(modelString);\n \n // Check if there's a proxy for this model\n const proxyResult = this.getProxyForModel(modelString);\n if (proxyResult) {\n return proxyResult;\n }\n\n // If explicit provider is specified, try to use it\n if (explicitProvider && this.providers[explicitProvider]) {\n return { \n provider: this.providers[explicitProvider],\n actualModel\n };\n }\n\n // Find provider by model prefix\n const providerType = this.getProviderTypeForModel(actualModel || modelString);\n if (providerType && this.providers[providerType]) {\n return {\n provider: this.providers[providerType],\n actualModel: actualModel || modelString\n };\n }\n\n // Check all providers to see if any explicitly support this model\n for (const [name, provider] of Object.entries(this.providers)) {\n if (provider.supportsModel && provider.supportsModel(actualModel || modelString)) {\n return {\n provider,\n actualModel: actualModel || modelString\n };\n }\n }\n\n return { provider: null, actualModel: actualModel || modelString };\n }\n\n /**\n * Generate a completion for the given messages\n * \n * @param {CompletionOptions} options - Completion options\n * @returns {Promise<Object>} - The completion response\n */\n async completion(options) {\n const { model: modelString } = options;\n const { provider, actualModel } = this.getProviderForModel(modelString);\n \n if (!provider) {\n throw new LiteLLMError(`No provider found for model: ${modelString}`, 400);\n }\n\n // Create a new options object with the actual model name\n const completionOptions = {\n ...options,\n model: actualModel\n };\n \n return await provider.completion(completionOptions);\n }\n\n /**\n * Generate a streaming completion for the given messages\n * \n * @param {CompletionOptions} options - Completion options\n * @returns {AsyncGenerator} - An async generator that yields completion chunks\n */\n async *streamCompletion(options) {\n const { model: modelString } = options;\n const { provider, actualModel } = this.getProviderForModel(modelString);\n \n if (!provider) {\n throw new LiteLLMError(`No provider found for model: ${modelString}`, 400);\n }\n\n // Create a new options object with the actual model name\n const completionOptions = {\n ...options,\n model: actualModel\n };\n \n yield* provider.streamCompletion(completionOptions);\n }\n\n /**\n * Process a text chunk from a stream\n * \n * @private\n * @param {string} chunk - The text chunk to process\n * @returns {Array} - Array of parsed JSON objects from the chunk\n */\n *_processChunk(chunk) {\n const lines = chunk\n .split('\\n')\n .filter(line => line.trim().startsWith('data:'))\n .map(line => line.replace(/^data: /, '').trim());\n \n for (const line of lines) {\n if (line === '[DONE]') {\n return;\n }\n \n try {\n if (line) {\n const parsed = JSON.parse(line);\n yield parsed;\n }\n } catch (e) {\n console.error('Error parsing SSE line:', line, e);\n }\n }\n }\n\n /**\n * Create a proxy provider\n * \n * @param {Object} options - Proxy options\n * @param {string} options.url - The proxy URL\n * @param {Object} options.headers - Headers to include with proxy requests\n * @param {Array<string>} options.models - List of models to route through this proxy\n * @param {string} options.name - The name of the proxy\n * @param {string} [options.proxyModel] - Optional model to use when making requests through the proxy\n * @returns {void}\n */\n createProxy(options) {\n const { url, headers = {}, models = ['*'], name, proxyModel = null } = options;\n const self = this;\n \n // Create a custom provider for this proxy\n const proxyProvider = {\n // Add properties to help identify this as a proxy provider\n isProxy: true, \n proxyName: name,\n providerType: 'proxy',\n \n completion: async (completionOptions) => {\n // If proxyModel is specified, use it instead of the requested model\n const finalOptions = {\n ...completionOptions,\n model: proxyModel || completionOptions.model\n };\n\n const response = await fetch(`${url}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers\n },\n body: JSON.stringify(finalOptions)\n });\n \n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new LiteLLMError(\n `Proxy request failed with status ${response.status}`,\n response.status,\n errorData\n );\n }\n \n return await response.json();\n },\n \n streamCompletion: async function* (completionOptions) {\n // If proxyModel is specified, use it instead of the requested model\n const finalOptions = {\n ...completionOptions,\n model: proxyModel || completionOptions.model,\n stream: true\n };\n\n const response = await fetch(`${url}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers\n },\n body: JSON.stringify(finalOptions)\n });\n \n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new LiteLLMError(\n `Proxy request failed with status ${response.status}`,\n response.status,\n errorData\n );\n }\n \n // Handle streaming in a way that works in both Node.js and browser environments\n if (typeof response.body === 'object' && response.body !== null) {\n // Browser environment or Node.js with fetch that supports ReadableStream\n if (typeof response.body.getReader === 'function') {\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8');\n \n try {\n while (true) {\n const { done, value } = await reader.read();\n \n if (done) {\n break;\n }\n \n const chunk = decoder.decode(value);\n yield* self._processChunk(chunk);\n }\n } finally {\n reader.releaseLock();\n }\n } \n // Node.js environment with response.body as a Node.js Readable stream\n else if (typeof response.body.on === 'function') {\n for await (const chunk of response.body) {\n const strChunk = new TextDecoder('utf-8').decode(chunk);\n yield* self._processChunk(strChunk);\n }\n }\n } else if (typeof response.text === 'function') {\n // Fallback for environments where we can't directly access the stream\n const text = await response.text();\n yield* self._processChunk(text);\n }\n }\n };\n \n // Register this proxy\n this.registerProxy({\n name,\n models,\n url,\n headers,\n provider: proxyProvider,\n proxyModel // Store the proxyModel with the proxy configuration\n });\n\n console.log(`Proxy '${name}' registered for models: ${models.join(', ')}${proxyModel ? ` (using proxyModel: ${proxyModel})` : ''}`);\n }\n}\n\n// Create and export a singleton instance\nconst liteLLM = new LiteLLM();\n\nexport default liteLLM;\nexport { LiteLLM };"],"names":["fetch"],"mappings":"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