""" Global configuration for Core Code API All configuration is loaded from environment variables or .env file. See .env.example for available settings. """ import tomllib from pathlib import Path from pydantic_settings import BaseSettings from functools import lru_cache def _get_version_from_pyproject() -> str: """Load version from pyproject.toml""" pyproject_path = Path(__file__).parent.parent.parent / "pyproject.toml" try: with open(pyproject_path, "rb") as f: data = tomllib.load(f) return data.get("project", {}).get("version", "0.0.0") except FileNotFoundError: return "0.0.0" __version__ = _get_version_from_pyproject() class Settings(BaseSettings): """Global application settings""" # Application app_name: str = "Core Code API" app_version: str = __version__ debug: bool = False # Server host: str = "0.0.0.0" port: int = 8083 # CORS - Note: When cors_credentials is True, cannot use "*" for origins # Set CORS_ORIGINS env var to override (comma-separated list) cors_origins: list[str] = [ "https://home.schweitz.net", "https://tatlock.schweitz.net", "http://localhost:8080", "http://localhost:3000", "http://127.0.0.1:8080", ] cors_credentials: bool = True cors_methods: list[str] = ["*"] cors_headers: list[str] = ["*"] # Logging log_level: str = "DEBUG" # Ollama Configuration (for AI orchestration) ollama_base_url: str # Required - set OLLAMA_BASE_URL in .env ollama_timeout: int = 300 # 5 minutes # Model Configuration default_model: str = "mistral-nemo-large:latest" agent_model: str = "mistral-nemo-large:latest" code_models: str = "mistral-nemo-large:latest" # System Prompt Variant (for A/B testing) system_prompt_variant: str = "v8_holistic" # Agent Configuration agent_fallback_enabled: bool = True # Model Aliases (OpenAI → Local) alias_gpt35: str = "gemma:7b" alias_gpt4: str = "mistral:7b" alias_gpt4_turbo: str = "mixtral:8x7b" alias_gpt4_code: str = "codestral:latest" # Memory Configuration memory_tier1_max_turns: int = 10 memory_consolidation_threshold: int = 10 # Qdrant Configuration qdrant_host: str = "qdrant" qdrant_port: int = 6333 qdrant_collection_conversations: str = "core_api_conversations" qdrant_collection_documents: str = "core_api_documents" qdrant_collection_user_facts: str = "core_api_user_facts" # Embeddings (using Ollama) embedding_model: str = "nomic-embed-text" embedding_dimension: int = 768 embedding_batch_size: int = 32 # Search Configuration search_provider: str = "searxng" searxng_url: str # Required - set SEARXNG_URL in .env # Infrastructure Management (Portainer) portainer_url: str # Required portainer_api_key: str # Required # Infrastructure Management (Nginx Proxy Manager) npm_url: str # Required npm_email: str # Required npm_password: str # Required # Home Assistant Configuration homeassistant_url: str # Required homeassistant_token: str # Required homeassistant_timeout: int = 30 # PostgreSQL Database postgres_host: str # Required postgres_user: str = "core_api" postgres_password: str # Required postgres_database: str = "core_api" @property def database_url(self) -> str: """Construct database URL from components""" return f"postgresql://{self.postgres_user}:{self.postgres_password}@{self.postgres_host}/{self.postgres_database}" # OIDC Authentication (Authentik) oidc_enabled: bool = False oidc_issuer: str = "https://auth.schweitz.net/application/o/core-api/" oidc_audience: str = "core-api" # Authentik API (for token validation and user management) authentik_url: str = "https://auth.schweitz.net" authentik_username: str = "" authentik_password: str = "" @property def model_aliases(self) -> dict: """Computed property for model aliases""" return { "gpt-3.5-turbo": self.alias_gpt35, "gpt-4": self.alias_gpt4, "gpt-4-turbo": self.alias_gpt4_turbo, "gpt-4-code": self.alias_gpt4_code, } def get_code_models(self) -> list[str]: """Parse comma-separated code models""" return [m.strip().strip('"').strip("'") for m in self.code_models.split(",") if m.strip()] class Config: env_file = ".env" case_sensitive = False extra = "ignore" @lru_cache() def get_settings() -> Settings: """Cached settings instance""" return Settings()