diff --git a/web/src/app/chat/components/research-activities-block.tsx b/web/src/app/chat/components/research-activities-block.tsx index 3e78022..2e83196 100644 --- a/web/src/app/chat/components/research-activities-block.tsx +++ b/web/src/app/chat/components/research-activities-block.tsx @@ -7,7 +7,7 @@ import { LRUCache } from "lru-cache"; import { BookOpenText, FileText, PencilRuler, Search } from "lucide-react"; import { useTranslations } from "next-intl"; import { useTheme } from "next-themes"; -import { useMemo } from "react"; +import React, { useMemo } from "react"; import SyntaxHighlighter from "react-syntax-highlighter"; import { docco } from "react-syntax-highlighter/dist/esm/styles/hljs"; import { dark } from "react-syntax-highlighter/dist/esm/styles/prism"; @@ -31,6 +31,10 @@ import { useMessage, useStore } from "~/core/store"; import { parseJSON } from "~/core/utils"; import { cn } from "~/lib/utils"; +// Performance optimization constants +const MAX_ANIMATED_ITEMS = 10; // Only animate first 10 items +const ANIMATION_DELAY_MULTIPLIER = 0.05; // Reduced delay between animations + export function ResearchActivitiesBlock({ className, researchId, @@ -42,27 +46,36 @@ export function ResearchActivitiesBlock({ state.researchActivityIds.get(researchId), )!; const ongoing = useStore((state) => state.ongoingResearchId === researchId); + return ( <> {ongoing && } @@ -70,7 +83,7 @@ export function ResearchActivitiesBlock({ ); } -function ActivityMessage({ messageId }: { messageId: string }) { +const ActivityMessage = React.memo(({ messageId }: { messageId: string }) => { const message = useMessage(messageId); if (message?.agent && message.content) { if (message.agent !== "reporter" && message.agent !== "planner") { @@ -84,9 +97,10 @@ function ActivityMessage({ messageId }: { messageId: string }) { } } return null; -} +}); +ActivityMessage.displayName = "ActivityMessage"; -function ActivityListItem({ messageId }: { messageId: string }) { +const ActivityListItem = React.memo(({ messageId }: { messageId: string }) => { const message = useMessage(messageId); if (message) { if (!message.isStreaming && message.toolCalls?.length) { @@ -109,7 +123,8 @@ function ActivityListItem({ messageId }: { messageId: string }) { } } return null; -} +}); +ActivityListItem.displayName = "ActivityListItem"; const __pageCache = new LRUCache({ max: 100 }); type SearchResult = @@ -187,38 +202,46 @@ function WebSearchToolCall({ toolCall }: { toolCall: ToolCallRuntime }) { ))} {pageResults .filter((result) => result.type === "page") - .map((searchResult, i) => ( - - - - {searchResult.title} - - - ))} - {imageResults.map((searchResult, i) => ( - { + const shouldAnimate = i < 6; // Only animate first 6 results + return ( + + + + {searchResult.title} + + + ); + })} + {imageResults + .slice(0, 10) // Limit displayed images for performance + .map((searchResult, i) => { + const shouldAnimate = i < 4; // Only animate first 4 images + return ( + - ))} + ); + })} )} @@ -263,10 +287,10 @@ function CrawlToolCall({ toolCall }: { toolCall: ToolCallRuntime }) {
    @@ -320,22 +344,25 @@ function RetrieverToolCall({ toolCall }: { toolCall: ToolCallRuntime }) { /> ))} - {documents?.map((doc, i) => ( - - - {doc.title} (chunk-{i},size-{doc.content.length}) - - ))} + {documents?.map((doc, i) => { + const shouldAnimate = i < 4; // Only animate first 4 documents + return ( + + + {doc.title} (chunk-{i},size-{doc.content.length}) + + ); + })}
)}