HTTP fallback leg (docs/19): POST /v1/frame + SSE /v1/events + long-poll

Second, short-lived-connection transport next to the WS: same frames,
same outbox/cursor, same token, served over plain HTTP (stdlib
ThreadingHTTPServer bridged into the asyncio loop; zero new deps).

- http_server.py: /v1/health (unauthenticated), POST /v1/frame
  (accept-and-ack; validation rejections as 4xx error frames), SSE
  /v1/events (outbox catch-up with id=cursor, event: hello, 15s
  heartbeat, bounded-queue backpressure), long-poll /v1/poll (25s hold).
  Bearer token + X-Iris-Device (same allowlist as WS hello), 64 KiB body
  cap, per-device rate limit, optional TLS, non-fatal bind failure.
- ws_server.py: inbound dispatch chain extracted to shared
  dispatch_frame() used by both transports.
- adapter.py: ANDROID_HTTP_PORT/CERT/KEY config; start/stop next to the
  WS; delivery counting in _broadcast_or_log (an SSE subscriber is a
  live subscriber -> no push, docs/19 19.8); _reply() routes
  point-to-point replies into the in-flight HTTP response (reply sink)
  or broadcasts when the device has no live WS (19.7); status/typing/
  channel events fan out to both transports.
- ws_probe.py: --http mode (health + POST + SSE turn drive, same
  assertion flags); tests/README updated.
- Tests: hermes-agent/tests/gateway/test_android_http.py (23 tests,
  incl. the 19.8 delivery-counting regression); test_android.py (74)
  still green.
This commit is contained in:
ARIA committed 2026-08-22 14:10:14 +02:00
1 parent 524ed8ce53
commit e5c7d690b8
7 files changed
+1315 -89

No files matched your search

+5 -2
View File
@@ -8,6 +8,7 @@ This folder is the single source of truth for *what to build and why*. Read it
top-to-bottom once, then use the numbered docs as a lookup while implementing.
> ⚠️ **READ FIRST — two hard rules**
>
> 1. **`hermes-agent/` (sibling of this folder) is a read-only research
> reference. It must NEVER be committed, pushed, or shipped.** It is
> git-ignored at the repo root. We only *install* our plugin into a live
@@ -20,7 +21,7 @@ top-to-bottom once, then use the numbered docs as a lookup while implementing.
## Reading order
| # | File | When to read |
|---|------|--------------|
| --- | ------ | -------------- |
| 0 | [`00-overview.md`](00-overview.md) | Always first. Vision, scope, disclaimers, locked decisions. |
| 1 | [`01-architecture.md`](01-architecture.md) | Before touching code. System shape + rationale. |
| 2 | [`02-monorepo.md`](02-monorepo.md) | When scaffolding the repo. |
@@ -39,8 +40,10 @@ top-to-bottom once, then use the numbered docs as a lookup while implementing.
| 15 | [`15-hermes-reference.md`](15-hermes-reference.md) | **Cheat-sheet** of hermes-agent source to read. |
| 16 | [`16-open-questions.md`](16-open-questions.md) | Decisions made + open items. |
| 17 | [`17-future-control-surface.md`](17-future-control-surface.md) | **Backlog** — what the app could control beyond chat (cron, kanban, models, …). |
| 19 | [`19-http-fallback-transport.md`](19-http-fallback-transport.md) | **Design** — HTTP fallback leg (POST + SSE/long-poll) so the app can send/receive when the WS is down. |
Machine-readable / diagrams:
- [`protocol/frames.schema.json`](protocol/frames.schema.json) — wire-frame schema.
- [`diagrams/architecture.mmd`](diagrams/architecture.mmd) — mermaid architecture.
@@ -65,4 +68,4 @@ project** (`app/`) with a shared KMP module (`app/shared`).
- **Phase:** M0–M6 complete; M7 (polish + E2E + docs) in progress.
- **Owner decisions locked:** see [`16-open-questions.md`](16-open-questions.md).
- **Last updated:** 2026-08-19.
- **Last updated:** 2026-08-19.