web: React+Vite SPA — sessions, streaming chat, task panel, spawn flow (build clean)

This commit is contained in:
Raphael Westphal
2026-08-18 13:37:14 +02:00
parent 345025b070
commit 7d5f866527
22 changed files with 4253 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
# lvmh web UI
React 19 + Vite + TypeScript single-page app for the lvmh daemon. Talks only
to the REST API under `/api` and the `/ws` websocket described in
`../PROTOCOL.md`.
## Run (dev)
```
cd web
npm install
npm run dev
```
Dev server proxies `/api` and `/ws` to `http://localhost:8686`
(see `vite.config.ts`).
## Build
```
npm run build
```
Type-checks with `tsc --noEmit`, bundles to `web/dist/` (the daemon serves
this directory).
## First use
On first load the UI shows a settings gate: server URL (defaults to
same-origin) + bearer token (`LVMH_TOKEN`). Stored in `localStorage`; cleared
via the "disconnect" button in the sidebar footer.
## Structure
- `src/protocol.ts` — typed mirror of PROTOCOL.md (envelope, event types,
REST routes, WS frames)
- `src/ws.ts` — single websocket manager: auto-reconnect with exponential
backoff + jitter, resubscribe on open, seq tracking helpers
- `src/api.ts``fetchJson` helper with bearer auth + error parsing
- `src/settings.ts` — localStorage settings + WS URL builder
- `src/store.ts` — sessions store (REST seed + WS `session_list` updates),
toasts, time formatting
- `src/derive.ts` — client-side derivation: chat view from events, todo list
from `todo` tool calls, subagent runs from `subagent` tool calls
- `src/ChatView.tsx` — chat: history load, live streaming via `message_update`,
abort, sticky scroll
- `src/SessionsView.tsx` — session list with online dots, agent badges, stop
- `src/SpawnView.tsx` — GitLab connect + repo/branch picker + spawn polling
- `src/SettingsGate.tsx` — first-run token gate
## Conventions
- No UI/state/HTTP libraries beyond react, react-dom, react-router-dom.
- All icon-only buttons carry `aria-label`.
- Dark theme, mobile-friendly (≤400px) via hand-rolled CSS in `src/index.css`.