web: open Agent at recent history and load older pages on demand

This commit is contained in:
2026-10-16 21:18:15 -07:00
parent 671ee98ab1
commit 7b48201e28
9 changed files with 490 additions and 28 deletions
+22
View File
@@ -605,6 +605,28 @@ durable entries and can advance without visible messages. Use returned cursors;
do not derive them from message IDs. `limit` bounds source entries, not displayed
messages.
The web Agent starts with one cursorless `limit=100` window and renders it in
chronological order, initially positioned at its newest end. `hasMore` on this
window or a `before` page means **older** source entries exist; on an `after`
page it means **newer** entries remain. Each **Load older messages** action fetches
one `before=<beforeCursor>&limit=100` page, even if that page has no visible rows.
Older pages do not advance the live replay/read cursor or overwrite newer copies
of the same message. Initial loading never walks forward from zero or drains
older history. Reconnect recovery still follows `after` from the accepted live
cursor. Aborted/replaced room sessions discard late responses.
Web unread counts cover loaded public replies. A `+` suffix (or a dot when no
loaded reply is known unread) indicates that earlier messages may also be unread;
the API does not supply an exact total for unloaded history. Observing the latest
end in a focused visible conversation marks it read through that rendered cursor,
including earlier unloaded history. Fetching or reading older pages does not
acknowledge newer replies. An internal-only window with no rendered public
messages does not acknowledge history; older loading remains an explicit action.
Initial source-entry/network work is bounded; retained
messages/DOM grow with explicit older loads and live updates. Offscreen web rows
use CSS `content-visibility: auto`, which skips rendering work while retaining
chronological DOM, selection, find and accessibility; it is not DOM virtualization.
### `POST /v1/agent/messages`
Body: `{ "content": "Check the oven", "requestId": "client-generated-uuid" }`.
+12
View File
@@ -337,6 +337,18 @@ The proxy closes upstream sockets when browsers leave or Sybil shuts down.
History remains durable in Sybil Agent. Shared read position is separate from delivery:
update `GET`/`PUT /v1/agent/read-state` only when messages have actually been viewed.
The web client first accepts source-bound read state and one recent REST history
window, then authenticates this socket with that window's `cursor`. Initial
`hasMore` refers to older history and does not trigger a forward replay from zero.
Older pages load on demand using a separate `beforeCursor`; delayed older pages
preserve live edits and never change the socket replay position. Reconnects and
foreground catch-up use the last accepted live cursor as before. Incoming output
follows the viewport only while it is pinned to the newest end; older prepends and
dynamic heights preserve the reader's keyed row. Only a focused, visible, settled
latest view acknowledges the rendered cursor, marking the conversation read
through that point. See [web history windows and unread counts](rest.md#get-v1agentmessages)
for unloaded-history count semantics and rendering limits.
### Agent attachment history, queued activity and replay
Uploads and attached sends use REST, as specified in [rest.md](./rest.md#agent-attachments-v1). WebSocket authentication, event types, stable message IDs, cursor semantics and raw tool rows are unchanged. Capability discovery is optional `GET /v1/agent` → `capabilities.attachments.version: 1`; absence disables new attachment sends. Upgrade/authenticate the native runtime and backend before advertising it.