""" Central configuration — single source of truth for all settings. Loaded from .env via pydantic-settings. Usage: from app.core.config import settings print(settings.REDIS_HOST) """ from __future__ import annotations import os from functools import lru_cache from typing import Optional class Settings: """Application settings loaded from environment variables.""" def __init__(self) -> None: # Redis self.REDIS_HOST: str = os.getenv("REDIS_HOST", "rmi-redis") self.REDIS_PORT: int = int(os.getenv("REDIS_PORT", "6379")) self.REDIS_PASSWORD: str = os.getenv("REDIS_PASSWORD", "") self.REDIS_DB: int = int(os.getenv("REDIS_DB", "0")) # Supabase self.SUPABASE_URL: str = os.getenv("SUPABASE_URL", "") self.SUPABASE_SERVICE_KEY: str = os.getenv("SUPABASE_SERVICE_KEY", "") or os.getenv("SUPABASE_KEY", "") # Admin self.ADMIN_API_KEY: str = os.getenv("ADMIN_API_KEY", "dev-key-change-me") # API Keys self.OPENROUTER_API_KEY: str = os.getenv("OPENROUTER_API_KEY", "") self.ETHERSCAN_API_KEY: str = os.getenv("ETHERSCAN_API_KEY", "") self.HELIUS_API_KEY: str = os.getenv("HELIUS_API_KEY", "") self.DEEPSEEK_API_KEY: str = os.getenv("DEEPSEEK_API_KEY", "") self.GEMINI_API_KEY: str = os.getenv("GEMINI_API_KEY", "") self.GEMINI_API_KEY_2: str = os.getenv("GEMINI_API_KEY_2", "") # Langfuse self.LANGFUSE_PUBLIC_KEY: str = os.getenv("LANGFUSE_PUBLIC_KEY", "") self.LANGFUSE_SECRET_KEY: str = os.getenv("LANGFUSE_SECRET_KEY", "") self.LANGFUSE_HOST: str = os.getenv("LANGFUSE_HOST", "http://langfuse-langfuse-web-1:3000") # Ollama self.OLLAMA_HOST: str = os.getenv("OLLAMA_HOST", "http://ollama:11434") # Wallet self.WALLET_VAULT_PASSWORD: str = os.getenv("WALLET_VAULT_PASSWORD", "") # R2 self.R2_API_TOKEN: str = os.getenv("R2_API_TOKEN", "") self.R2_ACCOUNT_ID: str = os.getenv("R2_ACCOUNT_ID", "") self.R2_BUCKET: str = os.getenv("R2_BUCKET", "rag-backup") def validate(self) -> list[str]: """Return list of missing critical env vars. Empty list = all good.""" critical = [ "REDIS_HOST", "SUPABASE_URL", "SUPABASE_SERVICE_KEY", "ADMIN_API_KEY", "WALLET_VAULT_PASSWORD", ] missing = [] for var in critical: if not getattr(self, var, None): missing.append(var) return missing @lru_cache(maxsize=1) def get_settings() -> Settings: """Cached singleton — call this, don't instantiate Settings directly.""" return Settings() # Module-level singleton — import this everywhere settings = get_settings()