@crestapps/ai-chat-ui 2.0.0-preview.215 → 2.0.0-preview.223
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat-widget.js +762 -964
- package/dist/ai-chat-widget.js.map +1 -1
- package/dist/ai-chat-widget.min.js +1 -1
- package/dist/ai-chat-widget.min.js.map +1 -1
- package/dist/ai-chat.css +0 -2
- package/dist/ai-chat.js +2380 -3698
- package/dist/ai-chat.js.map +1 -1
- package/dist/ai-chat.min.css +1 -1
- package/dist/ai-chat.min.js +78 -1
- package/dist/ai-chat.min.js.map +1 -1
- package/dist/chat-image-carousel.css +0 -2
- package/dist/chat-image-carousel.js +306 -482
- package/dist/chat-image-carousel.js.map +1 -1
- package/dist/chat-image-carousel.min.css +1 -1
- package/dist/chat-image-carousel.min.js +1 -1
- package/dist/chat-image-carousel.min.js.map +1 -1
- package/dist/chat-interaction-settings.js +221 -293
- package/dist/chat-interaction-settings.js.map +1 -1
- package/dist/chat-interaction-settings.min.js +1 -1
- package/dist/chat-interaction-settings.min.js.map +1 -1
- package/dist/chat-interaction.js +2330 -3557
- package/dist/chat-interaction.js.map +1 -1
- package/dist/chat-interaction.min.js +62 -1
- package/dist/chat-interaction.min.js.map +1 -1
- package/dist/chat-markers.js +193 -485
- package/dist/chat-markers.js.map +1 -1
- package/dist/chat-markers.min.js +2 -1
- package/dist/chat-markers.min.js.map +1 -1
- package/dist/chat-widget.css +0 -2
- package/dist/chat-widget.min.css +1 -1
- package/dist/document-drop-zone.css +0 -2
- package/dist/document-drop-zone.js +127 -153
- package/dist/document-drop-zone.js.map +1 -1
- package/dist/document-drop-zone.min.css +1 -1
- package/dist/document-drop-zone.min.js +1 -1
- package/dist/document-drop-zone.min.js.map +1 -1
- package/dist/realtime-audio.js +1639 -2504
- package/dist/realtime-audio.js.map +1 -1
- package/dist/realtime-audio.min.js +3 -1
- package/dist/realtime-audio.min.js.map +1 -1
- package/dist/technical-name-generator.js +58 -80
- package/dist/technical-name-generator.js.map +1 -1
- package/dist/technical-name-generator.min.js +1 -1
- package/dist/technical-name-generator.min.js.map +1 -1
- package/package.json +1 -5
- package/dist/ai-chat.css.map +0 -1
- package/dist/chat-image-carousel.css.map +0 -1
- package/dist/chat-widget.css.map +0 -1
- package/dist/document-drop-zone.css.map +0 -1
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
!function(e,t){"use strict";function n(e,t){var n=t.micDb,a="number"==typeof t.assistantDb?t.assistantDb:-100,o=t.nowMs,i=t.mode||{},r=null===e.lastMs?0:Math.max(0,Math.min(50,o-e.lastMs));e.lastMs=o,a>-50&&(e.assistantUntil=o+400);var c=o<e.assistantUntil;if(a>e.assistantPeakDb?e.assistantPeakDb=a:e.assistantPeakDb=Math.max(-100,e.assistantPeakDb-.02*r),n<=-95){if(null===e.floorDb)return e.open=!1,e}else null===e.floorDb&&(e.floorDb=Math.min(n,-50));if(n<e.floorDb)e.floorDb+=(n-e.floorDb)*Math.min(1,.0075*r);else if(!c){var s=null!==e.openSince&&o-e.openSince>1e4,l=e.open&&!s?1e-4:56e-5;e.floorDb+=(n-e.floorDb)*Math.min(1,l*r)}if(e.floorDb<-75&&(e.floorDb=-75),c&&!e.open&&a>-50&&!i.pushToTalk){var u=n-e.assistantPeakDb;if(null===e.echoReturnDb)e.echoReturnDb=u;else{var d=e.echoLearnedMs<1e3,p=u>e.echoReturnDb?d?.02:.0012:6e-4;e.echoReturnDb+=(u-e.echoReturnDb)*Math.min(1,p*r)}e.echoLearnedMs+=r}var f,m,h=null===e.echoReturnDb?-100:e.assistantPeakDb+e.echoReturnDb;c?(f=Math.max(e.floorDb+12,h+8,-45),m=Math.max(e.floorDb+3,h+3)):(f=e.floorDb+9,m=e.floorDb+3);var v=i.speechHangoverMs||2e3;n>f?c&&!e.open?(null===e.aboveSince&&(e.aboveSince=o),o-e.aboveSince>=250&&(e.speakUntil=o+v)):e.speakUntil=o+v:(e.aboveSince=null,e.open&&n>m&&(e.speakUntil=Math.max(e.speakUntil,o+250)));var b=o<e.speakUntil;return!c&&e.wasAssistantSpeaking&&(e.listenGraceUntil=o+1500),e.wasAssistantSpeaking=c,e.assistantSpeaking=c,i.pushToTalk?e.open=!!i.pttActive:i.bargeIn?e.open=b:e.open=!c&&(b||o<e.listenGraceUntil),e.open&&null===e.openSince?e.openSince=o:e.open||(e.openSince=null),e}function a(){return{floorDb:null,lastMs:null,speakUntil:0,assistantUntil:0,assistantPeakDb:-100,echoReturnDb:null,echoLearnedMs:0,aboveSince:null,listenGraceUntil:0,wasAssistantSpeaking:!1,assistantSpeaking:!1,open:!1,openSince:null}}function o(e){if(!e||!e.length)return-100;for(var t=0,n=0;n<e.length;n++)t+=e[n]*e[n];var a=Math.sqrt(t/e.length);return a>1e-7?20*Math.log10(a):-100}var i=["var decide = "+n.toString()+";","var newState = "+a.toString()+";","var rmsDb = "+o.toString()+";","class CoreAiMicGateProcessor extends AudioWorkletProcessor {"," constructor(options) {"," super();"," var o = (options && options.processorOptions) || {};"," this.delay = new Float32Array(Math.max(1, Math.round(sampleRate * (o.lookaheadMs || 80) / 1000)));"," this.delayPos = 0;"," this.gain = 0;"," this.mode = o.mode || {};"," this.state = newState();"," this.lastPost = 0;"," this.port.onmessage = function (e) { this.mode = e.data || {}; }.bind(this);"," }"," process(inputs, outputs) {"," var mic = (inputs[0] && inputs[0][0]) || null;"," var assistant = (inputs[1] && inputs[1][0]) || null;"," var out = (outputs[0] && outputs[0][0]) || null;"," if (!out) { return true; }"," var micDb = rmsDb(mic);"," decide(this.state, { micDb: micDb, assistantDb: rmsDb(assistant), nowMs: currentTime * 1000, mode: this.mode });"," var target = this.state.open ? 1 : 0;"," var step = 1 / (sampleRate * 0.01);"," var delay = this.delay;"," var pos = this.delayPos;"," var len = delay.length;"," for (var i = 0; i < out.length; i++) {"," var delayed = delay[pos];"," delay[pos] = mic ? mic[i] : 0;"," pos = (pos + 1) % len;"," if (this.gain < target) { this.gain = Math.min(target, this.gain + step); }"," else if (this.gain > target) { this.gain = Math.max(target, this.gain - step); }"," out[i] = delayed * this.gain;"," }"," this.delayPos = pos;"," if (currentTime * 1000 - this.lastPost > 100) {"," this.lastPost = currentTime * 1000;"," this.port.postMessage({ micDb: micDb, floorDb: this.state.floorDb, echoReturnDb: this.state.echoReturnDb, open: this.state.open, assistantSpeaking: this.state.assistantSpeaking });"," }"," return true;"," }","}",'registerProcessor("coreai-mic-gate", CoreAiMicGateProcessor);'].join("\n"),r=["class CoreAiCaptureProcessor extends AudioWorkletProcessor {"," constructor(options) {"," super();"," var o = (options && options.processorOptions) || {};"," this.size = Math.max(128, o.frameSamples || 4096);"," this.buf = new Float32Array(this.size);"," this.pos = 0;"," }"," process(inputs) {"," var input = (inputs[0] && inputs[0][0]) || null;"," var n = input ? input.length : 128;"," for (var i = 0; i < n; i++) {"," this.buf[this.pos++] = input ? input[i] : 0;"," if (this.pos === this.size) {"," this.port.postMessage(this.buf);"," this.pos = 0;"," }"," }"," return true;"," }","}",'registerProcessor("coreai-pcm-capture", CoreAiCaptureProcessor);'].join("\n");function c(t,n){var a=t&&t.getAudioTracks&&t.getAudioTracks()[0]||null,o={ctx:null,node:null,micSource:null,remoteSource:null,dest:null,timer:0,level:null,fallback:null,track:a,stopped:!1},r={track:a,usingWorklet:!1,getLevel:function(){return o.level},setMode:function(e){if(n=e||n,o.node&&o.node.port)try{o.node.port.postMessage(n)}catch(e){}o.fallback&&(o.fallback.mode=n)},attachAssistantStream:function(e){s(o,e)},stop:function(){if(o.stopped=!0,o.timer){try{e.clearInterval(o.timer)}catch(e){}o.timer=0}if(o.node){try{o.node.port.onmessage=null,o.node.disconnect()}catch(e){}o.node=null}if(o.micSource){try{o.micSource.disconnect()}catch(e){}o.micSource=null}if(o.remoteSource){try{o.remoteSource.disconnect()}catch(e){}o.remoteSource=null}if(o.dest){try{o.dest.disconnect()}catch(e){}o.dest=null}if(o.ctx){try{o.ctx.close()}catch(e){}o.ctx=null}o.fallback=null}},c=e.AudioContext||e.webkitAudioContext;if(!c||!a)return Promise.resolve(r);try{o.ctx=new c,"suspended"===o.ctx.state&&"function"==typeof o.ctx.resume&&o.ctx.resume().catch(function(){})}catch(e){return o.ctx=null,Promise.resolve(r)}var u=null;if(o.ctx.audioWorklet&&"function"==typeof o.ctx.audioWorklet.addModule)try{u=URL.createObjectURL(new Blob([i],{type:"application/javascript"}))}catch(e){u=null}return u?o.ctx.audioWorklet.addModule(u).then(function(){try{URL.revokeObjectURL(u)}catch(e){}if(o.stopped)return r;var i=new AudioWorkletNode(o.ctx,"coreai-mic-gate",{numberOfInputs:2,numberOfOutputs:1,outputChannelCount:[1],processorOptions:{lookaheadMs:80,mode:n}});return o.node=i,i.port.onmessage=function(t){o.level=t.data||null,e.CoreAIRealtime.lastGateLevel=o.level},o.micSource=o.ctx.createMediaStreamSource(t),o.micSource.connect(i,0,0),o.dest=o.ctx.createMediaStreamDestination(),i.connect(o.dest),o.pendingRemoteStream&&s(o,o.pendingRemoteStream),r.track=o.dest.stream.getAudioTracks()[0]||a,r.usingWorklet=!0,r}).catch(function(i){try{URL.revokeObjectURL(u)}catch(e){}return e.console&&console.warn&&console.warn("The realtime microphone gate worklet could not be loaded; using the simpler gate.",i),r.track=l(o,t,a,n),r}):(r.track=l(o,t,a,n),Promise.resolve(r))}function s(e,t){if(e.pendingRemoteStream=t||null,e.ctx&&t&&!e.stopped)try{if(e.remoteSource)try{e.remoteSource.disconnect()}catch(e){}var n=e.ctx.createMediaStreamSource(t);if(e.remoteSource=n,e.node)return void n.connect(e.node,0,1);if(e.fallback){var a=e.ctx.createAnalyser();a.fftSize=2048,n.connect(a),e.fallback.remoteAnalyser=a,e.fallback.remoteData=new Float32Array(a.fftSize)}}catch(e){}}function l(t,a,i,r){try{var c=t.ctx,l=c.createMediaStreamSource(a);t.micSource=l;var u=c.createAnalyser();u.fftSize=2048,l.connect(u);var d=c.createGain();d.gain.value=0,l.connect(d);var p=c.createMediaStreamDestination();t.dest=p,d.connect(p);var f={mode:r,remoteAnalyser:null,remoteData:null};t.fallback=f,t.pendingRemoteStream&&s(t,t.pendingRemoteStream);var m=new Float32Array(u.fftSize),h={floorDb:null,lastMs:null,speakUntil:0,assistantUntil:0,assistantPeakDb:-100,echoReturnDb:null,echoLearnedMs:0,aboveSince:null,listenGraceUntil:0,wasAssistantSpeaking:!1,assistantSpeaking:!1,open:!1,openSince:null};return t.timer=e.setInterval(function(){u.getFloatTimeDomainData(m);var a=o(m),i=-100;f.remoteAnalyser&&f.remoteData&&(f.remoteAnalyser.getFloatTimeDomainData(f.remoteData),i=o(f.remoteData));var r=e.performance&&performance.now?performance.now():Date.now();n(h,{micDb:a,assistantDb:i,nowMs:r,mode:f.mode||{}}),t.level={micDb:a,floorDb:h.floorDb,open:h.open,assistantSpeaking:h.assistantSpeaking};var s=h.open?1:0;try{d.gain.setTargetAtTime(s,c.currentTime,.015)}catch(e){d.gain.value=s}},20),p.stream.getAudioTracks()[0]||i}catch(e){return i}}function u(e,t){if(e&&"function"==typeof e.setSinkId)if(t)try{e.setSinkId(t).catch(function(){})}catch(e){}else navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&navigator.mediaDevices.enumerateDevices().then(function(t){var n=t.filter(function(e){return"audiooutput"===e.kind});if(n.length){for(var a="",o=0;o<n.length;o++)if("communications"===n[o].deviceId){a="communications";break}if(!a){for(var i=null,r=0;r<n.length;r++)if("default"===n[r].deviceId){i=n[r];break}if(i&&i.groupId)for(var c=0;c<n.length;c++)if("default"!==n[c].deviceId&&"communications"!==n[c].deviceId&&n[c].groupId===i.groupId){a=n[c].deviceId;break}}if(a)try{e.setSinkId(a).catch(function(){})}catch(e){}}}).catch(function(){})}function d(t,n){if(t&&"function"==typeof t.play){var a=t.play();a&&"function"==typeof a.catch&&a.catch(function(t){"function"==typeof n&&n(t),e.console&&console.warn&&console.warn("The browser blocked realtime audio playback. Interact with the page to enable audio.",t)})}}e.CoreAIRealtime={attach:function(n){var a=(n=n||{}).connection,o=n.selectors||{},i=n.voiceName||"",s=(n.capableDeployments||[]).map(function(e){return(e||"").toLowerCase()}),l=!!n.realtimeEnabled,p=function(){},f=n.onActivate||p,m=n.onDeactivate||p,h=n.onSessionStateChanged||p,v=n.onEnterRealtimeMode||p,b=n.onUserTurnPending||p,g=n.onUserTurnDropped||p,y=n.strings||{};function k(e,t){return"string"==typeof y[e]?y[e]:t}var S=n.ensureConnected||function(){return Promise.resolve(!0)},D=n.sendStart||p,M=n.getVoiceName||null,T=n.sendStartWebRtc||null,w=!0===n.webRtcEnabled&&"function"==typeof e.RTCPeerConnection&&!!T,x=Array.isArray(n.webRtcIceServers)&&n.webRtcIceServers.length?n.webRtcIceServers:null,C=[{urls:"stun:stun.l.google.com:19302"}],E=n.onStateChange||p,I="idle";function A(e){var n=o[e];return n?t.querySelector(n):null}var R=!1,L=!1,j=null,P=null,U=null,B=null,O=null,F=null,W=null,N=null,q=null,G=null,z=0,H=[],_=!1,V=null,Y=null,J=!1,K=!1,Q=[],X=!1,Z=null,$=!1,ee="coreai.realtime.webrtcBlocked",te=null,ne=0,ae=!1,oe=null,ie=null,re=!0,ce=!1,se=!1,le=!1,ue=null,de=null,pe=null,fe=null,me=1,he="",ve="",be="",ge=null,ye=1,ke=!1,Se=!1,De=null;function Me(e){return Math.round(100*Math.min(1.5,Math.max(.75,e)))/100}function Te(){var t={bargeIn:!0,pushToTalk:!1,volume:1,micDeviceId:"",outputDeviceId:"",language:"",speechSpeed:null,version:0};try{var n=e.localStorage.getItem("coreai.realtime.audioPrefs");if(n){var a=JSON.parse(n);"boolean"==typeof a.bargeIn&&(t.bargeIn=a.bargeIn),"boolean"==typeof a.pushToTalk&&(t.pushToTalk=a.pushToTalk),"number"==typeof a.volume&&isFinite(a.volume)&&(t.volume=Math.min(1,Math.max(0,a.volume))),"string"==typeof a.micDeviceId&&(t.micDeviceId=a.micDeviceId),"string"==typeof a.outputDeviceId&&(t.outputDeviceId=a.outputDeviceId),"string"==typeof a.language&&(t.language=a.language),"number"==typeof a.speechSpeed&&isFinite(a.speechSpeed)&&(t.speechSpeed=Me(a.speechSpeed)),"number"==typeof a.version&&(t.version=a.version)}}catch(e){}return function(e){if(3===e.version)return e;return e.version=3,e.bargeIn=!0,e.pushToTalk=!1,we(e),e}(t)}function we(t){try{e.localStorage.setItem("coreai.realtime.audioPrefs",JSON.stringify(t))}catch(e){}}function xe(e){re=!1!==e.bargeIn,ce=!!e.pushToTalk,me="number"==typeof e.volume?e.volume:1,he=e.micDeviceId||"",ve=e.outputDeviceId||"",be=e.language||"",ge="number"==typeof e.speechSpeed?e.speechSpeed:null,$e(),G&&(G.gain.value=me),Y&&(Y.volume=Math.max(0,Math.min(1,me)))}function Ce(e){if(!e||!e.tagName)return!1;var t=e.tagName.toLowerCase();return"input"===t||"textarea"===t||"select"===t||!0===e.isContentEditable}function Ee(){le||(le=!0,se=!1,ue=function(e){!ce||Ce(e.target)||"Space"!==e.code&&" "!==e.key||(e.preventDefault(),e.repeat||Ie(!0))},de=function(e){!ce||Ce(e.target)||"Space"!==e.code&&" "!==e.key||(e.preventDefault(),Ie(!1))},t.addEventListener("keydown",ue,!0),t.addEventListener("keyup",de,!0))}function Ie(e){se=e,$e(),pe&&(pe.classList.toggle("btn-danger",e),pe.classList.toggle("btn-outline-primary",!e),pe.innerHTML=e?'<i class="fa-solid fa-microphone me-1"></i> Listening…':'<i class="fa-solid fa-microphone me-1"></i> Hold to talk')}function Ae(){var n=A("realtimeButton");if(n&&!fe){var a=e.matchMedia&&e.matchMedia("(pointer: coarse)").matches,o=t.createElement("div");o.className="text-center mt-2";var i=t.createElement("button");i.type="button",i.className="btn btn-outline-primary btn-sm",i.innerHTML='<i class="fa-solid fa-microphone me-1"></i> Hold to talk';var r=t.createElement("div");r.className="form-text mt-1 mb-0",r.innerHTML=a?"Push-to-talk is on — press and hold the button to speak.":"Push-to-talk is on — hold <kbd>Space</kbd> or this button to speak.",o.appendChild(i),o.appendChild(r);var c=n.parentElement;c&&c.parentElement?c.parentElement.appendChild(o):n.insertAdjacentElement("afterend",o),pe=i,fe=o,i.addEventListener("pointerdown",function(e){e.preventDefault(),Ie(!0)}),i.addEventListener("pointerup",function(){Ie(!1)}),i.addEventListener("pointerleave",function(){Ie(!1)}),i.addEventListener("pointercancel",function(){Ie(!1)}),Ie(!1)}}function Re(n,a){if(a)if(e.DOMPurify&&"function"==typeof e.DOMPurify.sanitize)n.replaceChildren(e.DOMPurify.sanitize(a,{RETURN_DOM_FRAGMENT:!0}));else{var o=a.replace(/<[^>]*>/g," ").replace(/\s+/g," ").trim();n.replaceChildren(t.createTextNode(o))}}function Le(){h(R);var e=A("realtimeButton");e&&(R?(e.classList.add("active","btn-primary"),e.classList.remove("btn-dark","btn-outline-dark","btn-outline-secondary"),e.title=e.getAttribute("data-end-title")||"End Conversation",Re(e,e.getAttribute("data-end-html"))):(e.classList.remove("active","btn-primary","btn-dark","btn-outline-secondary"),e.classList.add("btn-outline-dark"),e.blur(),e.title=e.getAttribute("data-start-title")||"Start speaking",Re(e,e.getAttribute("data-start-html"))))}function je(e){l=e;var t=A("realtimeButton"),n=A("micButton"),a=A("conversationButton"),o=A("input"),i=A("sendButton"),r=De;e?(v(),o&&(o.hidden=!0),i&&(i.hidden=!0),n&&(n.hidden=!0),a&&(a.hidden=!0),t&&(t.hidden=!1),r&&(r.hidden=!1)):(R&&it(),t&&(t.hidden=!0),r&&(r.hidden=!0),function(){if(!P)return;try{P.remove()}catch(e){}P=null}(),ze(),o&&(o.hidden=!1),i&&(i.hidden=!1),n&&(n.hidden=!1),a&&(a.hidden=!1)),Le()}function Pe(e){return(isFinite(e)?e:1).toFixed(2)}function Ue(){return null!==ge?ge:ye}function Be(){if(De){var e=De.querySelector(".js-speed-row"),t=De.querySelector(".js-speed"),n=De.querySelector(".js-speed-val"),a=De.querySelector(".js-speed-reset");if(e&&t&&n&&a){var o=Ue();e.hidden=!ke,t.value=String(o),n.textContent=Pe(o),a.hidden=null===ge}}}function Oe(){if(R&&ke&&a&&"function"==typeof a.send)try{a.send("UpdateRealtimeSpeechSpeed",Ue())}catch(e){}}var Fe={"requesting-mic":k("requestingMic","Waiting for microphone access…"),connecting:k("connecting","Connecting…"),listening:k("listening","Listening"),"playback-blocked":k("playbackBlocked","Audio is blocked by the browser — click the page to enable it.")};function We(e,t){if(I!==e){I=e;var n=Fe[e];n?Ge(n,!1):"idle"===e&&ze();try{E({state:e,transport:_?"webrtc":"websocket",detail:t||null})}catch(e){}}}function Ne(){!L&&a&&(L=!0,a.on("ReceiveRealtimeEvent",function(e,t,n){R&&("speech_speed"===t?function(e){var t=parseFloat(e);ke=isFinite(t),ye=ke?t:1,Be(),null!==ge&&ge!==ye&&Oe()}(n):"session_ready"===t?We("listening"):"session_ended"===t?qe(n||"completed"):"speech_started"===t?re&&ct():"playback_flush"===t?ct():"user_turn_pending"===t?b(n):"user_turn_dropped"===t&&g(n))}),a.on("ReceiveError",function(){R&&(!_||X||$?qe("error"):ot("server reported an error before the peer connected"))}),"function"==typeof a.onclose&&a.onclose(function(){R&&qe("disconnected")}),"function"==typeof a.onreconnecting&&a.onreconnecting(function(){R&&qe("disconnected")}))}function qe(t){j=t,it(),We("ended",t),e.console&&console.info&&console.info("The realtime voice session ended ("+t+")."),"idle"===t?Ge(k("endedIdle","Voice paused after a period of silence."),!0):"max_duration"===t?Ge(k("endedMaxDuration","Voice paused — this session reached its time limit. You can start another."),!0):"disconnected"===t?Ge(k("endedDisconnected","Voice session ended — the connection dropped."),!0):"error"===t?Ge(k("endedError","Voice session ended unexpectedly."),!0):"device_lost"===t&&Ge(k("endedDeviceLost","Voice session ended — the microphone was disconnected."),!0)}function Ge(e,n){var a=A("realtimeButton");if(a){if(!U){(U=t.createElement("div")).className="form-text mt-2 mb-0 text-center",U.setAttribute("role","status"),U.setAttribute("aria-live","polite");var o=a.parentElement;o&&o.parentElement?o.parentElement.appendChild(U):a.insertAdjacentElement("afterend",U)}if(U.replaceChildren(),U.appendChild(t.createTextNode(e)),n){var i=t.createElement("button");i.type="button",i.className="btn btn-link btn-sm p-0 ms-2 align-baseline",i.textContent=k("resume","Resume"),i.addEventListener("click",function(){ze(),Ye()}),U.appendChild(i)}}}function ze(){if(U){try{U.remove()}catch(e){}U=null}}function He(){return x?Promise.resolve(x):te?Promise.resolve(te):a&&"function"==typeof a.invoke?a.invoke("GetRealtimeIceServers").then(function(e){return te=Array.isArray(e)&&e.length?e:C}).catch(function(t){return e.console&&console.warn&&console.warn("Could not resolve the realtime ICE servers; using the default STUN server.",t),te=C}):Promise.resolve(C)}function _e(e){var t=[];try{(e||[]).forEach(function(e){var n=e&&e.urls;"string"==typeof n?t.push(n):Array.isArray(n)&&n.forEach(function(e){e&&t.push(e)})})}catch(e){return"none"}return t.length?t.sort().join("|"):"none"}function Ve(){if(!P){var e=A("realtimeButton");if(e){var n=t.createElement("div");n.className="form-text mt-2 mb-0 text-center",n.setAttribute("role","status"),n.textContent=k("compatibilityMode","Using compatibility audio mode. Echo cancellation may be weaker — headphones are recommended.");var a=e.parentElement;a&&a.parentElement?a.parentElement.appendChild(n):e.insertAdjacentElement("afterend",n),P=n}}}function Ye(){if(l&&!R&&a){xe(Te()),te=null;var n=++ne;if($=!1,ke=!1,Be(),j=null,ze(),Ne(),We("requesting-mic"),!w)return at("the server did not advertise the WebRTC transport"),void Je();He().then(function(o){if(n===ne&&l&&!R)return function(t){try{return e.sessionStorage.getItem(ee)===_e(t)}catch(e){return!1}}(o)?(at("a WebRTC attempt already failed earlier in this browser session with the same ICE configuration"),void Je()):void function(){var e={echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0};he&&(e.deviceId={exact:he});navigator.mediaDevices.getUserMedia({audio:e}).then(function(e){S().then(function(){return He()}).then(function(n){B=e,R=!0,_=!0,f(),Le(),We("connecting"),K=!1,Q=[],X=!1;var o=new RTCPeerConnection({iceServers:n});V=o,Ee();var r=A("realtimeButton");if(r)try{r.blur()}catch(e){}ce&&Ae();var c=t.createElement("audio");c.autoplay=!0,c.style.display="none",c.volume=Math.max(0,Math.min(1,null!=me?me:1)),t.body.appendChild(c),Y=c,u(c,ve),o.ontrack=function(e){try{e.receiver&&"jitterBufferTarget"in e.receiver&&(e.receiver.jitterBufferTarget=150)}catch(e){}var t;e.streams&&e.streams[0]&&(c.srcObject=e.streams[0],function(e){d(e,function(){We("playback-blocked")})}(c),t=e.streams[0],ie=t||null,oe&&t&&oe.attachAssistantStream(t))},ae=!1,o.onicecandidate=function(e){if(e.candidate){e.candidate.candidate&&-1!==e.candidate.candidate.indexOf(" relay ")&&(ae=!0);try{a.send("AddRealtimeIceCandidate",e.candidate.candidate,e.candidate.sdpMid||"",e.candidate.sdpMLineIndex||0)}catch(e){}}else ae||X||!Z||(clearTimeout(Z),Z=setTimeout(function(){!X&&R&&ot("no relay candidate and no direct connection")},5e3))},o.onconnectionstatechange=function(){"connected"===o.connectionState?Qe():"failed"===o.connectionState?X?R&&it():ot("connection failed"):"closed"===o.connectionState&&R&&X&&it()},o.oniceconnectionstatechange=function(){var e=o.iceConnectionState;"connected"===e||"completed"===e?Qe():"failed"!==e||X||ot("ICE failed")},function(){if(J)return;J=!0,a.on("ReceiveRealtimeAnswer",function(e){V&&V.setRemoteDescription({type:"answer",sdp:e}).then(function(){K=!0;var e=Q;Q=[],e.forEach(function(e){try{V.addIceCandidate(e).catch(function(){})}catch(e){}})}).catch(function(e){console.error("Failed to apply the WebRTC answer.",e)})}),a.on("ReceiveRealtimeIceCandidate",function(e,t,n){if(V&&e){var a={candidate:e,sdpMid:t,sdpMLineIndex:n};if(K)try{V.addIceCandidate(a).catch(function(){})}catch(e){}else Q.push(a)}})}(),Z=setTimeout(function(){!X&&R&&ot("connection timed out")},8e3),et(e).then(function(t){return V!==o?null:(t&&o.addTrack(t,e),o.createOffer())}).then(function(e){return e&&V===o?o.setLocalDescription(e).then(function(){return e}):null}).then(function(e){if(e){var t=be||null,n=M&&M()||i||"";T(e.sdp,n,t,null,null,re)}}).catch(function(e){console.error("Failed to create the WebRTC offer; falling back to WebSocket.",e),ot("offer failed")})}).catch(function(t){e.getTracks().forEach(function(e){e.stop()}),R=!1,_=!1,m(),Le(),console.error("The realtime WebRTC conversation could not start because the chat connection is not available.",t)})}).catch(function(e){console.error("Microphone access denied:",e),R=!1,_=!1,m(),Le()})}()})}}function Je(){w&&Ve(),Ee();var t=A("realtimeButton");if(t)try{t.blur()}catch(e){}var n={channelCount:1,echoCancellation:{ideal:!0},noiseSuppression:!0,autoGainControl:!0,echoCancellationType:{ideal:"system"},voiceIsolation:{ideal:!0}};he&&(n.deviceId={exact:he}),navigator.mediaDevices.getUserMedia({audio:n}).then(function(t){S().then(function(){B=t,R=!0,f(),Le(),We("connecting");var n=e.AudioContext||e.webkitAudioContext;"suspended"===(O=new n({sampleRate:24e3})).state&&"function"==typeof O.resume&&O.resume().catch(function(t){We("playback-blocked"),e.console&&console.warn&&console.warn("The browser blocked realtime audio playback. Interact with the page to enable audio.",t)}),z=0,H=[],(G=O.createGain()).gain.value=null!=me?me:1,G.connect(O.destination),F=new e.signalR.Subject;var a=O,o=O.createGain();o.gain.value=0,q=o,o.connect(O.destination);var c=O.createMediaStreamDestination();G.connect(c);(function(t,n){function a(){var e=t.createScriptProcessor(4096,1,1);return e.onaudioprocess=function(e){n(e.inputBuffer.getChannelData(0))},e}var o=null;if(t.audioWorklet&&"function"==typeof t.audioWorklet.addModule&&"function"==typeof AudioWorkletNode)try{o=URL.createObjectURL(new Blob([r],{type:"application/javascript"}))}catch(e){o=null}return o?t.audioWorklet.addModule(o).then(function(){try{URL.revokeObjectURL(o)}catch(e){}var e=new AudioWorkletNode(t,"coreai-pcm-capture",{numberOfInputs:1,numberOfOutputs:1,outputChannelCount:[1],processorOptions:{frameSamples:4096}});return e.port.onmessage=function(e){e.data&&n(e.data)},e}).catch(function(t){try{URL.revokeObjectURL(o)}catch(e){}return e.console&&console.warn&&console.warn("The realtime capture worklet could not be loaded; falling back to a ScriptProcessorNode.",t),a()}):Promise.resolve(a())})(O,function(e){var t;t=ce?!se:!re&&O&&O.currentTime<z+.5;var n=new Int16Array(e.length);if(!t)for(var a=0;a<e.length;a++){var o=Math.max(-1,Math.min(1,e[a]));n[a]=o<0?32768*o:32767*o}for(var i=new Uint8Array(n.buffer),r="",c=0;c<i.length;c++)r+=String.fromCharCode(i[c]);try{F.next(btoa(r))}catch(e){}}).then(function(e){if(R&&O===a)W=e,e.connect(o),et(t).then(function(t){if(R&&O===a&&t){var n=new MediaStream([t]),o=O.createMediaStreamSource(n);N=o,o.connect(e),oe&&oe.attachAssistantStream(c.stream)}});else try{e.disconnect()}catch(e){}});var s=be||null,l=M&&M()||i||"";D(F,l,s,null,null,re),ce&&Ae()}).catch(function(e){t.getTracks().forEach(function(e){e.stop()}),R=!1,m(),Le(),console.error("The realtime conversation could not start because the chat connection is not available.",e)})}).catch(function(e){console.error("Microphone access denied:",e),R=!1,m(),Le()})}function Ke(){if(tt(),V){try{V.close()}catch(e){}V=null}if(Y){try{Y.srcObject=null,Y.remove()}catch(e){}Y=null}_=!1}function Qe(){X||(X=!0,Z&&(clearTimeout(Z),Z=null))}var Xe=2e3;function Ze(){return{pushToTalk:!!ce,pttActive:!!se,bargeIn:!!re,speechHangoverMs:Xe}}function $e(){oe&&oe.setMode(Ze())}function et(e){tt();var t=e&&e.getAudioTracks()[0]||null;return c(e,Ze()).then(function(e){return oe=e,ie&&e.attachAssistantStream(ie),e.track||t})}function tt(){if(oe){try{oe.stop()}catch(e){}oe=null}ie=null}function nt(){u(Y,ve)}function at(t){e.console&&console.warn&&console.warn("Realtime is using the WebSocket transport ("+t+"); acoustic echo cancellation is weaker than on WebRTC.")}function ot(t){if(!$){$=!0,Z&&(clearTimeout(Z),Z=null),e.console&&console.warn&&console.warn("Realtime WebRTC transport unavailable ("+t+"); falling back to the WebSocket transport."),function(){try{e.sessionStorage.setItem(ee,_e(te||x))}catch(e){}}(),Ve();try{B&&B.getTracks().forEach(function(e){e.stop()})}catch(e){}B=null,Ke(),_=!1,R=!1,Je()}}function it(){if(R)if(Z&&(clearTimeout(Z),Z=null),R=!1,m(),Le(),function(){if(le){le=!1,se=!1;try{t.removeEventListener("keydown",ue,!0)}catch(e){}try{t.removeEventListener("keyup",de,!0)}catch(e){}}}(),function(){if(pe=null,fe){try{fe.remove()}catch(e){}fe=null}}(),j||We("idle"),_){Ke();try{B&&B.getTracks().forEach(function(e){e.stop()})}catch(e){}B=null}else{try{F&&F.complete()}catch(e){}F=null,tt();try{W&&(W.disconnect(),W.onaudioprocess=null,W.port&&(W.port.onmessage=null,W.port.close()))}catch(e){}try{N&&N.disconnect()}catch(e){}try{q&&q.disconnect()}catch(e){}try{G&&G.disconnect()}catch(e){}try{B&&B.getTracks().forEach(function(e){e.stop()})}catch(e){}W=null,N=null,q=null,G=null,B=null,ct();try{O&&O.close()}catch(e){}O=null}}function rt(){R?it():Ye()}function ct(){H.forEach(function(e){try{e.stop()}catch(e){}}),H=[],O&&(z=O.currentTime)}function st(e){return!!e&&-1!==s.indexOf(e.toLowerCase())}var lt=A("realtimeButton");lt&&(lt.addEventListener("click",function(e){e&&0===e.detail&&R||rt()}),function(){var n=A("realtimeButton");if(n&&!Se){Se=!0;var o=Te();xe(o);var i=t.createElement("span");i.id="realtime-audio-settings",i.style.position="relative",i.style.display="inline-flex";var r=t.createElement("button");r.type="button",r.className="btn btn-outline-secondary",r.title=k("settingsTitle","Voice settings"),r.setAttribute("aria-label",k("settingsTitle","Voice settings")),r.innerHTML='<i class="fa-solid fa-headset"></i>';var c='<option value=""'+(""===o.language?" selected":"")+">"+k("languageAuto","Automatic")+"</option>"+[["en","English"],["es","Spanish"],["fr","French"],["de","German"],["it","Italian"],["pt","Portuguese"],["nl","Dutch"],["zh","Chinese"],["ja","Japanese"],["ko","Korean"],["ar","Arabic"],["hi","Hindi"],["ru","Russian"]].map(function(e){return'<option value="'+e[0]+'"'+(o.language===e[0]?" selected":"")+">"+e[1]+"</option>"}).join(""),s=t.createElement("div");s.className="card shadow-sm",s.style.cssText="position:absolute;bottom:calc(100% + 6px);right:0;z-index:1080;width:290px;max-height:70vh;overflow:auto;display:none;",s.innerHTML='<div class="card-body p-3"><div class="fw-semibold mb-2" style="font-size:0.85rem;">'+k("settingsTitle","Voice settings")+'</div><label class="form-label mb-1 d-block" style="font-size:0.8rem;">'+k("microphone","Microphone")+'</label><select class="form-select form-select-sm js-mic mb-2"><option value="">'+k("defaultMicrophone","Default microphone")+'</option></select><label class="form-label mb-1 d-block" style="font-size:0.8rem;">'+k("speaker","Speaker")+'</label><select class="form-select form-select-sm js-out mb-1"><option value="">'+k("automatic","Automatic")+'</option></select><button type="button" class="btn btn-outline-secondary btn-sm mb-2 js-pick-out" style="display:none;">'+k("chooseSpeaker","Choose speaker…")+'</button><div class="form-text mb-2 js-out-help">'+k("speakerHelp","Automatic uses the device your system uses for calls. If you cannot hear the assistant, pick the speakers you are actually listening to.")+'</div><label class="form-label mb-1 d-block" style="font-size:0.8rem;">'+k("assistantVolume","Assistant volume")+': <strong class="js-vol-val">'+Math.round(100*o.volume)+'</strong>%</label><input type="range" class="form-range js-vol mb-2" min="0" max="100" step="5" value="'+Math.round(100*o.volume)+'"><div class="js-speed-row" hidden><label class="form-label mb-1 d-flex align-items-baseline" style="font-size:0.8rem;"><span>'+k("speechSpeed","Speaking speed")+': <strong class="js-speed-val">1.00</strong>×</span><button type="button" class="btn btn-link btn-sm p-0 ms-auto js-speed-reset" style="font-size:0.8rem;" hidden>'+k("speechSpeedReset","Reset")+'</button></label><input type="range" class="form-range js-speed mb-0" min="0.75" max="1.5" step="0.05" value="1"><div class="form-text mt-0 mb-2">'+k("speechSpeedHelp","Applies from the assistant's next reply.")+'</div></div><label class="form-label mb-1 d-block" style="font-size:0.8rem;">'+k("language","Language")+'</label><select class="form-select form-select-sm js-lang mb-2">'+c+'</select><div class="form-check form-switch mb-1"><input class="form-check-input js-barge" type="checkbox" id="realtime-setting-barge"'+(o.bargeIn?" checked":"")+'><label class="form-check-label" for="realtime-setting-barge">'+k("allowInterruptions","Allow interruptions")+'</label></div><div class="form-text mb-2">'+k("allowInterruptionsHelp","Talk over the assistant to interrupt it. Turn this off if the assistant keeps hearing itself through your speakers.")+'</div><div class="form-check form-switch mb-1"><input class="form-check-input js-ptt" type="checkbox" id="realtime-setting-ptt"'+(o.pushToTalk?" checked":"")+'><label class="form-check-label" for="realtime-setting-ptt">'+k("pushToTalk","Push-to-talk")+'</label></div><div class="form-text">'+k("pushToTalkHelp","Hold <kbd>Space</kbd> (or the button) to talk. For very noisy places.")+"</div></div>",i.appendChild(r),i.appendChild(s),n.insertAdjacentElement("afterend",i),De=i;var l=s.querySelector(".js-barge"),u=s.querySelector(".js-ptt"),d=s.querySelector(".js-vol"),p=s.querySelector(".js-vol-val"),f=s.querySelector(".js-mic"),m=s.querySelector(".js-out"),h=s.querySelector(".js-pick-out"),v=s.querySelector(".js-lang"),b=s.querySelector(".js-speed"),g=s.querySelector(".js-speed-val"),y=s.querySelector(".js-speed-reset");T(),navigator.mediaDevices&&"function"==typeof navigator.mediaDevices.addEventListener&&navigator.mediaDevices.addEventListener("devicechange",function(){T(),R&&he&&navigator.mediaDevices.enumerateDevices().then(function(e){e.some(function(e){return"audioinput"===e.kind&&e.deviceId===he})||qe("device_lost")}).catch(function(){})}),r.addEventListener("click",function(n){n.stopPropagation();var a="none"===s.style.display;a&&(s.style.display="block",function(){s.style.right="0px",s.style.left="auto";var n=s.getBoundingClientRect();n.left<8&&(s.style.right=n.left-8+"px");for(var a=r.getBoundingClientRect(),o=8,i=s.parentElement?s.parentElement.parentElement:null;i&&i!==t.body&&i!==t.documentElement;){var c=e.getComputedStyle(i);if("auto"===c.overflowY||"scroll"===c.overflowY||"hidden"===c.overflowY||"fixed"===c.position){o=Math.max(o,i.getBoundingClientRect().top);break}i=i.parentElement}s.style.maxHeight=Math.max(160,a.top-o-10)+"px"}(),T()),s.style.display=a?"block":"none"}),s.addEventListener("click",function(e){e.stopPropagation()}),t.addEventListener("click",function(){s.style.display="none"}),l.addEventListener("change",D),u.addEventListener("change",D),d.addEventListener("input",function(){p.textContent=d.value,D()}),b.addEventListener("input",function(){g.textContent=Pe(parseFloat(b.value))}),b.addEventListener("change",function(){M(Me(parseFloat(b.value)))}),y.addEventListener("click",function(){M(null)}),f.addEventListener("change",D),v.addEventListener("change",D),m.addEventListener("change",function(){D(),nt()}),navigator.mediaDevices&&"function"==typeof navigator.mediaDevices.selectAudioOutput&&(h.style.display="",h.addEventListener("click",function(){navigator.mediaDevices.selectAudioOutput().then(function(e){if(e&&e.deviceId){var n=t.createElement("option");n.value=e.deviceId,n.textContent=e.label||k("selectedSpeaker","Selected speaker"),m.appendChild(n),m.value=e.deviceId,D(),nt()}}).catch(function(){})}))}function S(){return{bargeIn:l.checked,pushToTalk:u.checked,volume:(parseInt(d.value,10)||0)/100,micDeviceId:f.value||"",outputDeviceId:m.value||"",language:v.value||"",speechSpeed:ge,version:3}}function D(){var e=S();xe(e),we(e),function(){if(R&&a&&"function"==typeof a.send)try{a.send("UpdateRealtimeSettings",re,null,null)}catch(e){}}()}function M(e){ge=e,we(S()),Be(),Oe()}function T(){navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&navigator.mediaDevices.enumerateDevices().then(function(e){var t=['<option value="">'+k("defaultMicrophone","Default microphone")+"</option>"];e.filter(function(e){return"audioinput"===e.kind}).forEach(function(e,n){var a=e.label||k("microphone","Microphone")+" "+(n+1);t.push('<option value="'+e.deviceId+'"'+(e.deviceId===he?" selected":"")+">"+a.replace(/</g,"")+"</option>")}),f.innerHTML=t.join("");var n=e.filter(function(e){return"audiooutput"===e.kind&&e.deviceId&&"communications"!==e.deviceId&&"default"!==e.deviceId});if(n.length){var a=['<option value="">'+k("automatic","Automatic")+"</option>"];n.forEach(function(e,t){var n=e.label||k("speaker","Speaker")+" "+(t+1);a.push('<option value="'+e.deviceId+'"'+(e.deviceId===ve?" selected":"")+">"+n.replace(/</g,"")+"</option>")}),m.innerHTML=a.join("")}}).catch(function(){})}}());var ut=A("deploymentSelect");ut&&ut.addEventListener("change",function(){je(st(ut.value))}),je(l||ut&&st(ut.value));var dt={toggle:rt,start:Ye,stop:it,applyMode:je,isRealtimeDeployment:st,receivePcm:function(e){if(O&&e&&!(e.length<2)){for(var t=O,n=Math.floor(e.length/2),a=new Int16Array(e.buffer,e.byteOffset,n),o=new Float32Array(n),i=0;i<n;i++)o[i]=a[i]/32768;var r=t.createBuffer(1,n,t.sampleRate);r.copyToChannel(o,0);var c=t.createBufferSource();c.buffer=r,c.connect(G||t.destination);var s=t.currentTime;z<s&&(z=s),c.start(z),z+=r.duration,H.push(c),c.onended=function(){H=H.filter(function(e){return e!==c})}}},isActive:function(){return R},getState:function(){return I},getGateLevel:function(){return oe?oe.getLevel():null},getTransportStats:function(){return V&&"function"==typeof V.getStats?V.getStats().then(function(e){var t={transport:"webrtc",inbound:null,codec:null,sinkId:Y&&"string"==typeof Y.sinkId?Y.sinkId:null,jitterBufferTargetMs:function(){try{var e=V.getReceivers().filter(function(e){return e.track&&"audio"===e.track.kind})[0];return e&&"jitterBufferTarget"in e?e.jitterBufferTarget:null}catch(e){return null}}()};return e.forEach(function(n){if("inbound-rtp"===n.type&&"audio"===n.kind&&(t.inbound={packetsReceived:n.packetsReceived,packetsLost:n.packetsLost,packetsDiscarded:n.packetsDiscarded,jitterMs:"number"==typeof n.jitter?Math.round(1e3*n.jitter):null,jitterBufferDelayMs:"number"==typeof n.jitterBufferDelay&&n.jitterBufferEmittedCount?Math.round(n.jitterBufferDelay/n.jitterBufferEmittedCount*1e3):null,totalSamplesReceived:n.totalSamplesReceived,concealedSamples:n.concealedSamples,concealmentEvents:n.concealmentEvents,silentConcealedSamples:n.silentConcealedSamples,insertedSamplesForDeceleration:n.insertedSamplesForDeceleration,removedSamplesForAcceleration:n.removedSamplesForAcceleration,audioLevel:n.audioLevel},n.codecId)){var a=e.get(n.codecId);a&&(t.codec={mimeType:a.mimeType,clockRate:a.clockRate,channels:a.channels,sdpFmtpLine:a.sdpFmtpLine})}}),t}).catch(function(){return null}):Promise.resolve(null)}};return e.CoreAIRealtime.activeController=dt,dt},createMicGate:c,decideGate:n,createGateState:a,rmsDb:o,routeOutputToPreferredDevice:u,ensurePlayback:d}}(window,document);
|
|
1
|
+
(function(){(function(e,t){"use strict";function n(e,t){var n=t.micDb,r=typeof t.assistantDb==`number`?t.assistantDb:-100,i=t.nowMs,a=t.mode||{},o=e.lastMs===null?0:Math.max(0,Math.min(50,i-e.lastMs));e.lastMs=i,r>-50&&(e.assistantUntil=i+400);var s=i<e.assistantUntil;if(e.assistantPeakDb=r>e.assistantPeakDb?r:Math.max(-100,e.assistantPeakDb-.02*o),n<=-95){if(e.floorDb===null)return e.open=!1,e}else e.floorDb===null&&(e.floorDb=Math.min(n,-50));if(n<e.floorDb)e.floorDb+=(n-e.floorDb)*Math.min(1,.0075*o);else if(!s){var c=e.openSince!==null&&i-e.openSince>1e4,l=e.open&&!c?1e-4:56e-5;e.floorDb+=(n-e.floorDb)*Math.min(1,l*o)}if(e.floorDb<-75&&(e.floorDb=-75),s&&!e.open&&r>-50&&!a.pushToTalk){var u=n-e.assistantPeakDb;if(e.echoReturnDb===null)e.echoReturnDb=u;else{var d=e.echoLearnedMs<1e3,f=u>e.echoReturnDb?d?.02:.0012:6e-4;e.echoReturnDb+=(u-e.echoReturnDb)*Math.min(1,f*o)}e.echoLearnedMs+=o}var p=e.echoReturnDb===null?-100:e.assistantPeakDb+e.echoReturnDb,m,h;s?(m=Math.max(e.floorDb+12,p+8,-45),h=Math.max(e.floorDb+3,p+3)):(m=e.floorDb+9,h=e.floorDb+3);var g=a.speechHangoverMs||2e3;n>m?s&&!e.open?(e.aboveSince===null&&(e.aboveSince=i),i-e.aboveSince>=250&&(e.speakUntil=i+g)):e.speakUntil=i+g:(e.aboveSince=null,e.open&&n>h&&(e.speakUntil=Math.max(e.speakUntil,i+250)));var ee=i<e.speakUntil;return!s&&e.wasAssistantSpeaking&&(e.listenGraceUntil=i+1500),e.wasAssistantSpeaking=s,e.assistantSpeaking=s,e.open=a.pushToTalk?!!a.pttActive:a.bargeIn?ee:!s&&(ee||i<e.listenGraceUntil),e.open&&e.openSince===null?e.openSince=i:e.open||(e.openSince=null),e}function r(){return{floorDb:null,lastMs:null,speakUntil:0,assistantUntil:0,assistantPeakDb:-100,echoReturnDb:null,echoLearnedMs:0,aboveSince:null,listenGraceUntil:0,wasAssistantSpeaking:!1,assistantSpeaking:!1,open:!1,openSince:null}}function i(e){if(!e||!e.length)return-100;for(var t=0,n=0;n<e.length;n++)t+=e[n]*e[n];var r=Math.sqrt(t/e.length);return r>1e-7?20*Math.log10(r):-100}var a=[`var decide = `+n.toString()+`;`,`var newState = `+r.toString()+`;`,`var rmsDb = `+i.toString()+`;`,`class CoreAiMicGateProcessor extends AudioWorkletProcessor {`,` constructor(options) {`,` super();`,` var o = (options && options.processorOptions) || {};`,` this.delay = new Float32Array(Math.max(1, Math.round(sampleRate * (o.lookaheadMs || 80) / 1000)));`,` this.delayPos = 0;`,` this.gain = 0;`,` this.mode = o.mode || {};`,` this.state = newState();`,` this.lastPost = 0;`,` this.port.onmessage = function (e) { this.mode = e.data || {}; }.bind(this);`,` }`,` process(inputs, outputs) {`,` var mic = (inputs[0] && inputs[0][0]) || null;`,` var assistant = (inputs[1] && inputs[1][0]) || null;`,` var out = (outputs[0] && outputs[0][0]) || null;`,` if (!out) { return true; }`,` var micDb = rmsDb(mic);`,` decide(this.state, { micDb: micDb, assistantDb: rmsDb(assistant), nowMs: currentTime * 1000, mode: this.mode });`,` var target = this.state.open ? 1 : 0;`,` var step = 1 / (sampleRate * 0.01);`,` var delay = this.delay;`,` var pos = this.delayPos;`,` var len = delay.length;`,` for (var i = 0; i < out.length; i++) {`,` var delayed = delay[pos];`,` delay[pos] = mic ? mic[i] : 0;`,` pos = (pos + 1) % len;`,` if (this.gain < target) { this.gain = Math.min(target, this.gain + step); }`,` else if (this.gain > target) { this.gain = Math.max(target, this.gain - step); }`,` out[i] = delayed * this.gain;`,` }`,` this.delayPos = pos;`,` if (currentTime * 1000 - this.lastPost > 100) {`,` this.lastPost = currentTime * 1000;`,` this.port.postMessage({ micDb: micDb, floorDb: this.state.floorDb, echoReturnDb: this.state.echoReturnDb, open: this.state.open, assistantSpeaking: this.state.assistantSpeaking });`,` }`,` return true;`,` }`,`}`,`registerProcessor("coreai-mic-gate", CoreAiMicGateProcessor);`].join(`
|
|
2
|
+
`),o=4096,s=[`class CoreAiCaptureProcessor extends AudioWorkletProcessor {`,` constructor(options) {`,` super();`,` var o = (options && options.processorOptions) || {};`,` this.size = Math.max(128, o.frameSamples || 4096);`,` this.buf = new Float32Array(this.size);`,` this.pos = 0;`,` }`,` process(inputs) {`,` var input = (inputs[0] && inputs[0][0]) || null;`,` var n = input ? input.length : 128;`,` for (var i = 0; i < n; i++) {`,` this.buf[this.pos++] = input ? input[i] : 0;`,` if (this.pos === this.size) {`,` this.port.postMessage(this.buf);`,` this.pos = 0;`,` }`,` }`,` return true;`,` }`,`}`,`registerProcessor("coreai-pcm-capture", CoreAiCaptureProcessor);`].join(`
|
|
3
|
+
`);function c(t,n){function r(){var e=t.createScriptProcessor(o,1,1);return e.onaudioprocess=function(e){n(e.inputBuffer.getChannelData(0))},e}var i=null;if(t.audioWorklet&&typeof t.audioWorklet.addModule==`function`&&typeof AudioWorkletNode==`function`)try{i=URL.createObjectURL(new Blob([s],{type:`application/javascript`}))}catch{i=null}return i?t.audioWorklet.addModule(i).then(function(){try{URL.revokeObjectURL(i)}catch{}var e=new AudioWorkletNode(t,`coreai-pcm-capture`,{numberOfInputs:1,numberOfOutputs:1,outputChannelCount:[1],processorOptions:{frameSamples:o}});return e.port.onmessage=function(e){e.data&&n(e.data)},e}).catch(function(t){try{URL.revokeObjectURL(i)}catch{}return e.console&&console.warn&&console.warn(`The realtime capture worklet could not be loaded; falling back to a ScriptProcessorNode.`,t),r()}):Promise.resolve(r())}function l(t,n){var r=t&&t.getAudioTracks&&t.getAudioTracks()[0]||null,i={ctx:null,node:null,micSource:null,remoteSource:null,dest:null,timer:0,level:null,fallback:null,track:r,stopped:!1},o={track:r,usingWorklet:!1,getLevel:function(){return i.level},setMode:function(e){if(n=e||n,i.node&&i.node.port)try{i.node.port.postMessage(n)}catch{}i.fallback&&(i.fallback.mode=n)},attachAssistantStream:function(e){u(i,e)},stop:function(){if(i.stopped=!0,i.timer){try{e.clearInterval(i.timer)}catch{}i.timer=0}if(i.node){try{i.node.port.onmessage=null,i.node.disconnect()}catch{}i.node=null}if(i.micSource){try{i.micSource.disconnect()}catch{}i.micSource=null}if(i.remoteSource){try{i.remoteSource.disconnect()}catch{}i.remoteSource=null}if(i.dest){try{i.dest.disconnect()}catch{}i.dest=null}if(i.ctx){try{i.ctx.close()}catch{}i.ctx=null}i.fallback=null}},s=e.AudioContext||e.webkitAudioContext;if(!s||!r)return Promise.resolve(o);try{i.ctx=new s,i.ctx.state===`suspended`&&typeof i.ctx.resume==`function`&&i.ctx.resume().catch(function(){})}catch{return i.ctx=null,Promise.resolve(o)}var c=null;if(i.ctx.audioWorklet&&typeof i.ctx.audioWorklet.addModule==`function`)try{c=URL.createObjectURL(new Blob([a],{type:`application/javascript`}))}catch{c=null}return c?i.ctx.audioWorklet.addModule(c).then(function(){try{URL.revokeObjectURL(c)}catch{}if(i.stopped)return o;var a=new AudioWorkletNode(i.ctx,`coreai-mic-gate`,{numberOfInputs:2,numberOfOutputs:1,outputChannelCount:[1],processorOptions:{lookaheadMs:80,mode:n}});return i.node=a,a.port.onmessage=function(t){i.level=t.data||null,e.CoreAIRealtime.lastGateLevel=i.level},i.micSource=i.ctx.createMediaStreamSource(t),i.micSource.connect(a,0,0),i.dest=i.ctx.createMediaStreamDestination(),a.connect(i.dest),i.pendingRemoteStream&&u(i,i.pendingRemoteStream),o.track=i.dest.stream.getAudioTracks()[0]||r,o.usingWorklet=!0,o}).catch(function(a){try{URL.revokeObjectURL(c)}catch{}return e.console&&console.warn&&console.warn(`The realtime microphone gate worklet could not be loaded; using the simpler gate.`,a),o.track=d(i,t,r,n),o}):(o.track=d(i,t,r,n),Promise.resolve(o))}function u(e,t){if(e.pendingRemoteStream=t||null,e.ctx&&t&&!e.stopped)try{if(e.remoteSource)try{e.remoteSource.disconnect()}catch{}var n=e.ctx.createMediaStreamSource(t);if(e.remoteSource=n,e.node){n.connect(e.node,0,1);return}if(e.fallback){var r=e.ctx.createAnalyser();r.fftSize=2048,n.connect(r),e.fallback.remoteAnalyser=r,e.fallback.remoteData=new Float32Array(r.fftSize)}}catch{}}function d(t,a,o,s){try{var c=t.ctx,l=c.createMediaStreamSource(a);t.micSource=l;var d=c.createAnalyser();d.fftSize=2048,l.connect(d);var f=c.createGain();f.gain.value=0,l.connect(f);var p=c.createMediaStreamDestination();t.dest=p,f.connect(p);var m={mode:s,remoteAnalyser:null,remoteData:null};t.fallback=m,t.pendingRemoteStream&&u(t,t.pendingRemoteStream);var h=new Float32Array(d.fftSize),g=r();return t.timer=e.setInterval(function(){d.getFloatTimeDomainData(h);var r=i(h),a=-100;m.remoteAnalyser&&m.remoteData&&(m.remoteAnalyser.getFloatTimeDomainData(m.remoteData),a=i(m.remoteData));var o=e.performance&&performance.now?performance.now():Date.now();n(g,{micDb:r,assistantDb:a,nowMs:o,mode:m.mode||{}}),t.level={micDb:r,floorDb:g.floorDb,open:g.open,assistantSpeaking:g.assistantSpeaking};var s=+!!g.open;try{f.gain.setTargetAtTime(s,c.currentTime,.015)}catch{f.gain.value=s}},20),p.stream.getAudioTracks()[0]||o}catch{return o}}function f(e,t){if(e&&typeof e.setSinkId==`function`){if(t)try{e.setSinkId(t).catch(function(){})}catch{}else navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&navigator.mediaDevices.enumerateDevices().then(function(t){var n=t.filter(function(e){return e.kind===`audiooutput`});if(n.length){for(var r=``,i=0;i<n.length;i++)if(n[i].deviceId===`communications`){r=`communications`;break}if(!r){for(var a=null,o=0;o<n.length;o++)if(n[o].deviceId==="default"){a=n[o];break}if(a&&a.groupId){for(var s=0;s<n.length;s++)if(n[s].deviceId!=="default"&&n[s].deviceId!==`communications`&&n[s].groupId===a.groupId){r=n[s].deviceId;break}}}if(r)try{e.setSinkId(r).catch(function(){})}catch{}}}).catch(function(){})}}function p(t,n){if(t&&typeof t.play==`function`){var r=t.play();r&&typeof r.catch==`function`&&r.catch(function(t){typeof n==`function`&&n(t),e.console&&console.warn&&console.warn(`The browser blocked realtime audio playback. Interact with the page to enable audio.`,t)})}}function m(n){n||={};var r=n.connection,i=n.selectors||{},a=n.voiceName||``,o=(n.capableDeployments||[]).map(function(e){return(e||``).toLowerCase()}),s=!!n.realtimeEnabled,u=function(){},d=n.onActivate||u,m=n.onDeactivate||u,h=n.onSessionStateChanged||u,g=n.onEnterRealtimeMode||u,ee=n.onUserTurnPending||u,te=n.onUserTurnDropped||u,ne=n.strings||{};function _(e,t){return typeof ne[e]==`string`?ne[e]:t}var v=n.ensureConnected||function(){return Promise.resolve(!0)},re=n.sendStart||u,y=n.getVoiceName||null,ie=n.sendStartWebRtc||null,ae=n.webRtcEnabled===!0&&typeof e.RTCPeerConnection==`function`&&!!ie,oe=Array.isArray(n.webRtcIceServers)&&n.webRtcIceServers.length?n.webRtcIceServers:null,se=[{urls:`stun:stun.l.google.com:19302`}],ce=n.onStateChange||u,le=`idle`;function b(e){var n=i[e];return n?t.querySelector(n):null}var x=!1,ue=!1,de=null,fe=null,S=null,C=null,w=null,T=null,E=null,pe=null,me=null,D=null,O=0,k=[],A=!1,j=null,M=null,he=!1,ge=!1,_e=[],N=!1,P=null,ve=!1,ye=8e3,be=5e3,xe=150,Se=`coreai.realtime.webrtcBlocked`,F=null,Ce=0,we=!1,I=null,Te=null,L=!0,R=!1,z=!1,Ee=!1,De=null,Oe=null,B=null,V=null,H=1,U=``,ke=``,Ae=``,W=null,je=1,G=!1,Me=!1,K=null,Ne=.5,Pe=3,Fe=.75,Ie=1.5,Le=1;function Re(e){return Math.round(Math.min(Ie,Math.max(Fe,e))*100)/100}function ze(){var t={bargeIn:!0,pushToTalk:!1,volume:1,micDeviceId:``,outputDeviceId:``,language:``,speechSpeed:null,version:0};try{var n=e.localStorage.getItem(`coreai.realtime.audioPrefs`);if(n){var r=JSON.parse(n);typeof r.bargeIn==`boolean`&&(t.bargeIn=r.bargeIn),typeof r.pushToTalk==`boolean`&&(t.pushToTalk=r.pushToTalk),typeof r.volume==`number`&&isFinite(r.volume)&&(t.volume=Math.min(1,Math.max(0,r.volume))),typeof r.micDeviceId==`string`&&(t.micDeviceId=r.micDeviceId),typeof r.outputDeviceId==`string`&&(t.outputDeviceId=r.outputDeviceId),typeof r.language==`string`&&(t.language=r.language),typeof r.speechSpeed==`number`&&isFinite(r.speechSpeed)&&(t.speechSpeed=Re(r.speechSpeed)),typeof r.version==`number`&&(t.version=r.version)}}catch{}return Be(t)}function Be(e){return e.version===Pe||(e.version=Pe,e.bargeIn=!0,e.pushToTalk=!1,Ve(e)),e}function Ve(t){try{e.localStorage.setItem(`coreai.realtime.audioPrefs`,JSON.stringify(t))}catch{}}function He(e){L=e.bargeIn!==!1,R=!!e.pushToTalk,H=typeof e.volume==`number`?e.volume:1,U=e.micDeviceId||``,ke=e.outputDeviceId||``,Ae=e.language||``,W=typeof e.speechSpeed==`number`?e.speechSpeed:null,bt(),D&&(D.gain.value=H),M&&(M.volume=Math.max(0,Math.min(1,H)))}function Ue(e){if(!e||!e.tagName)return!1;var t=e.tagName.toLowerCase();return t===`input`||t===`textarea`||t===`select`||e.isContentEditable===!0}function We(){Ee||(Ee=!0,z=!1,De=function(e){R&&!Ue(e.target)&&(e.code===`Space`||e.key===` `)&&(e.preventDefault(),e.repeat||q(!0))},Oe=function(e){R&&!Ue(e.target)&&(e.code===`Space`||e.key===` `)&&(e.preventDefault(),q(!1))},t.addEventListener(`keydown`,De,!0),t.addEventListener(`keyup`,Oe,!0))}function Ge(){if(Ee){Ee=!1,z=!1;try{t.removeEventListener(`keydown`,De,!0)}catch{}try{t.removeEventListener(`keyup`,Oe,!0)}catch{}}}function q(e){z=e,bt(),B&&(B.classList.toggle(`btn-danger`,e),B.classList.toggle(`btn-outline-primary`,!e),B.innerHTML=e?`<i class="fa-solid fa-microphone me-1"></i> Listening…`:`<i class="fa-solid fa-microphone me-1"></i> Hold to talk`)}function Ke(){var n=b(`realtimeButton`);if(n&&!V){var r=e.matchMedia&&e.matchMedia(`(pointer: coarse)`).matches,i=t.createElement(`div`);i.className=`text-center mt-2`;var a=t.createElement(`button`);a.type=`button`,a.className=`btn btn-outline-primary btn-sm`,a.innerHTML=`<i class="fa-solid fa-microphone me-1"></i> Hold to talk`;var o=t.createElement(`div`);o.className=`form-text mt-1 mb-0`,o.innerHTML=r?`Push-to-talk is on — press and hold the button to speak.`:`Push-to-talk is on — hold <kbd>Space</kbd> or this button to speak.`,i.appendChild(a),i.appendChild(o);var s=n.parentElement;s&&s.parentElement?s.parentElement.appendChild(i):n.insertAdjacentElement(`afterend`,i),B=a,V=i,a.addEventListener(`pointerdown`,function(e){e.preventDefault(),q(!0)}),a.addEventListener(`pointerup`,function(){q(!1)}),a.addEventListener(`pointerleave`,function(){q(!1)}),a.addEventListener(`pointercancel`,function(){q(!1)}),q(!1)}}function qe(){if(B=null,V){try{V.remove()}catch{}V=null}}function Je(){var n=b(`realtimeButton`);if(!n||Me)return;Me=!0;var r=ze();He(r);var i=t.createElement(`span`);i.id=`realtime-audio-settings`,i.style.position=`relative`,i.style.display=`inline-flex`;var a=t.createElement(`button`);a.type=`button`,a.className=`btn btn-outline-secondary`,a.title=_(`settingsTitle`,`Voice settings`),a.setAttribute(`aria-label`,_(`settingsTitle`,`Voice settings`)),a.innerHTML=`<i class="fa-solid fa-headset"></i>`;var o=`<option value=""`+(r.language===``?` selected`:``)+`>`+_(`languageAuto`,`Automatic`)+`</option>`+[[`en`,`English`],[`es`,`Spanish`],[`fr`,`French`],[`de`,`German`],[`it`,`Italian`],[`pt`,`Portuguese`],[`nl`,`Dutch`],[`zh`,`Chinese`],[`ja`,`Japanese`],[`ko`,`Korean`],[`ar`,`Arabic`],[`hi`,`Hindi`],[`ru`,`Russian`]].map(function(e){return`<option value="`+e[0]+`"`+(r.language===e[0]?` selected`:``)+`>`+e[1]+`</option>`}).join(``),s=t.createElement(`div`);s.className=`card shadow-sm`,s.style.cssText=`position:absolute;bottom:calc(100% + 6px);right:0;z-index:1080;width:290px;max-height:70vh;overflow:auto;display:none;`,s.innerHTML=`<div class="card-body p-3"><div class="fw-semibold mb-2" style="font-size:0.85rem;">`+_(`settingsTitle`,`Voice settings`)+`</div><label class="form-label mb-1 d-block" style="font-size:0.8rem;">`+_(`microphone`,`Microphone`)+`</label><select class="form-select form-select-sm js-mic mb-2"><option value="">`+_(`defaultMicrophone`,`Default microphone`)+`</option></select><label class="form-label mb-1 d-block" style="font-size:0.8rem;">`+_(`speaker`,`Speaker`)+`</label><select class="form-select form-select-sm js-out mb-1"><option value="">`+_(`automatic`,`Automatic`)+`</option></select><button type="button" class="btn btn-outline-secondary btn-sm mb-2 js-pick-out" style="display:none;">`+_(`chooseSpeaker`,`Choose speaker…`)+`</button><div class="form-text mb-2 js-out-help">`+_(`speakerHelp`,`Automatic uses the device your system uses for calls. If you cannot hear the assistant, pick the speakers you are actually listening to.`)+`</div><label class="form-label mb-1 d-block" style="font-size:0.8rem;">`+_(`assistantVolume`,`Assistant volume`)+`: <strong class="js-vol-val">`+Math.round(r.volume*100)+`</strong>%</label><input type="range" class="form-range js-vol mb-2" min="0" max="100" step="5" value="`+Math.round(r.volume*100)+`"><div class="js-speed-row" hidden><label class="form-label mb-1 d-flex align-items-baseline" style="font-size:0.8rem;"><span>`+_(`speechSpeed`,`Speaking speed`)+`: <strong class="js-speed-val">1.00</strong>×</span><button type="button" class="btn btn-link btn-sm p-0 ms-auto js-speed-reset" style="font-size:0.8rem;" hidden>`+_(`speechSpeedReset`,`Reset`)+`</button></label><input type="range" class="form-range js-speed mb-0" min="`+Fe+`" max="`+Ie+`" step="0.05" value="`+Le+`"><div class="form-text mt-0 mb-2">`+_(`speechSpeedHelp`,`Applies from the assistant's next reply.`)+`</div></div><label class="form-label mb-1 d-block" style="font-size:0.8rem;">`+_(`language`,`Language`)+`</label><select class="form-select form-select-sm js-lang mb-2">`+o+`</select><div class="form-check form-switch mb-1"><input class="form-check-input js-barge" type="checkbox" id="realtime-setting-barge"`+(r.bargeIn?` checked`:``)+`><label class="form-check-label" for="realtime-setting-barge">`+_(`allowInterruptions`,`Allow interruptions`)+`</label></div><div class="form-text mb-2">`+_(`allowInterruptionsHelp`,`Talk over the assistant to interrupt it. Turn this off if the assistant keeps hearing itself through your speakers.`)+`</div><div class="form-check form-switch mb-1"><input class="form-check-input js-ptt" type="checkbox" id="realtime-setting-ptt"`+(r.pushToTalk?` checked`:``)+`><label class="form-check-label" for="realtime-setting-ptt">`+_(`pushToTalk`,`Push-to-talk`)+`</label></div><div class="form-text">`+_(`pushToTalkHelp`,`Hold <kbd>Space</kbd> (or the button) to talk. For very noisy places.`)+`</div></div>`,i.appendChild(a),i.appendChild(s),n.insertAdjacentElement(`afterend`,i),K=i;var c=s.querySelector(`.js-barge`),l=s.querySelector(`.js-ptt`),u=s.querySelector(`.js-vol`),d=s.querySelector(`.js-vol-val`),f=s.querySelector(`.js-mic`),p=s.querySelector(`.js-out`),m=s.querySelector(`.js-pick-out`),h=s.querySelector(`.js-lang`),g=s.querySelector(`.js-speed`),ee=s.querySelector(`.js-speed-val`),te=s.querySelector(`.js-speed-reset`);function ne(){return{bargeIn:c.checked,pushToTalk:l.checked,volume:(parseInt(u.value,10)||0)/100,micDeviceId:f.value||``,outputDeviceId:p.value||``,language:h.value||``,speechSpeed:W,version:Pe}}function v(){var e=ne();He(e),Ve(e),Ze()}function re(e){W=e,Ve(ne()),et(),tt()}function y(){navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&navigator.mediaDevices.enumerateDevices().then(function(e){var t=[`<option value="">`+_(`defaultMicrophone`,`Default microphone`)+`</option>`];e.filter(function(e){return e.kind===`audioinput`}).forEach(function(e,n){var r=e.label||_(`microphone`,`Microphone`)+` `+(n+1);t.push(`<option value="`+e.deviceId+`"`+(e.deviceId===U?` selected`:``)+`>`+r.replace(/</g,``)+`</option>`)}),f.innerHTML=t.join(``);var n=e.filter(function(e){return e.kind===`audiooutput`&&e.deviceId&&e.deviceId!==`communications`&&e.deviceId!=="default"});if(n.length){var r=[`<option value="">`+_(`automatic`,`Automatic`)+`</option>`];n.forEach(function(e,t){var n=e.label||_(`speaker`,`Speaker`)+` `+(t+1);r.push(`<option value="`+e.deviceId+`"`+(e.deviceId===ke?` selected`:``)+`>`+n.replace(/</g,``)+`</option>`)}),p.innerHTML=r.join(``)}}).catch(function(){})}y(),navigator.mediaDevices&&typeof navigator.mediaDevices.addEventListener==`function`&&navigator.mediaDevices.addEventListener(`devicechange`,function(){y(),x&&U&&navigator.mediaDevices.enumerateDevices().then(function(e){e.some(function(e){return e.kind===`audioinput`&&e.deviceId===U})||X(`device_lost`)}).catch(function(){})});function ie(){s.style.right=`0px`,s.style.left=`auto`;var n=s.getBoundingClientRect();n.left<8&&(s.style.right=n.left-8+`px`);for(var r=a.getBoundingClientRect(),i=8,o=s.parentElement?s.parentElement.parentElement:null;o&&o!==t.body&&o!==t.documentElement;){var c=e.getComputedStyle(o);if(c.overflowY===`auto`||c.overflowY===`scroll`||c.overflowY===`hidden`||c.position===`fixed`){i=Math.max(i,o.getBoundingClientRect().top);break}o=o.parentElement}s.style.maxHeight=Math.max(160,r.top-i-10)+`px`}a.addEventListener(`click`,function(e){e.stopPropagation();var t=s.style.display===`none`;t&&(s.style.display=`block`,ie(),y()),s.style.display=t?`block`:`none`}),s.addEventListener(`click`,function(e){e.stopPropagation()}),t.addEventListener(`click`,function(){s.style.display=`none`}),c.addEventListener(`change`,v),l.addEventListener(`change`,v),u.addEventListener(`input`,function(){d.textContent=u.value,v()}),g.addEventListener(`input`,function(){ee.textContent=Qe(parseFloat(g.value))}),g.addEventListener(`change`,function(){re(Re(parseFloat(g.value)))}),te.addEventListener(`click`,function(){re(null)}),f.addEventListener(`change`,v),h.addEventListener(`change`,v),p.addEventListener(`change`,function(){v(),wt()}),navigator.mediaDevices&&typeof navigator.mediaDevices.selectAudioOutput==`function`&&(m.style.display=``,m.addEventListener(`click`,function(){navigator.mediaDevices.selectAudioOutput().then(function(e){if(e&&e.deviceId){var n=t.createElement(`option`);n.value=e.deviceId,n.textContent=e.label||_(`selectedSpeaker`,`Selected speaker`),p.appendChild(n),p.value=e.deviceId,v(),wt()}}).catch(function(){})}))}function Ye(n,r){if(r){if(e.DOMPurify&&typeof e.DOMPurify.sanitize==`function`)n.replaceChildren(e.DOMPurify.sanitize(r,{RETURN_DOM_FRAGMENT:!0}));else{var i=r.replace(/<[^>]*>/g,` `).replace(/\s+/g,` `).trim();n.replaceChildren(t.createTextNode(i))}}}function J(){h(x);var e=b(`realtimeButton`);e&&(x?(e.classList.add(`active`,`btn-primary`),e.classList.remove(`btn-dark`,`btn-outline-dark`,`btn-outline-secondary`),e.title=e.getAttribute(`data-end-title`)||`End Conversation`,Ye(e,e.getAttribute(`data-end-html`))):(e.classList.remove(`active`,`btn-primary`,`btn-dark`,`btn-outline-secondary`),e.classList.add(`btn-outline-dark`),e.blur(),e.title=e.getAttribute(`data-start-title`)||`Start speaking`,Ye(e,e.getAttribute(`data-start-html`))))}function Xe(e){s=e;var t=b(`realtimeButton`),n=b(`micButton`),r=b(`conversationButton`),i=b(`input`),a=b(`sendButton`),o=K;e?(g(),i&&(i.hidden=!0),a&&(a.hidden=!0),n&&(n.hidden=!0),r&&(r.hidden=!0),t&&(t.hidden=!1),o&&(o.hidden=!1)):(x&&$(),t&&(t.hidden=!0),o&&(o.hidden=!0),dt(),at(),i&&(i.hidden=!1),a&&(a.hidden=!1),n&&(n.hidden=!1),r&&(r.hidden=!1)),J()}function Ze(){if(x&&r&&typeof r.send==`function`)try{r.send(`UpdateRealtimeSettings`,L,null,null)}catch{}}function Qe(e){return(isFinite(e)?e:Le).toFixed(2)}function $e(){return W===null?je:W}function et(){if(K){var e=K.querySelector(`.js-speed-row`),t=K.querySelector(`.js-speed`),n=K.querySelector(`.js-speed-val`),r=K.querySelector(`.js-speed-reset`);if(e&&t&&n&&r){var i=$e();e.hidden=!G,t.value=String(i),n.textContent=Qe(i),r.hidden=W===null}}}function tt(){if(x&&G&&r&&typeof r.send==`function`)try{r.send(`UpdateRealtimeSpeechSpeed`,$e())}catch{}}function nt(e){var t=parseFloat(e);G=isFinite(t),je=G?t:Le,et(),W!==null&&W!==je&&tt()}var rt={"requesting-mic":_(`requestingMic`,`Waiting for microphone access…`),connecting:_(`connecting`,`Connecting…`),listening:_(`listening`,`Listening`),"playback-blocked":_(`playbackBlocked`,`Audio is blocked by the browser — click the page to enable it.`)};function Y(e,t){if(le!==e){le=e;var n=rt[e];n?Z(n,!1):e===`idle`&&at();try{ce({state:e,transport:A?`webrtc`:`websocket`,detail:t||null})}catch{}}}function it(){!ue&&r&&(ue=!0,r.on(`ReceiveRealtimeEvent`,function(e,t,n){x&&(t===`speech_speed`?nt(n):t===`session_ready`?Y(`listening`):t===`session_ended`?X(n||`completed`):t===`speech_started`?L&&jt():t===`playback_flush`?jt():t===`user_turn_pending`?ee(n):t===`user_turn_dropped`&&te(n))}),r.on(`ReceiveError`,function(){x&&(A&&!N&&!ve?Q(`server reported an error before the peer connected`):X(`error`))}),typeof r.onclose==`function`&&r.onclose(function(){x&&X(`disconnected`)}),typeof r.onreconnecting==`function`&&r.onreconnecting(function(){x&&X(`disconnected`)}))}function X(t){de=t,$(),Y(`ended`,t),e.console&&console.info&&console.info(`The realtime voice session ended (`+t+`).`),t===`idle`?Z(_(`endedIdle`,`Voice paused after a period of silence.`),!0):t===`max_duration`?Z(_(`endedMaxDuration`,`Voice paused — this session reached its time limit. You can start another.`),!0):t===`disconnected`?Z(_(`endedDisconnected`,`Voice session ended — the connection dropped.`),!0):t===`error`?Z(_(`endedError`,`Voice session ended unexpectedly.`),!0):t===`device_lost`&&Z(_(`endedDeviceLost`,`Voice session ended — the microphone was disconnected.`),!0)}function Z(e,n){var r=b(`realtimeButton`);if(r){if(!S){S=t.createElement(`div`),S.className=`form-text mt-2 mb-0 text-center`,S.setAttribute(`role`,`status`),S.setAttribute(`aria-live`,`polite`);var i=r.parentElement;i&&i.parentElement?i.parentElement.appendChild(S):r.insertAdjacentElement(`afterend`,S)}if(S.replaceChildren(),S.appendChild(t.createTextNode(e)),n){var a=t.createElement(`button`);a.type=`button`,a.className=`btn btn-link btn-sm p-0 ms-2 align-baseline`,a.textContent=_(`resume`,`Resume`),a.addEventListener(`click`,function(){at(),ft()}),S.appendChild(a)}}}function at(){if(S){try{S.remove()}catch{}S=null}}function ot(){return oe?Promise.resolve(oe):F?Promise.resolve(F):!r||typeof r.invoke!=`function`?Promise.resolve(se):r.invoke(`GetRealtimeIceServers`).then(function(e){return F=Array.isArray(e)&&e.length?e:se,F}).catch(function(t){return e.console&&console.warn&&console.warn(`Could not resolve the realtime ICE servers; using the default STUN server.`,t),F=se,F})}function st(e){var t=[];try{(e||[]).forEach(function(e){var n=e&&e.urls;typeof n==`string`?t.push(n):Array.isArray(n)&&n.forEach(function(e){e&&t.push(e)})})}catch{return`none`}return t.length?t.sort().join(`|`):`none`}function ct(t){try{return e.sessionStorage.getItem(Se)===st(t)}catch{return!1}}function lt(){try{e.sessionStorage.setItem(Se,st(F||oe))}catch{}}function ut(){if(!fe){var e=b(`realtimeButton`);if(e){var n=t.createElement(`div`);n.className=`form-text mt-2 mb-0 text-center`,n.setAttribute(`role`,`status`),n.textContent=_(`compatibilityMode`,`Using compatibility audio mode. Echo cancellation may be weaker — headphones are recommended.`);var r=e.parentElement;r&&r.parentElement?r.parentElement.appendChild(n):e.insertAdjacentElement(`afterend`,n),fe=n}}}function dt(){if(fe){try{fe.remove()}catch{}fe=null}}function ft(){if(s&&!x&&r){He(ze()),F=null;var e=++Ce;ve=!1,G=!1,et(),de=null,at(),it(),Y(`requesting-mic`),ae?ot().then(function(t){e===Ce&&s&&!x&&(ct(t)?(Dt(`a WebRTC attempt already failed earlier in this browser session with the same ICE configuration`),pt()):mt())}):(Dt(`the server did not advertise the WebRTC transport`),pt())}}function pt(){ae&&ut(),We();var t=b(`realtimeButton`);if(t)try{t.blur()}catch{}var n={channelCount:1,echoCancellation:{ideal:!0},noiseSuppression:!0,autoGainControl:!0,echoCancellationType:{ideal:`system`},voiceIsolation:{ideal:!0}};U&&(n.deviceId={exact:U}),navigator.mediaDevices.getUserMedia({audio:n}).then(function(t){v().then(function(){C=t,x=!0,d(),J(),Y(`connecting`),w=new(e.AudioContext||e.webkitAudioContext)({sampleRate:24e3}),w.state===`suspended`&&typeof w.resume==`function`&&w.resume().catch(function(t){Y(`playback-blocked`),e.console&&console.warn&&console.warn(`The browser blocked realtime audio playback. Interact with the page to enable audio.`,t)}),O=0,k=[],D=w.createGain(),D.gain.value=H??1,D.connect(w.destination),T=new e.signalR.Subject;var n=w,r=w.createGain();r.gain.value=0,me=r,r.connect(w.destination);var i=w.createMediaStreamDestination();D.connect(i),c(w,function(e){var t=R?!z:!L&&w&&w.currentTime<O+Ne,n=new Int16Array(e.length);if(!t)for(var r=0;r<e.length;r++){var i=Math.max(-1,Math.min(1,e[r]));n[r]=i<0?i*32768:i*32767}for(var a=new Uint8Array(n.buffer),o=``,s=0;s<a.length;s++)o+=String.fromCharCode(a[s]);try{T.next(btoa(o))}catch{}}).then(function(e){if(!x||w!==n)try{e.disconnect()}catch{}else E=e,e.connect(r),xt(t).then(function(t){if(x&&w===n&&t){var r=new MediaStream([t]),a=w.createMediaStreamSource(r);pe=a,a.connect(e),I&&I.attachAssistantStream(i.stream)}})});var o=Ae||null,s=y&&y()||a||``;re(T,s,o,null,null,L),R&&Ke()}).catch(function(e){t.getTracks().forEach(function(e){e.stop()}),x=!1,m(),J(),console.error(`The realtime conversation could not start because the chat connection is not available.`,e)})}).catch(function(e){console.error(`Microphone access denied:`,e),x=!1,m(),J()})}function mt(){var e={echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0};U&&(e.deviceId={exact:U}),navigator.mediaDevices.getUserMedia({audio:e}).then(function(e){v().then(function(){return ot()}).then(function(n){C=e,x=!0,A=!0,d(),J(),Y(`connecting`),ge=!1,_e=[],N=!1;var i=new RTCPeerConnection({iceServers:n});j=i,We();var o=b(`realtimeButton`);if(o)try{o.blur()}catch{}R&&Ke();var s=t.createElement(`audio`);s.autoplay=!0,s.style.display=`none`,s.volume=Math.max(0,Math.min(1,H??1)),t.body.appendChild(s),M=s,Tt(s),i.ontrack=function(e){try{e.receiver&&`jitterBufferTarget`in e.receiver&&(e.receiver.jitterBufferTarget=xe)}catch{}e.streams&&e.streams[0]&&(s.srcObject=e.streams[0],Et(s),St(e.streams[0]))},we=!1,i.onicecandidate=function(e){if(e.candidate){e.candidate.candidate&&e.candidate.candidate.indexOf(` relay `)!==-1&&(we=!0);try{r.send(`AddRealtimeIceCandidate`,e.candidate.candidate,e.candidate.sdpMid||``,e.candidate.sdpMLineIndex||0)}catch{}}else!we&&!N&&P&&(clearTimeout(P),P=setTimeout(function(){!N&&x&&Q(`no relay candidate and no direct connection`)},be))},i.onconnectionstatechange=function(){i.connectionState===`connected`?_t():i.connectionState===`failed`?N?x&&$():Q(`connection failed`):i.connectionState===`closed`&&x&&N&&$()},i.oniceconnectionstatechange=function(){var e=i.iceConnectionState;e===`connected`||e===`completed`?_t():e===`failed`&&!N&&Q(`ICE failed`)},ht(),P=setTimeout(function(){!N&&x&&Q(`connection timed out`)},ye),xt(e).then(function(t){return j===i?(t&&i.addTrack(t,e),i.createOffer()):null}).then(function(e){return!e||j!==i?null:i.setLocalDescription(e).then(function(){return e})}).then(function(e){if(e){var t=Ae||null,n=y&&y()||a||``;ie(e.sdp,n,t,null,null,L)}}).catch(function(e){console.error(`Failed to create the WebRTC offer; falling back to WebSocket.`,e),Q(`offer failed`)})}).catch(function(t){e.getTracks().forEach(function(e){e.stop()}),x=!1,A=!1,m(),J(),console.error(`The realtime WebRTC conversation could not start because the chat connection is not available.`,t)})}).catch(function(e){console.error(`Microphone access denied:`,e),x=!1,A=!1,m(),J()})}function ht(){he||(he=!0,r.on(`ReceiveRealtimeAnswer`,function(e){j&&j.setRemoteDescription({type:`answer`,sdp:e}).then(function(){ge=!0;var e=_e;_e=[],e.forEach(function(e){try{j.addIceCandidate(e).catch(function(){})}catch{}})}).catch(function(e){console.error(`Failed to apply the WebRTC answer.`,e)})}),r.on(`ReceiveRealtimeIceCandidate`,function(e,t,n){if(j&&e){var r={candidate:e,sdpMid:t,sdpMLineIndex:n};if(ge)try{j.addIceCandidate(r).catch(function(){})}catch{}else _e.push(r)}}))}function gt(){if(Ct(),j){try{j.close()}catch{}j=null}if(M){try{M.srcObject=null,M.remove()}catch{}M=null}A=!1}function _t(){N||(N=!0,P&&=(clearTimeout(P),null))}var vt=2e3;function yt(){return{pushToTalk:!!R,pttActive:!!z,bargeIn:!!L,speechHangoverMs:vt}}function bt(){I&&I.setMode(yt())}function xt(e){Ct();var t=e&&e.getAudioTracks()[0]||null;return l(e,yt()).then(function(e){return I=e,Te&&e.attachAssistantStream(Te),e.track||t})}function St(e){Te=e||null,I&&e&&I.attachAssistantStream(e)}function Ct(){if(I){try{I.stop()}catch{}I=null}Te=null}function wt(){f(M,ke)}function Tt(e){f(e,ke)}function Et(e){p(e,function(){Y(`playback-blocked`)})}function Dt(t){e.console&&console.warn&&console.warn(`Realtime is using the WebSocket transport (`+t+`); acoustic echo cancellation is weaker than on WebRTC.`)}function Q(t){if(!ve){ve=!0,P&&=(clearTimeout(P),null),e.console&&console.warn&&console.warn(`Realtime WebRTC transport unavailable (`+t+`); falling back to the WebSocket transport.`),lt(),ut();try{C&&C.getTracks().forEach(function(e){e.stop()})}catch{}C=null,gt(),A=!1,x=!1,pt()}}function $(){if(x){if(P&&=(clearTimeout(P),null),x=!1,m(),J(),Ge(),qe(),de||Y(`idle`),A){gt();try{C&&C.getTracks().forEach(function(e){e.stop()})}catch{}C=null}else{try{T&&T.complete()}catch{}T=null,Ct();try{E&&(E.disconnect(),E.onaudioprocess=null,E.port&&(E.port.onmessage=null,E.port.close()))}catch{}try{pe&&pe.disconnect()}catch{}try{me&&me.disconnect()}catch{}try{D&&D.disconnect()}catch{}try{C&&C.getTracks().forEach(function(e){e.stop()})}catch{}E=null,pe=null,me=null,D=null,C=null,jt();try{w&&w.close()}catch{}w=null}}}function Ot(){x?$():ft()}function kt(){return!j||typeof j.getStats!=`function`?Promise.resolve(null):j.getStats().then(function(e){var t={transport:`webrtc`,inbound:null,codec:null,sinkId:M&&typeof M.sinkId==`string`?M.sinkId:null,jitterBufferTargetMs:(function(){try{var e=j.getReceivers().filter(function(e){return e.track&&e.track.kind===`audio`})[0];return e&&`jitterBufferTarget`in e?e.jitterBufferTarget:null}catch{return null}})()};return e.forEach(function(n){if(n.type===`inbound-rtp`&&n.kind===`audio`&&(t.inbound={packetsReceived:n.packetsReceived,packetsLost:n.packetsLost,packetsDiscarded:n.packetsDiscarded,jitterMs:typeof n.jitter==`number`?Math.round(n.jitter*1e3):null,jitterBufferDelayMs:typeof n.jitterBufferDelay==`number`&&n.jitterBufferEmittedCount?Math.round(n.jitterBufferDelay/n.jitterBufferEmittedCount*1e3):null,totalSamplesReceived:n.totalSamplesReceived,concealedSamples:n.concealedSamples,concealmentEvents:n.concealmentEvents,silentConcealedSamples:n.silentConcealedSamples,insertedSamplesForDeceleration:n.insertedSamplesForDeceleration,removedSamplesForAcceleration:n.removedSamplesForAcceleration,audioLevel:n.audioLevel},n.codecId)){var r=e.get(n.codecId);r&&(t.codec={mimeType:r.mimeType,clockRate:r.clockRate,channels:r.channels,sdpFmtpLine:r.sdpFmtpLine})}}),t}).catch(function(){return null})}function At(e){if(!(!w||!e||e.length<2)){for(var t=w,n=Math.floor(e.length/2),r=new Int16Array(e.buffer,e.byteOffset,n),i=new Float32Array(n),a=0;a<n;a++)i[a]=r[a]/32768;var o=t.createBuffer(1,n,t.sampleRate);o.copyToChannel(i,0);var s=t.createBufferSource();s.buffer=o,s.connect(D||t.destination);var c=t.currentTime;O<c&&(O=c),s.start(O),O+=o.duration,k.push(s),s.onended=function(){k=k.filter(function(e){return e!==s})}}}function jt(){k.forEach(function(e){try{e.stop()}catch{}}),k=[],w&&(O=w.currentTime)}function Mt(e){return e?o.indexOf(e.toLowerCase())!==-1:!1}var Nt=b(`realtimeButton`);Nt&&(Nt.addEventListener(`click`,function(e){e&&e.detail===0&&x||Ot()}),Je());var Pt=b(`deploymentSelect`);Pt&&Pt.addEventListener(`change`,function(){Xe(Mt(Pt.value))}),Xe(s||Pt&&Mt(Pt.value));var Ft={toggle:Ot,start:ft,stop:$,applyMode:Xe,isRealtimeDeployment:Mt,receivePcm:At,isActive:function(){return x},getState:function(){return le},getGateLevel:function(){return I?I.getLevel():null},getTransportStats:kt};return e.CoreAIRealtime.activeController=Ft,Ft}e.CoreAIRealtime={attach:m,createMicGate:l,decideGate:n,createGateState:r,rmsDb:i,routeOutputToPreferredDevice:f,ensurePlayback:p}})(window,document)})();
|
|
2
4
|
//# sourceMappingURL=realtime-audio.min.js.map
|