Introduce --log-level and --log-file CLI arguments. Add execution time tracking and detailed logs across all modules.
55 lines
1.6 KiB
Python
55 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
import logging
|
|
import re
|
|
from typing import Self
|
|
|
|
from dotenv import load_dotenv
|
|
import os
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class Settings:
|
|
api_key: str | None
|
|
base_url: str | None
|
|
model: str
|
|
|
|
@classmethod
|
|
def from_env(cls, env_file: Path | None = None, model_override: str | None = None) -> Self:
|
|
if env_file:
|
|
logger.info("Loading environment variables from %s", env_file)
|
|
load_dotenv(env_file)
|
|
else:
|
|
logger.debug("Loading environment variables using default dotenv lookup")
|
|
load_dotenv()
|
|
|
|
settings = cls(
|
|
api_key=os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY"),
|
|
base_url=os.getenv("GEMINI_BASE_URL") or None,
|
|
model=model_override or os.getenv("GEMINI_MODEL") or "gemini-2.5-flash",
|
|
)
|
|
logger.info(
|
|
"Configuration loaded: model=%s base_url=%s api_key=%s",
|
|
settings.model,
|
|
settings.normalized_base_url() or "<default>",
|
|
"set" if settings.api_key else "missing",
|
|
)
|
|
return settings
|
|
|
|
def require_api_key(self) -> None:
|
|
if not self.api_key:
|
|
raise ValueError("Missing GEMINI_API_KEY (or GOOGLE_API_KEY) in the environment.")
|
|
logger.debug("Gemini API key is available")
|
|
|
|
def normalized_base_url(self) -> str | None:
|
|
if not self.base_url:
|
|
return None
|
|
|
|
base_url = self.base_url.strip().rstrip("/")
|
|
return re.sub(r"/v\d+(?:alpha|beta)?$", "", base_url, flags=re.IGNORECASE)
|