import type { Message } from 'ai'; import { Fragment } from 'react'; import { classNames } from '~/utils/classNames'; import { AssistantMessage } from './AssistantMessage'; import { UserMessage } from './UserMessage'; import { useLocation } from '@remix-run/react'; import { db, chatId } from '~/lib/persistence/useChatHistory'; import { forkChat } from '~/lib/persistence/db'; import { toast } from 'react-toastify'; import WithTooltip from '~/components/ui/Tooltip'; import { useStore } from '@nanostores/react'; import { profileStore } from '~/lib/stores/profile'; import { forwardRef } from 'react'; import type { ForwardedRef } from 'react'; interface MessagesProps { id?: string; className?: string; isStreaming?: boolean; messages?: Message[]; } export const Messages = forwardRef( (props: MessagesProps, ref: ForwardedRef | undefined) => { const { id, isStreaming = false, messages = [] } = props; const location = useLocation(); const profile = useStore(profileStore); const handleRewind = (messageId: string) => { const searchParams = new URLSearchParams(location.search); searchParams.set('rewindTo', messageId); window.location.search = searchParams.toString(); }; const handleFork = async (messageId: string) => { try { if (!db || !chatId.get()) { toast.error('Chat persistence is not available'); return; } const urlId = await forkChat(db, chatId.get()!, messageId); window.location.href = `/chat/${urlId}`; } catch (error) { toast.error('Failed to fork chat: ' + (error as Error).message); } }; return (
{messages.length > 0 ? messages.map((message, index) => { const { role, content, id: messageId, annotations } = message; const isUserMessage = role === 'user'; const isFirst = index === 0; const isLast = index === messages.length - 1; const isHidden = annotations?.includes('hidden'); if (isHidden) { return ; } return (
{isUserMessage && (
{profile?.avatar ? ( {profile?.username ) : (
)}
)}
{isUserMessage ? ( ) : ( )}
{!isUserMessage && (
{messageId && (
)}
); }) : null} {isStreaming && (
)}
); }, );