import { Tools } from 'librechat-data-provider'; import { useState, useRef, useMemo, useLayoutEffect, useEffect } from 'react'; import type { MemoryArtifact, TAttachment } from 'librechat-data-provider'; import MemoryInfo from './MemoryInfo'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; export default function MemoryArtifacts({ attachments }: { attachments?: TAttachment[] }) { const localize = useLocalize(); const [showInfo, setShowInfo] = useState(false); const contentRef = useRef(null); const [contentHeight, setContentHeight] = useState(0); const [isAnimating, setIsAnimating] = useState(false); const prevShowInfoRef = useRef(showInfo); const { hasErrors, memoryArtifacts } = useMemo(() => { let hasErrors = false; const result: MemoryArtifact[] = []; if (!attachments || attachments.length === 0) { return { hasErrors, memoryArtifacts: result }; } for (const attachment of attachments) { if (attachment?.[Tools.memory] != null) { result.push(attachment[Tools.memory]); if (!hasErrors && attachment[Tools.memory].type === 'error') { hasErrors = true; } } } return { hasErrors, memoryArtifacts: result }; }, [attachments]); useLayoutEffect(() => { if (showInfo !== prevShowInfoRef.current) { prevShowInfoRef.current = showInfo; setIsAnimating(true); if (showInfo && contentRef.current) { requestAnimationFrame(() => { if (contentRef.current) { const height = contentRef.current.scrollHeight; setContentHeight(height + 4); } }); } else { setContentHeight(0); } const timer = setTimeout(() => { setIsAnimating(false); }, 400); return () => clearTimeout(timer); } }, [showInfo]); useEffect(() => { if (!contentRef.current) { return; } const resizeObserver = new ResizeObserver((entries) => { if (showInfo && !isAnimating) { for (const entry of entries) { if (entry.target === contentRef.current) { setContentHeight(entry.contentRect.height + 4); } } } }); resizeObserver.observe(contentRef.current); return () => { resizeObserver.disconnect(); }; }, [showInfo, isAnimating]); if (!memoryArtifacts || memoryArtifacts.length === 0) { return null; } return ( <>
{showInfo && }
); }