# Architecture ## Overview Hermes Mobile is split into two deployable parts: 1. Mobile app - Native Android app built with Capacitor around a shared React UI. - PWA/web build remains available as fallback and dev target. - Talks only to the companion server. - Does not need direct access to Hermes files or credentials. 2. Companion server - Runs on the same Linux machine as Hermes Agent. - Bridges mobile UI actions to Hermes Agent. - Owns upload storage, push notifications, pairing/auth, app metadata, and realtime event fanout. ```text +---------------------------+ | Android App | | - Chat | | - Tool timeline | | - Cron UI | | - Files | | - Approvals | +-------------+-------------+ | | HTTPS REST + WebSocket/SSE + native push/Web Push fallback v +---------------------------+ | Hermes Companion Server | | - Auth/pairing | | - Task orchestrator | | - Hermes adapters | | - Event bus | | - Upload store | | - Cron wrapper | | - Notification providers | +------+------+-------------+ | | | +--------------------+ | | v v +-------------+ +--------------+ | Hermes CLI | | Hermes files | | Hermes API | | sessions/db | | AIAgent | | cron jobs | +-------------+ +--------------+ ``` ## Key Architectural Rule The companion server should depend on stable Hermes surfaces first, but isolate every integration behind interfaces. ```ts interface HermesAdapter { health(): Promise startTask(input: StartTaskInput): AsyncIterable continueSession(sessionId: string, input: StartTaskInput): AsyncIterable stopTask(taskId: string): Promise } ``` Possible implementations: - `CliHermesAdapter`: spawns `hermes chat -q` or interactive process. Easiest baseline, weakest event detail. - `ApiHermesAdapter`: calls Hermes API server. Good for compatibility, but generic OpenAI API hides some tool events. - `PythonHermesAdapter`: imports Hermes Agent modules and uses callbacks for stream/tool progress. Best long-term event fidelity. - `GatewayHermesAdapter`: uses existing gateway/session machinery if exposed. ## Companion Server Modules ```text companion/ src/ app.ts # server bootstrap config/ # env/yaml config loading auth/ # pairing, sessions, tokens, passkeys later db/ # SQLite schema/migrations/repositories events/ # event bus + SSE/WebSocket fanout hermes/ # adapter interface + implementations tasks/ # task lifecycle/orchestration uploads/ # multipart upload handling + retention notifications/ # webpush/ntfy/gotify providers cron/ # Hermes cron wrapper approvals/ # approval queue + Hermes callbacks later routes/ # REST API routes ws/ # realtime endpoints system/ # service health, logs, install info ``` ## Event Bus Everything that happens in the companion becomes an event. Core event shape: ```ts type CompanionEvent = { id: string type: string taskId?: string sessionId?: string ts: string level?: 'debug' | 'info' | 'warn' | 'error' payload: unknown } ``` Important event types: ```text task.created task.started task.status task.finished task.failed task.cancelled assistant.delta assistant.message assistant.final tool_call.started tool_call.output tool_call.finished tool_call.failed file.uploaded file.generated approval.required approval.resolved cron.job.listed cron.job.updated cron.job.finished notification.sent notification.failed ``` The mobile app subscribes by: - WebSocket for active app foreground. - SSE fallback. - Push notifications when app is background/closed. ## Data Storage ### SQLite Companion-owned metadata: - paired devices - auth sessions - tasks - task events - uploaded files metadata - notification subscriptions - user settings/cache Do not duplicate full Hermes session content unless needed for mobile indexing. Hermes session DB remains source of truth. ### Filesystem Default paths: ```text /var/lib/hermes-mobile/ hermes-mobile.db uploads/ / generated/ cache/ logs/ ``` User-mode install paths: ```text ~/.local/share/hermes-mobile/ ~/.config/hermes-mobile/config.yaml ``` ## API Surface ### Auth / Pairing ```http POST /api/pair/start POST /api/pair/confirm POST /api/auth/login POST /api/auth/logout GET /api/me ``` Pairing flow: 1. Installer prints `https://host/pair?code=123-456`. 2. User opens on phone. 3. Server binds device and issues token. 4. Future sessions use secure cookie or bearer token. ### Tasks ```http POST /api/tasks GET /api/tasks GET /api/tasks/:id POST /api/tasks/:id/stop GET /api/tasks/:id/events WS /api/tasks/:id/stream ``` ### Uploads ```http POST /api/uploads GET /api/files GET /api/files/:id/download DELETE /api/files/:id ``` ### Sessions ```http GET /api/sessions GET /api/sessions/:id POST /api/sessions/:id/continue PATCH /api/sessions/:id ``` ### Cron ```http GET /api/cron/jobs POST /api/cron/jobs/:id/run POST /api/cron/jobs/:id/pause POST /api/cron/jobs/:id/resume DELETE /api/cron/jobs/:id ``` ### System ```http GET /api/health GET /api/hermes/health POST /api/hermes/test GET /api/logs ``` ## Hermes Integration Notes Existing useful surfaces observed: - Hermes API server exposes `/v1/chat/completions`, `/v1/responses`, `/v1/models`, `/health`. - `AIAgent` supports `stream_delta_callback` and `tool_progress_callback` constructor params. - Cron jobs are manageable through Hermes CLI/tooling and stored under Hermes home. - Gateway platforms already handle STT/media patterns, but mobile should not depend on Telegram. Long-term ideal: - Add/consume a Hermes-native event stream from AIAgent that emits structured tool events. - Companion server can either import Hermes modules or call a local IPC endpoint. ## Security Model Default deployments: 1. LAN/Tailscale only, simple pairing token. 2. Public HTTPS, pairing token + device token + optional passkey. Security requirements: - No unauthenticated access to prompt endpoints. - Upload size limits. - File paths normalized; no arbitrary file read from upload endpoints. - CSRF protection if cookie auth used. - Audit log for approvals. - Secrets remain in Hermes config/vault, not in mobile app. ## Notification Architecture Provider interface: ```ts interface NotificationProvider { send(device: Device, message: NotificationMessage): Promise test(device: Device): Promise } ``` Providers: - `WebPushProvider` - `NtfyProvider` - `GotifyProvider` - `NoopProvider` ## Deployment Modes ### User mode - Runs as current user. - Uses `~/.config/hermes-mobile` and `~/.local/share/hermes-mobile`. - Good for dev/single-user boxes. ### System mode - Creates `hermes-mobile` system user or runs under Hermes user. - Uses `/etc/hermes-mobile` and `/var/lib/hermes-mobile`. - systemd service. - Better production posture. ## Native Android Shell Capacitor Android is part of the primary architecture, not a future contingency. - The shared React UI builds into `apps/mobile/dist`. - Capacitor packages that build into an Android APK. - PWA/web access remains useful for dev, desktop, and fallback. - Native plugins provide share target, richer push, haptics, status bar, splash screen, microphone/file improvements, and Android lifecycle hooks.