Files
hermes-ui/ARCHITECTURE.md
T
toor 1e9ea89d86
Build / build (push) Canceled after 0s
NPM Lockfile Check / npm ci --ignore-scripts (push) Canceled after 0s
Playwright / e2e (push) Canceled after 0s
chore: bootstrap hermes-ui skeleton from 0.6.29 snapshot
Import the client, server, skills, tests, and build scripts as the starting
point for the rebuild, then trim the surfaces this project does not ship:
Electron desktop packaging, the marketing website, and the ESP32 firmware
tree. CI keeps the web build, e2e, lockfile, release, and Docker workflows.

Rename the package and CLI entry points to hermes-ui, drop the prepare hook so
npm ci no longer triggers a build, and drop the removed tsconfig and nodemon
references. Rewrite AGENTS.md, ARCHITECTURE.md, DEVELOPMENT.md, and the READMEs
so the documented package map and hard rules match this repository.

reference_code/ is ignored: it is a read-only snapshot, not an input to the build.
2026-10-16 10:34:35 +08:00

5.5 KiB

Architecture

hermes-ui is a TypeScript project that ships a browser dashboard and a Koa backend around Hermes Agent. It runs on Node.js and talks to Hermes over an Agent Bridge (see "Hermes Integration" below).

Package Boundaries

Area Path Responsibility
Client packages/client/src Vue UI, routing, Pinia stores, API wrappers, i18n, browser-visible state.
Server packages/server/src HTTP API, auth, Socket.IO, SQLite stores, file access, Hermes runtime integration.
Skills packages/skills Built-in skills injected into the Hermes skills directory.
Legacy agent packages/ekko-agent In-house agent runtime. Slated for removal in Phase 003; do not extend it.
Tests tests Vitest unit/integration tests and Playwright browser tests.
CI .github/workflows Build, e2e, lockfile, Docker, and release automation.

This is not an npm workspaces monorepo. packages/client and packages/server have no package.json; their dependencies are declared in the root package.json.

Request Flow

  1. The browser loads the Vite-built client from the Koa server.
  2. Client modules call API helpers from packages/client/src/api.
  3. Server routes in packages/server/src/routes wire HTTP paths to controllers.
  4. Controllers validate request concerns and delegate reusable behavior to services.
  5. Services own side effects: files, SQLite, Hermes profiles, subprocesses, bridges, and credentials.
  6. Long-running chat and group-chat flows use Socket.IO namespaces managed by server services.

Keep each layer narrow. Routes should not grow business logic, and client code should not duplicate server persistence rules.

State And Data Ownership

  • Web UI state defaults to ~/.hermes-web-ui through config.appHome.
  • HERMES_WEB_UI_HOME and HERMES_WEBUI_STATE_DIR override Web UI state location. These identifiers are intentionally kept from the 0.6.x line: renaming them would break existing deployment scripts and orphan existing data directories.
  • Hermes Agent state lives under Hermes profile directories and must stay distinct from Web UI state. Profile isolation is done by injecting HERMES_HOME into child processes, never by copying directories.
  • Hermes state.db is read-only and owned by the Hermes Agent. Node-side code must never open it; read session history through the bridge's getHistory/getOutput.
  • The project's own SQLite store under packages/server/src/db is the only writable store for sessions, messages, and usage. There is no startup import sync from Hermes state.
  • Uploads default to config.uploadDir, which is derived from the Web UI home unless UPLOAD_DIR is set.
  • Runtime data directories must also live under the Web UI home, not beside built dist assets.
  • Profile-scoped Hermes data should use existing profile helpers instead of manually joining paths.

Server Structure

  • routes/ registers HTTP and WebSocket entry points.
  • controllers/ handles request-level behavior.
  • services/ owns reusable IO, domain behavior, external process calls, and integration logic.
  • db/ owns SQLite schemas and stores.
  • middleware/ owns request middleware such as user auth.
  • shared/ contains cross-server constants and helpers.

Architecture rules:

  • Register local API routes before proxy catch-all routes.
  • Keep auth behavior centralized in packages/server/src/services/auth.ts.
  • Prefer execFile or spawn with argument arrays over shell command strings.
  • All Hermes CLI calls go through execHermesWithBin/spawnHermesWithBin in services/hermes/hermes-process.ts.
  • Use structured file and YAML/JSON parsers when editing structured data.

Hermes Integration

Chat runs through the Agent Bridge, which is the only supported path:

browser --Socket.IO--> Koa/Node server --JSON over Unix socket--> Python child
                                                                   └- hermes-agent run_agent.AIAgent
  • services/hermes/agent-bridge/python/ is vendored, read-only code. The only exception is the HERMES_DESKTOP checks in bridge_runtime.py, which hide the Windows console window for git subprocesses and must stay.
  • services/hermes/group-chat/, lib/context-compressor/, and services/hermes/context-engine/ form the chat chain. Changes there require a docs/chat-chain-changes/<date>-<slug>.md fragment.
  • The Hermes CLI is user-installed. Point HERMES_BIN at the executable, or let the server resolve hermes from PATH.

Client Structure

  • views/ contains route-level screens.
  • components/ contains reusable UI.
  • stores/ contains Pinia state.
  • api/ contains HTTP clients and should use packages/client/src/api/client.ts.
  • i18n/ contains locale messages for user-facing strings. Only zh and en are supported.
  • styles/ contains global styling and theme primitives.

Frontend rules:

  • Use Vue 3 Composition API with <script setup lang="ts">.
  • Use Arco Design Vue components. Naive UI is being removed; do not add new naive-ui imports.
  • Add visible text to every locale file.
  • Keep component styles scoped unless the style is intentionally global.

Validation Surface

The minimum mechanical harness is:

  • npm run harness:check for repository docs, workflow, and package-script invariants.
  • npm run test or focused Vitest tests for local logic.
  • npm run test:e2e for browser-visible routing/auth/chat regressions.
  • npm run build for type checking and production bundles.

See docs/harness/validation.md for change-specific commands.