mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix: profile paths broken in Docker — profiles go to /root/.hermes instead of mounted volume (#7170)
In Docker, HERMES_HOME=/opt/data (set in Dockerfile) and users mount their .hermes directory to /opt/data. However, profile operations used Path.home() / '.hermes' which resolves to /root/.hermes in Docker — an ephemeral container path, not the mounted volume. This caused: - Profiles created at /root/.hermes/profiles/ (lost on container recreate) - active_profile sticky file written to wrong location - profile list looking at wrong directory Fix: Add get_default_hermes_root() to hermes_constants.py that detects Docker/custom deployments (HERMES_HOME outside ~/.hermes) and returns HERMES_HOME as the root. Also handles Docker profiles correctly (<root>/profiles/<name> → root is grandparent). Files changed: - hermes_constants.py: new get_default_hermes_root() - hermes_cli/profiles.py: _get_default_hermes_home() delegates to shared fn - hermes_cli/main.py: _apply_profile_override() + _invalidate_update_cache() - hermes_cli/gateway.py: _profile_suffix() + _profile_arg() - Tests: 12 new tests covering Docker scenarios
This commit is contained in:
parent
916fbf362c
commit
4a65c9cd08
8 changed files with 218 additions and 24 deletions
|
|
@ -17,6 +17,45 @@ def get_hermes_home() -> Path:
|
|||
return Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
||||
|
||||
|
||||
def get_default_hermes_root() -> Path:
|
||||
"""Return the root Hermes directory for profile-level operations.
|
||||
|
||||
In standard deployments this is ``~/.hermes``.
|
||||
|
||||
In Docker or custom deployments where ``HERMES_HOME`` points outside
|
||||
``~/.hermes`` (e.g. ``/opt/data``), returns ``HERMES_HOME`` directly
|
||||
— that IS the root.
|
||||
|
||||
In profile mode where ``HERMES_HOME`` is ``<root>/profiles/<name>``,
|
||||
returns ``<root>`` so that ``profile list`` can see all profiles.
|
||||
Works both for standard (``~/.hermes/profiles/coder``) and Docker
|
||||
(``/opt/data/profiles/coder``) layouts.
|
||||
|
||||
Import-safe — no dependencies beyond stdlib.
|
||||
"""
|
||||
native_home = Path.home() / ".hermes"
|
||||
env_home = os.environ.get("HERMES_HOME", "")
|
||||
if not env_home:
|
||||
return native_home
|
||||
env_path = Path(env_home)
|
||||
try:
|
||||
env_path.resolve().relative_to(native_home.resolve())
|
||||
# HERMES_HOME is under ~/.hermes (normal or profile mode)
|
||||
return native_home
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Docker / custom deployment.
|
||||
# Check if this is a profile path: <root>/profiles/<name>
|
||||
# If the immediate parent dir is named "profiles", the root is
|
||||
# the grandparent — this covers Docker profiles correctly.
|
||||
if env_path.parent.name == "profiles":
|
||||
return env_path.parent.parent
|
||||
|
||||
# Not a profile path — HERMES_HOME itself is the root
|
||||
return env_path
|
||||
|
||||
|
||||
def get_optional_skills_dir(default: Path | None = None) -> Path:
|
||||
"""Return the optional-skills directory, honoring package-manager wrappers.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue