/**
* Chat functionality for AI system
*/
// Global variables
let currentConversationId = null;
let messageHistory = [];
let waitingForPermission = false;
let permissionReason = '';
// DOM elements
document.addEventListener('DOMContentLoaded', function() {
const chatForm = document.getElementById('chat-form');
const messageInput = document.getElementById('message-input');
const chatMessages = document.getElementById('chat-messages');
const loadingIndicator = document.getElementById('loading-indicator');
const permissionModal = new bootstrap.Modal(document.getElementById('permission-modal'));
const permissionReasonElement = document.getElementById('permission-reason');
const allowButton = document.getElementById('allow-button');
const denyButton = document.getElementById('deny-button');
// Check if all elements exist (they might not on some pages)
if (!chatForm || !messageInput || !chatMessages) {
return; // Exit if we're not on a page with chat functionality
}
// Load conversation if one is active
const activeConversationElement = document.getElementById('active-conversation');
if (activeConversationElement) {
currentConversationId = activeConversationElement.dataset.conversationId;
loadMessages(currentConversationId);
}
// Set up event listeners
chatForm.addEventListener('submit', function(e) {
e.preventDefault();
sendMessage();
});
// Permission modal buttons
if (allowButton) {
allowButton.addEventListener('click', function() {
handlePermissionResponse(true);
});
}
if (denyButton) {
denyButton.addEventListener('click', function() {
handlePermissionResponse(false);
});
}
// Allow pressing Enter to submit
messageInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
/**
* Send a message to the AI
*/
function sendMessage() {
const message = messageInput.value.trim();
if (!message) {
return; // Don't send empty messages
}
// Clear input field
messageInput.value = '';
// Add user message to chat
addMessageToChat('user', message);
// Show loading indicator
if (loadingIndicator) {
loadingIndicator.classList.remove('d-none');
}
// Send message to server
fetch('/api/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: message,
conversation_id: currentConversationId
}),
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
// Hide loading indicator
if (loadingIndicator) {
loadingIndicator.classList.add('d-none');
}
// Update conversation ID if new
if (data.conversation_id && !currentConversationId) {
currentConversationId = data.conversation_id;
// Update URL without reloading page
history.pushState(
{conversationId: currentConversationId},
'',
`/conversation/${currentConversationId}`
);
}
// Check if response requires permission
if (data.requires_permission) {
waitingForPermission = true;
permissionReason = data.permission_reason || 'performing this action';
// Show permission modal
if (permissionReasonElement) {
permissionReasonElement.textContent = data.permission_reason || 'this operation';
}
permissionModal.show();
// Don't add AI response yet
return;
}
// Add AI response to chat
addMessageToChat('ai', data.response);
})
.catch(error => {
console.error('Error:', error);
// Hide loading indicator
if (loadingIndicator) {
loadingIndicator.classList.add('d-none');
}
// Show error message
addMessageToChat('system', 'Error: Failed to get a response. Please try again.');
});
}
/**
* Add a message to the chat display
*/
function addMessageToChat(sender, content) {
// Create message element
const messageElement = document.createElement('div');
messageElement.className = `message ${sender}-message`;
// Create avatar
const avatarElement = document.createElement('div');
avatarElement.className = 'message-avatar';
if (sender === 'user') {
avatarElement.innerHTML = '';
} else if (sender === 'ai') {
avatarElement.innerHTML = '';
} else {
avatarElement.innerHTML = '';
}
// Create content
const contentElement = document.createElement('div');
contentElement.className = 'message-content';
// Convert newlines to
tags
contentElement.innerHTML = content.replace(/\n/g, '
');
// Assemble message
messageElement.appendChild(avatarElement);
messageElement.appendChild(contentElement);
// Add to chat
chatMessages.appendChild(messageElement);
// Scroll to bottom
chatMessages.scrollTop = chatMessages.scrollHeight;
// Add to history
messageHistory.push({
sender: sender,
content: content,
timestamp: new Date().toISOString()
});
}
/**
* Handle user's response to permission request
*/
function handlePermissionResponse(granted) {
if (!waitingForPermission) {
return;
}
// Hide modal
permissionModal.hide();
// Show loading indicator
if (loadingIndicator) {
loadingIndicator.classList.remove('d-none');
}
// Send permission response to server
fetch('/api/permission', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
permission_granted: granted,
operation: permissionReason,
conversation_id: currentConversationId
}),
})
.then(response => response.json())
.then(data => {
// Hide loading indicator
if (loadingIndicator) {
loadingIndicator.classList.add('d-none');
}
// Add AI response to chat
addMessageToChat('ai', data.response);
// Reset permission state
waitingForPermission = false;
permissionReason = '';
})
.catch(error => {
console.error('Error:', error);
// Hide loading indicator
if (loadingIndicator) {
loadingIndicator.classList.add('d-none');
}
// Show error message
addMessageToChat('system', 'Error: Failed to process permission response.');
// Reset permission state
waitingForPermission = false;
permissionReason = '';
});
}
/**
* Load messages for a conversation
*/
function loadMessages(conversationId) {
// This function would load existing messages from the server
// For now, we're just using what's already in the DOM
const messageElements = document.querySelectorAll('.message-history .message');
messageElements.forEach(element => {
const sender = element.classList.contains('user-message') ? 'user' : 'ai';
const content = element.querySelector('.message-content').textContent;
messageHistory.push({
sender: sender,
content: content,
timestamp: new Date().toISOString()
});
});
}
});