# Hermes Web UI -- Changelog ## [Unreleased] ### Fixed - **Recurring cron jobs with no next run need attention** — the Tasks panel now distinguishes anomalous recurring jobs (`enabled=false`, `state=completed`, `next_run_at=null`) from ordinary off jobs, shows a warning with recovery actions, and lets users copy diagnostics for scheduler/runtime failures. (`static/panels.js`, `static/style.css`, `static/i18n.js`, `tests/test_cron_needs_attention.py`) - **Legacy `@provider:model` session models** — persisted sessions with an old explicit provider hint (for example `@copilot:gpt-5.5`) now pass through the same stale-model compatibility recovery as slash-prefixed session models, so they can continue after the active provider changes. (`api/routes.py`) - **Docker Hindsight memory provider dependency** — Docker startup now ensures `hindsight-client` is installed in the WebUI container venv, even on fast restarts where `/app/venv/.deps_installed` already exists. This lets two-container WebUI deployments import Hermes Agent's Hindsight memory provider without a manual container-side install. (`docker_init.bash`, `tests/test_issue926_hindsight_docker_dependency.py`) Closes #926. ## v0.50.225 — 2026-04-27 ### Added - **Cron job attention state** — recurring jobs that land in a broken state (`enabled=false`, `state=completed`, `next_run_at=null`) now show an amber "needs attention" badge instead of the misleading "off" badge. Detail panel shows a warning banner with Resume & recalculate, Run once, and Copy diagnostics actions. Korean locale translated. (`static/panels.js`, `static/style.css`, `static/i18n.js`) [#1133 @franksong2702] ### Fixed - **Image attachments: composer tray thumbnails** — pasted/dragged images now show as 56×56 thumbnail chips in the composer instead of paperclip pills. Blob URL revoked on remove. (`static/ui.js`, `static/style.css`) [#1135] - **Image attachments: chat history inline** — uploaded images in sent messages now load correctly via `api/file/raw?session_id=SID&path=FILENAME` instead of the broken `api/media?path=FILENAME` path. Click any image to open a lightbox overlay (dark backdrop, 90vw/90vh, × or Escape to close). (`static/ui.js`, `static/style.css`) [#1135] Closes #1095 - **pytest state isolation** — `conftest.py` now uses direct assignment for `HERMES_WEBUI_STATE_DIR` / `HERMES_HOME` / `HERMES_WEBUI_DEFAULT_WORKSPACE` so tests importing `api.config` in the pytest process cannot inherit the real `~/.hermes/webui` state tree. (`tests/conftest.py`) [#1136 @franksong2702] ## v0.50.223 — 2026-04-26 ### Added - **Drag & drop workspace files into composer** — files and folders in the workspace file tree are now draggable; dropping them into the chat composer inserts an `@path` reference at the cursor with smart spacing. OS file drag-and-drop (attach files) still works as before. (`static/ui.js`, `static/panels.js`) [#1123 @bergeouss] Closes #1097 - **Composer placeholder reflects active profile** — when a named profile is active (not `default`), the composer placeholder and title bar show the profile name (capitalised) instead of the global `bot_name`; falls back to `bot_name`/Hermes for the default profile. (`static/boot.js`, `static/panels.js`) [#1122 @bergeouss] Closes #1116 ### Fixed - **Copy buttons — clipboard-write Permissions-Policy** — added `clipboard-write=(self)` to the `Permissions-Policy` header so Firefox allows `navigator.clipboard.writeText()`. Extracted `_fallbackCopy()` with explicit `focus()` before `select()` and correct visible-but-hidden positioning (no more `-9999px` offscreen failure). (`api/helpers.py`, `static/ui.js`) [#1125 @bergeouss] Closes #1096 - **Model picker shows all configured providers** — `XAI_API_KEY` and `MISTRAL_API_KEY` env vars now map to `x-ai` and `mistralai` respectively. Providers configured in `config.yaml` under `providers:` are also detected and shown in the model picker. (`api/config.py`) [#1126 @bergeouss] Partially closes #604 - **api() retries on stale keep-alive after idle** — after a long idle period, `fetch()` throws a `TypeError` when the TCP connection has been dropped by a NAT or proxy timeout. `api()` in `workspace.js` now retries up to 3 times on `TypeError` only; 4xx/5xx HTTP errors and 401 redirects are not retried. (`static/workspace.js`) [#1121 @bergeouss] Closes #1118 - **Google Fonts allowed in CSP** — Mermaid themes inject `@import url(fonts.googleapis.com)` at render time; the CSP `style-src` and `font-src` directives now include `fonts.googleapis.com` and `fonts.gstatic.com`. (`api/helpers.py`) [#1121 @bergeouss] Closes #1112 ## v0.50.221 — 2026-04-26 ### Fixed - **Custom providers model dropdown** — models dict keys in `custom_providers[].models` now all appear in the dropdown; previously only the singular `model` field was read. (`api/config.py`) [#1111 @bergeouss] Closes #1106 - **Custom providers SSRF false positive** — hostnames from user-configured `custom_providers[].base_url` are now trusted through the SSRF check; local inference servers (llama.cpp, vLLM, TabbyAPI) no longer blocked. (`api/config.py`) [#1113 @bergeouss] Closes #1105 - **Mobile/iPad session navigation** — tap no longer fails on first touch; replaced hover-triggered layout-shift pattern with `onpointerup` + right/middle-click filter + `touch-action:manipulation`. Desktop hover padding restored via `@media (hover:hover)` so mouse users are unaffected. (`static/sessions.js`, `static/style.css`) [#1110 @sheng-di] - **Pasted/dragged images render inline** — image attachments now show as `` with click-to-fullscreen instead of a paperclip badge. Hoisted `_IMAGE_EXTS` to module scope (was causing `ReferenceError` in `renderMessages`); added `avif` support. (`static/ui.js`) [#1109 @bergeouss] Closes #1095 - **Copy buttons on HTTP** — `_copyText()` helper checks `isSecureContext` and falls back to `execCommand('copy')` for plain-HTTP self-hosted installs. Silent failure in `addCopyButtons` fixed with error feedback. All 6 locales get `copy_failed` key. (`static/ui.js`, `static/i18n.js`) [#1107 @bergeouss] Closes #1096 ## v0.50.220 — 2026-04-26 ### Fixed - **Workspace panel collapse priority** — as the right panel narrows, the git badge now disappears first (below 220px), the "Workspace" label second (below 160px), and the icon buttons survive the longest. Previously `.panel-header` used `justify-content:space-between` with no flex-shrink ratios, compressing all three children simultaneously. Fix: declare `.rightpanel` as a `container-type:inline-size` container, replace `space-between` with `gap:6px` + `flex-shrink` ladder (icons=0, label=2, badge=3), and add `@container rightpanel` queries. (`static/style.css`) [#1089] - **Project color dot truncated/invisible on long titles** — the colored project marker on session items was appended inside `.session-title` (`overflow:hidden;text-overflow:ellipsis`), so long titles clipped the dot off entirely. Fix: move dot to a flex sibling in `.session-title-row` between title and timestamp; move `.session-time` from `position:absolute` to `margin-left:auto` in flex flow; reduce desktop rest padding-right from 86px to 8px (no longer reserving space for an absolute timestamp); mobile rest padding-right from 86px to 40px (same fix). (`static/sessions.js`, `static/style.css`) [#1089] ## v0.50.219 — 2026-04-26 ### Fixed - **Project context menu transparent background** — the right-click menu on project chips no longer bleeds the session list through it. `_showProjectContextMenu` was using `background: var(--panel)`, but `--panel` is not defined in this codebase — CSS fell back to `transparent`. Fix: use `var(--surface)` (same opaque variable used by `.session-action-menu` and other floating popovers). (`static/sessions.js`) [#1086] - **Project rename / create input auto-sizing** — the rename and new-project input is no longer fixed at 100px. CSS changed to `min-width:40px; max-width:180px; width:auto`. New `_resizeProjectInput()` helper measures the current value via a hidden span (font properties read from `getComputedStyle`) and updates the pixel width as the user types. Wired into both `_startProjectRename` and `_startProjectCreate`. (`static/sessions.js`, `static/style.css`) [#1086] ## v0.50.218 — 2026-04-26 ### Fixed - **Long URL / unbreakable string overflow** — chat bubble boundaries no longer overflow when a message contains very long URLs, file paths, or base64 data. `overflow-wrap: anywhere` added to `.msg-body` and the user-bubble variant so continuous non-whitespace text wraps at the column edge instead of bleeding into adjacent layout areas. (`static/style.css`) Closes #1080 [#1081] - **Project chip rename now works** — double-clicking a project chip now reliably triggers the rename input. Root cause: `onclick` was calling `renderSessionListFromCache()` which destroyed the chip DOM node before `ondblclick` could fire. Fixed with a 220ms `_clickTimer` delay on `onclick` (same pattern used by session items), so a double-click cancels the single-click and invokes rename instead. (`static/sessions.js`) Closes #1078 [#1082] - **Block-level constructs inside blockquotes** — fenced code blocks, headings, horizontal rules, and ordered lists inside blockquotes now render correctly; `>`-entity-encoded blockquotes from LLM output also render correctly (entity decode moved before the blockquote pre-pass). New pre-pass walks lines fence-aware, strips `>` prefix, recursively renders stripped content with the full pipeline, stashes rendered HTML with `\x00Q` token. (`static/ui.js`, `static/style.css`) [#1083] ### Added - **Project color picker** — right-clicking a project chip now shows a context menu with Rename, a row of color swatches, and Delete. Selecting a swatch updates the project color via `/api/projects/rename`. (`static/sessions.js`) Closes #1078 [#1082] ## v0.50.217 — 2026-04-26 ### Fixed - **`/queue`, `/interrupt`, `/steer` send normally when agent is idle** — typing any of these commands while nothing is running now sends the message as a normal turn instead of showing an error toast. Matches CLI behaviour: commands are mode-sensitive (queue/interrupt/steer when busy, plain send when idle). `/stop` when idle still shows the error — stopping nothing is always an error. (`static/commands.js`) [#1076] ## v0.50.216 — 2026-04-26 ### Added - **Compression chain collapse** — `get_importable_agent_sessions()` now merges linear compression continuation chains into a single sidebar entry, showing the chain tip's activity time and model. The chain root's title and start time are preserved for display; the latest importable segment is used for import. Non-compression parent/child pairs are unchanged. (`api/agent_sessions.py`, `tests/test_gateway_sync.py`) Closes #1012 [#1012 @franksong2702] - **Comprehensive markdown renderer improvements** — blockquote grouping, strikethrough, task lists, CRLF normalisation, nested blockquotes, lists inside blockquotes. See details below. (`static/ui.js`) [#1073] ### Fixed - **Blockquote rendering** — consecutive `> lines` now group into one `
`, blank `>` continuation lines become `
`, bare `>` (no space) handled, `>>` nested blockquotes recurse correctly, lists inside blockquotes render `