v0.46.0: security, Docker UID/GID, model discovery, i18n, cancel fix
* fix: decode HTML entities before markdown processing + zh/zh-Hant translations (#239) Adds decode() helper in renderMd() to fix double-escaping of HTML entities from LLM output (e.g. <code> becoming &lt;code&gt; instead of rendering). XSS-safe: decode runs before esc(), only 5 entity patterns. Also adds 40+ missing zh (Simplified Chinese) translation keys and a new zh-Hant (Traditional Chinese) locale with 163 keys. Fix applied: removed duplicate settings_label_notifications key in both zh and zh-Hant locales. Fixes #240 * fix: restore custom model list discovery with config api key (#238) get_available_models() now reads api_key from config.yaml before env vars: 1. model.api_key 2. providers.<active>.api_key / providers.custom.api_key 3. env var fallbacks (HERMES_API_KEY, OPENAI_API_KEY, etc.) Also adds OpenAI/Python User-Agent header and a regression test covering authenticated /v1/models discovery. Fixes users with LM Studio / Ollama custom endpoints configured in config.yaml whose model picker silently collapsed to the default model. * feat: Docker UID/GID matching to avoid root-owned .hermes files (#237) Adds docker_init.bash with hermeswebuitoo/hermeswebui user pattern so container files match the host user UID/GID. Prevents .hermes volume mounts from being owned by root when using a non-root host user. Configure via WANTED_UID and WANTED_GID env vars (default 1000/1000). Readme updated with setup instructions. Fix applied: removed duplicate WANTED_GID=1000 line in docker-compose.yml that was overriding the ${GID:-1000} variable expansion. * security: redact credentials from API responses and fix credential file permissions (#243) Adds response-layer credential redaction to three endpoints: - GET /api/session — messages[], tool_calls[], and title - GET /api/session/export — download also redacted - SSE done event — session payload in stream - GET /api/memory — MEMORY.md and USER.md content Adds api/startup.py with fix_credential_permissions() at server startup. Adds 13 tests in tests/test_security_redaction.py. Merged with #237 container detection changes in server.py. * fix: cancel button now interrupts agent and cleans up UI state (#244) Wires agent.interrupt() into cancel_stream() so the backend actually stops tool execution when the user clicks Cancel, rather than only stopping the SSE stream while the agent keeps running. Changes: - api/config.py: adds AGENT_INSTANCES dict (stream_id -> AIAgent) - api/streaming.py: stores agent in AGENT_INSTANCES after creation, checks CANCEL_FLAGS immediately after store (race condition fix), calls agent.interrupt() in cancel_stream(), cleans up in finally block - static/boot.js: removes stale setStatus(cancelling) call - static/messages.js: setBusy(false)/setStatus('') unconditionally on cancel Race condition fix: after storing agent in AGENT_INSTANCES, immediately checks if CANCEL_FLAGS[stream_id] is already set (cancel arrived during agent init) and interrupts before starting. Check is inside the same STREAMS_LOCK acquisition, making it atomic. New test file: tests/test_cancel_interrupt.py with 6 unit tests. * docs: v0.46.0 release notes, bump version, update test counts --------- Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
This commit is contained in:
26
CHANGELOG.md
26
CHANGELOG.md
@@ -6,6 +6,32 @@
|
||||
---
|
||||
|
||||
|
||||
## [v0.46.0] — 2026-04-11
|
||||
|
||||
### Features
|
||||
- **Docker UID/GID matching** (PR #237 by @mmartial): New `docker_init.bash` entrypoint adds `hermeswebui`/`hermeswebuitoo` user pattern so container-created files match the host user UID/GID. Prevents `.hermes` volume mounts from being owned by root. Configure via `WANTED_UID` and `WANTED_GID` env vars (default 1000/1000). README updated with setup instructions.
|
||||
- `Dockerfile` — two-user pattern with passwordless sudo; `/.within_container` marker for in-container detection; starts as `hermeswebuitoo`, switches to correct UID/GID
|
||||
- `docker-compose.yml` — mounts `.hermes` at `/home/hermeswebui/.hermes`; uses `${UID:-1000}/${GID:-1000}` for UID/GID passthrough
|
||||
- `server.py` — detects `/.within_container` and prints a note when binding to 0.0.0.0
|
||||
|
||||
### Security
|
||||
- **Credential redaction in API responses** (PR #243 by @kcclaw001): All API endpoints now redact credentials from responses at the response layer. Session files on disk are unchanged; only the API output is masked.
|
||||
- `api/helpers.py` — `redact_session_data()` and `_redact_value()` apply pattern-based redaction to messages, tool_calls, and title; covers GitHub PATs, OpenAI/Anthropic keys, AWS keys, Slack tokens, HuggingFace tokens, Authorization Bearer headers, and PEM private key blocks
|
||||
- `api/routes.py` — `GET /api/session`, `GET /api/session/export`, `GET /api/memory` all wrapped with redaction
|
||||
- `api/streaming.py` — SSE `done` event payload redacted before broadcast
|
||||
- `api/startup.py` — new `fix_credential_permissions()` called at startup; `chmod 600` on `.env`, `google_token.json`, `auth.json`, `.signing_key` if they have group/other read bits set
|
||||
- `tests/test_security_redaction.py` — 13 new tests covering redaction functions and endpoint structural verification
|
||||
|
||||
### Bug Fixes
|
||||
- **Custom model list discovery with config API key** (PR #238 by @ccqqlo): `get_available_models()` now reads `api_key` from `config.yaml` before env vars when fetching `/v1/models` from custom endpoints (LM Studio, Ollama, etc.). Priority: `model.api_key` → `providers.<active>.api_key` → `providers.custom.api_key` → env vars. Also adds `OpenAI/Python 1.0` User-Agent header. Fixes model picker collapsing to single default model for config-only setups. 1 new regression test.
|
||||
- **HTML entity decode before markdown processing** (PR #239 by @Argonaut790): Adds `decode()` helper in `renderMd()` to fix double-escaping of HTML entities from LLM output (e.g. `<code>` becoming `&lt;code&gt;` instead of rendering). XSS-safe: decode runs before `esc()`, only 5 entity patterns (`<`, `>`, `&`, `"`, `'`).
|
||||
- **Simplified Chinese translations completed** (PR #239 by @Argonaut790): 40+ missing keys added to `zh` locale (123 → 164 keys). New `zh-Hant` (Traditional Chinese) locale with 163 keys.
|
||||
- **Cancel button now interrupts agent execution** (PR #244 by @huangzt): `cancel_stream()` now calls `agent.interrupt()` to stop backend tool execution, not just the SSE stream. `AGENT_INSTANCES` dict (protected by `STREAMS_LOCK`) tracks active agents. Race condition fixed: after storing agent, immediately checks if cancel was already requested. Frontend: removes stale "Cancelling..." status text; `setBusy(false)` always called on cancel. 6 new unit tests in `tests/test_cancel_interrupt.py`.
|
||||
|
||||
**624 tests (up from 604 on v0.45.0 — +20 new tests)**
|
||||
|
||||
---
|
||||
|
||||
## [v0.45.0] — 2026-04-10
|
||||
|
||||
### Features
|
||||
|
||||
Reference in New Issue
Block a user