A fresh root install on Linux (e.g. a new Proxmox/Ubuntu VM) places the Hermes
Agent at /usr/local/lib/hermes-agent and links the CLI into /usr/local/bin,
while the modern `hermes` launcher is a `#!/usr/bin/env bash` wrapper that
exec's the venv entrypoint. The old discovery only checked
~/.hermes/hermes-agent-style paths and parsed the launcher's shebang as a Python
interpreter, so on a root VM discover_agent_dir() returned None, bootstrap built
a WebUI-only .venv, and chat aborted at launch with "Python environment cannot
import both WebUI dependencies and Hermes Agent."
Two complementary fixes:
- Add /usr/local/lib/hermes-agent to discover_agent_dir()'s candidate list.
- Harden _agent_dir_from_hermes_cli() to follow the launcher's exec target (any
absolute path quoted in the wrapper) up to run_agent.py, not just a Python
shebang. Skips /usr/bin/env indirection.
Now `python3 bootstrap.py` works out of the box for root/container installs with
no HERMES_WEBUI_PYTHON override needed. Adds tests for the bash-wrapper shape,
the env-indirection no-false-positive case, and the FHS candidate probe; updates
docs/troubleshooting.md.
Two in-stage fixes for v0.51.19 batch:
1) api/config.py — add resolve_alias=False param to
_resolve_configured_provider_id() and pass it from
resolve_model_provider(). The PR #1818 swap from
_resolve_provider_alias() to _resolve_configured_provider_id()
was correct for active-provider/badge surfaces but broke #1625's
local-server-provider literal-preservation contract: 'ollama' →
'custom' and 'lm-studio' → 'lmstudio' alias-collapse caused
_LOCAL_SERVER_PROVIDERS membership check to miss, breaking the
model-id full-path preservation for LM Studio/Ollama. The new
flag preserves the raw provider value when called from
resolve_model_provider, and named-custom-slug + base-url
fallback both still run unchanged.
2) tests/test_bootstrap_discover_agent.py — pin Path.home() in
_isolate_discover_agent_dir so the hard-coded
'Path.home() / .hermes / hermes-agent' / 'Path.home() /
hermes-agent' candidates in discover_agent_dir() can't pick up
the dev machine's real install. The original PR #1817 isolation
helper covered HERMES_HOME, HERMES_WEBUI_AGENT_DIR, and
REPO_ROOT but missed the Path.home() leak.
Both surfaced on full pytest pre-release gate, fixed in stage,
ship in v0.51.19. Tests: full suite green.
Addresses review feedback on PR #1817:
1. Extend the `_agent_dir_from_hermes_cli` docstring to spell out that
the shebang fallback is a last-resort discovery step, not an override.
Stale clones in known candidate paths still win — same precedence as
today, but now documented so a future maintainer doesn't get the
wrong idea.
2. Drop the misleading "install exists but no run_agent.py" comment in
`test_returns_none_when_shebang_interpreter_does_not_walk_to_run_agent`.
The test exercises a shebang pointing at /usr/bin/python3 whose
parents never reach a run_agent.py — it doesn't actually need a fake
install dir at all. Renamed for accuracy and removed the unused
_make_agent_install call.
`discover_agent_dir()` only checked four hard-coded layouts:
- HERMES_WEBUI_AGENT_DIR
- $HERMES_HOME/hermes-agent
- <webui-parent>/hermes-agent
- ~/.hermes/hermes-agent / ~/hermes-agent
Users who clone hermes-agent somewhere else (e.g. ~/Projects/GitHub/hermes-agent)
hit:
[bootstrap] ERROR: Python environment cannot import both WebUI dependencies
and Hermes Agent. Set HERMES_WEBUI_PYTHON to the Hermes Agent venv Python
or install the WebUI requirements into that environment.
…even though the `hermes` CLI is on PATH and works fine. The CLI is a
console-script with a venv-relative shebang:
#!/path/to/hermes-agent/venv/bin/python3
After the explicit candidates miss, fall back to introspecting that shebang
and walking up parents until we find `run_agent.py`. That's a reliable
pointer to the install root regardless of where the user cloned the repo.
Tests cover happy path, no `hermes` on PATH, missing/invalid shebang,
shebang pointing outside any agent install (e.g. /usr/bin/python3), and
explicit candidates winning over the shebang fallback.
Verified end-to-end: with hermes-agent at a non-standard path,
`uv run bootstrap.py` now succeeds without any HERMES_WEBUI_AGENT_DIR
override.