Spaces:
Running
Running
File size: 1,960 Bytes
cfb4d9b d265ba3 cfb4d9b d265ba3 cfb4d9b d265ba3 cfb4d9b d265ba3 cfb4d9b d265ba3 cfb4d9b d265ba3 cfb4d9b a1b6108 cfb4d9b d265ba3 a1b6108 cfb4d9b a1b6108 cfb4d9b d265ba3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
const form = document.getElementById('chat-form');
const input = form.querySelector('input');
const chatbox = document.getElementById('chatbox');
const avatar = document.getElementById('avatar');
const overlay = document.getElementById('overlay');
function addBubble(text, sender = 'user') {
const bubble = document.createElement('div');
bubble.className = 'bubble ' + sender;
bubble.innerText = text;
chatbox.appendChild(bubble);
chatbox.scrollTop = chatbox.scrollHeight;
}
function streamText(text, onDone) {
const bubble = document.createElement('div');
bubble.className = 'bubble ai';
chatbox.appendChild(bubble);
chatbox.scrollTop = chatbox.scrollHeight;
let i = 0;
function stream() {
if (i < text.length) {
bubble.innerText += text[i++];
chatbox.scrollTop = chatbox.scrollHeight;
setTimeout(stream, 20);
} else {
onDone && onDone();
}
}
stream();
}
function playAudio(url) {
avatar.classList.add('speaking');
const audio = new Audio(url);
audio.play();
audio.onended = () => {
avatar.classList.remove('speaking');
fetch(`/delete_audio?path=${encodeURIComponent(url)}`);
};
}
form.onsubmit = async (e) => {
e.preventDefault();
const msg = input.value.trim();
if (!msg) return;
addBubble(msg, 'user');
input.value = '';
try {
const res = await fetch('/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: msg })
});
if (!res.ok) {
// log the actual payload for debugging:
const text = await res.text();
console.error('Chat error:', res.status, text);
throw new Error(`Status ${res.status}`);
}
const { response: text, audio_url } = await res.json();
streamText(text, () => {
if (audio_url) playAudio(audio_url);
});
} catch (err) {
streamText("❌ SHODAN encountered an error.", null);
console.error(err);
}
};
|