Skip to content

Implement AI overview search UI#364

Merged
appflowy merged 5 commits into
mainfrom
feature/ai-overview-web
May 24, 2026
Merged

Implement AI overview search UI#364
appflowy merged 5 commits into
mainfrom
feature/ai-overview-web

Conversation

@appflowy
Copy link
Copy Markdown
Contributor

@appflowy appflowy commented May 22, 2026

Summary

  • add AI overview summary UI in search using desktop-matching assets and colors
  • wire search summary generation, source passing, Ask AI, and follow-up chat handoff
  • fix pasted Markdown simple-table rendering so table containers do not create stray text wrappers

Testing

  • pnpm run lint
  • pnpm exec jest src/components/editor/parsers/tests/markdown-parser.test.ts src/components/editor/parsers/tests/table-parser.test.ts src/components/editor/clipboard/tests/table-fragment.test.ts --runInBand --no-coverage
  • verified pasted Markdown table in browser: 4 rows, 12 cells, no stray tbody children, normal add-column height

Summary by Sourcery

Add an AI-powered search overview to the search dialog and improve simple table handling for pasted Markdown content.

New Features:

  • Introduce AI overview summary UI in workspace search, including source references and follow-up Ask AI actions.
  • Enable creating AI chat pages directly from search queries with optional contextual sources and initial prompts.

Bug Fixes:

  • Fix pasted Markdown simple-table parsing and rendering so table containers and rows/cells are handled correctly without stray wrapper nodes or misaligned indices in the editor.

Enhancements:

  • Refine search APIs and client logic to return rich document search results, support AI-generated summaries, and surface them in the search results header.
  • Align simple table row and cell rendering with semantic row/column indices and filter out non-cell children to keep HTML tables structurally correct.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 22, 2026

Reviewer's Guide

Adds an AI-powered overview experience to workspace search (including summary generation, sources, and Ask AI handoff to chat) and hardens simple-table paste/rendering so Markdown tables no longer create stray wrapper nodes or misaligned rows/cells.

Sequence diagram for AI overview search and summary generation

sequenceDiagram
  actor User
  participant Search as Search
  participant BestMatch as BestMatch
  participant SearchService as SearchService

  User->>Search: type searchValue
  Search->>BestMatch: render searchValue, askingAI
  BestMatch->>BestMatch: debounce(handleSearch)
  BestMatch->>SearchService: searchWorkspaceDocuments(workspaceId, searchTerm)
  SearchService->>SearchService: GET /api/search/{workspaceId}
  SearchService-->>BestMatch: SearchDocumentResponseItem[]
  BestMatch->>BestMatch: resolveSearchResultView(outline, item)
  BestMatch-->>Search: setViews(views)
  alt aiEnabled and results have content
    BestMatch->>SearchService: generateSearchSummary(workspaceId, searchTerm, results)
    SearchService->>SearchService: POST /api/search/{workspaceId}/summary
    SearchService-->>BestMatch: SearchSummaryResult
    BestMatch->>BestMatch: setSummary(summary)
  end
  BestMatch->>Search: render ViewList header
  Search->>Search: render SearchAIOverview(aiEnabled, summary, sources)
Loading

Sequence diagram for Ask AI handoff from search to chat

