// Global variables
let currentChatId = null;
let darkMode = localStorage.getItem('darkMode') === 'true';
// Apply theme on load
document.addEventListener('DOMContentLoaded', () => {
if (darkMode) {
document.body.classList.add('dark-mode');
document.getElementById('theme-toggle').innerHTML = '';
}
// Add enter key listener for chat input
const userInput = document.getElementById('user-input');
if (userInput) {
userInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
}
// Smooth scroll for navigation
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth'
});
});
});
});
// Toggle between light and dark mode
function toggleTheme() {
darkMode = !darkMode;
localStorage.setItem('darkMode', darkMode);
document.body.classList.toggle('dark-mode');
document.getElementById('theme-toggle').innerHTML = darkMode ?
'' : '';
}
// Function to send a chat message to the backend
async function sendMessage() {
const userInput = document.getElementById('user-input');
const messageText = userInput.value.trim();
const modelSelect = document.getElementById('model-select');
const selectedModel = modelSelect ? modelSelect.value : null;
if (!messageText) return;
// Clear input field
userInput.value = '';
// Add user message to chat
addMessageToChat('user', messageText);
// Show typing indicator
addTypingIndicator();
try {
// Send request to backend
const response = await fetch('/api/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: messageText,
chat_id: currentChatId,
model: selectedModel
}),
});
// Remove typing indicator
removeTypingIndicator();
if (response.ok) {
const data = await response.json();
currentChatId = data.chat_id;
// Add AI response to chat
addMessageToChat('assistant', data.response);
// Scroll to bottom of chat
scrollToBottom();
} else {
const errorData = await response.json();
addMessageToChat('system', `Error: ${errorData.detail || 'Something went wrong'}`);
}
} catch (error) {
// Remove typing indicator
removeTypingIndicator();
addMessageToChat('system', `Error: ${error.message || 'Failed to communicate with the server'}`);
}
// Scroll to bottom of chat
scrollToBottom();
}
// Add a message to the chat UI
function addMessageToChat(role, content) {
const chatMessages = document.getElementById('chat-messages');
if (!chatMessages) return;
const messageDiv = document.createElement('div');
messageDiv.className = `message ${role}-message`;
const contentDiv = document.createElement('div');
contentDiv.className = 'message-content';
// Simple markdown-like formatting
let formattedContent = content
.replace(/\*\*(.*?)\*\*/g, '$1') // Bold
.replace(/\*(.*?)\*/g, '$1') // Italic
.replace(/```([\s\S]*?)```/g, '
$1
') // Code blocks
.replace(/`(.*?)`/g, '$1') // Inline code
.replace(/\n/g, '
'); // Line breaks
contentDiv.innerHTML = formattedContent;
messageDiv.appendChild(contentDiv);
chatMessages.appendChild(messageDiv);
}
// Add typing indicator
function addTypingIndicator() {
const chatMessages = document.getElementById('chat-messages');
if (!chatMessages) return;
const indicator = document.createElement('div');
indicator.className = 'message assistant-message typing-indicator';
indicator.id = 'typing-indicator';
const dots = document.createElement('div');
dots.className = 'typing-dots';
for (let i = 0; i < 3; i++) {
const dot = document.createElement('span');
dots.appendChild(dot);
}
indicator.appendChild(dots);
chatMessages.appendChild(indicator);
scrollToBottom();
}
// Remove typing indicator
function removeTypingIndicator() {
const indicator = document.getElementById('typing-indicator');
if (indicator) {
indicator.remove();
}
}
// Scroll to the bottom of the chat
function scrollToBottom() {
const chatMessages = document.getElementById('chat-messages');
if (chatMessages) {
chatMessages.scrollTop = chatMessages.scrollHeight;
}
}
// Admin Panel Functions
function updateModel() {
const modelSelector = document.getElementById('model-selector');
const model = modelSelector.value;
fetch('/api/model', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ model: model }),
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
document.getElementById('current-model').textContent = data.model;
alert('Model updated successfully!');
}
})
.catch(error => alert('Error updating model: ' + error));
}
function addRule() {
const newRuleInput = document.getElementById('new-rule');
const rule = newRuleInput.value.trim();
if (!rule) return;
fetch('/api/rules', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ rule: rule }),
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
newRuleInput.value = '';
refreshRulesList(data.rules);
}
})
.catch(error => alert('Error adding rule: ' + error));
}
function deleteRule(ruleId) {
fetch(`/api/rules/${ruleId}`, {
method: 'DELETE',
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
refreshRulesList(data.rules);
}
})
.catch(error => alert('Error deleting rule: ' + error));
}
function refreshRulesList(rules) {
const rulesList = document.getElementById('rules-list');
rulesList.innerHTML = '';
rules.forEach((rule, index) => {
const li = document.createElement('li');
li.innerHTML = `${rule} `;
rulesList.appendChild(li);
});
}
function viewChat(chatId) {
fetch(`/api/chats/${chatId}`)
.then(response => response.json())
.then(data => {
const chatViewer = document.getElementById('chat-viewer');
chatViewer.innerHTML = 'Chat History
';
const chatContainer = document.createElement('div');
chatContainer.className = 'admin-chat-history';
data.history.forEach(message => {
const messageDiv = document.createElement('div');
messageDiv.className = `admin-message ${message.role}-message`;
messageDiv.textContent = `${message.role.toUpperCase()}: ${message.content}`;
chatContainer.appendChild(messageDiv);
});
chatViewer.appendChild(chatContainer);
})
.catch(error => alert('Error viewing chat: ' + error));
}
// Load chats for the admin panel
function loadChats() {
if (document.getElementById('active-chats')) {
fetch('/api/chats')
.then(response => response.json())
.then(data => {
const chatsList = document.getElementById('active-chats');
chatsList.innerHTML = '';
data.chats.forEach(chatId => {
const li = document.createElement('li');
li.innerHTML = `${chatId}`;
chatsList.appendChild(li);
});
})
.catch(error => console.error('Error loading chats:', error));
}
}
// Check if we're on the admin page and load chats
if (window.location.pathname === '/admin') {
loadChats();
}