From d0be66f2d11e2c01696415a7785a2d3283a4e4de Mon Sep 17 00:00:00 2001 From: nesquena-hermes Date: Mon, 29 Jun 2026 01:19:34 +0000 Subject: [PATCH] docs(changelog): composer footer fit-by-overflow (#4657) --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aa29fb8..c8b7c890 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ ### Added +- **The composer footer now fits its controls to the available width instead of relying on fixed breakpoints.** A small fit engine measures the footer's left control group and steps it down through full → icon-only → overflow-menu as space tightens (ResizeObserver + MutationObserver, rAF-debounced), so on mid-width layouts (e.g. tablet / split panes) more controls — the workspace, model, and reasoning chips — stay directly visible as clean chips before anything moves into the overflow menu, while very narrow widths still collapse to a tidy icon row. Verified equal-or-better than the previous fixed-breakpoint layout across wide / desktop / tablet / mobile. Thanks @Paladin173. (#4657) + - **Extensions can now declare browser-local settings that users review, edit, and reset from Settings → Extensions → Installed.** An extension that requests `permissions.storage.owned` can ship a `settings_schema` (typed fields: boolean / string / number / integer / enum, each with a label, default, and optional help text); core sanitizes the schema server-side (drops `sensitive` fields, unsupported types, malformed enum options, duplicate keys, and type-mismatched defaults), injects the accepted schema before extension scripts, and renders generic controls (with Save / Reset / Clear-storage) in the Installed panel. Persistence is **browser-local only** through core-mediated accessors (`window.hermesExt.settings.forExtension(id)` / `.storage.forExtension(id)`) keyed by an enforced `ext::` namespace, so one extension can't read or stomp another's (or core's) keys; the backend never stores extension settings, never exposes a generic write route, and never treats these values as secrets. Every rendered label/value is HTML-escaped. This is the agreed browser-local first pass of the extension-owned settings contract (RFC #5094); state-backed sync and secret-safe storage are intentionally deferred. Documented in `docs/EXTENSIONS.md`. Thanks @rodboev. (#5155, closes #5094) - **Extensions can now register a custom text-to-speech engine** via a new `window.registerHermesTtsEngine({ id, label, synthesize })` API. A registered engine appears in the Settings → TTS Engine dropdown alongside the built-ins (Browser / Edge / ElevenLabs) and is used by **both** playback paths — the hands-free voice-mode auto-read and the per-message "Listen" button. The extension only provides an async `synthesize(text, opts)` that returns audio bytes (ArrayBuffer / Blob); core owns selection, the dropdown option (label inserted via `textContent`, never HTML), and playback through the same `