holostaff-widget 2.1.1 → 2.1.3
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/{BufferResource-BsFZBMrk.js → BufferResource-Drqe9ZKX.js} +2 -2
- package/dist/{BufferResource-BsFZBMrk.js.map → BufferResource-Drqe9ZKX.js.map} +1 -1
- package/dist/{CanvasRenderer-B96cLgwp.js → CanvasRenderer-COWnLCuX.js} +3 -3
- package/dist/{CanvasRenderer-B96cLgwp.js.map → CanvasRenderer-COWnLCuX.js.map} +1 -1
- package/dist/{RenderTargetSystem-PMYeATEG.js → RenderTargetSystem-LdwnobMn.js} +2 -2
- package/dist/{RenderTargetSystem-PMYeATEG.js.map → RenderTargetSystem-LdwnobMn.js.map} +1 -1
- package/dist/{WebGLRenderer-C1eYS7oS.js → WebGLRenderer-clYIdI4A.js} +4 -4
- package/dist/{WebGLRenderer-C1eYS7oS.js.map → WebGLRenderer-clYIdI4A.js.map} +1 -1
- package/dist/{WebGPURenderer-7v4zfBVl.js → WebGPURenderer-JogCv1An.js} +4 -4
- package/dist/{WebGPURenderer-7v4zfBVl.js.map → WebGPURenderer-JogCv1An.js.map} +1 -1
- package/dist/{browserAll-Ch2G05sn.js → browserAll-Cn0_K3iB.js} +3 -3
- package/dist/{browserAll-Ch2G05sn.js.map → browserAll-Cn0_K3iB.js.map} +1 -1
- package/dist/hs-widget.es.js +1 -1
- package/dist/hs-widget.umd.js +6 -9
- package/dist/hs-widget.umd.js.map +1 -1
- package/dist/{index-c7eMXWz7.js → index-DKhmD0G-.js} +18 -20
- package/dist/{index-c7eMXWz7.js.map → index-DKhmD0G-.js.map} +1 -1
- package/dist/{webworkerAll-Ry9SJQ00.js → webworkerAll-u4U5Puve.js} +2 -2
- package/dist/{webworkerAll-Ry9SJQ00.js.map → webworkerAll-u4U5Puve.js.map} +1 -1
- package/package.json +1 -1
package/dist/hs-widget.es.js
CHANGED
package/dist/hs-widget.umd.js
CHANGED
|
@@ -919,19 +919,16 @@ fn mainFragment(
|
|
|
919
919
|
out vec4 finalColor;
|
|
920
920
|
|
|
921
921
|
uniform sampler2D uTexture;
|
|
922
|
+
uniform float uThreshold;
|
|
923
|
+
uniform float uSmoothness;
|
|
922
924
|
|
|
923
925
|
void main(void) {
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
// Sample alpha from the bottom half (grayscale → use .r as alpha)
|
|
929
|
-
vec2 alphaUV = vec2(vTextureCoord.x, vTextureCoord.y * 0.5 + 0.5);
|
|
930
|
-
float alpha = texture(uTexture, alphaUV).r;
|
|
931
|
-
|
|
926
|
+
vec4 color = texture(uTexture, vTextureCoord);
|
|
927
|
+
float luma = dot(color.rgb, vec3(0.299, 0.587, 0.114));
|
|
928
|
+
float alpha = smoothstep(uThreshold, uThreshold + uSmoothness, luma);
|
|
932
929
|
finalColor = vec4(color.rgb * alpha, alpha);
|
|
933
930
|
}
|
|
934
|
-
`;class by extends Dr{constructor(){const t=je.from({vertex:yy,fragment:xy});super({glProgram:t,resources:{stackedUniforms:{uDummy:{value:0,type:"f32"}}}})}}const os=200,de=os*(832/624),Hc=280;class vy{constructor(t,e){this.idleSprite=null,this.idleGroup=null,this.liveSprite=null,this.glowGraphic=null,this.videoElement=null,this.liveVideoElement=null,this.cancelGlow=null,this.cancelEntrance=null,this.visible=!1,this.stageWidth=t,this.stageHeight=e,this.container=new kt,this.container.visible=!1,this.container.y=e+de}async loadIdleVideo(t){this.videoElement=document.createElement("video"),this.videoElement.src=t,this.videoElement.loop=!0,this.videoElement.muted=!0,this.videoElement.playsInline=!0,this.videoElement.crossOrigin="anonymous",this.videoElement.style.display="none",document.body.appendChild(this.videoElement),await this.videoElement.play();const e=$.from(this.videoElement);this.idleSprite=new ye(e),this.idleSprite.width=os,this.idleSprite.height=de,this.idleSprite.anchor.set(.5,1),this.idleSprite.filters=[new by],this.idleGroup=new kt,this.idleGroup.addChild(this.idleSprite),this.container.addChild(this.idleGroup),this.container.x=this.stageWidth/2,this.container.y=this.stageHeight+de}async loadIdleImage(t){const e=$.from(t);this.idleSprite=new ye(e),this.idleSprite.width=os,this.idleSprite.height=de,this.idleSprite.anchor.set(.5,1),this.idleGroup=new kt,this.idleGroup.addChild(this.idleSprite),this.container.addChild(this.idleGroup),this.container.x=this.stageWidth/2,this.container.y=this.stageHeight+de}slideIn(t){if(this.visible)return;this.visible=!0;const e=this.stageHeight-10;this.container.alpha=1,this.container.visible=!0,this.container.y=this.stageHeight+de,this.cancelEntrance=Ai({target:this.container,props:{y:e},duration:700,easing:ti.easeOutBack,ticker:t}),this.idleGroup&&setTimeout(()=>{this.idleGroup&&(this.cancelGlow=Nc(this.idleGroup,t,.85,1,2500))},700)}slideOut(t){var e;this.visible&&(this.visible=!1,(e=this.cancelGlow)==null||e.call(this),this.cancelGlow=null,Ai({target:this.container,props:{y:this.stageHeight+de},duration:450,easing:ti.easeInCubic,ticker:t,onComplete:()=>{this.container.visible=!1}}))}get isVisible(){return this.visible}setInteractive(t){this.container.eventMode="static",this.container.cursor="pointer";const e=new bi;e.roundRect(-os/2,-de,os,de,12),e.fill({color:16777215,alpha:.001}),this.container.addChildAt(e,0),this.container.on("pointertap",t),this.container.on("pointerenter",()=>{this.container&&this.container.scale.set(1.04)}),this.container.on("pointerleave",()=>{this.container&&this.container.scale.set(1)})}setLiveVideo(t,e){this.liveVideoElement=t;const i=()=>{var l;const r=$.from(t);this.liveSprite=new ye(r);const n=t.videoWidth||1,o=t.videoHeight||1,a=Hc/n;this.liveSprite.width=Hc,this.liveSprite.height=o*a,this.liveSprite.anchor.set(.5,1),this.liveSprite.alpha=0,this.container.addChild(this.liveSprite),this.idleGroup&&(this.idleGroup.visible=!1),(l=this.cancelGlow)==null||l.call(this),this.cancelGlow=null,Ai({target:this.liveSprite,props:{alpha:1},duration:500,easing:ti.easeInOutSine,ticker:e})};if(t.videoWidth>0&&t.videoHeight>0)i();else{const r=()=>{t.removeEventListener("loadeddata",r),t.removeEventListener("resize",r),i()};t.addEventListener("loadeddata",r),t.addEventListener("resize",r)}}clearLiveVideo(t){this.liveSprite&&Ai({target:this.liveSprite,props:{alpha:0},duration:400,easing:ti.easeInCubic,ticker:t,onComplete:()=>{var e;(e=this.liveSprite)==null||e.destroy(),this.liveSprite=null,this.liveVideoElement=null}}),this.idleGroup&&(this.idleGroup.visible=!0,this.idleSprite&&(this.idleSprite.alpha=1)),this.idleGroup&&(this.cancelGlow=Nc(this.idleGroup,t,.85,1,2500))}destroy(){var t,e;(t=this.cancelGlow)==null||t.call(this),(e=this.cancelEntrance)==null||e.call(this),this.videoElement&&(this.videoElement.pause(),this.videoElement.remove()),this.container.destroy({children:!0})}}const jn=18,Wc=12,Ey=20,Ty=240,zs=14,Sy=35,Cy=2500,Vc=300,wy=16777215,Ay=13160666,Ry=1.5,Py=3820124,Iy=.1,My=["Got questions? Click me!","I can guide you through this page","Need help? Let’s chat!"];class ky{constructor(t,e){this.promptIndex=0,this.charIndex=0,this.phase="idle",this.phaseElapsed=0,this.cancelFade=null,this.tickCb=null,this.running=!1,this.ticker=t,this.prompts=e!=null&&e.length?e:My,this.container=new kt,this.container.alpha=0,this.container.visible=!1,this.bg=new bi,this.container.addChild(this.bg),this.label=new ng({text:"",style:{fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',fontSize:13,fontWeight:"500",fill:2763326,wordWrap:!0,wordWrapWidth:Ty-jn*2,lineHeight:19}}),this.label.x=jn,this.label.y=Wc,this.container.addChild(this.label),this.container.eventMode="static",this.container.cursor="pointer"}start(){this.running||(this.running=!0,this.container.visible=!0,this.promptIndex=0,this.beginTyping(),this.tickCb=t=>this.update(t.deltaMS),this.ticker.add(this.tickCb))}stop(){var t;this.running&&(this.running=!1,this.phase="idle",this.tickCb&&this.ticker.remove(this.tickCb),this.tickCb=null,(t=this.cancelFade)==null||t.call(this),this.cancelFade=null,this.container.visible=!1,this.container.alpha=0)}beginTyping(){this.charIndex=0,this.phaseElapsed=0,this.phase="typing",this.label.text="",this.drawBubble(),this.container.alpha=0,this.cancelFade=Ai({target:this.container,props:{alpha:1},duration:Vc,easing:ti.easeOutCubic,ticker:this.ticker})}update(t){var e;if(this.phase==="typing"){this.phaseElapsed+=t;const i=this.prompts[this.promptIndex],r=Math.min(Math.floor(this.phaseElapsed/Sy),i.length);r!==this.charIndex&&(this.charIndex=r,this.label.text=i.substring(0,this.charIndex),this.drawBubble()),this.charIndex>=i.length&&(this.phase="holding",this.phaseElapsed=0)}else this.phase==="holding"&&(this.phaseElapsed+=t,this.phaseElapsed>=Cy&&(this.phase="fading",this.phaseElapsed=0,(e=this.cancelFade)==null||e.call(this),this.cancelFade=Ai({target:this.container,props:{alpha:0},duration:Vc,easing:ti.easeInCubic,ticker:this.ticker,onComplete:()=>{this.promptIndex=(this.promptIndex+1)%this.prompts.length,this.beginTyping()}})))}drawBubble(){const t=Math.max(this.label.width,50),e=Math.max(this.label.height,18),i=t+jn*2,r=e+Wc*2,n=Ey,o=14,a=i*.5-o/2,l=i*.5+o/2,h=i*.48,c=r+zs;this.bg.clear(),this.bg.roundRect(2,3,i,r+2,n),this.bg.fill({color:Py,alpha:Iy}),this.bg.moveTo(n,0),this.bg.lineTo(i-n,0),this.bg.quadraticCurveTo(i,0,i,n),this.bg.lineTo(i,r-n),this.bg.quadraticCurveTo(i,r,i-n,r),this.bg.lineTo(l,r),this.bg.quadraticCurveTo(l-2,r+zs*.35,h,c),this.bg.quadraticCurveTo(a+2,r+zs*.55,a,r),this.bg.lineTo(n,r),this.bg.quadraticCurveTo(0,r,0,r-n),this.bg.lineTo(0,n),this.bg.quadraticCurveTo(0,0,n,0),this.bg.closePath(),this.bg.fill({color:wy,alpha:.97}),this.bg.stroke({color:Ay,width:Ry,alpha:.6}),this.container.pivot.x=i/2,this.container.pivot.y=r+zs}onClick(t){this.container.on("pointertap",t)}destroy(){this.stop(),this.container.destroy({children:!0})}}const By=[{urls:"stun:stun.l.google.com:19302"}],Oy=3e3,Dy="oai-events";class Gy{constructor(t){this.onConnected=null,this.onDisconnected=null,this.onRemoteTrack=null,this.onDataMessage=null,this.onError=null,this.pc=null,this.dc=null,this.micStream=null,this._remoteAudioStream=null,this._connected=!1,this.opts={model:"gpt-4o-realtime-preview",voice:"verse",instructions:"",tools:[],...t}}get isConnected(){return this._connected}get dataChannel(){return this.dc}get remoteAudioStream(){return this._remoteAudioStream}async connect(){var t,e;try{console.log("[RealtimeSession] Requesting microphone..."),this.micStream=await navigator.mediaDevices.getUserMedia({audio:!0}),console.log("[RealtimeSession] Microphone granted"),this.pc=new RTCPeerConnection({iceServers:By}),this.setupPeerConnectionHandlers();for(const o of this.micStream.getAudioTracks())this.pc.addTrack(o,this.micStream);this.dc=this.pc.createDataChannel(Dy),this.setupDataChannelHandlers();const i=await this.pc.createOffer();await this.pc.setLocalDescription(i),await this.waitForIceGathering();const r=(t=this.pc.localDescription)==null?void 0:t.sdp;if(!r)throw new Error("No local SDP after ICE gathering");console.log("[RealtimeSession] Exchanging SDP...");const n=await this.exchangeSDP(r);await this.pc.setRemoteDescription({type:"answer",sdp:n}),console.log("[RealtimeSession] Remote description set")}catch(i){const r=i instanceof Error?i:new Error(String(i));throw console.error("[RealtimeSession] Connection failed:",r.message),(e=this.onError)==null||e.call(this,r),this.close(),r}}sendJSON(t){if(!this.dc||this.dc.readyState!=="open"){console.warn("[RealtimeSession] Data channel not open, cannot send:",t);return}this.dc.send(JSON.stringify(t))}close(){var t;if(console.log("[RealtimeSession] Closing..."),this.dc){try{this.dc.close()}catch{}this.dc=null}if(this.pc){try{this.pc.close()}catch{}this.pc=null}if(this.micStream){for(const e of this.micStream.getTracks())e.stop();this.micStream=null}this._remoteAudioStream=null,this._connected&&(this._connected=!1,(t=this.onDisconnected)==null||t.call(this))}setupPeerConnectionHandlers(){this.pc&&(this.pc.ontrack=t=>{var e;console.log("[RealtimeSession] Remote audio track received"),this._remoteAudioStream=t.streams[0]??new MediaStream([t.track]),(e=this.onRemoteTrack)==null||e.call(this,this._remoteAudioStream)},this.pc.onconnectionstatechange=()=>{var e,i,r,n;const t=(e=this.pc)==null?void 0:e.connectionState;console.log("[RealtimeSession] Connection state:",t),t==="connected"?(this._connected=!0,(i=this.onConnected)==null||i.call(this)):(t==="failed"||t==="closed"||t==="disconnected")&&(this._connected&&(this._connected=!1,(r=this.onDisconnected)==null||r.call(this)),t==="failed"&&((n=this.onError)==null||n.call(this,new Error("WebRTC connection failed"))))})}waitForIceGathering(){return!this.pc||this.pc.iceGatheringState==="complete"?Promise.resolve():new Promise(t=>{const e=this.pc;let i;const r=()=>{clearTimeout(i);try{e.removeEventListener("icegatheringstatechange",n)}catch{}t()},n=()=>{e.iceGatheringState==="complete"&&r()};e.addEventListener("icegatheringstatechange",n),i=setTimeout(r,Oy)})}async exchangeSDP(t){const{webrtcUrl:e,ephemeralKey:i,model:r,voice:n}=this.opts,o=`${e}?model=${encodeURIComponent(r)}&voice=${encodeURIComponent(n)}`,a=await fetch(o,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/sdp",Accept:"application/sdp"},body:t});if(!a.ok){const l=await a.text().catch(()=>"");throw new Error(`SDP exchange failed (${a.status}): ${l}`)}return a.text()}setupDataChannelHandlers(){this.dc&&(this.dc.onopen=()=>{console.log("[RealtimeSession] Data channel open"),this.sendSessionUpdate(),this.sendJSON({type:"response.create"})},this.dc.onmessage=t=>{var e;try{const i=JSON.parse(t.data);(e=this.onDataMessage)==null||e.call(this,i)}catch(i){console.warn("[RealtimeSession] Failed to parse data channel message:",i)}},this.dc.onclose=()=>{console.log("[RealtimeSession] Data channel closed")},this.dc.onerror=t=>{console.error("[RealtimeSession] Data channel error:",t)})}sendSessionUpdate(){const t={instructions:this.opts.instructions,modalities:["audio","text"],input_audio_transcription:{model:"whisper-1"},turn_detection:{type:"server_vad",threshold:.5,prefix_padding_ms:300,silence_duration_ms:700,create_response:!0}};this.opts.tools&&this.opts.tools.length>0&&(t.tools=this.opts.tools),this.sendJSON({type:"session.update",session:t})}}const Uy=24e3,Ly=`
|
|
931
|
+
`;class by extends Dr{constructor(t=.02,e=.06){const i=je.from({vertex:yy,fragment:xy});super({glProgram:i,resources:{lumaUniforms:{uThreshold:{value:t,type:"f32"},uSmoothness:{value:e,type:"f32"}}}})}}const os=200,de=os*(416/624),Hc=280;class vy{constructor(t,e){this.idleSprite=null,this.idleGroup=null,this.liveSprite=null,this.glowGraphic=null,this.videoElement=null,this.liveVideoElement=null,this.cancelGlow=null,this.cancelEntrance=null,this.visible=!1,this.stageWidth=t,this.stageHeight=e,this.container=new kt,this.container.visible=!1,this.container.y=e+de}async loadIdleVideo(t){this.videoElement=document.createElement("video"),this.videoElement.src=t,this.videoElement.loop=!0,this.videoElement.muted=!0,this.videoElement.playsInline=!0,this.videoElement.crossOrigin="anonymous",this.videoElement.style.display="none",document.body.appendChild(this.videoElement),await this.videoElement.play();const e=$.from(this.videoElement);this.idleSprite=new ye(e),this.idleSprite.width=os,this.idleSprite.height=de,this.idleSprite.anchor.set(.5,1),this.idleSprite.filters=[new by],this.idleGroup=new kt,this.idleGroup.addChild(this.idleSprite),this.container.addChild(this.idleGroup),this.container.x=this.stageWidth/2,this.container.y=this.stageHeight+de}async loadIdleImage(t){const e=$.from(t);this.idleSprite=new ye(e),this.idleSprite.width=os,this.idleSprite.height=de,this.idleSprite.anchor.set(.5,1),this.idleGroup=new kt,this.idleGroup.addChild(this.idleSprite),this.container.addChild(this.idleGroup),this.container.x=this.stageWidth/2,this.container.y=this.stageHeight+de}slideIn(t){if(this.visible)return;this.visible=!0;const e=this.stageHeight-10;this.container.alpha=1,this.container.visible=!0,this.container.y=this.stageHeight+de,this.cancelEntrance=Ai({target:this.container,props:{y:e},duration:700,easing:ti.easeOutBack,ticker:t}),this.idleGroup&&setTimeout(()=>{this.idleGroup&&(this.cancelGlow=Nc(this.idleGroup,t,.85,1,2500))},700)}slideOut(t){var e;this.visible&&(this.visible=!1,(e=this.cancelGlow)==null||e.call(this),this.cancelGlow=null,Ai({target:this.container,props:{y:this.stageHeight+de},duration:450,easing:ti.easeInCubic,ticker:t,onComplete:()=>{this.container.visible=!1}}))}get isVisible(){return this.visible}setInteractive(t){this.container.eventMode="static",this.container.cursor="pointer";const e=new bi;e.roundRect(-os/2,-de,os,de,12),e.fill({color:16777215,alpha:.001}),this.container.addChildAt(e,0),this.container.on("pointertap",t),this.container.on("pointerenter",()=>{this.container&&this.container.scale.set(1.04)}),this.container.on("pointerleave",()=>{this.container&&this.container.scale.set(1)})}setLiveVideo(t,e){this.liveVideoElement=t;const i=()=>{var l;const r=$.from(t);this.liveSprite=new ye(r);const n=t.videoWidth||1,o=t.videoHeight||1,a=Hc/n;this.liveSprite.width=Hc,this.liveSprite.height=o*a,this.liveSprite.anchor.set(.5,1),this.liveSprite.alpha=0,this.container.addChild(this.liveSprite),this.idleGroup&&(this.idleGroup.visible=!1),(l=this.cancelGlow)==null||l.call(this),this.cancelGlow=null,Ai({target:this.liveSprite,props:{alpha:1},duration:500,easing:ti.easeInOutSine,ticker:e})};if(t.videoWidth>0&&t.videoHeight>0)i();else{const r=()=>{t.removeEventListener("loadeddata",r),t.removeEventListener("resize",r),i()};t.addEventListener("loadeddata",r),t.addEventListener("resize",r)}}clearLiveVideo(t){this.liveSprite&&Ai({target:this.liveSprite,props:{alpha:0},duration:400,easing:ti.easeInCubic,ticker:t,onComplete:()=>{var e;(e=this.liveSprite)==null||e.destroy(),this.liveSprite=null,this.liveVideoElement=null}}),this.idleGroup&&(this.idleGroup.visible=!0,this.idleSprite&&(this.idleSprite.alpha=1)),this.idleGroup&&(this.cancelGlow=Nc(this.idleGroup,t,.85,1,2500))}destroy(){var t,e;(t=this.cancelGlow)==null||t.call(this),(e=this.cancelEntrance)==null||e.call(this),this.videoElement&&(this.videoElement.pause(),this.videoElement.remove()),this.container.destroy({children:!0})}}const jn=18,Wc=12,Ey=20,Ty=240,zs=14,Sy=35,Cy=2500,Vc=300,wy=16777215,Ay=13160666,Ry=1.5,Py=3820124,Iy=.1,My=["Got questions? Click me!","I can guide you through this page","Need help? Let’s chat!"];class ky{constructor(t,e){this.promptIndex=0,this.charIndex=0,this.phase="idle",this.phaseElapsed=0,this.cancelFade=null,this.tickCb=null,this.running=!1,this.ticker=t,this.prompts=e!=null&&e.length?e:My,this.container=new kt,this.container.alpha=0,this.container.visible=!1,this.bg=new bi,this.container.addChild(this.bg),this.label=new ng({text:"",style:{fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',fontSize:13,fontWeight:"500",fill:2763326,wordWrap:!0,wordWrapWidth:Ty-jn*2,lineHeight:19}}),this.label.x=jn,this.label.y=Wc,this.container.addChild(this.label),this.container.eventMode="static",this.container.cursor="pointer"}start(){this.running||(this.running=!0,this.container.visible=!0,this.promptIndex=0,this.beginTyping(),this.tickCb=t=>this.update(t.deltaMS),this.ticker.add(this.tickCb))}stop(){var t;this.running&&(this.running=!1,this.phase="idle",this.tickCb&&this.ticker.remove(this.tickCb),this.tickCb=null,(t=this.cancelFade)==null||t.call(this),this.cancelFade=null,this.container.visible=!1,this.container.alpha=0)}beginTyping(){this.charIndex=0,this.phaseElapsed=0,this.phase="typing",this.label.text="",this.drawBubble(),this.container.alpha=0,this.cancelFade=Ai({target:this.container,props:{alpha:1},duration:Vc,easing:ti.easeOutCubic,ticker:this.ticker})}update(t){var e;if(this.phase==="typing"){this.phaseElapsed+=t;const i=this.prompts[this.promptIndex],r=Math.min(Math.floor(this.phaseElapsed/Sy),i.length);r!==this.charIndex&&(this.charIndex=r,this.label.text=i.substring(0,this.charIndex),this.drawBubble()),this.charIndex>=i.length&&(this.phase="holding",this.phaseElapsed=0)}else this.phase==="holding"&&(this.phaseElapsed+=t,this.phaseElapsed>=Cy&&(this.phase="fading",this.phaseElapsed=0,(e=this.cancelFade)==null||e.call(this),this.cancelFade=Ai({target:this.container,props:{alpha:0},duration:Vc,easing:ti.easeInCubic,ticker:this.ticker,onComplete:()=>{this.promptIndex=(this.promptIndex+1)%this.prompts.length,this.beginTyping()}})))}drawBubble(){const t=Math.max(this.label.width,50),e=Math.max(this.label.height,18),i=t+jn*2,r=e+Wc*2,n=Ey,o=14,a=i*.5-o/2,l=i*.5+o/2,h=i*.48,c=r+zs;this.bg.clear(),this.bg.roundRect(2,3,i,r+2,n),this.bg.fill({color:Py,alpha:Iy}),this.bg.moveTo(n,0),this.bg.lineTo(i-n,0),this.bg.quadraticCurveTo(i,0,i,n),this.bg.lineTo(i,r-n),this.bg.quadraticCurveTo(i,r,i-n,r),this.bg.lineTo(l,r),this.bg.quadraticCurveTo(l-2,r+zs*.35,h,c),this.bg.quadraticCurveTo(a+2,r+zs*.55,a,r),this.bg.lineTo(n,r),this.bg.quadraticCurveTo(0,r,0,r-n),this.bg.lineTo(0,n),this.bg.quadraticCurveTo(0,0,n,0),this.bg.closePath(),this.bg.fill({color:wy,alpha:.97}),this.bg.stroke({color:Ay,width:Ry,alpha:.6}),this.container.pivot.x=i/2,this.container.pivot.y=r+zs}onClick(t){this.container.on("pointertap",t)}destroy(){this.stop(),this.container.destroy({children:!0})}}const By=[{urls:"stun:stun.l.google.com:19302"}],Oy=3e3,Dy="oai-events";class Gy{constructor(t){this.onConnected=null,this.onDisconnected=null,this.onRemoteTrack=null,this.onDataMessage=null,this.onError=null,this.pc=null,this.dc=null,this.micStream=null,this._remoteAudioStream=null,this._connected=!1,this.opts={model:"gpt-4o-realtime-preview",voice:"verse",instructions:"",tools:[],...t}}get isConnected(){return this._connected}get dataChannel(){return this.dc}get remoteAudioStream(){return this._remoteAudioStream}async connect(){var t,e;try{console.log("[RealtimeSession] Requesting microphone..."),this.micStream=await navigator.mediaDevices.getUserMedia({audio:!0}),console.log("[RealtimeSession] Microphone granted"),this.pc=new RTCPeerConnection({iceServers:By}),this.setupPeerConnectionHandlers();for(const o of this.micStream.getAudioTracks())this.pc.addTrack(o,this.micStream);this.dc=this.pc.createDataChannel(Dy),this.setupDataChannelHandlers();const i=await this.pc.createOffer();await this.pc.setLocalDescription(i),await this.waitForIceGathering();const r=(t=this.pc.localDescription)==null?void 0:t.sdp;if(!r)throw new Error("No local SDP after ICE gathering");console.log("[RealtimeSession] Exchanging SDP...");const n=await this.exchangeSDP(r);await this.pc.setRemoteDescription({type:"answer",sdp:n}),console.log("[RealtimeSession] Remote description set")}catch(i){const r=i instanceof Error?i:new Error(String(i));throw console.error("[RealtimeSession] Connection failed:",r.message),(e=this.onError)==null||e.call(this,r),this.close(),r}}sendJSON(t){if(!this.dc||this.dc.readyState!=="open"){console.warn("[RealtimeSession] Data channel not open, cannot send:",t);return}this.dc.send(JSON.stringify(t))}close(){var t;if(console.log("[RealtimeSession] Closing..."),this.dc){try{this.dc.close()}catch{}this.dc=null}if(this.pc){try{this.pc.close()}catch{}this.pc=null}if(this.micStream){for(const e of this.micStream.getTracks())e.stop();this.micStream=null}this._remoteAudioStream=null,this._connected&&(this._connected=!1,(t=this.onDisconnected)==null||t.call(this))}setupPeerConnectionHandlers(){this.pc&&(this.pc.ontrack=t=>{var e;console.log("[RealtimeSession] Remote audio track received"),this._remoteAudioStream=t.streams[0]??new MediaStream([t.track]),(e=this.onRemoteTrack)==null||e.call(this,this._remoteAudioStream)},this.pc.onconnectionstatechange=()=>{var e,i,r,n;const t=(e=this.pc)==null?void 0:e.connectionState;console.log("[RealtimeSession] Connection state:",t),t==="connected"?(this._connected=!0,(i=this.onConnected)==null||i.call(this)):(t==="failed"||t==="closed"||t==="disconnected")&&(this._connected&&(this._connected=!1,(r=this.onDisconnected)==null||r.call(this)),t==="failed"&&((n=this.onError)==null||n.call(this,new Error("WebRTC connection failed"))))})}waitForIceGathering(){return!this.pc||this.pc.iceGatheringState==="complete"?Promise.resolve():new Promise(t=>{const e=this.pc;let i;const r=()=>{clearTimeout(i);try{e.removeEventListener("icegatheringstatechange",n)}catch{}t()},n=()=>{e.iceGatheringState==="complete"&&r()};e.addEventListener("icegatheringstatechange",n),i=setTimeout(r,Oy)})}async exchangeSDP(t){const{webrtcUrl:e,ephemeralKey:i,model:r,voice:n}=this.opts,o=`${e}?model=${encodeURIComponent(r)}&voice=${encodeURIComponent(n)}`,a=await fetch(o,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/sdp",Accept:"application/sdp"},body:t});if(!a.ok){const l=await a.text().catch(()=>"");throw new Error(`SDP exchange failed (${a.status}): ${l}`)}return a.text()}setupDataChannelHandlers(){this.dc&&(this.dc.onopen=()=>{console.log("[RealtimeSession] Data channel open"),this.sendSessionUpdate(),this.sendJSON({type:"response.create"})},this.dc.onmessage=t=>{var e;try{const i=JSON.parse(t.data);(e=this.onDataMessage)==null||e.call(this,i)}catch(i){console.warn("[RealtimeSession] Failed to parse data channel message:",i)}},this.dc.onclose=()=>{console.log("[RealtimeSession] Data channel closed")},this.dc.onerror=t=>{console.error("[RealtimeSession] Data channel error:",t)})}sendSessionUpdate(){const t={instructions:this.opts.instructions,modalities:["audio","text"],input_audio_transcription:{model:"whisper-1"},turn_detection:{type:"server_vad",threshold:.5,prefix_padding_ms:300,silence_duration_ms:700,create_response:!0}};this.opts.tools&&this.opts.tools.length>0&&(t.tools=this.opts.tools),this.sendJSON({type:"session.update",session:t})}}const Uy=24e3,Ly=`
|
|
935
932
|
class PcmBufferProcessor extends AudioWorkletProcessor {
|
|
936
933
|
constructor() {
|
|
937
934
|
super()
|