@w0nna_dev/lina-widget 1.1.0 → 1.1.1
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/lina-widget.es.js
CHANGED
|
@@ -41527,12 +41527,12 @@ const rw = {
|
|
|
41527
41527
|
// State-based colors (used automatically)
|
|
41528
41528
|
stateIdle: "#a855f7",
|
|
41529
41529
|
// Purple - same as main orb color
|
|
41530
|
-
stateListening: "#
|
|
41531
|
-
//
|
|
41532
|
-
stateThinking: "#
|
|
41533
|
-
//
|
|
41530
|
+
stateListening: "#f97316",
|
|
41531
|
+
// Orange - user is speaking, agent listening
|
|
41532
|
+
stateThinking: "#facc15",
|
|
41533
|
+
// Yellow - thinking/processing
|
|
41534
41534
|
stateSpeaking: "#10b981"
|
|
41535
|
-
// Muted green - speaking
|
|
41535
|
+
// Muted green - agent speaking
|
|
41536
41536
|
}, rl = {
|
|
41537
41537
|
idle: {
|
|
41538
41538
|
shellOpen: 0,
|
|
@@ -42180,7 +42180,7 @@ var ow = Object.defineProperty, cw = Object.getOwnPropertyDescriptor, jt = (i, e
|
|
|
42180
42180
|
};
|
|
42181
42181
|
let Ft = class extends es {
|
|
42182
42182
|
constructor() {
|
|
42183
|
-
super(...arguments), this.orbRenderer = null, this.orbContainerRef = No(), this.audioSimPhase = 0, this.animationId = null, this.callManager = null, this.size = 300, this.headerLogo = "HANC.ai", this.headerTitle = "Lina-Voice AI", this.showBranding = !0, this.version = "v1.1.
|
|
42183
|
+
super(...arguments), this.orbRenderer = null, this.orbContainerRef = No(), this.audioSimPhase = 0, this.animationId = null, this.callManager = null, this.size = 300, this.headerLogo = "HANC.ai", this.headerTitle = "Lina-Voice AI", this.showBranding = !0, this.version = "v1.1.1", this.agentId = "", this.voiceServiceUrl = "", this.btnStartText = "Start", this.btnEndText = "End", this.colors = {}, this.brandingLogoColor = "rgba(255, 255, 255, 0.9)", this.brandingTitleColor = "rgba(255, 255, 255, 0.6)", this.brandingDividerColor = "rgba(255, 255, 255, 0.3)", this.versionColor = "rgba(255, 255, 255, 0.3)", this.buttonBackground = "linear-gradient(135deg, rgba(139, 92, 246, 0.95) 0%, rgba(124, 58, 237, 0.95) 100%)", this.buttonTextColor = "rgba(255, 255, 255, 0.95)", this.currentState = "idle", this.callStatus = "idle", this.isLoading = !0, this._hasMicPermission = null, this._localAudioContext = null, this._localAudioAnalyser = null, this._localAudioMonitorId = null, this._agentAudioContext = null, this._agentAudioAnalyser = null, this._agentAudioMonitorId = null, this._agentIsSpeaking = !1, this._interruptionTimeout = null, this._lastInterruptionTime = 0, this.handleCallClick = async () => {
|
|
42184
42184
|
if (this.callStatus === "mic-denied")
|
|
42185
42185
|
try {
|
|
42186
42186
|
(await navigator.mediaDevices.getUserMedia({ audio: !0 })).getTracks().forEach((e) => e.stop()), this._hasMicPermission = !0, this.callStatus = "idle";
|
|
@@ -42228,7 +42228,7 @@ let Ft = class extends es {
|
|
|
42228
42228
|
const e = i.detail;
|
|
42229
42229
|
if (e) {
|
|
42230
42230
|
const t = new MediaStream([e]);
|
|
42231
|
-
this.connectAudioStream(t);
|
|
42231
|
+
this.connectAudioStream(t), this.startAgentAudioMonitoring(e);
|
|
42232
42232
|
}
|
|
42233
42233
|
})), this.callManager.addEventListener("microphone-disabled", () => {
|
|
42234
42234
|
this.callStatus === "active" && (this._hasMicPermission = !1);
|
|
@@ -42240,9 +42240,6 @@ let Ft = class extends es {
|
|
|
42240
42240
|
})), this.callManager.addEventListener("agent-command", ((i) => {
|
|
42241
42241
|
const e = i.detail;
|
|
42242
42242
|
this.handleAgentCommand(e);
|
|
42243
|
-
})), this.callManager.addEventListener("agent-speaking", ((i) => {
|
|
42244
|
-
var e;
|
|
42245
|
-
this._agentIsSpeaking = ((e = i.detail) == null ? void 0 : e.isSpeaking) ?? !1;
|
|
42246
42243
|
})), this.callManager.addEventListener("local-audio-track", ((i) => {
|
|
42247
42244
|
const e = i.detail;
|
|
42248
42245
|
e && this.startLocalAudioMonitoring(e);
|
|
@@ -42257,18 +42254,21 @@ let Ft = class extends es {
|
|
|
42257
42254
|
this._localAudioContext = new AudioContext(), this._localAudioAnalyser = this._localAudioContext.createAnalyser(), this._localAudioAnalyser.fftSize = 256;
|
|
42258
42255
|
const e = new MediaStream([i]);
|
|
42259
42256
|
this._localAudioContext.createMediaStreamSource(e).connect(this._localAudioAnalyser);
|
|
42260
|
-
const n = new Uint8Array(this._localAudioAnalyser.frequencyBinCount), s =
|
|
42257
|
+
const n = new Uint8Array(this._localAudioAnalyser.frequencyBinCount), s = 25;
|
|
42258
|
+
let r = 0;
|
|
42259
|
+
const o = 5, a = () => {
|
|
42260
|
+
var d;
|
|
42261
42261
|
if (!this._localAudioAnalyser || this.callStatus !== "active") {
|
|
42262
42262
|
this.stopLocalAudioMonitoring();
|
|
42263
42263
|
return;
|
|
42264
42264
|
}
|
|
42265
42265
|
this._localAudioAnalyser.getByteFrequencyData(n);
|
|
42266
|
-
let
|
|
42267
|
-
for (let
|
|
42268
|
-
|
|
42269
|
-
|
|
42266
|
+
let c = 0;
|
|
42267
|
+
for (let u = 0; u < n.length; u++)
|
|
42268
|
+
c += n[u];
|
|
42269
|
+
c / n.length > s ? (r++, r >= o && (this._agentIsSpeaking ? this.handleUserInterruption() : this.currentState !== "listening" && (this.currentState = "listening", (d = this.orbRenderer) == null || d.setState("listening")))) : r = 0, this._localAudioMonitorId = requestAnimationFrame(a);
|
|
42270
42270
|
};
|
|
42271
|
-
this._localAudioMonitorId = requestAnimationFrame(
|
|
42271
|
+
this._localAudioMonitorId = requestAnimationFrame(a);
|
|
42272
42272
|
} catch (e) {
|
|
42273
42273
|
console.warn("Failed to start local audio monitoring:", e);
|
|
42274
42274
|
}
|
|
@@ -42276,12 +42276,43 @@ let Ft = class extends es {
|
|
|
42276
42276
|
stopLocalAudioMonitoring() {
|
|
42277
42277
|
this._localAudioMonitorId && (cancelAnimationFrame(this._localAudioMonitorId), this._localAudioMonitorId = null), this._localAudioContext && (this._localAudioContext.close(), this._localAudioContext = null), this._localAudioAnalyser = null;
|
|
42278
42278
|
}
|
|
42279
|
+
/**
|
|
42280
|
+
* Monitor agent audio to detect when agent is actually speaking
|
|
42281
|
+
*/
|
|
42282
|
+
startAgentAudioMonitoring(i) {
|
|
42283
|
+
this.stopAgentAudioMonitoring();
|
|
42284
|
+
try {
|
|
42285
|
+
this._agentAudioContext = new AudioContext(), this._agentAudioAnalyser = this._agentAudioContext.createAnalyser(), this._agentAudioAnalyser.fftSize = 256;
|
|
42286
|
+
const e = new MediaStream([i]);
|
|
42287
|
+
this._agentAudioContext.createMediaStreamSource(e).connect(this._agentAudioAnalyser);
|
|
42288
|
+
const n = new Uint8Array(this._agentAudioAnalyser.frequencyBinCount), s = 15;
|
|
42289
|
+
let r = 0;
|
|
42290
|
+
const o = 15, a = () => {
|
|
42291
|
+
var d;
|
|
42292
|
+
if (!this._agentAudioAnalyser || this.callStatus !== "active") {
|
|
42293
|
+
this.stopAgentAudioMonitoring();
|
|
42294
|
+
return;
|
|
42295
|
+
}
|
|
42296
|
+
this._agentAudioAnalyser.getByteFrequencyData(n);
|
|
42297
|
+
let c = 0;
|
|
42298
|
+
for (let u = 0; u < n.length; u++)
|
|
42299
|
+
c += n[u];
|
|
42300
|
+
c / n.length > s ? (r = 0, this._agentIsSpeaking || (this._agentIsSpeaking = !0, this.currentState !== "speaking" && (this.currentState = "speaking", (d = this.orbRenderer) == null || d.setState("speaking")))) : (r++, r >= o && this._agentIsSpeaking && (this._agentIsSpeaking = !1)), this._agentAudioMonitorId = requestAnimationFrame(a);
|
|
42301
|
+
};
|
|
42302
|
+
this._agentAudioMonitorId = requestAnimationFrame(a);
|
|
42303
|
+
} catch (e) {
|
|
42304
|
+
console.warn("Failed to start agent audio monitoring:", e);
|
|
42305
|
+
}
|
|
42306
|
+
}
|
|
42307
|
+
stopAgentAudioMonitoring() {
|
|
42308
|
+
this._agentAudioMonitorId && (cancelAnimationFrame(this._agentAudioMonitorId), this._agentAudioMonitorId = null), this._agentAudioContext && (this._agentAudioContext.close(), this._agentAudioContext = null), this._agentAudioAnalyser = null;
|
|
42309
|
+
}
|
|
42279
42310
|
/**
|
|
42280
42311
|
* Handle commands received from the agent via data channel
|
|
42281
42312
|
*/
|
|
42282
42313
|
handleAgentCommand(i) {
|
|
42283
42314
|
var e, t, n;
|
|
42284
|
-
switch (i.type) {
|
|
42315
|
+
switch (console.log("[LinaWidget] Received agent command:", i), i.type) {
|
|
42285
42316
|
case "change_color":
|
|
42286
42317
|
(e = i.payload) != null && e.color && (this.setColors({ coreGlow: i.payload.color }), this.dispatchEvent(new CustomEvent("color-changed", {
|
|
42287
42318
|
detail: { color: i.payload.color },
|
|
@@ -42330,7 +42361,7 @@ let Ft = class extends es {
|
|
|
42330
42361
|
}
|
|
42331
42362
|
cleanup() {
|
|
42332
42363
|
var i, e;
|
|
42333
|
-
this.animationId !== null && (cancelAnimationFrame(this.animationId), this.animationId = null), this.stopLocalAudioMonitoring(), this._interruptionTimeout && (clearTimeout(this._interruptionTimeout), this._interruptionTimeout = null), (i = this.callManager) == null || i.hangUp(), (e = this.orbRenderer) == null || e.destroy(), this.orbRenderer = null;
|
|
42364
|
+
this.animationId !== null && (cancelAnimationFrame(this.animationId), this.animationId = null), this.stopLocalAudioMonitoring(), this.stopAgentAudioMonitoring(), this._interruptionTimeout && (clearTimeout(this._interruptionTimeout), this._interruptionTimeout = null), (i = this.callManager) == null || i.hangUp(), (e = this.orbRenderer) == null || e.destroy(), this.orbRenderer = null;
|
|
42334
42365
|
}
|
|
42335
42366
|
startIdleAnimation() {
|
|
42336
42367
|
this.animationId !== null && cancelAnimationFrame(this.animationId);
|
package/dist/lina-widget.umd.js
CHANGED
|
@@ -5206,7 +5206,7 @@ void main() {
|
|
|
5206
5206
|
display: inline-block;
|
|
5207
5207
|
contain: layout style;
|
|
5208
5208
|
}
|
|
5209
|
-
`,Et([ce({type:String,attribute:"agent-id"})],$.PillCall.prototype,"agentId",2),Et([ce({type:String,attribute:"voice-service-url"})],$.PillCall.prototype,"voiceServiceUrl",2),Et([fi()],$.PillCall.prototype,"callStatus",2),Et([fi()],$.PillCall.prototype,"microphoneEnabled",2),Et([ce({type:String,attribute:"button-start-text"})],$.PillCall.prototype,"buttonStartText",2),Et([ce({type:String,attribute:"button-connecting-text"})],$.PillCall.prototype,"buttonConnectingText",2),Et([ce({type:String,attribute:"button-end-text"})],$.PillCall.prototype,"buttonEndText",2),Et([ce({type:Number,attribute:"orb-size"})],$.PillCall.prototype,"orbSize",2),Et([ce({type:String,attribute:"theme"})],$.PillCall.prototype,"theme",2),Et([ce({type:String,attribute:"theme-mode"})],$.PillCall.prototype,"themeMode",2),Et([ce({type:Object,attribute:"orb-colors"})],$.PillCall.prototype,"orbColors",2),Et([ce({type:Number,attribute:"glow-intensity"})],$.PillCall.prototype,"glowIntensity",2),Et([ce({type:Number,attribute:"idle-glow-multiplier"})],$.PillCall.prototype,"idleGlowMultiplier",2),Et([ce({type:Number,attribute:"morph-strength"})],$.PillCall.prototype,"morphStrength",2),Et([ce({type:Number,attribute:"noise-scale"})],$.PillCall.prototype,"noiseScale",2),Et([ce({type:Number,attribute:"noise-speed"})],$.PillCall.prototype,"noiseSpeed",2),Et([ce({type:Number,attribute:"fresnel-power"})],$.PillCall.prototype,"fresnelPower",2),Et([ce({type:Number,attribute:"rotation-speed"})],$.PillCall.prototype,"rotationSpeed",2),Et([ce({type:Number,attribute:"audio-reactivity"})],$.PillCall.prototype,"audioReactivity",2),Et([ce({type:Number,attribute:"audio-smoothing"})],$.PillCall.prototype,"audioSmoothing",2),Et([ce({type:Number,attribute:"idle-morph-multiplier"})],$.PillCall.prototype,"idleMorphMultiplier",2),Et([ce({type:Number,attribute:"color-contrast"})],$.PillCall.prototype,"colorContrast",2),Et([ce({type:Boolean,attribute:"sound-enabled"})],$.PillCall.prototype,"soundEnabled",2),Et([ce({type:Number,attribute:"sound-volume"})],$.PillCall.prototype,"soundVolume",2),$.PillCall=Et([_a("hanc-ai-pill-call")],$.PillCall);const _M={core:"#ffffff",coreGlow:"#a855f7",lightning:"#c084fc",shell:"#1e1b2e",shellInner:"#0f0d17",particles:"#e9d5ff",pulseNeutral:"#a855f7",pulseJoy:"#22c55e",pulseThinking:"#3b82f6",pulseInterrupted:"#ef4444",stateIdle:"#a855f7",stateListening:"#
|
|
5209
|
+
`,Et([ce({type:String,attribute:"agent-id"})],$.PillCall.prototype,"agentId",2),Et([ce({type:String,attribute:"voice-service-url"})],$.PillCall.prototype,"voiceServiceUrl",2),Et([fi()],$.PillCall.prototype,"callStatus",2),Et([fi()],$.PillCall.prototype,"microphoneEnabled",2),Et([ce({type:String,attribute:"button-start-text"})],$.PillCall.prototype,"buttonStartText",2),Et([ce({type:String,attribute:"button-connecting-text"})],$.PillCall.prototype,"buttonConnectingText",2),Et([ce({type:String,attribute:"button-end-text"})],$.PillCall.prototype,"buttonEndText",2),Et([ce({type:Number,attribute:"orb-size"})],$.PillCall.prototype,"orbSize",2),Et([ce({type:String,attribute:"theme"})],$.PillCall.prototype,"theme",2),Et([ce({type:String,attribute:"theme-mode"})],$.PillCall.prototype,"themeMode",2),Et([ce({type:Object,attribute:"orb-colors"})],$.PillCall.prototype,"orbColors",2),Et([ce({type:Number,attribute:"glow-intensity"})],$.PillCall.prototype,"glowIntensity",2),Et([ce({type:Number,attribute:"idle-glow-multiplier"})],$.PillCall.prototype,"idleGlowMultiplier",2),Et([ce({type:Number,attribute:"morph-strength"})],$.PillCall.prototype,"morphStrength",2),Et([ce({type:Number,attribute:"noise-scale"})],$.PillCall.prototype,"noiseScale",2),Et([ce({type:Number,attribute:"noise-speed"})],$.PillCall.prototype,"noiseSpeed",2),Et([ce({type:Number,attribute:"fresnel-power"})],$.PillCall.prototype,"fresnelPower",2),Et([ce({type:Number,attribute:"rotation-speed"})],$.PillCall.prototype,"rotationSpeed",2),Et([ce({type:Number,attribute:"audio-reactivity"})],$.PillCall.prototype,"audioReactivity",2),Et([ce({type:Number,attribute:"audio-smoothing"})],$.PillCall.prototype,"audioSmoothing",2),Et([ce({type:Number,attribute:"idle-morph-multiplier"})],$.PillCall.prototype,"idleMorphMultiplier",2),Et([ce({type:Number,attribute:"color-contrast"})],$.PillCall.prototype,"colorContrast",2),Et([ce({type:Boolean,attribute:"sound-enabled"})],$.PillCall.prototype,"soundEnabled",2),Et([ce({type:Number,attribute:"sound-volume"})],$.PillCall.prototype,"soundVolume",2),$.PillCall=Et([_a("hanc-ai-pill-call")],$.PillCall);const _M={core:"#ffffff",coreGlow:"#a855f7",lightning:"#c084fc",shell:"#1e1b2e",shellInner:"#0f0d17",particles:"#e9d5ff",pulseNeutral:"#a855f7",pulseJoy:"#22c55e",pulseThinking:"#3b82f6",pulseInterrupted:"#ef4444",stateIdle:"#a855f7",stateListening:"#f97316",stateThinking:"#facc15",stateSpeaking:"#10b981"},pu={idle:{shellOpen:0,coreIntensity:.6,lightningCount:2,lightningIntensity:.3,particleSpeed:.3,coreScale:.7},listening:{shellOpen:.15,coreIntensity:.8,lightningCount:4,lightningIntensity:.5,particleSpeed:.5,coreScale:.8},thinking:{shellOpen:.25,coreIntensity:1,lightningCount:6,lightningIntensity:.7,particleSpeed:.7,coreScale:.9},speaking:{shellOpen:.4,coreIntensity:1.2,lightningCount:10,lightningIntensity:1,particleSpeed:1,coreScale:1}};class pg{constructor(e,t={}){this.shellSegments=[],this.coreInner=null,this.coreOuter=null,this.coreGlow=null,this.pulseRings=[],this.particles=null,this.particlePositions=null,this.particleVelocities=null,this.animationId=null,this._currentState="idle",this._currentEmotion="neutral",this.targetConfig={...pu.idle},this.currentConfig={...pu.idle},this.targetAudioLevel=0,this.currentAudioLevel=0,this.audioVelocity=0,this.targetPulseColor=new Fe("#a855f7"),this.currentPulseColor=new Fe("#a855f7"),this.targetRotation={x:0,y:0},this.currentRotation={x:0,y:0},this.time=0,this.animate=()=>{this.animationId=requestAnimationFrame(this.animate);const n=this.clock.getDelta();this.time+=n;const s=.05;this.currentConfig.coreIntensity+=(this.targetConfig.coreIntensity-this.currentConfig.coreIntensity)*s,this.currentConfig.lightningCount+=(this.targetConfig.lightningCount-this.currentConfig.lightningCount)*s,this.currentConfig.lightningIntensity+=(this.targetConfig.lightningIntensity-this.currentConfig.lightningIntensity)*s,this.currentConfig.particleSpeed+=(this.targetConfig.particleSpeed-this.currentConfig.particleSpeed)*s,this.currentConfig.coreScale+=(this.targetConfig.coreScale-this.currentConfig.coreScale)*s;const r=.08,o=.75,a=(this.targetAudioLevel-this.currentAudioLevel)*r;this.audioVelocity+=a,this.audioVelocity*=o,this.currentAudioLevel+=this.audioVelocity,this.currentAudioLevel=Math.max(0,Math.min(1,this.currentAudioLevel));const c=1+this.currentAudioLevel*.4;if(this.coreLight&&(this.coreLight.intensity=3+this.currentConfig.coreIntensity*2*c),this.coreInner){const l=this.coreInner.material;l.uniforms&&(l.uniforms.uTime.value=this.time,l.uniforms.uIntensity.value=this.currentConfig.coreIntensity*c);const d=this.currentConfig.coreScale*.9*c;this.coreInner.scale.setScalar(d)}if(this.coreOuter){const l=this.coreOuter.material;l.uniforms.uTime.value=this.time,l.uniforms.uIntensity.value=this.currentConfig.coreIntensity*c;const d=this.currentConfig.coreScale*c;this.coreOuter.scale.setScalar(d)}if(this.coreGlow){const l=this.coreGlow.material;l.uniforms.uTime.value=this.time,l.uniforms.uIntensity.value=this.currentConfig.coreIntensity*.7*c;const d=1+Math.sin(this.time*1.5)*.03*this.currentConfig.coreIntensity;this.coreGlow.scale.setScalar(d)}this.updateParticles(n),this.currentPulseColor.lerp(this.targetPulseColor,.08);for(const l of this.pulseRings){const d=l.material;d.uniforms.uTime.value=this.time,d.uniforms.uAudioLevel.value=this.currentAudioLevel,d.uniforms.uIntensity.value=this.currentConfig.coreIntensity,d.uniforms.uColor.value.copy(this.currentPulseColor);const u=l.ringConfig;l.rotation.y+=.003*u.speed,l.rotation.x=u.tiltX+Math.sin(this.time*.5+u.phase)*.1,l.rotation.z=u.tiltZ+Math.cos(this.time*.4+u.phase)*.08}this.currentRotation.x+=(this.targetRotation.x-this.currentRotation.x)*.05,this.currentRotation.y+=(this.targetRotation.y-this.currentRotation.y)*.05,this.scene.rotation.x=this.currentRotation.x,this.scene.rotation.y=this.currentRotation.y,this.renderer.render(this.scene,this.camera)},this.handleResize=()=>{const n=this.container.clientWidth*this.config.canvasPadding,s=this.container.clientHeight*this.config.canvasPadding;this.camera.aspect=n/s,this.camera.updateProjectionMatrix(),this.renderer.setSize(n,s)},this.handleMouseMove=n=>{const s=this.container.getBoundingClientRect(),r=(n.clientX-s.left)/s.width*2-1,o=-((n.clientY-s.top)/s.height)*2+1;this.targetRotation.x=o*.3,this.targetRotation.y=r*.3},this.handleMouseLeave=()=>{this.targetRotation.x=0,this.targetRotation.y=0},this.container=e,this.config={size:t.size??1,shellSegments:t.shellSegments??6,colors:t.colors??{},canvasPadding:t.canvasPadding??2},this.colors={..._M,...t.colors},this.clock=new Nm,this.initScene(),this.createShell(),this.createCore(),this.createParticles(),window.addEventListener("resize",this.handleResize),e.addEventListener("mousemove",this.handleMouseMove),e.addEventListener("mouseleave",this.handleMouseLeave)}initScene(){this.scene=new Mm;const e=this.container.clientWidth*this.config.canvasPadding,t=this.container.clientHeight*this.config.canvasPadding;this.camera=new Tn(50,e/t,.1,100),this.camera.position.z=3.5,this.renderer=new ug({antialias:!0,alpha:!0,powerPreference:"high-performance"}),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio,2)),this.renderer.setSize(e,t),this.renderer.setClearColor(0,0);const n=this.renderer.domElement;n.style.position="absolute",n.style.left="50%",n.style.top="50%",n.style.transform="translate(-50%, -50%)",n.style.pointerEvents="none",this.container.appendChild(n)}createShell(){const e=new zS(1710638,.6);this.scene.add(e);const t=new iu(16777215,1);t.position.set(3,4,5),this.scene.add(t);const n=new iu(9133302,.4);n.position.set(-3,2,3),this.scene.add(n);const s=new iu(6514417,.5);s.position.set(0,-2,-4),this.scene.add(s);const r=new FS(new Fe(this.colors.coreGlow),4,6);r.position.set(0,0,0),this.scene.add(r),this.coreLight=r}createCore(){const e=this.config.size*.3,t=new yr(e*.5,64,64),n=new tn({uniforms:{uTime:{value:0},uIntensity:{value:1}},vertexShader:`
|
|
5210
5210
|
varying vec3 vNormal;
|
|
5211
5211
|
varying vec3 vPosition;
|
|
5212
5212
|
void main() {
|
|
@@ -5524,7 +5524,7 @@ void main() {
|
|
|
5524
5524
|
|
|
5525
5525
|
gl_FragColor = vec4(color, alpha * 0.8);
|
|
5526
5526
|
}
|
|
5527
|
-
`,transparent:!0,blending:Ji,depthWrite:!1});this.particles=new IS(s,r),this.particleMaterial=r,this.scene.add(this.particles)}resetParticleFromCore(e){if(!this.particlePositions||!this.particleVelocities)return;const t=e*3,n=Math.random()*Math.PI*2,s=Math.acos(2*Math.random()-1),r=this.config.size*(.1+Math.random()*.15);this.particlePositions[t]=Math.sin(s)*Math.cos(n)*r,this.particlePositions[t+1]=Math.cos(s)*r,this.particlePositions[t+2]=Math.sin(s)*Math.sin(n)*r;const o=.0027+Math.random()*.008;this.particleVelocities[t]=this.particlePositions[t]/r*o,this.particleVelocities[t+1]=this.particlePositions[t+1]/r*o,this.particleVelocities[t+2]=this.particlePositions[t+2]/r*o,this.particleVelocities[t]+=(Math.random()-.5)*.0013,this.particleVelocities[t+1]+=(Math.random()-.5)*.0013,this.particleVelocities[t+2]+=(Math.random()-.5)*.0013}updateParticles(e){if(!this.particlePositions||!this.particleVelocities||!this.particles)return;const t=this.currentConfig.particleSpeed,n=this.config.size*.7;this.particleMaterial&&(this.particleMaterial.uniforms.uTime.value=this.time);for(let s=0;s<this.particlePositions.length/3;s++){const r=s*3;this.particlePositions[r]+=this.particleVelocities[r]*t,this.particlePositions[r+1]+=this.particleVelocities[r+1]*t,this.particlePositions[r+2]+=this.particleVelocities[r+2]*t,(Math.sqrt(this.particlePositions[r]**2+this.particlePositions[r+1]**2+this.particlePositions[r+2]**2)>=n||Math.random()<.003)&&this.resetParticleFromCore(s)}this.particles.geometry.attributes.position.needsUpdate=!0}setState(e){switch(this._currentState=e,this.targetConfig={...pu[e]},e){case"listening":this.targetPulseColor.set(this.colors.stateListening);break;case"thinking":this.targetPulseColor.set(this.colors.stateThinking);break;case"speaking":this.targetPulseColor.set(this.colors.stateSpeaking);break;default:this.targetPulseColor.set(this.colors.stateIdle)}}getState(){return this._currentState}setAudioLevel(e){this.targetAudioLevel=Math.max(0,Math.min(1,e))}setEmotion(e){switch(this._currentEmotion=e,e){case"joy":this.targetPulseColor.set(this.colors.pulseJoy);break;case"thinking":this.targetPulseColor.set(this.colors.pulseThinking);break;case"interrupted":this.targetPulseColor.set(this.colors.pulseInterrupted);break;default:this.targetPulseColor.set(this.colors.pulseNeutral)}}getEmotion(){return this._currentEmotion}setColors(e){this.colors={...this.colors,...e},e.coreGlow&&this.coreOuter&&this.coreOuter.material.uniforms.uColorOuter.value.set(e.coreGlow),e.coreGlow&&this.coreGlow&&this.coreGlow.material.uniforms.uColor.value.set(e.coreGlow),e.particles&&this.particleMaterial&&this.particleMaterial.uniforms.uColor.value.set(e.particles),e.coreGlow&&this.coreLight&&this.coreLight.color.set(e.coreGlow),(e.pulseNeutral||e.pulseJoy||e.pulseThinking||e.pulseInterrupted)&&this.setEmotion(this._currentEmotion)}start(){this.animationId===null&&(this.clock.start(),this.animate())}stop(){this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null)}getCanvas(){return this.renderer.domElement}destroy(){this.stop(),window.removeEventListener("resize",this.handleResize),this.container.removeEventListener("mousemove",this.handleMouseMove),this.container.removeEventListener("mouseleave",this.handleMouseLeave),this.shellSegments.forEach(e=>{e.geometry.dispose(),e.material.dispose()}),this.coreInner&&(this.coreInner.geometry.dispose(),this.coreInner.material.dispose()),this.coreOuter&&(this.coreOuter.geometry.dispose(),this.coreOuter.material.dispose()),this.coreGlow&&(this.coreGlow.geometry.dispose(),this.coreGlow.material.dispose());for(const e of this.pulseRings)e.geometry.dispose(),e.material.dispose();this.pulseRings=[],this.particles&&(this.particles.geometry.dispose(),this.particles.material.dispose()),this.renderer.dispose(),this.renderer.domElement.parentNode&&this.renderer.domElement.parentNode.removeChild(this.renderer.domElement)}}var SM=Object.defineProperty,xM=Object.getOwnPropertyDescriptor,Vt=(i,e,t,n)=>{for(var s=n>1?void 0:n?xM(e,t):e,r=i.length-1,o;r>=0;r--)(o=i[r])&&(s=(n?o(e,t,s):o(s))||s);return n&&s&&SM(e,t,s),s};$.LinaWidget=class extends Fi{constructor(){super(...arguments),this.orbRenderer=null,this.orbContainerRef=xa(),this.audioSimPhase=0,this.animationId=null,this.callManager=null,this.size=300,this.headerLogo="HANC.ai",this.headerTitle="Lina-Voice AI",this.showBranding=!0,this.version="v1.1.0",this.agentId="",this.voiceServiceUrl="",this.btnStartText="Start",this.btnEndText="End",this.colors={},this.brandingLogoColor="rgba(255, 255, 255, 0.9)",this.brandingTitleColor="rgba(255, 255, 255, 0.6)",this.brandingDividerColor="rgba(255, 255, 255, 0.3)",this.versionColor="rgba(255, 255, 255, 0.3)",this.buttonBackground="linear-gradient(135deg, rgba(139, 92, 246, 0.95) 0%, rgba(124, 58, 237, 0.95) 100%)",this.buttonTextColor="rgba(255, 255, 255, 0.95)",this.currentState="idle",this.callStatus="idle",this.isLoading=!0,this._hasMicPermission=null,this._localAudioContext=null,this._localAudioAnalyser=null,this._localAudioMonitorId=null,this._agentIsSpeaking=!1,this._interruptionTimeout=null,this._lastInterruptionTime=0,this.handleCallClick=async()=>{if(this.callStatus==="mic-denied")try{(await navigator.mediaDevices.getUserMedia({audio:!0})).getTracks().forEach(t=>t.stop()),this._hasMicPermission=!0,this.callStatus="idle"}catch{return}this.callStatus==="active"||this.callStatus==="connecting"?await this.endCall():this.callStatus==="idle"&&await this.startCall()}}connectedCallback(){super.connectedCallback(),this.checkMicrophonePermission()}disconnectedCallback(){super.disconnectedCallback(),this.cleanup()}firstUpdated(){this.initializeOrb()}async checkMicrophonePermission(){try{const e=await navigator.permissions.query({name:"microphone"});this._hasMicPermission=e.state==="granted",e.addEventListener("change",()=>{this._hasMicPermission=e.state==="granted",e.state==="denied"?this.callStatus="mic-denied":this.callStatus==="mic-denied"&&(this.callStatus="idle")})}catch{this._hasMicPermission=null}}initializeOrb(){const e=this.orbContainerRef.value;e&&(this.orbRenderer=new pg(e,{size:1,colors:this.colors}),this.orbRenderer.start(),this.startIdleAnimation(),requestAnimationFrame(()=>{setTimeout(()=>{this.isLoading=!1},300)}))}initializeCallManager(){this.callManager||(this.callManager=new ro,this.voiceServiceUrl&&(this.callManager.serviceUrl=this.voiceServiceUrl),this.callManager.addEventListener("status-changed",(e=>{const t=e.detail;this.handleCallStatusChange(t)})),this.callManager.addEventListener("audio-track",(e=>{const t=e.detail;if(t){const n=new MediaStream([t]);this.connectAudioStream(n)}})),this.callManager.addEventListener("microphone-disabled",()=>{this.callStatus==="active"&&(this._hasMicPermission=!1)}),this.callManager.addEventListener("error",(e=>{var t,n;console.error("Call error:",(t=e.detail)==null?void 0:t.error),this.callStatus="error",this.currentState="idle",(n=this.orbRenderer)==null||n.setState("idle"),setTimeout(()=>{this.callStatus==="error"&&(this.callStatus="idle")},3e3)})),this.callManager.addEventListener("agent-command",(e=>{const t=e.detail;this.handleAgentCommand(t)})),this.callManager.addEventListener("agent-speaking",(e=>{var t;this._agentIsSpeaking=((t=e.detail)==null?void 0:t.isSpeaking)??!1})),this.callManager.addEventListener("local-audio-track",(e=>{const t=e.detail;t&&this.startLocalAudioMonitoring(t)})))}startLocalAudioMonitoring(e){this.stopLocalAudioMonitoring();try{this._localAudioContext=new AudioContext,this._localAudioAnalyser=this._localAudioContext.createAnalyser(),this._localAudioAnalyser.fftSize=256;const t=new MediaStream([e]);this._localAudioContext.createMediaStreamSource(t).connect(this._localAudioAnalyser);const s=new Uint8Array(this._localAudioAnalyser.frequencyBinCount),r=30,o=()=>{if(!this._localAudioAnalyser||this.callStatus!=="active"){this.stopLocalAudioMonitoring();return}this._localAudioAnalyser.getByteFrequencyData(s);let a=0;for(let l=0;l<s.length;l++)a+=s[l];a/s.length>r&&this._agentIsSpeaking&&this.handleUserInterruption(),this._localAudioMonitorId=requestAnimationFrame(o)};this._localAudioMonitorId=requestAnimationFrame(o)}catch(t){console.warn("Failed to start local audio monitoring:",t)}}stopLocalAudioMonitoring(){this._localAudioMonitorId&&(cancelAnimationFrame(this._localAudioMonitorId),this._localAudioMonitorId=null),this._localAudioContext&&(this._localAudioContext.close(),this._localAudioContext=null),this._localAudioAnalyser=null}handleAgentCommand(e){var t,n,s;switch(e.type){case"change_color":(t=e.payload)!=null&&t.color&&(this.setColors({coreGlow:e.payload.color}),this.dispatchEvent(new CustomEvent("color-changed",{detail:{color:e.payload.color},bubbles:!0,composed:!0})));break;case"set_emotion":(n=e.payload)!=null&&n.emotion&&this.setEmotion(e.payload.emotion);break;case"agent_state":(s=e.payload)!=null&&s.state&&(this.setState(e.payload.state),this._agentIsSpeaking=e.payload.state==="speaking");break}}handleUserInterruption(){const e=Date.now();e-this._lastInterruptionTime<1e3||(this._lastInterruptionTime=e,this.setEmotion("interrupted"),this._interruptionTimeout&&clearTimeout(this._interruptionTimeout),this._interruptionTimeout=setTimeout(()=>{this.getEmotion()==="interrupted"&&this.setEmotion("neutral"),this._interruptionTimeout=null},1500))}handleCallStatusChange(e){var t,n,s,r;switch(e){case"connecting":case"ringing":this.callStatus="connecting",this.currentState="listening",(t=this.orbRenderer)==null||t.setState("listening");break;case"connected":case"agent-connected":this.callStatus="active",this.currentState="speaking",(n=this.orbRenderer)==null||n.setState("speaking"),this.startActiveAnimation();break;case"disconnecting":this.callStatus="ending";break;case"disconnected":this.callStatus="idle",this.currentState="idle",(s=this.orbRenderer)==null||s.setState("idle"),this.startIdleAnimation();break;case"error":this.callStatus="error",this.currentState="idle",(r=this.orbRenderer)==null||r.setState("idle");break}}cleanup(){var e,t;this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null),this.stopLocalAudioMonitoring(),this._interruptionTimeout&&(clearTimeout(this._interruptionTimeout),this._interruptionTimeout=null),(e=this.callManager)==null||e.hangUp(),(t=this.orbRenderer)==null||t.destroy(),this.orbRenderer=null}startIdleAnimation(){this.animationId!==null&&cancelAnimationFrame(this.animationId);const e=()=>{if(!this.orbRenderer)return;const t=performance.now()/1e3,n=Math.sin(t*.4)*.08+Math.sin(t*.7)*.04+.15;this.orbRenderer.setAudioLevel(n),this.animationId=requestAnimationFrame(e)};this.animationId=requestAnimationFrame(e)}startActiveAnimation(){this.animationId!==null&&cancelAnimationFrame(this.animationId),this.audioSimPhase=Math.random()*Math.PI*2;const e=()=>{if(!this.orbRenderer||this.callStatus!=="active"){this.startIdleAnimation();return}this.audioSimPhase+=.03;const t=Math.sin(this.audioSimPhase*.25)*.25+.45,n=Math.sin(this.audioSimPhase*2)*.15,s=Math.sin(this.audioSimPhase*4.5)*.08,r=(Math.random()-.5)*.08,o=Math.random()>.97?Math.random()*.2:0,a=Math.max(0,Math.min(1,t+n+s+r+o));this.orbRenderer.setAudioLevel(a),this.animationId=requestAnimationFrame(e)};this.animationId=requestAnimationFrame(e)}connectAudioStream(e){if(!this.orbRenderer)return;this.animationId!==null&&cancelAnimationFrame(this.animationId);const t=new AudioContext,n=t.createAnalyser();n.fftSize=256,t.createMediaStreamSource(e).connect(n);const r=new Uint8Array(n.frequencyBinCount),o=()=>{if(!this.orbRenderer||this.callStatus!=="active"){t.close(),this.startIdleAnimation();return}n.getByteFrequencyData(r);let a=0;for(let d=0;d<r.length;d++)a+=r[d];const c=a/r.length/255,l=Math.pow(c,.7)*1.2;this.orbRenderer.setAudioLevel(Math.min(1,l)),this.animationId=requestAnimationFrame(o)};this.animationId=requestAnimationFrame(o)}async startCall(){var e,t,n,s;if(this._hasMicPermission!==!0)try{(await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}})).getTracks().forEach(o=>o.stop()),this._hasMicPermission=!0}catch{this._hasMicPermission=!1,this.callStatus="mic-denied";return}if(this.agentId&&this.voiceServiceUrl){this.initializeCallManager(),this.callStatus="connecting",this.currentState="listening",(e=this.orbRenderer)==null||e.setState("listening");try{await((t=this.callManager)==null?void 0:t.makeCall({agentId:this.agentId}))}catch(r){console.error("Failed to start call:",r),this.callStatus="error",setTimeout(()=>{var o;this.callStatus==="error"&&(this.callStatus="idle",this.currentState="idle",(o=this.orbRenderer)==null||o.setState("idle"))},3e3)}}else this.callStatus="connecting",this.currentState="listening",(n=this.orbRenderer)==null||n.setState("listening"),await new Promise(r=>setTimeout(r,1500)),this.callStatus="active",this.currentState="speaking",(s=this.orbRenderer)==null||s.setState("speaking"),this.startActiveAnimation(),this.dispatchEvent(new CustomEvent("call-start",{detail:{agentId:"demo",timestamp:Date.now()},bubbles:!0,composed:!0}))}async endCall(){var e;this.callStatus="ending",this.callManager&&await this.callManager.hangUp(),this.callStatus="idle",this.currentState="idle",(e=this.orbRenderer)==null||e.setState("idle"),this.startIdleAnimation(),this.dispatchEvent(new CustomEvent("call-end",{detail:{timestamp:Date.now()},bubbles:!0,composed:!0}))}setState(e){var t;this.currentState=e,(t=this.orbRenderer)==null||t.setState(e)}setAudioLevel(e){var t;(t=this.orbRenderer)==null||t.setAudioLevel(e)}setColors(e){var t;this.colors={...this.colors,...e},(t=this.orbRenderer)==null||t.setColors(e)}setEmotion(e){var t;(t=this.orbRenderer)==null||t.setEmotion(e)}getEmotion(){var e;return(e=this.orbRenderer)==null?void 0:e.getEmotion()}getState(){return this.currentState}getCallStatus(){return this.callStatus}getButtonContent(){switch(this.callStatus){case"connecting":return Rt`
|
|
5527
|
+
`,transparent:!0,blending:Ji,depthWrite:!1});this.particles=new IS(s,r),this.particleMaterial=r,this.scene.add(this.particles)}resetParticleFromCore(e){if(!this.particlePositions||!this.particleVelocities)return;const t=e*3,n=Math.random()*Math.PI*2,s=Math.acos(2*Math.random()-1),r=this.config.size*(.1+Math.random()*.15);this.particlePositions[t]=Math.sin(s)*Math.cos(n)*r,this.particlePositions[t+1]=Math.cos(s)*r,this.particlePositions[t+2]=Math.sin(s)*Math.sin(n)*r;const o=.0027+Math.random()*.008;this.particleVelocities[t]=this.particlePositions[t]/r*o,this.particleVelocities[t+1]=this.particlePositions[t+1]/r*o,this.particleVelocities[t+2]=this.particlePositions[t+2]/r*o,this.particleVelocities[t]+=(Math.random()-.5)*.0013,this.particleVelocities[t+1]+=(Math.random()-.5)*.0013,this.particleVelocities[t+2]+=(Math.random()-.5)*.0013}updateParticles(e){if(!this.particlePositions||!this.particleVelocities||!this.particles)return;const t=this.currentConfig.particleSpeed,n=this.config.size*.7;this.particleMaterial&&(this.particleMaterial.uniforms.uTime.value=this.time);for(let s=0;s<this.particlePositions.length/3;s++){const r=s*3;this.particlePositions[r]+=this.particleVelocities[r]*t,this.particlePositions[r+1]+=this.particleVelocities[r+1]*t,this.particlePositions[r+2]+=this.particleVelocities[r+2]*t,(Math.sqrt(this.particlePositions[r]**2+this.particlePositions[r+1]**2+this.particlePositions[r+2]**2)>=n||Math.random()<.003)&&this.resetParticleFromCore(s)}this.particles.geometry.attributes.position.needsUpdate=!0}setState(e){switch(this._currentState=e,this.targetConfig={...pu[e]},e){case"listening":this.targetPulseColor.set(this.colors.stateListening);break;case"thinking":this.targetPulseColor.set(this.colors.stateThinking);break;case"speaking":this.targetPulseColor.set(this.colors.stateSpeaking);break;default:this.targetPulseColor.set(this.colors.stateIdle)}}getState(){return this._currentState}setAudioLevel(e){this.targetAudioLevel=Math.max(0,Math.min(1,e))}setEmotion(e){switch(this._currentEmotion=e,e){case"joy":this.targetPulseColor.set(this.colors.pulseJoy);break;case"thinking":this.targetPulseColor.set(this.colors.pulseThinking);break;case"interrupted":this.targetPulseColor.set(this.colors.pulseInterrupted);break;default:this.targetPulseColor.set(this.colors.pulseNeutral)}}getEmotion(){return this._currentEmotion}setColors(e){this.colors={...this.colors,...e},e.coreGlow&&this.coreOuter&&this.coreOuter.material.uniforms.uColorOuter.value.set(e.coreGlow),e.coreGlow&&this.coreGlow&&this.coreGlow.material.uniforms.uColor.value.set(e.coreGlow),e.particles&&this.particleMaterial&&this.particleMaterial.uniforms.uColor.value.set(e.particles),e.coreGlow&&this.coreLight&&this.coreLight.color.set(e.coreGlow),(e.pulseNeutral||e.pulseJoy||e.pulseThinking||e.pulseInterrupted)&&this.setEmotion(this._currentEmotion)}start(){this.animationId===null&&(this.clock.start(),this.animate())}stop(){this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null)}getCanvas(){return this.renderer.domElement}destroy(){this.stop(),window.removeEventListener("resize",this.handleResize),this.container.removeEventListener("mousemove",this.handleMouseMove),this.container.removeEventListener("mouseleave",this.handleMouseLeave),this.shellSegments.forEach(e=>{e.geometry.dispose(),e.material.dispose()}),this.coreInner&&(this.coreInner.geometry.dispose(),this.coreInner.material.dispose()),this.coreOuter&&(this.coreOuter.geometry.dispose(),this.coreOuter.material.dispose()),this.coreGlow&&(this.coreGlow.geometry.dispose(),this.coreGlow.material.dispose());for(const e of this.pulseRings)e.geometry.dispose(),e.material.dispose();this.pulseRings=[],this.particles&&(this.particles.geometry.dispose(),this.particles.material.dispose()),this.renderer.dispose(),this.renderer.domElement.parentNode&&this.renderer.domElement.parentNode.removeChild(this.renderer.domElement)}}var SM=Object.defineProperty,xM=Object.getOwnPropertyDescriptor,Vt=(i,e,t,n)=>{for(var s=n>1?void 0:n?xM(e,t):e,r=i.length-1,o;r>=0;r--)(o=i[r])&&(s=(n?o(e,t,s):o(s))||s);return n&&s&&SM(e,t,s),s};$.LinaWidget=class extends Fi{constructor(){super(...arguments),this.orbRenderer=null,this.orbContainerRef=xa(),this.audioSimPhase=0,this.animationId=null,this.callManager=null,this.size=300,this.headerLogo="HANC.ai",this.headerTitle="Lina-Voice AI",this.showBranding=!0,this.version="v1.1.1",this.agentId="",this.voiceServiceUrl="",this.btnStartText="Start",this.btnEndText="End",this.colors={},this.brandingLogoColor="rgba(255, 255, 255, 0.9)",this.brandingTitleColor="rgba(255, 255, 255, 0.6)",this.brandingDividerColor="rgba(255, 255, 255, 0.3)",this.versionColor="rgba(255, 255, 255, 0.3)",this.buttonBackground="linear-gradient(135deg, rgba(139, 92, 246, 0.95) 0%, rgba(124, 58, 237, 0.95) 100%)",this.buttonTextColor="rgba(255, 255, 255, 0.95)",this.currentState="idle",this.callStatus="idle",this.isLoading=!0,this._hasMicPermission=null,this._localAudioContext=null,this._localAudioAnalyser=null,this._localAudioMonitorId=null,this._agentAudioContext=null,this._agentAudioAnalyser=null,this._agentAudioMonitorId=null,this._agentIsSpeaking=!1,this._interruptionTimeout=null,this._lastInterruptionTime=0,this.handleCallClick=async()=>{if(this.callStatus==="mic-denied")try{(await navigator.mediaDevices.getUserMedia({audio:!0})).getTracks().forEach(t=>t.stop()),this._hasMicPermission=!0,this.callStatus="idle"}catch{return}this.callStatus==="active"||this.callStatus==="connecting"?await this.endCall():this.callStatus==="idle"&&await this.startCall()}}connectedCallback(){super.connectedCallback(),this.checkMicrophonePermission()}disconnectedCallback(){super.disconnectedCallback(),this.cleanup()}firstUpdated(){this.initializeOrb()}async checkMicrophonePermission(){try{const e=await navigator.permissions.query({name:"microphone"});this._hasMicPermission=e.state==="granted",e.addEventListener("change",()=>{this._hasMicPermission=e.state==="granted",e.state==="denied"?this.callStatus="mic-denied":this.callStatus==="mic-denied"&&(this.callStatus="idle")})}catch{this._hasMicPermission=null}}initializeOrb(){const e=this.orbContainerRef.value;e&&(this.orbRenderer=new pg(e,{size:1,colors:this.colors}),this.orbRenderer.start(),this.startIdleAnimation(),requestAnimationFrame(()=>{setTimeout(()=>{this.isLoading=!1},300)}))}initializeCallManager(){this.callManager||(this.callManager=new ro,this.voiceServiceUrl&&(this.callManager.serviceUrl=this.voiceServiceUrl),this.callManager.addEventListener("status-changed",(e=>{const t=e.detail;this.handleCallStatusChange(t)})),this.callManager.addEventListener("audio-track",(e=>{const t=e.detail;if(t){const n=new MediaStream([t]);this.connectAudioStream(n),this.startAgentAudioMonitoring(t)}})),this.callManager.addEventListener("microphone-disabled",()=>{this.callStatus==="active"&&(this._hasMicPermission=!1)}),this.callManager.addEventListener("error",(e=>{var t,n;console.error("Call error:",(t=e.detail)==null?void 0:t.error),this.callStatus="error",this.currentState="idle",(n=this.orbRenderer)==null||n.setState("idle"),setTimeout(()=>{this.callStatus==="error"&&(this.callStatus="idle")},3e3)})),this.callManager.addEventListener("agent-command",(e=>{const t=e.detail;this.handleAgentCommand(t)})),this.callManager.addEventListener("local-audio-track",(e=>{const t=e.detail;t&&this.startLocalAudioMonitoring(t)})))}startLocalAudioMonitoring(e){this.stopLocalAudioMonitoring();try{this._localAudioContext=new AudioContext,this._localAudioAnalyser=this._localAudioContext.createAnalyser(),this._localAudioAnalyser.fftSize=256;const t=new MediaStream([e]);this._localAudioContext.createMediaStreamSource(t).connect(this._localAudioAnalyser);const s=new Uint8Array(this._localAudioAnalyser.frequencyBinCount),r=25;let o=0;const a=5,c=()=>{var u;if(!this._localAudioAnalyser||this.callStatus!=="active"){this.stopLocalAudioMonitoring();return}this._localAudioAnalyser.getByteFrequencyData(s);let l=0;for(let h=0;h<s.length;h++)l+=s[h];l/s.length>r?(o++,o>=a&&(this._agentIsSpeaking?this.handleUserInterruption():this.currentState!=="listening"&&(this.currentState="listening",(u=this.orbRenderer)==null||u.setState("listening")))):o=0,this._localAudioMonitorId=requestAnimationFrame(c)};this._localAudioMonitorId=requestAnimationFrame(c)}catch(t){console.warn("Failed to start local audio monitoring:",t)}}stopLocalAudioMonitoring(){this._localAudioMonitorId&&(cancelAnimationFrame(this._localAudioMonitorId),this._localAudioMonitorId=null),this._localAudioContext&&(this._localAudioContext.close(),this._localAudioContext=null),this._localAudioAnalyser=null}startAgentAudioMonitoring(e){this.stopAgentAudioMonitoring();try{this._agentAudioContext=new AudioContext,this._agentAudioAnalyser=this._agentAudioContext.createAnalyser(),this._agentAudioAnalyser.fftSize=256;const t=new MediaStream([e]);this._agentAudioContext.createMediaStreamSource(t).connect(this._agentAudioAnalyser);const s=new Uint8Array(this._agentAudioAnalyser.frequencyBinCount),r=15;let o=0;const a=15,c=()=>{var u;if(!this._agentAudioAnalyser||this.callStatus!=="active"){this.stopAgentAudioMonitoring();return}this._agentAudioAnalyser.getByteFrequencyData(s);let l=0;for(let h=0;h<s.length;h++)l+=s[h];l/s.length>r?(o=0,this._agentIsSpeaking||(this._agentIsSpeaking=!0,this.currentState!=="speaking"&&(this.currentState="speaking",(u=this.orbRenderer)==null||u.setState("speaking")))):(o++,o>=a&&this._agentIsSpeaking&&(this._agentIsSpeaking=!1)),this._agentAudioMonitorId=requestAnimationFrame(c)};this._agentAudioMonitorId=requestAnimationFrame(c)}catch(t){console.warn("Failed to start agent audio monitoring:",t)}}stopAgentAudioMonitoring(){this._agentAudioMonitorId&&(cancelAnimationFrame(this._agentAudioMonitorId),this._agentAudioMonitorId=null),this._agentAudioContext&&(this._agentAudioContext.close(),this._agentAudioContext=null),this._agentAudioAnalyser=null}handleAgentCommand(e){var t,n,s;switch(console.log("[LinaWidget] Received agent command:",e),e.type){case"change_color":(t=e.payload)!=null&&t.color&&(this.setColors({coreGlow:e.payload.color}),this.dispatchEvent(new CustomEvent("color-changed",{detail:{color:e.payload.color},bubbles:!0,composed:!0})));break;case"set_emotion":(n=e.payload)!=null&&n.emotion&&this.setEmotion(e.payload.emotion);break;case"agent_state":(s=e.payload)!=null&&s.state&&(this.setState(e.payload.state),this._agentIsSpeaking=e.payload.state==="speaking");break}}handleUserInterruption(){const e=Date.now();e-this._lastInterruptionTime<1e3||(this._lastInterruptionTime=e,this.setEmotion("interrupted"),this._interruptionTimeout&&clearTimeout(this._interruptionTimeout),this._interruptionTimeout=setTimeout(()=>{this.getEmotion()==="interrupted"&&this.setEmotion("neutral"),this._interruptionTimeout=null},1500))}handleCallStatusChange(e){var t,n,s,r;switch(e){case"connecting":case"ringing":this.callStatus="connecting",this.currentState="listening",(t=this.orbRenderer)==null||t.setState("listening");break;case"connected":case"agent-connected":this.callStatus="active",this.currentState="speaking",(n=this.orbRenderer)==null||n.setState("speaking"),this.startActiveAnimation();break;case"disconnecting":this.callStatus="ending";break;case"disconnected":this.callStatus="idle",this.currentState="idle",(s=this.orbRenderer)==null||s.setState("idle"),this.startIdleAnimation();break;case"error":this.callStatus="error",this.currentState="idle",(r=this.orbRenderer)==null||r.setState("idle");break}}cleanup(){var e,t;this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null),this.stopLocalAudioMonitoring(),this.stopAgentAudioMonitoring(),this._interruptionTimeout&&(clearTimeout(this._interruptionTimeout),this._interruptionTimeout=null),(e=this.callManager)==null||e.hangUp(),(t=this.orbRenderer)==null||t.destroy(),this.orbRenderer=null}startIdleAnimation(){this.animationId!==null&&cancelAnimationFrame(this.animationId);const e=()=>{if(!this.orbRenderer)return;const t=performance.now()/1e3,n=Math.sin(t*.4)*.08+Math.sin(t*.7)*.04+.15;this.orbRenderer.setAudioLevel(n),this.animationId=requestAnimationFrame(e)};this.animationId=requestAnimationFrame(e)}startActiveAnimation(){this.animationId!==null&&cancelAnimationFrame(this.animationId),this.audioSimPhase=Math.random()*Math.PI*2;const e=()=>{if(!this.orbRenderer||this.callStatus!=="active"){this.startIdleAnimation();return}this.audioSimPhase+=.03;const t=Math.sin(this.audioSimPhase*.25)*.25+.45,n=Math.sin(this.audioSimPhase*2)*.15,s=Math.sin(this.audioSimPhase*4.5)*.08,r=(Math.random()-.5)*.08,o=Math.random()>.97?Math.random()*.2:0,a=Math.max(0,Math.min(1,t+n+s+r+o));this.orbRenderer.setAudioLevel(a),this.animationId=requestAnimationFrame(e)};this.animationId=requestAnimationFrame(e)}connectAudioStream(e){if(!this.orbRenderer)return;this.animationId!==null&&cancelAnimationFrame(this.animationId);const t=new AudioContext,n=t.createAnalyser();n.fftSize=256,t.createMediaStreamSource(e).connect(n);const r=new Uint8Array(n.frequencyBinCount),o=()=>{if(!this.orbRenderer||this.callStatus!=="active"){t.close(),this.startIdleAnimation();return}n.getByteFrequencyData(r);let a=0;for(let d=0;d<r.length;d++)a+=r[d];const c=a/r.length/255,l=Math.pow(c,.7)*1.2;this.orbRenderer.setAudioLevel(Math.min(1,l)),this.animationId=requestAnimationFrame(o)};this.animationId=requestAnimationFrame(o)}async startCall(){var e,t,n,s;if(this._hasMicPermission!==!0)try{(await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}})).getTracks().forEach(o=>o.stop()),this._hasMicPermission=!0}catch{this._hasMicPermission=!1,this.callStatus="mic-denied";return}if(this.agentId&&this.voiceServiceUrl){this.initializeCallManager(),this.callStatus="connecting",this.currentState="listening",(e=this.orbRenderer)==null||e.setState("listening");try{await((t=this.callManager)==null?void 0:t.makeCall({agentId:this.agentId}))}catch(r){console.error("Failed to start call:",r),this.callStatus="error",setTimeout(()=>{var o;this.callStatus==="error"&&(this.callStatus="idle",this.currentState="idle",(o=this.orbRenderer)==null||o.setState("idle"))},3e3)}}else this.callStatus="connecting",this.currentState="listening",(n=this.orbRenderer)==null||n.setState("listening"),await new Promise(r=>setTimeout(r,1500)),this.callStatus="active",this.currentState="speaking",(s=this.orbRenderer)==null||s.setState("speaking"),this.startActiveAnimation(),this.dispatchEvent(new CustomEvent("call-start",{detail:{agentId:"demo",timestamp:Date.now()},bubbles:!0,composed:!0}))}async endCall(){var e;this.callStatus="ending",this.callManager&&await this.callManager.hangUp(),this.callStatus="idle",this.currentState="idle",(e=this.orbRenderer)==null||e.setState("idle"),this.startIdleAnimation(),this.dispatchEvent(new CustomEvent("call-end",{detail:{timestamp:Date.now()},bubbles:!0,composed:!0}))}setState(e){var t;this.currentState=e,(t=this.orbRenderer)==null||t.setState(e)}setAudioLevel(e){var t;(t=this.orbRenderer)==null||t.setAudioLevel(e)}setColors(e){var t;this.colors={...this.colors,...e},(t=this.orbRenderer)==null||t.setColors(e)}setEmotion(e){var t;(t=this.orbRenderer)==null||t.setEmotion(e)}getEmotion(){var e;return(e=this.orbRenderer)==null?void 0:e.getEmotion()}getState(){return this.currentState}getCallStatus(){return this.callStatus}getButtonContent(){switch(this.callStatus){case"connecting":return Rt`
|
|
5528
5528
|
<svg viewBox="0 0 24 24" fill="none">
|
|
5529
5529
|
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" stroke-dasharray="50 20" stroke-linecap="round"/>
|
|
5530
5530
|
</svg>
|
|
@@ -42,6 +42,14 @@ export declare class LinaWidget extends LitElement {
|
|
|
42
42
|
*/
|
|
43
43
|
private startLocalAudioMonitoring;
|
|
44
44
|
private stopLocalAudioMonitoring;
|
|
45
|
+
private _agentAudioContext;
|
|
46
|
+
private _agentAudioAnalyser;
|
|
47
|
+
private _agentAudioMonitorId;
|
|
48
|
+
/**
|
|
49
|
+
* Monitor agent audio to detect when agent is actually speaking
|
|
50
|
+
*/
|
|
51
|
+
private startAgentAudioMonitoring;
|
|
52
|
+
private stopAgentAudioMonitoring;
|
|
45
53
|
private _agentIsSpeaking;
|
|
46
54
|
private _interruptionTimeout;
|
|
47
55
|
/**
|