sssoc/script.js
2025-07-20 17:55:26 +07:00

97 lines
3.5 KiB
JavaScript

const messages = [];
const statusEl = document.getElementById("statusbox" );
const chatContainer = document.getElementById("chatbox" );
function setStatus(msg, stts) {
if (stts == "idle" ) statusEl.className = "status-idle";
if (stts == "responding" ) statusEl.className = "status-responding";
if (stts == "completed" ) statusEl.className = "status-completed";
if (stts == "failed" ) statusEl.className = "status-failed";
statusEl.textContent = msg;
}
async function sendPrompt() {
const role = document.getElementById("role" ).value;
const model = document.getElementById("model" ).value;
const response = document.getElementById("response" ).checked;
const promptBox = document.getElementById("prompt" );
const prompt = promptBox.value.trim();
if (!prompt) return;
const bubUser = document.createElement("div" );
const tagRole = document.createElement("span" );
const msgUser = document.createElement("div" );
const bubBot = document.createElement("div" );
const tagModel = document.createElement("span" );
const msgBot = document.createElement("div" );
bubUser .className = "bub bub-r bub-primary";
tagRole .className = "tag";
msgUser .className = "message";
bubBot .className = "bub bub-l bub-secondary";
tagModel .className = "tag";
msgBot .className = "message";
tagRole .textContent = `Role: ${role}`;
tagModel .textContent = `Model: ${model}`;
msgUser.innerHTML = marked.parse(prompt, { sanitize: true });
bubUser.appendChild(tagRole);
bubUser.appendChild(msgUser);
chatContainer.appendChild(bubUser);
bubBot.appendChild(tagModel);
bubBot.appendChild(msgBot);
if (response) chatContainer.appendChild(bubBot);
chatContainer.scrollTop = chatContainer.scrollHeight;
messages.push({ role: role, content: prompt }); // Add prompt to history
if (response) setStatus(`${model} Loading…`, "responding");
if (response) try {
const res = await fetch("http://localhost:11434/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ model, messages, stream: true })
});
const reader = res.body.getReader();
const decoder = new TextDecoder("utf-8");
let botReply = "";
setStatus(`✏️ ${model} Typing…`, "responding");
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true }).trim();
for (const line of chunk.split("\n")) {
if (!line) continue;
try {
const j = JSON.parse(line);
if (j.message?.content) {
botReply += j.message.content;
msgBot.innerHTML = marked.parse(botReply, { sanitize: true });
msgBot.prepend(tagModel);
chatContainer.scrollTop = chatContainer.scrollHeight;
}
} catch {}
}
}
messages.push({ role: "assistant", content: botReply });
setStatus(`✅ Response completed by ${model}`, "completed");
} catch (e) {
msgBot.innerHTML = "<em>[Failed to load answer]</em>";
msgBot.prepend(tagModel);
setStatus(`❌ Failed to get a response from ${model}`, "failed");
}
promptBox.value = "";
}