use-mcp/examples/chat-ui/src/components/ChatMessage.tsx
Glen Maddern 4f87d827aa Fix reasoning/content separation and eliminate empty message divs
- Remove extractReasoningMiddleware as it expects <think> tags but API sends reasoning fields directly
- Ensure reasoning and content tokens create separate assistant messages
- Filter empty assistant messages at conversation level to prevent empty divs
- Add deduplication for tool results to prevent duplicates
- Only render content div when message has actual content
2025-06-25 11:51:41 +10:00

72 lines
2.2 KiB
TypeScript

import React from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import rehypeHighlight from "rehype-highlight";
import { type Message } from "../types";
import ToolCallMessage from "./ToolCallMessage";
import ToolResultMessage from "./ToolResultMessage";
import ReasoningBlock from "./ReasoningBlock";
interface ChatMessageProps {
message: Message;
}
const ChatMessage: React.FC<ChatMessageProps> = ({
message,
}) => {
// Handle tool calls and results differently
if (message.role === "tool-call") {
return <ToolCallMessage message={message} />
}
if (message.role === "tool-result") {
return <ToolResultMessage message={message} />
}
// Handle regular messages (user, assistant, system)
return (
<div
className={`flex ${
message.role === "user" ? "justify-end" : "justify-start"
}`}
>
<div
className={`
${
message.role === "user"
? "max-w-[80%] rounded-2xl px-3 py-2 border border-zinc-200/10 bg-white text-black"
: " text-zinc-900 w-full"
}`}
>
{/* Show reasoning block for assistant messages with reasoning */}
{message.role === "assistant" && "reasoning" in message && (message.reasoning || message.isReasoningStreaming) && (
<ReasoningBlock
reasoning={message.reasoning || ""}
isStreaming={message.isReasoningStreaming}
startTime={message.reasoningStartTime}
endTime={message.reasoningEndTime}
/>
)}
{/* Only render content div if there's actual content */}
{message.content && message.content.trim() && (
<div className="prose prose-zinc">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeHighlight]}
components={{
table: ({ children }) => (
<div className="overflow-x-scroll text-sm">{children}</div>
),
}}
>
{message.content}
</ReactMarkdown>
</div>
)}
</div>
</div>
);
};
export default ChatMessage;