/** * Centralized proxy decision logic. * * Determines whether to use a CORS proxy for LLM API requests based on: * - Provider name * - API key pattern (for providers where it matters) */ /** * Check if a provider/API key combination requires a CORS proxy. * * @param provider - Provider name (e.g., "anthropic", "openai", "zai") * @param apiKey - API key for the provider * @returns true if proxy is required, false otherwise */ export function shouldUseProxyForProvider(provider, apiKey) { switch (provider.toLowerCase()) { case "zai": // Z-AI always requires proxy return true; case "anthropic": // Anthropic OAuth tokens (sk-ant-oat-*) require proxy // Regular API keys (sk-ant-api-*) do NOT require proxy return apiKey.startsWith("sk-ant-oat"); // These providers work without proxy case "openai": case "google": case "groq": case "openrouter": case "cerebras": case "xai": case "ollama": case "lmstudio": return false; // Unknown providers - assume no proxy needed // This allows new providers to work by default default: return false; } } /** * Apply CORS proxy to a model's baseUrl if needed. * * @param model - The model to potentially proxy * @param apiKey - API key for the provider * @param proxyUrl - CORS proxy URL (e.g., "https://proxy.mariozechner.at/proxy") * @returns Model with modified baseUrl if proxy is needed, otherwise original model */ export function applyProxyIfNeeded(model, apiKey, proxyUrl) { // If no proxy URL configured, return original model if (!proxyUrl) { return model; } // If model has no baseUrl, can't proxy it if (!model.baseUrl) { return model; } // Check if this provider/key needs proxy if (!shouldUseProxyForProvider(model.provider, apiKey)) { return model; } // Apply proxy to baseUrl return { ...model, baseUrl: `${proxyUrl}/?url=${encodeURIComponent(model.baseUrl)}`, }; } /** * Check if an error is likely a CORS error. * * CORS errors in browsers typically manifest as: * - TypeError with message "Failed to fetch" * - NetworkError * * @param error - The error to check * @returns true if error is likely a CORS error */ export function isCorsError(error) { if (!(error instanceof Error)) { return false; } // Check for common CORS error patterns const message = error.message.toLowerCase(); // "Failed to fetch" is the standard CORS error in most browsers if (error.name === "TypeError" && message.includes("failed to fetch")) { return true; } // Some browsers report "NetworkError" if (error.name === "NetworkError") { return true; } // CORS-specific messages if (message.includes("cors") || message.includes("cross-origin")) { return true; } return false; } //# sourceMappingURL=proxy-utils.js.map