HTTP transport: drop WS server, offline send queue + dead-stream watchdog
Gateway (docs/19): - Remove ws_server.py; frame dispatch factored into dispatch.py - http_server: media upload/pull, pairing over HTTP - protocol: media frames mirrored; tests + ws_probe updated for HTTP App: - HttpGateway: postFrame/uploadMedia/pullMedia no longer throw on network failure (PostResult ok=false / Result.failure) — uncaught SocketTimeoutException on Dispatchers.Default crashed the app - GatewayClient: dead-stream watchdog (health probe every 10s, 2 failures -> redial in ~20s instead of the 45s SSE read timeout); state flips to Reconnecting when the stream dies, restored from the last hello.ack on long-poll success; poke() + backoff reset on app resume (MainActivity.onResume) - Offline sends: composer enabled while disconnected; a send with no response (status 0) stays queued (Pending) and is auto-resent on the next (re)connect after a 2s outbox-replay grace; gateway 4xx rejections fail the bubble (tap to retry, no auto-loop) - ChatStore: echo-replace and thread-relocate also match Failed bubbles (POST response lost in a network drop); loadHistory dedupes local failed bubbles the server already has; failMessage() - MainActivity: poke() on resume so a backgrounded app reconnects promptly instead of waiting out the backoff
This commit is contained in:
1 parent
2349a95dd4
commit
e6015033b6
22 files changed
+2804
-2439
No files matched your search
@@ -26,11 +26,8 @@ PROTOCOL_VERSION = 1
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Pairing / lifecycle
|
||||
TYPE_HELLO = "hello"
|
||||
TYPE_HELLO_ACK = "hello.ack"
|
||||
TYPE_ERROR = "error"
|
||||
TYPE_PING = "ping"
|
||||
TYPE_PONG = "pong"
|
||||
|
||||
# Chat
|
||||
TYPE_MESSAGE = "message"
|
||||
@@ -82,12 +79,8 @@ TYPE_SYNC_DONE = "sync.done"
|
||||
TYPE_HISTORY = "history"
|
||||
|
||||
# Media (M4)
|
||||
TYPE_MEDIA_UPLOAD_START = "media.upload.start"
|
||||
TYPE_MEDIA_UPLOAD_END = "media.upload.end"
|
||||
TYPE_MEDIA_UPLOAD_ACK = "media.upload.ack"
|
||||
TYPE_MEDIA_OFFER = "media.offer"
|
||||
TYPE_MEDIA_PULL = "media.pull"
|
||||
TYPE_MEDIA_PULL_END = "media.pull.end"
|
||||
|
||||
# Push / notifications (M5)
|
||||
TYPE_NOTIFICATION = "notification"
|
||||
@@ -749,7 +742,8 @@ def media_offer(
|
||||
thread_id: str | None = None,
|
||||
message_id: str | None = None,
|
||||
) -> Frame:
|
||||
"""Event: the agent produced media the app can fetch via ``media.pull``.
|
||||
"""Event: the agent produced media the app can fetch via
|
||||
``GET /v1/media/{media_id}`` (docs/19 §19.15).
|
||||
|
||||
``message_id`` (optional) associates the offer with the assistant message
|
||||
it belongs to (the app falls back to the lane's last assistant message).
|
||||
@@ -766,14 +760,9 @@ def media_offer(
|
||||
return Frame(type=TYPE_MEDIA_OFFER, chat_id=chat_id, thread_id=thread_id, payload=payload)
|
||||
|
||||
|
||||
def media_pull_end(ok: bool, *, id: int | None = None) -> Frame:
|
||||
"""Terminal frame of a ``media.pull`` binary stream."""
|
||||
return Frame(type=TYPE_MEDIA_PULL_END, id=id, payload={"ok": ok})
|
||||
|
||||
|
||||
def media_upload_ack(ok: bool, media_ref: str, *, id: int | None = None) -> Frame:
|
||||
"""Response to ``media.upload.end``: the ref is cached and may be used in
|
||||
a ``message.send`` ``media_refs``. Failures use ``error`` frames instead."""
|
||||
"""Response to ``POST /v1/media``: the ref is cached and may be used in a
|
||||
``message.send`` ``media_refs``. Failures use ``error`` frames instead."""
|
||||
return Frame(
|
||||
type=TYPE_MEDIA_UPLOAD_ACK,
|
||||
id=id,
|
||||
@@ -783,10 +772,3 @@ def media_upload_ack(ok: bool, media_ref: str, *, id: int | None = None) -> Fram
|
||||
|
||||
def error(code: str, message: str, *, id: int | None = None) -> Frame:
|
||||
return Frame(type=TYPE_ERROR, id=id, payload={"code": code, "message": message})
|
||||
|
||||
|
||||
def pong(ts: int | None = None) -> Frame:
|
||||
payload: dict[str, Any] = {}
|
||||
if ts is not None:
|
||||
payload["ts"] = ts
|
||||
return Frame(type=TYPE_PONG, payload=payload)
|
||||
Reference in new issue
Block a user