import { Check, Copy } from "lucide-react"; import { useMemo } from "react"; import { Button } from "../../button"; import { HoverCard, HoverCardContent, HoverCardTrigger, } from "../../hover-card"; import { useCopyToClipboard } from "../hooks/use-copy-to-clipboard"; import { SourceData } from "../index"; import PdfDialog from "../widgets/PdfDialog"; const SCORE_THRESHOLD = 0.3; function SourceNumberButton({ index }: { index: number }) { return (
{index + 1}
); } type NodeInfo = { id: string; url?: string; }; export function ChatSources({ data }: { data: SourceData }) { const sources: NodeInfo[] = useMemo(() => { // aggregate nodes by url or file_path (get the highest one by score) const nodesByPath: { [path: string]: NodeInfo } = {}; data.nodes .filter((node) => (node.score ?? 1) > SCORE_THRESHOLD) .sort((a, b) => (b.score ?? 1) - (a.score ?? 1)) .forEach((node) => { const nodeInfo = { id: node.id, url: node.url, }; const key = nodeInfo.url ?? nodeInfo.id; // use id as key for UNKNOWN type if (!nodesByPath[key]) { nodesByPath[key] = nodeInfo; } }); return Object.values(nodesByPath); }, [data.nodes]); if (sources.length === 0) return null; return (
Sources:
{sources.map((nodeInfo: NodeInfo, index: number) => { if (nodeInfo.url?.endsWith(".pdf")) { return ( } /> ); } return (
); })}
); } function NodeInfo({ nodeInfo }: { nodeInfo: NodeInfo }) { const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 1000 }); if (nodeInfo.url) { // this is a node generated by the web loader or file loader, // add a link to view its URL and a button to copy the URL to the clipboard return (
{nodeInfo.url}
); } // node generated by unknown loader, implement renderer by analyzing logged out metadata return (

Sorry, unknown node type. Please add a new renderer in the NodeInfo component.

); }