feat: web UI dashboard for managing Hermes Agent - #7621
Conversation
Adds an embedded web UI dashboard accessible via `hermes web`. Provides a browser-based interface for: - Monitoring agent status, gateway, and active/recent sessions - Editing config.yaml with a schema-driven form editor - Managing API keys in .env (set, clear, view redacted) Backend: FastAPI server (hermes_cli/web_server.py) with REST endpoints. Frontend: Vite + React + TypeScript + Tailwind v4 SPA (web/ directory). Also adds: - `/reload` slash command for hot-reloading .env variables - `delete_env_value()` and `reload_env()` utilities in config.py - `[web]` optional dependency extra (fastapi + uvicorn) - Web build step in `hermes update` (both git and zip paths) - hermes_cli/web_dist/ to .gitignore and package-data Salvaged from PR #1813 by austinpickett onto current main. Fixes applied during salvage: - Replaced hardcoded CONFIG_SCHEMA with dynamic generation from DEFAULT_CONFIG - Restricted CORS to localhost origins (was allow_origins=[*]) - Dropped _maybe_reload_env from model_tools.py (stale reverts to core dispatch) - Dropped .python-version file - Skipped all stale-branch reverts (pyproject.toml, model_tools.py, etc.)
|
kshitijk4poor
left a comment
There was a problem hiding this comment.
PR Review — #7621: feat: web UI dashboard for managing Hermes Agent
Tests: 144 passed, 0 failed (test_config.py + test_commands.py)
Live test: imports ✓, CONFIG_SCHEMA generates 157 fields ✓, utility functions work ✓
Solid feature — clean React frontend, good schema-driven config editor, sensible defaults (localhost-only binding). A few issues to address before merge:
Critical
-
hermes_cli/web_server.py:367-370 — Path traversal in
serve_spa. The catch-all route doesfile_path = WEB_DIST / full_pathwithout validating the resolved path stays insideWEB_DIST. URL-encoded sequences like%2e%2e/bypass HTTP-level normalization and reachPath.__truediv__unmodified, allowing reads of arbitrary files (e.g.~/.hermes/.env). Fix: addif not file_path.resolve().is_relative_to(WEB_DIST.resolve()): return FileResponse(WEB_DIST / "index.html"). -
hermes_cli/config.py:2500 —
delete_env_value()duplicates the existingremove_env_value()(line 2425) but omits input validation (_ENV_VAR_NAME_RE), managed-mode check (is_managed()), and line sanitization (_sanitize_env_lines()). Should be deleted entirely — useremove_env_value()inweb_server.pyinstead.
Warnings
-
hermes_cli/web_server.py:384 — CORS origin list mutation is a no-op.
_LOCALHOST_ORIGINS.append(server_origin)runs instart_server(), butCORSMiddlewarecopiesallow_originsat__init__time (line 67). Custom--portvalues won't be allowed. Fix: create middleware lazily, or useallow_origin_regex=r"^https?://(localhost|127\.0\.0\.1)(:\d+)?$". -
hermes_cli/config.py:2535 —
reload_env()loads updated vars from.envintoos.environbut doesn't remove vars that were deleted from.env. Afterdelete_env_value()+/reload, the deleted key persists in the process environment. -
hermes_cli/web_server.py:242-251 —
SessionDB()instantiated on every request but never closed. With StatusPage polling every 5s, this leaks SQLite handles. Use a context manager or explicitclose(). -
hermes_cli/main.py:2894-2908, 3657-3671, 4216-4236 — Web UI build block (
npm install+npm run build) copy-pasted 3 times across_update_via_zip(),cmd_update(), andcmd_web(). Extract into a helper. -
hermes_cli/web_server.py:305-309, 337, 350 — Multiple endpoints return
str(e)in HTTP 500 responses. If the exception message includes file paths or partial values, those leak to the client. Log server-side, return generic error.
Suggestions
- web/src/pages/ConfigPage.tsx:100 — File input accepts
.json,.yaml,.ymlbuthandleImport()only parses JSON. YAML uploads will show "Invalid JSON file". Either remove.yaml/.ymlfromaccept, or add a YAML parser. - hermes_cli/web_server.py:303-309 —
PUT /api/configwritesbody.configto disk viasave_config()without schema validation. Any arbitrary keys or invalid value types are persisted. Consider validating againstCONFIG_SCHEMAbefore saving. - The PR adds ~600 lines of backend Python with zero tests.
delete_env_value(),reload_env(), schema generation, and the API endpoints should all have tests — the repo's test infrastructure is mature and the patterns are well-established. - Consider adding a
Hostheader check middleware to mitigate DNS rebinding (CORS alone doesn't fully protect localhost services). package-lock.json— add a.gitattributesentry (web/package-lock.json linguist-generated=true) so it collapses in GitHub diffs.
Looks Good
- CORS restricted to localhost — good security posture vs the original PR's
allow_origins=["*"]. - Dynamic config schema generated from
DEFAULT_CONFIGwith manual overrides — auto-discovers all 157 fields. /reloadcommand properly registered inCOMMAND_REGISTRYwith correct category.pyproject.tomlchanges are clean:[web]optional dep group,web_distpackage-data,allextra.- Vite build output correctly targets
../hermes_cli/web_dist/for bundling. - Frontend is well-structured: typed API client, proper TypeScript, clean component separation.
- Env vars are properly redacted — actual values never sent to the frontend.
- Atomic file write pattern in new config functions matches existing codebase style.
- Good decision to drop
_maybe_reload_envfrom the original PR (per-tool-call I/O overhead).
Salvage of PR NousResearch#7621 by @teknium1, based on original PR NousResearch#1813 by @austinpickett. Adds an embedded web UI dashboard accessible via `hermes web`: - Status page: agent version, active sessions, gateway status, platforms - Config editor: schema-driven form with tabbed categories, import/export - API Keys page: set, clear, and view redacted values with category grouping Backend (hermes_cli/web_server.py): - FastAPI server with REST endpoints (/api/status, /api/sessions, etc.) - Dynamic CONFIG_SCHEMA generated from DEFAULT_CONFIG (157 fields) Frontend (web/): - Vite + React + TypeScript + Tailwind v4 SPA - shadcn/ui-style components, auto-refresh status page, toast notifications Fixes applied during salvage (vs PR NousResearch#7621): - Path traversal: added resolve().is_relative_to() check in serve_spa - Replaced duplicate delete_env_value() with existing remove_env_value() (which has input validation, managed-mode check, and sanitization) - CORS: replaced static origin list with allow_origin_regex matching any localhost port (fixes custom --port not being allowed) - reload_env(): now removes known Hermes vars deleted from .env - SessionDB: added db.close() in finally blocks to prevent handle leaks - Extracted _build_web_ui() helper (was copy-pasted 3 times) - Endpoints return generic errors; full exceptions logged server-side - ConfigPage: removed .yaml/.yml from file import accept (only JSON works) - Added .gitattributes to collapse package-lock.json in diffs - Non-localhost --host binding now logs a security warning - Added 17 tests for reload_env, redact_key, API endpoints, schema generation, and path traversal prevention
) 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.
) 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.
* 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>
|
Closing during PR triage — not pursuing this approach. |
* feat: web UI dashboard for managing Hermes Agent (salvage of NousResearch#8204/NousResearch#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 NousResearch#1813), salvaged by @kshitijk4poor (PR NousResearch#7621 → NousResearch#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>
* feat: web UI dashboard for managing Hermes Agent (salvage of NousResearch#8204/NousResearch#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 NousResearch#1813), salvaged by @kshitijk4poor (PR NousResearch#7621 → NousResearch#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>
* feat: web UI dashboard for managing Hermes Agent (salvage of NousResearch#8204/NousResearch#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 NousResearch#1813), salvaged by @kshitijk4poor (PR NousResearch#7621 → NousResearch#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>
* feat: web UI dashboard for managing Hermes Agent (salvage of NousResearch#8204/NousResearch#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 NousResearch#1813), salvaged by @kshitijk4poor (PR NousResearch#7621 → NousResearch#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>
* feat: web UI dashboard for managing Hermes Agent (salvage of NousResearch#8204/NousResearch#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 NousResearch#1813), salvaged by @kshitijk4poor (PR NousResearch#7621 → NousResearch#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>
* feat: web UI dashboard for managing Hermes Agent (salvage of NousResearch#8204/NousResearch#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 NousResearch#1813), salvaged by @kshitijk4poor (PR NousResearch#7621 → NousResearch#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>
Summary
Salvage of PR #1813 by @austinpickett onto current main.
Adds an embedded web UI dashboard accessible via
hermes web:Backend
hermes_cli/web_server.py— FastAPI server with REST endpoints (/api/status,/api/sessions,/api/config,/api/env)hermes_cli/config.py— Addeddelete_env_value()andreload_env()utilitieshermes_cli/main.py— Addedhermes websubcommand (--port,--host,--no-open)cli.py/commands.py— Added/reloadslash command for hot-reloading .envpyproject.toml— Added[web]optional dependency extra (fastapi + uvicorn)Frontend
web/Fixes applied during salvage (vs original PR #1813)
DEFAULT_CONFIG(auto-discovers all 157 config fields, applies manual overrides for select dropdowns)allow_origins=['*']to localhost-only origins_maybe_reload_envfrom model_tools.py — the original addedos.path.getmtime()I/O on every tool call, and hardcoded~/.hermes/.env(breaks profiles). The/reloadcommand is the right UX for this..python-versionfile (3.11 pin doesn't belong in repo)Test plan
python -m pytest tests/hermes_cli/test_config.py tests/hermes_cli/test_commands.py -n0 -q→ 144 passeddelete_env_value(),reload_env(),redact_key()all verified with isolated HERMES_HOME