"""Minimal, dependency-free ``.env`` loader. The project keeps provider API keys (``OLLAMA_API_KEY``, ``OPENAI_API_KEY``, ``ANTHROPIC_API_KEY``, …) in a git-ignored ``.env`` at the repo root. Nothing loads it automatically, so a freshly launched web/CLI process doesn't see those keys unless the user exported them by hand — which is why ``ollama:…-cloud`` fails with "API key must be provided". ``load_dotenv()`` finds the nearest ``.env`` walking up from the current working directory and copies its ``KEY=VALUE`` lines into ``os.environ``. Real environment variables win by default (``override=False``), so an explicitly exported key is never clobbered. No third-party dependency (keeps the offline test suite dependency-free). """ from __future__ import annotations import os from pathlib import Path def _parse(text: str) -> dict[str, str]: out: dict[str, str] = {} for raw in text.splitlines(): line = raw.strip() if not line or line.startswith("#") or "=" not in line: continue if line.lower().startswith("export "): line = line[len("export "):].lstrip() key, _, val = line.partition("=") key = key.strip() val = val.strip() if val[:1] in {'"', "'"} and val[-1:] == val[:1]: val = val[1:-1] # quoted: keep verbatim (may contain '#') else: cut = val.find(" #") # unquoted: drop a whitespace-led inline comment if cut != -1: val = val[:cut].rstrip() if key: out[key] = val return out def find_dotenv(start: str | os.PathLike[str] | None = None) -> Path | None: """Return the nearest ``.env`` walking up from *start* (default CWD).""" base = Path(start) if start is not None else Path.cwd() base = base.resolve() for d in (base, *base.parents): candidate = d / ".env" if candidate.is_file(): return candidate return None def load_dotenv( start: str | os.PathLike[str] | None = None, *, override: bool = False ) -> str | None: """Load the nearest ``.env`` into ``os.environ``. Args: start: Directory to begin the upward search (default: CWD). override: If True, ``.env`` values replace existing env vars. Default False — a key already in the environment is left untouched. Returns: The path of the ``.env`` that was loaded, or ``None`` if none was found. """ path = find_dotenv(start) if path is None: return None for key, val in _parse(path.read_text(encoding="utf-8")).items(): if override or key not in os.environ: os.environ[key] = val return str(path)