import { IconBrain, IconCheck, IconChevronDown, IconCopy, IconDownload, IconFileText, } from "@tabler/icons-react" import { useState } from "react" import { useTranslation } from "react-i18next" import ReactMarkdown from "react-markdown" import rehypeHighlight from "rehype-highlight" import rehypeRaw from "rehype-raw" import rehypeSanitize from "rehype-sanitize" import remarkGfm from "remark-gfm" import { Button } from "@/components/ui/button" import { formatMessageTime } from "@/hooks/use-pico-chat" import { cn } from "@/lib/utils" import { type ChatAttachment } from "@/store/chat" interface AssistantMessageProps { content: string attachments?: ChatAttachment[] isThought?: boolean timestamp?: string | number } export function AssistantMessage({ content, attachments = [], isThought = false, timestamp = "", }: AssistantMessageProps) { const { t } = useTranslation() const [isCopied, setIsCopied] = useState(false) const hasText = content.trim().length > 0 const imageAttachments = attachments.filter( (attachment) => attachment.type === "image", ) const fileAttachments = attachments.filter( (attachment) => attachment.type !== "image", ) const [isExpanded, setIsExpanded] = useState(true) const formattedTimestamp = timestamp !== "" ? formatMessageTime(timestamp) : "" const handleCopy = () => { navigator.clipboard.writeText(content).then(() => { setIsCopied(true) setTimeout(() => setIsCopied(false), 2000) }) } return (
{!isThought && (
PicoClaw {formattedTimestamp && ( <> {formattedTimestamp} )}
)} {(hasText || isThought) && (
{isThought && (
setIsExpanded(!isExpanded)} >
{t("chat.reasoningLabel")}
)} {(!isThought || isExpanded) && hasText && (
{content}
)} {!isThought && hasText && ( )}
)} {imageAttachments.length > 0 && (
{imageAttachments.map((attachment, index) => ( {attachment.filename
))}
)} {fileAttachments.length > 0 && (
{fileAttachments.map((attachment, index) => (
{attachment.filename || "Download file"} {attachment.filename?.split(".").pop()?.toUpperCase() || "FILE"}
))}
)}
) }