/** Default timeouts (ms) for hybrid discovery. */ export const DEFAULT_BOOT_TIMEOUT_MS = 5_000; export const DEFAULT_RETRY_TIMEOUT_MS = 5_000; export const DEFAULT_RELOAD_TIMEOUT_MS = 30_000; export interface CLIPProxyConfig { baseUrl: string; apiKey: string; /** Normalized URL to GET for model listing (includes `/models`). */ modelsUrl: string; bootTimeoutMs: number; retryTimeoutMs: number; reloadTimeoutMs: number; } export type ConfigResult = | { ok: true; config: CLIPProxyConfig } | { ok: false; error: string }; /** * Parse a positive integer env value; invalid or non-positive → fallback. */ export function parseTimeoutMs(raw: string | undefined, fallback: number): number { if (raw === undefined || raw.trim() === '') return fallback; const n = Number(raw); if (!Number.isFinite(n) || n <= 0) return fallback; return Math.floor(n); } /** * Normalize user-supplied base URL for CLIProxyAPI. * - trim * - strip trailing slashes * - if already ends with `/models`, treat as models endpoint base (no double append later) * - does NOT invent a missing `/v1` */ export function normalizeBaseUrl(raw: string): string { let url = raw.trim(); while (url.endsWith('/')) { url = url.slice(0, -1); } return url; } /** Build the models list endpoint from a normalized base URL. */ export function buildModelsUrl(normalizedBaseUrl: string): string { if (/\/models$/i.test(normalizedBaseUrl)) { return normalizedBaseUrl; } return `${normalizedBaseUrl}/models`; } /** * Read provider config from environment. * Required: CLIPROXY_BASE_URL, CLIPROXY_API_KEY. */ export function loadConfig( env: NodeJS.ProcessEnv = process.env, ): ConfigResult { const baseRaw = env.CLIPROXY_BASE_URL; const apiKey = env.CLIPROXY_API_KEY; if (!baseRaw?.trim() || !apiKey?.trim()) { return { ok: false, error: 'CLIPROXY_BASE_URL 和 CLIPROXY_API_KEY 为必填环境变量。Provider 未注册。', }; } const baseUrl = normalizeBaseUrl(baseRaw); return { ok: true, config: { baseUrl, apiKey: apiKey.trim(), modelsUrl: buildModelsUrl(baseUrl), bootTimeoutMs: parseTimeoutMs(env.CLIPROXY_BOOT_TIMEOUT_MS, DEFAULT_BOOT_TIMEOUT_MS), retryTimeoutMs: parseTimeoutMs(env.CLIPROXY_RETRY_TIMEOUT_MS, DEFAULT_RETRY_TIMEOUT_MS), reloadTimeoutMs: parseTimeoutMs(env.CLIPROXY_RELOAD_TIMEOUT_MS, DEFAULT_RELOAD_TIMEOUT_MS), }, }; }