from __future__ import annotations from functools import lru_cache from pathlib import Path from typing import Self from pydantic import Field, model_validator from pydantic_settings import BaseSettings, SettingsConfigDict from supply_agent.paths import resolve_path class Settings(BaseSettings): """Application settings loaded from environment variables or .env file.""" model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", extra="ignore", ) # OpenRouter openrouter_api_key: str = Field(..., alias="OPENROUTER_API_KEY") openrouter_model: str = Field( default="google/gemini-2.5-flash", alias="OPENROUTER_MODEL", ) openrouter_base_url: str = Field( default="https://openrouter.ai/api/v1", alias="OPENROUTER_BASE_URL", ) openrouter_site_url: str = Field(default="", alias="OPENROUTER_SITE_URL") openrouter_site_name: str = Field(default="SupplyAgent", alias="OPENROUTER_SITE_NAME") openrouter_timeout_seconds: float = Field( default=120.0, alias="OPENROUTER_TIMEOUT_SECONDS", ) # Agent agent_max_iterations: int = Field(default=20, alias="AGENT_MAX_ITERATIONS") agent_temperature: float = Field(default=0.7, alias="AGENT_TEMPERATURE") find_agent_timeout_seconds: float = Field( default=1800.0, ge=60.0, le=7200.0, alias="FIND_AGENT_TIMEOUT_SECONDS", ) # Skills skills_dir: Path = Field(default=Path("skills"), alias="SKILLS_DIR") # Logging logs_dir: Path = Field(default=Path("logs"), alias="LOGS_DIR") log_enabled: bool = Field(default=True, alias="LOG_ENABLED") @model_validator(mode="after") def resolve_relative_paths(self) -> Self: """Resolve skills_dir and logs_dir against project root when needed.""" self.skills_dir = resolve_path(self.skills_dir) self.logs_dir = resolve_path(self.logs_dir) return self @classmethod def from_env(cls, **overrides: object) -> Self: """Create settings with optional overrides (useful for testing).""" return cls(**overrides) # type: ignore[arg-type] @lru_cache def get_settings() -> Settings: return Settings() # type: ignore[call-arg]