const chatMessages = document.getElementById('chatMessages'); const messageInput = document.getElementById('messageInput'); const sendBtn = document.getElementById('sendBtn'); const uploadBtn = document.getElementById('uploadBtn'); const fileInput = document.getElementById('fileInput'); const documentList = document.getElementById('documentList'); const ragToggle = document.getElementById('ragToggle'); let sessionId = generateSessionId(); function generateSessionId() { return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); } function addMessage(content, isUser = false) { const messageDiv = document.createElement('div'); messageDiv.className = `message ${isUser ? 'user' : 'assistant'}`; messageDiv.textContent = content; chatMessages.appendChild(messageDiv); chatMessages.scrollTop = chatMessages.scrollHeight; return messageDiv; } function addLoadingMessage() { const messageDiv = document.createElement('div'); messageDiv.className = 'message loading'; messageDiv.textContent = 'Thinking...'; chatMessages.appendChild(messageDiv); chatMessages.scrollTop = chatMessages.scrollHeight; return messageDiv; } async function sendMessage() { const message = messageInput.value.trim(); if (!message) return; addMessage(message, true); messageInput.value = ''; sendBtn.disabled = true; const loadingMsg = addLoadingMessage(); try { const response = await fetch('/chat/stream', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ message: message, session_id: sessionId, use_rag: ragToggle.checked }) }); const reader = response.body.getReader(); const decoder = new TextDecoder(); loadingMsg.remove(); const assistantMsg = addMessage('', false); let fullResponse = ''; while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); const lines = chunk.split('\n'); for (const line of lines) { if (line.startsWith('data: ')) { const data = JSON.parse(line.slice(6)); if (data.chunk) { fullResponse += data.chunk; assistantMsg.textContent = fullResponse; chatMessages.scrollTop = chatMessages.scrollHeight; } if (data.error) { assistantMsg.textContent = 'Error: ' + data.error; assistantMsg.style.color = '#dc3545'; } } } } } catch (error) { loadingMsg.remove(); addMessage('Error: ' + error.message, false); } finally { sendBtn.disabled = false; messageInput.focus(); } } messageInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { sendMessage(); } }); sendBtn.addEventListener('click', sendMessage); uploadBtn.addEventListener('click', () => { fileInput.click(); }); fileInput.addEventListener('change', async (e) => { const file = e.target.files[0]; if (!file) return; const formData = new FormData(); formData.append('file', file); uploadBtn.disabled = true; uploadBtn.textContent = 'Uploading...'; try { const response = await fetch('/documents/upload', { method: 'POST', body: formData }); if (response.ok) { const data = await response.json(); addMessage(`Document "${data.filename}" uploaded successfully! (${data.chunk_count} chunks)`, false); loadDocuments(); } else { const error = await response.json(); addMessage('Upload failed: ' + error.detail, false); } } catch (error) { addMessage('Upload error: ' + error.message, false); } finally { uploadBtn.disabled = false; uploadBtn.textContent = 'Upload Document'; fileInput.value = ''; } }); async function loadDocuments() { try { const response = await fetch('/documents/'); const documents = await response.json(); documentList.innerHTML = ''; documents.forEach(doc => { const docDiv = document.createElement('div'); docDiv.className = 'document-item'; const nameSpan = document.createElement('span'); nameSpan.className = 'document-name'; nameSpan.textContent = doc.filename; const deleteBtn = document.createElement('button'); deleteBtn.className = 'btn-delete'; deleteBtn.textContent = 'Delete'; deleteBtn.onclick = () => deleteDocument(doc.id); docDiv.appendChild(nameSpan); docDiv.appendChild(deleteBtn); documentList.appendChild(docDiv); }); } catch (error) { console.error('Failed to load documents:', error); } } async function deleteDocument(docId) { if (!confirm('Are you sure you want to delete this document?')) return; try { const response = await fetch(`/documents/${docId}`, { method: 'DELETE' }); if (response.ok) { loadDocuments(); addMessage('Document deleted successfully', false); } } catch (error) { addMessage('Delete failed: ' + error.message, false); } } loadDocuments();