Skip to content

feat(chat): projection-aware find-in-chat search - #989

Draft
beruro wants to merge 7 commits into
developfrom
junyu/chat-search-projection
Draft

feat(chat): projection-aware find-in-chat search#989
beruro wants to merge 7 commits into
developfrom
junyu/chat-search-projection

Conversation

@beruro

@beruro beruro commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Problem

Find-in-chat search could not reliably scroll to or highlight matches when turn pagination was disabled. The scroll path reused turn-page slices (pages[currentPageIndex]) to compute Virtuoso flat indices even though the non-paginated view renders the full flat list. Matches outside the first turn page therefore resolved to null display indices and search appeared broken.

The previous useChatSearchIntegration shim also duplicated navigation, DOM highlighting, and visibility wiring without a shared projection index or cross-pane sync contract.

Solution

Replace the integration shim with a projection-aware useChatSearch hook and extracted helpers:

  • Build an event-id → global flat index map from grouped projection data (chatSearchProjection).
  • Scroll via ChatHistoryList.scrollToChatTarget using DOM search-target attributes on rendered rows.
  • Expand collapsed turns/events before scrolling; when pagination is enabled, switch to the target turn page first.
  • Non-paginated fix: pass no page slice into toDisplayFlatIndex so global flat indices are preserved.
  • Persist find-in-chat visibility per session (chatFindInChatOpenAtomFamily) and publish live query/active match via chatSearchSyncAtomFamily for ChatHistory ↔ My Station MessageViewer highlight sync.
  • Add unit tests for projection mapping, helper mapping, and the non-paginated index regression.

Potential risks

  • Scroll/highlight correctness still depends on rendered rows exposing search-target attributes; virtualized/off-screen matches rely on Virtuoso scroll + layout follow-up.
  • Cross-pane sync reads shared atoms; stale session keys could leave highlights on the wrong pane until search closes.
  • Rust es_search_chat_events IPC must stay in sync with frontend session scoping (sessionId argument).
  • Manual QA for paginated mode, collapsed turns, and My Station message viewer sync is still outstanding.

Verification

  • pnpm exec vitest run src/engines/ChatPanel/ChatHistory/hooks/__tests__/chatSearchProjection.test.ts src/engines/ChatPanel/ChatHistory/hooks/__tests__/chatSearchHelpers.test.ts src/engines/ChatPanel/hooks/useSessionHeaderActions.test.ts src/engines/ChatPanel/ChatPanelContent.test.ts — 17 passed
  • Pre-commit scoped TypeScript check on staged files — passed
  • Manual: turn pagination off → Find in chat → match outside first turn scrolls/highlights
  • Manual: turn pagination on → search across turns still navigates correctly
  • Manual: My Station MessageViewer highlights follow active chat search match

beruro and others added 7 commits August 26, 2026 13:45
Replace the integration shim with a projection-indexed search hook that
scrolls to matches via flat-item targets, syncs highlights across panes,
and fixes non-paginated mode where turn page slices clipped scroll indices.

Pre-commit hook ran. Total eslint: 0, total circular: 0
Re-wire assistantCopyEventIds and resolveAssistantTurnCopyContent from
group meta through ChatHistoryList into AgentTurnContext so AgentMessageBlock
no longer crashes when rendering the copy-turn footer.

Pre-commit hook ran. Total eslint: 0, total circular: 0
Render ChatSearchBar in the pinned header portal above turn pagination
instead of inside the scrollable transcript so it no longer overlays messages.

Pre-commit hook ran. Total eslint: 0, total circular: 0
Rust EventStore search can return no hits while the rendered transcript
still contains the query (evicted store or id drift). Fall back to
scanning the already-loaded chatHistory so result counts match DOM highlights.

Pre-commit hook ran. Total eslint: 0, total circular: 0
ChatHistory passes setTurnPageSelection into useChatSearch but the
projection hook omitted it from its return object after the search refactor.

Pre-commit hook ran. Total eslint: 0, total circular: 0
Search refactor regressed ChatHistoryList by deriving virtualizer keys
from body content and splitting static/virtual into early returns.
Restore buildChatGroupRenderKeys, keep one scroll container for both
modes, forward null through measureVirtualRow, and mock ResizeObserver
in the identity regression test.

Pre-commit hook ran. Total eslint: 0, total circular: 0
@Harry19081 Harry19081 added enhancement New feature or request chat Chat, composer, markdown, canvas, browser, or terminal surfaces frontend-ui Frontend UI, design system, accessibility, layout, or theming UX Improvements to user experience, workflow smoothness labels Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chat Chat, composer, markdown, canvas, browser, or terminal surfaces enhancement New feature or request frontend-ui Frontend UI, design system, accessibility, layout, or theming UX Improvements to user experience, workflow smoothness

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants