import { logger } from '@librechat/data-schemas'; import { CohereConstants } from 'librechat-data-provider'; /** * Extracts a valid OpenAI baseURL from a given string, matching "url/v1," followed by an optional suffix. * The suffix can be one of several predefined values (e.g., 'openai', 'azure-openai', etc.), * accommodating different proxy patterns like Cloudflare, LiteLLM, etc. * Returns the original URL if no valid pattern is found. * * Examples: * - `https://open.ai/v1/chat` -> `https://open.ai/v1` * - `https://open.ai/v1/chat/completions` -> `https://open.ai/v1` * - `https://gateway.ai.cloudflare.com/v1/account/gateway/azure-openai/completions` -> `https://gateway.ai.cloudflare.com/v1/account/gateway/azure-openai` * - `https://open.ai/v1/hi/openai` -> `https://open.ai/v1/hi/openai` * - `https://api.example.com/v1/replicate` -> `https://api.example.com/v1/replicate` * * @param url - The URL to be processed. * @returns The matched pattern or input if no match is found. */ export function extractBaseURL(url: string): string | null | undefined { if (!url || typeof url !== 'string') { return undefined; } if (url.startsWith(CohereConstants.API_URL)) { return null; } if (!url.includes('/v1')) { return url; } const v1Index = url.indexOf('/v1'); let baseUrl = url.substring(0, v1Index + 3); const openai = 'openai'; const suffixes = [ 'azure-openai', openai, 'aws-bedrock', 'anthropic', 'cohere', 'deepseek', 'google-ai-studio', 'google-vertex-ai', 'grok', 'groq', 'mistral', 'openrouter', 'perplexity-ai', 'replicate', 'huggingface', 'workers-ai', 'aws-bedrock', ]; const suffixUsed = suffixes.find((suffix) => url.includes(`/${suffix}`)); if (suffixUsed === 'azure-openai') { return url.split(/\/(chat|completion)/)[0]; } const openaiIndex = url.indexOf(`/${openai}`, v1Index + 3); const suffixIndex = suffixUsed === openai ? openaiIndex : url.indexOf(`/${suffixUsed}`, v1Index + 3); if (openaiIndex === v1Index + 3) { const nextSlashIndex = url.indexOf('/', openaiIndex + 7); if (nextSlashIndex === -1) { baseUrl = url.substring(0, openaiIndex + 7); } else { baseUrl = url.substring(0, nextSlashIndex); } } else if (suffixIndex > 0) { baseUrl = url.substring(0, suffixIndex + (suffixUsed?.length ?? 0) + 1); } return baseUrl; } /** * Extracts the base URL (protocol + hostname + port) from the provided URL. * Used primarily for Ollama endpoints to derive the host. * @param fullURL - The full URL. * @returns The base URL (protocol://hostname:port). */ export function deriveBaseURL(fullURL: string): string { try { const parsedUrl = new URL(fullURL); const protocol = parsedUrl.protocol; const hostname = parsedUrl.hostname; const port = parsedUrl.port; if (!protocol || !hostname) { return fullURL; } return `${protocol}//${hostname}${port ? `:${port}` : ''}`; } catch (error) { logger.error('Failed to derive base URL', error); return fullURL; } }