Files
clawdbot/docs/webchat.md
2025-12-08 11:25:00 +01:00

57 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Web Chat architecture (local + remote)
Date: 2025-12-08 · Status: draft plan
## Goal
- Serve the Clawdis Web Chat UI from the Node relay (loopback-only HTTP), while the macOS app keeps the same UX by embedding it in a WKWebView.
- Keep remote mode working: when Clawdis runs on a remote host via SSH, the mac app should still show the web chat backed by that remote relay (via an SSH tunnel).
## Proposed architecture
1) **Server location**
- A tiny HTTP server lives in the Node relay process.
- Bind to 127.0.0.1 on a chosen port (fixed or random with discovery endpoint).
- Serve static assets for `/webchat/` and a JSON RPC endpoint for sending messages.
2) **Endpoints**
- `GET /webchat/*`: serves bundled web assets (current WebChat build, moved from mac bundle into the Node package, e.g., `src/webchat/dist`).
- `GET /webchat/info`: returns `{ baseUrl, token? }` for the mac app to embed (token optional; see security below).
- `POST /webchat/rpc`: accepts `{ text, session, thinking?, deliver?, to? }` and replies with `{ ok, payloads?, error? }`. Internally calls the same agent pipeline that `clawdis rpc` uses today (in-process, no subprocess).
- (Optional) `GET /webchat/history?session=<key>`: returns pre-serialized message history so the mac app doesnt scrape JSONL. Can be folded into `/webchat/info` as an `initialMessages` field.
3) **Sessions & history**
- Use the relays own session store (default `~/.clawdis/sessions/sessions.json` on the relay host). No SSH file reads from the mac app anymore.
- When the page loads, it receives `initialMessages` from the server (either embedded in `info` or via a history endpoint).
- Remote mode automatically shows the remote session because the remote relay owns that store.
4) **Mac app embedding**
- On WebChatWindow init, the mac app calls `/webchat/info`:
- Local mode: directly over loopback (127.0.0.1:port chosen by relay).
- Remote mode: establish/reuse an SSH tunnel forwarding the relays webchat port to a local ephemeral port, then call `/webchat/info` through the tunnel and load the returned `baseUrl`.
- WKWebView loads `baseUrl` (e.g., `http://127.0.0.1:<forward>/webchat/`).
- Web page sends messages to `/webchat/rpc` (same origin as the static assets), so no extra mac plumbing.
5) **Security**
- Bind to loopback only. For extra hardening, issue a random short-lived token in `/webchat/info` and require it as a header/query on `/webchat/rpc` and history.
- Remote mode relies on SSH port forwarding; no WAN exposure.
6) **Failure handling**
- If `/webchat/info` fails, show an in-app error (“Web chat server unreachable”).
- Log the chosen port/URL and tunnel target in mac logs for debugging.
- History fetch failures fall back to an empty transcript but keep sending enabled.
7) **Migration steps**
- Move WebChat bundle into the Node project (e.g., `src/webchat/dist`) and serve statically.
- Add the loopback HTTP server and `/webchat` routes to the relay startup.
- Expose `/webchat/info` (port + token + optional initialMessages).
- Mac app: replace local asset load with the fetched `baseUrl`; use SSH tunnel in remote mode.
- Remove mac-side JSONL scraping and `AgentRPC` usage for web chat; keep other agent uses intact.
- Tests: webchat loads + sends in local and remote modes; tunnel discovery works; history returns non-empty when sessions exist.
8) **Current behavior (for reference, to be replaced)**
- Mac app reads remote session files over SSH (`clawdis sessions --json`, then `cat` the `.jsonl`) and injects history; sends via `clawdis rpc` subprocess. This document tracks the plan to move both pieces into the relay server instead.
## Open questions
- Fixed port vs random per run? (Random + info endpoint is safer.)
- Token enforcement default on/off? (Recommended on when remote tunneling isnt used.)
- Should `/webchat/rpc` also expose typing/streaming? (Nice-to-have; not required for parity.)