mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
refactor: consolidate get_hermes_home() and parse_reasoning_effort() (#3062)
Centralizes two widely-duplicated patterns into hermes_constants.py:
1. get_hermes_home() — Path resolution for ~/.hermes (HERMES_HOME env var)
- Was copy-pasted inline across 30+ files as:
Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
- Now defined once in hermes_constants.py (zero-dependency module)
- hermes_cli/config.py re-exports it for backward compatibility
- Removed local wrapper functions in honcho_integration/client.py,
tools/website_policy.py, tools/tirith_security.py, hermes_cli/uninstall.py
2. parse_reasoning_effort() — Reasoning effort string validation
- Was copy-pasted in cli.py, gateway/run.py, cron/scheduler.py
- Same validation logic: check against (xhigh, high, medium, low, minimal, none)
- Now defined once in hermes_constants.py, called from all 3 locations
- Warning log for unknown values kept at call sites (context-specific)
31 files changed, net +31 lines (125 insertions, 94 deletions)
Full test suite: 6179 passed, 0 failed
This commit is contained in:
parent
e0cfc089da
commit
77bcaba2d7
31 changed files with 125 additions and 94 deletions
|
|
@ -18,6 +18,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
|
|
||||||
|
|
||||||
def _setup_logging() -> None:
|
def _setup_logging() -> None:
|
||||||
|
|
@ -44,7 +45,7 @@ def _load_env() -> None:
|
||||||
"""Load .env from HERMES_HOME (default ``~/.hermes``)."""
|
"""Load .env from HERMES_HOME (default ``~/.hermes``)."""
|
||||||
from hermes_cli.env_loader import load_hermes_dotenv
|
from hermes_cli.env_loader import load_hermes_dotenv
|
||||||
|
|
||||||
hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
hermes_home = get_hermes_home()
|
||||||
loaded = load_hermes_dotenv(hermes_home=hermes_home)
|
loaded = load_hermes_dotenv(hermes_home=hermes_home)
|
||||||
if loaded:
|
if loaded:
|
||||||
for env_file in loaded:
|
for env_file in loaded:
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ history.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
@ -251,7 +253,7 @@ class SessionManager:
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from hermes_state import SessionDB
|
from hermes_state import SessionDB
|
||||||
hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
hermes_home = get_hermes_home()
|
||||||
self._db_instance = SessionDB(db_path=hermes_home / "state.db")
|
self._db_instance = SessionDB(db_path=hermes_home / "state.db")
|
||||||
return self._db_instance
|
return self._db_instance
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
|
|
@ -450,7 +452,7 @@ _OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e"
|
||||||
_OAUTH_TOKEN_URL = "https://console.anthropic.com/v1/oauth/token"
|
_OAUTH_TOKEN_URL = "https://console.anthropic.com/v1/oauth/token"
|
||||||
_OAUTH_REDIRECT_URI = "https://console.anthropic.com/oauth/code/callback"
|
_OAUTH_REDIRECT_URI = "https://console.anthropic.com/oauth/code/callback"
|
||||||
_OAUTH_SCOPES = "org:create_api_key user:profile user:inference"
|
_OAUTH_SCOPES = "org:create_api_key user:profile user:inference"
|
||||||
_HERMES_OAUTH_FILE = Path(os.getenv("HERMES_HOME", str(Path.home() / ".hermes"))) / ".anthropic_oauth.json"
|
_HERMES_OAUTH_FILE = get_hermes_home() / ".anthropic_oauth.json"
|
||||||
|
|
||||||
|
|
||||||
def _generate_pkce() -> tuple:
|
def _generate_pkce() -> tuple:
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -320,7 +322,7 @@ def build_skills_system_prompt(
|
||||||
match skills by meaning, not just name.
|
match skills by meaning, not just name.
|
||||||
Filters out skills incompatible with the current OS platform.
|
Filters out skills incompatible with the current OS platform.
|
||||||
"""
|
"""
|
||||||
hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
hermes_home = get_hermes_home()
|
||||||
skills_dir = hermes_home / "skills"
|
skills_dir = hermes_home / "skills"
|
||||||
|
|
||||||
if not skills_dir.exists():
|
if not skills_dir.exists():
|
||||||
|
|
@ -449,7 +451,7 @@ def load_soul_md() -> Optional[str]:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug("Could not ensure HERMES_HOME before loading SOUL.md: %s", e)
|
logger.debug("Could not ensure HERMES_HOME before loading SOUL.md: %s", e)
|
||||||
|
|
||||||
soul_path = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes")) / "SOUL.md"
|
soul_path = get_hermes_home() / "SOUL.md"
|
||||||
if not soul_path.exists():
|
if not soul_path.exists():
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
27
cli.py
27
cli.py
|
|
@ -70,10 +70,10 @@ _COMMAND_SPINNER_FRAMES = ("⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧
|
||||||
|
|
||||||
# Load .env from ~/.hermes/.env first, then project root as dev fallback.
|
# Load .env from ~/.hermes/.env first, then project root as dev fallback.
|
||||||
# User-managed env files should override stale shell exports on restart.
|
# User-managed env files should override stale shell exports on restart.
|
||||||
from hermes_constants import OPENROUTER_BASE_URL
|
from hermes_constants import get_hermes_home, OPENROUTER_BASE_URL
|
||||||
from hermes_cli.env_loader import load_hermes_dotenv
|
from hermes_cli.env_loader import load_hermes_dotenv
|
||||||
|
|
||||||
_hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
_hermes_home = get_hermes_home()
|
||||||
_project_env = Path(__file__).parent / '.env'
|
_project_env = Path(__file__).parent / '.env'
|
||||||
load_hermes_dotenv(hermes_home=_hermes_home, project_env=_project_env)
|
load_hermes_dotenv(hermes_home=_hermes_home, project_env=_project_env)
|
||||||
|
|
||||||
|
|
@ -112,21 +112,12 @@ def _load_prefill_messages(file_path: str) -> List[Dict[str, Any]]:
|
||||||
|
|
||||||
|
|
||||||
def _parse_reasoning_config(effort: str) -> dict | None:
|
def _parse_reasoning_config(effort: str) -> dict | None:
|
||||||
"""Parse a reasoning effort level into an OpenRouter reasoning config dict.
|
"""Parse a reasoning effort level into an OpenRouter reasoning config dict."""
|
||||||
|
from hermes_constants import parse_reasoning_effort
|
||||||
Valid levels: "xhigh", "high", "medium", "low", "minimal", "none".
|
result = parse_reasoning_effort(effort)
|
||||||
Returns None to use the default (medium), or a config dict to override.
|
if effort and effort.strip() and result is None:
|
||||||
"""
|
logger.warning("Unknown reasoning_effort '%s', using default (medium)", effort)
|
||||||
if not effort or not effort.strip():
|
return result
|
||||||
return None
|
|
||||||
effort = effort.strip().lower()
|
|
||||||
if effort == "none":
|
|
||||||
return {"enabled": False}
|
|
||||||
valid = ("xhigh", "high", "medium", "low", "minimal")
|
|
||||||
if effort in valid:
|
|
||||||
return {"enabled": True, "effort": effort}
|
|
||||||
logger.warning("Unknown reasoning_effort '%s', using default (medium)", effort)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def load_cli_config() -> Dict[str, Any]:
|
def load_cli_config() -> Dict[str, Any]:
|
||||||
|
|
@ -2316,7 +2307,7 @@ class HermesCLI:
|
||||||
"""
|
"""
|
||||||
from hermes_cli.clipboard import save_clipboard_image
|
from hermes_cli.clipboard import save_clipboard_image
|
||||||
|
|
||||||
img_dir = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes")) / "images"
|
img_dir = get_hermes_home() / "images"
|
||||||
self._image_counter += 1
|
self._image_counter += 1
|
||||||
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
img_path = img_dir / f"clip_{ts}_{self._image_counter}.png"
|
img_path = img_dir / f"clip_{ts}_{self._image_counter}.png"
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import re
|
||||||
import uuid
|
import uuid
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Optional, Dict, List, Any
|
from typing import Optional, Dict, List, Any
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -30,7 +31,7 @@ except ImportError:
|
||||||
# Configuration
|
# Configuration
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
HERMES_DIR = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
HERMES_DIR = get_hermes_home()
|
||||||
CRON_DIR = HERMES_DIR / "cron"
|
CRON_DIR = HERMES_DIR / "cron"
|
||||||
JOBS_FILE = CRON_DIR / "jobs.json"
|
JOBS_FILE = CRON_DIR / "jobs.json"
|
||||||
OUTPUT_DIR = CRON_DIR / "output"
|
OUTPUT_DIR = CRON_DIR / "output"
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ except ImportError:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
msvcrt = None
|
msvcrt = None
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from hermes_time import now as _hermes_now
|
from hermes_time import now as _hermes_now
|
||||||
|
|
@ -42,7 +43,7 @@ from cron.jobs import get_due_jobs, mark_job_run, save_job_output
|
||||||
SILENT_MARKER = "[SILENT]"
|
SILENT_MARKER = "[SILENT]"
|
||||||
|
|
||||||
# Resolve Hermes home directory (respects HERMES_HOME override)
|
# Resolve Hermes home directory (respects HERMES_HOME override)
|
||||||
_hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
_hermes_home = get_hermes_home()
|
||||||
|
|
||||||
# File-based lock prevents concurrent ticks from gateway + daemon + systemd timer
|
# File-based lock prevents concurrent ticks from gateway + daemon + systemd timer
|
||||||
_LOCK_DIR = _hermes_home / "cron"
|
_LOCK_DIR = _hermes_home / "cron"
|
||||||
|
|
@ -327,16 +328,11 @@ def run_job(job: dict) -> tuple[bool, str, str, Optional[str]]:
|
||||||
logger.warning("Job '%s': failed to load config.yaml, using defaults: %s", job_id, e)
|
logger.warning("Job '%s': failed to load config.yaml, using defaults: %s", job_id, e)
|
||||||
|
|
||||||
# Reasoning config from env or config.yaml
|
# Reasoning config from env or config.yaml
|
||||||
reasoning_config = None
|
from hermes_constants import parse_reasoning_effort
|
||||||
effort = os.getenv("HERMES_REASONING_EFFORT", "")
|
effort = os.getenv("HERMES_REASONING_EFFORT", "")
|
||||||
if not effort:
|
if not effort:
|
||||||
effort = str(_cfg.get("agent", {}).get("reasoning_effort", "")).strip()
|
effort = str(_cfg.get("agent", {}).get("reasoning_effort", "")).strip()
|
||||||
if effort and effort.lower() != "none":
|
reasoning_config = parse_reasoning_effort(effort)
|
||||||
valid = ("xhigh", "high", "medium", "low", "minimal")
|
|
||||||
if effort.lower() in valid:
|
|
||||||
reasoning_config = {"enabled": True, "effort": effort.lower()}
|
|
||||||
elif effort.lower() == "none":
|
|
||||||
reasoning_config = {"enabled": False}
|
|
||||||
|
|
||||||
# Prefill messages from env or config.yaml
|
# Prefill messages from env or config.yaml
|
||||||
prefill_messages = None
|
prefill_messages = None
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,8 @@ _ensure_ssl_certs()
|
||||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
||||||
# Resolve Hermes home directory (respects HERMES_HOME override)
|
# Resolve Hermes home directory (respects HERMES_HOME override)
|
||||||
_hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
from hermes_constants import get_hermes_home
|
||||||
|
_hermes_home = get_hermes_home()
|
||||||
|
|
||||||
# Load environment variables from ~/.hermes/.env first.
|
# Load environment variables from ~/.hermes/.env first.
|
||||||
# User-managed env files should override stale shell exports on restart.
|
# User-managed env files should override stale shell exports on restart.
|
||||||
|
|
@ -805,6 +806,7 @@ class GatewayRunner:
|
||||||
"medium", "low", "minimal", "none". Returns None to use default
|
"medium", "low", "minimal", "none". Returns None to use default
|
||||||
(medium).
|
(medium).
|
||||||
"""
|
"""
|
||||||
|
from hermes_constants import parse_reasoning_effort
|
||||||
effort = ""
|
effort = ""
|
||||||
try:
|
try:
|
||||||
import yaml as _y
|
import yaml as _y
|
||||||
|
|
@ -817,16 +819,10 @@ class GatewayRunner:
|
||||||
pass
|
pass
|
||||||
if not effort:
|
if not effort:
|
||||||
effort = os.getenv("HERMES_REASONING_EFFORT", "")
|
effort = os.getenv("HERMES_REASONING_EFFORT", "")
|
||||||
if not effort:
|
result = parse_reasoning_effort(effort)
|
||||||
return None
|
if effort and effort.strip() and result is None:
|
||||||
effort = effort.lower().strip()
|
logger.warning("Unknown reasoning_effort '%s', using default (medium)", effort)
|
||||||
if effort == "none":
|
return result
|
||||||
return {"enabled": False}
|
|
||||||
valid = ("xhigh", "high", "medium", "low", "minimal")
|
|
||||||
if effort in valid:
|
|
||||||
return {"enabled": True, "effort": effort}
|
|
||||||
logger.warning("Unknown reasoning_effort '%s', using default (medium)", effort)
|
|
||||||
return None
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _load_show_reasoning() -> bool:
|
def _load_show_reasoning() -> bool:
|
||||||
|
|
@ -5743,7 +5739,7 @@ async def start_gateway(config: Optional[GatewayConfig] = None, replace: bool =
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
hermes_home = os.getenv("HERMES_HOME", "~/.hermes")
|
hermes_home = str(get_hermes_home())
|
||||||
logger.error(
|
logger.error(
|
||||||
"Another gateway instance is already running (PID %d, HERMES_HOME=%s). "
|
"Another gateway instance is already running (PID %d, HERMES_HOME=%s). "
|
||||||
"Use 'hermes gateway restart' to replace it, or 'hermes gateway stop' first.",
|
"Use 'hermes gateway restart' to replace it, or 'hermes gateway stop' first.",
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
_GATEWAY_KIND = "hermes-gateway"
|
_GATEWAY_KIND = "hermes-gateway"
|
||||||
|
|
@ -26,7 +27,7 @@ _LOCKS_DIRNAME = "gateway-locks"
|
||||||
|
|
||||||
def _get_pid_path() -> Path:
|
def _get_pid_path() -> Path:
|
||||||
"""Return the path to the gateway PID file, respecting HERMES_HOME."""
|
"""Return the path to the gateway PID file, respecting HERMES_HOME."""
|
||||||
home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
home = get_hermes_home()
|
||||||
return home / "gateway.pid"
|
return home / "gateway.pid"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import subprocess
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
@ -136,7 +137,7 @@ def check_for_updates() -> Optional[int]:
|
||||||
``~/.hermes/.update_check``). Returns the number of commits behind,
|
``~/.hermes/.update_check``). Returns the number of commits behind,
|
||||||
or ``None`` if the check fails or isn't applicable.
|
or ``None`` if the check fails or isn't applicable.
|
||||||
"""
|
"""
|
||||||
hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
hermes_home = get_hermes_home()
|
||||||
repo_dir = hermes_home / "hermes-agent"
|
repo_dir = hermes_home / "hermes-agent"
|
||||||
cache_file = hermes_home / ".update_check"
|
cache_file = hermes_home / ".update_check"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ def is_managed() -> bool:
|
||||||
"""
|
"""
|
||||||
if os.getenv("HERMES_MANAGED", "").lower() in ("true", "1", "yes"):
|
if os.getenv("HERMES_MANAGED", "").lower() in ("true", "1", "yes"):
|
||||||
return True
|
return True
|
||||||
managed_marker = Path(os.getenv("HERMES_HOME", str(Path.home() / ".hermes"))) / ".managed"
|
managed_marker = get_hermes_home() / ".managed"
|
||||||
return managed_marker.exists()
|
return managed_marker.exists()
|
||||||
|
|
||||||
def managed_error(action: str = "modify configuration"):
|
def managed_error(action: str = "modify configuration"):
|
||||||
|
|
@ -76,9 +76,8 @@ def managed_error(action: str = "modify configuration"):
|
||||||
# Config paths
|
# Config paths
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
def get_hermes_home() -> Path:
|
# Re-export from hermes_constants — canonical definition lives there.
|
||||||
"""Get the Hermes home directory (~/.hermes)."""
|
from hermes_constants import get_hermes_home # noqa: F811,E402
|
||||||
return Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
|
||||||
|
|
||||||
def get_config_path() -> Path:
|
def get_config_path() -> Path:
|
||||||
"""Get the main config file path."""
|
"""Get the main config file path."""
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ def get_service_name() -> str:
|
||||||
"""
|
"""
|
||||||
import hashlib
|
import hashlib
|
||||||
from pathlib import Path as _Path # local import to avoid monkeypatch interference
|
from pathlib import Path as _Path # local import to avoid monkeypatch interference
|
||||||
home = _Path(os.getenv("HERMES_HOME", _Path.home() / ".hermes")).resolve()
|
home = get_hermes_home().resolve()
|
||||||
default = (_Path.home() / ".hermes").resolve()
|
default = (_Path.home() / ".hermes").resolve()
|
||||||
if home == default:
|
if home == default:
|
||||||
return _SERVICE_BASE
|
return _SERVICE_BASE
|
||||||
|
|
@ -437,7 +437,7 @@ def generate_systemd_unit(system: bool = False, run_as_user: str | None = None)
|
||||||
path_entries.extend(["/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", "/sbin", "/bin"])
|
path_entries.extend(["/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", "/sbin", "/bin"])
|
||||||
sane_path = ":".join(path_entries)
|
sane_path = ":".join(path_entries)
|
||||||
|
|
||||||
hermes_home = str(Path(os.getenv("HERMES_HOME", Path.home() / ".hermes")).resolve())
|
hermes_home = str(get_hermes_home().resolve())
|
||||||
|
|
||||||
if system:
|
if system:
|
||||||
username, group_name, home_dir = _system_service_identity(run_as_user)
|
username, group_name, home_dir = _system_service_identity(run_as_user)
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,8 @@ from dataclasses import dataclass, field
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -513,8 +515,7 @@ _active_skin_name: str = "default"
|
||||||
|
|
||||||
def _skins_dir() -> Path:
|
def _skins_dir() -> Path:
|
||||||
"""User skins directory."""
|
"""User skins directory."""
|
||||||
home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
return get_hermes_home() / "skins"
|
||||||
return home / "skins"
|
|
||||||
|
|
||||||
|
|
||||||
def _load_skin_from_yaml(path: Path) -> Optional[Dict[str, Any]]:
|
def _load_skin_from_yaml(path: Path) -> Optional[Dict[str, Any]]:
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
|
|
||||||
from hermes_cli.colors import Colors, color
|
from hermes_cli.colors import Colors, color
|
||||||
|
|
||||||
def log_info(msg: str):
|
def log_info(msg: str):
|
||||||
|
|
@ -31,11 +33,6 @@ def get_project_root() -> Path:
|
||||||
return Path(__file__).parent.parent.resolve()
|
return Path(__file__).parent.parent.resolve()
|
||||||
|
|
||||||
|
|
||||||
def get_hermes_home() -> Path:
|
|
||||||
"""Get the Hermes home directory (~/.hermes)."""
|
|
||||||
return Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
|
||||||
|
|
||||||
|
|
||||||
def find_shell_configs() -> list:
|
def find_shell_configs() -> list:
|
||||||
"""Find shell configuration files that might have PATH entries."""
|
"""Find shell configuration files that might have PATH entries."""
|
||||||
home = Path.home()
|
home = Path.home()
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,40 @@ Import-safe module with no dependencies — can be imported from anywhere
|
||||||
without risk of circular imports.
|
without risk of circular imports.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def get_hermes_home() -> Path:
|
||||||
|
"""Return the Hermes home directory (default: ~/.hermes).
|
||||||
|
|
||||||
|
Reads HERMES_HOME env var, falls back to ~/.hermes.
|
||||||
|
This is the single source of truth — all other copies should import this.
|
||||||
|
"""
|
||||||
|
return Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
||||||
|
|
||||||
|
|
||||||
|
VALID_REASONING_EFFORTS = ("xhigh", "high", "medium", "low", "minimal")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_reasoning_effort(effort: str) -> dict | None:
|
||||||
|
"""Parse a reasoning effort level into a config dict.
|
||||||
|
|
||||||
|
Valid levels: "xhigh", "high", "medium", "low", "minimal", "none".
|
||||||
|
Returns None when the input is empty or unrecognized (caller uses default).
|
||||||
|
Returns {"enabled": False} for "none".
|
||||||
|
Returns {"enabled": True, "effort": <level>} for valid effort levels.
|
||||||
|
"""
|
||||||
|
if not effort or not effort.strip():
|
||||||
|
return None
|
||||||
|
effort = effort.strip().lower()
|
||||||
|
if effort == "none":
|
||||||
|
return {"enabled": False}
|
||||||
|
if effort in VALID_REASONING_EFFORTS:
|
||||||
|
return {"enabled": True, "effort": effort}
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1"
|
OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1"
|
||||||
OPENROUTER_MODELS_URL = f"{OPENROUTER_BASE_URL}/models"
|
OPENROUTER_MODELS_URL = f"{OPENROUTER_BASE_URL}/models"
|
||||||
OPENROUTER_CHAT_URL = f"{OPENROUTER_BASE_URL}/chat/completions"
|
OPENROUTER_CHAT_URL = f"{OPENROUTER_BASE_URL}/chat/completions"
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,11 @@ import sqlite3
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_DB_PATH = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes")) / "state.db"
|
DEFAULT_DB_PATH = get_hermes_home() / "state.db"
|
||||||
|
|
||||||
SCHEMA_VERSION = 6
|
SCHEMA_VERSION = 6
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -48,7 +49,7 @@ def _resolve_timezone_name() -> str:
|
||||||
# 2. config.yaml ``timezone`` key
|
# 2. config.yaml ``timezone`` key
|
||||||
try:
|
try:
|
||||||
import yaml
|
import yaml
|
||||||
hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
hermes_home = get_hermes_home()
|
||||||
config_path = hermes_home / "config.yaml"
|
config_path = hermes_home / "config.yaml"
|
||||||
if config_path.exists():
|
if config_path.exists():
|
||||||
with open(config_path) as f:
|
with open(config_path) as f:
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ import os
|
||||||
import logging
|
import logging
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Any, TYPE_CHECKING
|
from typing import Any, TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
@ -29,11 +31,6 @@ GLOBAL_CONFIG_PATH = Path.home() / ".honcho" / "config.json"
|
||||||
HOST = "hermes"
|
HOST = "hermes"
|
||||||
|
|
||||||
|
|
||||||
def _get_hermes_home() -> Path:
|
|
||||||
"""Get HERMES_HOME without importing hermes_cli (avoids circular deps)."""
|
|
||||||
return Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
|
||||||
|
|
||||||
|
|
||||||
def resolve_config_path() -> Path:
|
def resolve_config_path() -> Path:
|
||||||
"""Return the active Honcho config path.
|
"""Return the active Honcho config path.
|
||||||
|
|
||||||
|
|
@ -41,7 +38,7 @@ def resolve_config_path() -> Path:
|
||||||
to ~/.honcho/config.json (global). Returns the global path if neither
|
to ~/.honcho/config.json (global). Returns the global path if neither
|
||||||
exists (for first-time setup writes).
|
exists (for first-time setup writes).
|
||||||
"""
|
"""
|
||||||
local_path = _get_hermes_home() / "honcho.json"
|
local_path = get_hermes_home() / "honcho.json"
|
||||||
if local_path.exists():
|
if local_path.exists():
|
||||||
return local_path
|
return local_path
|
||||||
return GLOBAL_CONFIG_PATH
|
return GLOBAL_CONFIG_PATH
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import yaml
|
||||||
|
|
||||||
# Load .env from ~/.hermes/.env first, then project root as dev fallback.
|
# Load .env from ~/.hermes/.env first, then project root as dev fallback.
|
||||||
# User-managed env files should override stale shell exports on restart.
|
# User-managed env files should override stale shell exports on restart.
|
||||||
_hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
_hermes_home = get_hermes_home()
|
||||||
_project_env = Path(__file__).parent / '.env'
|
_project_env = Path(__file__).parent / '.env'
|
||||||
|
|
||||||
from hermes_cli.env_loader import load_hermes_dotenv
|
from hermes_cli.env_loader import load_hermes_dotenv
|
||||||
|
|
@ -60,7 +60,7 @@ from tools.rl_training_tool import get_missing_keys
|
||||||
# Config Loading
|
# Config Loading
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
from hermes_constants import OPENROUTER_BASE_URL
|
from hermes_constants import get_hermes_home, OPENROUTER_BASE_URL
|
||||||
|
|
||||||
DEFAULT_MODEL = "anthropic/claude-opus-4.5"
|
DEFAULT_MODEL = "anthropic/claude-opus-4.5"
|
||||||
DEFAULT_BASE_URL = OPENROUTER_BASE_URL
|
DEFAULT_BASE_URL = OPENROUTER_BASE_URL
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,13 @@ import fire
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
|
|
||||||
# Load .env from ~/.hermes/.env first, then project root as dev fallback.
|
# Load .env from ~/.hermes/.env first, then project root as dev fallback.
|
||||||
# User-managed env files should override stale shell exports on restart.
|
# User-managed env files should override stale shell exports on restart.
|
||||||
from hermes_cli.env_loader import load_hermes_dotenv
|
from hermes_cli.env_loader import load_hermes_dotenv
|
||||||
|
|
||||||
_hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
_hermes_home = get_hermes_home()
|
||||||
_project_env = Path(__file__).parent / '.env'
|
_project_env = Path(__file__).parent / '.env'
|
||||||
_loaded_env_paths = load_hermes_dotenv(hermes_home=_hermes_home, project_env=_project_env)
|
_loaded_env_paths = load_hermes_dotenv(hermes_home=_hermes_home, project_env=_project_env)
|
||||||
if _loaded_env_paths:
|
if _loaded_env_paths:
|
||||||
|
|
@ -855,7 +857,7 @@ class AIAgent:
|
||||||
self.session_id = f"{timestamp_str}_{short_uuid}"
|
self.session_id = f"{timestamp_str}_{short_uuid}"
|
||||||
|
|
||||||
# Session logs go into ~/.hermes/sessions/ alongside gateway sessions
|
# Session logs go into ~/.hermes/sessions/ alongside gateway sessions
|
||||||
hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
hermes_home = get_hermes_home()
|
||||||
self.logs_dir = hermes_home / "sessions"
|
self.logs_dir = hermes_home / "sessions"
|
||||||
self.logs_dir.mkdir(parents=True, exist_ok=True)
|
self.logs_dir.mkdir(parents=True, exist_ok=True)
|
||||||
self.session_log_file = self.logs_dir / f"session_{self.session_id}.json"
|
self.session_log_file = self.logs_dir / f"session_{self.session_id}.json"
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Dict, List, Optional, Set
|
from typing import Dict, List, Optional, Set
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -32,7 +33,7 @@ logger = logging.getLogger(__name__)
|
||||||
# Constants
|
# Constants
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
CHECKPOINT_BASE = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes")) / "checkpoints"
|
CHECKPOINT_BASE = get_hermes_home() / "checkpoints"
|
||||||
|
|
||||||
DEFAULT_EXCLUDES = [
|
DEFAULT_EXCLUDES = [
|
||||||
"node_modules/",
|
"node_modules/",
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,13 @@ import re
|
||||||
import tempfile
|
import tempfile
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Where memory files live
|
# Where memory files live
|
||||||
MEMORY_DIR = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes")) / "memories"
|
MEMORY_DIR = get_hermes_home() / "memories"
|
||||||
|
|
||||||
ENTRY_DELIMITER = "\n§\n"
|
ENTRY_DELIMITER = "\n§\n"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
@ -55,7 +57,7 @@ HERMES_ROOT = Path(__file__).parent.parent
|
||||||
TINKER_ATROPOS_ROOT = HERMES_ROOT / "tinker-atropos"
|
TINKER_ATROPOS_ROOT = HERMES_ROOT / "tinker-atropos"
|
||||||
ENVIRONMENTS_DIR = TINKER_ATROPOS_ROOT / "tinker_atropos" / "environments"
|
ENVIRONMENTS_DIR = TINKER_ATROPOS_ROOT / "tinker_atropos" / "environments"
|
||||||
CONFIGS_DIR = TINKER_ATROPOS_ROOT / "configs"
|
CONFIGS_DIR = TINKER_ATROPOS_ROOT / "configs"
|
||||||
LOGS_DIR = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes")) / "logs" / "rl_training"
|
LOGS_DIR = get_hermes_home() / "logs" / "rl_training"
|
||||||
|
|
||||||
def _ensure_logs_dir():
|
def _ensure_logs_dir():
|
||||||
"""Lazily create logs directory on first use (avoid side effects at import time)."""
|
"""Lazily create logs directory on first use (avoid side effects at import time)."""
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import re
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Dict, Any, Optional
|
from typing import Dict, Any, Optional
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -76,7 +77,7 @@ import yaml
|
||||||
|
|
||||||
|
|
||||||
# All skills live in ~/.hermes/skills/ (single source of truth)
|
# All skills live in ~/.hermes/skills/ (single source of truth)
|
||||||
HERMES_HOME = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
HERMES_HOME = get_hermes_home()
|
||||||
SKILLS_DIR = HERMES_HOME / "skills"
|
SKILLS_DIR = HERMES_HOME / "skills"
|
||||||
|
|
||||||
MAX_NAME_LENGTH = 64
|
MAX_NAME_LENGTH = 64
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ from abc import ABC, abstractmethod
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||||
from urllib.parse import urlparse, urlunparse
|
from urllib.parse import urlparse, urlunparse
|
||||||
|
|
||||||
|
|
@ -42,7 +43,7 @@ logger = logging.getLogger(__name__)
|
||||||
# Paths
|
# Paths
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
HERMES_HOME = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
HERMES_HOME = get_hermes_home()
|
||||||
SKILLS_DIR = HERMES_HOME / "skills"
|
SKILLS_DIR = HERMES_HOME / "skills"
|
||||||
HUB_DIR = SKILLS_DIR / ".hub"
|
HUB_DIR = SKILLS_DIR / ".hub"
|
||||||
LOCK_FILE = HUB_DIR / "lock.json"
|
LOCK_FILE = HUB_DIR / "lock.json"
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,13 @@ import logging
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Dict, List, Tuple
|
from typing import Dict, List, Tuple
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
HERMES_HOME = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
HERMES_HOME = get_hermes_home()
|
||||||
SKILLS_DIR = HERMES_HOME / "skills"
|
SKILLS_DIR = HERMES_HOME / "skills"
|
||||||
MANIFEST_FILE = SKILLS_DIR / ".bundled_manifest"
|
MANIFEST_FILE = SKILLS_DIR / ".bundled_manifest"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ Usage:
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -85,7 +87,7 @@ logger = logging.getLogger(__name__)
|
||||||
# All skills live in ~/.hermes/skills/ (seeded from bundled skills/ on install).
|
# All skills live in ~/.hermes/skills/ (seeded from bundled skills/ on install).
|
||||||
# This is the single source of truth -- agent edits, hub installs, and bundled
|
# This is the single source of truth -- agent edits, hub installs, and bundled
|
||||||
# skills all coexist here without polluting the git repo.
|
# skills all coexist here without polluting the git repo.
|
||||||
HERMES_HOME = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
HERMES_HOME = get_hermes_home()
|
||||||
SKILLS_DIR = HERMES_HOME / "skills"
|
SKILLS_DIR = HERMES_HOME / "skills"
|
||||||
|
|
||||||
# Anthropic-recommended limits for progressive disclosure efficiency
|
# Anthropic-recommended limits for progressive disclosure efficiency
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ import threading
|
||||||
import time
|
import time
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_REPO = "sheeki03/tirith"
|
_REPO = "sheeki03/tirith"
|
||||||
|
|
@ -104,14 +106,8 @@ _MARKER_TTL = 86400 # 24 hours
|
||||||
|
|
||||||
|
|
||||||
def _get_hermes_home() -> str:
|
def _get_hermes_home() -> str:
|
||||||
"""Return the Hermes home directory, respecting HERMES_HOME env var.
|
"""Return the Hermes home directory, respecting HERMES_HOME env var."""
|
||||||
|
return str(get_hermes_home())
|
||||||
Matches the convention used throughout the codebase (hermes_cli.config,
|
|
||||||
cli.py, gateway/run.py, etc.) so tirith state stays inside the active
|
|
||||||
profile and tests get automatic isolation via conftest's HERMES_HOME
|
|
||||||
monkeypatch.
|
|
||||||
"""
|
|
||||||
return os.getenv("HERMES_HOME") or os.path.join(os.path.expanduser("~"), ".hermes")
|
|
||||||
|
|
||||||
|
|
||||||
def _failure_marker_path() -> str:
|
def _failure_marker_path() -> str:
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Dict, Any
|
from typing import Optional, Dict, Any
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -83,7 +85,7 @@ def get_stt_model_from_config() -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
import yaml
|
import yaml
|
||||||
cfg_path = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes")) / "config.yaml"
|
cfg_path = get_hermes_home() / "config.yaml"
|
||||||
if cfg_path.exists():
|
if cfg_path.exists():
|
||||||
with open(cfg_path) as f:
|
with open(cfg_path) as f:
|
||||||
data = yaml.safe_load(f) or {}
|
data = yaml.safe_load(f) or {}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
from typing import Callable, Dict, Any, Optional
|
from typing import Callable, Dict, Any, Optional
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -73,7 +74,7 @@ DEFAULT_ELEVENLABS_MODEL_ID = "eleven_multilingual_v2"
|
||||||
DEFAULT_ELEVENLABS_STREAMING_MODEL_ID = "eleven_flash_v2_5"
|
DEFAULT_ELEVENLABS_STREAMING_MODEL_ID = "eleven_flash_v2_5"
|
||||||
DEFAULT_OPENAI_MODEL = "gpt-4o-mini-tts"
|
DEFAULT_OPENAI_MODEL = "gpt-4o-mini-tts"
|
||||||
DEFAULT_OPENAI_VOICE = "alloy"
|
DEFAULT_OPENAI_VOICE = "alloy"
|
||||||
DEFAULT_OUTPUT_DIR = str(Path(os.getenv("HERMES_HOME", Path.home() / ".hermes")) / "audio_cache")
|
DEFAULT_OUTPUT_DIR = str(get_hermes_home() / "audio_cache")
|
||||||
MAX_TEXT_LENGTH = 4000
|
MAX_TEXT_LENGTH = 4000
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_DEFAULT_WEBSITE_BLOCKLIST = {
|
_DEFAULT_WEBSITE_BLOCKLIST = {
|
||||||
|
|
@ -36,12 +38,8 @@ _cached_policy_path: Optional[str] = None
|
||||||
_cached_policy_time: float = 0.0
|
_cached_policy_time: float = 0.0
|
||||||
|
|
||||||
|
|
||||||
def _get_hermes_home() -> Path:
|
|
||||||
return Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
|
||||||
|
|
||||||
|
|
||||||
def _get_default_config_path() -> Path:
|
def _get_default_config_path() -> Path:
|
||||||
return _get_hermes_home() / "config.yaml"
|
return get_hermes_home() / "config.yaml"
|
||||||
|
|
||||||
|
|
||||||
class WebsitePolicyError(Exception):
|
class WebsitePolicyError(Exception):
|
||||||
|
|
@ -182,7 +180,7 @@ def load_website_blocklist(config_path: Optional[Path] = None) -> Dict[str, Any]
|
||||||
continue
|
continue
|
||||||
path = Path(shared_file).expanduser()
|
path = Path(shared_file).expanduser()
|
||||||
if not path.is_absolute():
|
if not path.is_absolute():
|
||||||
path = (_get_hermes_home() / path).resolve()
|
path = (get_hermes_home() / path).resolve()
|
||||||
for normalized in _iter_blocklist_file_rules(path):
|
for normalized in _iter_blocklist_file_rules(path):
|
||||||
key = (str(path), normalized)
|
key = (str(path), normalized)
|
||||||
if key in seen:
|
if key in seen:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue