Skip to content

fix: load complete paginated run history#3305

Open
Eilen6316 wants to merge 2 commits into
bytedance:mainfrom
Eilen6316:fix-run-message-history-pagination-3290
Open

fix: load complete paginated run history#3305
Eilen6316 wants to merge 2 commits into
bytedance:mainfrom
Eilen6316:fix-run-message-history-pagination-3290

Conversation

@Eilen6316
Copy link
Copy Markdown
Contributor

@Eilen6316 Eilen6316 commented May 28, 2026

Summary

Fixes #3290.

This PR fixes incomplete chat history restoration for long runs where a single run has more message events than the first /messages page returns. Previously the frontend loaded only one page per run, so older messages could disappear after reopening/restarting the app, and exports based on the loaded message list could miss the same older context even though token usage still reflected the full run.

Changes

  • Continue loading /api/threads/{thread_id}/runs/{run_id}/messages pages for the same run while the backend returns has_more.
  • Use the oldest returned message seq as the next before_seq cursor, so long runs are restored page by page instead of being marked loaded after the first page.
  • Add seq to the frontend RunMessage type and helper functions for pagination cursor handling / URL construction.
  • Keep compatibility with both has_more and the older camelCase hasMore response field.
  • Add a shared backend trim_run_message_page() helper so both run-message endpoints trim the extra limit + 1 sentinel row consistently.
  • Preserve pagination boundaries correctly:
    • default/latest and before_seq pages keep the newest side and drop the older sentinel row;
    • after_seq pages keep the oldest side and drop the newer sentinel row.
  • Add regression tests for backend pagination boundaries and frontend cursor helpers.

Risk / scope

The change is limited to run-message history pagination. It does not alter run creation, streaming, model invocation, or message persistence. The backend behavior keeps the existing limit + 1 contract and only centralizes which sentinel row is trimmed.

Tests

  • Backend pagination tests:

    docker exec deer-flow-gateway sh -lc 'cd /app/backend && uv run pytest tests/test_thread_run_messages_pagination.py tests/test_runs_api_endpoints.py'

    Result: 27 passed, 1 warning

  • Frontend unit tests:

    docker exec deer-flow-frontend sh -lc 'cd /app/frontend && pnpm test -- --run tests/unit/core/threads/message-merge.test.ts'

    Result: 20 passed, 128 passed

  • Backend lint / format:

    docker exec deer-flow-gateway sh -lc 'cd /app/backend && uvx ruff check app/gateway/routers/runs.py app/gateway/routers/thread_runs.py app/gateway/pagination.py tests/test_runs_api_endpoints.py tests/test_thread_run_messages_pagination.py tests/_run_message_pagination_helpers.py && uvx ruff format --check app/gateway/routers/runs.py app/gateway/routers/thread_runs.py app/gateway/pagination.py tests/test_runs_api_endpoints.py tests/test_thread_run_messages_pagination.py tests/_run_message_pagination_helpers.py'

    Result: passed

  • Frontend format:

    docker exec deer-flow-frontend sh -lc 'cd /app/frontend && pnpm exec prettier --check src/core/threads/hooks.ts src/core/threads/types.ts tests/unit/core/threads/message-merge.test.ts'

    Result: passed

@WillemJiang
Copy link
Copy Markdown
Collaborator

@Eilen6316 Do you mind resolving the confilct?

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes incomplete restoration of long run histories by paginating through /api/threads/{thread_id}/runs/{run_id}/messages until the backend indicates there are no more pages. It also centralizes backend “limit + 1” sentinel trimming so pagination boundaries remain correct for both forward (after_seq) and backward/latest (before_seq / default) pagination.

Changes:

  • Frontend: add run-message pagination cursor support (seq), helpers to detect has_more/hasMore, compute the next before_seq, and build message URLs safely.
  • Frontend: update useThreadHistory to repeatedly fetch additional pages for the same run using before_seq until fully loaded.
  • Backend: introduce a shared trim_run_message_page() helper to consistently trim the sentinel row while preserving correct page boundaries; add regression tests for trimming behavior.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
frontend/tests/unit/core/threads/message-merge.test.ts Adds unit tests for new run-message pagination helpers and URL construction.
frontend/src/core/threads/types.ts Extends RunMessage to include optional seq used for pagination cursors.
frontend/src/core/threads/hooks.ts Implements cursor-based multi-page loading per run and adds pagination helper utilities.
backend/tests/test_thread_run_messages_pagination.py Adds boundary regression tests for thread-scoped run message pagination trimming.
backend/tests/test_runs_api_endpoints.py Adds boundary regression tests for run-scoped message pagination trimming.
backend/tests/_run_message_pagination_helpers.py Introduces a shared assertion helper for run-message pagination tests.
backend/app/gateway/routers/thread_runs.py Switches to shared trimming helper for run-message pagination.
backend/app/gateway/routers/runs.py Switches to shared trimming helper for run-message pagination.
backend/app/gateway/pagination.py Adds trim_run_message_page() to correctly trim “limit + 1” pages for both cursor directions.

@Eilen6316
Copy link
Copy Markdown
Contributor Author

@Eilen6316 Do you mind resolving the confilct?

Sure, I’ve resolved the conflict. Could you please review it again when you get a chance? Thanks!

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.

重启gateway后上文消失

3 participants