/** * ChatMessage — single message bubble in the conversation. * * Supports user messages (plain text) and assistant messages * (rich markdown with inline tool call activity). */ import { type ReactNode } from "react"; import { cn } from "../lib/utils"; import { Markdown } from "../markdown/markdown"; export type MessageRole = "user" | "assistant" | "system"; export interface ChatMessageProps { role: MessageRole; content: string; /** Inline tool call activity rendered between text chunks */ toolCalls?: ReactNode; /** Whether the message is still streaming */ isStreaming?: boolean; /** Timestamp */ timestamp?: Date; className?: string; /** Custom user label. Default: "You" */ userLabel?: string; /** Custom assistant label. Default: "Agent" */ assistantLabel?: string; /** Hide the role label row entirely */ hideRoleLabel?: boolean; } export function ChatMessage({ role, content, toolCalls, isStreaming, timestamp, className, userLabel = "You", assistantLabel = "Agent", hideRoleLabel, }: ChatMessageProps) { const isUser = role === "user"; return (
{!hideRoleLabel && (
{isUser ? userLabel : assistantLabel} {timestamp && ( {formatTime(timestamp)} )}
)} {/* Bubble */}
{/* Message body */} {isUser ? (
{content}
) : ( <> {content && {content}} {isStreaming && ( )} )} {/* Inline tool calls (left-aligned below agent text) */} {toolCalls}
); } function formatTime(date: Date): string { return date.toLocaleTimeString(undefined, { hour: "numeric", minute: "2-digit", }); }