diff --git a/CHANGELOG.md b/CHANGELOG.md index 74c6fb52..75219873 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ ### Fixed +- **`.zip` artifacts now open from chat instead of silently failing.** A `MEDIA:/path/to/file.zip` link always failed to open: `.zip` was absent from `MIME_MAP`, so archives resolved to `application/octet-stream`, which the session `MEDIA:` token allow-list rejects. `.zip` now maps to `application/zip` and archives are admitted to the session-token type set. Archives are download-only by construction — the new `_ARCHIVE_TYPES` set is never added to either inline-preview set, so a zip always gets `Content-Disposition: attachment` and can never render inline (verified including `inline=1` and an uppercase `.ZIP` suffix). Path confinement is unchanged: a session token still grants only the exact canonical path an assistant-emitted token referenced, and the state/secret deny guard still runs ahead of the allow decision. Thanks @carlotestor. (#7612) +- **WebUI no longer depends on Hermes Agent compatibility shims that have already passed their removal date.** The Agent's September 2026 decomposition moved several names WebUI imports (`tools.approval`, `tools.mcp_tool`, `hermes_cli.kanban_db`, …) into sibling modules, leaving the old paths resolvable only through PEP 562 `__getattr__` pointers scheduled for deletion on 2026-09-14. Because every affected call site is wrapped in a broad `except`, losing those pointers would not have crashed anything — features would have degraded *silently*: MCP tools missing from turns, the per-turn approval session key never binding, Claude Code credential linking stopping, and the kanban bridge raising `AttributeError`. A new `api/agent_compat.py::agent_attr()` resolves each moved name from the original module's own namespace first (pre-split Agents and test stubs), then the new home module (split Agents, with or without the pointers), then plain attribute access — so WebUI works across all three Agent shapes and stops emitting `HermesPluginCompatWarning`. Thanks @mikemchargue. (#7574) - **Typing in a long session no longer lags.** The composer's `autoResize()` has a fast path meant to skip an expensive measure-and-restore layout on every keystroke, but the guard enabling it compared the composer height against its CSS `min-height` (44px) rather than the height a single row actually settles at (line-height + padding + borders, ~48px), so the skip never fired in a real browser. Every keystroke then forced a full-document synchronous layout whose cost grows with the rendered transcript — on a ~750-message session this was ~168ms of echo latency per key versus ~72ms with the transcript detached. The fast path now compares against the real one-row height (tracking the appearance font size), so single-row typing skips the layout while any append that genuinely needs a taller composer still triggers a full resize. Thanks @KevinMeinon. (#7604) - **Live-follow no longer breaks mid-stream when content above the tail collapses.** A reader pinned flush at the bottom of the transcript was being unpinned whenever a section *above* the tail collapsed — a worklog "Done" fold, a thinking/tool card collapse, an interim-note collapse. The collapse shrinks the transcript height, the browser clamps the scroll position downward and fires a scroll event, and that was misread as the user scrolling away, killing live-follow while a response was still streaming. The scroll listener now only treats an upward scroll as intent when the reader has actually left the bottom, so an above-tail collapse keeps following the stream. Genuine upward scrolls still unpin immediately. Thanks @KevinMeinon. (#7605) - **Sidebar source-filter tabs are now localized.** The WebUI / CLI session-source tabs in the sidebar were hardcoded English (`WebUI sessions (N)` / `CLI sessions (N)`) and assigned straight to `textContent`, so they stayed English under every non-English locale. They now route through `t()` with the standard `{0}` count placeholder and are translated across all shipped locales. Thanks @Yularzhi. (#7602, #7580)