"use client"; import { useState } from "react"; import { getAnnotationData, Message } from "@llamaindex/chat-ui"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { ExternalLink, FileText, Github, Globe } from "lucide-react"; interface Source { id: number; title: string; description: string; url: string; } interface SourceGroup { id: number; name: string; type: string; sources: Source[]; } function getSourceIcon(type: string) { switch (type) { case "GITHUB_CONNECTOR": return ; case "NOTION_CONNECTOR": return ; case "FILE": case "USER_SELECTED_FILE": return ; default: return ; } } function SourceCard({ source }: { source: Source }) { const hasUrl = source.url && source.url.trim() !== ""; return (
{source.title} {hasUrl && ( )}
{source.description}
); } export default function ChatSourcesDisplay({ message }: { message: Message }) { const [open, setOpen] = useState(false); const annotations = getAnnotationData(message, "SOURCES"); // Flatten the nested array structure and ensure we have source groups const sourceGroups: SourceGroup[] = Array.isArray(annotations) && annotations.length > 0 ? annotations .flat() .filter( (group): group is SourceGroup => group !== null && group !== undefined && typeof group === "object" && "sources" in group && Array.isArray(group.sources) ) : []; if (sourceGroups.length === 0) { return null; } const totalSources = sourceGroups.reduce( (acc, group) => acc + group.sources.length, 0 ); return ( Sources {sourceGroups.map((group) => ( {getSourceIcon(group.type)} {group.name} {group.sources.length} ))} {sourceGroups.map((group) => (
{group.sources.map((source) => ( ))}
))}
); }