Skip to content

Open chat history at any message, and page towards the present (GRYT-1686) - #282

Merged
sivert-io merged 1 commit into
mainfrom
claude/GRYT-1686-history-window
Oct 6, 2026
Merged

sivert-io merged 1 commit into
mainfrom
claude/GRYT-1686-history-window

Conversation

@sivert-io

@sivert-io sivert-io commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

The server half of opening chat history at any message, instead of paging back to it. Task: GRYT-1686. The client half is client#812. It falls back to paging on a server without this, so the two can land in either order.

What changed

chat:fetch takes two more options:

  • around: <message id> returns half a page each side of that message, plus the message itself. anchorFound comes back false when the message is gone or is a thread reply.
  • after: <ISO time> returns the next page, oldest first, for scrolling down from an old window towards the present.

Both answers carry hasNewer, and the client merges its window back into the channel's list once that's false. A request with neither option gets exactly the response it always did.

listMessagesAfter in src/db/sqlite/messages.ts is the only new query. It mirrors listMessages: created_at > and ascending.

Look at

  • src/db is review-required. The query is one prepared statement with the same conversation_id / thread_id IS NULL filters as listMessages, using the existing (conversation_id, created_at) index.
  • A behaviour change: the page limit is now capped at 100. It used to be whatever the client sent, so one request could pull a whole channel. The apps send 50.
  • Same-timestamp ties. Both halves cut strictly on created_at, like before already did, so a message sharing the anchor's exact millisecond would be skipped. That's the existing pagination behaviour, not new.
  • Access, rate limiting and blocked senders all run before the new branches, the same as for before.

Tested

  • messagesWindow.test.ts: forward pages, thread replies left out, a short last page, the two halves joining around a message with no gap or repeat, and a forward walk covering all 30 messages exactly once. The full suite passes (1,991).
  • End to end with the client branch on a seeded channel (220 messages, a pin on the 4th):
    • opening the pin returned 29 rows around it, in about 1.7 s
    • four after pages reached the present, and the window merged
  • The same client against main's server (no around) fell back to paging and found it in about 4 s.

🤖 Generated with Claude Code

…1686)

chat:fetch could only page backwards, with `before`. Jumping to an old
pin or reply meant loading every page in between, and the client gave
up after 1,000 messages.

It now takes two more options:

- `around: <message id>` returns half a page each side of that message,
  with the message itself. `anchorFound` is false when it's gone or is
  a thread reply.
- `after: <time>` returns the next page, oldest first, for scrolling
  down from an old window towards the present.

Both answers carry `hasNewer`, so the client knows when it has reached
the newest message. A request that uses neither gets exactly the
response it always did, which keeps older clients working.

listMessagesAfter is the one new query: the mirror of listMessages,
with `created_at >` and ascending order. The test checks that the two
halves join around a message with no gap or repeat, and that paging
forward walks the whole channel once.

The page limit is now capped at 100. It was whatever the client sent.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@sivert-io
sivert-io merged commit b70bab3 into main Oct 6, 2026
6 checks passed
@sivert-io
sivert-io deleted the claude/GRYT-1686-history-window branch October 6, 2026 20:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant