opencode icon indicating copy to clipboard operation
opencode copied to clipboard

feat(session): bi-directional cursor-based pagination (#6548)

Open CasualDeveloper opened this issue 6 days ago • 3 comments

Summary

This PR implements bi-directional cursor-based pagination for message loading to support long session histories without performance degradation. Closes #6548.

  • Backend: before/after/oldest cursor support with RFC 5005 Link headers
  • TUI: Infinite scroll with memory bounding (500 messages), Home/End jump navigation
  • Tests: 18 tests across 3 test files

Context

Supersedes #6656 by @ry2009 (earlier partial implementation). This PR is a ground-up rewrite that adds:

  • Bi-directional pagination (both before and after cursors)
  • oldest param for jumping to beginning of history
  • Proper parseLinkHeader utility instead of brittle string matching
  • Memory bounding to prevent unbounded growth
  • Error state feedback instead of silent failures
  • RFC 5005 compliant Link header semantics

Changes

Backend (session/index.ts, server/server.ts, message-v2.ts)

  • Add before, after, and oldest cursor params to Session.messages()
  • Add ascending option to MessageV2.stream() for oldest-first iteration
  • Add Binary.lowerBound to util for efficient cursor lookup
  • Return 400 when mutually exclusive cursors specified
  • RFC 5005 Link headers: rel="prev" → older, rel="next" → newer

TUI (sync.tsx, routes/session/index.tsx)

  • message_page state tracking (hasOlder, hasNewer, loading, error)
  • loadOlder/loadNewer with scroll position restoration
  • jumpToOldest (Home key) / jumpToLatest (End key) for absolute navigation
  • Revert-aware: jumpToLatest preserves revert marker when jumping to newest
  • 500-message sliding window with 50-message eviction chunks
  • Skip SSE inserts when detached from head (hasNewer=true)
  • Race condition prevention: check page state before acquiring loading guard

Tests

File Tests Coverage
messages-pagination.test.ts 5 Cursor, boundary, deletion
session-messages.test.ts 6 API validation, Link headers, oldest param
parse-link-header.test.ts 9 RFC 8288 parsing edge cases

Testing

bun test test/session/messages-pagination.test.ts test/server/session-messages.test.ts test/util/parse-link-header.test.ts
# 18 pass, 0 fail

Related

  • Closes #6548
  • Supersedes #6656
  • Related: #6137, #6138 (message_limit config — this makes that less necessary)

CasualDeveloper avatar Jan 14 '26 19:01 CasualDeveloper