from __future__ import annotations from dataclasses import dataclass from pathlib import Path import os ROOT = Path(__file__).resolve().parents[2] ENV_PATH = ROOT / ".env" def _load_env_file(path: Path = ENV_PATH) -> dict[str, str]: values: dict[str, str] = {} if not path.exists(): return values for raw in path.read_text().splitlines(): line = raw.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) values[key.strip()] = value.strip().strip('"').strip("'") return values def _env(name: str, default: str = "") -> str: file_values = _load_env_file() return os.getenv(name, file_values.get(name, default)) def _env_bool(name: str, default: bool = False) -> bool: value = _env(name, "true" if default else "false").strip().lower() return value in {"1", "true", "yes", "on"} def _env_bool_any(*names: str, default: bool = False) -> bool: file_values = _load_env_file() for name in names: value = os.getenv(name) if value is None: value = file_values.get(name) if value is not None: return value.strip().lower() in {"1", "true", "yes", "on"} return default def _env_int(name: str, default: int) -> int: try: return int(_env(name, str(default))) except Exception: return default @dataclass(frozen=True) class HermesConfig: trader_url: str argus_url: str crypto_url: str metals_url: str news_url: str atlas_url: str exec_url: str crypto_timeframes: tuple[str, ...] retention_days: int prune_interval_hours: int cycle_seconds: int breakout_memory_window_seconds: int hermes_allow_actions: bool def load_config() -> HermesConfig: timeframes = tuple( part.strip() for part in _env("HERMES_CRYPTO_TIMEFRAMES", "5m,15m,1h,4h,1d").split(",") if part.strip() ) return HermesConfig( trader_url=_env("HERMES_TRADER_URL", "http://127.0.0.1:8570"), argus_url=_env("HERMES_ARGUS_URL", "http://127.0.0.1:8520"), crypto_url=_env("HERMES_CRYPTO_URL", "http://127.0.0.1:8580"), metals_url=_env("HERMES_METALS_URL", "http://127.0.0.1:8591"), news_url=_env("HERMES_NEWS_URL", "http://127.0.0.1:8600"), atlas_url=_env("HERMES_ATLAS_URL", "http://127.0.0.1:8550"), exec_url=_env("HERMES_EXEC_URL", "http://127.0.0.1:8560"), crypto_timeframes=timeframes, retention_days=_env_int("HERMES_RETENTION_DAYS", 7), prune_interval_hours=_env_int("HERMES_PRUNE_INTERVAL_HOURS", 6), cycle_seconds=_env_int("HERMES_CYCLE_SECONDS", 60), breakout_memory_window_seconds=_env_int("HERMES_BREAKOUT_MEMORY_WINDOW_SECONDS", 900), hermes_allow_actions=_env_bool_any("HERMES_ALLOW_ACTIONS", "HERMES_ALLOW_AUTO_ACTIONS", default=False), )