Files
webui/CHANGELOG.md
Hermes 7019c25021 Hermes Web UI — Sprints 11-14: multi-provider models, settings, session QoL, alerts, polish
Sprint 11 (v0.13): multi-provider model support, streaming smoothness
- Dynamic model dropdown populated from configured API keys (OpenAI, Anthropic,
  Google, DeepSeek, GLM, Kimi, MiniMax, OpenRouter, Nous Portal)
- Scroll pinning during streaming (no forced scroll when user has scrolled up)
- All route handlers extracted to api/routes.py (server.py now ~76 lines)

Sprint 12 (v0.14): settings panel, SSE reconnect, session QoL
- Settings panel (gear icon) -- persist default model and workspace server-side
- SSE auto-reconnect on network blips
- Pin/star sessions to top of sidebar
- Import session from JSON export

Sprint 13 (v0.15): cron alerts, background errors, session duplicate, tab title
- Cron completion alerts: toast per completion + unread badge on Tasks tab
- Background agent error banner when a non-active session errors mid-stream
- Session duplicate button
- Browser tab title reflects active session name

Sprint 14 (v0.16): Mermaid diagrams, file ops, session archive/tags, timestamps
- Mermaid diagram rendering inline (dark theme, lazy CDN load)
- File rename (double-click in file tree) and create folder
- Session archive (hide without deleting, toggle to show)
- Session tags -- #hashtag in title becomes colored chip + click-to-filter
- Message timestamps (HH:MM on hover, full date as tooltip)

Test suite: 224 tests across 14 sprint files + regression gate, 0 failures.
2026-03-31 07:02:47 +00:00

409 lines
19 KiB
Markdown

