mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-11 08:42:11 +00:00
* docs(code-execution): document HERMES_* env narrowing + passthrough workaround
The execute_code sandbox-child env scrub (108397726, #27303) deliberately
dropped the broad HERMES_ prefix passthrough, keeping only an operational
4-var allowlist (HERMES_HOME/PROFILE/CONFIG/ENV). A script that relied on a
non-secret HERMES_* var (HERMES_BASE_URL, HERMES_KANBAN_DB, HERMES_*_WEBHOOK,
or a plugin-defined one) now sees it unset in the child.
Document the behavior change and the two recovery routes (terminal.env_passthrough
in config.yaml, or required_environment_variables in skill frontmatter), plus
the debug log line that surfaces the drop for diagnosis.
* feat(cli): warn on unsupported pip installs + fix stale update-check cache after pip upgrade
Banner now shows a yellow warning when detect_install_method() == 'pip':
'pip install hermes-agent' isn't the supported install path (it exists on
PyPI for internal/CI reasons), so updates and issue support don't behave
correctly. Reuses existing install-method detection; warn, never block.
Also fixes #34491: check_for_updates() keyed its 6h cache only on ts+rev.
On the pip path (no HERMES_REVISION), rev is always None, so a
'pip install --upgrade' changed VERSION but left the cache valid — the
stale 'N commits behind' count survived the upgrade. Cache now also keys
on the installed VERSION and invalidates on mismatch.
111 lines
4.4 KiB
Python
111 lines
4.4 KiB
Python
from unittest.mock import patch
|
|
|
|
|
|
def test_pip_install_detected_when_no_git_dir(tmp_path):
|
|
"""When PROJECT_ROOT has no .git, detect as pip install."""
|
|
with patch("hermes_cli.config.get_managed_system", return_value=None), \
|
|
patch("hermes_cli.config.get_hermes_home", return_value=tmp_path):
|
|
from hermes_cli.config import detect_install_method
|
|
method = detect_install_method(project_root=tmp_path)
|
|
assert method == "pip"
|
|
|
|
|
|
def test_git_install_detected_when_git_dir_exists(tmp_path):
|
|
"""When PROJECT_ROOT has .git, detect as git install."""
|
|
(tmp_path / ".git").mkdir()
|
|
with patch("hermes_cli.config.get_managed_system", return_value=None), \
|
|
patch("hermes_cli.config.get_hermes_home", return_value=tmp_path):
|
|
from hermes_cli.config import detect_install_method
|
|
method = detect_install_method(project_root=tmp_path)
|
|
assert method == "git"
|
|
|
|
|
|
def test_managed_install_takes_precedence(tmp_path):
|
|
"""When HERMES_MANAGED is set, that takes precedence over git detection."""
|
|
(tmp_path / ".git").mkdir()
|
|
with patch("hermes_cli.config.get_managed_system", return_value="NixOS"), \
|
|
patch("hermes_cli.config.get_hermes_home", return_value=tmp_path):
|
|
from hermes_cli.config import detect_install_method
|
|
method = detect_install_method(project_root=tmp_path)
|
|
assert method == "nixos"
|
|
|
|
|
|
def test_recommended_update_command_pip():
|
|
"""Pip installs recommend pip install --upgrade."""
|
|
from hermes_cli.config import recommended_update_command_for_method
|
|
cmd = recommended_update_command_for_method("pip")
|
|
assert "pip install" in cmd or "uv pip install" in cmd
|
|
assert "--upgrade" in cmd
|
|
assert "hermes-agent" in cmd
|
|
|
|
|
|
def test_stamp_file_takes_precedence(tmp_path):
|
|
(tmp_path / ".git").mkdir()
|
|
(tmp_path / ".install_method").write_text("docker\n")
|
|
with patch("hermes_cli.config.get_managed_system", return_value=None), \
|
|
patch("hermes_cli.config.get_hermes_home", return_value=tmp_path):
|
|
from hermes_cli.config import detect_install_method
|
|
assert detect_install_method(project_root=tmp_path) == "docker"
|
|
|
|
|
|
def test_docker_detected_via_dockerenv(tmp_path):
|
|
with patch("hermes_cli.config.get_managed_system", return_value=None), \
|
|
patch("hermes_cli.config.get_hermes_home", return_value=tmp_path), \
|
|
patch("hermes_constants.is_container", return_value=True):
|
|
from hermes_cli.config import detect_install_method
|
|
assert detect_install_method(project_root=tmp_path) == "docker"
|
|
|
|
|
|
def test_recommended_update_command_docker():
|
|
from hermes_cli.config import recommended_update_command_for_method
|
|
assert "docker pull" in recommended_update_command_for_method("docker")
|
|
|
|
|
|
def test_banner_warns_on_pip_install(tmp_path):
|
|
"""The welcome banner surfaces a warning when the install method is pip."""
|
|
import io
|
|
from rich.console import Console
|
|
from hermes_cli import banner
|
|
|
|
hh = tmp_path / ".hermes"
|
|
hh.mkdir()
|
|
(hh / ".install_method").write_text("pip\n")
|
|
|
|
with patch("hermes_cli.config.get_hermes_home", return_value=hh), \
|
|
patch("hermes_constants.get_hermes_home", return_value=hh):
|
|
buf = io.StringIO()
|
|
# Wide console so the warning isn't wrapped across lines in the panel.
|
|
console = Console(file=buf, width=400, force_terminal=False, color_system=None)
|
|
banner.build_welcome_banner(
|
|
console, model="m", cwd="/tmp",
|
|
tools=[{"function": {"name": "terminal"}}],
|
|
enabled_toolsets=["terminal"],
|
|
)
|
|
out = buf.getvalue()
|
|
|
|
assert "officially" in out
|
|
assert "instability" in out
|
|
|
|
|
|
def test_banner_no_pip_warning_on_git_install(tmp_path):
|
|
"""Git installs must not show the pip-install warning."""
|
|
import io
|
|
from rich.console import Console
|
|
from hermes_cli import banner
|
|
|
|
hh = tmp_path / ".hermes"
|
|
hh.mkdir()
|
|
(hh / ".install_method").write_text("git\n")
|
|
|
|
with patch("hermes_cli.config.get_hermes_home", return_value=hh), \
|
|
patch("hermes_constants.get_hermes_home", return_value=hh):
|
|
buf = io.StringIO()
|
|
console = Console(file=buf, width=400, force_terminal=False, color_system=None)
|
|
banner.build_welcome_banner(
|
|
console, model="m", cwd="/tmp",
|
|
tools=[{"function": {"name": "terminal"}}],
|
|
enabled_toolsets=["terminal"],
|
|
)
|
|
out = buf.getvalue()
|
|
|
|
assert "officially" not in out
|