Spaces:
Runtime error
Runtime error
| // URL/format normalizers for provider key validation. Pure string helpers extracted from | |
| // validation.ts (god-file decomposition): no I/O, no side effects — they only shape base URLs | |
| // and chat endpoints per provider format. Behavior is byte-identical to the original inline defs. | |
| import { | |
| stripAnthropicMessagesSuffix, | |
| stripClaudeCodeCompatibleEndpointSuffix, | |
| } from "@omniroute/open-sse/services/claudeCodeCompatible.ts"; | |
| import { isOpenAICompatibleProvider } from "@/shared/constants/providers"; | |
| export const OPENAI_LIKE_FORMATS = new Set(["openai", "openai-responses"]); | |
| export const GEMINI_LIKE_FORMATS = new Set(["gemini", "gemini-cli"]); | |
| export function normalizeBaseUrl(baseUrl: string) { | |
| // Guard against a non-string baseUrl reaching .trim() / .replace() — see #2463 | |
| // where NVIDIA NIM validation surfaced as `e.startsWith is not a function` | |
| // after the bundler renamed `baseUrl` to `e`. Any malformed providerSpecificData | |
| // (e.g. saved as object from a UI bug) would otherwise crash mid-validation. | |
| const value = typeof baseUrl === "string" ? baseUrl : ""; | |
| return value.trim().replace(/\/$/, ""); | |
| } | |
| export function normalizeAzureOpenAIBaseUrl(baseUrl: string) { | |
| return normalizeBaseUrl(baseUrl) | |
| .replace(/\/openai$/i, "") | |
| .replace(/\/openai\/deployments\/[^/]+\/chat\/completions.*$/i, ""); | |
| } | |
| export function normalizeAnthropicBaseUrl(baseUrl: string) { | |
| return stripAnthropicMessagesSuffix(baseUrl || ""); | |
| } | |
| export function normalizeClaudeCodeCompatibleBaseUrl(baseUrl: string) { | |
| return stripClaudeCodeCompatibleEndpointSuffix(baseUrl || ""); | |
| } | |
| export function addModelsSuffix(baseUrl: string) { | |
| const normalized = normalizeBaseUrl(baseUrl); | |
| if (!normalized) return ""; | |
| const suffixes = ["/chat/completions", "/responses", "/chat", "/messages"]; | |
| if (normalized.endsWith("/models")) { | |
| return normalized; | |
| } | |
| for (const suffix of suffixes) { | |
| if (normalized.endsWith(suffix)) { | |
| return `${normalized.slice(0, -suffix.length)}/models`; | |
| } | |
| } | |
| return `${normalized}/models`; | |
| } | |
| export function resolveBaseUrl(entry: any, providerSpecificData: any = {}) { | |
| if (providerSpecificData?.baseUrl) return normalizeBaseUrl(providerSpecificData.baseUrl); | |
| if (entry?.baseUrl) return normalizeBaseUrl(entry.baseUrl); | |
| return ""; | |
| } | |
| export function resolveChatUrl(provider: string, baseUrl: string, providerSpecificData: any = {}) { | |
| const normalized = normalizeBaseUrl(baseUrl); | |
| if (!normalized) return ""; | |
| if (isOpenAICompatibleProvider(provider)) { | |
| if (providerSpecificData?.chatPath) { | |
| return `${normalized}${providerSpecificData.chatPath}`; | |
| } | |
| if (providerSpecificData?.apiType === "responses") { | |
| return `${normalized}/responses`; | |
| } | |
| return `${normalized}/chat/completions`; | |
| } | |
| if ( | |
| normalized.endsWith("/chat/completions") || | |
| normalized.endsWith("/responses") || | |
| normalized.endsWith("/chat") | |
| ) { | |
| return normalized; | |
| } | |
| if (normalized.endsWith("/v1")) { | |
| return `${normalized}/chat/completions`; | |
| } | |
| return normalized; | |
| } | |
| export function normalizeHerokuChatUrl(baseUrl: string) { | |
| const normalized = normalizeBaseUrl(baseUrl); | |
| if (!normalized) return ""; | |
| return normalized.endsWith("/v1/chat/completions") | |
| ? normalized | |
| : `${normalized}/v1/chat/completions`; | |
| } | |
| export function normalizeDatabricksChatUrl(baseUrl: string) { | |
| const normalized = normalizeBaseUrl(baseUrl); | |
| if (!normalized) return ""; | |
| return normalized.endsWith("/chat/completions") ? normalized : `${normalized}/chat/completions`; | |
| } | |
| export function normalizeSnowflakeChatUrl(baseUrl: string) { | |
| const normalized = normalizeBaseUrl(baseUrl) | |
| .replace(/\/cortex\/inference:complete$/, "") | |
| .replace(/\/api\/v2$/, ""); | |
| if (!normalized) return ""; | |
| return `${normalized}/api/v2/cortex/inference:complete`; | |
| } | |
| export function normalizeGigachatChatUrl(baseUrl: string) { | |
| const normalized = normalizeBaseUrl(baseUrl).replace(/\/chat\/completions$/, ""); | |
| if (!normalized) return ""; | |
| return `${normalized}/chat/completions`; | |
| } | |