-
Notifications
You must be signed in to change notification settings - Fork 29
feat(agent_manager): add pagination and lazy loading for chat history (#116) #124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
AmitAvital1
merged 11 commits into
extra-org:main
from
rishu685:feat/issue-116-chat-history-pagination
Aug 23, 2026
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
984eb09
feat(agent_manager): add pagination and lazy loading for chat history…
rishu685 1853252
Merge origin/main into feat/issue-116-chat-history-pagination
rishu685 032ee04
test(agent_manager): update test_api for paginated conversations resp…
rishu685 3147504
build(widget): rebuild widget bundle for chat history pagination
rishu685 d25be31
test(e2e): update Playwright route mocks for paginated conversations …
rishu685 3b2c7b0
fix(agent_manager): address review feedback on pagination for PR #124…
rishu685 1bc0a4f
refactor(agent_manager): fix architecture layering and pagination rev…
rishu685 ace375d
docs(adr): add ADR 0003 for chat history keyset pagination
rishu685 b5e7578
fix(widget): add drawer error notice and retry UI, and expand contrac…
rishu685 a8f8352
fix(test): resolve mypy typecheck errors in test_repository_contract.py
rishu685 df28800
docs(adr): rename ADR 0003 to 0003-cursor-pagination-and-list-respons…
rishu685 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
39 changes: 39 additions & 0 deletions
39
docs/adr/0003-cursor-pagination-and-list-response-envelope.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| # ADR 0003 — Cursor pagination and list response envelope | ||
|
|
||
| - **Status:** Accepted | ||
| - **Date:** 2026-08-23 | ||
|
|
||
| ## Context | ||
|
|
||
| `GET /conversations` previously returned a flat, unbounded list of all conversations for a user. As conversation counts grow per user, loading the complete list in one request causes high latency, database scan overhead, and excessive payload sizes for clients. | ||
|
|
||
| Additionally, simple offset pagination (`OFFSET N`) suffers from severe database performance degradation on large offsets and produces inconsistent results (skipped or duplicated rows) if conversations receive messages or are created while a user is paginating. | ||
|
|
||
| ## Decision | ||
|
|
||
| 1. **Keyset Cursor Pagination**: | ||
| - `GET /conversations` uses keyset pagination based on the composite ordering key `(COALESCE(last_message_at, created_at) DESC, session_id DESC)`. | ||
| - The active timestamp `COALESCE(last_message_at, created_at)` ensures empty conversations without messages sort predictably by their creation time alongside active threads. | ||
|
|
||
| 2. **Opaque Base64 Cursor Token**: | ||
| - Cursors are opaque server tokens containing base64-encoded JSON `{"t": "<iso8601_utc_timestamp>", "id": "<session_id>"}`. | ||
| - The pagination token codec (`encode_cursor`, `decode_cursor`) and exception `InvalidCursorError` live in `agent_manager.domain.pagination` (pure Python domain value objects and utilities with zero framework dependencies). | ||
| - Malformed or invalid cursor tokens raise `InvalidCursorError`, which is mapped by `as_http_error()` to `HTTP 400 Bad Request` with payload `{ "error_type": "invalid_cursor", "message": "invalid pagination cursor" }`. | ||
|
|
||
| 3. **Domain Layer Bounds**: | ||
| - `PageRequest` value object encapsulates pagination parameters (`limit`, `cursor`). | ||
| - Default page size is 20 (`DEFAULT_PAGE_LIMIT`) and maximum page limit is 100 (`MAX_PAGE_LIMIT`), enforced at domain instantiation time in `PageRequest.__post_init__`. | ||
|
|
||
| 4. **Database Indexing**: | ||
| - Migration `0005_add_session_pagination_index.py` and `tables.py` add an expression index `idx_conversation_sessions_user_active_session` on `(user_id, COALESCE(last_message_at, created_at), session_id)` to enable fast index range seeks for keyset pagination. | ||
|
|
||
| ## Contract changes | ||
|
|
||
| - **BREAKING CHANGE**: `GET /conversations` response shape changed from a flat list `[ConversationSummary, ...]` to a paginated envelope object `{ "items": [ConversationSummary, ...], "next_cursor": "..." | null }`. | ||
| - `GET /conversations` accepts optional query parameters `limit` (integer, 1..100) and `cursor` (opaque string). | ||
|
|
||
| ## Consequences | ||
|
|
||
| - Clients fetch subsequent pages using `next_cursor` until `next_cursor` is `null`. | ||
| - Keyset range seeks eliminate `OFFSET` database performance degradation and prevent skipped/duplicated sessions when thread activity changes mid-page. | ||
| - Frontends deduplicate threads by `conversation_id` to handle live thread updates gracefully. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.