from __future__ import annotations from functools import lru_cache from pathlib import Path from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict ROOT_DIR = Path(__file__).resolve().parents[2] class Settings(BaseSettings): app_name: str = Field(default="Recruitment Agent API", validation_alias="APP_NAME") environment: str = Field(default="development", validation_alias="APP_ENV") host: str = Field(default="0.0.0.0", validation_alias="APP_HOST") port: int = Field(default=7860, validation_alias="APP_PORT") cors_origins: str = Field(default="*", validation_alias="CORS_ORIGINS") gemini_api_key: str = Field(default="", validation_alias="GEMINI_API_KEY") gemini_model: str = Field(default="gemini-2.5-flash", validation_alias="GEMINI_MODEL") embedding_model: str = Field( default="models/text-embedding-004", validation_alias="GEMINI_EMBEDDING_MODEL", ) qdrant_url: str | None = Field(default=None, validation_alias="QDRANT_URL") qdrant_api_key: str | None = Field(default=None, validation_alias="QDRANT_API_KEY") qdrant_collection: str = Field( default="recruitment_candidates", validation_alias="QDRANT_COLLECTION", ) # Generic S3-compatible storage. Works with Supabase Storage, Backblaze B2, # AWS S3, MinIO, etc. — just point S3_ENDPOINT at the provider's URL. s3_endpoint: str | None = Field(default=None, validation_alias="S3_ENDPOINT") s3_access_key_id: str | None = Field(default=None, validation_alias="S3_ACCESS_KEY_ID") s3_secret_access_key: str | None = Field( default=None, validation_alias="S3_SECRET_ACCESS_KEY", ) s3_bucket: str | None = Field(default=None, validation_alias="S3_BUCKET") s3_region: str = Field(default="us-east-1", validation_alias="S3_REGION") s3_public_base_url: str | None = Field( default=None, validation_alias="S3_PUBLIC_BASE_URL", ) sqlite_db_path: str = Field( default=str(ROOT_DIR / "backend" / "data" / "candidates.db"), validation_alias="SQLITE_DB_PATH", ) uploads_dir: str = Field( default=str(ROOT_DIR / "backend" / "data" / "uploads"), validation_alias="UPLOADS_DIR", ) mcp_server_base_url: str = Field( default="http://127.0.0.1:7860/mcp-server/sse", validation_alias="MCP_SERVER_BASE_URL", ) chunk_size: int = Field(default=1100, validation_alias="CHUNK_SIZE") chunk_overlap: int = Field(default=150, validation_alias="CHUNK_OVERLAP") max_chunks_per_document: int = Field(default=50, validation_alias="MAX_CHUNKS_PER_DOC") smtp_host: str | None = Field(default=None, validation_alias="SMTP_HOST") smtp_port: int = Field(default=587, validation_alias="SMTP_PORT") smtp_user: str | None = Field(default=None, validation_alias="SMTP_USER") smtp_password: str | None = Field(default=None, validation_alias="SMTP_PASSWORD") smtp_from: str | None = Field(default=None, validation_alias="SMTP_FROM") smtp_use_tls: bool = Field(default=True, validation_alias="SMTP_USE_TLS") # Resend (https://resend.com) — HTTPS email API. Free 3000/month but # restricted to your own email address until you verify a sending domain. resend_api_key: str | None = Field(default=None, validation_alias="RESEND_API_KEY") # Brevo (https://brevo.com, formerly Sendinblue) — HTTPS email API. Free # 300 emails/day. Only needs a *single sender email* verified (no DNS # required), and you can send TO any recipient. Best free option when the # demo needs to email arbitrary addresses on day one. brevo_api_key: str | None = Field(default=None, validation_alias="BREVO_API_KEY") calendly_event_url: str | None = Field(default=None, validation_alias="CALENDLY_EVENT_URL") model_config = SettingsConfigDict( env_file=(str(ROOT_DIR / ".env"), str(ROOT_DIR.parent / ".env")), env_file_encoding="utf-8", extra="ignore", ) @property def sqlite_url(self) -> str: return f"sqlite:///{Path(self.sqlite_db_path).resolve()}" @property def cors_origin_list(self) -> list[str]: if self.cors_origins.strip() == "*": return ["*"] return [item.strip() for item in self.cors_origins.split(",") if item.strip()] @property def has_qdrant_config(self) -> bool: return bool(self.qdrant_url and self.qdrant_api_key) @property def has_s3_config(self) -> bool: return bool( self.s3_endpoint and self.s3_access_key_id and self.s3_secret_access_key and self.s3_bucket ) @property def has_smtp_config(self) -> bool: return bool(self.smtp_host and self.smtp_from) @lru_cache(maxsize=1) def get_settings() -> Settings: return Settings()