diff --git a/frontend-web/src/components/workspace/messages/message-group.tsx b/frontend-web/src/components/workspace/messages/message-group.tsx index f4909372..013639fe 100644 --- a/frontend-web/src/components/workspace/messages/message-group.tsx +++ b/frontend-web/src/components/workspace/messages/message-group.tsx @@ -15,7 +15,7 @@ import { SquareTerminalIcon, WrenchIcon, } from "lucide-react"; -import { useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useState, type AnchorHTMLAttributes } from "react"; import { ChainOfThought, @@ -58,6 +58,7 @@ import { useRehypeSplitWordsIntoSpans } from "@/core/rehype"; import { useLocalSettings } from "@/core/settings"; import { useSkills } from "@/core/skills/hooks"; import { + applyInlineCitations, buildSkillDisplayMap, findDisplayConfigForTool, isDisplaySamplePayload, @@ -71,6 +72,7 @@ import { env } from "@/env"; import { cn } from "@/lib/utils"; import { useArtifactsOptional } from "../artifacts"; +import { CitationLink } from "../citations/citation-link"; import { FlipDisplay } from "../flip-display"; import { Tooltip } from "../tooltip"; import { @@ -79,15 +81,18 @@ import { } from "../skill-display-sources"; import { MarkdownContent } from "./markdown-content"; +import { SingleRoundRagCitationDialog } from "./message-list-item"; export function MessageGroup({ className, messages, isLoading = false, + displaySources = [], }: { className?: string; messages: Message[]; isLoading?: boolean; + displaySources?: RuntimeDisplaySource[]; }) { const { t } = useI18n(); const [showAbove, setShowAbove] = useState( @@ -124,11 +129,29 @@ export function MessageGroup({ } }, [lastToolCallStep, steps]); const rehypePlugins = useRehypeSplitWordsIntoSpans(isLoading); + const [selectedCitation, setSelectedCitation] = + useState(null); + const handleCitationClick = useCallback( + (referenceId: string) => { + const referenceIndex = Number(referenceId); + if (!Number.isInteger(referenceIndex) || referenceIndex < 1) return; + const source = + displaySources.find((item) => item.index === referenceIndex) ?? + displaySources[referenceIndex - 1]; + if (source) setSelectedCitation(source); + }, + [displaySources], + ); + const reasoningId = + lastReasoningStep?.id ?? + messages.find((message) => message.type === "ai")?.id; return ( - + <> + {aboveLastToolCallSteps.length > 0 && (