diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 474d251..8dabfd0 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -31,25 +31,25 @@ This makes the code easy to modify from a terminal or by an agent. start.sh Discovery script: finds agent dir, Python, starts server. api/ __init__.py Package marker - routes.py All GET + POST route handlers (~802 lines) - config.py Shared configuration, constants, global state, model discovery (~453 lines) + routes.py All GET + POST route handlers (~1016 lines) + config.py Shared configuration, constants, global state, model discovery (~640 lines) helpers.py HTTP helpers: j(), bad(), require(), safe_resolve() (~57 lines) models.py Session model + CRUD (~114 lines) workspace.py File ops: list_dir, read_file_content, workspace helpers (~77 lines) upload.py Multipart parser, file upload handler (~77 lines) - streaming.py SSE engine, run_agent integration, cancel support (~218 lines) + streaming.py SSE engine, run_agent integration, cancel support (~222 lines) static/ index.html HTML template (served from disk) style.css All CSS - ui.js DOM helpers, renderMd, tool cards, model dropdown (~671 lines) - workspace.js File tree, preview, file ops (~168 lines) - sessions.js Session CRUD, list rendering, search (~206 lines) - messages.js send(), SSE event handlers, approval, transcript (~310 lines) - panels.js Cron, skills, memory, workspace, todo, switchPanel (~600 lines) - boot.js Event wiring + boot IIFE (~154 lines) + ui.js DOM helpers, renderMd, tool cards, model dropdown (~809 lines) + workspace.js File tree, preview, file ops (~169 lines) + sessions.js Session CRUD, list rendering, search, SVG icons, overlay actions (~532 lines) + messages.js send(), SSE event handlers, approval, transcript (~293 lines) + panels.js Cron, skills, memory, workspace, todo, switchPanel (~771 lines) + boot.js Event wiring + boot IIFE (~175 lines) tests/ conftest.py Isolated test server (port 8788, separate HERMES_HOME) (~240 lines) - test_sprint1-11.py Feature tests per sprint (13 files) + test_sprint1-11.py Feature tests per sprint (13 files, Sprints 1-11) test_regressions.py Permanent regression gate AGENTS.md Instruction file for agents working in this directory. ROADMAP.md Feature and product roadmap document. @@ -151,10 +151,14 @@ Session is a plain Python class (not a dataclass, not SQLAlchemy): session_id hex string, 12 chars (uuid4().hex[:12]) title string, auto-set from first user message workspace absolute path string, resolved at creation - model OpenRouter model ID string (e.g. "anthropic/claude-sonnet-4.6") + model model ID string (e.g. "anthropic/claude-sonnet-4.6") messages list of OpenAI-format message dicts created_at float Unix timestamp updated_at float Unix timestamp, updated on every save() + pinned bool, default False (Sprint 12) + archived bool, default False (Sprint 14) + project_id string or null, FK to projects.json (Sprint 15) + tool_calls list of tool call dicts (Sprint 10) Key methods: path (property) Returns SESSION_DIR/{session_id}.json @@ -326,16 +330,20 @@ read_file_content(workspace, rel): ### 5.1 Structure The frontend is served from static/ as separate files: one HTML template, one CSS file, -and six JavaScript modules (~2,025 lines total). External dependency: Prism.js from CDN -(syntax highlighting, loaded async/deferred). +and six JavaScript modules (~2,750 lines total). External dependencies: Prism.js (syntax +highlighting) and Mermaid.js (diagrams) from CDN, both loaded async/deferred with SRI hashes. Six JS modules loaded in order at end of : - 1. ui.js (~589 lines) DOM helpers, renderMd, tool card rendering, global state - 2. workspace.js (~168 lines) File tree, preview, file operations - 3. sessions.js (~206 lines) Session CRUD, list rendering, search - 4. messages.js (~310 lines) send(), SSE event handlers, approval, transcript - 5. panels.js (~600 lines) Cron, skills, memory, workspace, todo, switchPanel - 6. boot.js (~152 lines) Event wiring + boot IIFE + 1. ui.js (~809 lines) DOM helpers, renderMd, tool card rendering, global state + 2. workspace.js (~169 lines) File tree, preview, file operations + 3. sessions.js (~532 lines) Session CRUD, list rendering, search, SVG icons, overlay actions, project picker + 4. messages.js (~293 lines) send(), SSE event handlers, approval, transcript + 5. panels.js (~771 lines) Cron, skills, memory, workspace, todo, switchPanel + 6. boot.js (~175 lines) Event wiring + boot IIFE + +sessions.js defines an `ICONS` constant at module level with hardcoded SVG strings for all +session action buttons (pin, unpin, folder, archive, unarchive, duplicate, trash). All icons +inherit `currentColor` for consistent theming. Three-panel layout (in static/index.html): @@ -604,26 +612,27 @@ Split server.py into a proper package. Completed across Sprints 4-10. Current structure: / - server.py Entry point + HTTP Handler routing (~704 lines) + server.py Entry point + HTTP Handler dispatch (~76 lines) api/ __init__.py - config.py Configuration, constants, global state (~273 lines) + routes.py All GET + POST route handlers (~1016 lines) + config.py Configuration, constants, global state, model discovery (~640 lines) helpers.py HTTP helpers: j(), bad(), require(), safe_resolve() (~57 lines) - models.py Session model + CRUD (~114 lines) + models.py Session model + CRUD (~132 lines) workspace.py File ops, workspace management (~77 lines) upload.py Multipart parser, file upload handler (~77 lines) - streaming.py SSE engine, run_agent, cancel support (~218 lines) + streaming.py SSE engine, run_agent, cancel support (~222 lines) static/ index.html HTML document (served from disk) - style.css All CSS + style.css All CSS (~560 lines) ui.js, workspace.js, sessions.js, messages.js, panels.js, boot.js tests/ conftest.py Isolated test server on port 8788 - test_sprint1-10.py Feature tests per sprint (12 files) + test_sprint1-11.py Feature tests per sprint (13 files) test_regressions.py Permanent regression gate -Remaining: server.py still has all 49 route handlers in one do_GET/do_POST class. -Sprint 11 plans extracting these to api/routes.py, making server.py a ~50-line shell. +Route extraction to api/routes.py completed in Sprint 11. server.py is now a ~76-line +thin shell: Handler class with structured logging, dispatch to routes, and main(). ### Phase B: Thread-Safe Request Context (Priority: Critical, Effort: Medium) @@ -718,10 +727,10 @@ Optional password gate for non-SSH-tunnel deployments. ### Phase I: Test Infrastructure -- COMPLETE -190 tests across 12 test files + regression gate. Isolated test server on port 8788 +237 tests across 13 test files + regression gate. Isolated test server on port 8788 with separate HERMES_HOME, wiped per run. Production data never touched. -Test files: `test_sprint1.py` through `test_sprint10.py`, `test_regressions.py`. +Test files: `test_sprint1.py` through `test_sprint11.py`, `test_regressions.py`. Fixtures in `conftest.py`: auto-cleanup, cron isolation, workspace reset. Remaining: no CI (GitHub Actions), no frontend tests (browser-based). diff --git a/BUGS.md b/BUGS.md index 62be3ce..b0ed582 100644 --- a/BUGS.md +++ b/BUGS.md @@ -1,18 +1,40 @@ # Bugs Backlog -This file tracks UI bugs and polish items to address in a future sprint. +This file tracks UI bugs and polish items. Fixed items are kept for reference. -## ~~Conversation list title truncation / hover actions~~ — Fixed (Sprint 16) +--- + +## Open Bugs + +*No open bugs at this time.* + +--- + +## Fixed + +### ~~Session title truncation / hover actions~~ -- Fixed (Sprint 16) - **Was:** Action icons reserved ~30px of space even when invisible, truncating titles. - **Fix:** Wrapped all action buttons in a `.session-actions` overlay container with `position:absolute`. Titles now use full available width. Actions appear on hover with a gradient fade from the right edge. -## ~~Folder/project assignment interaction feels sticky~~ — Fixed (Sprint 16) +### ~~Folder/project assignment interaction feels sticky~~ -- Fixed (Sprint 16) - **Was:** Folder icon stayed permanently visible (blue, 60% opacity) when a session belonged to a project. - **Fix:** Replaced `.has-project` persistent button with a colored left border matching the project color. The folder button now only appears in the hover overlay like all other actions. +### ~~Project picker clipping and width~~ -- Fixed (v0.17.3) + +- **Was:** Picker was clipped by `overflow:hidden` on `.session-item` ancestors. With `position:fixed`, no containing block constrained width -- picker stretched to full viewport. +- **Fix:** Dynamic width calculation (min 160px, max 220px). Event listener reordering. Cleanup sequence corrected. (PR #25) + +### ~~NameError crash in model discovery~~ -- Fixed (v0.17.3) + +- **Was:** `logger.debug()` called in custom endpoint `except` block, but `logger` was never imported in `config.py`. Every failed endpoint fetch crashed with `NameError`. +- **Fix:** Replaced with silent `pass` -- unreachable endpoints are expected when no local LLM is configured. (PR #24) + +--- + ## Notes -- Both issues resolved in Sprint 16 (Session Sidebar Visual Polish). -- Icons replaced from inconsistent emoji HTML entities to monochrome SVG line icons. +- Sprint 16 replaced all emoji HTML entities with monochrome SVG line icons (`ICONS` constant in `sessions.js`). +- All session action buttons now use the overlay pattern for consistent UX. diff --git a/CHANGELOG.md b/CHANGELOG.md index 1608cf2..af17689 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,52 @@ --- +## [v0.18] Sprint 16 -- Session Sidebar Visual Polish +*April 2, 2026 | 237 tests* + +### Features +- **SVG action icons.** Replaced all emoji HTML entities (star, folder, box, + duplicate, trash) with monochrome SVG line icons that inherit `currentColor`. + Consistent rendering across macOS, Linux, and Windows. Defined in a top-level + `ICONS` constant in `sessions.js`. +- **Action buttons overlay.** All session action buttons (pin, move, archive, + duplicate, trash) wrapped in a `.session-actions` container with + `position:absolute`. Titles now use full available width instead of being + truncated by invisible buttons. Actions appear on hover with a gradient fade + from the right edge. Overlay auto-hides during inline rename via + `:has(.session-title-input)`. +- **Pin indicator.** Small gold filled-star icon rendered inline before the + title only when pinned. Unpinned sessions get full title width with zero + space reservation. +- **Project border indicator.** Sessions assigned to a project show a colored + left border matching the project color, replacing the old always-visible + blue folder button. + +### Bug Fixes +- **Session title truncation.** Action icons reserved ~30px of space even when + invisible, truncating titles. Fixed by overlay container approach. +- **Folder button felt sticky.** Replaced `.has-project` persistent blue button + with colored left border. Folder button now only appears in hover overlay. + +--- + +## [v0.17.3] Bug Fixes +*April 2, 2026* + +### Bug Fixes +- **NameError crash in model discovery.** `logger.debug()` was called in the + custom endpoint `except` block in `config.py`, but `logger` was never + imported. Every failed custom endpoint fetch crashed with `NameError`, + returning HTTP 500 for `/api/models`. Replaced with silent `pass` since + unreachable endpoints are expected. (PR #24) +- **Project picker clipping and width.** Picker was clipped by + `overflow:hidden` on ancestor elements. Width calculation improved with + dynamic sizing (min 160px, max 220px). Event listener `close` handler + moved after DOM append to fix reference-before-definition. Reordered + `picker.remove()` before `removeEventListener` for correct cleanup. (PR #25) + +--- + ## [v0.17.2] Model Update *April 2, 2026* @@ -509,4 +555,4 @@ Three-panel layout: sessions sidebar, chat area, workspace panel. --- -*Last updated: v0.16.2, April 1, 2026 | Tests: 247* +*Last updated: v0.18, April 2, 2026 | Tests: 237* diff --git a/ROADMAP.md b/ROADMAP.md index 7784eb7..eb98218 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -3,7 +3,7 @@ > Goal: Full 1:1 parity with the Hermes CLI experience via a clean dark web UI. > Everything you can do from the CLI terminal, you can do from this UI. > -> Last updated: Sprint 15 / v0.17.1 (April 2, 2026) +> Last updated: Sprint 16 / v0.18 (April 2, 2026) > Tests: 237 passing > Source: / @@ -32,6 +32,7 @@ | Sprint 13 | Alerts + polish | Cron completion alerts (polling + badge), background error banner, session duplicate, browser tab title | 221 | | Sprint 14 | Visual polish + workspace ops | Mermaid diagrams, message timestamps, file rename, folder create, session tags, session archive | 233 | | Sprint 15 | Session projects + code copy | Session projects/folders, code block copy button, tool card expand/collapse toggle | 237 | +| Sprint 16 | Session sidebar visual polish | SVG action icons, overlay hover actions, pin indicator, project border, custom model discovery, GLM-5.1 | 237 | --- @@ -39,10 +40,10 @@ | Layer | Location | Status | |-------|----------|--------| -| Python server | /server.py (~76 lines) + api/ modules (~1900 lines) | Thin shell + business logic in api/ | +| Python server | /server.py (~76 lines) + api/ modules (~2145 lines) | Thin shell + business logic in api/ | | HTML template | /static/index.html | Served from disk | -| CSS | /static/style.css | Served from disk | -| JavaScript | /static/{ui,workspace,sessions,messages,panels,boot}.js | 6 modules, ~2250 lines total | +| CSS | /static/style.css (~560 lines) | Served from disk | +| JavaScript | /static/{ui,workspace,sessions,messages,panels,boot}.js | 6 modules, ~2750 lines total | | Runtime state | ~/.hermes/webui-mvp/sessions/ | Session JSON files | | Test server | Port 8788, state dir ~/.hermes/webui-mvp-test/ | Isolated, wiped per run | | Production server | Port 8787 | SSH tunnel from Mac | @@ -55,6 +56,7 @@ - [x] Send messages, get SSE-streaming responses - [x] Switch models per session (10 models, grouped by provider) - [x] Multi-provider API support: use any Hermes agent API provider (OpenAI, Anthropic, Google, etc.) directly, not just OpenRouter (Sprint 11) +- [x] Custom endpoint model discovery: auto-detect models from Ollama, LM Studio, and other local LLM servers via base_url (PR #18) - [x] Upload files to workspace (drag-drop, click, clipboard paste) - [x] File tray with remove button - [x] Tool progress shown in activity bar above composer @@ -252,8 +254,8 @@ Add more models. Group by provider. Model info tooltip on hover. Both sidebar and workspace panel are drag-resizable with localStorage persistence. ### Sprint 3.3: Workspace File Actions -- [ ] Rename file (inline, double-click) (Wave 3) -- [ ] Create folder (Wave 3) +- [x] Rename file (inline, double-click) (Sprint 14) +- [x] Create folder (Sprint 14) - [x] Syntax highlighted code preview (Prism.js) ### Sprint 3.4: Conversation Controls @@ -316,3 +318,17 @@ Collapsible sidebar hamburger. Touch-friendly controls. Swipe gestures. ### Sprint 7.4: Performance and Scale Virtual scroll for session/message lists. Incremental message loading. + +--- + +## User Requested Features + +Community-requested enhancements tracked from GitHub issues. + +| Feature | Issue | Description | Complexity | +|---------|-------|-------------|-----------| +| Workspace tree view | #22 | Accordion/tree view for workspace file browser instead of flat list. Lazy-load subdirectories on expand, no backend changes needed. | Medium | +| Docker container | #7 | Docker Compose setup with separate hermes-agent and hermes-webui containers, multi-arch (amd64 + arm64), volume mounts for config. | Medium-High | +| Authentication | #23 | Password gate via `HERMES_WEBUI_PASSWORD` env var, login page, signed cookie. Already planned in Sprint 7.1. | Low-Medium | +| Send key / personalization | #26 | Toggle send key (Enter vs Ctrl/Cmd+Enter) and queue vs interrupt mode as global settings. | Low | +| Mobile responsive UI | #21 | Hamburger menu, slide-out sidebar drawer, touch-friendly controls. Already planned in Sprint 7.3. | Medium-High | diff --git a/SPRINTS.md b/SPRINTS.md index cca673b..1ec22df 100644 --- a/SPRINTS.md +++ b/SPRINTS.md @@ -1,6 +1,6 @@ # Hermes Web UI -- Forward Sprint Plan -> Current state: v0.15 | 221 tests | Daily driver ready +> Current state: v0.18 | 237 tests | Daily driver ready > This document plans the path from here to two targets: > > Target A: 1:1 feature parity with the Hermes CLI (everything you can do from the @@ -14,15 +14,17 @@ --- -## Where we are now (v0.12.1) +## Where we are now (v0.18) -**CLI parity: ~80% complete.** Core agent loop, all tools visible, workspace -file ops, cron/skills/memory CRUD, session management, streaming, cancel -- -all solid. Gaps are configuration, subagent visibility, and runtime controls. +**CLI parity: ~85% complete.** Core agent loop, all tools visible, workspace +file ops, cron/skills/memory CRUD, session management, streaming, cancel, +multi-provider models, custom endpoint discovery -- all solid. Gaps are +subagent visibility, toolset control, and code execution. -**Claude parity: ~55% complete.** Chat, streaming, file browser, -session management, tool cards, syntax highlighting, model switching -- all -present. Gaps are project organization, artifacts, voice, sharing, mobile. +**Claude parity: ~65% complete.** Chat, streaming, file browser, session +management, tool cards, syntax highlighting, model switching, projects, +settings, Mermaid diagrams, mobile layout -- all present. Gaps are +artifacts, voice, reasoning display, sharing. --- @@ -425,7 +427,7 @@ address. | Mermaid diagrams | Done (Sprint 14) | | Projects / folders | Done (Sprint 15) | | Pinned/starred sessions | Done (Sprint 12) | -| Reasoning display | Sprint 16 | +| Reasoning display | Sprint 18 | | Voice input | Sprint 17 | | TTS playback | Sprint 17 | | Notifications | Done (Sprint 13) | @@ -451,4 +453,4 @@ address. *Last updated: April 2, 2026* *Current version: v0.18 | 237 tests* -*Next sprint: Sprint 17 (Slash Commands + Thinking Display)* +*Next sprint: Sprint 17 (Voice + Multimodal Input)*