Files
jusfutura/web/chat.js
T
2026-08-19 23:17:20 -03:00

289 lines
7.2 KiB
JavaScript

// All comments are in English.
// TODO: window.location = `/api/file/${file_id}/${original_name}`
let conversationId = null;
let conversations = [];
async function login() {
window.location = "/login";
// if (AUTH_MODE === "oauth") { ... }
}
function toggleTheme() {
document.body.classList.toggle("dark");
}
function exportTXT() {
window.location = `/api/export/txt/${conversationId}/conversa.txt`
}
function exportMD() {
window.location = `/api/export/md/${conversationId}/conversa.md`
}
function exportHTML() {
window.location = `/api/export/html/${conversationId}/conversa.html`
}
function exportDOCX() {
window.location = `/api/export/docx/${conversationId}/conversa.docx`
}
function exportODT() {
window.location = `/api/export/odt/${conversationId}/conversa.odt`
}
async function sendAsync() {
const r = await fetch("/api/queue/generate", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
conversation_id: conversationId,
model: "llama3.2",
prompt: document.getElementById("prompt").value
})
});
const { task_id } = await r.json();
pollTask(task_id);
}
async function pollTask(taskId) {
const interval = setInterval(async () => {
const r = await fetch(`/api/queue/status/${taskId}`);
const data = await r.json();
if (data.state === "SUCCESS") {
clearInterval(interval);
await loadHistory();
}
}, 1500);
}
function exportPPTX() {
window.location = `/api/export/pptx/${conversationId}/conversa.pptx`
}
function exportODP() {
window.location = `/api/export/odp/${conversationId}/conversa.odp`
}
async function importExcel() {
const file = document.getElementById("excelFile").files[0];
const form = new FormData();
form.append("file", file);
const r = await fetch(`/api/import_excel/${conversationId}`, {
method: "POST",
body: form
});
const data = await r.json();
console.log("Imported sheets:", data.sheets);
await loadHistory();
}
async function loadConversations() {
const r = await fetch("/api/conversations");
conversations = await r.json();
renderTabs();
}
function renderTabs() {
const tabs = document.getElementById("tabs");
tabs.innerHTML = "";
conversations.forEach(c => {
const btn = document.createElement("button");
btn.textContent = c.title;
btn.onclick = () => selectConversation(c.id);
tabs.appendChild(btn);
});
}
async function sendAudio() {
const file = document.getElementById("audioFile").files[0];
const form = new FormData();
form.append("file", file);
await fetch(`/api/audio/transcribe/${conversationId}`, {
method: "POST",
body: form
});
await loadHistory();
}
async function sendImage() {
const file = document.getElementById("visionFile").files[0];
const form = new FormData();
form.append("file", file);
await fetch(`/api/vision/${conversationId}`, {
method: "POST",
body: form
});
await loadHistory();
}
async function newConversation() {
const title = prompt("Conversation title:");
const r = await fetch("/api/new_conversation", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({title})
});
const data = await r.json();
conversationId = data.conversation_id;
await loadConversations();
await loadHistory();
}
async function selectConversation(id) {
conversationId = id;
await loadHistory();
}
async function loadHistory() {
const r = await fetch(`/api/history/${conversationId}`);
const msgs = await r.json();
const chat = document.getElementById("chat");
chat.innerHTML = "";
msgs.forEach(m => {
const div = document.createElement("div");
div.className = "msg " + m.role;
div.innerHTML = `<div class="avatar">${m.role === "user" ? "🧑" : "🤖"}</div>
<div class="bubble">${m.content}</div>`;
chat.appendChild(div);
});
// Load attachments
const a = await fetch(`/api/attachments/${conversationId}`);
const attachments = await a.json();
attachments.forEach(att => {
const div = document.createElement("div");
div.className = "msg user";
div.innerHTML = `
<div class="avatar">🧑</div>
<div class="bubble">
<strong>Attachment:</strong> ${att.filename}<br>
<a href="/api/download/${att.id}" target="_blank">Download</a>
</div>
`;
chat.appendChild(div);
});
}
async function searchMessages() {
const q = prompt("Search:");
const r = await fetch(`/api/search?q=${encodeURIComponent(q)}`);
const results = await r.json();
console.log(results);
}
async function addTags() {
const tags = prompt("Tags (comma separated):");
await fetch(`/api/tags/${conversationId}`, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({tags: tags.split(",")})
});
}
async function shareConversation() {
const email = prompt("Share with email:");
await fetch(`/api/share/${conversationId}`, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({email})
});
}
function exportMD() {
window.open(`/api/export/md/${conversationId}/conversa.md`, "_blank");
}
function exportPDF() {
window.open(`/api/export/pdf/${conversationId}/conversa.pdf`, "_blank");
}
async function importFile() {
const file = document.getElementById("importFile").files[0];
const form = new FormData();
form.append("file", file);
await fetch(`/api/import/${conversationId}`, {
method: "POST",
body: form
});
await loadHistory();
}
async function sendMessage() {
const promptText = document.getElementById("prompt").value;
const file = document.getElementById("attachment").files[0];
if (!conversationId) {
await newConversation();
}
if (file) {
const form = new FormData();
form.append("file", file);
await fetch(`/api/attachment/${conversationId}`, {
method: "POST",
body: form
});
}
const chat = document.getElementById("chat");
const userDiv = document.createElement("div");
userDiv.className = "msg user";
userDiv.innerHTML = `<div class="avatar">🧑</div>
<div class="bubble">${marked.parse(promptText)}</div>`;
chat.appendChild(userDiv);
const assistantDiv = document.createElement("div");
assistantDiv.className = "msg assistant streaming";
assistantDiv.innerHTML = `<div class="avatar">🤖</div>
<div class="bubble"><span id="stream-text"></span><span class="cursor">▌</span></div>`;
chat.appendChild(assistantDiv);
const url = `/api/stream?conversation_id=${conversationId}&model=llama3.2&prompt=${encodeURIComponent(promptText)}`;
const evtSource = new EventSource(url);
let buffer = "";
const streamSpan = document.getElementById("stream-text");
evtSource.onmessage = (event) => {
const data = JSON.parse(event.data);
buffer += data.token;
streamSpan.innerHTML = marked.parse(buffer);
};
evtSource.onerror = () => {
evtSource.close();
assistantDiv.classList.remove("streaming");
};
}
window.onload = loadConversations;
const ws = new WebSocket("ws://" + window.location.host + "/ws/notifications");
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
// Show toast, badge, etc.
};