import { DEFAULT_DISPLAY_BASE_URL } from "@/shared/hooks"; export interface CustomCliAliasMapping { alias: string; model: string; } export interface CustomCliConfigInput { cliName: string; baseUrl: string; apiKey: string; defaultModel?: string; aliasMappings?: CustomCliAliasMapping[]; } export function normalizeOpenAiBaseUrl(baseUrl: string): string { const trimmed = (baseUrl || DEFAULT_DISPLAY_BASE_URL).trim().replace(/\/+$/, ""); return trimmed.endsWith("/v1") ? trimmed : `${trimmed}/v1`; } export function slugifyCliCommand(cliName: string): string { const normalized = cliName .trim() .toLowerCase() .replace(/[^a-z0-9]+/g, "-") .replace(/^-+|-+$/g, ""); return normalized || "my-cli"; } export function buildAliasEnvVar(alias: string): string | null { const normalized = alias .trim() .replace(/[^a-zA-Z0-9]+/g, "_") .replace(/^_+|_+$/g, "") .toUpperCase(); if (!normalized) return null; return `OMNIROUTE_MODEL_${normalized}`; } function getValidMappings(aliasMappings: CustomCliAliasMapping[] = []): CustomCliAliasMapping[] { return aliasMappings.filter( (mapping) => mapping.alias.trim().length > 0 && mapping.model.trim().length > 0 ); } export function buildCustomCliEnvScript({ cliName, baseUrl, apiKey, defaultModel = "", aliasMappings = [], }: CustomCliConfigInput): string { const normalizedBaseUrl = normalizeOpenAiBaseUrl(baseUrl); const resolvedName = cliName.trim() || "Custom CLI"; const resolvedCommand = slugifyCliCommand(resolvedName); const resolvedDefaultModel = defaultModel.trim(); const mappings = getValidMappings(aliasMappings); const lines = [ `# ${resolvedName} -> OmniRoute (OpenAI-compatible)`, `export OPENAI_BASE_URL="${normalizedBaseUrl}"`, `export OPENAI_API_KEY="${apiKey}"`, ]; if (resolvedDefaultModel) { lines.push(`export OPENAI_MODEL="${resolvedDefaultModel}"`); } if (mappings.length > 0) { lines.push("", "# Optional alias mappings for wrapper scripts"); mappings.forEach((mapping) => { const envVar = buildAliasEnvVar(mapping.alias); if (!envVar) return; lines.push(`export ${envVar}="${mapping.model.trim()}"`); }); } lines.push("", "# Raw chat completions endpoint", `# ${normalizedBaseUrl}/chat/completions`, ""); const exampleCommand = [ resolvedCommand, '--base-url "$OPENAI_BASE_URL"', '--api-key "$OPENAI_API_KEY"', resolvedDefaultModel ? '--model "$OPENAI_MODEL"' : "", ] .filter(Boolean) .join(" "); lines.push("# Example invocation", exampleCommand); const firstAliasEnv = buildAliasEnvVar(mappings[0]?.alias ?? ""); if (firstAliasEnv) { lines.push(`# Alias example: ${resolvedCommand} --model "\${${firstAliasEnv}:-$OPENAI_MODEL}"`); } return lines.join("\n"); } export function buildCustomCliJsonConfig({ cliName, baseUrl, apiKey, defaultModel = "", aliasMappings = [], }: CustomCliConfigInput): string { const normalizedBaseUrl = normalizeOpenAiBaseUrl(baseUrl); const resolvedName = cliName.trim() || "Custom CLI"; const resolvedDefaultModel = defaultModel.trim(); const mappings = getValidMappings(aliasMappings); const config = { name: resolvedName, provider: { type: "openai", baseURL: normalizedBaseUrl, apiKey, ...(resolvedDefaultModel ? { model: resolvedDefaultModel } : {}), }, ...(mappings.length > 0 ? { modelAliases: Object.fromEntries( mappings.map((mapping) => [mapping.alias.trim(), mapping.model.trim()]) ), } : {}), }; return JSON.stringify(config, null, 2); }