Commit graph

3 commits

Author SHA1 Message Date
emozilla
3d21aee811 feat(web): add Chat tab with xterm.js terminal + Sessions resume button
Wires the new /api/pty WebSocket into the dashboard as a top-level
Chat tab. Clicking Chat (or the ▶ play icon on any session row)
spawns a PTY running hermes --tui and renders its ANSI output with
xterm.js in the browser.

Frontend
--------

web/src/pages/ChatPage.tsx
  * @xterm/xterm v6 + @xterm/addon-webgl renderer (pixel-perfect cell
    grid — DOM and canvas renderers each have layout artifacts that
    break box-drawing glyph connectivity in a browser)
  * @xterm/addon-fit for container-driven resize
  * @xterm/addon-unicode11 for modern wide-char widths (matches Ink's
    string-width computation so kaomoji / CJK / emoji land on the
    same cell boundaries as the host expects)
  * @xterm/addon-web-links for URL auto-linking
  * Rounded dark-teal "terminal window" container with 12px internal
    padding + drop shadow for visual identity within the dashboard
  * Clipboard wiring:
      - Ctrl/Cmd+Shift+C copies xterm selection to system clipboard
      - Ctrl/Cmd+Shift+V pastes system clipboard into the PTY
      - OSC 52 handler writes terminal-emitted clipboard sequences
        (how Ink's own Ctrl+C and /copy command deliver copy events);
        decodes via TextDecoder so multi-byte UTF-8 codepoints
        (U+2265, emoji, CJK) round-trip correctly
      - Plain Ctrl+C still passes through as SIGINT to interrupt a
        running response
  * Floating "copy last response" button in the bottom-right corner.
    Triggers Ink's /copy slash by sending bytes in two frames with a
    100ms gap — Ink's tokenizer coalesces rapid adjacent bytes into
    a paste event (bypasses the slash dispatcher), so we deliberately
    split '/copy' and '\r' into separate packets to land them as
    individual keypresses.

web/src/App.tsx
  Chat nav entry (Terminal icon) at position 2 and <Route path="/chat">.

web/src/pages/SessionsPage.tsx
  Play-icon button per session row that navigates to /chat?resume=<id>;
  the PTY bridge forwards the resume param to hermes --tui --resume.

web/src/i18n/{en,zh,types}.ts
  nav.chat label + sessions.resumeInChat action label.

web/vite.config.ts
  /api proxy gains ws: true so WebSocket upgrades forward to :9119
  when running Vite dev mode against a separate hermes dashboard
  backend.

web/src/index.css + web/public/fonts-terminal/
  Bundles JetBrains Mono (Regular/Bold/Italic, Apache-2.0, ~280 KB
  total) as a local webfont. Fonts live outside web/public/fonts/
  because the sync-assets prebuild step wipes that directory from
  @nous-research/ui every build.

Package deps
------------

Net new: @xterm/xterm ^6.0.0, @xterm/addon-fit ^0.11.0,
         @xterm/addon-webgl ^0.19.0, @xterm/addon-unicode11 ^0.9.0,
         @xterm/addon-web-links ^0.12.0.

Bundle impact: +420 KB minified / +105 KB gzipped. Acceptable for a
feature that replaces what would otherwise be a rewrite of the entire
TUI surface in React.

Backend contract preserved
---------------------------

Every TUI affordance (slash popover, model picker, tool cards,
markdown streaming, clarify/sudo/approval prompts, skin engine, wide
chars, mouse tracking) lands in the browser unchanged because we are
running the real Ink binary. Adding a feature to the TUI surfaces in
the dashboard immediately. Do NOT add parallel React chat surfaces.
2026-04-21 03:10:30 -04:00
Austin Pickett
923539a46b fix: add nous-research/ui package 2026-04-19 10:48:56 -04:00
Teknium
e2a9b5369f
feat: web UI dashboard for managing Hermes Agent (#8756)
* feat: web UI dashboard for managing Hermes Agent (salvage of #8204/#7621)

Adds an embedded web UI dashboard accessible via `hermes web`:
- Status page: agent version, active sessions, gateway status, connected platforms
- Config editor: schema-driven form with tabbed categories, import/export, reset
- API Keys page: set, clear, and view redacted values with category grouping
- Sessions, Skills, Cron, Logs, and Analytics pages

Backend:
- hermes_cli/web_server.py: FastAPI server with REST endpoints
- hermes_cli/config.py: reload_env() utility for hot-reloading .env
- hermes_cli/main.py: `hermes web` subcommand (--port, --host, --no-open)
- cli.py / commands.py: /reload slash command for .env hot-reload
- pyproject.toml: [web] optional dependency extra (fastapi + uvicorn)
- Both update paths (git + zip) auto-build web frontend when npm available

Frontend:
- Vite + React + TypeScript + Tailwind v4 SPA in web/
- shadcn/ui-style components, Nous design language
- Auto-refresh status page, toast notifications, masked password inputs

Security:
- Path traversal guard (resolve().is_relative_to()) on SPA file serving
- CORS localhost-only via allow_origin_regex
- Generic error messages (no internal leak), SessionDB handles closed properly

Tests: 47 tests covering reload_env, redact_key, API endpoints, schema
generation, path traversal, category merging, internal key stripping,
and full config round-trip.

Original work by @austinpickett (PR #1813), salvaged by @kshitijk4poor
(PR #7621#8204), re-salvaged onto current main with stale-branch
regressions removed.

* fix(web): clean up status page cards, always rebuild on `hermes web`

- Remove config version migration alert banner from status page
- Remove config version card (internal noise, not surfaced in TUI)
- Reorder status cards: Agent → Gateway → Active Sessions (3-col grid)
- `hermes web` now always rebuilds from source before serving,
  preventing stale web_dist when editing frontend files

* feat(web): full-text search across session messages

- Add GET /api/sessions/search endpoint backed by FTS5
- Auto-append prefix wildcards so partial words match (e.g. 'nimb' → 'nimby')
- Debounced search (300ms) with spinner in the search icon slot
- Search results show FTS5 snippets with highlighted match delimiters
- Expanding a search hit auto-scrolls to the first matching message
- Matching messages get a warning ring + 'match' badge
- Inline term highlighting within Markdown (text, bold, italic, headings, lists)
- Clear button (x) on search input for quick reset

---------

Co-authored-by: emozilla <emozilla@nousresearch.com>
2026-04-12 22:26:28 -07:00