Coral-помощник
● на связи
Не заменяет визит к врачу. Рекомендации носят информационный характер.
`); w.document.close(); } // ── голосовой ввод (STT через Whisper) ── const micEl=document.getElementById('mic'); let mediaRec=null, audioChunks=[], recStream=null, recording=false; if(!navigator.mediaDevices||!window.MediaRecorder){ micEl.style.display='none'; } micEl.onclick=async()=>{ if(micEl.classList.contains('busy'))return; if(recording){ stopRec(); return; } try{ recStream=await navigator.mediaDevices.getUserMedia({audio:true}); }catch(e){ addBubble('bot','Не удалось получить доступ к микрофону. Разрешите доступ в браузере или напишите текстом.'); return; } audioChunks=[]; const mime=MediaRecorder.isTypeSupported('audio/webm')?'audio/webm':''; mediaRec=new MediaRecorder(recStream, mime?{mimeType:mime}:undefined); mediaRec.ondataavailable=e=>{ if(e.data.size>0) audioChunks.push(e.data); }; mediaRec.onstop=onRecStop; mediaRec.start(); recording=true; micEl.classList.add('rec'); micEl.textContent='■'; inputEl.placeholder='Говорите… нажмите ■ чтобы остановить'; }; function stopRec(){ recording=false; try{ mediaRec&&mediaRec.state!=='inactive'&&mediaRec.stop(); }catch(e){} recStream&&recStream.getTracks().forEach(t=>t.stop()); } async function onRecStop(){ micEl.classList.remove('rec'); micEl.classList.add('busy'); micEl.textContent='…'; inputEl.placeholder='Распознаём речь…'; const blob=new Blob(audioChunks,{type:(mediaRec&&mediaRec.mimeType)||'audio/webm'}); if(!blob.size){ resetMic(); return; } try{ const fd=new FormData(); fd.append('file', blob, 'voice.webm'); const r=await fetch('/api/coral/transcribe',{method:'POST',body:fd}); const d=await r.json(); if(r.ok && d.text){ inputEl.value=(inputEl.value?inputEl.value+' ':'')+d.text; autoGrow(); inputEl.focus(); }else if(d.message){ addBubble('bot',d.message); } }catch(e){ addBubble('bot','Не получилось распознать запись. Попробуйте ещё раз или напишите текстом.'); } resetMic(); } function resetMic(){ micEl.classList.remove('busy','rec'); micEl.textContent='🎤'; inputEl.placeholder='Напишите, что вас беспокоит…'; } // ── стартовое приветствие (локально) + быстрые старты из каталога ── addBubble('bot','Здравствуйте! Я Coral-помощник 🌿 Расскажите, что вас беспокоит в последнее время — задам несколько вопросов о самочувствии и помогу разобраться, на что обратить внимание и что может поддержать ваш организм. Можно и анализы прикрепить — подскажу по ним.'); fetch('/api/coral/catalog').then(r=>r.json()).then(d=>{ renderChips((d.concerns||[]).slice(0,6).map(c=>c.icon+' '+c.label)); }).catch(()=>{});