"use client";
import * as React from "react";
import { Sparkles, User } from "lucide-react";
import { cn } from "@/lib/utils";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
export type AIMessageProps = {
role: "user" | "assistant" | "system";
content: string;
timestamp?: Date;
};
/** Minimal markdown: **bold**, *italic*, `code`, lists */
function renderAssistantMarkdown(content: string): React.ReactNode {
const lines = content.split("\n");
const blocks: React.ReactNode[] = [];
let listBuf: { ordered: boolean; items: string[] } | null = null;
let blockKey = 0;
const parseInline = (text: string, keyPrefix: string): React.ReactNode[] => {
const nodes: React.ReactNode[] = [];
let remaining = text;
let i = 0;
while (remaining.length > 0) {
const tick = remaining.match(/^`([^`]+)`/);
if (tick) {
nodes.push(
{tick[1]}
,
);
remaining = remaining.slice(tick[0].length);
continue;
}
const bold = remaining.match(/^\*\*([^*]+)\*\*/);
if (bold) {
nodes.push(
{bold[1]}
,
);
remaining = remaining.slice(bold[0].length);
continue;
}
const italic = remaining.match(/^\*([^*]+)\*/);
if (italic) {
nodes.push(
{italic[1]}
,
);
remaining = remaining.slice(italic[0].length);
continue;
}
const nextSpecial = remaining.search(/[`\*]/);
if (nextSpecial === -1) {
nodes.push(remaining);
break;
}
if (nextSpecial > 0) {
nodes.push(remaining.slice(0, nextSpecial));
remaining = remaining.slice(nextSpecial);
continue;
}
nodes.push(remaining[0]);
remaining = remaining.slice(1);
}
return nodes;
};
const flushList = () => {
if (!listBuf || listBuf.items.length === 0) return;
const { ordered, items } = listBuf;
listBuf = null;
const lis = items.map((line, i) => (
{parseInline(line, `p-${blockKey}`)}
, ); } } flushList(); return{content}
{content}
) : (