M1: Add composite DB index and getMessagesPaginated()#21562
Conversation
…istory pagination Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 65a6cec0bb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Re: tie-breaker cursor — this is explicitly scoped out as a follow-up hardening task. Re: no callers — correct, these are introduced ahead of M2 (#21553) which wires them into |
* feat: add composite DB index and getMessagesPaginated() for message history pagination (#21562) Co-authored-by: Vellum Assistant <assistant@vellum.ai> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * M2: Wire pagination into handleListMessages HTTP endpoint (#21569) * feat: wire server-side pagination into handleListMessages HTTP endpoint Part of #21550 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: gate pagination fields behind isPaginated and regenerate openapi spec Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Vellum Assistant <assistant@vellum.ai> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * M3: Client-side safety fixes for pagination edge cases (#21565) * fix: remove trim-after-pagination and add 60s safety timeout for stuck loading state Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use minimal state clear instead of resetMessagePagination() on timeout Replace resetMessagePagination() in the 60s timeout handler with a targeted clear of isLoadingMoreMessages + loadMoreTimeoutTask. This preserves the user's scroll position, historyCursor, and hasMoreHistory so they can retry by scrolling up, rather than collapsing the visible window. Also update doc comments to reflect the 30s/60s two-stage timeout behavior and the accepted misclassification tradeoff. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Vellum Assistant <assistant@vellum.ai> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add pagination test suite for handleListMessages (#21578) Part of #21550. Adds 9 test cases covering backward compatibility, cursor pagination, strict exclusivity, hasMore logic, metadata correctness, empty conversations, and input validation. Co-authored-by: Vellum Assistant <assistant@vellum.ai> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove duplicate guard let self in timeout closure (non-optional after first unwrap) --------- Co-authored-by: Vellum Assistant <assistant@vellum.ai> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
idx_messages_conversation_created_atonmessages(conversation_id, created_at)for efficient paginated history queriesgetMessagesPaginated()with limit+1 sentinel pattern for server-side cursor paginationgetLastAssistantTimestampBefore()for interface diff seedingPart of #21550.
Test plan
getMessagesPaginated()withlimit=undefinedreturns all messages in ASC order withhasMore: falsegetMessagesPaginated()with a limit returns correct slice with sentinel-basedhasMoregetMessagesPaginated()withbeforeTimestampfilters correctlygetLastAssistantTimestampBefore()returns correct timestamp or 0Generated with Claude Code