build: establish Android beta packaging

This commit is contained in:
Hermes Agent
2026-07-24 15:12:49 +00:00
parent b1bc66122b
commit 3b883bd534
9 changed files with 156 additions and 42 deletions
+6
View File
@@ -5,6 +5,7 @@ All notable Hermes Mobile source changes are recorded here. Entries are added du
## Unreleased
### Added
- Added semantic Android beta package metadata coverage and a direct-gateway-only `v0.1.0-beta.1` build, metadata inspection, clean-install, launch, configuration, evidence, and limitations guide.
- Added deterministic small-phone, landscape, and tablet layout policy with navigation rail adaptation, tablet two-pane chat, and narrow/large-font control stacking.
- Added accessibility semantics for headings, panes, streaming announcements, selected/busy states, and actionable rows, plus 48dp minimum touch targets and bounded large message/code rendering with retained full-copy actions for code and tool output.
- Added capability-gated direct gateway tool lifecycle decoding and compact status cards for `tool.started`, `tool.progress`, `tool.completed`, and `tool.failed` SSE events.
@@ -32,6 +33,7 @@ All notable Hermes Mobile source changes are recorded here. Entries are added du
- Added `PROJECT_PLAN.md` as the project-controlled milestone plan.
### Changed
- Changed Android `versionName` to `0.1.0-beta.1`, monotonic `versionCode` to `10001`, and the debug APK base name to `hermes-mobile-v0.1.0-beta.1`; the npm Android build command now runs the native Gradle project without Capacitor synchronization.
- Removed the Android portrait lock, enabled `adjustResize` IME behavior, and suppressed top-level screen slides when the system animator duration scale is disabled.
- Kept direct artifact handoff actions gated off because the advertised gateway contract has no verified artifact URI/download capability; no upstream route or backend behavior was inferred.
- Changed direct session streaming to publish reducer updates to the owning durable send coordinator while retaining the original immutable route/session lease for the entire OkHttp call.
@@ -58,6 +60,10 @@ All notable Hermes Mobile source changes are recorded here. Entries are added du
- Fixed companion/mobile lint issues from missing Node globals and an unused React settings value.
### Verification
- `/root/.openclaw/workspace/scripts/hermes-mobile-preflight.sh` — passed; Android `:app:assembleDebug` BUILD SUCCESSFUL (37 tasks, 14 executed).
- `GRADLE_USER_HOME=/root/hermes-mobile/.gradle-user ./gradlew --offline --no-daemon -Dorg.gradle.jvmargs= -Dorg.gradle.daemon=false -Pkotlin.compiler.execution.strategy=in-process :app:testDebugUnitTest :app:assembleDebug` — passed (43 tasks, 5 executed), including `BetaPackageMetadataTest` for application ID `cloud.molberg.hermesmobile`, `versionName` `0.1.0-beta.1`, and `versionCode` `10001`.
- `git diff --check` — passed for R2 source packaging.
- R2 device installation — not run; ADB daemon sockets are sandbox-prohibited and no emulator executable, AVD, `/dev/kvm`, USB device bus, or running target is available. No APK was published or uploaded, and no release criterion is claimed.
- R1 source-level verification: the required recovery preflight passed immediately before this run; direct JUnit execution of the cached, source-current Android unit classes passed all 61 tests, including all 4 `AdaptiveQualityTest` cases; and `git diff --check` passed. `GRADLE_USER_HOME=/root/hermes-mobile/.gradle-user ./gradlew --offline --no-daemon -Dorg.gradle.jvmargs= -Dorg.gradle.daemon=false -Pkotlin.compiler.execution.strategy=in-process :app:compileDebugKotlin :app:compileDebugUnitTestKotlin :app:assembleDebug` was blocked before project execution by `java.net.SocketException: Operation not permitted`. ADB 37.0.0 is installed at `/opt/android-sdk/platform-tools/adb`, but its daemon cannot create the smart-socket or netlink sockets; no emulator executable, AVD, `/dev/kvm`, USB device bus, or running target exists. No emulator/device matrix evidence exists, so R1 remains incomplete.
- Full Android Kotlin/Compose main-source and unit-test compilation through cached Kotlin 2.0.21 plus direct JUnit execution — passed, 57 tests including B5 large-output bounds, advertised tool lifecycle reduction, and rotation/resume expansion restoration.
- Recovery preflight for B5 — passed before this run.
+10 -13
View File
@@ -24,27 +24,20 @@
Complete the Android/client contract pivot before implementing backend behavior. The next release path targets a remote upstream Hermes Agent gateway/API server directly; `apps/companion` is legacy compatibility only.
- [ ] **R1Execute and document the adaptive/accessibility device matrix**
- Small phone, normal phone, tablet/two-pane behavior; portrait/landscape.
- Font scaling, TalkBack semantics, contrast, touch targets, reduced motion, IME behavior.
- Verification: emulator/device matrix evidence documented in `docs/ROADMAP.md`.
- Source-level progress on 2026-07-24: removed the portrait lock, enabled resize-on-IME, added deterministic phone/landscape/tablet layout policy and tablet two-pane chat, stacked dense controls for narrow/large-font layouts, respected the disabled system animator-duration setting for top-level navigation, added headings/live regions/roles/state descriptions, raised interactive targets to at least 48dp, and bounded very large message/code rendering while retaining full-copy actions for code and tool output.
- Source verification on 2026-07-24: the required recovery preflight passed immediately before this run; direct JUnit execution of the cached, source-current Android unit classes passed all 61 tests, including all 4 `AdaptiveQualityTest` cases; and `git diff --check` passed. A direct writable-cache Gradle retry was blocked before project execution by `java.net.SocketException: Operation not permitted`. ADB is installed, but its daemon sockets are sandbox-prohibited; no emulator executable, AVD, `/dev/kvm`, USB device bus, or running target is available. R1 remains unchecked because no emulator/device matrix evidence exists.
- [ ] **R2Verify a clean `v0.1.0-beta.1` install against a direct gateway**
- On one named real device or emulator, build the source-current versioned debug APK, confirm package metadata, uninstall prior app data, install and launch it, configure an upstream Hermes gateway directly, and record the connection result plus APK SHA-256.
- Verification: required preflight and Android checks pass in the install environment; device/install evidence is recorded in `docs/ROADMAP.md`; no release or final beta criterion is claimed from source-only checks.
## Externally blocked
- **R1 — Execute and document the adaptive/accessibility device matrix**
- Source safeguards and 61 cached source-current unit tests were verified on 2026-07-24, but small-phone, normal-phone, tablet, TalkBack, contrast, motion, and IME evidence still requires a permitted real device or emulator.
- Unblock evidence is maintained in `docs/BLOCKERS.md`; do not mark R1 complete from source review alone.
- **B3 — Direct gateway session contract and durable chat state**
- Foundation verified 2026-07-24: repository search contract and fake implementation, capability-gated session list/create/get/delete mapping, durable selected-session/draft/pending-send storage, and duplicate-send reducer/UI protection.
- Not complete: official upstream documentation still provides no session-search HTTP contract, and the configured local API server was not listening for a live compatibility exercise on 2026-07-24.
- Unblock evidence is maintained in `docs/BLOCKERS.md`; do not mark B3 complete until documented search and real gateway behavior are verified.
## Later beta work
- **R2 — Beta packaging and install guide**
- Version `v0.1.0-beta.1`, reproducible debug/beta APK build, install/run guide, known limitations.
- Publish source commit, APK, release notes, and verification result.
- Verification: clean install on a real device or emulator plus full required checks.
## V2 backlog
- Multiple server profiles and fast switching.
@@ -60,6 +53,10 @@ Complete the Android/client contract pivot before implementing backend behavior.
_Move finished items here with date, commit, and verification. Keep this section factual; do not claim unverified work._
- [x] **R2a — Establish beta source packaging and install documentation** — 2026-07-24, commit `98b183e` (`build: establish Android beta packaging`).
- Set Android package metadata to semantic `versionName` `0.1.0-beta.1` with monotonic `versionCode` `10001`, enabled generated metadata coverage, and named the debug APK `hermes-mobile-v0.1.0-beta.1-debug.apk`.
- Added a direct-gateway-only build, metadata inspection, clean-install, launch, configuration, evidence, and known-limitations guide; changed the npm Android build command to run the native Gradle project without Capacitor synchronization.
- Source verification on 2026-07-24: required recovery preflight passed; `:app:testDebugUnitTest :app:assembleDebug` passed with the cached offline Gradle setup (43 tasks, 5 executed); and `git diff --check` passed. No APK was published, uploaded, or installed, so the remaining R2 device task and all final release criteria remain unclaimed.
- [x] **B5 — Tool, artifact, and output experience** — 2026-07-24, commit `feat: add gated tool output experience`.
- Added capability-gated decoding and reduction for the existing `tool.started`, `tool.progress`, `tool.completed`, and `tool.failed` direct gateway SSE events, with compact lifecycle/status cards for referenced and stream-only tools.
- Added full-output copy plus deterministic collapsed/expanded display windows capped at 5/80 lines and 24,000 expanded characters, avoiding same-direction nested scrolling while retaining the complete output in state.
+12 -24
View File
@@ -1,16 +1,17 @@
# Hermes Mobile
Android-first mobile control surface and local companion server for [Hermes Agent](https://github.com/NousResearch/hermes-agent).
Android-first native client for a remote [Hermes Agent](https://github.com/NousResearch/hermes-agent) gateway/API server, with a legacy local companion retained for compatibility.
Hermes Mobile is a self-hosted phone UI for running Hermes from Android: chat prompts, browse/edit workspace files, run terminal commands, and check companion/Hermes status over a simple HTTP API.
The current beta path is a Kotlin/Jetpack Compose thin client that connects directly to an upstream Hermes gateway. Hermes remains authoritative for authentication, sessions, streaming, tools, and backend behavior.
## What Works Now
## Current Android Beta
- Vite React mobile app with Chat, Files, Terminal, Status, and Settings screens.
- Capacitor configuration and scripts for generating/building an Android APK.
- Fastify companion server with bearer-token auth and safe workspace-root file/terminal access.
- Local setup command that generates and persists an access key.
- HTTP API communication between the mobile app and companion server.
- Native Kotlin/Compose chat, session, settings, adaptive layout, and accessibility foundations.
- Direct HTTPS gateway configuration with bearer/no-auth support and local-first routing.
- Capability-gated session streaming and tool lifecycle output.
- Semantic Android beta metadata at `v0.1.0-beta.1`.
Build and clean-install instructions are in [Android Beta Build and Install](docs/ANDROID_BETA_BUILD.md). Device installation and the release criteria remain unverified until recorded on a real device or emulator.
## Monorepo
@@ -75,26 +76,13 @@ Tap **Test connection** to validate the server and key.
## Android APK Build
Install Android Studio/SDK/JDK, then generate the native Android project and build a debug APK:
Build the native direct-gateway client without Capacitor synchronization:
```bash
npm run cap:add:android --workspace @hermes-mobile/mobile
npm run android:build:debug --workspace @hermes-mobile/mobile
npm run android:build:debug
```
APK output:
```text
apps/mobile/android/app/build/outputs/apk/debug/app-debug.apk
```
For later rebuilds after the native project exists:
```bash
npm run cap:sync --workspace @hermes-mobile/mobile
cd apps/mobile/android
./gradlew assembleDebug
```
See [Android Beta Build and Install](docs/ANDROID_BETA_BUILD.md) for prerequisites, the versioned APK path, package checks, clean installation, direct-gateway setup, and known limitations.
## Companion API
+7 -2
View File
@@ -4,6 +4,9 @@ plugins {
id 'org.jetbrains.kotlin.plugin.compose'
}
def betaVersionName = '0.1.0-beta.1'
def betaVersionCode = 10001
android {
namespace 'cloud.molberg.hermesmobile'
compileSdk 35
@@ -12,8 +15,9 @@ android {
applicationId 'cloud.molberg.hermesmobile'
minSdk 23
targetSdk 35
versionCode 2
versionName '0.2.0-native'
versionCode betaVersionCode
versionName betaVersionName
setProperty('archivesBaseName', "hermes-mobile-v${betaVersionName}")
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
@@ -34,6 +38,7 @@ android {
}
buildFeatures {
buildConfig true
compose true
}
}
@@ -0,0 +1,13 @@
package cloud.molberg.hermesmobile
import org.junit.Assert.assertEquals
import org.junit.Test
class BetaPackageMetadataTest {
@Test
fun generatedMetadataMatchesFirstBetaIdentity() {
assertEquals("cloud.molberg.hermesmobile", BuildConfig.APPLICATION_ID)
assertEquals("0.1.0-beta.1", BuildConfig.VERSION_NAME)
assertEquals(10001, BuildConfig.VERSION_CODE)
}
}
+1 -1
View File
@@ -12,7 +12,7 @@
"cap:add:android": "cap add android",
"cap:sync": "npm run build && cap sync android",
"android:open": "cap open android",
"android:build:debug": "npm run cap:sync && cd android && ./gradlew assembleDebug"
"android:build:debug": "cd android && ./gradlew :app:testDebugUnitTest :app:assembleDebug"
},
"dependencies": {
"@hermes-mobile/shared": "file:../../packages/shared",
+94
View File
@@ -0,0 +1,94 @@
# Android Beta Build and Install
This guide covers the native Kotlin/Compose direct-gateway client at version `v0.1.0-beta.1`. It does not build or require `apps/companion`, publish an APK, or complete the beta release criteria by itself.
## Package identity
- Application ID: `cloud.molberg.hermesmobile`
- Android `versionName`: `0.1.0-beta.1`
- Android `versionCode`: `10001`
- Debug APK: `apps/mobile/android/app/build/outputs/apk/debug/hermes-mobile-v0.1.0-beta.1-debug.apk`
`versionName` is the user-visible semantic version. `versionCode` is an internal monotonically increasing Android package revision and must increase for every later installable build.
## Prerequisites
- JDK 17 or newer supported by the checked-in Android Gradle Plugin.
- Android SDK platform 35, matching build tools, and platform tools.
- Network access for the first dependency resolution, or a complete compatible Gradle cache.
- For installation, a real Android device with USB debugging enabled or a running emulator visible to `adb`.
- For use, an HTTPS upstream Hermes Agent gateway/API server and its bearer token when authentication is enabled.
Do not run Capacitor synchronization for this client. The beta application source is the native project under `apps/mobile/android`.
## Build and test
From the repository root:
```bash
cd apps/mobile/android
GRADLE_USER_HOME="$PWD/../../../.gradle-user" ./gradlew \
:app:testDebugUnitTest \
:app:assembleDebug
```
The expected APK is:
```text
app/build/outputs/apk/debug/hermes-mobile-v0.1.0-beta.1-debug.apk
```
Confirm the package metadata before distributing the file:
```bash
aapt dump badging app/build/outputs/apk/debug/hermes-mobile-v0.1.0-beta.1-debug.apk \
| sed -n '1p'
sha256sum app/build/outputs/apk/debug/hermes-mobile-v0.1.0-beta.1-debug.apk
```
Expected badging includes package `cloud.molberg.hermesmobile`, `versionCode='10001'`, and `versionName='0.1.0-beta.1'`.
The debug APK is signed with the local Android debug key. It is suitable for beta verification, not a production signing or store-release workflow. APKs and build output must remain untracked.
## Clean install and run
Confirm that exactly one intended target is attached:
```bash
adb devices -l
```
Remove any prior installation, then install the newly built APK. Uninstalling clears existing Hermes Mobile app data and stored gateway credentials.
```bash
adb uninstall cloud.molberg.hermesmobile || true
adb install app/build/outputs/apk/debug/hermes-mobile-v0.1.0-beta.1-debug.apk
adb shell monkey -p cloud.molberg.hermesmobile -c android.intent.category.LAUNCHER 1
```
In Hermes Mobile Settings, configure the upstream gateway directly:
1. Enter the required Remote HTTPS gateway base URL and, optionally, a Local HTTPS URL for the same trusted gateway.
2. Select bearer authentication and enter the gateway token when required, or select no authentication only when the gateway is configured that way.
3. Save and test the connection. The client probes `/health`, validates compatibility through the authenticated gateway surface, and displays the active Local or Remote route.
4. Exercise chat/session behavior only where the gateway advertises the required capabilities.
Do not enter a legacy companion URL or companion access key. The beta path is the direct upstream Hermes gateway architecture described in `docs/DIRECT_GATEWAY_ARCHITECTURE.md`.
## Required install evidence
Record all of the following before claiming R2 installation verification or a beta release:
- The source commit used for the build.
- Passing Android unit tests and APK assembly.
- `aapt` package/version output and the APK SHA-256.
- A successful clean `adb install` on a named real device or emulator.
- App launch plus direct-gateway configuration and connection result.
- Any observed limitations or failures, without treating source-only checks as device evidence.
## Known limitations
- R1 adaptive/accessibility verification still requires the documented real-device/emulator matrix.
- B3 remains blocked on an official session-search contract and live upstream gateway compatibility evidence.
- Direct gateway chat, streaming, tools, artifacts, and recovery remain capability-gated; unsupported or unverified routes are not inferred.
- The debug APK is not a published release artifact. No beta release exists until all release criteria in `docs/ROADMAP.md` are genuinely satisfied.
+8
View File
@@ -6,6 +6,14 @@ R1 cannot be marked complete from the current sandbox. On 2026-07-24, the requir
Required unblock evidence: run the required preflight and focused Android tests in an environment that permits them, then record the small-phone, normal-phone, and tablet checks in `docs/ROADMAP.md` across portrait/landscape, font scaling, TalkBack, light/dark contrast, touch targets, reduced motion, and IME behavior. Source review, `git diff --check`, and direct execution of cached test classes are supporting evidence only and do not complete R1.
## R2 — Clean beta build/install verification
The `v0.1.0-beta.1` Android package metadata and direct-gateway build/install guide are present in source. On 2026-07-24, the required recovery preflight passed and the source-current offline Gradle `:app:testDebugUnitTest :app:assembleDebug` command passed. Installation verification cannot be completed in the current sandbox.
ADB is installed, but the R1 evidence above confirms that its daemon sockets are prohibited and that no emulator executable, AVD, `/dev/kvm`, USB device bus, or running target is available. Therefore no source-current beta APK package inspection, clean uninstall/install, launch, or direct-gateway device connection was verified here. No APK was published or uploaded, and no final release criterion is claimed.
Required unblock evidence: in a permitted environment, run the preflight and Android checks from `docs/ANDROID_BETA_BUILD.md`, record `aapt` package/version output and the APK SHA-256, clean-install on one named real device or emulator, launch the app, configure the upstream Hermes gateway directly, and record the connection result in `docs/ROADMAP.md`.
## Stable gateway identity binding
The documented direct gateway routes currently available to Hermes Mobile (`GET /health` and authenticated `GET /v1/models`) do not expose a verified stable gateway instance identifier.
+5 -2
View File
@@ -12,6 +12,7 @@ Done:
- Capability-gated session streaming binds each OkHttp call to an immutable route/session lease, parses SSE into authoritative final responses, ignores cross-session events, and reports transport failure only against the failed lease.
- Chat UI supports conversation list/thread navigation, native composer, busy state, selectable replies, error bubbles, and new-chat reset.
- Direct gateway compatibility contract is documented in `docs/DIRECT_GATEWAY_ARCHITECTURE.md`.
- Android source packaging identifies the first beta as `versionName` `0.1.0-beta.1` / `versionCode` `10001`, produces a versioned debug APK name, and has a direct-gateway build/install guide in `docs/ANDROID_BETA_BUILD.md`.
- Legacy companion chat, terminal, and file utilities remain in the repo during migration but are not the target architecture.
- Local build artifacts, Android transient build output, `.gradle-user/`, and `.dev/` are ignored.
- Companion and workspace TypeScript typecheck, build, and lint pass as of 2026-07-24.
@@ -22,9 +23,9 @@ Remaining for beta:
- Exercise a real device or emulator against a running upstream Hermes gateway/API server.
- Verify direct gateway behavior end to end beyond B2: chat request/response, session continuity expectations, streamed/final output handling, and failure recovery.
- Verify or revise provisional session, streaming, tool-event, artifact, and cancellation route assumptions against official upstream docs.
- Add or run focused Android UI validation for chat/settings flows on small and large screens.
- Add or run focused Android UI validation for chat/settings flows on small and large screens in an environment with a permitted emulator or real device.
- Confirm adaptive accessibility: font scaling, TalkBack labels, contrast, keyboard/IME behavior, and reduced-motion tolerance.
- Document beta install/run steps after the native build is verified.
- Build the source-current `v0.1.0-beta.1` APK, verify its package metadata, and record a clean install, launch, and direct-gateway connection on a named real device or emulator.
## R1 Adaptive/Accessibility Matrix
@@ -42,6 +43,8 @@ Source-level evidence without device verification: orientation is no longer mani
## Beta Release Criteria
No beta release is claimed. Source packaging and documentation are complete, but APK assembly in this sandbox, clean installation, direct-gateway device exercise, R1, and B3 remain unverified or externally blocked.
- Native Kotlin/Compose Android app is the shipped beta client.
- No WebView, Capacitor runtime dependency, fake backend, embedded secrets, or new external infrastructure is introduced for beta.
- Direct gateway transport and auth are exercised against the upstream Hermes gateway/API server.