Repository navigation
FEAT: Page saved conversations - #3818
Roman Lutz (romanlutz) wants to merge 18 commits into
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Hand focus to stable paging status only during its owning activation, without scrolling or asynchronous focus changes. Keep saved narrow evidence on one scroll surface, retaining continuation position and resetting only for saved owner changes or leaving saved mode. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Extend the incumbent offline hierarchy fixture and journeys with split scored multimodal pieces, overlapping IDs, independent reference pages, retry/restart failures, stale ownership and keyboard/narrow reload coverage. Document the saved consumer and piece-based paging contract. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Scroll the actual desktop message-list before a held continuation and saved conversation selection. Verify the selected first user evidence starts in view and the stale old-owner completion cannot carry over the scroll position. Existing loading ownership already resets that inner surface; no production change is needed. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Saved-chat loading remains unbounded, score changes discard already-loaded transcript evidence, and manual conversation-list refreshes lose keyboard focus.
3 open issues
What changed in this PR
Adds paged saved-conversation evidence to PyRIT’s existing Chat viewer, building on the bounded backend APIs from #3167 and Scenario navigation from #3611.
Changes:
- Adds independent paging for conversation references and message pieces, with retry and restart controls.
- Merges split turns while preserving media, scores, and piece ordering; blocks whole-transcript actions while evidence is incomplete.
- Extends unit tests, offline browser coverage, and documentation for saved-evidence workflows.
| File | Description |
|---|---|
pyrit/backend/README.md |
Documents bounded reads and saved-viewer behavior. |
frontend/src/utils/messageMapper.ts |
Merges paged pieces and marks partial turns. |
frontend/src/utils/messageMapper.test.ts |
Tests merging, ordering, and evidence preservation. |
frontend/src/types/index.ts |
Adds pagination and saved-message metadata types. |
frontend/src/services/api.ts |
Adds optional conversation paging parameters. |
frontend/src/services/api.test.ts |
Tests bounded requests and unpaged compatibility. |
frontend/src/hooks/useConversationMessages.ts |
Manages transcript paging, retries, and stale responses. |
frontend/src/hooks/useConversationMessages.test.ts |
Tests pagination state and request ownership. |
frontend/src/components/Chat/MessageList.tsx |
Displays partial turns and controls scrolling and copying. |
frontend/src/components/Chat/MessageList.test.tsx |
Tests row identity, scrolling, and disabled actions. |
frontend/src/components/Chat/MessageList.styles.ts |
Adjusts narrow-screen saved-evidence layout. |
frontend/src/components/Chat/ConversationPanel.tsx |
Adds reference paging and keyboard handling. |
frontend/src/components/Chat/ConversationPanel.test.tsx |
Tests reference paging, recovery, and focus. |
frontend/src/components/Chat/ConversationPanel.styles.ts |
Styles paging controls and off-page selection notices. |
frontend/src/components/Chat/ChatWindow.tsx |
Integrates saved paging and incomplete-transcript safeguards. |
frontend/src/components/Chat/ChatWindow.test.tsx |
Tests saved-viewer integration and action gating. |
frontend/src/components/Chat/ChatWindow.styles.ts |
Styles transcript controls and responsive scrolling. |
frontend/README.md |
Documents saved paging and browser validation. |
frontend/e2e/scenario-hierarchy.spec.ts |
Adds real-route paging, recovery, and navigation journeys. |
frontend/e2e/fixtures/scenario_hierarchy_backend.py |
Adds long saved evidence and controlled read failures. |
Review effort: Balanced
Avoid complete reference arrays during initial Chat hydration while retaining legacy attack summaries. Validate selected membership independently of reference paging and avoid closed finding-dialog detail reads. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Refresh human scores without resetting loaded saved pieces or pagination. Preserve manual conversation rows and keyboard focus, announce pending page reads, and cover bounded metadata and real score mutations in the offline browser journeys. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Richard Lundeen (richlundeen)
left a comment
There was a problem hiding this comment.
One nonblocking usability finding from the code review. Earlier concerns are addressed at this head; no approval or merge action is requested.
Richard Lundeen (richlundeen)
left a comment
There was a problem hiding this comment.
Automated review completed. No blocking concerns remain. This review records source coverage; it does not authorize merge.
[P3] inline:4463645025: Same supported cause as local:ui-transcript-paging-copy-density, already posted at discussion_r4463645025; not a new independent defect or a reason to duplicate the comment. At unchanged ChatWindow.tsx:2495-2515, INCOMPLETE_TRANSCRIPT_REASON repeats the full blocked-operation sentence on every incomplete page. Independently assessed narrow-paging.png shows three lines before Load more at the observed 390px initial viewport; desktop-default/second-page evidence shows repetition after continuation. This is a nonblocking scanning/density cost, not a correctness failure. Any future change must retain counts, incomplete/loading/end/retry/restart announcements, operation gates and accessible action-specific explanations. The full 109px footer is not removable overhead and no task-time saving was measured.
[P3] local:ui-transcript-paging-copy-density: Preserved unchanged from the completed exact-head full review and independent finding assessment, with its structured evidence retained losslessly in approval-review.json and immutable original review d3c4ee91886a8790f05bc7f3cf12e9bc1a28ef492fe3801017e1b81874097af2. ChatWindow.tsx:2495-2515 appends the repeated blocked-operation reason to incomplete-page status. Independent image assessment supports three lines at the observed 390px initial page and repetition after desktop continuation. Existing copy/branch descriptions, export help and aria-describedby references provide action-specific explanation. Supported open P3 only: retain counts, incomplete status, loading/end/retry/restart announcements, safety gates and accessible descriptions; do not remove the shared constant globally. This duplicates public inline:4463645025 and must remain nonblocking under both collected IDs without another comment. No universal wrap guarantee, 109px saving or measured task-time improvement is claimed.
Keep loaded counts, incomplete state and pending announcements in the pager. Retain the full restrictions in disabled-action help and accessible descriptions without changing safety guards. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve bounded saved evidence alongside the current Chat, dataset draft, file-drop, and navigation behavior. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use paged saved-response fixtures, compact route metadata, canonical scan history, and the current outcome and expanded-group controls. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Integrate upstream through c756e7f to clear the behind state. The saved conversation frontend and production backend are unchanged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Description
Large saved attack results can contain many main/pruned conversation references and long transcripts. Opening a result should not require fetching all of those references or the entire selected transcript before the user can read its evidence.
This completes roadmap scope 10B in the existing Chat viewer, using the bounded backend APIs from #3167 and the existing Scenario navigation from #3611:
Paging is enabled for saved, read-only attack results, not only routes with Scenario context. Live/manual Chat keeps its existing full-history loading, send/edit/recovery and draft behavior. Optional API arguments preserve unpaged callers. The change also covers tightly coupled manual star-keyboard and optimistic-row identity regressions. There is no new backend hierarchy, transcript store or renderer.
Tests and Documentation
Updated the frontend and backend READMEs with the saved-consumer behavior and piece-based paging contract. Extended the existing offline hierarchy fixture and browser harness rather than adding a second harness.
Validation was retained for delivered head
fa859f17680100f18b36e651dc6acd1da07d2c3a:npm --prefix frontend test -- --runInBand --runTestsByPath src\services\api.test.ts src\utils\messageMapper.test.ts src\hooks\useConversationMessages.test.ts src\components\Chat\ChatWindow.test.tsx src\components\Chat\MessageList.test.tsx src\components\Chat\ConversationPanel.test.tsx --silent6772dc0; all production and unit-test files are unchanged at the final head.npm --prefix frontend run test:e2e:scenario-hierarchynpm run type-checkfromfrontenduv run --no-sync ruff check frontend\e2e\fixtures\scenario_hierarchy_backend.pyuv run --no-sync ruff format --check frontend\e2e\fixtures\scenario_hierarchy_backend.pyuv run --no-sync ty check frontend\e2e\fixtures\scenario_hierarchy_backend.pyuv run --no-sync python build_scripts\check_async_suffix.py frontend\e2e\fixtures\scenario_hierarchy_backend.pygit diff --checkThe offline journeys exercise actual routes and SQLite data without provider calls or API mocks: 222 unique pieces across overlapping 100/100/24-piece responses, 121 references, decoded original/converted images and supporting scores, retry/restart failures, stale ownership, desktop/narrow scrolling, keyboard paging and off-first-page selection/reload.
Exact browser environment and additional lint/compiler command (passed)
Browser command, from the repository root:
The additional compiler check includes the E2E spec, which the production tsconfig does not include, while retaining the production compiler options. No dependency or tsconfig changes were needed.
Existing Vite configuration/chunk-size and Pydantic warnings remain; none failed these checks. The final commit adds only desktop browser scroll-ownership coverage. JupyText was not run because no notebooks or executable documentation examples changed.