Files
meatbag/handoffs/2026-06-30-desktop-agent-handoff.md

203 lines
5.1 KiB
Markdown
Raw Permalink Normal View History

2026-06-30 17:31:59 -06:00
# Meatbag Desktop Agent Handoff
Date: 2026-06-30
Project: Meatbag
Ecosystem: WhetForge
Repository: http://localhost:3000/bill/meatbag
Branch: main
## Current State
Meatbag is a Kotlin/Compose Multiplatform MVP scaffold for a "Human Latency Optimization Tool." The intended flow is:
1. CLI agent or script sends an SDUI request to the backend.
2. Ktor backend evaluates active devices and user attention rules.
3. Backend pushes a JSON UI payload over WebSocket to the best device.
4. Human taps a response.
5. Client posts the response back to the backend.
6. Backend completes the pending agent callback.
The repository has three modules:
- `common`: shared kotlinx.serialization models for SDUI primitives, attention tiers, device context, callbacks, and responses.
- `backend`: stateful Ktor backend with in-memory device registry and routing engine.
- `client`: Compose Multiplatform stateless renderer and desktop simulator, plus Android/Wear attention hook scaffolding.
## Important Commit
Initial pushed commit:
```text
8b4cb8e Initialize Meatbag SDUI platform
```
This handoff should be committed after that initial push.
## Gitea Notes
The actual Gitea is containerized in Colima/Docker:
- URL: `http://localhost:3000`
- Repo: `http://localhost:3000/bill/meatbag`
- Container name: `gitea`
- SSH exposed by container: host port `2222` to container port `22`
If `localhost:3000` is down, check:
```sh
colima status
colima start
docker ps
```
Do not use the old top-level `/Users/blindmouse/gitea_setup.sh` as the source of truth. That was an older non-container setup path.
## What Works Conceptually
- `common/src/commonMain/kotlin/meatbag/common/UiPrimitive.kt`
- Strict sealed serializable SDUI model hierarchy:
- `ApprovalRequest`
- `ActionList`
- `TextInput`
- `Message`
- Attention schema:
- `SILENT_HAPTIC`
- `BACKGROUND_NOTIFICATION`
- `OVERRIDE_SCREEN`
- Payload/context types:
- `WebSocketPayload`
- `AttentionPolicy`
- `DeviceContext`
- `CallbackRequest`
- `ApprovalResponse`
- `backend/src/main/kotlin/meatbag/backend/RoutingEngine.kt`
- In-memory pending request map.
- Mock `UserRuleSet`.
- Watch-first routing for silent haptics.
- Override-screen fan-out to multiple active devices.
- Enriched payload context per target device.
- `backend/src/main/kotlin/meatbag/backend/Application.kt`
- `GET /api/status`
- `POST /api/request`
- `POST /api/respond`
- `WS /ws/connect?deviceType=WEAR_OS_WATCH|PHONE|DESKTOP`
- `client/src/commonMain/kotlin/meatbag/client/ComponentRegistry.kt`
- Stateless UDF renderer.
- No reflection.
- Typed `ComponentIntent` out, converted to `ApprovalResponse` at the client boundary.
- `client/src/desktopMain/kotlin/meatbag/client/Main.kt`
- Desktop simulator for local payload testing and WebSocket connection testing.
## Not Ready Yet
The repo is not yet a ready-to-install Android/Wear app for an S23 Ultra or watch.
Missing pieces:
- Android app packaging:
- `AndroidManifest.xml`
- `MainActivity`
- Compose app bootstrap for `MeatbagClient`
- internet permission
- cleartext HTTP allowance for local backend testing
- Wear app packaging:
- Wear entry point
- manifest
- real haptic implementation using Android vibrator APIs
- watch-specific UI constraints
- Build verification:
- Previous environment did not have a Java runtime available, so Gradle tests/builds were not run successfully.
## Recommended Next Task
Make the Android phone client installable first, then add Wear OS.
Suggested sequence:
1. Install/confirm JDK 17 on the machine doing the build.
2. Run:
```sh
./gradlew :common:jvmTest :backend:test :client:compileKotlinDesktop
```
3. Fix any compile issues from the recent scaffold.
4. Add Android app entry:
- `client/src/androidMain/AndroidManifest.xml`
- `client/src/androidMain/kotlin/meatbag/client/MainActivity.kt`
- Compose root that uses `MeatbagClient`
- host/IP configuration for the backend
5. Verify an S23 can connect to:
```text
ws://<computer-lan-ip>:8080/ws/connect?deviceType=PHONE
```
6. Add Wear OS entry after phone works:
```text
ws://<computer-lan-ip>:8080/ws/connect?deviceType=WEAR_OS_WATCH
```
7. Wire `WearAttentionFeedback` to real haptic APIs.
## Local Backend Smoke Test Shape
Once backend runs on the computer:
```sh
./gradlew :backend:run
```
Connect a client WebSocket:
```text
ws://localhost:8080/ws/connect?deviceType=WEAR_OS_WATCH&deviceId=watch_1
```
Send an approval request:
```sh
curl -X POST 'http://localhost:8080/api/request?urgent=true' \
-H 'Content-Type: application/json' \
-d '{
"type": "ApprovalRequest",
"id": "req_1",
"prompt": "Allow agent to continue?",
"target": "desktop-agent"
}'
```
Respond:
```sh
curl -X POST 'http://localhost:8080/api/respond' \
-H 'Content-Type: application/json' \
-d '{
"requestId": "req_1",
"approved": true
}'
```
## Caution
There is a mistakenly downloaded standalone Gitea binary at:
```text
/Users/blindmouse/bin/gitea
```
And old non-container setup files under:
```text
/Users/blindmouse/gitea
```
Those are not the active Gitea. The active Gitea is the Docker container named `gitea`.