const parseInteger = (value: string | undefined, fallback: number) => { if (!value) return fallback; const parsed = Number.parseInt(value, 10); return Number.isFinite(parsed) ? parsed : fallback; }; const parseBoolean = (value: string | undefined, fallback: boolean) => { if (value == null || value === "") return fallback; return value === "1" || value.toLowerCase() === "true"; }; const parseList = (value: string | undefined) => (value ?? "") .split(",") .map((item) => item.trim()) .filter(Boolean); export const ENV = { appId: process.env.VITE_APP_ID ?? "", appPublicBaseUrl: process.env.APP_PUBLIC_BASE_URL ?? "", cookieSecret: process.env.JWT_SECRET ?? "", databaseUrl: process.env.DATABASE_URL ?? "", registrationInviteCode: process.env.REGISTRATION_INVITE_CODE ?? "CA2026", oAuthServerUrl: process.env.OAUTH_SERVER_URL ?? "", ownerOpenId: process.env.OWNER_OPEN_ID ?? "", adminUsernames: parseList(process.env.ADMIN_USERNAMES), isProduction: process.env.NODE_ENV === "production", forgeApiUrl: process.env.BUILT_IN_FORGE_API_URL ?? "", forgeApiKey: process.env.BUILT_IN_FORGE_API_KEY ?? "", localStorageDir: process.env.LOCAL_STORAGE_DIR ?? "./data/storage", llmApiUrl: process.env.LLM_API_URL ?? (process.env.BUILT_IN_FORGE_API_URL ? `${process.env.BUILT_IN_FORGE_API_URL.replace(/\/$/, "")}/v1/chat/completions` : ""), llmApiKey: process.env.LLM_API_KEY ?? process.env.BUILT_IN_FORGE_API_KEY ?? "", llmModel: process.env.LLM_MODEL ?? "gemini-2.5-flash", llmVisionApiUrl: process.env.LLM_VISION_API_URL ?? process.env.LLM_API_URL ?? (process.env.BUILT_IN_FORGE_API_URL ? `${process.env.BUILT_IN_FORGE_API_URL.replace(/\/$/, "")}/v1/chat/completions` : ""), llmVisionApiKey: process.env.LLM_VISION_API_KEY ?? process.env.LLM_API_KEY ?? process.env.BUILT_IN_FORGE_API_KEY ?? "", llmVisionModel: process.env.LLM_VISION_MODEL ?? process.env.LLM_MODEL ?? "gemini-2.5-flash", llmMaxTokens: parseInteger(process.env.LLM_MAX_TOKENS, 32768), llmEnableThinking: parseBoolean(process.env.LLM_ENABLE_THINKING, false), llmThinkingBudget: parseInteger(process.env.LLM_THINKING_BUDGET, 128), llmTimeoutMs: parseInteger(process.env.LLM_TIMEOUT_MS, 45000), llmRetryCount: parseInteger(process.env.LLM_RETRY_COUNT, 1), mediaServiceUrl: process.env.MEDIA_SERVICE_URL ?? "", mediaFetchTimeoutMs: parseInteger(process.env.MEDIA_FETCH_TIMEOUT_MS, 12000), mediaFetchRetryCount: parseInteger(process.env.MEDIA_FETCH_RETRY_COUNT, 2), youtubeApiKey: process.env.YOUTUBE_API_KEY ?? "", backgroundTaskPollMs: parseInteger(process.env.BACKGROUND_TASK_POLL_MS, 3000), backgroundTaskStaleMs: parseInteger(process.env.BACKGROUND_TASK_STALE_MS, 300000), backgroundTaskHeartbeatMs: parseInteger(process.env.BACKGROUND_TASK_HEARTBEAT_MS, 5000), };