#19754: feat(webchat): add cursor-based pagination to chat.history
app: web-ui
gateway
size: S
## Summary
Adds backward cursor-based pagination to `chat.history` so users can scroll back to the beginning of long conversations.
**Discussion**: #19753
- **Server**: New optional `before` parameter returns messages preceding a given index. Response now includes `cursor` (index of first returned message) and `hasMore` (whether older messages exist). Fully backward-compatible.
- **Client**: Detects when user scrolls near the top of the chat thread and automatically fetches the previous page, preserving scroll position. Shows a "Loading older messages..." indicator.
Bounded by the existing 1000-message hard max. Does not add virtual scrolling (see PR #16020).
Related: #19060, #13703, PR #19343
## Test plan
- [x] Extended existing e2e test (300 messages) to verify `before` cursor returns messages 0-99 after initial load returns 100-299
- [x] Verified `cursor` and `hasMore` fields in both default and paginated responses
- [x] Session-switch safety: stale responses discarded if session changes mid-fetch
- [x] TypeScript compiles cleanly (0 errors)
- [x] All 439 gateway tests pass
AI-assisted (Claude Code). Tested via TypeScript compilation and gateway unit/integration test suite. Full build + e2e require Node >= 22 (environment has Node 20).
---
🤖 [Tackled](https://github.com/aleiby/claude-skills/tree/main/tackle) with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Adds backward cursor-based pagination to `chat.history`, allowing users to scroll back through long conversations. The server-side changes introduce `before`, `cursor`, and `hasMore` fields — well-structured and backward-compatible. The client detects when the user scrolls near the top and fetches older pages, preserving scroll position. Session-switch safety is handled via a session key check.
- **Critical**: The client-side `CHAT_HISTORY_RENDER_LIMIT` (200) in `buildChatItems` (`ui/src/ui/views/chat.ts:485`) renders only the last 200 messages from the `chatMessages` array. Since `loadOlderChatHistory` *prepends* older messages, they are immediately excluded by this render cap — making the pagination UI-invisible. This needs to be addressed for the feature to work as intended.
- **Minor**: The `onLoadOlderMessages` callback fires on every scroll event while near the top. After scroll-position restoration, this could trigger rapid successive fetches. A debounce or cooldown would be more robust.
- Server-side cursor math, schema changes, and test coverage look correct. The e2e test properly validates the `before` cursor and `hasMore` semantics.
<h3>Confidence Score: 2/5</h3>
- The server-side pagination is correct, but the client-side rendering bug means older messages will never be visible to users.
- The core client-side feature is broken: CHAT_HISTORY_RENDER_LIMIT in buildChatItems caps rendering to the last 200 messages, so prepended older messages from pagination are never displayed. The server-side changes are clean and well-tested, but the end-to-end feature does not work.
- ui/src/ui/views/chat.ts (render limit conflicts with pagination), ui/src/ui/app-scroll.ts (debounce concern)
<sub>Last reviewed commit: 5b5c695</sub>
<!-- greptile_other_comments_section -->
<sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#14966: fix(webchat): preserve user message visibility after chat.send
by BenediktSchackenberg · 2026-02-12
77.3%
#7522: fix(webchat): auto-scroll when message queue changes
by alsoknownasfoo · 2026-02-02
76.8%
#19722: feat(chat): add search functionality for chat history
by aleiby · 2026-02-18
76.0%
#20347: fix(webchat): resolve streaming scroll race condition
by ndaemy · 2026-02-18
75.3%
#11711: feat(webui): add terminal-style input history navigation
by stephenschoettler · 2026-02-08
74.7%
#20211: feat(webchat): add search UI for chat history
by aleiby · 2026-02-18
74.6%
#22798: feat(webchat): ChatGPT-style multi-chat threads with generated titles
by opnsec · 2026-02-21
74.4%
#15110: fix: enable auto-scroll during assistant response streaming
by jwchmodx · 2026-02-13
73.7%
#16020: perf(ui): virtualize chat message list for large conversations
by fagemx · 2026-02-14
73.5%
#21693: feat(gateway): expose session entry id on chat history messages
by tlxue · 2026-02-20
73.5%