Files
toor 01d9e301fc
Build / build (push) Canceled after 0s
Playwright / browser (push) Canceled after 0s
initialize Electron desktop app and remove unused files
2026-10-25 01:09:01 +08:00

221 lines
9.7 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 electron:setup
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` launches Electron, its local Koa utility process, and the Vite renderer.
- `npm run electron:setup` downloads Electron and rebuilds native modules for its ABI.
- `npm run dev:web` retains standalone Vite + Koa development.
- `npm start` launches the built desktop app; `npm run start:web` serves the web build.
- `npm run pack` / `npm run dist` create desktop applications / installers.
- See `docs/electron.md` for runtime, data, packaging and smoke tests.
- `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.
## Hermes CLI Detection
The installation probe runs `hermes --help` in the Web UI service environment.
Some Hermes versions synchronously check upstream updates during `--version`, so
version output is not a reliable installation/liveness probe. A timeout does not
mean Hermes is absent and must not send users to the installation guide.
`GET /api/hermes/cli-status` reports `available`, `bin`, and `reason` (`ready`,
`missing`, `permission_denied`, `timeout`, or `failed`). `?refresh=1` bypasses the
completed-result cache while sharing an in-flight probe. Deploy validation must
check this endpoint as well as HTTP health; a running Node process alone does not
prove that its service user can execute Hermes.
When investigating, reproduce with the service's `HERMES_BIN`, `PATH`, `HOME`, and
`HERMES_HOME`. Inspect the complete launcher/interpreter path before changing
permissions. Do not use recursive permission changes to treat a probe timeout.
## 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 optional web 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`. Electron sets these to `userData/state`; standalone web defaults 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`
```