# Hermes Web UI -- Changelog
> Living document. Updated at the end of every sprint.
> Source: <repo>/
> Repository: https://github.com/<your-username>/hermes-webui
---
## [v0.16] Sprint 14 -- Visual Polish + Workspace Ops + Session Organization
*March 30, 2026 | 233 tests*
### Features
- **Mermaid diagram rendering.** Code blocks tagged `mermaid` render as
diagrams inline. Mermaid.js loaded lazily from CDN on first encounter.
Dark theme with matching colors. Falls back to code block on parse error.
- **Message timestamps.** Subtle HH:MM time next to each role label. Full
date/time on hover tooltip. User messages get `_ts` field when sent.
- **File rename.** Double-click any filename in workspace panel to rename
inline. `POST /api/file/rename` endpoint with path traversal protection.
- **Folder create.** Folder icon button in workspace panel header. Prompt
for name, `POST /api/file/create-dir` endpoint.
- **Session tags.** Add `#tag` to session titles. Tags shown as colored
chips in sidebar. Click a tag to filter the session list.
- **Session archive.** Archive icon on each session. Archived sessions
hidden by default; "Show N archived" toggle at top of list. Backend
`POST /api/session/archive` with `archived` field on Session model.
### Bug Fixes
- **Date grouping fix.** Session list groups (Today/Yesterday/Earlier) now
use `created_at` instead of `updated_at`, preventing sessions from jumping
between groups when auto-titling touches `updated_at`.
---
## [v0.15] Sprint 13 -- Alerts + Session QoL + Polish
*March 30, 2026 | 221 tests*
### Features
- **Cron completion alerts.** New `GET /api/crons/recent` endpoint. UI polls every
30s (pauses when tab is hidden). Toast notification per completion with status icon.
Red badge count on Tasks nav tab, cleared when tab is opened.
- **Background agent error alerts.** When a streaming session errors out and the user
is viewing a different session, a persistent red banner appears above the messages:
"Session X has encountered an error." View button navigates, Dismiss clears.
- **Session duplicate.** Copy icon on each session in the sidebar (visible on hover).
Creates a new session with the same workspace and model, titled "(copy)".
- **Browser tab title.** `document.title` updates to show the active session title
(e.g. "My Task -- Hermes"). Resets to "Hermes" when no session is active.
### Bug Fixes
- Click guard added for duplicate button to prevent accidental session navigation.
---
## [v0.14] Sprint 12 -- Settings Panel + Reliability + Session QoL
*March 30, 2026 | 211 tests*
### Features
- **Settings panel.** Gear icon in topbar opens slide-in overlay. Persist default
model and workspace server-side in `settings.json`. Server reads on startup.
- **SSE auto-reconnect.** When EventSource drops mid-stream, attempts one reconnect
using the same stream_id after 1.5s. Shared `_wireSSE()` function eliminates
handler duplication.
- **Pin sessions.** Star icon on each session. Pinned sessions float to top of sidebar
under a gold "Pinned" header. Persisted in session JSON.
- **Import session from JSON.** Upload button in sidebar. Creates new session with
fresh ID from exported JSON file.
### Bug Fixes
- `models.py` uses `_cfg.DEFAULT_MODEL` module reference so `save_settings()` changes
take effect for `new_session()`.
- Full-scan fallback sort in `all_sessions()` now accounts for pinned sessions.
- `save_settings()` whitelists known keys only, rejecting arbitrary data.
- Escape key closes settings overlay.
---
## [v0.13] Sprint 11 -- Multi-Provider Models + Streaming Smoothness
*March 30, 2026 | 201 tests*
### Features
- **Multi-provider model support.** New `GET /api/models` endpoint discovers configured
providers from `config.yaml`, `auth.json`, and API key environment variables. The model
dropdown now populates dynamically from whatever providers the user has set up (Anthropic,
OpenAI, Google, DeepSeek, Nous Portal, OpenRouter, etc.). Falls back to the hardcoded
OpenRouter list when no providers are detected. Sessions with unlisted models auto-add
them to the dropdown.
- **Smooth scroll pinning.** During streaming, auto-scroll only when the user is near the
bottom of the message area. If the user scrolls up to read earlier content, new tokens
no longer yank them back down. Pinning resumes when they scroll back to the bottom.
### Architecture
- **Routes extracted to api/routes.py.** All 49 GET/POST route handlers moved from server.py
into `api/routes.py` (802 lines). server.py is now a 76-line thin shell: Handler class
with structured logging, dispatch to `handle_get()`/`handle_post()`, and `main()`.
Completes the server split started in Sprint 10.
- **Cleaned up duplicate dead-code routes** that existed in the old `do_GET` (skills/save,
skills/delete, memory/write were duplicated in both GET and POST handlers).
### Bug Fixes
- Regression tests updated for new route module structure.
---
## [v0.12.2] Concurrency + Correctness Sweeps
*March 31, 2026 | 190 tests*
Two systematic audits of all concurrent multi-session scenarios. Each finding
became a regression test so it cannot silently return.
### Sweep 1 (R10-R12)
- **R10: Approval response to wrong session.** `respondApproval()` used
`S.session.session_id` -- whoever you were viewing. If session A triggered
a dangerous command requiring approval and you switched to B then clicked
Allow, the approval went to B's session_id. Agent on A stayed stuck. Fixed:
approval events tag `_approvalSessionId`; `respondApproval()` uses that.
- **R11: Activity bar showed cross-session tool status.** Session A's tool
name appeared in session B's activity bar while you were viewing B. Fixed:
`setStatus()` in the tool SSE handler is now inside the `activeSid` guard.
- **R12: Live tool cards vanished on switch-away and back.** Switching back to
an in-flight session showed empty live cards even though tools had fired.
Fixed: `loadSession()` INFLIGHT branch now restores cards from `S.toolCalls`.
### Sweep 2 (R13-R15)
- **R13: Settled tool cards never rendered after response completes.**
`renderMessages()` has a `!S.busy` guard on tool card rendering. It was
called with `S.busy=true` in the done handler -- tool cards were skipped
every time. Fixed: `S.busy=false` set inline before `renderMessages()`.
- **R14: Wrong model sent for sessions with unlisted model.** `send()` used
`$('modelSelect').value` which could be stale if the session's model isn't
in the dropdown. Fixed: now uses `S.session.model || $('modelSelect').value`.
- **R15: Stale live tool cards in new sessions.** `newSession()` didn't call
`clearLiveToolCards()`. Fixed.
---
## [v0.12.1] Sprint 10 Post-Release Fixes
*March 31, 2026 | 177 tests*
Critical regressions introduced during the server.py split, caught by users and fixed immediately.
- **`uuid` not imported in server.py** -- `chat/start` returned 500 (NameError) on every new message
- **`AIAgent` not imported in api/streaming.py** -- agent thread crashed immediately, SSE returned 404
- **`has_pending` not imported in api/streaming.py** -- NameError during tool approval checks
- **`Session.__init__` missing `tool_calls` param** -- 500 on any session with tool history
- **SSE loop did not break on `cancel` event** -- connection hung after cancel
- **Regression test file added** (`tests/test_regressions.py`): 10 tests, one per introduced bug. These form a permanent regression gate so each class of error can never silently return.
---
## [v0.12] Sprint 10 -- Server Health + Operational Polish
*March 31, 2026 | 167 tests*
### Post-sprint Bug Fixes
- SSE loop now breaks on `cancel` event (was hanging after cancel)
- `setBusy(false)` now always hides the Cancel button
- `S.activeStreamId` properly initialized in the S global state object
- Tool card "Show more" button uses data attributes instead of inline JSON.stringify (XSS/parse safety)
- Version label updated to v0.2
- `Session.__init__` accepts `**kwargs` for forward-compatibility with future JSON fields
- Test cron jobs now isolated via `HERMES_HOME` env var in conftest (no more pollution of real jobs.json)
- `last_workspace` reset after each test in conftest (prevents workspace state bleed between tests)
- Tool cards now grouped per assistant turn instead of piled before last message
- Tool card insertion uses `data-msg-idx` attribute correctly (was `msgIdx`, matching HTML5 dataset API)
### Architecture
- **server.py split into api/ modules.** 1,150 lines -> 673 lines in server.py.
Extracted modules: `api/config.py` (101), `api/helpers.py` (57), `api/models.py` (114),
`api/workspace.py` (77), `api/upload.py` (77), `api/streaming.py` (187).
server.py is now the thin routing shell only. All business logic is independently importable.
### Features
- **Background task cancel.** Red "Cancel" button appears in the activity bar while a task
is running. Calls `GET /api/chat/cancel?stream_id=X`. The agent thread receives a cancel
event, emits a 'cancel' SSE event, and the UI shows "*Task cancelled.*" in the conversation.
Note: a tool call already in progress (e.g. a long terminal command) completes before
the cancel takes effect -- same behavior as CLI Ctrl+C.
- **Cron run history viewer.** Each job in the Tasks panel now has an "All runs" button.
Click to expand a list of up to 20 past runs with timestamps, each collapsible to show
the full output. Click again to hide.
- **Tool card UX polish.** Three improvements:
1. Pulsing blue dot on cards for in-progress tools (distinct from completed cards)
2. Smart snippet truncation at sentence boundaries instead of hard byte cutoff
3. "Show more / Show less" toggle on tool results longer than 220 chars
---
## [v0.11] Sprint 9 -- Codebase Health + Daily Driver Gaps
*March 31, 2026 | 149 tests*
The sprint that closed the last gaps for heavy agentic use.
### Architecture
- **app.js replaced by 6 modules.** `app.js` is deleted. The browser now loads 6 focused files:
`ui.js` (530), `workspace.js` (132), `sessions.js` (189), `messages.js` (221),
`panels.js` (555), `boot.js` (142). The modules are a superset of the original app.js
(two functions -- `loadTodos`, `toolIcon` -- were added directly to the modules after the split).
No single file exceeds 555 lines.
### Features
- **Tool call cards inline.** Every tool Hermes uses now appears as a collapsible card
in the conversation between the user message and the response. Live during streaming,
restored from session history on reload. Shows tool name, preview, args, result snippet.
- **Attachment metadata persists on reload.** File badges on user messages survive page
refresh. Server stores filenames on the user message in session JSON.
- **Todo list panel.** New checkmark tab in the sidebar. Shows current task list parsed
from the most recent todo tool result in message history. Status icons: pending (○),
in-progress (◉), completed (✓), cancelled (✗). Auto-refreshes when panel is active.
- **Model preference persists.** Last-used model saved to localStorage. Restored on page
load. New sessions inherit it automatically.
### Bug Fixes
- Tool card toggle arrow only shown when card has expandable content
- Attachment tagging matches by message content to avoid wrong-turn tagging
- SSE tool event was missing `args` field
- `/api/session` GET was not returning `tool_calls` (history lost on reload)
---
## [v0.10] Sprint 8 -- Daily Driver Finish Line
*March 31, 2026 | 139 tests*
### Features
- **Edit user message + regenerate.** Hover any user bubble, click the pencil icon.
Inline textarea, Enter submits, Escape cancels. Truncates session at that point and re-runs.
- **Regenerate last response.** Retry icon on the last assistant bubble only.
- **Clear conversation.** "Clear" button in topbar. Wipes messages, keeps session slot.
- **Syntax highlighting.** Prism.js via CDN (deferred). Python, JS, bash, JSON, SQL and more.
### Bug Fixes
- Reconnect banner false positive on normal loads (90-second window)
- Session list clipping on short screens
- Favicon 404 console noise (server now returns 204)
- Edit textarea auto-resize on open
- Send button guard while inline edit is active
- Escape closes dropdown, clears search, cancels active edit
- Approval polling not restarted on INFLIGHT session switch-back
- Version label updated to v0.10
### Hotfix: Message Queue + INFLIGHT
- **Message queue.** Sending while busy queues the message with toast + badge.
Drains automatically on completion. Cleared on session switch.
- **Message stays visible on switch-away/back.** loadSession checks INFLIGHT before
server fetch, so sent message and thinking dots persist correctly.
---
## [v0.9] Sprint 7 -- Wave 2 Core: CRUD + Search
*March 31, 2026 | 125 tests*
### Features
- **Cron edit + delete.** Inline edit form per job, save and delete with confirmation.
- **Skill create, edit, delete.** "+ New skill" form in Skills panel. Writes to `~/.hermes/skills/`.
- **Memory inline edit.** "Edit" button opens textarea for MEMORY.md. Saves via `/api/memory/write`.
- **Session content search.** Filter box searches message text (up to 5 messages per session)
in addition to titles. Debounced API call, results appended below title matches.
### Architecture
- `/health` now returns `active_streams` and `uptime_seconds`
- `git init` on `<repo>/`, pushed to GitHub
### Bug Fixes
- Activity bar overlap on short viewports
- Model chip stale after session switch
- Cron output overflow in tasks panel
---
## [v0.8] Sprint 6 -- Polish + Phase E Complete
*March 31, 2026 | 106 tests*
### Architecture
- **Phase E complete.** HTML extracted to `static/index.html`. server.py now pure Python.
Line count progression: 1778 (Sprint 1) → 1042 (Sprint 5) → 903 (Sprint 6).
- **Phase D complete.** All endpoints validated with proper 400/404 responses.
### Features
- **Resizable panels.** Sidebar and workspace panel drag-resizable. Widths persisted to localStorage.
- **Create cron job from UI.** "+ New job" form in Tasks panel with name, schedule, prompt, delivery.
- **Session JSON export.** Downloads full session as JSON via "JSON" button in sidebar footer.
- **Escape from file editor.** Cancels inline file edit without saving.
---
## [v0.7] Sprint 5 -- Phase A Complete + Workspace Management
*March 30, 2026 | 86 tests*
### Architecture
- **Phase A complete.** JS extracted to `static/app.js`. server.py: 1778 → 1042 lines.
- **LRU session cache.** `collections.OrderedDict` with cap of 100, oldest evicted automatically.
- **Session index.** `sessions/_index.json` for O(1) session list loads.
- **Isolated test server.** Port 8788 with own state dir, conftest autouse cleanup.
### Features
- **Workspace management panel.** Add/remove/rename workspaces. Persisted to `workspaces.json`.
- **Topbar workspace quick-switch.** Dropdown chip lists all workspaces, switches on click.
- **New sessions inherit last workspace.** `last_workspace.txt` tracks last used.
- **Copy message to clipboard.** Hover icon on each bubble with checkmark confirmation.
- **Inline file editor.** Preview any file, click Edit to modify, Save writes to disk.
---
## [v0.6] Sprint 4 -- Relocation + Session Power Features
*March 30, 2026 | 68 tests*
### Architecture
- **Source relocated** to `<repo>/` outside the hermes-agent git repo.
Safe from `git pull`, `git reset`, `git stash`. Symlink maintained at `hermes-agent/webui-mvp`.
- **CSS extracted (Phase A start).** All CSS moved to `static/style.css`.
- **Per-session agent lock (Phase B).** Prevents concurrent requests to same session from
corrupting environment variables.
### Features
- **Session rename.** Double-click any title in sidebar to edit inline. Enter saves, Escape cancels.
- **Session search/filter.** Live client-side filter box above session list.
- **File delete.** Hover trash icon on workspace files. Confirm dialog.
- **File create.** "+" button in workspace panel header.
---
## [v0.5] Sprint 3 -- Panel Navigation + Feature Viewers
*March 30, 2026 | 48 tests*
### Features
- **Sidebar panel navigation.** Four tabs: Chat, Tasks, Skills, Memory. Lazy-loads on first open.
- **Tasks panel.** Lists scheduled cron jobs with status badges. Run now, Pause, Resume.
Shows last run output automatically.
- **Skills panel.** All skills grouped by category. Search/filter. Click to preview SKILL.md.
- **Memory panel.** Renders MEMORY.md and USER.md as formatted markdown with timestamps.
### Bug Fixes
- B6: New session inherits current workspace
- B10: Tool events replace thinking dots (not stacked alongside)
- B14: Cmd/Ctrl+K creates new chat from anywhere
---
## [v0.4] Sprint 2 -- Rich File Preview
*March 30, 2026 | 27 tests*
### Features
- **Image preview.** PNG, JPG, GIF, SVG, WEBP displayed inline in workspace panel.
- **Rendered markdown.** `.md` files render as formatted HTML in the preview panel.
- **Table support.** Pipe-delimited markdown tables render as HTML tables.
- **Smart file icons.** Type-appropriate icons by extension in the file tree.
- **Preview path bar with type badge.** Colored badge shows file type.
---
## [v0.3] Sprint 1 -- Bug Fixes + Foundations
*March 30, 2026 | 19 tests*
The first sprint. Established the test suite, fixed critical bugs.
### Bug Fixes
- B1: Approval card now shows pattern keys
- B2: File input accepts valid types only
- B3: Model chip label correct for all 10 models (replaced substring check with dict)
- B4/B5: Reconnect banner on mid-stream reload (localStorage inflight tracking)
- B7: Session titles no longer overflow sidebar
- B9: Empty assistant messages no longer render as blank bubbles
- B11: `/api/session` GET returns 400 (not silent session creation) when ID missing
### Architecture
- Thread lock on SESSIONS dict
- Structured JSON request logging
- 10-model dropdown with 3 provider groups (OpenAI, Anthropic, Other)
- First test suite: 19 HTTP integration tests
---
## [v0.2] UI Polish Pass
*March 30, 2026*
Visual audit via screenshot analysis. No new features -- design refinement only.
- Nav tabs: icon-only with CSS tooltip (5 tabs, no overflow)
- Session list: grouped by Today / Yesterday / Earlier
- Active session: blue left border accent
- Role labels: Title Case, softened color, circular icons
- Code blocks: connected language header with separator
- Send button: gradient + hover lift
- Composer: blue glow ring on focus
- Toast: frosted glass with float animation
- Tool status moved from composer footer to activity bar above composer
- Empty session flood fixed (filter + cleanup endpoint + test autouse)
---
## [v0.1] Initial Build
*March 30, 2026*
Single-file web UI for Hermes. stdlib HTTP server, no external dependencies.
Three-panel layout: sessions sidebar, chat area, workspace panel.
**Core capabilities:**
- Send messages, receive SSE-streamed responses
- Session create/load/delete, auto-title from first message
- File upload with manual multipart parser
- Workspace file tree with directory navigation
- Tool approval card (4 choices: once, session, always, deny)
- INFLIGHT session-switch guard
- 10-model dropdown (OpenAI, Anthropic, Other)
- SSH tunnel access on port 8787
---
*Last updated: Sprint 14, March 31, 2026 | Tests: 224/224*