async function sendMessage() {
document.getElementById('loadingSpinner').style.display = 'block';
const inputField = document.getElementById('userInput');
const imageInput = document.getElementById('imageInput');
const modelSelect = document.getElementById('modelSelect').value;
const streamToggle = document.getElementById('streamToggle').checked;
const ollamaToggle = document.getElementById('ollamaToggle').checked;
const userMessage = inputField.value.trim();
if (!userMessage && !imageInput.files.length) {
document.getElementById('loadingSpinner').style.display = 'none';
return;
}
const output = document.getElementById('output');
const userDiv = document.createElement('div');
userDiv.textContent = `EU: ${userMessage || '[imagem enviada]'}`;
output.appendChild(userDiv);
const botDiv = document.createElement('div');
botDiv.textContent = '...';
output.appendChild(botDiv);
output.scrollTop = output.scrollHeight;
const formData = new FormData();
formData.append("userMessage", userMessage);
formData.append("modelSelect", modelSelect);
formData.append("streamToggle", streamToggle);
formData.append("ollamaToggle", ollamaToggle);
if (imageInput.files.length) {
formData.append("image", imageInput.files[0]);
}
inputField.value = '';
imageInput.value = '';
let botMessage = '';
try {
const response = await fetch('chatController.php', {
method: 'POST',
body: formData
});
if (!response.ok) {
const errorText = await response.text();
botDiv.textContent = `Erro do servidor (${response.status}): ${errorText}`;
document.getElementById('loadingSpinner').style.display = 'none';
return;
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
botDiv.textContent = '';
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
const chunk = decoder.decode(value, { stream: true });
botMessage += chunk;
botDiv.textContent = botMessage;
output.scrollTop = output.scrollHeight;
}
let finalBotContent = botMessage;
if (!streamToggle) {
try {
const parsedJson = JSON.parse(botMessage);
if (ollamaToggle) {
if (parsedJson && typeof parsedJson.response === 'string') {
finalBotContent = parsedJson.response;
} else {
console.warn("Ollama non-streaming response did not match expected JSON structure:", parsedJson);
}
} else {
if (parsedJson && parsedJson.choices && parsedJson.choices[0] && parsedJson.choices[0].message && typeof parsedJson.choices[0].message.content === 'string') {
finalBotContent = parsedJson.choices[0].message.content;
} else {
console.warn("LM Studio non-streaming response did not match expected JSON structure:", parsedJson);
}
}
} catch (e) {
console.warn("Failed to parse non-streaming response as JSON. Treating as raw text.", e);
}
}
botDiv.innerHTML = formatMessage(finalBotContent);
hljs.highlightAll();
document.getElementById('loadingSpinner').style.display = 'none';
saveMessageToHistory(userMessage, finalBotContent);
} catch (error) {
botDiv.textContent = `Erro na requisição: ${error}`;
document.getElementById('loadingSpinner').style.display = 'none';
}
}
document.getElementById("btnenvia").addEventListener("click", sendMessage);
function formatMessage(message) {
message = message.replace(/```(\w+)?\n([\s\S]*?)```/g, (match, lang, code) => {
code = code.replace(/\n/g, ' ');
return `<pre><code class="${lang || 'plaintext'}">${escapeHtml(code)}</code></pre>`;
});
message = message.replace(/`([^`]+)`/g, '<code>$1</code>');
message = message.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
message = message.replace(/\*(.*?)\*/g, '<em>$1</em>');
message = message.replace(/\n/g, '<br>');
return `<div>${message}</div>`;
}
function escapeHtml(unsafe) {
return unsafe.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
function saveMessageToHistory(userMessage, botMessage) {
let chatHistory = JSON.parse(localStorage.getItem("chatHistory")) || [];
chatHistory.push({ user: userMessage, bot: botMessage });
localStorage.setItem("chatHistory", JSON.stringify(chatHistory));
loadChatHistory();
}
function loadChatHistory() {
const historyList = document.getElementById("historyList");
historyList.innerHTML = "";
const chatHistory = JSON.parse(localStorage.getItem("chatHistory")) || [];
chatHistory.forEach((chat, index) => {
const listItem = document.createElement("li");
listItem.classList.add("list-group-item", "list-group-item-action");
listItem.textContent = `? ${chat.user}`;
listItem.onclick = () => restoreConversation(index);
historyList.appendChild(listItem);
});
}
function restoreConversation(index) {
const chatHistory = JSON.parse(localStorage.getItem("chatHistory")) || [];
if (!chatHistory[index]) return;
const output = document.getElementById("output");
output.innerHTML = "";
const userDiv = document.createElement("div");
userDiv.textContent = `Eu: ${chatHistory[index].user}`;
output.appendChild(userDiv);
const botDiv = document.createElement("div");
botDiv.innerHTML = formatMessage(chatHistory[index].bot);
output.appendChild(botDiv);
hljs.highlightAll();
}
document.addEventListener("DOMContentLoaded", loadChatHistory);
|