sequenceDiagram
  actor User
  participant Search as Search
  participant BestMatch as BestMatch
  participant SearchAIOverview as SearchAIOverview
  participant AppOps as addPage
  participant ChatRequest as ChatRequest
  participant Router as toView
  participant EmptyMessages as EmptyMessages
  participant MsgCtx as MessagesHandlerContext

  User->>Search: open search dialog
  Search->>BestMatch: render with onAskAI
  User->>SearchAIOverview: click AskAI / Ask follow-up
  SearchAIOverview->>BestMatch: onAskAI(sourceIds)
  BestMatch-->>Search: onAskAI(query, sourceIds)
  Search->>Search: getAIChatParent(outline, currentViewId)
  Search->>AppOps: addPage(parent.view_id, { layout: AIChat, name, prev_view_id })
  AppOps-->>Search: created AI chat View
  alt query or sourceIds provided
    Search->>ChatRequest: new ChatRequest(workspaceId, created.view_id, axiosInstance)
    Search->>ChatRequest: updateChatSettings({ rag_ids, metadata.initial_prompt })
  end
  Search->>Router: toView(created.view_id)
  Search->>Search: handleClose()
  Router-->>EmptyMessages: mount with chatSettings
  EmptyMessages->>MsgCtx: useMessagesHandlerContext()
  EmptyMessages->>EmptyMessages: detect metadata.initial_prompt and !initial_prompt_consumed
  EmptyMessages->>MsgCtx: submitQuestion(initial_prompt)
  EmptyMessages->>MsgCtx: updateChatSettings({ metadata.initial_prompt_consumed: true })
Loading

File-Level Changes

Change Details Files
Enhance search to use document-level search API and support AI-generated overviews with source links and Ask AI handoff.
  • Replace basic searchWorkspace usage with searchWorkspaceDocuments that returns rich document metadata and previews
  • Implement result-to-view resolution logic that handles object, database view, and database IDs while filtering out space nodes
  • Track search sequence IDs to ignore stale async responses and reset results/summary on new queries
  • Call generateSearchSummary to fetch AI summaries when AI is enabled and there is indexed content, handling loading, errors, and fallbacks
  • Compute overview sources from summary.source IDs and search results, de-duplicating and resolving to views for navigation
src/components/app/search/BestMatch.tsx
src/application/services/js-services/http/misc-api.ts
src/application/services/domains/search.ts
Add SearchAIOverview UI that surfaces the AI overview, highlights query text, shows reference sources, and drives follow-up AI chat or Ask AI entrypoints.
  • Introduce SearchAIOverview component with summary header, loading state, and Ask AI / Ask follow-up actions
  • Implement HighlightedSummary with truncated display, see-more expansion, and inline reference-sources trigger
  • Add ReferenceSources popover listing source views with icons and navigation hooks
  • Wire SearchAIOverview as a header into ViewList so search results list displays the AI overview card above results
  • Add new AI-related SVG icons used by the overview UI
src/components/app/search/SearchAIOverview.tsx
src/components/app/search/ViewList.tsx
src/assets/icons/ai_searching_icon.svg
src/assets/icons/chat_ai_page.svg
src/assets/icons/m_home_ai_chat_icon.svg
src/assets/icons/m_toolbar_link.svg
Wire Ask AI from search into AI chat pages, including initial prompt and RAG source selection, and auto-send the first query when opening a chat this way.
  • Extend Search with AI-related hooks (AI enabled, outline, current view, workspace ID, navigation, and operations) and a controlled askingAI state
  • Add getAIChatParent helper to choose the space/current space as parent for new AI chat pages
  • On Ask AI, create an AIChat view, optionally configure chat settings with rag_ids and an initial_prompt via ChatRequest, and navigate to it
  • Update EmptyMessages to read metadata.initial_prompt, submit it once automatically, then mark initial_prompt_consumed in chat settings to avoid re-sending
src/components/app/search/Search.tsx
src/components/chat/components/chat-messages/empty-messages.tsx
Fix simple-table rendering/paste issues by making table row/cell rendering robust to hidden text nodes and by preserving table container structure when converting parsed blocks to Slate elements.
  • Add simple-table.utils helpers to detect row/cell node types generically from node.type
  • In SimpleTable, derive rowNodes from children using type guards, compute column count from cell children only, and render only SimpleTableRowBlock children inside tbody
  • In SimpleTableRow, compute a semantic row index based on tableNode children, filter children so only SimpleTableCellBlock nodes render as
