Hermes startup entrypoints now load ~/.hermes/.env and project fallback env files with user config taking precedence over stale shell-exported values. This makes model/provider/base URL changes in .env actually take effect after restarting Hermes. Adds a shared env loader plus regression coverage, and reproduces the original bug case where OPENAI_BASE_URL and HERMES_INFERENCE_PROVIDER remained stuck on old shell values before import.
47 lines
1.5 KiB
Python
47 lines
1.5 KiB
Python
"""Helpers for loading Hermes .env files consistently across entrypoints."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Iterable
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
|
|
def _load_dotenv_with_fallback(path: Path, *, override: bool) -> None:
|
|
try:
|
|
load_dotenv(dotenv_path=path, override=override, encoding="utf-8")
|
|
except UnicodeDecodeError:
|
|
load_dotenv(dotenv_path=path, override=override, encoding="latin-1")
|
|
|
|
|
|
def load_hermes_dotenv(
|
|
*,
|
|
hermes_home: str | os.PathLike | None = None,
|
|
project_env: str | os.PathLike | None = None,
|
|
) -> list[Path]:
|
|
"""Load Hermes environment files with user config taking precedence.
|
|
|
|
Behavior:
|
|
- `~/.hermes/.env` overrides stale shell-exported values when present.
|
|
- project `.env` acts as a dev fallback and only fills missing values when
|
|
the user env exists.
|
|
- if no user env exists, the project `.env` also overrides stale shell vars.
|
|
"""
|
|
loaded: list[Path] = []
|
|
|
|
home_path = Path(hermes_home or os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
|
user_env = home_path / ".env"
|
|
project_env_path = Path(project_env) if project_env else None
|
|
|
|
if user_env.exists():
|
|
_load_dotenv_with_fallback(user_env, override=True)
|
|
loaded.append(user_env)
|
|
|
|
if project_env_path and project_env_path.exists():
|
|
_load_dotenv_with_fallback(project_env_path, override=not loaded)
|
|
loaded.append(project_env_path)
|
|
|
|
return loaded
|