feat: surface live activity timeline#2847
Closed
AJV20 wants to merge 2 commits into
Closed
Conversation
Collaborator
|
Shipped in v0.51.126 via release/stage-batch8 (#2851). Thanks! |
pull Bot
pushed a commit
to TKaxv-7S/hermes-webui
that referenced
this pull request
May 24, 2026
Squashed from 2 author commits: - d2237e2 feat: surface live activity timeline - eee57ec fix: satisfy activity timeline CI guards Frontend-only telemetry from existing stream events. Replaces empty Thinking… placeholder with observable run status (Waiting on model / Waiting on tool result / Working for …). New CSS, new test file.
pull Bot
pushed a commit
to TKaxv-7S/hermes-webui
that referenced
this pull request
May 24, 2026
Cherry-picked PRs: - nesquena#2819 (humayunak) — kanban markdown full GFM rendering - nesquena#2847 (AJV20) — live activity timeline observable telemetry (squashed from 2)
eleboucher
pushed a commit
to eleboucher/homelab
that referenced
this pull request
May 25, 2026
…➔ 0.51.134) (#650)
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [ghcr.io/nesquena/hermes-webui](https://github.com/nesquena/hermes-webui) | patch | `0.51.124` → `0.51.134` |
---
> ⚠️ **Warning**
>
> Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/567) for more information.
---
### Release Notes
<details>
<summary>nesquena/hermes-webui (ghcr.io/nesquena/hermes-webui)</summary>
### [`v0.51.134`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051134--2026-05-25--Release-DF-stage-batch16--single-PR-Windows-path-defaults)
[Compare Source](https://github.com/nesquena/hermes-webui/compare/v0.51.133...v0.51.134)
##### Fixed
- **PR [#​2897](https://github.com/nesquena/hermes-webui/issues/2897)** by [@​chouzz](https://github.com/chouzz) — On Windows, WebUI default state and config paths now align with Hermes Agent's `%LOCALAPPDATA%\hermes` convention instead of `%USERPROFILE%\.hermes`, so a fresh Windows install finds the same `~/.hermes/config.yaml` / `auth.json` / `webui/` state directory that the Hermes Agent created. POSIX behavior is unchanged (`~/.hermes` remains the default). `HERMES_HOME` and `HERMES_WEBUI_STATE_DIR` env overrides take precedence on both platforms. Closes [#​2840](https://github.com/nesquena/hermes-webui/issues/2840).
### [`v0.51.133`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051133--2026-05-25--Release-DE-stage-batch15--6-PR-contributor-batch--aux-task-validation--workspace-artifact-gating--update-apply-guard--Joplin-auth-header--prefill-cache-guard--notes-drawer-i18n)
[Compare Source](https://github.com/nesquena/hermes-webui/compare/v0.51.132...v0.51.133)
##### Fixed
- **PR [#​2891](https://github.com/nesquena/hermes-webui/issues/2891)** by [@​franksong2702](https://github.com/franksong2702) — Auxiliary model settings now reject unknown task slots instead of allowing arbitrary keys under `config.yaml`'s `auxiliary` block. Valid slots and the `__reset__` sentinel continue to work.
- **PR [#​2892](https://github.com/nesquena/hermes-webui/issues/2892)** by [@​franksong2702](https://github.com/franksong2702) — Workspace Artifacts now keeps read-only tool paths out of the "files changed" list by gating structured path extraction to known file-mutation tools.
- **PR [#​2893](https://github.com/nesquena/hermes-webui/issues/2893)** by [@​franksong2702](https://github.com/franksong2702) — Update Now no longer reports success or enters the restart wait flow when no WebUI or Agent update target is selected.
- **PR [#​2895](https://github.com/nesquena/hermes-webui/issues/2895)** by [@​franksong2702](https://github.com/franksong2702) — Cached WebUI agents no longer overwrite `prefill_messages` with an empty list when a later request does not include explicit prefill context.
- **PR [#​2894](https://github.com/nesquena/hermes-webui/issues/2894)** by [@​franksong2702](https://github.com/franksong2702) — Joplin notes drawer API calls now send the Web Clipper token in an `Authorization` header instead of placing it in the request URL query string.
- **PR [#​2896](https://github.com/nesquena/hermes-webui/issues/2896)** by [@​franksong2702](https://github.com/franksong2702) — Third-party notes drawer copy now uses localized strings in the supported non-English locale bundles (it, ja, ru, es, de, zh, zh-Hant, pt, ko, fr, tr) instead of reusing the English defaults.
### [`v0.51.132`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051132--2026-05-24--Release-DD-stage-batch14--4-PR-replayed-context--interrupted-response--shutdown-affordance--passkey-opt-in)
[Compare Source](https://github.com/nesquena/hermes-webui/compare/v0.51.131...v0.51.132)
##### Added
- **PR [#​2859](https://github.com/nesquena/hermes-webui/issues/2859)** by [@​AJV20](https://github.com/AJV20) — Optional passkey/WebAuthn sign-in for password-protected WebUI instances. Authenticated users can register/remove passkeys from Settings -> System, and `/login` shows a passwordless sign-in button only after a passkey exists. Password auth remains the default-off bootstrap and recovery path. **Opt-in default-off behind `HERMES_WEBUI_PASSKEY=1` env var or `webui_passkey_enabled: true` config flag** — when disabled, the UI block hides, all 6 `/api/auth/passkey/*` endpoints return 404, and `is_auth_enabled()` ignores any pre-existing credential file so the auth posture cannot silently flip if the flag is unset later.
- **PR [#​2824](https://github.com/nesquena/hermes-webui/issues/2824)** by [@​gavinssr](https://github.com/gavinssr) — A "Stop server" affordance in Settings → System that gracefully shuts down the local WebUI server. Useful when WebUI was launched via `./ctl.sh start` or the native macOS/Windows app and the user wants to stop it without context-switching to a terminal. Confirmation dialog before the actual shutdown. The `/api/shutdown` route is CSRF-gated and intended for local-loopback use. Originally a title-bar button; relocated to Settings per the project's deep-UX rule (default-hidden for niche destructive actions on always-visible surfaces).
##### Fixed
- **PR [#​2685](https://github.com/nesquena/hermes-webui/issues/2685)** by [@​LumenYoung](https://github.com/LumenYoung) — Prevent replayed context in chat reconciliation and metering. When a WebUI session is recovered (e.g., after a process restart, network drop, or browser reload), the sidebar/`state.db` reconciliation logic walks the sidecar transcript in order and only skips rows that can actually be aligned with the remaining sidecar context. The prior set-membership check was too broad: a legitimate fresh message that happened to share a key with any older repeated short message in the sidecar was mis-classified as already-seen and dropped from the replay, leading to lost context and inconsistent metering. Also caps the per-turn live-tool-prompt token estimate at 12,000 to prevent unbounded growth on bursts of large tool reads before exact provider accounting overrides.
- **PR [#​2739](https://github.com/nesquena/hermes-webui/issues/2739)** by [@​ai-ag2026](https://github.com/ai-ag2026) — Clarify `Response interrupted` recovery markers so they report that the live response stream stopped instead of asserting that the WebUI process restarted. The recovery path now records distinct interruption causes for real process restarts, stream/run split-brain, and lost worker bookkeeping; browser-side SSE transport failures show a separate `Connection interrupted` message, client-side `BrokenPipeError` disconnects no longer get logged as server 500s, and chat/gateway SSE errors emit rate-limited (30 events / 60s / 4KB body cap), sanitized client diagnostics to `/api/client-events/log` for future root-cause checks. The stream-status `terminal_state` value for lost-worker bookkeeping changes from `stale-from-restart` to `lost-worker-bookkeeping`, matching the new non-restart wording.
##### Notes
- **6,532 pytest passed** sequentially before Opus pass + locale parity fix; full re-run pending after Opus SHOULD-FIX patches.
- **Opus Advisor verdict: SHIP-WITH-SHOULD-FIXES applied.** Zero MUST-FIX. Four SHOULD-FIX items patched inline before tag:
- `/api/auth/status` now gates `passkeys_enabled` / `passwordless_enabled` on the feature flag (fixes broken-affordance trap where passkey login button could show but endpoints returned 404)
- Settings → System Passkeys block now starts `display:none` and only reveals when the server confirms the flag is on AND credentials are accessible
- `/api/settings/save` refuses to set passwordless mode when the passkey feature flag is off (closes the auth-bypass path: user goes passwordless while flag on → admin unsets flag → restart serves WebUI fully unauthenticated)
- CHANGELOG entries added for PR [#​2685](https://github.com/nesquena/hermes-webui/issues/2685) and PR [#​2824](https://github.com/nesquena/hermes-webui/issues/2824) (both originally missing despite functional code changes)
- Deferred to follow-up: per-turn cumulative live-tool-prompt token cap ([#​2685](https://github.com/nesquena/hermes-webui/issues/2685) only added per-call cap; aggregate across many tool calls is a separate refactor).
- **i18n parity**: 7 new shutdown-affordance keys added across all 11 non-en locales (it, ja, ru, es, de, zh, zh-Hant, pt, ko, fr, tr) so locale parity tests pass on first run.
### [`v0.51.131`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051131--2026-05-24--Release-DC-stage-batch13--6-PR-notes-drawer--context-parity--PWA-swipe--locale-polish)
[Compare Source](https://github.com/nesquena/hermes-webui/compare/v0.51.130...v0.51.131)
##### Added
- **PR [#​2868](https://github.com/nesquena/hermes-webui/issues/2868)** by [@​AJV20](https://github.com/AJV20) — Installed/mobile PWA sessions now support an edge swipe from the left side of the screen to open the mobile sidebar drawer, while preserving the existing hamburger and overlay controls. PWA-standalone-gated, edge X<28px, vertical-tolerance 48px, interactive-target exclusion. Defends against accidental triggers from text selection or button taps.
- **PR [#​2527](https://github.com/nesquena/hermes-webui/issues/2527)** by [@​AJV20](https://github.com/AJV20) — Default-off, read-only Third-party notes drawer in the Memory panel. Lists configured note/knowledge MCP sources (Joplin, Obsidian, Notion, llm-wiki) when explicitly enabled via `webui_external_notes_sources` config or `HERMES_WEBUI_EXTERNAL_NOTES_SOURCES=1`. Automatic session recall unchanged. 4 API endpoints (`/api/notes/sources`, `/api/notes/search`, `/api/notes/item`, plus `external_notes_enabled` in memory\_read response) all gated behind the feature flag.
- **PR [#​2547](https://github.com/nesquena/hermes-webui/issues/2547)** by [@​AJV20](https://github.com/AJV20) — SSE stream runtime diagnostics in deep health checks: active stream count, subscriber totals, and offline buffered-event counts for stuck or slow WebUI chat investigations. Non-sensitive payload only.
- **PR [#​2547](https://github.com/nesquena/hermes-webui/issues/2547)** by [@​AJV20](https://github.com/AJV20) — WebUI session prefill parity for bounded JSON files. Browser-originated chat turns can load configured prefill context from `prefill_messages_file`, pass it to Hermes Agent as ephemeral model context, and surface a compact context status event in the chat UI without exposing prefill message bodies. WebUI intentionally does not execute `prefill_messages_script`; executable recall should go through the existing MCP/tool surface. Backward-compatible: degrades gracefully on older agent builds that don't support the `prefill_messages` kwarg.
##### Changed
- **PR [#​2547](https://github.com/nesquena/hermes-webui/issues/2547)** by [@​AJV20](https://github.com/AJV20) — Browser-surface session context is now attached to WebUI agent turns so the agent can distinguish a WebUI chat from messaging-platform transcripts. Context is ephemeral (not saved to history). WebUI progress guidance now preserves the normal Hermes messaging style instead of encouraging extra browser-only status chatter.
##### Fixed
- **PR [#​2865](https://github.com/nesquena/hermes-webui/issues/2865)** by [@​AJV20](https://github.com/AJV20) — New WebUI sessions no longer persist `display.personality` into per-session `Session.personality`; only explicit personality changes remain durable, preventing stale global display defaults from overriding profile-scoped session behavior. Closes [#​2845](https://github.com/nesquena/hermes-webui/issues/2845).
- **PR [#​2882](https://github.com/nesquena/hermes-webui/issues/2882)** by [@​ycj](https://github.com/ycj) — zh-CN (Simplified Chinese) session-time relative labels are now clearer: `${n}分钟前`, `${n}小时前`, `${n}天前`, and the more natural last-week phrasing `上周` instead of the previous bare-unit shorthand. Also corrects a small indentation glitch in the zh-TW (Traditional Chinese) locale. (Cherry-picked onto fresh stage with `Co-authored-by` attribution — original PR was based on stale master.)
- **PR [#​2873](https://github.com/nesquena/hermes-webui/issues/2873)** by [@​Charanis](https://github.com/Charanis) — The WebUI launcher (`ctl.sh` + `bootstrap.py`) now preserves environment variables that have already been resolved by the shell (for example `HERMES_WEBUI_PORT`, `HERMES_WEBUI_STATE_DIR`, `HERMES_WEBUI_HOST`) instead of letting a repo-level `.env` clobber them mid-launch. The `.env` keeps working as a default-only source for unset variables, gated by `HERMES_WEBUI_PRESERVE_ENV=1` set by the launcher subshell.
##### Notes
- **6,503 pytest passed** (sequential mode; the test infrastructure uses a single test server that doesn't support xdist parallelism — known limitation, tracked separately).
- **Opus Advisor verdict: SHIP-AS-IS.** Zero MUST-FIX. Three SHOULD-FIX items filed as follow-up issues (incomplete locale coverage for notes-drawer i18n keys, `_joplin_api_get` URL-token defense-in-depth, prefill `setattr` cache-reuse safety net).
- **[#​2527](https://github.com/nesquena/hermes-webui/issues/2527) i18n coverage**: 10 of the 11 non-en locales currently ship the English string `'Third-party notes'` for the drawer header. Since the drawer is default-off, user impact is zero today; follow-up issue tracks proper translations before any default-on transition.
### [`v0.51.130`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051130--2026-05-24--Release-DB-stage-batch12--3-PR-profile-isolation--boot-precedence--workspace-Artifacts-tab)
[Compare Source](https://github.com/nesquena/hermes-webui/compare/v0.51.129...v0.51.130)
##### Fixed
- **PR [#​2827](https://github.com/nesquena/hermes-webui/issues/2827)** by [@​Koraji95-coder](https://github.com/Koraji95-coder) — Profile state-sync TLS-vs-thread fix (closes [#​2762](https://github.com/nesquena/hermes-webui/issues/2762)). When switching profiles via the WebUI cookie selector, session token-usage and title were being written to the *previously-active* profile's `state.db` instead of the cookie-switched one (sidecar messages + workspace files were already routed correctly; only the `state.db` sidecar sync leaked). Root cause: the cookie middleware sets `_tls.profile = '<cookie>'` on the HTTP request thread, but the daemon thread spawned in `_run_agent_streaming` doesn't inherit that TLS. When the streaming worker calls `sync_session_usage`, `_get_state_db → get_active_hermes_home → get_active_profile_name` finds no TLS profile, falls through to `_active_profile` (the process default), and opens the wrong DB. Fix plumbs the session's own `profile` field through `sync_session_usage(..., profile=...)` and `_get_state_db(profile=...)` rather than leaning on TLS that doesn't exist on the worker thread. Keeps the existing TLS path for callers that don't pass `profile=` explicitly, so external integrations don't regress. Also adds defensive `_validate_profile_name` rejecting `../etc`, leading-dash, whitespace, and over-long names (prevents path traversal via cookie tampering). Adds 11 regression tests covering explicit-profile honors, multi-thread profile preservation, unknown-profile-name fallback path, invalid-name refusal, and legacy-call-shape compatibility.
- **PR [#​2726](https://github.com/nesquena/hermes-webui/issues/2726)** by [@​starship-s](https://github.com/starship-s) — Boot model-default precedence follow-up (refines [#​2709](https://github.com/nesquena/hermes-webui/issues/2709)). The original v0.51.105 fix correctly preferred the profile/server default on fresh boot, but the implementation had two over-broad side effects flagged in post-merge review: (1) boot unconditionally cleared the persisted browser model state, even on restored sessions where that state should remain authoritative, and (2) `populateModelDropdown()` reapplied the default on every repopulate when no session model was present, which clobbered the in-page selection during ordinary dropdown refreshes. Fix is to gate the default-reapply behind an opt-in `{preferProfileDefaultOnFreshBoot: true}` parameter so boot keeps profile-default precedence, restored sessions keep their session model, and non-boot dropdown refreshes preserve the loaded session's model or the current in-page selection. Browser model state is no longer deleted just because the profile default wins this boot. Expanded the regression test coverage with a Node `select` / DOM shim that exercises the real `populateModelDropdown()` path for boot-default, restored-session, current-selection, and removed-model scenarios (+306 LOC tests).
##### Added
- **PR [#​2673](https://github.com/nesquena/hermes-webui/issues/2673)** by [@​AJV20](https://github.com/AJV20) — Workspace Artifacts tab (closes [#​2655](https://github.com/nesquena/hermes-webui/issues/2655)). New tab in the workspace panel that lists likely files mentioned, edited, or created during the active session. Prioritizes structured tool-call paths (file\_write, edit, patch, etc.), filters dependency/build noise (node\_modules, `__pycache__`, `.git`, lock files), and refreshes while live tool calls arrive. Artifact entries open through the existing workspace file preview flow. The MVP is frontend-scoped — backend ingestion uses the existing tool-call event stream rather than a new persistence path — so the maintainer can evaluate the UX before deciding whether artifact tracking should grow into a backend-backed feature. Refreshes alongside the file tree in `loadDir()` via a `typeof renderSessionArtifacts==='function'` guard so it composes cleanly with [#​2716](https://github.com/nesquena/hermes-webui/issues/2716)'s session stale-guard pattern. Adds `tests/test_issue2655_frontend.py`.
##### Notes
- **In-stage cherry-pick mechanics**: All 3 PRs were on stale-base merge-bases (master had advanced through 3 releases). Used `git apply --3way` of each PR's net delta vs its merge-base onto current stage HEAD, then resolved 2 small JS conflicts manually:
- `static/boot.js` ([#​2726](https://github.com/nesquena/hermes-webui/issues/2726) vs [post-#​2716](https://github.com/post-/hermes-webui/issues/2716) master): kept PR's parameterized `populateModelDropdown({preferProfileDefaultOnFreshBoot:true})` call (the whole point of [#​2726](https://github.com/nesquena/hermes-webui/issues/2726)) on top of master's [#​2716](https://github.com/nesquena/hermes-webui/issues/2716) hydration flow.
- `static/workspace.js` ([#​2673](https://github.com/nesquena/hermes-webui/issues/2673) vs [post-#​2716](https://github.com/post-/hermes-webui/issues/2716) master): kept master's `sessionId`-capture stale-session guard (closure-scoped sessionId check after `await`) AND added PR's `renderSessionArtifacts()` call to refresh the new Artifacts tab when the file tree updates. Wrapped in `typeof === 'function'` guard for defense-in-depth.
- **In-stage test fixes**: Patched 3 brittle source-string assertions to accept both [pre-#​2716](https://github.com/pre-/hermes-webui/issues/2716) and [post-#​2716](https://github.com/post-/hermes-webui/issues/2716) JS shapes (variable names changed during the cherry-pick, semantics preserved). Patched 1 schema mismatch in `tests/test_issue2762_state_sync_profile_kwarg.py::_read_session` helper — it queried `sessions.session_id` but the real `state.db` schema has `sessions.id` as primary key. Fix is mechanical: `SELECT id AS session_id` + `WHERE id = ?` so the helper queries the actual schema.
- Full pytest: pending re-run on this finalized stage. Touched-tests gate: 41 passed (covering [#​2827](https://github.com/nesquena/hermes-webui/issues/2827) + [#​2726](https://github.com/nesquena/hermes-webui/issues/2726) + [#​2673](https://github.com/nesquena/hermes-webui/issues/2673) surface areas).
- Agent self-verified: profile= kwarg threading on `_get_state_db` + `sync_session_usage`, production call site in `api/streaming.py:5078` passes `profile=getattr(s, 'profile', None)`, `populateModelDropdown` opt-in parameterization present, boot.js calls with `preferProfileDefaultOnFreshBoot:true`, workspace `renderSessionArtifacts()` defined + called.
### [`v0.51.129`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051129--2026-05-24--Release-DA-stage-batch11--4-PR-feature--perf-batch)
[Compare Source](https://github.com/nesquena/hermes-webui/compare/v0.51.128...v0.51.129)
##### Performance
- **PR [#​2836](https://github.com/nesquena/hermes-webui/issues/2836)** by [@​v2psv](https://github.com/v2psv) — HTTP/1.1 keep-alive for WebUI responses. Bumps `Handler.protocol_version` from the HTTP/1.0 default to `HTTP/1.1` so browsers can reuse TCP connections across normal API and static-file requests. Adds explicit `Content-Length` headers to hand-written responses that weren't already using shared `j()` / `t()` helpers. Adds `Content-Length: 0` to empty redirect / range-error responses. Switches SSE-style streaming endpoints from `Connection: keep-alive` to `Connection: close` (keep-alive is only safe when the response body is framed; SSE bodies have no fixed length). Significant first-paint / session-open improvements on high-RTT / VPN / proxied paths — author reports \~47% faster first paint and \~30-40% improvements on panel-load flows on a typical remote-host setup.
**Opus pre-release advisor caught one missing framing site** in the on-the-fly folder ZIP download path (`/api/folder/download`): the body has no known length, doesn't use chunked encoding, and was relying on HTTP/1.0 connection-close-equals-EOF. Under HTTP/1.1 this would have left clients hanging waiting for the next response after the central-directory bytes finished. Patched inline before tag: add `Connection: close` header to mirror the SSE-endpoint pattern. Opus verified this was the ONLY remaining streaming response in the codebase that needed the header — all 12 hand-written response paths + 8 SSE streams + j()/t() helpers + auth flow were already correctly framed by the PR.
##### Added
- **PR [#​2680](https://github.com/nesquena/hermes-webui/issues/2680)** by [@​mccxj](https://github.com/mccxj) — Auxiliary Models settings card in Settings → Preferences. Lets users configure per-task model routing for 9 canonical side-task slots: vision, web extract, compression, session search, approval, MCP tool reasoning, title generation, skills hub, curator. Each slot exposes a provider dropdown + model dropdown plus an "auto (use main model)" / "auto (use provider default)" pair so users can keep aux routing implicit when they don't care. New endpoints: `GET /api/model/auxiliary` returns current assignments; `POST /api/model/set` writes assignments (`scope=auxiliary` for aux slots, `scope=main` for the default chat model) and supports `task="__reset__"` to reset all slots back to auto. 16 new i18n keys added across all 12 locales (en, it, ja, ru, es, de, zh, zh-Hant, pt, ko, fr, tr — Turkish translations added in-stage to cover the sibling-PR collision with v0.51.127's Turkish locale baseline). 24 source-level test assertions covering HTML structure, JS logic, i18n parity, and route registration.
- **PR [#​2842](https://github.com/nesquena/hermes-webui/issues/2842)** by [@​AJV20](https://github.com/AJV20) — PWA polish for installed launches. New `static/pwa-startup.js` is loaded synchronously in `<head>` before the main UI bundle, so the page knows whether it's running standalone / in-browser / on iOS / offline before first paint. Marks `pwa-standalone`, `pwa-browser`, `pwa-ios`, `pwa-offline`, and short-lived `pwa-resumed` classes on `<html>`. Exposes `window.HermesPWA.{isStandalone, syncMode, launchAction, promptInstall}` helpers and captures `beforeinstallprompt` / `appinstalled` early enough that any future install-prompt UI can chain off them. Manifest gains app identity / scope / `display_override` (`window-controls-overlay` → `standalone` → `minimal-ui`) and a "New conversation" PWA App Shortcut. Service worker pre-caches the startup helper, switches navigation and shell-asset fetches to `cache: 'no-store'` before falling back to CacheStorage. Boot path wires `?source=pwa&action=new-chat` to start a fresh chat instead of reopening the last saved session. The viewport meta now sets `maximum-scale=1, user-scalable=no` for native-feel — acknowledged trade-off against WCAG 2.1 1.4.4 (Resize text), intentionally kept for the PWA-installed feel of this user base.
- **PR [#​2794](https://github.com/nesquena/hermes-webui/issues/2794)** by [@​Michaelyklam](https://github.com/Michaelyklam) — Runtime adapter route selection harness. Routes explicit adapter-mode chat starts through `build_runtime_adapter(...)` and keeps `legacy-direct` as the default `/api/chat/start` path. Continues the [#​1925](https://github.com/nesquena/hermes-webui/issues/1925) RFC slice progression: this is slice 4e, the default-off chat-start route-selection seam. Returns a bounded `501 Not Configured` response when `runner-local` is explicitly selected before a supervised runner client exists, instead of silently starting a legacy WebUI-owned run. New `_chat_start_response_from_run_start(...)` helper whitelists legacy-compatible chat-start response fields and keeps adapter-internal `run_id`, `status`, and `active_controls` out of public responses. Updates `docs/rfcs/hermes-run-adapter-contract.md` to mark [#​2744](https://github.com/nesquena/hermes-webui/issues/2744) shipped and define slice 4e.
##### Notes
- Full pytest: **6,467 passed / 6 skipped / 3 xpassed / 8 subtests passed**.
- Opus pre-release advisor reviewed all 7 risk areas (HTTP framing surface completeness, PWA startup ordering, sibling-PR `api/routes.py` interaction, service worker cache invalidation, viewport-meta trade-off, runtime adapter response shape, locale-counter brittleness). Verdict: **1 MUST-FIX patched inline** (folder ZIP `Connection: close` header), **0 inline SHOULD-FIX**, 1 follow-up suggested (`set_auxiliary_model` could validate `task` against `AUX_TASK_SLOTS` whitelist — auth-gated, low severity, filing as follow-up).
- Agent self-verified: protocol\_version bumped, SSE Connection-close + Content-Length plumbing, Auxiliary Models API surface (config + endpoints + frontend), PWA helpers + manifest shortcuts + display\_override, Runtime adapter wiring + whitelisting, i18n parity for all 12 locales on the 16 new aux keys.
- Browser-verified at 1920×1080: Auxiliary Models card renders correctly under Settings → Preferences, 9 task slots with provider/model dropdowns, "Reset all to auto" button, layout consistent with surrounding Settings cards, no clutter or clipping. PWA classes populate on `<html>` and HermesPWA namespace populates with 4 helpers as expected.
- In-stage commits added Turkish translations for [#​2680](https://github.com/nesquena/hermes-webui/issues/2680)'s 16 `settings_aux_*` / `settings_label_auxiliary_models` / `settings_desc_auxiliary_models` keys to close the sibling-collision gap with v0.51.127's Turkish locale ([#​2772](https://github.com/nesquena/hermes-webui/issues/2772)). Bumped `test_auxiliary_models_settings.py::test_all_locales_have_auxiliary_keys` from `count == 11` to `count == 12` (the locale set grew when Turkish landed).
### [`v0.51.128`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051128--2026-05-24--Release-CZ-stage-batch10--2-PR-perf--correctness-batch)
[Compare Source](https://github.com/nesquena/hermes-webui/compare/v0.51.127...v0.51.128)
##### Fixed
- **PR [#​2830](https://github.com/nesquena/hermes-webui/issues/2830)** by [@​franksong2702](https://github.com/franksong2702) — Pin state synchronization between persisted index and in-memory sessions (closes [#​2821](https://github.com/nesquena/hermes-webui/issues/2821)). Three coupled bugs:
- **Bug A (load-bearing):** `/api/session/pin` pre-snapshot used `getattr(session, "pinned", False)` which always returned `False` for dict-backed index rows from `all_sessions()`. With \~55-session profiles and LRU eviction churn, pinned counts routinely under-counted because the persisted snapshot was effectively empty. New `_session_field(session, field, default)` helper resolves both dict-backed and Session-object snapshots correctly.
- **Bug B:** Removed stale client-side `pinLimitReached` short-circuit in the sidebar action menu that could block pin clicks before the server saw them, based on `_allSessions` data that was stale mid-render. Server now enforces the cap; the toast surfaces the 400 response.
- **Bug C recovery:** Pin/unpin failure path (4xx response from `/api/session/pin`) now triggers `renderSessionList()` to refresh `_allSessions` from the server, so the sidebar never gets stuck on stale optimistic state.
Adds `tests/test_issue2821_session_pin_state_sync.py` (70 LOC) covering the `_session_field` helper, the persisted-pinned snapshot, the removed `pinLimitReached` reference, and the failure-catch refresh path. Companion fix to [#​2782](https://github.com/nesquena/hermes-webui/issues/2782) (server-side 404→200 transition for missing CLI-synced sessions) which remains out of scope.
##### Performance
- **PR [#​2716](https://github.com/nesquena/hermes-webui/issues/2716)** by [@​dobby-d-elf](https://github.com/dobby-d-elf) — Six independent perf nudges plus one correctness fix. nesquena-APPROVED on 2026-05-22 after a deep-review iteration; cherry-picked onto post-v0.51.127 master via 3-way apply with sibling-PR composition resolution.
- **Metadata-only `/api/session` correctness fix.** Refactors the prior inline reconciliation into `_metadata_only_message_summary(sid, profile=None)` helper that runs the full `merge_session_messages_append_only()` path. Pre-fix shortcut could over-count stale state.db replay rows that the merge intentionally filters out, producing false "transcript newer than loaded conversation" signals (same bug class as [#​2705](https://github.com/nesquena/hermes-webui/issues/2705) / [#​2686](https://github.com/nesquena/hermes-webui/issues/2686)). The new helper threads `profile=` through to `get_state_db_session_messages` to preserve [#​2827](https://github.com/nesquena/hermes-webui/issues/2827)'s TLS-vs-thread profile fix on background-thread reads.
- **Batched persisted-session checks in sidebar indexing.** One `SESSION_DIR.glob('*.json')` snapshot per call replaces per-row `_index_entry_exists()` filesystem lookups during `all_sessions()` pruning. Fallback to the per-row helper preserved when the glob raises.
- **Deferred render-cache signature.** `cachedRenderSignature` closes over the lookup-time signature so the cache STORE path reuses it without recomputing. `_messageRenderCacheSignature()` continues to include the content hash per [#​2692](https://github.com/nesquena/hermes-webui/issues/2692), preserving the cache-invalidation invariant.
- **Hoisted assistant tool-activity index.** Footer-rendering loop now uses an `O(1)` Set lookup instead of `S.toolCalls.some(...)` per message — \~30× fewer comparisons for a 100-message conversation with 30 tool calls.
- **Workspace stale-session guards.** `loadDir` and `_refreshGitBadge` in `static/workspace.js` capture `sessionId` at call time and check it after each `await` (including the catch path of `_refreshGitBadge` — without it, a late 404 from the previous session would hide the git badge on the current session).
- **Background model-catalog prime.** `_startBootModelDropdown` fires fire-and-forget on boot via `setTimeout(0)` so the live catalog hydrates without blocking. The existing `await` on the saved-session restore path is preserved (re-applies the saved session's model after hydration so the chip never shows the stale static default).
- **Failed hydration retryable.** `window._modelDropdownReady = null; throw e;` lets the next caller refetch instead of being stuck on a permanent failure.
Adds 76 LOC of new tests across `test_session_metadata_fast_path.py`, `test_webui_state_db_reconciliation.py`, `test_session_index.py`, `test_issue1539_provider_removal_dropdown_invalidation.py`, `test_issue1785_workspace_preview_breadcrumb.py`, `test_parallel_session_switch.py`.
##### Notes
- PR [#​2716](https://github.com/nesquena/hermes-webui/issues/2716) had been pending merge since 2026-05-22 due to a rebase blocker against the rapidly-advancing master (10+ intervening releases). Cherry-picked via `git apply --3way` of the PR's net delta vs its original merge-base (`f9302601`); 12 of 14 files applied cleanly. Two files had genuine conflicts requiring resolution: `api/routes.py` (took the PR's helper extraction AND added `profile=` threading to preserve [#​2827](https://github.com/nesquena/hermes-webui/issues/2827)'s fix), and `tests/test_webui_state_db_reconciliation.py` (kept BOTH master's pre-existing `test_api_session_reload_drops_stale_cached_user_tail_after_saved_assistant` AND the PR's new `test_metadata_fast_path_matches_reconciliation_for_restamped_replays` — they pin different invariants).
- Opus pre-release advisor reviewed all 6 risk areas (helper extraction correctness, sibling-PR composition, `Session.load` profile-safety, test coverage, deferred Bug D, stale-line-number cleanup nit). Verdict: **SHIP AS-IS** — no MUST-FIX, no inline SHOULD-FIX. Two follow-up issues to file post-tag (Bug D startup index rebuild perf; multi-profile state.db test for the `profile=` threading invariant).
- Full pytest: **6,434 passed / 6 skipped / 3 xpassed / 8 subtests passed** in 2m43s.
- Agent self-verified the producer→consumer channel for `_metadata_only_message_summary` with unmocked invocation against a real session-load path (per skill rule Trigger A + E for mocked-consumer test patterns).
- Closes: [#​2821](https://github.com/nesquena/hermes-webui/issues/2821) (pin state sync), and `get_state_db_session_summary` dead-code removed ([#​2716](https://github.com/nesquena/hermes-webui/issues/2716)).
### [`v0.51.127`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051127--2026-05-24--Release-CY-stage-batch9--7-PR-low-risk-batch--brick-class-Linux--brick-class-update-apply--composer-wide-screen--Turkish-locale--MCP-toggle--SSE-settlement--Windows-CI)
[Compare Source](https://github.com/nesquena/hermes-webui/compare/v0.51.126...v0.51.127)
##### Fixed
- **PR [#​2854](https://github.com/nesquena/hermes-webui/issues/2854)** by [@​nesquena-hermes](https://github.com/nesquena-hermes) — Embedded terminal opens then immediately closes with `[terminal closed]` on every Linux install past `71d8a8fb`. Root cause: `_terminal_shell_preexec_fn` set `PR_SET_PDEATHSIG=SIGTERM` on the PTY shell so orphans would die when WebUI crashed, but `PR_SET_PDEATHSIG` is **per-thread**, not per-process. WebUI uses `ThreadingHTTPServer`, so each HTTP request runs in its own short-lived worker thread; when the request handler returns and the worker thread exits, the kernel sees the pdeathsig-parent thread has died and SIGTERMs the PTY shell within \~10ms. macOS users were unaffected because `libc.prctl` doesn't exist there. Fix: drop the `preexec_fn` entirely; rely on `atexit.register(close_all_terminals)` for graceful shutdown and explicit `close_terminal` for user-driven close. Adds `tests/test_terminal_process_cleanup.py::test_pty_shell_survives_when_spawning_thread_exits` (real PTY shell spawned via worker thread, asserts shell alive after 500ms grace) plus static-check that `preexec_fn` cannot be re-introduced. Closes [#​2853](https://github.com/nesquena/hermes-webui/issues/2853).
- **PR [#​2855](https://github.com/nesquena/hermes-webui/issues/2855)** by [@​nesquena-hermes](https://github.com/nesquena-hermes) — "Update Now" loops for every user past the latest tag ([#​2846](https://github.com/nesquena/hermes-webui/issues/2846)). After [#​2758](https://github.com/nesquena/hermes-webui/issues/2758) the update check correctly fell through to branch comparison when `HEAD` had moved past the latest `v*` tag, but `_select_apply_compare_ref` still returned `tags[0]` — so `git pull --ff-only v2026.5.16` no-op'd, the server bounced, and the banner reappeared unchanged. `apply_force_update` had the same bug except worse (would `git reset --hard v2026.5.16` and rewind the checkout 254 commits). Fix: extract `_head_is_past_latest_tag(path, current_tag)` and have both check and apply paths consult it. Opus pre-release review caught a "case D" parameter-asymmetry drift (HEAD on older tag + commits + newer tag exists → predicate flipped between the two callsites) and patched the apply-side predicate to use `current_tag` + a `behind == 0` gate, exactly mirroring the check-side rule. Adds `test_select_apply_compare_ref_case_d_older_tag_with_commits_and_newer_tag_exists`. Closes [#​2846](https://github.com/nesquena/hermes-webui/issues/2846).
- **PR [#​2852](https://github.com/nesquena/hermes-webui/issues/2852)** by [@​ai-ag2026](https://github.com/ai-ag2026) — Chat `stream_end` handler now settles from the persisted session when `done` was not received or replayed, instead of leaving the active pane with live `Thinking` / assistant DOM and inflight state projected indefinitely. Reconnect / journal / replay paths can deliver `stream_end` without preceding `done`; the prior code treated `stream_end` as transport-only close. Duplicate / replayed `done` events are also made idempotent before completion sound / final render side effects. Opus pre-release review added a post-await race guard inside `_restoreSettledSession` to catch the case where a late `done` event runs the finalize path while the settlement is awaiting the `/api/session` roundtrip. Adds 4 new regression tests across `tests/test_1694_terminal_cleanup_ownership.py` covering both `stream_end`-without-`done` and duplicate-`done` paths.
- **PR [#​2811](https://github.com/nesquena/hermes-webui/issues/2811)** by [@​Koraji95-coder](https://github.com/Koraji95-coder) — Native-Windows startup E2E workflow now self-tests on PR push (closes the [post-#​2783](https://github.com/post-/hermes-webui/issues/2783) gap where Windows-only regressions like the WOW64 ProgramFiles redirect could only be caught after release). Reworked per maintainer feedback to use a stub `hermes_cli/__init__.py` next to a sibling `hermes-agent/` folder rather than `pip install hermes-agent` (which is not on PyPI). Workflow runs `start.ps1` for 8s and asserts none of its `Write-Error` guards fired (no Python, no agent dir, bad port, missing `hermes_cli`, missing `server.py`). PowerShell syntax + path discovery is the testable surface; the server can't actually boot on a stub. `taskkill` exit-128 swallowed when the stub process is already gone.
##### Changed
- **PR [#​2812](https://github.com/nesquena/hermes-webui/issues/2812)** by [@​Koraji95-coder](https://github.com/Koraji95-coder) — Composer max-width is now responsive on wide displays. Pre-change `.composer-box` had a fixed `max-width: 780px` that pinched footer chips (workspace name, model picker, reasoning chip, context ring) against each other on 1440p+ monitors. Switched to `max-width: clamp(780px, 60vw, 1100px)` — the 780px floor preserves byte-identical layout at 1280px (Aron's laptop reference width); 1440px viewports gain \~84px (864px composer); 1920px viewports gain \~320px (1100px composer cap). Mobile responsive logic untouched. Single-line CSS change in `static/style.css`.
##### Added
- **PR [#​2772](https://github.com/nesquena/hermes-webui/issues/2772)** by [@​vaur94](https://github.com/vaur94) — Complete Turkish (`tr`) locale across `static/i18n.js` (\~1,182 keys matching existing locale coverage). Adds Turkish login page strings in `api/routes.py` `_LOGIN_LOCALE`. Settings → Language now offers **Türkçe**; speech recognition uses `tr-TR`. Stage build absorbed a sibling-PR i18n collision with [#​2776](https://github.com/nesquena/hermes-webui/issues/2776) below (9 missing keys: `mcp_enable_server`, `mcp_disable_server`, `mcp_enabled_toast`, `mcp_disabled_toast`, `mcp_toggle_failed`, `open_in_vscode`, `open_in_vscode_failed`, `settings_label_ignore_agent_updates`, `settings_desc_ignore_agent_updates`) — Turkish translations added in-stage so locale-parity test passes. Closes [#​2537](https://github.com/nesquena/hermes-webui/issues/2537) as superseded (byzuzayli's earlier Turkish PR with narrower scope).
- **PR [#​2776](https://github.com/nesquena/hermes-webui/issues/2776)** by [@​roryford](https://github.com/roryford) — New `PATCH /api/mcp/servers/{name}` endpoint accepts `{"enabled": bool}`, writes `mcp_servers.<name>.enabled` to `config.yaml`, calls `reload_config()`, returns `{"ok": true, "name": "<name>", "enabled": <bool>}`. Each MCP server row in the panel now shows a clickable Enabled/Disabled toggle. Also fixes a pre-existing bug: `_handle_mcp_server_delete` and `_handle_mcp_server_update` were defined at line \~11656 but never wired into the HTTP router — DELETE wired into `handle_delete`, PUT wired via new `handle_put` / `do_PUT` in `server.py`. CORS preflight `Access-Control-Allow-Methods` updated to include `PUT` (Opus pre-release review nit). Adds 5 i18n keys to all 11 locales (en, it, ja, ru, es, de, zh, zh-Hant, pt, ko, fr, tr via in-stage parity fix). 7 new tests covering enable, disable, 404, empty-name, missing-field, response payload, URL-decoded names.
##### Notes
- Two PRs ([#​2854](https://github.com/nesquena/hermes-webui/issues/2854), [#​2855](https://github.com/nesquena/hermes-webui/issues/2855)) are brick-class fixes — every Linux install was unable to use the embedded terminal, and every install past the latest agent tag was stuck in an Update Now loop. They land in the same low-risk batch as cosmetic / locale / CI changes because both fixes are mechanical, well-tested, and the brick-class severity made deferring impossible.
- Opus pre-release advisor reviewed all 5 risk areas (PR\_SET\_PDEATHSIG removal, update apply path symmetry, MCP toggle wiring, composer clamp, stream\_end settlement). 1 MUST-FIX + 3 SHOULD-FIX all addressed inline before tag. Net: +69/-9 across 5 files for the Opus fixes.
- Full pytest: 6,424 passed / 6 skipped / 3 xpassed / 8 subtests passed.
- UX evidence for [#​2812](https://github.com/nesquena/hermes-webui/issues/2812) captured at 1280/1440/1920/mobile (iPhone 14 emulation); Telegram-approved.
- File a follow-up issue for pdeathsig-on-supervisor-thread hardening ([#​2854](https://github.com/nesquena/hermes-webui/issues/2854) deferred Option B) and French-locale `open_in_vscode` parity gap (predates this batch, Opus advisor flagged).
### [`v0.51.126`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051126--2026-05-24--Release-CX-stage-batch8--2-PR-low-risk-batch--kanban-markdown--live-activity-timeline)
[Compare Source](https://github.com/nesquena/hermes-webui/compare/v0.51.125...v0.51.126)
##### Added
- **PR [#​2819](https://github.com/nesquena/hermes-webui/issues/2819)** by [@​humayunak](https://github.com/humayunak) — Kanban task descriptions and comments now render as full GFM Markdown instead of plain-text. `_kanbanRenderMarkdown()` in `static/panels.js` rewrote the line-per-`<p>` wrapper as a block-parsing pipeline supporting headings, code blocks (fenced + indented), ordered/unordered lists, task lists with checkboxes, tables, blockquotes, horizontal rules, and strikethrough. `_kanbanRenderMarkdownInline()` gains `~~strikethrough~~` and tightens the italic regex to avoid mid-identifier `*` matches. CSS adds table borders, code-block background, checkbox styling, blockquote accent, and heading sizing scoped to `.hermes-kanban-md`. Frontend-only, scoped to the kanban panel. 95 existing kanban tests pass.
##### Changed
- **PR [#​2847](https://github.com/nesquena/hermes-webui/issues/2847)** by [@​AJV20](https://github.com/AJV20) — Live chat Activity disclosure now shows observable run telemetry instead of an empty `Thinking…` placeholder when no reasoning text is available (squashed from 2 author commits). New baseline rows surface run-start metadata (model, profile), `Waiting on model` / `Waiting on tool result` / `Working for …` status, tool start/finish in the timeline alongside the existing compact tool cards, and a `No recent activity for …` state after quiet periods. Frontend-only telemetry derived from existing stream events — no new backend event types. Adds `tests/test_live_activity_timeline.py` (4 tests). The compact/calm default Activity disclosure is preserved; it only becomes informative when expanded.
### [`v0.51.125`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051125--2026-05-24--Release-CW-stage-batch7--10-PR-low-risk-batch--UIUX-polish--bug-fixes--diagnostics)
[Compare Source](https://github.com/nesquena/hermes-webui/compare/v0.51.124...v0.51.125)
##### Fixed
- **PR [#​2839](https://github.com/nesquena/hermes-webui/issues/2839)** by [@​tn801534](https://github.com/tn801534) — Kanban worker log endpoint constructed URLs with a double query string (`?board=<slug>?tail=65536`) when a non-default board was active. The frontend was appending `?tail=65536` directly to a URL that already had `?board=...` from `_kanbanBoardQuery()`. Fix: pass `{tail: 65536}` as the `extra` argument to `_kanbanBoardQuery()` so it composes both params into a single valid query string. One-line, narrow scope.
- **PR [#​2832](https://github.com/nesquena/hermes-webui/issues/2832)** by [@​franksong2702](https://github.com/franksong2702) — Malformed HTTP request logging in `server.py` falls back to `"-"` for missing `command` or `path` instead of raising `AttributeError`. Defensive `getattr(self, 'command', None) or '-'` matches the pattern already used for `_req_t0` elsewhere in the handler. Adds `tests/test_issue2775_log_request.py` covering the malformed-request-before-path-assigned case.
- **PR [#​2818](https://github.com/nesquena/hermes-webui/issues/2818)** by [@​humayunak](https://github.com/humayunak) — Approval and clarify cards no longer steal focus from the composer textarea (`#msg`) when the user is mid-type. `showApprovalCard()` and `showClarifyCard()` now guard the `focus()` call on `document.activeElement !== $('msg')`, matching the pattern already used elsewhere for focus-sensitive paths. The clarify card also moves the focus call out of `setTimeout` for snappier UX. Silently dropped keystrokes during streaming are eliminated.
- **PR [#​2826](https://github.com/nesquena/hermes-webui/issues/2826)** by [@​Koraji95-coder](https://github.com/Koraji95-coder) — Composer footer chip wraps no longer overlap at narrow widths (closes [#​2740](https://github.com/nesquena/hermes-webui/issues/2740)). The five chip wraps (`.composer-profile-wrap`, `.composer-ws-wrap`, `.composer-model-wrap`, `.composer-reasoning-wrap`, `.composer-toolsets-wrap`) had `flex: 0 1 auto` + `min-width: 0` so they would compress past their content's natural width when the composer narrowed, causing visual overlap of the profile / workspace / model / reasoning chips. Switched to `flex: 0 0 auto` via a single grouped selector. Each chip now keeps its natural width and the existing `overflow-x: auto` on `.composer-left` handles overflow via horizontal scroll. Default-width layout unchanged; only affects the overflow regime. Mobile-specific rules (already `flex: 0 0 auto`) untouched.
- **PR [#​2829](https://github.com/nesquena/hermes-webui/issues/2829)** by [@​franksong2702](https://github.com/franksong2702) — Workspace Markdown previews fall back to plain text for very large files (>64 KB or >1500 lines) instead of synchronously running the full rich Markdown renderer on the browser main thread, which could lock up the tab for several seconds on multi-megabyte `.md` files. Plain-text preview shows file size + line count in the status line so users know why rich rendering was bypassed; Edit mode still shows raw content as before. Closes [#​2823](https://github.com/nesquena/hermes-webui/issues/2823). Supersedes [#​2828](https://github.com/nesquena/hermes-webui/issues/2828) (same scope, less polished).
- **PR [#​2837](https://github.com/nesquena/hermes-webui/issues/2837)** by [@​franksong2702](https://github.com/franksong2702) — CSRF rejections now distinguish origin/proxy mismatches from expired session tokens, so provider-key removal and other protected requests show actionable diagnostics instead of the generic "Cross-origin request rejected" error. Adds `tests/test_issue2572_csrf_diagnostics.py` covering both failure modes.
- **PR [#​2834](https://github.com/nesquena/hermes-webui/issues/2834)** by [@​franksong2702](https://github.com/franksong2702) — Workspace Markdown `mailto:` and `tel:` links now render as clickable links, and sandboxed HTML preview links open outside the iframe (via injected `<base target="_blank">`) instead of navigating the preview into a browser-blocked page. Adds `tests/test_issue2768_workspace_links.py`.
- **PR [#​2838](https://github.com/nesquena/hermes-webui/issues/2838)** by [@​franksong2702](https://github.com/franksong2702) — Tasks panel surfaces a warning when the Hermes gateway is not configured or not running, so Docker users know scheduled jobs need the gateway daemon to tick while away. The single-container Docker boundary is also clarified in `docs/docker.md`. Adds `tests/test_issue2785_gateway_cron_guidance.py`.
##### Added
- **PR [#​2820](https://github.com/nesquena/hermes-webui/issues/2820)** by [@​tangerine-fan](https://github.com/tangerine-fan) — Clarify user choice is now echoed as a visible message in the conversation transcript. After the user responds to a clarify prompt, a synthetic user message with the chosen value is inserted into `S.messages` (marked `_clarify_response: true` so downstream consumers can filter if needed). Previously the choice was only visible in the transient clarify card; now the chat history preserves the decision.
- **PR [#​2843](https://github.com/nesquena/hermes-webui/issues/2843)** by [@​AJV20](https://github.com/AJV20) — New Settings preference "Ignore Agent updates" keeps WebUI update notices, banners, and update actions enabled while suppressing Hermes Agent update checks. Default `False` (current behavior). Useful when running an unreleased agent build or pinning to a specific agent commit.
</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/650
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thinking Path
Thinking…placeholder.What Changed
Thinking…content with status rows likeWaiting on modelorWaiting on tool resultwhen no reasoning text is available.Working for …and surfaces aNo recent activity for …state after quiet periods.Why It Matters
Verification
node --check static/ui.jspython3 -m py_compile tests/test_live_activity_timeline.pypython3 -m pytest tests/test_live_activity_timeline.py -qpython3 -m pytest tests/test_sprint49.py tests/test_streaming_markdown.py -qgit diff --checkRisks / Follow-ups