import * as React from "react"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Send, Square, User, Bot } from "lucide-react"; import ReactMarkdown from "react-markdown"; import { AssistantInfo } from "@/types/chat"; export interface ChatProps extends React.HTMLAttributes { messages: Array<{ id: string; role: "user" | "assistant" | "system"; content: string; createdAt?: Date; assistantInfo?: AssistantInfo; }>; input: string; handleInputChange: (e: React.ChangeEvent) => void; handleSubmit: (e: React.FormEvent) => void; isGenerating?: boolean; stop?: () => void; } const Chat = React.forwardRef( ( { className, messages, input, handleInputChange, handleSubmit, isGenerating, stop, ...props }, ref ) => { const messagesEndRef = React.useRef(null); const messagesContainerRef = React.useRef(null); const scrollToBottom = () => { if (messagesContainerRef.current) { const element = messagesContainerRef.current; element.scrollTop = element.scrollHeight; } }; React.useEffect(() => { console.log( "Chat component - messages updated:", messages.length, messages.map((m) => ({ id: m.id, role: m.role, content: m.content.slice(0, 50) + "...", })) ); // Always scroll to bottom when messages change const timeoutId = setTimeout(() => { scrollToBottom(); }, 50); return () => clearTimeout(timeoutId); }, [messages]); return (
{/* Messages */}
{messages.length === 0 ? (

No messages yet. Start a conversation!

) : ( messages.map((message, index) => (
{/* Avatar for assistant */} {message.role !== "user" && (
)} {/* Message content */}
{message.role === "user" ? ( "You" ) : message.assistantInfo ? ( <> {message.assistantInfo.name} {message.assistantInfo.type !== "default" && ( {message.assistantInfo.type === "user" ? "Mine" : message.assistantInfo.type === "template" ? "Template" : "New"} )} {message.assistantInfo.originalTemplate && ( (from {message.assistantInfo.originalTemplate}) )} ) : ( "Assistant" )} #{index + 1}
(

{children}

), ul: ({ children }) => (
    {children}
), ol: ({ children }) => (
    {children}
), li: ({ children }) => (
  • {children}
  • ), code: ({ children, className }) => { const isInline = !className; return isInline ? ( {children} ) : ( {children} ); }, pre: ({ children }) => (
    {children}
    ), strong: ({ children }) => ( {children} ), em: ({ children }) => ( {children} ), blockquote: ({ children }) => (
    {children}
    ), h1: ({ children }) => (

    {children}

    ), h2: ({ children }) => (

    {children}

    ), h3: ({ children }) => (

    {children}

    ), }} > {message.content}
    {/* Avatar for user */} {message.role === "user" && (
    )}
    )) )}
    {/* Input */}