import React, { useMemo } from 'react' import { ChatCompletionRole, ContentType, ThreadMessage } from '@janhq/core' import { useAtomValue } from 'jotai' import 'katex/dist/katex.min.css' import { twMerge } from 'tailwind-merge' import LogoMark from '@/containers/Brand/Logo/Mark' import { displayDate } from '@/utils/datetime' import EditChatInput from '../EditChatInput' import MessageToolbar from '../MessageToolbar' import DocMessage from './DocMessage' import ImageMessage from './ImageMessage' import { MarkdownTextMessage } from './MarkdownTextMessage' import { activeAssistantAtom } from '@/helpers/atoms/Assistant.atom' import { editMessageAtom, tokenSpeedAtom, } from '@/helpers/atoms/ChatMessage.atom' import { chatWidthAtom } from '@/helpers/atoms/Setting.atom' const MessageContainer: React.FC< ThreadMessage & { isCurrentMessage: boolean } > = (props) => { const isUser = props.role === ChatCompletionRole.User const isSystem = props.role === ChatCompletionRole.System const editMessage = useAtomValue(editMessageAtom) const activeAssistant = useAtomValue(activeAssistantAtom) const tokenSpeed = useAtomValue(tokenSpeedAtom) const chatWidth = useAtomValue(chatWidthAtom) const text = useMemo( () => props.content.find((e) => e.type === ContentType.Text)?.text?.value ?? '', [props.content] ) const image = useMemo( () => props.content.find((e) => e.type === ContentType.Image)?.image_url?.url, [props.content] ) const attachedFile = useMemo(() => 'attachments' in props, [props]) return (
{!isUser && !isSystem && } {isUser && (
)}
{isUser ? props.role : (activeAssistant?.assistant_name ?? props.role)}

{props.created && displayDate(props.created ?? new Date())}

{tokenSpeed && tokenSpeed.message === props.id && tokenSpeed.tokenSpeed > 0 && (

Token Speed: {Number(tokenSpeed.tokenSpeed).toFixed(2)}t/s

)}
<> {image && } {attachedFile && } {editMessage === props.id ? (
) : (
)}
) } export default React.memo(MessageContainer)