198 lines
8.3 KiB
Markdown
198 lines
8.3 KiB
Markdown
# Development Guidelines
|
|
|
|
This document defines project-level development rules for hermes-ui. It is tool-agnostic and applies to all contributors and coding agents.
|
|
|
|
## Prerequisites
|
|
|
|
- Node.js `>=23` (see `engines` in `package.json`).
|
|
- Python with `hermes-agent` installed. The Hermes CLI is not bundled; point
|
|
`HERMES_BIN` at the executable or make `hermes` resolvable from `PATH`.
|
|
- A C/C++ toolchain, **but only on Linux**: `python3`, `make`, `g++`. See
|
|
"Platform Notes" below.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
npm ci --ignore-scripts
|
|
npm rebuild node-pty
|
|
npm run dev
|
|
npm run test
|
|
npm run test:coverage
|
|
npm run test:e2e
|
|
npm run build
|
|
```
|
|
|
|
- `npm ci --ignore-scripts` installs exactly what `package-lock.json` pins. Do not upgrade dependencies.
|
|
- `npm rebuild node-pty` is **required**, not optional. `npm ci --ignore-scripts`
|
|
skips every install script, and `node-pty`'s install script is what puts a
|
|
loadable native module in place. Skipping it leaves the terminal feature
|
|
silently disabled — the server logs a warning and keeps running.
|
|
- `npm run dev` starts the Vite client and Koa server together.
|
|
- `npm run test` runs Vitest unit tests.
|
|
- `npm run test:coverage` is what the Build workflow runs before `npm run build`.
|
|
- `npm run test:e2e` runs Playwright browser tests against a mocked BFF API.
|
|
- `npm run build` type-checks and builds both client and server.
|
|
|
|
## One-Click Deploy
|
|
|
|
`deploy.sh` deploys a checkout to a host that runs the built server under
|
|
systemd:
|
|
|
|
```bash
|
|
./deploy.sh # pull, install, build, restart, verify
|
|
./deploy.sh --dry-run # print the plan and exit
|
|
./deploy.sh --help # all options
|
|
```
|
|
|
|
It pulls `origin/main` with `--ff-only`, reinstalls dependencies only when
|
|
`package-lock.json` changed, rebuilds the `node-pty` native module, builds the
|
|
client and the server, restarts the `hermes-ui.service` unit, and verifies the
|
|
result against both `/health` and `/api/auth/status`. The previous `dist/` is
|
|
backed up to `~/.local/state/hermes-ui-deploy/backups/` first and restored
|
|
automatically when the build or the health check fails.
|
|
|
|
`start.sh` is the development launcher (foreground Vite + Koa); `deploy.sh` is
|
|
the production path. Do not mix them.
|
|
|
|
## Platform Notes
|
|
|
|
The server runs on Windows, macOS, and Linux. The parts that differ are
|
|
isolated behind `process.platform` checks, so the same source runs everywhere.
|
|
|
|
### node-pty
|
|
|
|
`node-pty` ships prebuilt binaries for Windows and macOS only:
|
|
|
|
| Platform | Where the native module comes from | Build step |
|
|
| --- | --- | --- |
|
|
| Windows | `prebuilds/win32-<arch>/` (shipped in the npm tarball) | not needed |
|
|
| macOS | `prebuilds/darwin-<arch>/` (shipped in the npm tarball) | not needed |
|
|
| Linux | **none — must be compiled from source** | `npm rebuild node-pty` |
|
|
|
|
On Linux, `npm rebuild node-pty` compiles `node-pty` from source and needs
|
|
`python3`, `make`, and `g++` on the machine. The Dockerfile installs exactly
|
|
those for this reason.
|
|
|
|
On macOS the prebuilt `spawn-helper` may arrive without its executable bit.
|
|
The server repairs that at startup
|
|
(`packages/server/src/routes/hermes/terminal.ts`), and `bin/hermes-ui.mjs`
|
|
does the same for the installed CLI.
|
|
|
|
### Other platform differences
|
|
|
|
- **Terminal shell**: `powershell.exe` on Windows, `$SHELL` (falling back to
|
|
`/bin/zsh` then `/bin/bash`) on macOS and Linux.
|
|
- **Agent Bridge transport**: a Unix domain socket at
|
|
`ipc:///tmp/hermes-agent-bridge.sock` on macOS and Linux, a TCP port
|
|
(`tcp://127.0.0.1:18765`) on Windows, which has no Unix socket support in
|
|
Node.
|
|
- **Python interpreter**: `python3` on macOS and Linux, `python` on Windows.
|
|
Virtualenv layout differs too (`venv/bin/python3` vs `venv\Scripts\python.exe`).
|
|
- **Gateway process tree**: `taskkill /T` on Windows, process-group signals on
|
|
macOS and Linux.
|
|
- **Hermes home**: `~/.hermes` on macOS and Linux; on Windows, an existing
|
|
`%LOCALAPPDATA%\hermes` or `%APPDATA%\hermes` takes priority.
|
|
|
|
### Verification
|
|
|
|
Linux is covered by the `Build` and `Playwright` workflows, which run on
|
|
`ubuntu-latest`. macOS is not covered by any hosted runner; the
|
|
`macOS Verification` workflow (`workflow_dispatch` only) runs the same checks
|
|
when a macOS runner is available.
|
|
|
|
## Architecture
|
|
|
|
- Frontend code lives under `packages/client/src`.
|
|
- Server code lives under `packages/server/src`.
|
|
- Hermes-specific client code stays under `hermes` namespaces: API modules, views, stores, and components.
|
|
- Server routes should stay thin. Put request handling in controllers and reusable behavior in services.
|
|
- The chat runtime is Socket.IO based and lives under `packages/server/src/services/hermes/run-chat`.
|
|
- Web UI state lives under `HERMES_WEB_UI_HOME` or `HERMES_WEBUI_STATE_DIR`, defaulting to `~/.hermes-web-ui`.
|
|
- Hermes `state.db` is read-only. Never open it from Node-side code.
|
|
|
|
## Coding Rules
|
|
|
|
- Prefer existing local patterns over new abstractions.
|
|
- Keep changes scoped to the requested behavior.
|
|
- Do not mix unrelated refactors into feature or bugfix commits.
|
|
- Do not reintroduce deprecated compatibility switches without a current caller.
|
|
- Use structured APIs and parsers for structured data instead of ad hoc string edits when possible.
|
|
- Add comments only where they explain non-obvious behavior or constraints.
|
|
|
|
## Frontend Rules
|
|
|
|
- Use Vue 3 Composition API with `<script setup lang="ts">`.
|
|
- Use Pinia setup stores.
|
|
- Use the shared API request helper in `packages/client/src/api/client.ts`.
|
|
- Add user-facing strings to all locale files (`zh.ts` and `en.ts` are the only two).
|
|
- Keep component styles scoped with SCSS unless the style is intentionally global.
|
|
- Use Arco Design Vue components and follow existing Arco patterns. Do not add new `naive-ui` imports
|
|
and do not introduce another UI library.
|
|
|
|
## Server Rules
|
|
|
|
- Register local API routes before proxy catch-all routes.
|
|
- Keep auth behavior centralized in `packages/server/src/services/auth.ts`.
|
|
- Use `config.appHome` for Web UI state paths.
|
|
- Keep Hermes home paths separate from Web UI home paths.
|
|
- Use `getActiveProfileDir()` or related profile helpers for Hermes profile files.
|
|
- Avoid shell string construction for CLI calls; prefer `execFile`/`spawn` with argument arrays,
|
|
routed through `execHermesWithBin`/`spawnHermesWithBin`.
|
|
|
|
## Red Lines
|
|
|
|
- `packages/server/src/services/hermes/agent-bridge/python/` is vendored and read-only. The
|
|
`HERMES_DESKTOP` checks in `bridge_runtime.py` are the one exception and must stay.
|
|
- The `/chat-run` Socket.IO event contract is frozen: no changes to event names, field names,
|
|
field types, or emission timing. Adding optional fields is allowed.
|
|
- Changes under `services/hermes/group-chat/`, `lib/context-compressor/`, or
|
|
`services/hermes/context-engine/` require a `docs/chat-chain-changes/<date>-<slug>.md` fragment.
|
|
|
|
## Testing Rules
|
|
|
|
- Add focused Vitest coverage for server and store logic changes.
|
|
- Add Playwright coverage for browser-visible flows and routing/auth regressions.
|
|
- For frontend browser tests, prefer API/socket mocks over real external services.
|
|
- Before opening a PR, run the smallest relevant tests plus `npm run build`.
|
|
- For broad changes, run:
|
|
|
|
```bash
|
|
npm run test:coverage
|
|
npm run test:e2e
|
|
npm run build
|
|
```
|
|
|
|
## Commit And PR Rules
|
|
|
|
- Branch from `main` for new work.
|
|
- Use short, descriptive branch names such as `fix/login-token` or `feat/group-chat-copy`.
|
|
- Commit only files that belong to the change.
|
|
- Use concise commit messages that describe the change, for example `fix login token storage` or `add group chat clone naming`.
|
|
- Keep commits focused. Do not bundle unrelated cleanup with feature work unless the cleanup is required.
|
|
- Push the branch and open a PR against `main` unless the issue explicitly targets another base.
|
|
- Prefer draft PRs while validation is still running or when the change needs review before merge.
|
|
- Mark a PR ready only after the relevant tests and build pass.
|
|
- Keep PR titles concrete and scoped, for example `make Web UI state directory configurable`.
|
|
- Link issues in the PR body with `Closes #123`, `Fixes #123`, or `Refs #123` as appropriate.
|
|
- PR descriptions should include:
|
|
- what changed
|
|
- why it changed
|
|
- user or developer impact
|
|
- validation commands run
|
|
- known limitations or follow-up work, if any
|
|
- Do not overwrite or revert unrelated user changes.
|
|
|
|
Use this PR body shape by default:
|
|
|
|
```md
|
|
## Summary
|
|
- ...
|
|
- ...
|
|
|
|
Closes #123
|
|
|
|
## Validation
|
|
- `npm run test:coverage`
|
|
- `npm run build`
|
|
```
|