# Flynn Web UI / Control Dashboard **Date:** 2026-02-07 **Priority:** P7 **Status:** Completed ## Overview Upgrade the existing minimal web UI (`src/gateway/ui/`) into a proper control dashboard with: 1. **Dashboard** — system health, sessions, tools, channels, usage stats 2. **Chat** — real-time streaming chat with token-by-token content, session management 3. **Sessions** — browse/switch/delete sessions, view history 4. **Settings** — view/edit configuration, manage channels, view/edit hooks ## Architecture ### Tech Stack - **No build step** — vanilla HTML/CSS/JS (consistent with existing UI) - **SPA routing** — hash-based (`#/`, `#/chat`, `#/sessions`, `#/settings`) - **WebSocket** — reuse existing JSON-RPC protocol for all data - **CSS** — extend existing `style.css` design system (dark theme, design tokens) - **Marked.js** — CDN for markdown rendering (already used) - **Highlight.js** — CDN for syntax highlighting in code blocks ### File Structure ``` src/gateway/ui/ ├── index.html # SPA shell (nav + router) ├── style.css # Extended design system ├── app.js # SPA router + WebSocket client ├── pages/ │ ├── dashboard.js # Dashboard page │ ├── chat.js # Chat page │ ├── sessions.js # Sessions browser │ └── settings.js # Settings page └── lib/ └── ws-client.js # WebSocket RPC client (shared) ``` ### Backend Changes 1. **`content` streaming events** — `agent.send` should emit `content` events with text chunks as the model generates them. Currently only emits `tool_start`, `tool_end`, `done`. Requires wiring the model client's streaming iterator through the agent. 2. **New gateway methods**: - `sessions.delete` — clear a session's history - `sessions.switch` — switch the connection's active session - `system.channels` — list active channel adapters and their status - `system.usage` — aggregated usage stats (tokens, cost) - `config.channels` — channel-specific configuration view 3. **Static file serving** — extend `static.ts` to serve `.js` files from subdirectories (already supports `.js`, but need to handle nested paths under `pages/` and `lib/`) 4. **Content-type additions** — add `.png`, `.ico`, `.woff2` to `CONTENT_TYPES` in `static.ts` (for future assets). ## Implementation Phases ### Phase 1: Backend enhancements — DONE - Added `sessions.delete` handler (clears session history) - Added `sessions.switch` handler (switches WS connection to different session) - Added `system.channels` handler (lists active channel adapters and status) - Added `system.usage` handler (aggregated usage stats) - Extended `static.ts` with `.mjs`, `.png`, `.ico`, `.woff2` content types - Wired `channelRegistry` into `GatewayServerConfig` (duck-typed interface) - Note: Streaming `content` events deferred — chat page works with `done` event containing full response ### Phase 2: SPA shell + WebSocket client — DONE - Rewrote `index.html` as SPA shell with sidebar nav and hash router - Created `lib/ws-client.js` — promise-based JSON-RPC client with auto-reconnect, event streaming - Created `app.js` — page router with lifecycle (render/teardown), connection status indicator - Extended `style.css` with ~500 lines for SPA layout, sidebar, stats grid, chat, sessions, settings ### Phase 3: Dashboard page — DONE - Health cards (status, version, uptime, connections, sessions, tools) - Channel status cards with colored dots - Usage summary section - Auto-refresh every 10 seconds ### Phase 4: Chat page — DONE - Session selector dropdown with new session button - Load history button - Streaming tool events (collapsible with spinner/checkmark) - Markdown rendering with syntax highlighting (marked.js + highlight.js) - Enter to send, Shift+Enter for newline, auto-resizing textarea - Works with `done` event (full response), ready for future `content` streaming events ### Phase 5: Sessions page — DONE - Session list table with ID, message count, and actions - Click to view full session history - Delete button with confirmation dialog ### Phase 6: Settings page — DONE - Editable hook patterns (confirm/log/silent) with save button via `config.patch` - Tool list table with name and description - Channel status grid - Read-only redacted config JSON viewer ## Files Created/Modified ### New Files - `src/gateway/ui/app.js` — SPA router - `src/gateway/ui/lib/ws-client.js` — WebSocket RPC client - `src/gateway/ui/pages/dashboard.js` — Dashboard page - `src/gateway/ui/pages/chat.js` — Chat page - `src/gateway/ui/pages/sessions.js` — Sessions page - `src/gateway/ui/pages/settings.js` — Settings page ### Modified Files - `src/gateway/ui/index.html` — Rewritten as SPA shell - `src/gateway/ui/style.css` — Extended with ~500 lines - `src/gateway/static.ts` — Added content types - `src/gateway/server.ts` — Added `channelRegistry` to config - `src/gateway/handlers/system.ts` — Added `system.channels` and `system.usage` - `src/gateway/handlers/sessions.ts` — Added `sessions.delete` and `sessions.switch` - `src/daemon/index.ts` — Wired channelRegistry into gateway