// Renders an assistant message: markdown for prose, plus pills for any // command-bus action blocks or native tool calls attached to the message. // Tool-role messages (results from a function call) render as a JSON card. import { useMemo } from "react" import ReactMarkdown from "react-markdown" import { Sparkles, Wrench } from "lucide-react" import { extractActionBlocks } from "@crema/action-bus" import { stripToolCallTags, type ToolCall } from "@crema/llm-ui" const ACTION_BLOCK_RE = /```action\s*\n[\s\S]*?```/g export type MessageBodyProps = { content: string /** When set, render as a tool-result card. */ isToolResult?: boolean /** Native tool calls attached to this assistant message, if any. */ toolCalls?: ToolCall[] } export function MessageBody({ content, isToolResult, toolCalls }: MessageBodyProps) { const { prose, actionCount } = useMemo(() => { const blocks = extractActionBlocks(content) const cleaned = stripToolCallTags(content).replace(ACTION_BLOCK_RE, "").trim() return { prose: cleaned, actionCount: blocks.length, } }, [content]) if (isToolResult) { return (
{content}
{children}
, code: ({ children, className }) => { const isBlock = className?.startsWith("language-") if (isBlock) { return (
{children}
)
}
return (
{children}
)
},
ul: ({ children }) =>