const recordButton = document.getElementById('recordButton'); const sendTextButton = document.getElementById('sendTextButton'); const textInput = document.getElementById('textInput'); const statusEl = document.getElementById('status'); const transcriptEl = document.getElementById('transcript'); const replyEl = document.getElementById('reply'); const audioReply = document.getElementById('audioReply'); let recorder; let chunks = []; function setStatus(text) { statusEl.textContent = text; } async function askFriday(text) { setStatus('Asking FRIDAY...'); const response = await fetch('/api/ask', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text, speaker_id: null, confidence: 0 }) }); if (!response.ok) throw new Error(await response.text()); const data = await response.json(); replyEl.textContent = data.reply; setStatus(`Authorization: ${data.authorization_level}; ${data.reason}`); await speak(data.reply); } async function speak(text) { const response = await fetch('/api/speak', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text }) }); if (!response.ok) return; const blob = await response.blob(); audioReply.src = URL.createObjectURL(blob); await audioReply.play().catch(() => {}); } async function transcribe(blob) { setStatus('Transcribing...'); const form = new FormData(); form.append('audio', blob, 'utterance.webm'); const response = await fetch('/api/transcribe', { method: 'POST', headers: { 'Content-Type': 'audio/webm' }, body: blob }); if (!response.ok) throw new Error(await response.text()); const data = await response.json(); transcriptEl.textContent = data.text; textInput.value = data.text; return data.text; } async function startRecording() { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); chunks = []; recorder = new MediaRecorder(stream, { mimeType: 'audio/webm' }); recorder.addEventListener('dataavailable', event => { if (event.data.size > 0) chunks.push(event.data); }); recorder.addEventListener('stop', async () => { stream.getTracks().forEach(track => track.stop()); recordButton.classList.remove('recording'); recordButton.textContent = 'Hold to Talk'; try { const text = await transcribe(new Blob(chunks, { type: 'audio/webm' })); if (text.trim()) await askFriday(text); } catch (error) { setStatus(`Error: ${error.message}`); } }); recorder.start(); recordButton.classList.add('recording'); recordButton.textContent = 'Listening... release to send'; setStatus('Listening...'); } function stopRecording() { if (recorder && recorder.state === 'recording') recorder.stop(); } recordButton.addEventListener('pointerdown', startRecording); recordButton.addEventListener('pointerup', stopRecording); recordButton.addEventListener('pointerleave', stopRecording); sendTextButton.addEventListener('click', async () => { const text = textInput.value.trim(); if (!text) return; transcriptEl.textContent = text; try { await askFriday(text); } catch (error) { setStatus(`Error: ${error.message}`); } });