import React, { useState, useEffect, useRef } from 'react'; import ReactMarkdown from 'react-markdown'; const BASE_DOMAIN_NAME_PORT = import.meta.env.REACT_APP_DOMAIN_NAME_PORT || 'localhost:8004'; interface Message { sender: 'user' | 'bot'; text: string; } interface ChatTurn { question: string; intermediateMessages: { title: string; payload: string }[]; finalAnswer: string | null; isLoading: boolean; showIntermediate: boolean; } const App: React.FC = () => { const [messages, setMessages] = useState([]); const [intermediateMessages, setIntermediateMessages] = useState<{title: string, payload: string}[]>([]); const [finalAnswer, setFinalAnswer] = useState(null); const [isLoading, setIsLoading] = useState(false); const [showIntermediate, setShowIntermediate] = useState(false); const [newMessage, setNewMessage] = useState(''); const [socket, setSocket] = useState(null); const mounted = useRef(false); useEffect(() => { mounted.current = true; const ws = new WebSocket(`ws://${BASE_DOMAIN_NAME_PORT}/ws`); setSocket(ws); ws.onopen = () => { console.log('WebSocket connection opened'); }; ws.onmessage = (event) => { try { const data = JSON.parse(event.data); if (data.type === 'message' && data.payload && mounted.current) { // legacy support, treat as final setMessages((prevMessages) => { const lastMessage = prevMessages[prevMessages.length - 1]; if (lastMessage && lastMessage.sender === 'bot') { return [...prevMessages.slice(0, -1), { ...lastMessage, text: lastMessage.text + data.payload }]; } else { return [...prevMessages, { sender: 'bot', text: data.payload }]; } }); setFinalAnswer(data.payload); } else if (data.type === 'intermediate') { setIntermediateMessages((prev) => [...prev, { title: data.title, payload: data.payload }]); } else if (data.type === 'final') { setFinalAnswer(data.payload); } else if (data.type === 'done') { setIsLoading(false); } else { console.error('Unexpected message format:', data); } } catch (error) { console.error('Error parsing message:', error); } }; ws.onclose = () => { console.log('WebSocket connection closed'); }; ws.onerror = (error) => { console.error('WebSocket error:', error); }; return () => { mounted.current = false; ws.close(); }; }, []); const sendMessage = () => { if (newMessage.trim() !== '' && !isLoading) { setIsLoading(true); setIntermediateMessages([]); setFinalAnswer(null); setMessages((prevMessages) => [...prevMessages, { sender: 'user', text: newMessage }]); const message = [{ role: 'user', content: newMessage }]; socket?.send(JSON.stringify(message)); setNewMessage(''); } }; return (

Simple Chatbot

{messages.map((msg, index) => (
{msg.text}
))} {/* Status box for intermediate steps */} {intermediateMessages.length > 0 && (
{/* Spinner icon */} {isLoading && ( )} Working on: {/* Key steps summary */}
{intermediateMessages.map((msg, idx) => ( {msg.title} ))}
{/* Expanded details */} {showIntermediate && (
{intermediateMessages.map((msg, idx) => (
{msg.title}
{msg.payload}
))}
)}
)} {/* Final answer for this question */} {finalAnswer && (
{finalAnswer}
)}
setNewMessage(e.target.value)} className="flex-grow p-2 border border-gray-300 rounded-lg mr-2" disabled={isLoading} />
); }; export default App;