fix: detect agent version from copied source - #2703
Michaelyklam wants to merge 1 commit into
Conversation
3c37511 to
eadafaa
Compare
|
Read the diff at PR head SummaryFix matches the bug shape in #2691 and the layering is right: this is a webui-side detection bug (agent-side already returns Code referenceThe new copied-source fallback (api/updates.py in the diff): def _read_agent_source_version(agent_dir: Path) -> str | None:
init_file = agent_dir / 'hermes_cli' / '__init__.py'
try:
text = init_file.read_text(encoding='utf-8')
except (OSError, UnicodeDecodeError):
return None
m = re.search(r"""__version__\s*=\s*['"]([^'"]+)['"]""", text)
if m and m.group(1).strip():
return m.group(1).strip()
return NoneThis is solid — Concern: gateway
|
…ource (Docker two-container System panel) (closes nesquena#2691) Closes nesquena#2691 Co-authored-by: Michaelyklam <Michaelyklam@users.noreply.github.com>
…➔ 0.51.105) (#613) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/nesquena/hermes-webui](https://github.com/nesquena/hermes-webui) | patch | `0.51.103` → `0.51.105` | --- ### Release Notes <details> <summary>nesquena/hermes-webui (ghcr.io/nesquena/hermes-webui)</summary> ### [`v0.51.105`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051105--2026-05-21--Release-CC-stage-398--4-PR-batch--hide-suggestions-preference--Docker-agent-version-from-copied-source--runner-local-adapter-selection--configurable-pinned-session-limit) [Compare Source](nesquena/hermes-webui@v0.51.104...v0.51.105) ##### Added - **PR [#​2687](nesquena/hermes-webui#2687 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2679](nesquena/hermes-webui#2679)) — Settings → Preferences gains a `Hide chat suggestions` toggle (config key `hide_empty_state_suggestions`). The empty new-chat screen normally shows three suggestion buttons as first-class tap targets, which causes accidental taps on mobile. Users who don't want the suggestions can hide them via the preference; the toggle persists across sessions and reloads. Default is OFF (suggestions remain visible) so existing users see no change. - **PR [#​2700](nesquena/hermes-webui#2700 by [@​ai-ag2026](https://github.com/ai-ag2026) — Settings → Preferences gains a `Pinned conversations limit` numeric input. Builds on v0.51.96's [#​2614](nesquena/hermes-webui#2614) 3-cap by making the cap configurable (range 1–99, default 3, validated server-side via `_SETTINGS_INT_RANGES`). Backend validates the new cap on read, surfaces an error if a pin attempt would exceed it, and the right-click menu disables the pin item with an explanatory tooltip when the cap is reached. Default-3 keeps existing users on identical behavior. - **PR [#​2696](nesquena/hermes-webui#2696 by [@​Michaelyklam](https://github.com/Michaelyklam) — RuntimeAdapter slice 4c — feature-flagged runner backend selection. The existing `HERMES_WEBUI_RUNTIME_ADAPTER` env var gains a new `runner-local` mode that wires up a `RunnerRuntimeAdapter` factory and adds a restart/reattach harness gate before the runner backend is used at the dispatcher. No user-visible change in this slice — unset / `legacy-direct` keeps existing behavior intact, and no production caller wires the new adapter yet. The slice exists so future work can land a sidecar runner without changing the runtime contract for existing users. ##### Fixed - **PR [#​2703](nesquena/hermes-webui#2703 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2691](nesquena/hermes-webui#2691)) — System panel now detects the Hermes Agent version in Docker two-container deployments where the WebUI sees a copied Agent source volume instead of a live git checkout. The new detection cascade reads `VERSION` if present, falls back to the package metadata (`hermes_cli`), and finally to a `.git` describe if either is available, so the System panel reports the right version even when both `VERSION` and `.git` are absent in the copied source. ### [`v0.51.104`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051104--2026-05-21--Release-CB-stage-397--9-PR-batch--i18n-zh-CNzh-TW-cron-status--geist-contrast-skin-polish--tablet-hardware-Enter--stale-Codex-slash-model-state--SSE-reconnect-jitter--cron-run-inline-expansion--inflight-send-race--new-chat-model-provider-sync--virtualized-sidebar-scroll-clamp-resync--transcript-cache-invalidation-on-same-count-content) [Compare Source](nesquena/hermes-webui@v0.51.103...v0.51.104) ##### Fixed - **PR [#​2690](nesquena/hermes-webui#2690 by [@​laiaman](https://github.com/laiaman) — Correct the zh-CN and zh-Hant translations for the `cron_status_active` label so it reads "enabled / scheduled" (`已启用` / `已啟用`) instead of "running" (`运行中` / `活躍中`). The English source is "active" (enabled, scheduled), and the prior Chinese strings conflated it with the separate `cron_status_running` "currently executing" state, making both labels look identical when a job was both scheduled and not currently firing. - **PR [#​2701](nesquena/hermes-webui#2701 by [@​jasonjcwu](https://github.com/jasonjcwu) — Geist-contrast skin composer polish: force `--user-bubble-text` to `#111` in light mode so typed text is black on the light input background; hide the textarea scrollbar to match the rest of the skin; recolor the send button so it reads correctly against the contrast palette. - **PR [#​2706](nesquena/hermes-webui#2706 by [@​dobby-d-elf](https://github.com/dobby-d-elf) — Tablet (iPad-class) devices with an attached hardware keyboard now send on Enter and newline on Shift+Enter, matching desktop behavior. The prior touch-primary check forced Enter→newline on every touch device, but tablets with hardware keyboards have a physical Shift key and should follow the desktop contract. Detection uses `matchMedia('(pointer:coarse)')` + a `window.visualViewport` height-delta probe (>120px shrink = software keyboard open) so an iPad with hardware keyboard (viewport not shrunk) treats Enter as send, while a phone tapping into the composer (soft keyboard shrinks the viewport) keeps Enter as newline. Falls back to the legacy touch behavior when `visualViewport` is unavailable. - **PR [#​2684](nesquena/hermes-webui#2684 by [@​ai-ag2026](https://github.com/ai-ag2026) — Repair stale `openai/...` slash-qualified model IDs when the active/session provider is `openai-codex`. A stale browser/localStorage selection of `openai/gpt-5` against an `openai-codex` provider previously routed the chat to OpenAI directly instead of through Codex. The cross-provider model-switch resolver now detects the mismatch and re-resolves the model to the matching `codex/...` ID before the request goes out. Explicit OpenRouter slash-qualified selections continue to fast-path through unchanged. - **PR [#​2671](nesquena/hermes-webui#2671 by [@​AJV20](https://github.com/AJV20) (closes [#​2629](nesquena/hermes-webui#2629) + [#​2661](nesquena/hermes-webui#2661)) — Session-list SSE reconnects now use bounded jitter/backoff (each retry delay is `base*0.75 + random*(base*0.35)` where `base = min(30000, 5000 * 2^attempt)`, capped at 30s) instead of a fixed 5-second retry, so tabs that all dropped at the same time (server restart, network drop) don't all retry in lockstep. Expanded cron run rows now render the full output inline immediately on click; the truncated preview remains only for collapsed rows, and the full-output fallback no longer drops content when Markdown rendering is unavailable. - **PR [#​2689](nesquena/hermes-webui#2689 by [@​ai-ag2026](https://github.com/ai-ag2026) — Preserve the optimistic in-flight message array across the `/api/chat/start` await window so a fast back-to-back send doesn't clear the user's message before the stream ID arrives. The fix snapshots the inflight entry before the await, recreates it if a sidebar/session refresh pruned it during that window, and skips stale-inflight cleanup for the submitting session until a stream ID is bound. Regression test covers the race. - **PR [#​2674](nesquena/hermes-webui#2674 by [@​AJV20](https://github.com/AJV20) — Resync the new-chat model picker when the server-created session has the same model ID as the current dropdown but a different provider. New conversations now resync to the configured default model provider instead of inheriting a stale persisted picker selection (e.g. `openai/gpt-5` from a previous session). Without this, the dropdown text matched the new session's model, but the provider attribute still pointed at the stale choice. - **PR [#​2688](nesquena/hermes-webui#2688 by [@​ai-ag2026](https://github.com/ai-ag2026) — Resync the virtualized session sidebar after restoring a saved scroll position if the browser clamps or rejects that scroll position. Without this, date-group headers could render without their session rows beneath them until the user manually scrolled or a later refresh recomputed the virtual window. Regression test pins the recompute path. - **PR [#​2692](nesquena/hermes-webui#2692 by [@​ai-ag2026](https://github.com/ai-ag2026) (refs [#​2613](nesquena/hermes-webui#2613)) — Invalidate the transcript render cache on same-count content changes, not just on count changes. The prior cache key was `(message_count, render_window_size)`, which silently reused a cached transcript whenever a same-count edit produced visibly different content (e.g. a tool retry that replaces a single assistant message with corrected text). The new cache signature folds a content hash into the key so any visible change forces a fresh render. Regression test asserts cache-bust on same-count content swap. </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/613
…ource (Docker two-container System panel) (closes nesquena#2691) Closes nesquena#2691 Co-authored-by: Michaelyklam <Michaelyklam@users.noreply.github.com>
…ource (Docker two-container System panel) (closes nesquena#2691) Closes nesquena#2691 Co-authored-by: Michaelyklam <Michaelyklam@users.noreply.github.com>
Thinking Path
VERSIONand.git, so the existing detection path falls through tonot detected.hermes_cli/__init__.py; future gateway health payloads may also expose a version.What Changed
hermes_cli.__version__whenVERSIONandgit describeare unavailable.GATEWAY_HEALTH_URL/HERMES_GATEWAY_HEALTH_URLor the Docker service defaulthttp://hermes-agent:8642./healthor/health/detailedpayloads when present.Why It Matters
This fixes the officially documented two-container setup showing
Agent: not detectedeven when the Agent container is present and reachable, and removes the need for users to hand-write aVERSIONfile after each image update.Closes #2691
Verification
/home/michael/.hermes/hermes-agent/venv/bin/python -m pytest tests/test_update_banner_fixes.py -q— 66 passed/home/michael/.hermes/hermes-agent/venv/bin/python -m py_compile api/updates.py tests/test_update_banner_fixes.pygit diff --checkRisks / Follow-ups
hermes_cli.__version__.Model Used
AI-assisted change with repository inspection, targeted editing, and shell-based test verification.