, and use semantic index for styling when available
  • In SimpleTableCell, compute semantic row/column indices by scanning tableNode rows/cells by blockId, and filter rendered children to exclude raw text and row nodes
  • Extend parsedBlockToSlateElement/insertParsedBlocks to treat simple-table containers specially so they preserve their nested block structure instead of being flattened into text
  • Tighten table paste handling (TSV parsing, HTML cell extraction) mainly via stylistic arrow-function updates
  • src/components/editor/components/blocks/simple-table/simple-table.utils.ts
    src/components/editor/components/blocks/simple-table/SimpleTable.tsx
    src/components/editor/components/blocks/simple-table/SimpleTableRow.tsx
    src/components/editor/components/blocks/simple-table/SimpleTableCell.tsx
    src/components/editor/plugins/withPasted.ts

    Tips and commands

    Interacting with Sourcery

    • Trigger a new review: Comment @sourcery-ai review on the pull request.
    • Continue discussions: Reply directly to Sourcery's review comments.
    • Generate a GitHub issue from a review comment: Ask Sourcery to create an
      issue from a review comment by replying to it. You can also reply to a
      review comment with @sourcery-ai issue to create an issue from it.
    • Generate a pull request title: Write @sourcery-ai anywhere in the pull
      request title to generate a title at any time. You can also comment
      @sourcery-ai title on the pull request to (re-)generate the title at any time.
    • Generate a pull request summary: Write @sourcery-ai summary anywhere in
      the pull request body to generate a PR summary at any time exactly where you
      want it. You can also comment @sourcery-ai summary on the pull request to
      (re-)generate the summary at any time.
    • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
      request to (re-)generate the reviewer's guide at any time.
    • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
      pull request to resolve all Sourcery comments. Useful if you've already
      addressed all the comments and don't want to see them anymore.
    • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
      request to dismiss all existing Sourcery reviews. Especially useful if you
      want to start fresh with a new review - don't forget to comment
      @sourcery-ai review to trigger a new review!

    Customizing Your Experience

    Access your dashboard to:

    • Enable or disable review features such as the Sourcery-generated pull request
      summary, the reviewer's guide, and others.
    • Change the review language.
    • Add, remove or edit custom review instructions.
    • Adjust other review settings.

    Getting Help

    Copy link
    Copy Markdown

    @sourcery-ai sourcery-ai Bot left a comment

    Choose a reason for hiding this comment

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

    Hey - I've left some high level feedback:

    • The new semantic indexing logic for simple table rows/cells (SimpleTableRow/SimpleTableCell) does multiple array scans (filter/find/findIndex) per render; consider precomputing a blockId→(row,col) map once in the table context and passing indices down to avoid O(n²) work on larger tables.
    • In SimpleTableRow and SimpleTableCell, useMemo dependencies like [context?.tableNode.children] can confuse React hook linting and cause unnecessary recomputations; it would be more robust to pull const tableNode = context?.tableNode and depend on tableNode (or tableNode.children) directly, or memoize the table node shape in the context.
    Prompt for AI Agents
    Please address the comments from this code review:
    
    ## Overall Comments
    - The new semantic indexing logic for simple table rows/cells (`SimpleTableRow`/`SimpleTableCell`) does multiple array scans (`filter`/`find`/`findIndex`) per render; consider precomputing a blockId→(row,col) map once in the table context and passing indices down to avoid O(n²) work on larger tables.
    - In `SimpleTableRow` and `SimpleTableCell`, `useMemo` dependencies like `[context?.tableNode.children]` can confuse React hook linting and cause unnecessary recomputations; it would be more robust to pull `const tableNode = context?.tableNode` and depend on `tableNode` (or `tableNode.children`) directly, or memoize the table node shape in the context.

    Sourcery is free for open source - if you like our reviews please consider sharing them ✨
    Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

    @appflowy appflowy merged commit 694b5e4 into main May 24, 2026
    6 checks passed
    @appflowy appflowy deleted the feature/ai-overview-web branch May 24, 2026 03:58
    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.

    1 participant