import React, { useState, useRef, useEffect } from 'react'; import axios from 'axios'; import ReactMarkdown from 'react-markdown'; import { Send, Paperclip, Trash2, Bot, User, AlertCircle, FileText, Loader2, Cloud, Calendar, Database, File, X, Plus, MessageSquare, History, Menu, HardDrive // Added icon for storage } from 'lucide-react'; import './App.css'; import StorageManager from './components/StorageManager'; // Import StorageManager function App() { // Use environment variable for backend URL, default to http://localhost:7860 const BACKEND_URL = process.env.REACT_APP_BACKEND_URL || 'http://localhost:7860'; const [sessions, setSessions] = useState(() => { const saved = localStorage.getItem('chat_sessions'); return saved ? JSON.parse(saved) : []; }); const [currentSessionId, setCurrentSessionId] = useState(Date.now()); const [messages, setMessages] = useState([ { role: 'assistant', content: 'Hello! I\'m your **Multi-Agent AI assistant**. I can help with:\n\n- 🌤️ **Weather information**\n- 📄 **Document analysis** (upload PDF/TXT/MD)\n- 📅 **Meeting scheduling** with weather checks\n- 💾 **Database queries** about meetings\n\nHow can I help you today?' } ]); const [input, setInput] = useState(''); const [isLoading, setIsLoading] = useState(false); const [uploadedFile, setUploadedFile] = useState(null); const [isSidebarOpen, setIsSidebarOpen] = useState(true); const [isPersistentUpload, setIsPersistentUpload] = useState(false); // State for persistent upload toggle const [showStorageManager, setShowStorageManager] = useState(false); // State to toggle Storage Manager view const messagesEndRef = useRef(null); const fileInputRef = useRef(null); const textInputRef = useRef(null); const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }; useEffect(() => { scrollToBottom(); }, [messages]); // Save sessions to localStorage useEffect(() => { localStorage.setItem('chat_sessions', JSON.stringify(sessions)); }, [sessions]); // Update current session in sessions list useEffect(() => { if (messages.length <= 1 && !uploadedFile) return; setSessions(prev => { const existingIdx = prev.findIndex(s => s.id === currentSessionId); const title = messages.find(m => m.role === 'user')?.content.substring(0, 30) || 'New Chat'; const sessionData = { id: currentSessionId, title: title.length >= 30 ? title + '...' : title, messages, uploadedFile, timestamp: new Date().toISOString() }; if (existingIdx >= 0) { const newSessions = [...prev]; newSessions[existingIdx] = sessionData; return newSessions; } else { return [sessionData, ...prev]; } }); }, [messages, uploadedFile, currentSessionId]); const createNewChat = () => { setCurrentSessionId(Date.now()); setMessages([ { role: 'assistant', content: 'Hello! I\'m your **Multi-Agent AI assistant**. I can help with:\n\n- 🌤️ **Weather information**\n- 📄 **Document analysis** (upload PDF/TXT/MD)\n- 📅 **Meeting scheduling** with weather checks\n- 💾 **Database queries** about meetings\n\nHow can I help you today?' } ]); setUploadedFile(null); if (textInputRef.current) textInputRef.current.focus(); }; const loadSession = (session) => { setCurrentSessionId(session.id); setMessages(session.messages); setUploadedFile(session.uploadedFile); }; const deleteSession = (e, id) => { e.stopPropagation(); setSessions(prev => prev.filter(s => s.id !== id)); if (currentSessionId === id) { createNewChat(); } }; const handleFileUpload = async (e) => { const file = e.target.files[0]; if (!file) return; const formData = new FormData(); formData.append('file', file); if (isPersistentUpload) { formData.append('persistent', 'true'); } try { setIsLoading(true); const response = await axios.post(`${BACKEND_URL}/upload`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }); setUploadedFile({ name: file.name, path: response.data.file_path, size: response.data.file_size, isPersistent: isPersistentUpload }); setMessages(prev => [...prev, { role: 'system', content: `📎 **File uploaded:** ${file.name} (${response.data.file_size}) ${isPersistentUpload ? '(Persistent)' : ''}\n\nYou can now ask questions about this document!` }]); } catch (error) { setMessages(prev => [...prev, { role: 'error', content: `❌ File upload failed: ${error.response?.data?.detail || error.message}` }]); } finally { setIsLoading(false); if (fileInputRef.current) { fileInputRef.current.value = ''; } } }; const removeFile = (e) => { e.stopPropagation(); setUploadedFile(null); if (fileInputRef.current) { fileInputRef.current.value = ''; } setMessages(prev => [...prev, { role: 'system', content: '📎 File removed from context.' }]); }; const handleSubmit = async (e) => { e.preventDefault(); if (!input.trim() || isLoading) return; const userMessage = input.trim(); setInput(''); setMessages(prev => [...prev, { role: 'user', content: userMessage }]); setIsLoading(true); try { const response = await axios.post(`${BACKEND_URL}/chat`, { query: userMessage, file_path: uploadedFile?.path || null }); setMessages(prev => [...prev, { role: 'assistant', content: response.data.response }]); } catch (error) { setMessages(prev => [...prev, { role: 'error', content: `❌ Error: ${error.response?.data?.detail || error.message}` }]); } finally { setIsLoading(false); setTimeout(() => textInputRef.current?.focus(), 100); } }; const clearChat = () => { setMessages([{ role: 'assistant', content: 'Chat cleared! How can I help you?' }]); setUploadedFile(null); if (fileInputRef.current) { fileInputRef.current.value = ''; } if (textInputRef.current) { textInputRef.current.focus(); } }; const handleExampleClick = (text) => { setInput(text); if (textInputRef.current) { textInputRef.current.focus(); } }; const exampleQueries = [ { icon: , text: 'What\'s the weather in Chennai?' }, { icon: , text: 'Schedule a team meeting tomorrow at 2pm' }, { icon: , text: 'Show all meetings scheduled tomorrow' }, { icon: , text: 'What is the remote work policy?' } ]; return (

Multi-Agent AI Assistant

Weather • Documents • Meetings • SQL

{uploadedFile && (
{uploadedFile.name}
)}
{showStorageManager ? (
) : ( <>
{messages.map((msg, idx) => (
{msg.role === 'user' ? : msg.role === 'error' ? : msg.role === 'system' ? : }
{msg.content}
))} {isLoading && (
Thinking...
)}
{exampleQueries.map((query, idx) => ( ))}
setInput(e.target.value)} placeholder="Ask about weather, meetings, documents, or upload a file..." disabled={isLoading} className="chat-input" />
)}
); } export default App;