config.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. from __future__ import annotations
  2. from functools import lru_cache
  3. from pathlib import Path
  4. from typing import Self
  5. from pydantic import Field, model_validator
  6. from pydantic_settings import BaseSettings, SettingsConfigDict
  7. from supply_agent.paths import resolve_path
  8. class Settings(BaseSettings):
  9. """Application settings loaded from environment variables or .env file."""
  10. model_config = SettingsConfigDict(
  11. env_file=".env",
  12. env_file_encoding="utf-8",
  13. extra="ignore",
  14. )
  15. # OpenRouter
  16. openrouter_api_key: str = Field(..., alias="OPENROUTER_API_KEY")
  17. openrouter_model: str = Field(
  18. default="google/gemini-2.5-flash",
  19. alias="OPENROUTER_MODEL",
  20. )
  21. openrouter_base_url: str = Field(
  22. default="https://openrouter.ai/api/v1",
  23. alias="OPENROUTER_BASE_URL",
  24. )
  25. openrouter_site_url: str = Field(default="", alias="OPENROUTER_SITE_URL")
  26. openrouter_site_name: str = Field(default="SupplyAgent", alias="OPENROUTER_SITE_NAME")
  27. openrouter_timeout_seconds: float = Field(
  28. default=120.0,
  29. alias="OPENROUTER_TIMEOUT_SECONDS",
  30. )
  31. # Agent
  32. agent_max_iterations: int = Field(default=20, alias="AGENT_MAX_ITERATIONS")
  33. agent_temperature: float = Field(default=0.7, alias="AGENT_TEMPERATURE")
  34. # Skills
  35. skills_dir: Path = Field(default=Path("skills"), alias="SKILLS_DIR")
  36. # Logging
  37. logs_dir: Path = Field(default=Path("logs"), alias="LOGS_DIR")
  38. log_enabled: bool = Field(default=True, alias="LOG_ENABLED")
  39. @model_validator(mode="after")
  40. def resolve_relative_paths(self) -> Self:
  41. """Resolve skills_dir and logs_dir against project root when needed."""
  42. self.skills_dir = resolve_path(self.skills_dir)
  43. self.logs_dir = resolve_path(self.logs_dir)
  44. return self
  45. @classmethod
  46. def from_env(cls, **overrides: object) -> Self:
  47. """Create settings with optional overrides (useful for testing)."""
  48. return cls(**overrides) # type: ignore[arg-type]
  49. @lru_cache
  50. def get_settings() -> Settings:
  51. return Settings() # type: ignore[call-arg]