read alout chat messages

This commit is contained in:
2026-02-25 05:33:16 +00:00
parent de309ee0e4
commit 88fff9efae
@@ -99,9 +99,10 @@ type MessageBubbleProps = {
export const MessageBubble = ({ message, onAnswer }: MessageBubbleProps) => { export const MessageBubble = ({ message, onAnswer }: MessageBubbleProps) => {
switch (message.role) { switch (message.role) {
case 'user': { case 'user': {
const match = message.text.match(FRONTMATTER_RE); const rawText = typeof message.text === 'string' ? message.text : '';
const match = rawText.match(FRONTMATTER_RE);
const metadata = match ? match[1]!.trim() : null; const metadata = match ? match[1]!.trim() : null;
const text = match ? message.text.slice(match[0]!.length) : message.text; const text = match ? rawText.slice(match[0]!.length) : rawText;
return ( return (
<> <>
{metadata && <CollapsibleBlock label="Frontmatter" content={metadata} />} {metadata && <CollapsibleBlock label="Frontmatter" content={metadata} />}
@@ -120,24 +121,26 @@ export const MessageBubble = ({ message, onAnswer }: MessageBubbleProps) => {
case 'system': case 'system':
return <CollapsibleBlock label="System prompt" content={message.text} />; return <CollapsibleBlock label="System prompt" content={message.text} />;
case 'assistant': case 'assistant': {
if (!message.text) return null; const assistantText = typeof message.text === 'string' ? message.text : '';
if (!assistantText) return null;
return ( return (
<div className="flex justify-start"> <div className="flex justify-start">
<div className="max-w-[85%]"> <div className="max-w-[85%]">
<div className="rounded-2xl rounded-tl-sm bg-muted/50 border border-border/50 px-4 py-2.5"> <div className="rounded-2xl rounded-tl-sm bg-muted/50 border border-border/50 px-4 py-2.5">
<div className="chat-md"> <div className="chat-md">
<ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}> <ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}>
{injectImages(message.text)} {injectImages(assistantText)}
</ReactMarkdown> </ReactMarkdown>
</div> </div>
</div> </div>
<div className="flex justify-end mt-0.5"> <div className="flex justify-end mt-0.5">
<ReadAloudButton id={message.id ?? message.text.slice(0, 64)} text={message.text} /> <ReadAloudButton id={message.id ?? crypto.randomUUID()} text={assistantText} />
</div> </div>
</div> </div>
</div> </div>
); );
}
case 'tool': case 'tool':
if (message.toolName === 'question' && onAnswer) { if (message.toolName === 'question' && onAnswer) {