Skip to content

v0.51.19 — 15-PR contributor sweep + 1 in-stage absorb#1829

Merged
nesquena-hermes merged 37 commits intomasterfrom
stage-313
May 7, 2026
Merged

v0.51.19 — 15-PR contributor sweep + 1 in-stage absorb#1829
nesquena-hermes merged 37 commits intomasterfrom
stage-313

Conversation

@nesquena-hermes
Copy link
Copy Markdown
Collaborator

v0.51.19 — 15-PR contributor sweep + 1 in-stage absorb

Single-commit release rolling up 15 contributor PRs spanning workspace robustness, IPv6 server bind, bootstrap path discovery, named custom provider routing, quota cards (Codex/Anthropic), live Codex model listing, sidebar/composer/approval correctness, and historical-transcript repair tooling.

Constituent PRs

Backend / config

Backend / providers

Frontend / sessions

Frontend / ui

Streaming

Ops

In-stage absorbs (during pre-release gate)

  1. api/config.py — Added resolve_alias=False flag to _resolve_configured_provider_id() so resolve_model_provider() preserves raw 'ollama' / 'lm-studio' / 'vllm' etc. provider strings for _LOCAL_SERVER_PROVIDERS set membership in bug(config): resolve_model_provider() strips provider prefix on local model servers — LM Studio loads duplicate instance with default settings #1625's full-model-id-preservation contract. PR fix: route named custom provider model selections #1818's swap was correct for active-provider/badge surfaces but broke this branch via _resolve_provider_alias collapsing 'ollama' → 'custom'.
  2. tests/test_bootstrap_discover_agent.py — Pinned Path.home() in _isolate_discover_agent_dir so PR fix(bootstrap): discover agent dir via hermes CLI shebang #1817's tests don't pick up the dev machine's real ~/.hermes/hermes-agent. Test-only.

Tests

  • 4747 → 4790 collected (+43)
  • 4776 passed, 11 skipped, 1 xfailed, 2 xpassed, 0 failed in 145.9s
  • Browser API harness 11/11 endpoints green
  • JS syntax check 5/5 modified files green (node -c)
  • Python syntax check 25/25 files green
  • No file deletions, no merge-conflict markers

Pre-release verification

  • All 15 PRs CI-green individually
  • File overlaps resolved via stage-HEAD rebase for sibling PRs (sessions.js trio: 1797/1802/1819; ui.js trio: 1801/1803/1813; api/providers.py pair: 1805/1812; bootstrap.py pair: 1815/1817; CHANGELOG.md stripped from contributor branches before merge)
  • Pre-stamp re-fetch: all 15 PR heads still match local rebases (no mid-sweep force-pushes)
  • Opus advisor: SHIP verdict, 0 MUST-FIX, 0 SHOULD-FIX in-release. Two narrow follow-ups deferred to new issues:

Maintainer triage

Closes #1792, #1795, #1796, #1800, #1806, #1807, #1694.

Frank Song and others added 30 commits May 7, 2026 17:36
Detect IPv6 addresses (containing ':') in QuietHTTPServer.__init__ and set address_family to AF_INET6 before socket creation, fixing EAFNOSUPPORT when binding to :: or ::1.

Also updates the loopback check to recognize ::1 and the container warning to mention :: as the IPv6 equivalent of 0.0.0.0. Documents IPv6 usage in HERMES_WEBUI_HOST env var description.
Without symlinks=True, mise/asdf shared-library Python builds on macOS
default venv to copy mode. The copied python3 binary still references
@executable_path/../lib/libpython3.X.dylib in its load command, but the
dylib is never copied into .venv/lib — so any import in the new venv
(starting with ensurepip) aborts with SIGABRT.

Reproduces with mise's cpython 3.13.9 build:

    [bootstrap] Creating local virtualenv at .../.venv
    [bootstrap] ERROR: Command '[".../.venv/bin/python3.13", "-m",
      "ensurepip", "--upgrade", "--default-pip"]' died with
      <Signals.SIGABRT: 6>.

Symlinking the interpreter keeps @executable_path resolving back to the
original install where libpython lives. uv-managed Pythons already
symlink by default; mise's do not.
Addresses review feedback on PR #1815:

1. Extend the inline comment to note that CPython's venv falls back to
   copy mode when symlink creation fails (e.g. older Windows without
   SeCreateSymbolicLinkPrivilege), so symlinks=True is safe to set
   unconditionally — no platform branching needed.

2. Add a regression test that asserts EnvBuilder is called with
   symlinks=True. Cheap insurance against a future "simplify" pass
   removing the flag without realising it's load-bearing on macOS.
`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.
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.
nesquena-hermes and others added 7 commits May 7, 2026 16:58
…on + harden bootstrap test isolation

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.
… absorb

- 15 contributor PRs across backend (workspace, IPv6, bootstrap pair,
  named custom provider routing, quota cards, live Codex models),
  frontend (sessions trio: optimistic-row preservation, cross-surface
  continuation, session-owned approval prompts; ui trio: workspace
  metadata strip, error toast Copy + hover-pause, file picker + HTML
  preview interactions), streaming (workspace-prefix dedupe), and
  ops (workspace user-turn repair script).
- 1 in-stage absorb on api/config.py: gate _resolve_configured_provider_id
  alias resolution behind resolve_alias flag so resolve_model_provider
  preserves raw provider strings for #1625 _LOCAL_SERVER_PROVIDERS
  literal-match.
- 1 in-stage test absorb on test_bootstrap_discover_agent.py: pin
  Path.home() in isolation helper so PR #1817 tests don't pick up
  the dev machine's real ~/.hermes/hermes-agent.
- 4747 → 4790 collected (+43). 4776 pass + 11 skip + 1 xfail + 2 xpass.
- Browser API harness 11/11 green. JS syntax 5/5 clean.
- Opus advisor SHIP verdict, 0 MUST-FIX, 0 SHOULD-FIX in-release.

Closes #1792, #1795, #1796, #1800, #1806, #1807, #1694.
@nesquena-hermes nesquena-hermes merged commit bc73299 into master May 7, 2026
3 checks passed
@nesquena-hermes nesquena-hermes deleted the stage-313 branch May 7, 2026 17:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment