Files
clawdbot/apps/macos/Sources/Clawdis/Resources/WebChat/utils/proxy-utils.js
2025-12-06 05:01:28 +01:00

97 lines
3.0 KiB
JavaScript

/**
* 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