fix(cli): no false "[HERMES_HOME fallback] wrong profile" warning on every command
Users who set a sticky profile with `hermes profile use <name>` saw
`[HERMES_HOME fallback] HERMES_HOME is unset but active profile is '<name>'
... Any data this process writes will land in the wrong profile` printed by
EVERY `hermes` invocation (`--version`, `update`, `gateway restart`), even
though the CLI re-homes to that profile a few lines later and nothing lands
in the wrong place.
`main._apply_profile_override` scans argv with `top_level_value_flag_sets()`,
which builds the real parser BEFORE the override sets HERMES_HOME. Since
23036e20a6 the `--no-config` help string spells the config path through
`display_hermes_home()` -> `get_hermes_home()`, and that lookup fires the
one-shot fallback warning for a throwaway help string.
`display_hermes_home()` takes an optional `home`; the parser's `_cfg_path()`
passes `get_process_hermes_home()`, which reads HERMES_HOME without the
warning and, after the override, IS the profile home — so `hermes -p coder
--help` still shows `~/.hermes/profiles/coder/config.yaml`. The genuine
warning (a process that really runs under the wrong home) is untouched.
Fixes #112319
Part of #112839
This commit is contained in:
@@ -27,10 +27,16 @@ _OPTIONAL_VALUE_FLAGS_FALLBACK: frozenset[str] = frozenset({"-c", "--continue"})
|
||||
|
||||
|
||||
def _cfg_path() -> str:
|
||||
"""``~/.hermes/config.yaml`` spelled for the active profile, for help text."""
|
||||
from hermes_constants import display_hermes_home
|
||||
"""``~/.hermes/config.yaml`` spelled for the active profile, for help text.
|
||||
|
||||
return f"{display_hermes_home()}/config.yaml"
|
||||
``main._apply_profile_override`` builds this parser (via ``top_level_value_flag_sets``) BEFORE
|
||||
it re-homes the process to the sticky ``active_profile``; ``get_hermes_home()`` would emit the
|
||||
"[HERMES_HOME fallback] ... wrong profile" warning on every ``hermes`` command for that
|
||||
throwaway help string. Read the process home directly: after the override it IS the profile home.
|
||||
"""
|
||||
from hermes_constants import display_hermes_home, get_process_hermes_home
|
||||
|
||||
return f"{display_hermes_home(get_process_hermes_home())}/config.yaml"
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
|
||||
@@ -809,9 +809,14 @@ def _legacy_path_has_content(path: Path) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def display_hermes_home() -> str:
|
||||
"""User-facing ``~/`` display string for HERMES_HOME (``~/.hermes/profiles/coder``)."""
|
||||
home = get_hermes_home()
|
||||
def display_hermes_home(home: Path | None = None) -> str:
|
||||
"""User-facing ``~/`` display string for HERMES_HOME (``~/.hermes/profiles/coder``).
|
||||
|
||||
``home`` overrides the lookup for callers that run before the CLI has applied the sticky
|
||||
``active_profile`` (``get_hermes_home()`` would emit the wrong-profile fallback warning there).
|
||||
"""
|
||||
if home is None:
|
||||
home = get_hermes_home()
|
||||
try: # as_posix(): str() on Windows yields chimeras like ~/AppData\Local\hermes/skills/
|
||||
return "~/" + home.relative_to(Path.home()).as_posix()
|
||||
except ValueError:
|
||||
|
||||
40
tests/hermes_cli/test_parser_help_home.py
Normal file
40
tests/hermes_cli/test_parser_help_home.py
Normal file
@@ -0,0 +1,40 @@
|
||||
"""The top-level parser's help text must not trip the wrong-profile fallback warning.
|
||||
|
||||
``main._apply_profile_override`` builds the parser (``top_level_value_flag_sets``) before it
|
||||
re-homes the process to the sticky ``active_profile``; a help string that resolved the home through
|
||||
``get_hermes_home()`` printed ``[HERMES_HOME fallback] ... wrong profile`` on every ``hermes``
|
||||
command for users of ``hermes profile use`` (#112319, also reported in #112839).
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sticky_profile_home(monkeypatch, tmp_path):
|
||||
import hermes_constants
|
||||
|
||||
monkeypatch.setattr(Path, "home", lambda: tmp_path)
|
||||
monkeypatch.delenv("HERMES_HOME", raising=False)
|
||||
root = tmp_path / ".hermes"
|
||||
(root / "profiles" / "coder").mkdir(parents=True)
|
||||
(root / "active_profile").write_text("coder\n", encoding="utf-8")
|
||||
monkeypatch.setattr(hermes_constants, "_profile_fallback_warned", False)
|
||||
return root
|
||||
|
||||
|
||||
def test_building_the_parser_before_the_profile_override_stays_silent(sticky_profile_home, capsys):
|
||||
from hermes_cli._parser import build_top_level_parser
|
||||
|
||||
build_top_level_parser()
|
||||
|
||||
assert "HERMES_HOME fallback" not in capsys.readouterr().err
|
||||
|
||||
|
||||
def test_help_text_names_the_profile_config_once_the_process_is_re_homed(sticky_profile_home, monkeypatch):
|
||||
from hermes_cli._parser import _cfg_path
|
||||
|
||||
monkeypatch.setenv("HERMES_HOME", str(sticky_profile_home / "profiles" / "coder"))
|
||||
|
||||
assert _cfg_path() == "~/.hermes/profiles/coder/config.yaml"
|
||||
Reference in New Issue
Block a user