M0: toolchain, monorepo scaffold, gateway plugin skeleton, CMP app
- gateway-plugin/: android platform plugin (plugin.yaml + adapter.py register(ctx) + no-op AndroidAdapter) + stub modules for M1-M5 - app/: Compose Multiplatform project (shared KMP + androidApp + desktopApp) with Gradle wrapper; builds :androidApp:assembleDebug and :desktopApp:compileKotlin - scripts/guard_hermes_agent.sh + pre-commit hook: fail if hermes-agent/ is staged (read-only reference, never committed) - .gitignore excludes hermes-agent/; docs/ reference library
This commit is contained in:
commit
59acf66c89
49 files changed
+3950
No files matched your search
@@ -0,0 +1,130 @@
|
||||
# 02 — Monorepo Structure
|
||||
|
||||
One repository, three artifacts. `hermes-agent/` is **not** part of the repo
|
||||
(git-ignored reference).
|
||||
|
||||
## Top-level tree
|
||||
|
||||
```
|
||||
iris_x_hermes/
|
||||
├── .gitignore # MUST exclude hermes-agent/ (see below)
|
||||
├── README.md # Repo root readme (short; points to docs/)
|
||||
├── docs/ # ← THIS reference library
|
||||
│
|
||||
├── hermes-agent/ # ⚠️ READ-ONLY REFERENCE — NEVER PUSHED (git-ignored)
|
||||
│
|
||||
├── gateway-plugin/ # ① Python plugin → installed to ~/.hermes/plugins/android
|
||||
│ ├── plugin.yaml # manifest (kind: platform, env vars, home channel)
|
||||
│ ├── __init__.py
|
||||
│ ├── adapter.py # AndroidAdapter(BasePlatformAdapter) + register(ctx)
|
||||
│ ├── ws_server.py # websockets server, connection registry, framing
|
||||
│ ├── protocol.py # frame schemas (source of truth, mirrored in Kotlin)
|
||||
│ ├── media.py # inbound cache + outbound chunked streaming
|
||||
│ ├── outbox.py # SQLite offline outbox + sync cursor
|
||||
│ ├── push.py # PushBackend: FcmBackend + NtfyBackend
|
||||
│ ├── pairing.py # token gen/verify, device registry
|
||||
│ ├── search.py # FTS5 session search bridge
|
||||
│ └── tests/ # pytest (run via hermes scripts/run_tests.sh)
|
||||
│
|
||||
├── app/ # ② + ③ Compose Multiplatform project (Kotlin)
|
||||
│ ├── settings.gradle.kts
|
||||
│ ├── build.gradle.kts
|
||||
│ ├── gradle.properties
|
||||
│ ├── gradle/ gradlew gradlew.bat
|
||||
│ ├── shared/ # KMP module — the bulk of the code
|
||||
│ │ ├── build.gradle.kts
|
||||
│ │ └── src/
|
||||
│ │ ├── commonMain/kotlin/iris/… # protocol, WS client, repo, state, Compose UI
|
||||
│ │ ├── androidMain/kotlin/… # FCM, ExoPlayer, SAF picker, notifications
|
||||
│ │ └── desktopMain/kotlin/… # tray, file dialog, player, window
|
||||
│ ├── androidApp/ # thin Android shell (Application, MainActivity)
|
||||
│ │ ├── build.gradle.kts
|
||||
│ │ └── src/main/… # AndroidManifest, res, Firebase options
|
||||
│ └── desktopApp/ # thin Desktop shell (main(), window)
|
||||
│ ├── build.gradle.kts
|
||||
│ └── src/main/kotlin/…
|
||||
│
|
||||
└── (no other top-level code)
|
||||
```
|
||||
|
||||
## Module responsibilities
|
||||
|
||||
### `gateway-plugin/` (Python)
|
||||
- **`plugin.yaml`** — manifest: `name: android-platform`, `kind: platform`,
|
||||
`requires_env` / `optional_env` (surfaced in `hermes config`/setup).
|
||||
- **`adapter.py`** — `AndroidAdapter(BasePlatformAdapter)` + `register(ctx)`.
|
||||
The heart of the plugin. See `03-gateway-plugin.md`.
|
||||
- **`ws_server.py`** — `websockets` server, per-device connection registry,
|
||||
frame encode/decode, heartbeat, broadcast routing to all connected devices.
|
||||
- **`protocol.py`** — dataclasses/constants for every frame (single source of
|
||||
truth; `docs/protocol/frames.schema.json` is generated/mirrored from it).
|
||||
- **`media.py`** — inbound chunked upload → `cache_*_from_bytes`; outbound
|
||||
`media.offer`/`media.pull` chunked streaming.
|
||||
- **`outbox.py`** — SQLite outbox per `chat_id` + monotonic sync cursor.
|
||||
- **`push.py`** — `PushBackend` interface; `FcmBackend` (httpx, FCM HTTP v1) and
|
||||
`NtfyBackend` (reuses hermes ntfy publish). Selected by `ANDROID_PUSH_BACKEND`.
|
||||
- **`pairing.py`** — token generation/verification (constant-time), device
|
||||
registry (SQLite), QR payload.
|
||||
- **`search.py`** — FTS5 query bridge over the hermes session store.
|
||||
|
||||
### `app/shared` (Kotlin KMP)
|
||||
- **`commonMain`** — protocol models (kotlinx-serialization), `GatewayClient`
|
||||
(OkHttp WS), repositories (Room), ViewModels (StateFlow), and the Compose UI
|
||||
(design system, screens). ~80% of app code.
|
||||
- **`androidMain`** — FCM service, ExoPlayer, SAF media picker, system
|
||||
notifications, `MediaPlayer` actual.
|
||||
- **`desktopMain`** — tray + OS notifications, desktop player, file dialog,
|
||||
window management, `MediaPlayer` actual.
|
||||
|
||||
### `app/androidApp` / `app/desktopApp`
|
||||
Thin shells: `Application`/`MainActivity` (Android) and `main()`/window
|
||||
(Desktop). They compose the `shared` UI and inject platform services.
|
||||
|
||||
## Build systems
|
||||
|
||||
- **Python plugin:** no build step (pure Python, stdlib + hermes core deps).
|
||||
Installed by copying/symlinking into `~/.hermes/plugins/android`. Tested with
|
||||
hermes's `scripts/run_tests.sh`.
|
||||
- **Kotlin/CMP:** Gradle (Kotlin DSL) with the Compose Multiplatform plugin.
|
||||
`./gradlew :androidApp:installDebug`, `./gradlew :desktopApp:run`,
|
||||
`./gradlew :shared:testDebugUnitTest`.
|
||||
|
||||
## `.gitignore` (root) — critical
|
||||
|
||||
```gitignore
|
||||
# hermes-agent is a read-only research reference — NEVER commit/push it
|
||||
/hermes-agent/
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.venv/
|
||||
venv/
|
||||
|
||||
# Kotlin / Gradle
|
||||
.gradle/
|
||||
build/
|
||||
local.properties
|
||||
*.iml
|
||||
.idea/
|
||||
|
||||
# Android / Firebase
|
||||
app/androidApp/src/main/res/values/secrets.xml
|
||||
google-services.json
|
||||
*.jks
|
||||
keystore.jks
|
||||
|
||||
# OS / misc
|
||||
.DS_Store
|
||||
*.log
|
||||
```
|
||||
|
||||
> The `/hermes-agent/` line is non-negotiable. Add a pre-commit guard (or CI
|
||||
> check) that fails if any path under `hermes-agent/` is staged.
|
||||
|
||||
## Install layout (runtime)
|
||||
|
||||
- **Plugin:** `~/.hermes/plugins/android/` ← copy of `gateway-plugin/`
|
||||
(or a symlink for dev). Discovered by hermes's `PluginManager`.
|
||||
- **App (dev):** installed on-device via `./gradlew :androidApp:installDebug`.
|
||||
- **App (desktop, dev):** `./gradlew :desktopApp:run`.
|
||||
Reference in new issue
Block a user