// MessageContent.tsx (Updated to match border fixes) import React, { useState, useRef, useEffect } from 'react'; import { marked } from 'marked'; import DOMPurify from 'dompurify'; import { TypingIndicator } from './TypingIndicator'; import { ToolCall } from './ToolCall'; import type { MessageData } from './Message'; import './style.scss'; export interface MessageContentProps { message: MessageData; className?: string; } export const MessageContent: React.FC = ({ message, className = '' }) => { // Function to ensure text ends with punctuation const ensurePunctuation = (text: string): string => { if (!text) return text; const trimmed = text.trim(); if (!trimmed) return trimmed; // Check if the text already ends with punctuation const lastChar = trimmed[trimmed.length - 1]; const punctuationMarks = ['.', '!', '?', ':', ';', '。', '!', '?']; if (!punctuationMarks.includes(lastChar)) { return trimmed + '.'; } return trimmed; }; // Combine summaries if tool result is present let summary = message.metadata?.summary; if (message.toolResult && message.toolResult.metadata?.summary) { // Only use tool result summary if it exists summary = ensurePunctuation(message.toolResult.metadata.summary); } else if (summary) { summary = ensurePunctuation(summary); } const [isExpanded, setIsExpanded] = useState(false); // Collapsed by default if summary exists const contentRef = useRef(null); const [contentHeight, setContentHeight] = useState(null); useEffect(() => { if (contentRef.current) { setContentHeight(contentRef.current.scrollHeight); } }, [message.content, message.thinking_content, message.tools, isExpanded]); const renderContent = (text: string, isUser: boolean) => { if (isUser) { return DOMPurify.sanitize(text); } return DOMPurify.sanitize(marked.parse(text) as string); }; // Extract values from message const content = message.content; const thinkingContent = message.thinking_content; const role = message.role; const tools = message.tools || []; const isTyping = message.role === 'assistant' && message.streaming && !message.content; const isUser = role === 'user'; const handleSummaryClick = () => { if (summary) { setIsExpanded(!isExpanded); } }; return (
{summary && (
{summary}
)}
{/* Thinking content for reasoning models */} {thinkingContent && (
)} {/* Tool calls */} {tools.length > 0 && (
{tools.map((tool, index) => ( ))} {/* Tool result if present */} {message.toolResult && (
)}
)} {/* Main message content with summary */} {content && (
)}
{/* Typing indicator */} {isTyping && (
)}
); };