AgentnessBench / proteus /env_loader.py
irregular6612's picture
feat(web): load API keys from git-ignored .env at startup (fixes ollama:*-cloud key error)
7e1ccef
Raw
History Blame Contribute Delete
2.73 kB
"""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)