Commit Graph

581 Commits

Author SHA1 Message Date
nesquena-hermes
76e602af25 feat: remove bubble_layout setting end-to-end (#777)
Removes the bubble_layout toggle from Settings, all persistence, CSS, i18n strings, and the UI docs demo. The CSS was already effectively dead. Users with a saved bubble_layout value in settings.json get a clean migration via _SETTINGS_LEGACY_DROP_KEYS.

Credit: @aronprins (PR #760 / #777)

Co-authored-by: aronprins <aronprins@users.noreply.github.com>
2026-04-20 22:34:45 +00:00
nesquena-hermes
63f9b719bb fix(config): use Hermes config.yaml as single source of default model (#773)
Removes split-brain where WebUI Settings persisted default_model separately from Hermes runtime config.yaml. New POST /api/default-model endpoint writes to config.yaml. Existing saved values migrated on first load.

Fixes #761

Co-authored-by: aronprins <aronprins@users.noreply.github.com>
2026-04-20 22:12:01 +00:00
nesquena-hermes
f35ac3a727 fix(ui): streamline slash sub-argument autocomplete (#771)
Adds sub-argument suggestions for /model, /personality, /reasoning slash commands. /reasoning is now discoverable from the first slash. Keyboard navigation pre-selects the first item. Fixes bug where no-arg commands (/clear, /new, /stop, etc.) would loop the dropdown on selection.

Fixes #632

Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
2026-04-20 22:04:28 +00:00
Frank Song
0dd5d6f21c feat(ui): add sidebar density mode to session list (#764)
Adds compact/detailed toggle for the session list sidebar. Compact is the default (no behavior change for existing users). Detailed mode shows message count and model; profile names only appear when mixing sessions across profiles.

Fixes #673

Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
2026-04-20 19:43:40 +00:00
nesquena-hermes
a8979f74d5 fix(ui): dark-mode user bubbles use subtle tint + thinking card collapsible — v0.50.111 (#759)
## Summary

Rebased on behalf of @aronprins from fork branch `codex/dark-user-bubbles`. Two asset-only commits (PR screenshot add/remove) were dropped; the two code commits are applied cleanly on top of current master (v0.50.110).

### What changed

**Dark-mode user bubbles** (`static/style.css`):
- `:root.dark` now overrides `--user-bubble-bg`/`--user-bubble-border` to `var(--accent-bg-strong)` (a 15% opacity tint) — keeps the bubble visually subdued in dark skins instead of a glaring bright accent fill
- Removes 6 per-skin `--user-bubble-text` hacks (ares, mono, slate, poseidon, sisyphus, charizard); text falls back to `var(--text)` which is already correct in dark mode
- Adds `--user-bubble-placeholder` token; edit-area box-shadow now uses `--focus-ring` instead of hardcoded `rgba(255,255,255,.15)`

**Thinking card collapsibility** (`static/ui.js` + `static/style.css`):
- `_thinkingMarkup()` now includes `onclick` toggle and chevron affordance, matching the compression reference card pattern
- `.thinking-card-header` gets `display:flex; gap:8px` for proper icon/label/chevron alignment

**Tests**: 2 new in `test_bugbatch_apr2026.py` (dark bubble token contract + no-per-skin-hack assertion), 2 updated in `test_ui_card_animation.py` (flex header layout + onclick pattern).

1520 passed. QA 20/20. Browser verified: dark mode bubble uses subtle tint, thinking card toggles correctly.

(credit: @aronprins)
2026-04-20 01:12:45 -07:00
nesquena-hermes
711d8bb6c0 fix(ui): hover-only footer chrome with timestamps for both user and assistant — v0.50.110 (fixes #680) (#758)
Squash merge of PR #717 — rebased on behalf of @franksong2702.

## What it does

Fixes #680. Footer chrome (timestamps, copy, edit, regenerate) is now hover-only for both user and assistant message rows, consistent throughout the conversation. The last assistant turn keeps cumulative usage visible at rest; timestamp and actions are revealed inline on hover in the same row.

Key changes:
- `static/ui.js`: new `_formatMessageFooterTimestamp()` (local timezone, cross-day fuller format); `timeHtml` no longer gated to user-only; last assistant usage moved from separate `.msg-usage` div to inline `.msg-usage-inline` span in the footer
- `static/style.css`: `.msg-foot-with-usage` class + rules; assistant footer opacity changed from 0.45 to 0 (hover-only); `:focus-within` alongside `:hover` for keyboard users
- `api/streaming.py`: `_restore_reasoning_metadata()` now preserves `_ts`/`timestamp` for unchanged historical messages
- `tests/test_sprint49.py`: 8 new tests covering rendering contract, hover CSS, timestamp preservation

Tests: 1518 passed. QA: 20/20. Browser verified. Reviewed and approved by @nesquena and @aronprins.
2026-04-20 00:53:19 -07:00
nesquena-hermes
a1c5c395e5 fix(tests): pin _cfg_mtime in _models_with_cfg to prevent ordering-dependent failure — v0.50.109 (fixes #754) (#756)
## Summary

Fixes the ordering-dependent test failure in `test_custom_provider_display_name.py` (issue #754).

**Root cause:** `_models_with_cfg()` patches `config.cfg` then calls `get_available_models()`. That function checks `config.yaml`'s mtime on every call — if it has changed since the last `reload_config()`, it calls `reload_config()` again, which reads from disk and silently overwrites the patch. Any test that writes `config.yaml` (e.g. via `save_settings()`) before this test runs changes the mtime and triggers the reload.

**Fix:** Pin `config._cfg_mtime` to the current `config.yaml` mtime before calling `get_available_models()`, then restore it in the `finally` block. This is the same pattern already used in `test_model_resolver.py` (lines 249, 393).

**Also restores `_cfg_mtime`** in the `finally` block so the patch leaves no side effects on subsequent tests.

## Tests

1510 passed — the previously-flaky test now passes regardless of which tests ran before it.

Closes #754
2026-04-20 00:39:24 -07:00
nesquena-hermes
69570ca77c release: v0.50.102–v0.50.108 batch (code blocks, utf-8, image URLs, deletion warning, PermissionError, Docker docs, kimi-k2.5) (#755)
## Batch release: v0.50.102 – v0.50.108

Seven self-built PRs reviewed and approved by @nesquena, now consolidated into a single release branch.

### Included fixes

| Version | PR | What it fixes |
|---|---|---|
| v0.50.102 | #746 | Code blocks lose newlines when not preceded by blank line (fixes #745) |
| v0.50.103 | #743 | `encoding='utf-8'` on `write_text()` in `api/profiles.py` — Windows `.env` detection (fixes #741) |
| v0.50.104 | #735 | Agent `MEDIA:localhost:*` image URLs rewritten to `document.baseURI` — remote users get working images (fixes #642) |
| v0.50.105 | #736 | Profile deletion warning strengthened: "permanently deleted, cannot be undone" across all 6 locales (fixes #637) |
| v0.50.106 | #738 | Catch `PermissionError` in `_signing_key()` — three-container Docker UID mismatch no longer crashes all HTTP requests |
| v0.50.107 | #737 | Docs: three-container UID/GID alignment guide in README + `HERMES_UID`/`HERMES_GID` forwarded in compose (fixes #645) |
| v0.50.108 | #742 | Add `kimi-k2.5` to Kimi/Moonshot provider model list (fixes #740) |

### Testing
- **pytest**: 1510 passed, 1 warning (1 pre-existing unrelated failure excluded)
- **QA harness**: 20/20 passed (`~/WebUI/scripts/run-browser-tests.sh`)
- **Browser**: layout, slash autocomplete width, edit button, image URL rewrite, profile deletion dialog all verified

All PRs reviewed and approved by @nesquena. Ready to merge and tag **v0.50.108**.
2026-04-20 00:26:55 -07:00
nesquena-hermes
aa767d28d0 fix(renderer): preserve newlines in code blocks during paragraph split (#745) (#746)
Squash merge PR #746: fix(renderer): preserve newlines in code blocks — v0.50.102

All tests pass (1510). Browser QA verified. Reviewed and approved by @nesquena.
2026-04-20 00:04:27 -07:00
nesquena-hermes
78c4f1e425 fix: null/empty session model must not trigger index rebuild — v0.50.101 (#753)
## Summary

Follow-up to #751/#752. Code review identified a case where `_normalize_session_model_in_place` could call `session.save()` (which triggers a full session index rebuild) for sessions with `model: null` or missing model field.

Root cause: `_resolve_compatible_session_model(None)` returns `(default_model, True)` when a default exists — which was interpreted as "changed, needs save." But there's nothing to correct for a session with no model; the default is just a fallback for display purposes, not a cross-provider correction worth persisting.

Fix: capture `original_model` before calling `_resolve_compatible_session_model`. Only call `session.save()` if `original_model` was non-empty and actually changed.

Adds a test asserting `save_calls == []` when `session.model is None`.

No behavior change for sessions with a real model (the primary use case of #751 is unaffected).
2026-04-19 23:44:46 -07:00
nesquena-hermes
81ba420716 fix: custom/unknown model prefixes must not be stripped on provider switch — v0.50.100 (#752)
## Summary

Regression fix for #751.

Models with custom or unrecognized prefixes (e.g. `custom-provider/my-model`, `test/import-model`) were being incorrectly replaced with the active provider default. Root cause: `_normalize_provider_id("custom-provider")` matched the `"custom"` prefix and returned `"custom"`, which ≠ `active_provider` → normalization fired.

Two-part fix:
1. Add `"custom"` and `"openrouter"` to the `model_provider` exclusion set in `_resolve_compatible_session_model` (parallel to the existing `active_provider` guard)
2. Return `""` for unknown prefixes in `_normalize_provider_id` so the `if model_provider` truthiness check safely short-circuits

Adds a regression test covering `custom-provider/`, `test/`, `my-local-llm/`, and `lmstudio-community/` prefixes.

## Tests

1499 passed, 0 failures (was 2 failures before this fix)
2026-04-19 23:27:24 -07:00
nesquena-hermes
7f16a41a31 fix: normalize stale session models after provider switch — v0.50.99 (#751)
## Summary

Rebased-on-behalf of @likawa3b (originally PR #748 — stale base).

Sessions can outlive provider changes. When an old session still points to a model from a previous provider (e.g. `gemini-3.1-pro-preview` after switching the agent to OpenAI Codex), starting a chat hits the wrong backend and fails silently.

This PR adds a lightweight normalization pass:
- `_normalize_provider_id()` maps common prefixes to canonical provider IDs
- `_resolve_compatible_session_model()` checks the session model's provider against `active_provider` and returns the default model if they differ
- `_normalize_session_model_in_place()` is called at GET `/api/session` — corrects and persists stale models once
- Chat start also normalizes via `_resolve_compatible_session_model()` and returns `effective_model` in the response
- `messages.js` applies `effective_model` back to the UI/localStorage/dropdown if set

Closes #748

## Tests

1498 passed (2 pre-existing ordering failures unrelated to this PR; 5 new tests added in `test_provider_mismatch.py`).

**Original author:** @likawa3b
2026-04-19 23:22:26 -07:00
nesquena-hermes
c68420d9aa fix(ui): constrain slash autocomplete width to composer — v0.50.98 (closes #633) (#750)
## Summary

Rebased-on-behalf of @franksong2702 (originally PR #728 — had CHANGELOG conflict after #747 merged).

Moves `#cmdDropdown` from outside `composer-box` to inside it, so the `position:absolute` anchor is scoped to the composer width rather than the full chat panel. CSS updated to use `bottom:calc(100% + 4px)` and `width:auto;max-width:100%` for clean upward positioning.

Closes #633

## Changes
- `static/index.html` — moved `cmd-dropdown` div inside `composer-box`
- `static/style.css` — updated `.cmd-dropdown` positioning (remove `margin-bottom`, use `bottom:calc(100% + 4px)`, add `width:auto;max-width:100%`)
- `tests/test_sprint50.py` — 2 new structural tests verifying DOM position and CSS rules

## Tests
1493 passed, 1 warning (2 new tests added)

**Original author:** @franksong2702
2026-04-19 23:17:00 -07:00
Frank Song
aa78175cca fix(ui): restrict edit to latest user message (#747)
fix(ui): restrict edit to latest user message (#747)

Only the latest user turn shows the pencil/edit affordance. Older user
messages remain read-only (copy + timestamp still work). Avoids the
misleading implication that historical messages can be lightly edited
when the actual action truncates the session and restarts the
conversation from that point.

Closes #744

Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
2026-04-19 23:11:49 -07:00
nesquena-hermes
da1fdca22c docs: fix docker-compose files + add three-container config — v0.50.96 (PR #708)
Fixes gateway port exposure, workspace path expansion, HERMES_WEBUI_STATE_DIR default, and adds three-container reference config with dashboard. All ports localhost-bound by default.
2026-04-19 07:10:05 +00:00
nesquena-hermes
067d96bb30 feat: add full Russian (ru-RU) localization — v0.50.95 (PR #713)
Full Russian locale — 389/389 English keys, Slavic plural forms, native Cyrillic. Rebased from PR #605 with rebase artifacts fixed. Login page Russian added to api/routes.py. Credits: @DrMaks22 (translation), @renheqiang (PR #605 author).

Co-authored-by: DrMaks22 <DrMaks22@users.noreply.github.com>
Co-authored-by: renheqiang <renheqiang@users.noreply.github.com>
2026-04-19 06:47:24 +00:00
nesquena-hermes
e637965388 fix: robust mic toggle + Tailscale MediaRecorder fallback — v0.50.94 (PR #715)
Fixes and extends PR #683 (MatzAgent). recognition.start() is now a real call. _isRecording race guard added with correct reset in all paths. localStorage persistence of fallback flag. Closes #683.

Co-authored-by: MatzAgent <MatzAgent@users.noreply.github.com>
2026-04-19 06:28:14 +00:00
nesquena-hermes
66fbfbaa2b fix: gateway sync race condition + hybrid session data loss — v0.50.93 (PR #714)
Fixes and extends PR #676 (yunyunyunyun-yun). Race guard in sessions.js SSE handler; prefix-equality check in routes.py _handle_session_import_cli. Closes #676.

Co-authored-by: yunyunyunyun-yun <yunyunyunyun-yun@users.noreply.github.com>
2026-04-19 06:18:28 +00:00
nesquena-hermes
877a32f49c fix: XML tool-call leak + workspace empty-state + notification text — v0.50.92 (PR #712)
Strips <function_calls> XML from assistant messages before rendering, adds workspace file panel empty-state messages, and changes notification description from 'tab' to 'app'. 16 new tests. Fixes #702, #703, #704.
2026-04-19 05:40:37 +00:00
nesquena-hermes
0386dc261a feat: slash command parity + skill autocomplete — v0.50.91 (PR #711)
Combines PR #618 (@renheqiang) slash command parity (/retry /undo /stop /title /status /voice) with PR #701 (@franksong2702) skill autocomplete. 1469 tests pass. Closes #460.

Co-authored-by: renheqiang <renheqiang@users.noreply.github.com>
Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
2026-04-19 05:37:44 +00:00
nesquena-hermes
17e965b52f chore: block agent-local files from git (.claude/ CLAUDE.md AGENTS.md etc)
Removes stale webui-mvp AGENTS.md and expands .gitignore to block all agent-local context files from being committed. Fixes .claude/* → .claude/ (directory block).
2026-04-19 05:37:42 +00:00
nesquena-hermes
d3a686a266 fix(compress): prefer persisted reference handoff after completion — v0.50.90 (PR #699 by @franksong2702)
Fixes the /compress reference card showing only a short 3-line summary immediately after compression. Now prefers the persisted compaction message (full handoff) over the raw API summary, matching what is shown after page reload. Closes #695.
2026-04-19 04:29:07 +00:00
nesquena-hermes
3cd38b2b31 chore: add CHANGELOG entries for v0.50.88 and v0.50.89
Adds entries for #672 (model dropdown fix) and #700 (UTF-8 encoding fix). CHANGELOG-only change.
2026-04-19 04:23:38 +00:00
woaijiadanoo
d7071cd424 fix: explicit UTF-8 encoding on all read_text() calls — v0.50.89 (PR #700 by @woaijiadanoo)
Fixes config loading failures on Windows with non-UTF-8 default locales (GBK, Shift_JIS etc). All Path.read_text() calls in api/config.py and api/profiles.py now specify encoding='utf-8'.
2026-04-19 04:22:28 +00:00
nesquena-hermes
e0ad593801 fix(model dropdown): stop injecting default_model into unrelated providers — v0.50.88 (PR #672 by @franksong2702) 2026-04-19 04:18:43 +00:00
Frank Song
75e4f8b201 fix(model dropdown): stop injecting default into unrelated providers 2026-04-19 08:18:24 +08:00
nesquena-hermes
352354790f fix: streaming scroll override, Gemini 3.x models, read-only workspace, two-container UID — v0.50.87 (closes #677 #669 #670 #668)
- #677: renderMessages() and appendThinking() use scrollIfPinned() during stream; scroll threshold 80→150px; floating ↓ scroll-to-bottom button added
- #669: Gemini 3.1 Pro Preview, 3 Flash Preview, 3.1 Flash Lite Preview added to all provider sections; gemini-3.1-flash-lite-preview was the missing ID causing API_KEY_INVALID; GEMINI_API_KEY env var detection added
- #670: docker_init.bash guards chown/write-test with [ -w ]; :ro workspace mounts no longer crash startup
- #668: UID/GID auto-detect probes /home/hermeswebui/.hermes and HERMES_HOME before /workspace; two-container Zeabur/Compose setups inherit correct UID automatically
- 18 new tests; 1441 total passing
2026-04-18 17:09:59 +00:00
nesquena-hermes
5266ee26bd feat(ui): searchable model picker with provider group headers — v0.50.86 (PR #659 by @mmartial)
- Live search input in model dropdown (filter by name or ID)
- Provider group headers preserved in filtered view
- Clear button, Escape-to-close, No models found empty state
- i18n EN/ES/zh-CN strings
- CSS uses var(--accent) consistent with current theme system
- zh-CN double-escape fix included
- Provider headers regression fix included
- 1423 tests pass

Co-authored-by: mmartial <mmartial@users.noreply.github.com>
2026-04-18 16:27:36 +00:00
nesquena-hermes
5c2840e2da fix(onboarding): remove CLI fast path from _provider_oauth_authenticated — fixes 4 test failures
The hermes_cli fast path ignored hermes_home, returning True from real system auth for OAuth providers. Removed — auth now scoped to hermes_home/auth.json only. 1423 passed, 0 failed.
2026-04-18 07:23:16 +00:00
nesquena-hermes
75e6595e06 feat: add MiniMax M2.7 to fallback model list and fix env var detection — PR #650 by @octo-patch
MiniMax M2.7/highspeed added to _FALLBACK_MODELS. MINIMAX_API_KEY and MINIMAX_CN_API_KEY added to env scan tuple so os.environ is checked. 11 tests. Independent review by @nesquena confirmed correct, needed rebase only.
2026-04-18 07:18:20 +00:00
nesquena-hermes
20a5f48a1f fix(config): load provider models from config.yaml in model dropdown — PR #644 by @ccqqlo
Providers in config.yaml with explicit models: list were silently ignored. Fix extends the model-list builder to check cfg.providers[pid].models, covering both dict and list formats. Also includes providers only in config.yaml (not _PROVIDER_MODELS). 5 regression tests added. Independent review by @nesquena.
2026-04-18 07:14:03 +00:00
nesquena-hermes
ad6e76e48e chore: reorder CHANGELOG v0.50.77-v0.50.82 in descending order
Co-authored-by: nesquena-hermes <hermes@nesquena.com>
2026-04-18 07:09:06 +00:00
nesquena-hermes
b49de92893 feat(/compress): manual session compression with focus topic — closes #469 (PR #619 by @franksong2702)
POST /api/session/compress with optional focus_topic. Transcript-inline cards: command, running, complete (collapsible green), reference. /compact alias kept. Fixes: var(--green) undefined color, focus_topic 500-char cap. Independent review by @nesquena (4 passes).
2026-04-18 06:55:04 +00:00
nesquena-hermes
b1aa1cfa4d fix(title): auto-title extraction for tool-heavy first turns — closes #639 (PR #640 by @franksong2702)
The auto-title extractor now uses _looks_invalid_generated_title() to distinguish tool-call preambles from substantive agentic replies. Fixes _is_provisional_title() whitespace normalization. 5 regression tests added. Independent review by @nesquena (a553b2b+a0ca9fe).
2026-04-18 06:52:45 +00:00
nesquena-hermes
8c68ea8823 fix: skill panel auto-open, thinking scroll, nav icon alignment, Safari zoom — closes #643 #638 #636 #630 (PR #647)
Four self-contained CSS/JS fixes: skill click auto-opens workspace panel (ensureWorkspacePreviewVisible before api call), thinking card body scrolls when open (overflow-y:auto), nav tab icons properly centered (display:flex), Safari iOS zoom prevented (textarea 14px->16px). Independent review by @nesquena confirmed all four correct.
2026-04-18 06:50:14 +00:00
nesquena-hermes
ec48c482e2 fix(config): default model empty string — no unavailable OpenAI model for non-OpenAI users — closes #646 (PR #649)
DEFAULT_MODEL now defaults to "" instead of "openai/gpt-5.4-mini". Guards added in model-list builder so empty default does not create blank model entries. Adds 3 tests in test_issue646.py. Independent review by @nesquena.
2026-04-18 06:46:43 +00:00
nesquena-hermes
bded1cf906 fix(streaming): strip Gemma 4 thinking token delimiter in all paths — closes #607
Fixes <|turn|>thinking delimiter (was wrong as <|turn>thinking) in api/streaming.py, static/messages.js, and static/ui.js. Adds 13 regression tests. Independent review by @nesquena.
2026-04-18 06:45:39 +00:00
Aron Prins
7cb5547056 feat(theme): replace color scheme system with light/dark + accent skins (PR #627 by @aronprins)
Independent review by @nesquena confirmed all blockers resolved. Theme×skin two-axis system replaces old monolithic color schemes. Closes #627. Co-Authored-By: aronprins <aronprins@users.noreply.github.com>
2026-04-18 06:37:09 +00:00
nesquena-hermes
f3f23abd4e fix(csp): allow external https images in img-src — closes #608
Co-authored-by: Hermes Agent <agent@hermes>
2026-04-16 23:34:21 -07:00
nesquena-hermes
d6267f4d31 chore: CHANGELOG v0.50.75 + version badge (#620 test isolation fix) (#621)
Co-authored-by: Hermes Agent <agent@hermes>
2026-04-16 23:06:16 -07:00
nesquena-hermes
e7b8ab4d70 fix: harden test server isolation — HERMES_BASE_HOME + strip provider keys + mock _get_active_hermes_home in unit tests (#620)
Fixes the root cause of OPENROUTER_API_KEY being overwritten with test-key-fresh on every pytest run.

Three-layer fix:
1. Unit tests: mock _get_active_hermes_home in TestApplyOnboardingSetupGuard so .env writes land in /tmp, never ~/.hermes
2. Test server subprocess: add HERMES_BASE_HOME=TEST_STATE_DIR to hard-lock profile resolution inside the server process
3. Test server subprocess: strip real provider keys (OPENROUTER_API_KEY etc.) from the inherited env before server starts

Reviewed and approved by @nesquena. 1373 passed, 0 skipped.
2026-04-16 23:03:32 -07:00
nesquena-hermes
79428f93c6 fix: catch OSError from SETTINGS_FILE.exists() — Docker UID-mismatch 500 crash (#614)
Squash-merges PR #614. Fixes Docker 500-on-every-request crash from PermissionError in load_settings() (issue #570 follow-up).

Both SETTINGS_FILE.exists() call sites now catch OSError and fall back to defaults. Reviewer nits addressed: removed unused imports/var in tests, improved log message to say "inaccessible?" instead of "permission denied?". Rebased clean onto v0.50.73. 1373 tests passing, QA harness green.
2026-04-16 20:16:07 -07:00
nesquena-hermes
a2ea15b557 fix: add favicon (SVG + PNG + ICO), fix static MIME types (#613)
Squash-merges PR #613. Adds favicon to the app (was missing entirely — blank tab icon). 1371 tests passing, QA harness green. Review by independent agent (see PR comments). Follow-up commit addresses all three reviewer notes: hoisted _STATIC_MIME to module scope, fixed charset=utf-8 being appended to binary MIME types, confirmed correct MIME types on all three favicon formats.

Co-authored-by: tiansiyuan <tiansiyuan@users.noreply.github.com>
2026-04-16 20:11:02 -07:00
franksong2702
692ba68e42 fix(title): strip markdown labels and skip empty placeholders in auto-title (#611)
Squash-merges PR #611 (@franksong2702). Fixes two edge cases in auto-generated session titles.

1. Strip Markdown labels (`**Session Title:**`, `Title:`) from sanitizer output — these were being persisted verbatim when the LLM emitted them.
2. Skip empty assistant tool-call placeholder messages when extracting the first exchange for title generation — previously the empty row could be latched onto instead of the first real answer.

Also tightens the title prompt to explicitly forbid Markdown, bullets, and label prefixes.

1371 tests passing, QA harness green.

Co-authored-by: Frank Song <franksong2702@gmail.com>
2026-04-16 18:51:00 -07:00
nesquena-hermes
2484409b7a fix: HERMES_WEBUI_DEFAULT_WORKSPACE wins over settings.json; trust DEFAULT_WORKSPACE subtree (#610)
Squash-merges PR #610. Fixes Docker workspace env var override and trust validation (issue #609). 1367 tests passing, QA harness green. Reviewed by independent agent (see PR comments).
2026-04-16 18:09:16 -07:00
nesquena-hermes
b608f8837e Update image sources and attributes in README (#606) 2026-04-16 15:32:40 -07:00
nesquena-hermes
d5bea959a5 chore: CHANGELOG v0.50.70 + version badge (post-merge meta for PR #587 by @aronprins)
Post-merge meta commit for PR #587 by @aronprins. CHANGELOG entry for v0.50.70 + version badge bump. No code changes. 1361 tests passing.
2026-04-16 14:14:55 -07:00
Aron Prins
9a3dc10d93 feat: redesign chat transcript + fix streaming/persistence lifecycle — v0.50.70 (PR #587 by @aronprins)
Redesign chat transcript + fix streaming/persistence lifecycle — v0.50.70

Squash-merges PR #587 by @aronprins (Aron Prins). Full credit to @aronprins for all feature and fix work.

Transcript redesign: unified --msg-rail/--msg-max CSS variables, user turns as tinted cards, thinking cards as bordered panels, error card treatment, day-change separators, composer fade.

Approval/clarify as composer flyouts: cards slide up from behind composer top, overflow:hidden + translateY clip prevents travel visibility, focus({preventScroll:true}).

Streaming lifecycle: DOM order user→thinking→tool cards→response, no mid-stream jump. Live tool cards inserted before [data-live-assistant].

Persistence: reasoning attached before s.save(), _restore_reasoning_metadata on reload, role=tool rows preserved in S.messages, CLI-session tool-result fallback.

Workspace panel FOUC fix: [data-workspace-panel] set at parse time.

Docs: docs/ui-ux/index.html + two-stage-proposal.html.

Maintainer additions (433b867): CHANGELOG v0.50.70, version badge, usage badge loop simplification.

Reviewed and approved by @nesquena (independent review). 1361 tests passing.
2026-04-16 14:04:42 -07:00
nesquena-hermes
25d38a467a fix: Docker UID/GID auto-detect from workspace mount + message count tests — v0.50.69
Fixes #569: docker_init.bash auto-detects WANTED_UID/WANTED_GID from the mounted /workspace UID at Phase 1, before usermod remaps the container user. On macOS, host UIDs start at 501 — the default 1024 caused an empty workspace. Guards against root (0). Fallback 1024 preserved. Closes #579: topbar already correctly filters tool messages; sidebar count removed in #584. Regression tests added. Reviewed and approved by @nesquena. 1347 tests passing.
2026-04-16 12:19:25 -07:00
nesquena-hermes
6c5911a79f fix: light theme dialogs, workspace panel snap, model cache staleness, docker-compose docs — v0.50.68
Fixes four bugs + locks in one existing fix with regression tests.

Closes #594 (light theme dialogs), #576 (workspace panel snap), #585 (stale model list after CLI change), #567 (docker-compose macOS UID docs). Confirms and tests #590 (transcribing spinner already present).

Reviewed and approved by @nesquena. 1340 tests passing.
2026-04-16 11:55:18 -07:00