Gateway restart notices: explicit status{restarting} signal, correct timing
CI / Gateway plugin tests (push) Successful in 4m22s
CI / Kotlin tests (android host + desktop) (push) Successful in 7m41s

The app previously showed 'Gateway restarting' on every connection loss.
Now the gateway broadcasts status{state=restarting} on its shutdown path
(before closing the sockets), and the app:

- posts 'Gateway restarting' immediately on that frame (not on the
  socket-drop transition, which lags by the ~20s WS ping timeout)
- posts 'Gateway online' on the next reconnect only when the restart
  notice was posted (latch) - a plain network drop shows neither, just
  the reconnect banner
- drops the 'Gateway is restarting...' banner (replaced by the chat notice)

Docs (04-wire-protocol, frames.schema.json) updated: restarting is no
longer reserved. Test for the disconnect broadcast added to the local
hermes-agent test mirror (git-ignored, not committed).
This commit is contained in:
ARIA committed 2026-08-22 11:31:10 +02:00
1 parent 3a33f6be15
commit 6591d7cec0
6 files changed
+79 -33

No files matched your search

+7 -1
View File
@@ -280,7 +280,13 @@ messages only.
### `status`
Gateway health state. Broadcast to all connected clients at startup
(`state: "online"`); `restarting` / `degraded` are reserved for future use.
(`state: "online"`) and to late joiners on `hello.ack`. The gateway also
broadcasts `state: "restarting"` on its shutdown path (restart/stop), right
before closing the sockets — the app posts the "Gateway restarting" chat
notice immediately on that frame (the socket can take up to the ~20 s ping
timeout to actually drop, so the notice must not wait for the disconnect);
a plain network drop shows just the reconnect banner. `degraded` is reserved
for future use.
```json
{"type":"status","payload":{"state":"online"}}
+1 -1
View File
@@ -59,7 +59,7 @@
"search.results": { "payload": { "query": { "type": "string" }, "scope": { "type": "string", "enum": ["all", "chat"] }, "hits": { "type": "array", "items": { "type": "object", "properties": { "message_id": {"type":"string"}, "chat_id": {"type":"string"}, "thread_id": {"type":["string","null"]}, "role": {"type":"string"}, "snippet": {"type":"string"}, "ts": {"type":"integer"} } } } } },
"media.offer": { "description": "Agent-sent media available; app pulls bytes.", "payload": { "$ref": "#/definitions/media_ref" } },
"read.receipt": { "description": "Agent received and started processing the user's message; app shows ✓✓ on user bubbles. Emitted to the originating connection when a message.send is accepted for processing.", "payload": { "message_id": { "type": "string" } } },
"status": { "description": "Gateway health state; broadcast to all connected clients at startup (state=online).", "payload": { "state": { "type": "string", "enum": ["online", "restarting", "degraded"] } } },
"status": { "description": "Gateway health state; broadcast to all connected clients at startup (state=online) and to late joiners on hello.ack. state=restarting is broadcast on the gateway's shutdown path (restart/stop) before the sockets close; the app shows the 'Gateway restarting' chat notice only on that signal, not on a plain network drop.", "payload": { "state": { "type": "string", "enum": ["online", "restarting", "degraded"] } } },
"error": { "payload": { "code": { "type": "string", "enum": ["auth", "not_found", "rate_limited", "media_too_large", "unsupported", "internal"] }, "message": { "type": "string" } } },
"pong": { "payload": { "ts": { "type": "integer" } } },
"sync.done": { "payload": { "cursor": { "type": "integer" } } },