@streamoji/avatar-widget 0.4.2 → 0.4.4
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/avatar-widget.cjs +6 -6
- package/dist/avatar-widget.css +1 -1
- package/dist/avatar-widget.js +843 -808
- package/dist/avatar-widget.umd.js +166 -166
- package/dist/avatar-widget.umd.js.map +1 -1
- package/dist/index.d.ts +2 -4
- package/package.json +1 -1
package/dist/avatar-widget.js
CHANGED
|
@@ -1,100 +1,90 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useGLTF as
|
|
3
|
-
import { useFrame as
|
|
4
|
-
import { memo as
|
|
5
|
-
import * as
|
|
6
|
-
import { GLTFLoader as
|
|
7
|
-
const
|
|
8
|
-
},
|
|
9
|
-
},
|
|
10
|
-
const
|
|
11
|
-
return
|
|
12
|
-
const
|
|
13
|
-
if (!
|
|
14
|
-
const
|
|
15
|
-
if (!
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
(!
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
for (let
|
|
30
|
-
let
|
|
31
|
-
if (
|
|
32
|
-
const
|
|
33
|
-
for (let
|
|
34
|
-
const
|
|
35
|
-
|
|
1
|
+
import { jsx as l, jsxs as be } from "react/jsx-runtime";
|
|
2
|
+
import { useGLTF as Mt, Environment as vn } from "@react-three/drei";
|
|
3
|
+
import { useFrame as kn, Canvas as Rn, useThree as xn } from "@react-three/fiber";
|
|
4
|
+
import { memo as Tn, useMemo as Ut, useRef as c, useState as v, useEffect as W, useCallback as tt, useLayoutEffect as An, Suspense as En } from "react";
|
|
5
|
+
import * as at from "three";
|
|
6
|
+
import { GLTFLoader as Mn } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
7
|
+
const nt = "https://ai.streamoji.com", N = (...g) => {
|
|
8
|
+
}, In = (...g) => {
|
|
9
|
+
}, Yt = ({ analyser: g }) => {
|
|
10
|
+
const y = c(null), S = c(null);
|
|
11
|
+
return W(() => {
|
|
12
|
+
const L = y.current;
|
|
13
|
+
if (!L) return;
|
|
14
|
+
const j = L.getContext("2d", { alpha: !0 });
|
|
15
|
+
if (!j) return;
|
|
16
|
+
let Q, ee = null;
|
|
17
|
+
g && (g.fftSize = 128, ee = new Uint8Array(g.frequencyBinCount));
|
|
18
|
+
const Xe = () => {
|
|
19
|
+
Q = requestAnimationFrame(Xe), (L.width !== L.offsetWidth || L.height !== L.offsetHeight) && (L.width = L.offsetWidth, L.height = L.offsetHeight);
|
|
20
|
+
const Be = L.width, U = L.height;
|
|
21
|
+
if (Be === 0 || U === 0) return;
|
|
22
|
+
const rt = U / 2;
|
|
23
|
+
j.clearRect(0, 0, Be, U), j.fillStyle = "#1e293b";
|
|
24
|
+
const ve = 2, G = ve + 2, Ae = Be * 0.95, q = Math.floor(Ae / G);
|
|
25
|
+
(!S.current || S.current.length !== q) && (S.current = new Float32Array(q).fill(2));
|
|
26
|
+
const se = q * G, M = (Be - se) / 2;
|
|
27
|
+
g && ee && g.getByteFrequencyData(ee);
|
|
28
|
+
const _e = ee ? ee.length : 0, b = Math.floor(_e * 0.7) / q, ae = new Float32Array(q);
|
|
29
|
+
for (let m = 0; m < q; m++) {
|
|
30
|
+
let O = 0;
|
|
31
|
+
if (ee && b > 0) {
|
|
32
|
+
const I = Math.floor(m * b), F = Math.floor((m + 1) * b);
|
|
33
|
+
for (let Y = I; Y < F; Y++) {
|
|
34
|
+
const X = ee[Y] || 0;
|
|
35
|
+
X > O && (O = X);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
38
|
+
O < 10 && (O = 0);
|
|
39
|
+
const z = O / 255, A = O > 0 ? Math.max(2, Math.pow(z, 1.4) * U * 0.25) : 2;
|
|
40
|
+
ae[m] = A;
|
|
41
41
|
}
|
|
42
|
-
for (let
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
42
|
+
for (let m = 0; m < q; m++) {
|
|
43
|
+
const O = q - 1 - m, z = Math.max(ae[m], ae[O]), A = S.current[m] + (z - S.current[m]) * 0.3;
|
|
44
|
+
S.current[m] = A;
|
|
45
|
+
const I = M + m * G, F = rt - A / 2;
|
|
46
|
+
j.beginPath(), j.roundRect ? j.roundRect(I, F, ve, A, 4) : j.fillRect(I, F, ve, A), j.fill();
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
|
-
return
|
|
50
|
-
cancelAnimationFrame(
|
|
49
|
+
return Xe(), () => {
|
|
50
|
+
cancelAnimationFrame(Q);
|
|
51
51
|
};
|
|
52
|
-
}, [
|
|
52
|
+
}, [g]), /* @__PURE__ */ l(
|
|
53
53
|
"canvas",
|
|
54
54
|
{
|
|
55
|
-
ref:
|
|
55
|
+
ref: y,
|
|
56
56
|
style: { width: "100%", height: "100%", display: "block" }
|
|
57
57
|
}
|
|
58
58
|
);
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return Array.from(new Uint8Array(C)).map((E) => E.toString(16).padStart(2, "0")).join("");
|
|
66
|
-
}
|
|
67
|
-
function xn(m) {
|
|
68
|
-
const [C, E] = x(null);
|
|
69
|
-
return j(() => {
|
|
70
|
-
if (!m) {
|
|
71
|
-
E(null);
|
|
59
|
+
}, Dn = "https://pub-48df6f7d60d6440bbd01676ea5d90e55.r2.dev", Kt = "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/default-models/avatar-blue-suit.glb";
|
|
60
|
+
function On(g) {
|
|
61
|
+
const [y, S] = v(null);
|
|
62
|
+
return W(() => {
|
|
63
|
+
if (!g) {
|
|
64
|
+
S(null);
|
|
72
65
|
return;
|
|
73
66
|
}
|
|
74
|
-
let
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}).catch(() => {
|
|
81
|
-
y || E(qt);
|
|
82
|
-
});
|
|
67
|
+
let L = !1;
|
|
68
|
+
const j = `${Dn}/${g}.glb`;
|
|
69
|
+
return fetch(j, { method: "HEAD" }).then((Q) => {
|
|
70
|
+
L || S(Q.ok ? j : Kt);
|
|
71
|
+
}).catch(() => {
|
|
72
|
+
L || S(Kt);
|
|
83
73
|
}), () => {
|
|
84
|
-
|
|
74
|
+
L = !0;
|
|
85
75
|
};
|
|
86
|
-
}, [
|
|
76
|
+
}, [g]), y;
|
|
87
77
|
}
|
|
88
|
-
const
|
|
78
|
+
const Cn = [
|
|
89
79
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/M_Standing_Idle_Variations_001.glb",
|
|
90
80
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/M_Standing_Idle_Variations_002.glb",
|
|
91
81
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/M_Standing_Idle_002.glb",
|
|
92
82
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/M_Standing_Idle_Variations_005.glb"
|
|
93
|
-
],
|
|
83
|
+
], Un = [
|
|
94
84
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/F_Standing_Idle_Variations_001.glb",
|
|
95
85
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/F_Standing_Idle_Variations_003.glb",
|
|
96
86
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/F_Standing_Idle_Variations_003.glb"
|
|
97
|
-
],
|
|
87
|
+
], Nn = [
|
|
98
88
|
{
|
|
99
89
|
id: "m_expr_01",
|
|
100
90
|
name: "Friendly Wave",
|
|
@@ -260,23 +250,23 @@ const Tn = [
|
|
|
260
250
|
name: "Take It Easy",
|
|
261
251
|
url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_006.glb"
|
|
262
252
|
}
|
|
263
|
-
],
|
|
253
|
+
], Fn = [
|
|
264
254
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_005.glb",
|
|
265
255
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_007.glb",
|
|
266
256
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_006.glb"
|
|
267
|
-
],
|
|
257
|
+
], Pn = [
|
|
268
258
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_004.glb",
|
|
269
259
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_005.glb",
|
|
270
260
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_006.glb",
|
|
271
261
|
"https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_002.glb"
|
|
272
|
-
],
|
|
262
|
+
], Bn = {
|
|
273
263
|
zoom: 0.85,
|
|
274
264
|
position: [0.15, -0.8, 0],
|
|
275
265
|
scale: 1.5,
|
|
276
266
|
rotation: [0.15, 0.02, 0]
|
|
277
|
-
},
|
|
267
|
+
}, Wn = [-0.45, 1.9, 0.1], Vn = [-0.45, 1.75, 0.1], $n = {
|
|
278
268
|
browInnerUp: 0.2
|
|
279
|
-
},
|
|
269
|
+
}, It = 0.18, Hn = 1, jn = 0.5, Qt = 3, bt = 0.55, Dt = 0.12, Xt = 2, Zt = 2, _t = 4, en = 8, Gn = 1, tn = 0.38, nn = 0.32, rn = "__branding__", wt = {
|
|
280
270
|
neutral: { eyeLookDownLeft: 0.1, eyeLookDownRight: 0.1 },
|
|
281
271
|
happy: {
|
|
282
272
|
mouthSmileLeft: 0.2,
|
|
@@ -358,7 +348,7 @@ const Tn = [
|
|
|
358
348
|
mouthUpperUpLeft: 0.1,
|
|
359
349
|
mouthUpperUpRight: 0.1
|
|
360
350
|
}
|
|
361
|
-
},
|
|
351
|
+
}, Jn = [
|
|
362
352
|
{
|
|
363
353
|
key: "viseme_aa",
|
|
364
354
|
mix: { jawOpen: 0.4, mouthSmileLeft: 0.15, mouthSmileRight: 0.15 },
|
|
@@ -593,7 +583,7 @@ const Tn = [
|
|
|
593
583
|
}
|
|
594
584
|
},
|
|
595
585
|
{ key: "viseme_sil", mix: {} }
|
|
596
|
-
],
|
|
586
|
+
], qn = {
|
|
597
587
|
aei: [
|
|
598
588
|
{ v: "E", w: 0.8 },
|
|
599
589
|
{ v: "I", w: 0.2 }
|
|
@@ -622,507 +612,552 @@ const Tn = [
|
|
|
622
612
|
],
|
|
623
613
|
sil: [{ v: "sil", w: 1 }]
|
|
624
614
|
};
|
|
625
|
-
function
|
|
626
|
-
if (!
|
|
627
|
-
const
|
|
628
|
-
return
|
|
615
|
+
function zn(g) {
|
|
616
|
+
if (!g) return [{ v: "sil", w: 1 }];
|
|
617
|
+
const y = g.toLowerCase();
|
|
618
|
+
return qn[y] ?? [{ v: "sil", w: 1 }];
|
|
629
619
|
}
|
|
630
|
-
function
|
|
631
|
-
const { camera:
|
|
632
|
-
return
|
|
633
|
-
|
|
634
|
-
}, [
|
|
620
|
+
function Yn({ target: g }) {
|
|
621
|
+
const { camera: y } = xn();
|
|
622
|
+
return W(() => {
|
|
623
|
+
y.lookAt(...g);
|
|
624
|
+
}, [y, g]), null;
|
|
635
625
|
}
|
|
636
|
-
function
|
|
637
|
-
if (!
|
|
626
|
+
function u(g, y, S) {
|
|
627
|
+
if (!g || !g.morphTargetDictionary)
|
|
638
628
|
return;
|
|
639
|
-
const
|
|
640
|
-
if (
|
|
641
|
-
for (const
|
|
642
|
-
|
|
629
|
+
const L = g, j = L.morphTargetDictionary, Q = L.morphTargetInfluences;
|
|
630
|
+
if (Q)
|
|
631
|
+
for (const ee in j)
|
|
632
|
+
ee.toLowerCase() === y.toLowerCase() && (Q[j[ee]] = S);
|
|
643
633
|
}
|
|
644
|
-
function
|
|
645
|
-
if (!
|
|
646
|
-
const
|
|
647
|
-
if (
|
|
648
|
-
for (let
|
|
649
|
-
|
|
634
|
+
function Ot(g, y = 0.97) {
|
|
635
|
+
if (!g) return;
|
|
636
|
+
const S = g;
|
|
637
|
+
if (S.morphTargetInfluences)
|
|
638
|
+
for (let L = 0; L < S.morphTargetInfluences.length; L++)
|
|
639
|
+
S.morphTargetInfluences[L] *= y;
|
|
650
640
|
}
|
|
651
|
-
const
|
|
641
|
+
const Kn = Tn(
|
|
652
642
|
({
|
|
653
|
-
avatarUrl:
|
|
654
|
-
isPlayingRef:
|
|
655
|
-
visemeQueueRef:
|
|
656
|
-
audioContextRef:
|
|
657
|
-
responseAudioStartTimeRef:
|
|
658
|
-
adjustments:
|
|
659
|
-
mood:
|
|
660
|
-
expression:
|
|
661
|
-
agentResponse:
|
|
662
|
-
isSpeaking:
|
|
663
|
-
nextStartTimeRef:
|
|
664
|
-
stopPlayback:
|
|
665
|
-
setIsSpeaking:
|
|
666
|
-
expressionUrl:
|
|
667
|
-
onExpressionFinished:
|
|
668
|
-
isNudgeResponse:
|
|
669
|
-
avatarGender:
|
|
643
|
+
avatarUrl: g,
|
|
644
|
+
isPlayingRef: y,
|
|
645
|
+
visemeQueueRef: S,
|
|
646
|
+
audioContextRef: L,
|
|
647
|
+
responseAudioStartTimeRef: j,
|
|
648
|
+
adjustments: Q,
|
|
649
|
+
mood: ee,
|
|
650
|
+
expression: Xe,
|
|
651
|
+
agentResponse: Be,
|
|
652
|
+
isSpeaking: U,
|
|
653
|
+
nextStartTimeRef: rt,
|
|
654
|
+
stopPlayback: ve,
|
|
655
|
+
setIsSpeaking: We,
|
|
656
|
+
expressionUrl: G,
|
|
657
|
+
onExpressionFinished: Ae,
|
|
658
|
+
isNudgeResponse: q,
|
|
659
|
+
avatarGender: se
|
|
670
660
|
}) => {
|
|
671
|
-
const { scene:
|
|
672
|
-
() =>
|
|
673
|
-
[
|
|
674
|
-
),
|
|
675
|
-
() =>
|
|
676
|
-
[
|
|
677
|
-
),
|
|
678
|
-
|
|
679
|
-
if (!(!
|
|
680
|
-
if (
|
|
681
|
-
const
|
|
682
|
-
if (!
|
|
683
|
-
const
|
|
684
|
-
|
|
661
|
+
const { scene: M } = Mt(g), H = Mt(se === "female" ? Un : Cn), b = Ut(
|
|
662
|
+
() => H.flatMap((p) => p.animations),
|
|
663
|
+
[H]
|
|
664
|
+
), m = Mt(se === "female" ? Pn : Fn), O = Ut(
|
|
665
|
+
() => m.flatMap((p) => p.animations),
|
|
666
|
+
[m]
|
|
667
|
+
), z = c(null), A = c(null), I = c(null), F = c(null), Y = c(null), X = c(null), yt = c([]), [te] = v(() => new at.AnimationMixer(M)), J = c({}), V = c(null), Ee = c(0), Ze = c(!1), Ve = c(0), Me = c(!1), we = c(null), Ie = c(Qt), ct = c(-1), De = c("left"), $e = c(_t + Math.random() * (en - _t)), de = c(0), Oe = c("smile");
|
|
668
|
+
W(() => {
|
|
669
|
+
if (!(!b || !M)) {
|
|
670
|
+
if (b.forEach((p, h) => {
|
|
671
|
+
const a = `idle_${h}`;
|
|
672
|
+
if (!J.current[a]) {
|
|
673
|
+
const o = te.clipAction(p, M);
|
|
674
|
+
o.name = a, o.setLoop(at.LoopOnce, 1), o.clampWhenFinished = !0, J.current[a] = o;
|
|
685
675
|
}
|
|
686
|
-
}),
|
|
687
|
-
const
|
|
688
|
-
if (!
|
|
689
|
-
const
|
|
690
|
-
|
|
676
|
+
}), O.forEach((p, h) => {
|
|
677
|
+
const a = `talk_${h}`;
|
|
678
|
+
if (!J.current[a]) {
|
|
679
|
+
const o = te.clipAction(p, M);
|
|
680
|
+
o.name = a, o.setLoop(at.LoopOnce, 1), o.clampWhenFinished = !0, J.current[a] = o;
|
|
691
681
|
}
|
|
692
|
-
}),
|
|
693
|
-
const
|
|
694
|
-
|
|
682
|
+
}), b.length > 0) {
|
|
683
|
+
const p = J.current.idle_0, h = V.current && te.existingAction(V.current.getClip());
|
|
684
|
+
p && !h && (p.reset().fadeIn(0.5).play(), V.current = p);
|
|
695
685
|
}
|
|
696
686
|
return () => {
|
|
697
|
-
|
|
687
|
+
te.stopAllAction(), J.current = {}, V.current = null;
|
|
698
688
|
};
|
|
699
689
|
}
|
|
700
|
-
}, [
|
|
701
|
-
const
|
|
702
|
-
|
|
703
|
-
if (!
|
|
704
|
-
|
|
705
|
-
|
|
690
|
+
}, [b, O, M, te]);
|
|
691
|
+
const ke = c("");
|
|
692
|
+
W(() => {
|
|
693
|
+
if (!G || !M || G === ke.current) return;
|
|
694
|
+
ke.current = G, we.current = G, new Mn().load(
|
|
695
|
+
G,
|
|
706
696
|
(h) => {
|
|
707
697
|
if (h.animations && h.animations.length > 0) {
|
|
708
|
-
const
|
|
709
|
-
if (
|
|
710
|
-
const
|
|
711
|
-
|
|
698
|
+
const a = h.animations[0], o = te.clipAction(a, M);
|
|
699
|
+
if (o.name = `EXPR_${G}`, o.setLoop(at.LoopOnce, 1), o.clampWhenFinished = !0, J.current[`EXPR_${G}`] = o, U && we.current === G) {
|
|
700
|
+
const d = V.current;
|
|
701
|
+
o.reset().fadeIn(0.3).play(), d && d !== o && d.crossFadeTo(o, 0.3, !0), V.current = o, we.current = null;
|
|
712
702
|
}
|
|
713
703
|
}
|
|
714
704
|
},
|
|
715
705
|
void 0,
|
|
716
706
|
(h) => {
|
|
717
|
-
console.error(`[ANIMATION] Failed to load ${
|
|
707
|
+
console.error(`[ANIMATION] Failed to load ${G}`, h);
|
|
718
708
|
}
|
|
719
709
|
);
|
|
720
|
-
}, [
|
|
721
|
-
const
|
|
722
|
-
const
|
|
723
|
-
if (
|
|
724
|
-
const
|
|
725
|
-
|
|
726
|
-
} else if (
|
|
727
|
-
if (
|
|
728
|
-
const
|
|
729
|
-
Math.random() *
|
|
730
|
-
),
|
|
731
|
-
|
|
710
|
+
}, [G, M, te, U]), W(() => {
|
|
711
|
+
const p = (h) => {
|
|
712
|
+
const a = h.action, o = a.name || "";
|
|
713
|
+
if (o.startsWith("idle_")) {
|
|
714
|
+
const D = (parseInt(o.split("_")[1]) + 1) % b.length, ne = J.current[`idle_${D}`];
|
|
715
|
+
ne && (ne.reset().fadeIn(0.5).play(), a.crossFadeTo(ne, 0.5, !0), V.current = ne);
|
|
716
|
+
} else if (o.startsWith("EXPR_")) {
|
|
717
|
+
if (U) {
|
|
718
|
+
const d = Math.floor(
|
|
719
|
+
Math.random() * O.length
|
|
720
|
+
), D = J.current[`talk_${d}`];
|
|
721
|
+
D && (D.reset().fadeIn(0.5).play(), a.crossFadeTo(D, 0.5, !0), V.current = D);
|
|
732
722
|
} else {
|
|
733
|
-
const
|
|
734
|
-
|
|
723
|
+
const d = J.current.idle_0;
|
|
724
|
+
d && (d.reset().fadeIn(0.5).play(), a.crossFadeTo(d, 0.5, !0), V.current = d);
|
|
735
725
|
}
|
|
736
|
-
|
|
737
|
-
} else if (
|
|
738
|
-
if (
|
|
739
|
-
const
|
|
740
|
-
|
|
726
|
+
Ae && Ae();
|
|
727
|
+
} else if (o.startsWith("talk_"))
|
|
728
|
+
if (U && !q) {
|
|
729
|
+
const D = (parseInt(o.split("_")[1]) + 1) % O.length, ne = J.current[`talk_${D}`];
|
|
730
|
+
ne && (ne.reset().fadeIn(0.3).play(), a.crossFadeTo(ne, 0.3, !0), V.current = ne);
|
|
741
731
|
} else {
|
|
742
|
-
const
|
|
743
|
-
|
|
732
|
+
const d = J.current.idle_0;
|
|
733
|
+
d && (d.reset().fadeIn(0.5).play(), a.crossFadeTo(d, 0.5, !0), V.current = d);
|
|
744
734
|
}
|
|
745
735
|
};
|
|
746
|
-
return
|
|
736
|
+
return te.addEventListener("finished", p), () => te.removeEventListener("finished", p);
|
|
747
737
|
}, [
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
]),
|
|
755
|
-
if (
|
|
756
|
-
const
|
|
738
|
+
te,
|
|
739
|
+
b,
|
|
740
|
+
O,
|
|
741
|
+
U,
|
|
742
|
+
q,
|
|
743
|
+
Ae
|
|
744
|
+
]), W(() => {
|
|
745
|
+
if (U && M) {
|
|
746
|
+
const p = V.current, h = p?.name || "";
|
|
757
747
|
if (h.startsWith("idle_") || h.startsWith("talk_") || h === "") {
|
|
758
|
-
const
|
|
759
|
-
if (
|
|
760
|
-
const
|
|
761
|
-
if (
|
|
762
|
-
|
|
748
|
+
const a = we.current;
|
|
749
|
+
if (a) {
|
|
750
|
+
const o = J.current[`EXPR_${a}`];
|
|
751
|
+
if (o) {
|
|
752
|
+
o.reset().fadeIn(0.3).play(), p && p !== o && p.crossFadeTo(o, 0.3, !0), V.current = o, we.current = null;
|
|
763
753
|
return;
|
|
764
754
|
}
|
|
765
755
|
}
|
|
766
756
|
if (h.startsWith("idle_") || h === "") {
|
|
767
|
-
const
|
|
768
|
-
Math.random() *
|
|
769
|
-
),
|
|
770
|
-
|
|
757
|
+
const o = Math.floor(
|
|
758
|
+
Math.random() * O.length
|
|
759
|
+
), d = J.current[`talk_${o}`];
|
|
760
|
+
d && (d.reset().fadeIn(0.5).play(), p && p.crossFadeTo(d, 0.5, !0), V.current = d);
|
|
771
761
|
}
|
|
772
762
|
}
|
|
773
|
-
} else if (!
|
|
774
|
-
const
|
|
763
|
+
} else if (!U && M) {
|
|
764
|
+
const p = V.current, h = p?.name || "";
|
|
775
765
|
if (h.startsWith("talk_") || h.startsWith("EXPR_")) {
|
|
776
|
-
const
|
|
777
|
-
|
|
766
|
+
const a = J.current.idle_0;
|
|
767
|
+
a && (a.reset().fadeIn(0.5).play(), p && p.crossFadeTo(a, 0.5, !0), V.current = a);
|
|
778
768
|
}
|
|
779
769
|
}
|
|
780
|
-
}, [
|
|
781
|
-
if (!
|
|
782
|
-
|
|
783
|
-
if (
|
|
784
|
-
const
|
|
785
|
-
(
|
|
770
|
+
}, [U, M, G]), W(() => {
|
|
771
|
+
if (!M) return;
|
|
772
|
+
M.traverse((a) => {
|
|
773
|
+
if (a.isMesh && a.morphTargetDictionary) {
|
|
774
|
+
const o = a.name.toLowerCase();
|
|
775
|
+
(o.includes("head") || o.includes("avatar")) && (A.current = a, N(`[ANIMATION] Found head mesh: ${a.name}`)), o.includes("teeth") && (I.current = a, N(`[ANIMATION] Found teeth mesh: ${a.name}`)), o.includes("beard") && (F.current = a, N(`[ANIMATION] Found beard mesh: ${a.name}`)), o.includes("eyeleft") && (Y.current = a, N(`[ANIMATION] Found eye left mesh: ${a.name}`)), o.includes("eyeright") && (X.current = a, N(`[ANIMATION] Found eye right mesh: ${a.name}`));
|
|
786
776
|
}
|
|
787
777
|
});
|
|
788
|
-
const
|
|
789
|
-
|
|
790
|
-
(
|
|
778
|
+
const p = A.current?.morphTargetDictionary;
|
|
779
|
+
p && Object.keys(p).filter(
|
|
780
|
+
(a) => a.toLowerCase().includes("brow")
|
|
791
781
|
);
|
|
792
782
|
const h = [];
|
|
793
|
-
|
|
794
|
-
if (
|
|
795
|
-
const
|
|
796
|
-
|
|
783
|
+
M.traverse((a) => {
|
|
784
|
+
if (a.isMesh) {
|
|
785
|
+
const d = a.morphTargetDictionary;
|
|
786
|
+
d && Object.keys(d).some((D) => D.toLowerCase().includes("brow")) && h.push(a);
|
|
797
787
|
}
|
|
798
|
-
}),
|
|
799
|
-
}, [
|
|
800
|
-
const
|
|
801
|
-
const
|
|
802
|
-
if (
|
|
803
|
-
for (const
|
|
804
|
-
const
|
|
805
|
-
|
|
788
|
+
}), yt.current = h, h.length > 0 && N("[ANIMATION] Meshes with brow morphs:", h.length);
|
|
789
|
+
}, [M]);
|
|
790
|
+
const ot = (p, h = 1) => {
|
|
791
|
+
const a = `viseme_${p}`.toLowerCase(), o = Jn.find((d) => d.key.toLowerCase() === a);
|
|
792
|
+
if (o) {
|
|
793
|
+
for (const d in o.mix) {
|
|
794
|
+
const D = o.mix[d] * h;
|
|
795
|
+
u(A.current, d, D), u(F.current, d, D), (!o.teethMix || !(d in o.teethMix)) && u(I.current, d, D);
|
|
806
796
|
}
|
|
807
|
-
if (
|
|
808
|
-
for (const
|
|
809
|
-
const
|
|
810
|
-
|
|
797
|
+
if (o.teethMix)
|
|
798
|
+
for (const d in o.teethMix) {
|
|
799
|
+
const D = o.teethMix[d] * h;
|
|
800
|
+
u(I.current, d, D);
|
|
811
801
|
}
|
|
812
802
|
}
|
|
813
|
-
},
|
|
814
|
-
const h =
|
|
815
|
-
for (const
|
|
816
|
-
|
|
803
|
+
}, it = (p) => {
|
|
804
|
+
const h = wt[p] ?? wt.neutral;
|
|
805
|
+
for (const a in h)
|
|
806
|
+
u(A.current, a, h[a]), u(I.current, a, h[a]), u(F.current, a, h[a]);
|
|
817
807
|
};
|
|
818
|
-
return
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
const
|
|
822
|
-
let
|
|
823
|
-
if (Math.floor(
|
|
824
|
-
let
|
|
825
|
-
|
|
826
|
-
|
|
808
|
+
return kn((p, h) => {
|
|
809
|
+
const a = Math.pow(0.88, 60 * h);
|
|
810
|
+
Ot(A.current, a), Ot(I.current, a), Ot(F.current, a), it(ee);
|
|
811
|
+
const o = p.clock.elapsedTime;
|
|
812
|
+
let d = 0;
|
|
813
|
+
if (Math.floor(o) % 5 === 0 && Math.floor((o - h) % 5) !== 0) {
|
|
814
|
+
let _ = null;
|
|
815
|
+
M.traverse((P) => {
|
|
816
|
+
P.name.toLowerCase().includes("hips") && (_ = P);
|
|
827
817
|
});
|
|
828
|
-
const
|
|
829
|
-
N(`[ANIMATION] Mixer Time: ${
|
|
818
|
+
const K = _ ? `Hips Y: ${_.position.y.toFixed(4)}` : "Hips not found";
|
|
819
|
+
N(`[ANIMATION] Mixer Time: ${te.time.toFixed(2)}, ${K}`);
|
|
830
820
|
}
|
|
831
|
-
if (
|
|
832
|
-
const
|
|
833
|
-
if (
|
|
834
|
-
if (
|
|
835
|
-
const
|
|
836
|
-
|
|
821
|
+
if (te.update(h), o > Ee.current && !Ze.current && (Ze.current = !0, Ve.current = o), Ze.current) {
|
|
822
|
+
const _ = U ? 0.2 : 0.3, K = (o - Ve.current) / _;
|
|
823
|
+
if (K >= 1)
|
|
824
|
+
if (Ze.current = !1, Me.current) {
|
|
825
|
+
const P = U ? 1 : 2.5;
|
|
826
|
+
Ee.current = o + P, Me.current = !1;
|
|
837
827
|
} else
|
|
838
|
-
|
|
828
|
+
Ee.current = o + 0.12, Me.current = !0;
|
|
839
829
|
else {
|
|
840
|
-
const
|
|
841
|
-
|
|
830
|
+
const P = K < 0.5 ? K * 2 : (1 - K) * 2;
|
|
831
|
+
u(A.current, "eyeBlinkLeft", P), u(A.current, "eyeBlinkRight", P), u(I.current, "eyeBlinkLeft", P), u(I.current, "eyeBlinkRight", P), u(F.current, "eyeBlinkLeft", P), u(F.current, "eyeBlinkRight", P), d = P * $n.browInnerUp;
|
|
842
832
|
}
|
|
843
833
|
}
|
|
844
|
-
const
|
|
845
|
-
|
|
846
|
-
const
|
|
847
|
-
|
|
848
|
-
const
|
|
849
|
-
(
|
|
850
|
-
const
|
|
851
|
-
if (
|
|
852
|
-
|
|
853
|
-
const
|
|
854
|
-
|
|
834
|
+
const D = wt[ee] ?? wt.neutral, ne = D.browInnerUp ?? 0, St = D.browOuterUpLeft ?? 0, He = D.browOuterUpRight ?? 0, re = o * Hn, ut = It * Math.sin(re), Ce = It * 0.7 * Math.sin(re + 0.7), je = It * 0.7 * Math.sin(re + 1.3), R = (_) => Math.max(0, Math.min(1, _)), lt = R(ne + ut), Ge = R(St + Ce), Je = R(He + je), ht = R(lt + d);
|
|
835
|
+
u(A.current, "browInnerUp", ht), u(I.current, "browInnerUp", ht), u(F.current, "browInnerUp", ht), u(A.current, "browOuterUpLeft", Ge), u(I.current, "browOuterUpLeft", Ge), u(F.current, "browOuterUpLeft", Ge), u(A.current, "browOuterUpRight", Je), u(I.current, "browOuterUpRight", Je), u(F.current, "browOuterUpRight", Je);
|
|
836
|
+
const qe = Ie.current, Ue = qe + bt, fe = Ue + Dt;
|
|
837
|
+
o > fe && (Ie.current += bt + Dt + Qt);
|
|
838
|
+
const ye = !U && o >= qe && o < Ue, Ne = !U && o >= Ue && o < fe;
|
|
839
|
+
(ye || Ne) && ct.current !== qe && (ct.current = qe, De.current = Math.random() < 0.7 ? "left" : "up");
|
|
840
|
+
const dt = ye ? o - qe : Ne ? bt : 0, oe = ye || Ne ? Math.min(1, dt / bt) : 0, ze = oe <= 0 ? 0 : Math.sin(oe * Math.PI), ft = Ne ? 1 - (o - Ue) / Dt : 1, Lt = ye ? ze : Ne ? ze * ft : 0, Fe = jn * Lt, x = (_) => D[_] ?? 0;
|
|
841
|
+
if (De.current === "up" ? (u(Y.current, "eyeLookUpLeft", R(x("eyeLookUpLeft") + Fe)), u(Y.current, "eyeLookDownLeft", R(x("eyeLookDownLeft"))), u(Y.current, "eyeLookOutLeft", R(x("eyeLookOutLeft"))), u(Y.current, "eyeLookInLeft", R(x("eyeLookInLeft"))), u(X.current, "eyeLookUpRight", R(x("eyeLookUpRight") + Fe)), u(X.current, "eyeLookDownRight", R(x("eyeLookDownRight"))), u(X.current, "eyeLookOutRight", R(x("eyeLookOutRight"))), u(X.current, "eyeLookInRight", R(x("eyeLookInRight")))) : (u(Y.current, "eyeLookUpLeft", R(x("eyeLookUpLeft"))), u(Y.current, "eyeLookDownLeft", R(x("eyeLookDownLeft"))), u(Y.current, "eyeLookOutLeft", R(x("eyeLookOutLeft"))), u(Y.current, "eyeLookInLeft", R(x("eyeLookInLeft") + Fe)), u(X.current, "eyeLookUpRight", R(x("eyeLookUpRight"))), u(X.current, "eyeLookDownRight", R(x("eyeLookDownRight"))), u(X.current, "eyeLookOutRight", R(x("eyeLookOutRight") + Fe)), u(X.current, "eyeLookInRight", R(x("eyeLookInRight")))), !U && o >= $e.current) {
|
|
842
|
+
de.current = o, Oe.current = Math.random() < 0.5 ? "pucker" : "smile";
|
|
843
|
+
const _ = Oe.current === "pucker" ? Zt : Xt;
|
|
844
|
+
$e.current = o + _ + _t + Math.random() * (en - _t);
|
|
855
845
|
}
|
|
856
|
-
const
|
|
857
|
-
const
|
|
858
|
-
return 1 -
|
|
859
|
-
})(),
|
|
860
|
-
if (
|
|
861
|
-
if (
|
|
862
|
-
const
|
|
863
|
-
|
|
846
|
+
const ce = Oe.current === "pucker" ? Zt : Xt, ue = !U && o >= de.current && o < de.current + ce, Ye = ue ? (o - de.current) / ce : 0, Re = Ye <= 0 ? 0 : Ye < 0.5 ? Ye * 2 : (() => {
|
|
847
|
+
const _ = (Ye - 0.5) * 2;
|
|
848
|
+
return 1 - _ * _ * (3 - 2 * _);
|
|
849
|
+
})(), me = (_) => D[_] ?? 0;
|
|
850
|
+
if (ue)
|
|
851
|
+
if (Oe.current === "pucker") {
|
|
852
|
+
const _ = R(me("mouthPucker") + Gn * Re);
|
|
853
|
+
u(A.current, "mouthPucker", _), u(I.current, "mouthPucker", _), u(F.current, "mouthPucker", _);
|
|
864
854
|
} else {
|
|
865
|
-
const
|
|
866
|
-
|
|
855
|
+
const _ = R(me("mouthSmileLeft") + tn * Re), K = R(me("mouthSmileRight") + tn * Re), P = R(me("mouthDimpleLeft") + nn * Re), xe = R(me("mouthDimpleRight") + nn * Re);
|
|
856
|
+
u(A.current, "mouthSmileLeft", _), u(A.current, "mouthSmileRight", K), u(A.current, "mouthDimpleLeft", P), u(A.current, "mouthDimpleRight", xe), u(I.current, "mouthSmileLeft", _), u(I.current, "mouthSmileRight", K), u(I.current, "mouthDimpleLeft", P), u(I.current, "mouthDimpleRight", xe), u(F.current, "mouthSmileLeft", _), u(F.current, "mouthSmileRight", K), u(F.current, "mouthDimpleLeft", P), u(F.current, "mouthDimpleRight", xe);
|
|
867
857
|
}
|
|
868
|
-
if (
|
|
869
|
-
const
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
858
|
+
if (z.current) {
|
|
859
|
+
const _ = y.current ? 0 : Q.rotation[1];
|
|
860
|
+
z.current.rotation.y = at.MathUtils.lerp(
|
|
861
|
+
z.current.rotation.y,
|
|
862
|
+
_,
|
|
873
863
|
0.1
|
|
874
|
-
),
|
|
864
|
+
), z.current.position.set(...Q.position), z.current.scale.setScalar(Q.scale), z.current.rotation.x = Q.rotation[0], z.current.rotation.z = Q.rotation[2];
|
|
875
865
|
}
|
|
876
|
-
if (
|
|
877
|
-
const
|
|
878
|
-
for (let
|
|
879
|
-
const
|
|
880
|
-
|
|
866
|
+
if (y.current && L.current) {
|
|
867
|
+
const _ = L.current.currentTime, xe = (_ - j.current) * 1e3 - -150;
|
|
868
|
+
for (let le = 0; le < S.current.length; le++) {
|
|
869
|
+
const he = S.current[le];
|
|
870
|
+
xe >= he.vtime && xe < he.vtime + he.vduration && ot(he.viseme, he.weight ?? 1);
|
|
881
871
|
}
|
|
882
|
-
|
|
872
|
+
_ > rt.current + 0.5 && (ve(), We(!1));
|
|
883
873
|
}
|
|
884
|
-
}), /* @__PURE__ */
|
|
874
|
+
}), /* @__PURE__ */ l("group", { ref: z, children: /* @__PURE__ */ l("primitive", { object: M }) });
|
|
885
875
|
}
|
|
886
876
|
);
|
|
887
|
-
function
|
|
888
|
-
return
|
|
877
|
+
function Qn(g) {
|
|
878
|
+
return g ? g.charAt(0).toUpperCase() + g.slice(1).toLowerCase() : "";
|
|
889
879
|
}
|
|
890
|
-
function
|
|
891
|
-
return
|
|
880
|
+
function on(g) {
|
|
881
|
+
return g.replace(/\*(.*?)\*/g, " $1 ").replace(/\[.*?\]/g, " ").replace(/<.*?\/>/g, " ").replace(/<.*?>.*?<\/.*?>/g, " ").replace(/\s+/g, " ").trim();
|
|
892
882
|
}
|
|
893
|
-
const
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
883
|
+
const Ct = /* @__PURE__ */ new Map(), Xn = ({
|
|
884
|
+
onNavigationRequested: g,
|
|
885
|
+
agentId: y,
|
|
886
|
+
presetUserDetails: S,
|
|
887
|
+
onAvatarReady: L
|
|
888
|
+
}) => {
|
|
889
|
+
const [j, Q] = v(""), [ee, Xe] = v("male"), [Be, U] = v(""), [rt, ve] = v(!1), We = j, G = ee;
|
|
890
|
+
W(() => {
|
|
891
|
+
if (!y) {
|
|
892
|
+
ve(!0);
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
let e = !1;
|
|
896
|
+
return (async () => {
|
|
897
|
+
console.log(">> fetchConfig RUNNING for", y);
|
|
898
|
+
try {
|
|
899
|
+
const n = `agent_config_${y}`, i = sessionStorage.getItem(n);
|
|
900
|
+
if (i)
|
|
901
|
+
try {
|
|
902
|
+
const s = JSON.parse(i);
|
|
903
|
+
e || (s.encryptedAgentToken && Q(s.encryptedAgentToken), s.avatarGender && Xe(s.avatarGender), s.agent_id && U(s.agent_id), ve(!0));
|
|
904
|
+
return;
|
|
905
|
+
} catch (s) {
|
|
906
|
+
console.error("Failed to parse cached avatar config:", s), sessionStorage.removeItem(n);
|
|
907
|
+
}
|
|
908
|
+
let t;
|
|
909
|
+
if (Ct.has(y))
|
|
910
|
+
console.log(">> REUSING in-flight fetch for", y), t = await Ct.get(y);
|
|
911
|
+
else {
|
|
912
|
+
const s = (async () => {
|
|
913
|
+
console.log(">> INITIATING visitedWebsite fetch for", y);
|
|
914
|
+
const f = { agentId: y }, w = await fetch(`${nt}/visitedWebsite`, {
|
|
915
|
+
method: "POST",
|
|
916
|
+
headers: { "Content-Type": "application/json" },
|
|
917
|
+
body: JSON.stringify(f)
|
|
918
|
+
});
|
|
919
|
+
if (!w.ok) throw new Error(`Fetch failed: ${w.status}`);
|
|
920
|
+
const k = await w.json();
|
|
921
|
+
return sessionStorage.setItem(n, JSON.stringify(k)), k;
|
|
922
|
+
})();
|
|
923
|
+
Ct.set(y, s), t = await s;
|
|
924
|
+
}
|
|
925
|
+
if (e) return;
|
|
926
|
+
t && (t.encryptedAgentToken && Q(t.encryptedAgentToken), t.avatarGender && Xe(t.avatarGender), t.agent_id && U(t.agent_id));
|
|
927
|
+
} catch (n) {
|
|
928
|
+
console.error("Failed to fetch avatar config:", n);
|
|
929
|
+
} finally {
|
|
930
|
+
e || ve(!0);
|
|
931
|
+
}
|
|
932
|
+
})(), () => {
|
|
933
|
+
e = !0;
|
|
934
|
+
};
|
|
935
|
+
}, [y]);
|
|
936
|
+
const Ae = On(y ?? Be), [q, se] = v(""), [M, _e] = v(""), [H, b] = v("Ready"), [ae, m] = v(!1), [O, z] = v(!1), [A, I] = v([]), [F, Y] = v(""), X = c(null), [yt, te] = v(
|
|
902
937
|
() => typeof window < "u" ? window.matchMedia("(max-width: 480px)").matches : !1
|
|
903
938
|
);
|
|
904
|
-
|
|
905
|
-
const e = window.matchMedia("(max-width: 480px)"),
|
|
906
|
-
return e.addEventListener("change",
|
|
939
|
+
W(() => {
|
|
940
|
+
const e = window.matchMedia("(max-width: 480px)"), r = () => te(e.matches);
|
|
941
|
+
return e.addEventListener("change", r), () => e.removeEventListener("change", r);
|
|
907
942
|
}, []);
|
|
908
|
-
const
|
|
909
|
-
|
|
910
|
-
const
|
|
943
|
+
const J = yt ? 80 : 600, V = c(!1), Ee = c([]), Ze = c(0), Ve = c(!1), Me = c([]), we = c(null), Ie = c([]);
|
|
944
|
+
c([]);
|
|
945
|
+
const ct = c([]), De = c(0), $e = c(0), de = c(0), Oe = c(0), ke = c(!1), [ot, it] = v(
|
|
911
946
|
null
|
|
912
|
-
),
|
|
947
|
+
), p = c(null), [h, a] = v("neutral"), [o, d] = v(""), [D, ne] = v(""), [St, He] = v("Chat with us"), [re, ut] = v(
|
|
913
948
|
null
|
|
914
|
-
), [
|
|
915
|
-
|
|
916
|
-
const [
|
|
917
|
-
|
|
918
|
-
const
|
|
919
|
-
|
|
920
|
-
if (
|
|
921
|
-
|
|
949
|
+
), [Ce, je] = v("hidden"), [R, lt] = v(""), Ge = c(null), Je = c(Ce);
|
|
950
|
+
Je.current = Ce;
|
|
951
|
+
const [ht, qe] = v(null), Ue = c(null), fe = c(null), [ye, Ne] = v(!1), dt = c(null), [oe, ze] = v("hidden"), [ft, Lt] = v(""), Fe = c(oe);
|
|
952
|
+
Fe.current = oe;
|
|
953
|
+
const x = c(""), ce = c(!1), ue = c(""), Ye = c(Date.now()), Re = c([]), me = c(!1), [_, K] = v(!1), [P, xe] = v(!1), le = c(null), he = Ut(() => ye ? "Try again" : H === "Busy" ? "Busy" : H === "Thinking..." || H === "Processing Voice..." ? H : re != null && re !== "" && re !== "none" && re !== "<none>" ? `Enter ${Qn(re)}` : oe !== "hidden" || !P ? null : rn, [H, re, ye, oe, P]), Nt = !ye && H !== "Busy" && H !== "Thinking..." && H !== "Processing Voice..." && (re == null || re === "" || re === "none" || re === "<none>");
|
|
954
|
+
W(() => {
|
|
955
|
+
if (oe !== "hidden" || !Nt) {
|
|
956
|
+
xe(!1), le.current != null && (clearTimeout(le.current), le.current = null);
|
|
922
957
|
return;
|
|
923
958
|
}
|
|
924
|
-
return
|
|
925
|
-
|
|
959
|
+
return le.current = setTimeout(() => {
|
|
960
|
+
le.current = null, xe(!0);
|
|
926
961
|
}, 400), () => {
|
|
927
|
-
|
|
962
|
+
le.current != null && (clearTimeout(le.current), le.current = null);
|
|
928
963
|
};
|
|
929
|
-
}, [
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
const e =
|
|
964
|
+
}, [oe, Nt]);
|
|
965
|
+
const mt = he != null && he !== "";
|
|
966
|
+
W(() => {
|
|
967
|
+
const e = Je.current;
|
|
933
968
|
if (!(e === "exiting" || e === "entering")) {
|
|
934
969
|
if (e === "hidden") {
|
|
935
|
-
|
|
970
|
+
mt && (lt(he ?? ""), je("entering"));
|
|
936
971
|
return;
|
|
937
972
|
}
|
|
938
|
-
e === "visible" && (!
|
|
973
|
+
e === "visible" && (!mt || he !== R) && (Ge.current = mt ? he : null, je("exiting"));
|
|
939
974
|
}
|
|
940
975
|
}, [
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
]),
|
|
946
|
-
if (
|
|
947
|
-
|
|
976
|
+
mt,
|
|
977
|
+
he,
|
|
978
|
+
Ce,
|
|
979
|
+
R
|
|
980
|
+
]), W(() => {
|
|
981
|
+
if (H !== "Busy") {
|
|
982
|
+
fe.current != null && (clearTimeout(fe.current), fe.current = null);
|
|
948
983
|
return;
|
|
949
984
|
}
|
|
950
|
-
return
|
|
951
|
-
|
|
985
|
+
return fe.current = setTimeout(() => {
|
|
986
|
+
fe.current = null, b("Ready"), Ne(!0);
|
|
952
987
|
}, 12e3), () => {
|
|
953
|
-
|
|
988
|
+
fe.current != null && (clearTimeout(fe.current), fe.current = null);
|
|
954
989
|
};
|
|
955
|
-
}, [
|
|
956
|
-
if (!
|
|
957
|
-
const e = setTimeout(() =>
|
|
990
|
+
}, [H]), W(() => {
|
|
991
|
+
if (!ye) return;
|
|
992
|
+
const e = setTimeout(() => Ne(!1), 2500);
|
|
958
993
|
return () => clearTimeout(e);
|
|
959
|
-
}, [
|
|
960
|
-
const
|
|
961
|
-
const e =
|
|
994
|
+
}, [ye]);
|
|
995
|
+
const sn = tt(() => {
|
|
996
|
+
const e = Je.current;
|
|
962
997
|
if (e === "exiting") {
|
|
963
|
-
|
|
964
|
-
const
|
|
965
|
-
|
|
966
|
-
} else e === "entering" &&
|
|
967
|
-
}, []),
|
|
998
|
+
je("hidden");
|
|
999
|
+
const r = Ge.current;
|
|
1000
|
+
Ge.current = null, r != null && r !== "" && (lt(r), je("entering"));
|
|
1001
|
+
} else e === "entering" && je("visible");
|
|
1002
|
+
}, []), an = (e) => {
|
|
968
1003
|
if (!e) return;
|
|
969
1004
|
if (e.mood != null) {
|
|
970
|
-
const
|
|
971
|
-
|
|
1005
|
+
const t = String(e.mood).toLowerCase();
|
|
1006
|
+
a(t);
|
|
972
1007
|
}
|
|
973
1008
|
if (e.expression != null) {
|
|
974
|
-
const
|
|
975
|
-
|
|
976
|
-
const
|
|
977
|
-
(
|
|
1009
|
+
const t = String(e.expression).trim();
|
|
1010
|
+
d(t);
|
|
1011
|
+
const s = Nn.find(
|
|
1012
|
+
(f) => f.name.toLowerCase() === t.toLowerCase()
|
|
978
1013
|
);
|
|
979
1014
|
N(
|
|
980
|
-
`[STREAM] Animation match for "${
|
|
981
|
-
),
|
|
1015
|
+
`[STREAM] Animation match for "${t}": ${s ? s.name : "NONE"}`
|
|
1016
|
+
), ne(s?.url ?? "");
|
|
982
1017
|
}
|
|
983
1018
|
if (e.navigation != null) {
|
|
984
|
-
const
|
|
985
|
-
|
|
1019
|
+
const t = String(e.navigation).trim();
|
|
1020
|
+
t !== "" && (g ? g(t) : window.open(t, "_blank"));
|
|
986
1021
|
}
|
|
987
|
-
const
|
|
988
|
-
if (
|
|
989
|
-
const
|
|
990
|
-
if (
|
|
1022
|
+
const r = e.ask_for || e.lead_capture?.ask_for, n = r ? String(r).trim().toLowerCase() : "", i = n === "none" || n === "<none>";
|
|
1023
|
+
if (r && !i) {
|
|
1024
|
+
const t = n;
|
|
1025
|
+
if (S && (t === "email" && S.email || t === "name" && S.name || t === "phone" && S.phone))
|
|
991
1026
|
return;
|
|
992
|
-
|
|
993
|
-
} else (
|
|
1027
|
+
ut(t || null), He(t === "email" ? "Enter your email" : t === "name" ? "Enter your name" : t === "phone" ? "Enter your phone number" : "Chat with us");
|
|
1028
|
+
} else (i || e.ask_for === null || e.lead_capture && e.lead_capture.ask_for === null || e.ask_for === "none") && (ut(null), St !== "Chat with us" && He("Chat with us"));
|
|
994
1029
|
e.collected, e.valid;
|
|
995
|
-
},
|
|
996
|
-
const
|
|
997
|
-
if (!
|
|
998
|
-
if (
|
|
1030
|
+
}, cn = (e) => {
|
|
1031
|
+
const r = e.trim();
|
|
1032
|
+
if (!r) return null;
|
|
1033
|
+
if (r.startsWith("{"))
|
|
999
1034
|
try {
|
|
1000
|
-
return JSON.parse(
|
|
1035
|
+
return JSON.parse(r);
|
|
1001
1036
|
} catch {
|
|
1002
1037
|
return null;
|
|
1003
1038
|
}
|
|
1004
|
-
if (
|
|
1005
|
-
const
|
|
1006
|
-
return { [
|
|
1039
|
+
if (r.includes(":")) {
|
|
1040
|
+
const n = r.split(":"), i = n[0].trim().toLowerCase(), t = n.slice(1).join(":").trim();
|
|
1041
|
+
return { [i]: t };
|
|
1007
1042
|
}
|
|
1008
1043
|
return null;
|
|
1009
|
-
},
|
|
1010
|
-
}, []),
|
|
1011
|
-
for (;
|
|
1044
|
+
}, un = tt(() => {
|
|
1045
|
+
}, []), Pe = "§", vt = () => {
|
|
1046
|
+
for (; x.current.includes(`
|
|
1012
1047
|
`); ) {
|
|
1013
|
-
const e =
|
|
1014
|
-
`),
|
|
1015
|
-
|
|
1016
|
-
const
|
|
1017
|
-
|
|
1048
|
+
const e = x.current.indexOf(`
|
|
1049
|
+
`), r = x.current.slice(0, e).trim();
|
|
1050
|
+
x.current = x.current.slice(e + 1);
|
|
1051
|
+
const n = cn(r);
|
|
1052
|
+
n && an(n);
|
|
1018
1053
|
}
|
|
1019
|
-
},
|
|
1020
|
-
if (
|
|
1021
|
-
if (e.includes(
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1024
|
-
} else e ===
|
|
1025
|
-
else if (e.includes(
|
|
1026
|
-
const
|
|
1027
|
-
|
|
1028
|
-
} else if (e ===
|
|
1029
|
-
|
|
1054
|
+
}, Ft = (e) => {
|
|
1055
|
+
if (ce.current)
|
|
1056
|
+
if (e.includes(Pe)) {
|
|
1057
|
+
const r = e.indexOf(Pe), n = e.slice(0, r), i = e.slice(r + Pe.length);
|
|
1058
|
+
n && (ue.current += n, _e((t) => t + n)), ce.current = !1, i && (x.current += i, vt());
|
|
1059
|
+
} else e === Pe ? ce.current = !1 : (ue.current += e, _e((r) => r + e));
|
|
1060
|
+
else if (e.includes(Pe)) {
|
|
1061
|
+
const r = e.indexOf(Pe), n = e.slice(0, r), i = e.slice(r + Pe.length);
|
|
1062
|
+
x.current += n, vt(), ce.current = !0, i && (ue.current += i, _e((t) => t + i));
|
|
1063
|
+
} else if (e === Pe) {
|
|
1064
|
+
ce.current = !0;
|
|
1030
1065
|
return;
|
|
1031
1066
|
} else
|
|
1032
|
-
|
|
1067
|
+
x.current += e, vt();
|
|
1033
1068
|
};
|
|
1034
|
-
|
|
1069
|
+
W(() => {
|
|
1035
1070
|
(async () => {
|
|
1036
1071
|
if (!sessionStorage.getItem(
|
|
1037
1072
|
"STREAMOJI_LEADS_SESSION_LEAD_ID"
|
|
1038
1073
|
)) {
|
|
1039
|
-
const
|
|
1074
|
+
const t = "secret", s = Math.floor(Date.now() / 1e3).toString();
|
|
1040
1075
|
try {
|
|
1041
|
-
const
|
|
1076
|
+
const f = new TextEncoder(), w = await crypto.subtle.importKey(
|
|
1042
1077
|
"raw",
|
|
1043
|
-
|
|
1078
|
+
f.encode(t),
|
|
1044
1079
|
{ name: "HMAC", hash: "SHA-256" },
|
|
1045
1080
|
!1,
|
|
1046
1081
|
["sign"]
|
|
1047
1082
|
), k = await crypto.subtle.sign(
|
|
1048
1083
|
"HMAC",
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
),
|
|
1052
|
-
sessionStorage.setItem("STREAMOJI_LEADS_SESSION_LEAD_ID",
|
|
1053
|
-
} catch (
|
|
1054
|
-
console.error("[SESSION] HMAC generation failed:",
|
|
1055
|
-
const
|
|
1056
|
-
sessionStorage.setItem("STREAMOJI_LEADS_SESSION_LEAD_ID",
|
|
1084
|
+
w,
|
|
1085
|
+
f.encode(s)
|
|
1086
|
+
), T = Array.from(new Uint8Array(k)).map((C) => C.toString(16).padStart(2, "0")).join("");
|
|
1087
|
+
sessionStorage.setItem("STREAMOJI_LEADS_SESSION_LEAD_ID", T), N("[SESSION] New HMAC UID generated and saved:", T);
|
|
1088
|
+
} catch (f) {
|
|
1089
|
+
console.error("[SESSION] HMAC generation failed:", f);
|
|
1090
|
+
const w = Math.random().toString(36) + Date.now().toString();
|
|
1091
|
+
sessionStorage.setItem("STREAMOJI_LEADS_SESSION_LEAD_ID", w);
|
|
1057
1092
|
}
|
|
1058
1093
|
}
|
|
1059
|
-
const
|
|
1060
|
-
let
|
|
1061
|
-
if (
|
|
1094
|
+
const n = sessionStorage.getItem("STREAMOJI_LEADS_SESSION_MESSAGES");
|
|
1095
|
+
let i = [];
|
|
1096
|
+
if (n)
|
|
1062
1097
|
try {
|
|
1063
|
-
|
|
1098
|
+
i = JSON.parse(n);
|
|
1064
1099
|
} catch {
|
|
1065
|
-
|
|
1100
|
+
i = [];
|
|
1066
1101
|
}
|
|
1067
|
-
|
|
1102
|
+
i.length === 0 && S && (S.name || S.email) ? (i = [{ role: "user", content: `PRESET_USER_DETAILS: Name is "${S.name || ""}" , Email is "${S.email || ""}"` }], sessionStorage.setItem(
|
|
1068
1103
|
"STREAMOJI_LEADS_SESSION_MESSAGES",
|
|
1069
|
-
JSON.stringify(
|
|
1070
|
-
)) :
|
|
1104
|
+
JSON.stringify(i)
|
|
1105
|
+
)) : n || sessionStorage.setItem(
|
|
1071
1106
|
"STREAMOJI_LEADS_SESSION_MESSAGES",
|
|
1072
1107
|
JSON.stringify([])
|
|
1073
1108
|
);
|
|
1074
1109
|
})();
|
|
1075
|
-
}, [
|
|
1110
|
+
}, [S]), W(() => {
|
|
1076
1111
|
const e = () => {
|
|
1077
|
-
|
|
1112
|
+
Ye.current = Date.now(), me.current && (me.current = !1, K(!1), I([]), Y(""), _e(""), z(!1));
|
|
1078
1113
|
};
|
|
1079
1114
|
window.addEventListener("mousemove", e), window.addEventListener("keydown", e), window.addEventListener("mousedown", e), window.addEventListener("touchstart", e);
|
|
1080
|
-
const
|
|
1081
|
-
if (Date.now() -
|
|
1082
|
-
if (
|
|
1083
|
-
|
|
1115
|
+
const r = setInterval(async () => {
|
|
1116
|
+
if (Date.now() - Ye.current >= 3e4 && !O && !ae && H === "Ready" && !me.current)
|
|
1117
|
+
if (me.current = !0, Re.current.length > 0)
|
|
1118
|
+
K(!0), I(Re.current);
|
|
1084
1119
|
else
|
|
1085
1120
|
try {
|
|
1086
|
-
const
|
|
1121
|
+
const t = `${nt}/nudgeUser`, s = {
|
|
1087
1122
|
navigationUrl: window.location.href,
|
|
1088
|
-
token:
|
|
1089
|
-
},
|
|
1123
|
+
token: We
|
|
1124
|
+
}, f = await fetch(t, {
|
|
1090
1125
|
method: "POST",
|
|
1091
1126
|
headers: {
|
|
1092
1127
|
"Content-Type": "application/json"
|
|
1093
1128
|
},
|
|
1094
|
-
body: JSON.stringify(
|
|
1129
|
+
body: JSON.stringify(s)
|
|
1095
1130
|
});
|
|
1096
|
-
if (
|
|
1097
|
-
const k = (await
|
|
1098
|
-
k && k.length > 0 && (N("[NUDGE] Received nudge questions from API:", k),
|
|
1131
|
+
if (f.ok) {
|
|
1132
|
+
const k = (await f.json()).nudge_questions;
|
|
1133
|
+
k && k.length > 0 && (N("[NUDGE] Received nudge questions from API:", k), Re.current = k, K(!0), I(k));
|
|
1099
1134
|
}
|
|
1100
|
-
} catch (
|
|
1101
|
-
console.error("[NUDGE] Error calling /nudgeUser:",
|
|
1135
|
+
} catch (t) {
|
|
1136
|
+
console.error("[NUDGE] Error calling /nudgeUser:", t), me.current = !1;
|
|
1102
1137
|
}
|
|
1103
1138
|
}, 1e3);
|
|
1104
1139
|
return () => {
|
|
1105
|
-
window.removeEventListener("mousemove", e), window.removeEventListener("keydown", e), window.removeEventListener("mousedown", e), window.removeEventListener("touchstart", e), clearInterval(
|
|
1140
|
+
window.removeEventListener("mousemove", e), window.removeEventListener("keydown", e), window.removeEventListener("mousedown", e), window.removeEventListener("touchstart", e), clearInterval(r);
|
|
1106
1141
|
};
|
|
1107
|
-
}, [
|
|
1108
|
-
if (
|
|
1109
|
-
let e = 0,
|
|
1110
|
-
const
|
|
1111
|
-
const
|
|
1112
|
-
if (
|
|
1113
|
-
const
|
|
1114
|
-
|
|
1142
|
+
}, [We, O, ae, H]), W(() => {
|
|
1143
|
+
if (A.length === 0) return;
|
|
1144
|
+
let e = 0, r = 0, n = !1, i = 100;
|
|
1145
|
+
const t = () => {
|
|
1146
|
+
const s = A[e];
|
|
1147
|
+
if (n) {
|
|
1148
|
+
const f = s.substring(0, r - 1);
|
|
1149
|
+
Y(f), r--, i = 50;
|
|
1115
1150
|
} else {
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1151
|
+
const f = s.substring(0, r + 1);
|
|
1152
|
+
Y(f), r++, i = 100;
|
|
1118
1153
|
}
|
|
1119
|
-
!
|
|
1154
|
+
!n && r === s.length ? (n = !0, i = 3e3) : n && r === 0 && (n = !1, e = (e + 1) % A.length, i = 500), X.current = setTimeout(t, i);
|
|
1120
1155
|
};
|
|
1121
|
-
return
|
|
1122
|
-
|
|
1156
|
+
return t(), () => {
|
|
1157
|
+
X.current && clearTimeout(X.current);
|
|
1123
1158
|
};
|
|
1124
|
-
}, [
|
|
1125
|
-
const
|
|
1159
|
+
}, [A]);
|
|
1160
|
+
const Pt = () => {
|
|
1126
1161
|
try {
|
|
1127
1162
|
return JSON.parse(
|
|
1128
1163
|
sessionStorage.getItem("STREAMOJI_LEADS_SESSION_MESSAGES") || "[]"
|
|
@@ -1130,232 +1165,233 @@ const Jn = ({
|
|
|
1130
1165
|
} catch {
|
|
1131
1166
|
return [];
|
|
1132
1167
|
}
|
|
1133
|
-
},
|
|
1168
|
+
}, ln = (e) => {
|
|
1134
1169
|
sessionStorage.setItem(
|
|
1135
1170
|
"STREAMOJI_LEADS_SESSION_MESSAGES",
|
|
1136
1171
|
JSON.stringify(e)
|
|
1137
1172
|
);
|
|
1138
|
-
}, [
|
|
1173
|
+
}, [kt, Rt] = v(!1), [Bt, xt] = v(0), Se = c(null), pt = c([]), Wt = c(0), [Vt, hn] = v(
|
|
1139
1174
|
null
|
|
1140
|
-
), [
|
|
1175
|
+
), [dn, Tt] = v(
|
|
1141
1176
|
null
|
|
1142
|
-
),
|
|
1177
|
+
), Te = c(null), Ke = c(
|
|
1143
1178
|
null
|
|
1144
|
-
),
|
|
1145
|
-
e && (
|
|
1179
|
+
), st = tt((e = !1) => {
|
|
1180
|
+
e && (ke.current = !0, m(!1), b("Ready")), Me.current = [], Ee.current = [], Ve.current = !1, z(!1), De.current = 0, $e.current = 0, de.current = 0, Ie.current.forEach((r) => {
|
|
1146
1181
|
try {
|
|
1147
|
-
|
|
1182
|
+
r.stop();
|
|
1148
1183
|
} catch {
|
|
1149
1184
|
}
|
|
1150
|
-
}),
|
|
1151
|
-
}, []),
|
|
1185
|
+
}), Ue.current && (clearTimeout(Ue.current), Ue.current = null), qe(null), ne(""), Ie.current = [];
|
|
1186
|
+
}, []), fn = async () => {
|
|
1152
1187
|
try {
|
|
1153
|
-
const e = await navigator.mediaDevices.getUserMedia({ audio: !0 }),
|
|
1154
|
-
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
},
|
|
1159
|
-
const
|
|
1160
|
-
if (
|
|
1161
|
-
|
|
1188
|
+
const e = await navigator.mediaDevices.getUserMedia({ audio: !0 }), r = window.AudioContext || window.webkitAudioContext, n = new r(), i = n.createMediaStreamSource(e), t = n.createAnalyser();
|
|
1189
|
+
t.fftSize = 64, i.connect(t), Te.current = n, Ke.current = i, Tt(t);
|
|
1190
|
+
const s = new MediaRecorder(e);
|
|
1191
|
+
Se.current = s, pt.current = [], s.ondataavailable = (f) => {
|
|
1192
|
+
f.data.size > 0 && pt.current.push(f.data);
|
|
1193
|
+
}, s.onstop = async () => {
|
|
1194
|
+
const f = Date.now() - Wt.current;
|
|
1195
|
+
if (Tt(null), Ke.current && (Ke.current.disconnect(), Ke.current = null), Te.current && Te.current.state !== "closed" && (Te.current.close(), Te.current = null), f < 1e3) {
|
|
1196
|
+
b("Recording too short. Hold or click longer."), m(!1);
|
|
1162
1197
|
return;
|
|
1163
1198
|
}
|
|
1164
|
-
const
|
|
1199
|
+
const w = new Blob(pt.current, {
|
|
1165
1200
|
type: "audio/wav"
|
|
1166
1201
|
});
|
|
1167
|
-
await
|
|
1168
|
-
},
|
|
1202
|
+
await bn(w);
|
|
1203
|
+
}, Wt.current = Date.now(), s.start(100), Rt(!0), b("Listening...");
|
|
1169
1204
|
} catch (e) {
|
|
1170
|
-
console.error("Error accessing microphone:", e),
|
|
1205
|
+
console.error("Error accessing microphone:", e), b("Mic Access Error");
|
|
1171
1206
|
}
|
|
1172
|
-
},
|
|
1173
|
-
|
|
1174
|
-
},
|
|
1175
|
-
|
|
1207
|
+
}, mn = () => {
|
|
1208
|
+
Se.current && Se.current.state !== "inactive" && (Se.current.stop(), Se.current.stream.getTracks().forEach((e) => e.stop()), Rt(!1));
|
|
1209
|
+
}, pn = () => {
|
|
1210
|
+
Se.current && Se.current.state !== "inactive" && (Se.current.onstop = null, Se.current.stop(), Se.current.stream.getTracks().forEach((e) => e.stop()), Tt(null), Ke.current && (Ke.current.disconnect(), Ke.current = null), Te.current && Te.current.state !== "closed" && (Te.current.close(), Te.current = null), Rt(!1), pt.current = [], b("Ready"));
|
|
1176
1211
|
};
|
|
1177
|
-
|
|
1178
|
-
if (!
|
|
1212
|
+
W(() => {
|
|
1213
|
+
if (!O) return;
|
|
1179
1214
|
const e = () => {
|
|
1180
|
-
const
|
|
1181
|
-
if (
|
|
1182
|
-
const
|
|
1183
|
-
if (!
|
|
1184
|
-
const
|
|
1185
|
-
if (
|
|
1215
|
+
const r = de.current;
|
|
1216
|
+
if (r <= 0) return;
|
|
1217
|
+
const n = we.current, i = De.current;
|
|
1218
|
+
if (!n) return;
|
|
1219
|
+
const t = n.currentTime - i, s = Math.min(Math.max(0, t), r), w = on(M).trim().length;
|
|
1220
|
+
if (w <= 0) return;
|
|
1186
1221
|
const k = Math.min(
|
|
1187
|
-
Math.round(
|
|
1188
|
-
|
|
1222
|
+
Math.round(s / r * w),
|
|
1223
|
+
w
|
|
1189
1224
|
);
|
|
1190
|
-
|
|
1225
|
+
it(k);
|
|
1191
1226
|
};
|
|
1192
|
-
return clearInterval(
|
|
1193
|
-
}, [
|
|
1227
|
+
return clearInterval(p.current ?? void 0), p.current = setInterval(e, 90), () => clearInterval(p.current ?? void 0);
|
|
1228
|
+
}, [O, M, de.current]), W(() => {
|
|
1194
1229
|
let e;
|
|
1195
|
-
return
|
|
1196
|
-
|
|
1197
|
-
}, 1e3)) :
|
|
1198
|
-
}, [
|
|
1199
|
-
const
|
|
1200
|
-
const
|
|
1201
|
-
let
|
|
1202
|
-
const
|
|
1203
|
-
|
|
1204
|
-
},
|
|
1205
|
-
|
|
1230
|
+
return kt ? (xt(0), e = window.setInterval(() => {
|
|
1231
|
+
xt((r) => r + 1);
|
|
1232
|
+
}, 1e3)) : xt(0), () => clearInterval(e);
|
|
1233
|
+
}, [kt]);
|
|
1234
|
+
const gn = (e) => {
|
|
1235
|
+
const r = e.numberOfChannels, n = e.length * r * 2 + 44, i = new ArrayBuffer(n), t = new DataView(i);
|
|
1236
|
+
let s = 0;
|
|
1237
|
+
const f = (T) => {
|
|
1238
|
+
t.setUint16(s, T, !0), s += 2;
|
|
1239
|
+
}, w = (T) => {
|
|
1240
|
+
t.setUint32(s, T, !0), s += 4;
|
|
1206
1241
|
};
|
|
1207
|
-
|
|
1242
|
+
w(1179011410), w(n - 8), w(1163280727), w(544501094), w(16), f(1), f(r), w(e.sampleRate), w(e.sampleRate * 2 * r), f(r * 2), f(16), w(1635017060), w(n - s - 4);
|
|
1208
1243
|
const k = [];
|
|
1209
|
-
for (let
|
|
1210
|
-
let
|
|
1211
|
-
for (;
|
|
1212
|
-
for (let
|
|
1213
|
-
let
|
|
1214
|
-
|
|
1244
|
+
for (let T = 0; T < r; T++) k.push(e.getChannelData(T));
|
|
1245
|
+
let E = 0;
|
|
1246
|
+
for (; s < n; ) {
|
|
1247
|
+
for (let T = 0; T < r; T++) {
|
|
1248
|
+
let C = Math.max(-1, Math.min(1, k[T][E]));
|
|
1249
|
+
C = C < 0 ? C * 32768 : C * 32767, t.setInt16(s, C, !0), s += 2;
|
|
1215
1250
|
}
|
|
1216
|
-
|
|
1251
|
+
E++;
|
|
1217
1252
|
}
|
|
1218
|
-
return new Blob([
|
|
1219
|
-
},
|
|
1220
|
-
if (!
|
|
1221
|
-
if (
|
|
1222
|
-
|
|
1253
|
+
return new Blob([i], { type: "audio/wav" });
|
|
1254
|
+
}, At = async (e, r, n = !1) => {
|
|
1255
|
+
if (!ke.current) {
|
|
1256
|
+
if (V.current) {
|
|
1257
|
+
Ee.current.push({
|
|
1223
1258
|
audio: e,
|
|
1224
|
-
visemes:
|
|
1225
|
-
isNewSegment:
|
|
1259
|
+
visemes: r,
|
|
1260
|
+
isNewSegment: n
|
|
1226
1261
|
});
|
|
1227
1262
|
return;
|
|
1228
1263
|
}
|
|
1229
|
-
|
|
1264
|
+
V.current = !0;
|
|
1230
1265
|
try {
|
|
1231
|
-
const
|
|
1232
|
-
|
|
1233
|
-
const
|
|
1234
|
-
for (let
|
|
1235
|
-
|
|
1236
|
-
const
|
|
1237
|
-
|
|
1238
|
-
const k =
|
|
1239
|
-
let
|
|
1240
|
-
const
|
|
1241
|
-
|
|
1242
|
-
const
|
|
1243
|
-
|
|
1244
|
-
let Z =
|
|
1245
|
-
if ((!Z || Z.context !==
|
|
1246
|
-
|
|
1266
|
+
const i = window.AudioContext || window.webkitAudioContext, t = we.current ?? new i();
|
|
1267
|
+
t.state === "suspended" && await t.resume(), we.current = t;
|
|
1268
|
+
const s = window.atob(e), f = new Uint8Array(s.length);
|
|
1269
|
+
for (let $ = 0; $ < s.length; $++)
|
|
1270
|
+
f[$] = s.charCodeAt($);
|
|
1271
|
+
const w = await t.decodeAudioData(f.buffer.slice(0));
|
|
1272
|
+
de.current += w.duration;
|
|
1273
|
+
const k = t.currentTime;
|
|
1274
|
+
let E = $e.current;
|
|
1275
|
+
const T = !Ve.current;
|
|
1276
|
+
E < k && (E = k + 0.1), $e.current = E + w.duration;
|
|
1277
|
+
const C = t.createBufferSource();
|
|
1278
|
+
C.buffer = w;
|
|
1279
|
+
let Z = Vt;
|
|
1280
|
+
if ((!Z || Z.context !== t) && (Z = t.createAnalyser(), Z.fftSize = 64, Z.connect(t.destination), hn(Z)), C.connect(Z), Ie.current.push(C), ke.current) {
|
|
1281
|
+
Ie.current = Ie.current.filter(($) => $ !== C);
|
|
1247
1282
|
return;
|
|
1248
1283
|
}
|
|
1249
|
-
if (
|
|
1250
|
-
|
|
1251
|
-
`[AUDIO] setIsSpeaking(true) - First chunk starting at ${
|
|
1284
|
+
if (T) {
|
|
1285
|
+
Ve.current = !0, z(!0), N(
|
|
1286
|
+
`[AUDIO] setIsSpeaking(true) - First chunk starting at ${E.toFixed(
|
|
1252
1287
|
3
|
|
1253
1288
|
)}`
|
|
1254
|
-
),
|
|
1255
|
-
const
|
|
1256
|
-
|
|
1257
|
-
`[AUDIO] Response started. Initial startTime: ${
|
|
1289
|
+
), De.current = E;
|
|
1290
|
+
const $ = (E - k) * 1e3;
|
|
1291
|
+
Ze.current = performance.now() + $, N(
|
|
1292
|
+
`[AUDIO] Response started. Initial startTime: ${E.toFixed(
|
|
1258
1293
|
3
|
|
1259
1294
|
)}, CT: ${k.toFixed(3)}`
|
|
1260
1295
|
);
|
|
1261
1296
|
}
|
|
1262
|
-
|
|
1263
|
-
const
|
|
1264
|
-
|
|
1265
|
-
`[AUDIO] New segment detected at +${
|
|
1297
|
+
C.start(E);
|
|
1298
|
+
const ie = (E - De.current) * 1e3;
|
|
1299
|
+
n && (Oe.current = ie, N(
|
|
1300
|
+
`[AUDIO] New segment detected at +${ie.toFixed(
|
|
1266
1301
|
0
|
|
1267
1302
|
)}ms. Resetting segment offset.`
|
|
1268
|
-
)),
|
|
1269
|
-
const
|
|
1270
|
-
if (
|
|
1271
|
-
const
|
|
1272
|
-
|
|
1273
|
-
`[AUDIO] Viseme "${
|
|
1303
|
+
)), r.forEach(($, pe) => {
|
|
1304
|
+
const B = $.symbol ?? "";
|
|
1305
|
+
if (B) {
|
|
1306
|
+
const ge = zn(B), Le = Math.round($.start * 1e3), Qe = Math.round(($.duration ?? 0) * 1e3), qt = Oe.current + Le;
|
|
1307
|
+
pe < 3 && N(
|
|
1308
|
+
`[AUDIO] Viseme "${B}": segment_relative=${Le}ms, segment_offset=${Oe.current.toFixed(
|
|
1274
1309
|
0
|
|
1275
|
-
)}ms => vtime=${
|
|
1276
|
-
),
|
|
1277
|
-
|
|
1278
|
-
viseme:
|
|
1279
|
-
weight:
|
|
1280
|
-
vtime:
|
|
1281
|
-
vduration:
|
|
1310
|
+
)}ms => vtime=${qt}ms`
|
|
1311
|
+
), ge.forEach((zt) => {
|
|
1312
|
+
Me.current.push({
|
|
1313
|
+
viseme: zt.v,
|
|
1314
|
+
weight: zt.w,
|
|
1315
|
+
vtime: qt,
|
|
1316
|
+
vduration: Qe
|
|
1282
1317
|
});
|
|
1283
1318
|
});
|
|
1284
1319
|
}
|
|
1285
|
-
}),
|
|
1320
|
+
}), b("Speaking...");
|
|
1286
1321
|
} finally {
|
|
1287
|
-
if (
|
|
1288
|
-
const
|
|
1289
|
-
|
|
1322
|
+
if (V.current = !1, Ee.current.length > 0) {
|
|
1323
|
+
const i = Ee.current.shift();
|
|
1324
|
+
i && At(i.audio, i.visemes, i.isNewSegment);
|
|
1290
1325
|
}
|
|
1291
1326
|
}
|
|
1292
1327
|
}
|
|
1293
|
-
},
|
|
1328
|
+
}, bn = async (e) => {
|
|
1294
1329
|
try {
|
|
1295
|
-
|
|
1296
|
-
const
|
|
1297
|
-
|
|
1298
|
-
const
|
|
1299
|
-
|
|
1300
|
-
const
|
|
1301
|
-
|
|
1302
|
-
)}`, k = await fetch(
|
|
1330
|
+
m(!0), K(!1), ue.current = "", _e(""), b("Processing Voice...");
|
|
1331
|
+
const r = await e.arrayBuffer(), i = await new (window.AudioContext || window.webkitAudioContext)().decodeAudioData(r), t = gn(i), s = new FileReader();
|
|
1332
|
+
s.readAsDataURL(t), s.onloadend = async () => {
|
|
1333
|
+
const f = s.result.split(",")[1];
|
|
1334
|
+
st(), se(""), x.current = "", ce.current = !1;
|
|
1335
|
+
const w = `${nt}/stt?token=${encodeURIComponent(
|
|
1336
|
+
We
|
|
1337
|
+
)}`, k = await fetch(w, {
|
|
1303
1338
|
method: "POST",
|
|
1304
1339
|
headers: { "Content-Type": "application/json" },
|
|
1305
1340
|
body: JSON.stringify({
|
|
1306
|
-
audio_base64:
|
|
1307
|
-
audio_format: "wav"
|
|
1341
|
+
audio_base64: f,
|
|
1342
|
+
audio_format: "wav",
|
|
1343
|
+
agentId: y
|
|
1308
1344
|
})
|
|
1309
1345
|
});
|
|
1310
1346
|
if (k.status === 429) {
|
|
1311
1347
|
try {
|
|
1312
|
-
const
|
|
1313
|
-
N("[STT] 429 agent at capacity:",
|
|
1348
|
+
const pe = await k.text(), B = JSON.parse(pe);
|
|
1349
|
+
N("[STT] 429 agent at capacity:", B?.detail);
|
|
1314
1350
|
} catch {
|
|
1315
1351
|
}
|
|
1316
|
-
|
|
1352
|
+
se(""), b("Busy"), m(!1);
|
|
1317
1353
|
return;
|
|
1318
1354
|
}
|
|
1319
1355
|
if (!k.ok) {
|
|
1320
|
-
const
|
|
1321
|
-
let
|
|
1356
|
+
const pe = await k.text();
|
|
1357
|
+
let B = "STT Failed";
|
|
1322
1358
|
try {
|
|
1323
|
-
|
|
1359
|
+
B = JSON.parse(pe).error || B;
|
|
1324
1360
|
} catch {
|
|
1325
|
-
|
|
1361
|
+
pe && (B = pe.slice(0, 200));
|
|
1326
1362
|
}
|
|
1327
|
-
throw new Error(
|
|
1363
|
+
throw new Error(B);
|
|
1328
1364
|
}
|
|
1329
|
-
const
|
|
1330
|
-
if (N("this is body" +
|
|
1331
|
-
|
|
1365
|
+
const E = k.body;
|
|
1366
|
+
if (N("this is body" + E), !E) {
|
|
1367
|
+
b("STT Failed"), m(!1);
|
|
1332
1368
|
return;
|
|
1333
1369
|
}
|
|
1334
|
-
const
|
|
1335
|
-
|
|
1336
|
-
const
|
|
1337
|
-
let Z = "",
|
|
1338
|
-
const
|
|
1339
|
-
switch (
|
|
1370
|
+
const T = E.getReader();
|
|
1371
|
+
ke.current = !1;
|
|
1372
|
+
const C = new TextDecoder();
|
|
1373
|
+
let Z = "", ie = !1;
|
|
1374
|
+
const $ = async (pe, B) => {
|
|
1375
|
+
switch (pe) {
|
|
1340
1376
|
case "transcript":
|
|
1341
|
-
|
|
1377
|
+
B.transcript != null && se(String(B.transcript));
|
|
1342
1378
|
break;
|
|
1343
1379
|
case "text": {
|
|
1344
|
-
const
|
|
1345
|
-
|
|
1380
|
+
const ge = B.delta ?? B.text ?? "";
|
|
1381
|
+
ge && Ft(ge);
|
|
1346
1382
|
break;
|
|
1347
1383
|
}
|
|
1348
1384
|
case "audio": {
|
|
1349
|
-
const
|
|
1350
|
-
|
|
1385
|
+
const ge = B.chunk, Le = B.visemes ?? [], Qe = !!B.is_new_segment;
|
|
1386
|
+
ge && await At(ge, Le, Qe);
|
|
1351
1387
|
break;
|
|
1352
1388
|
}
|
|
1353
1389
|
case "done": {
|
|
1354
|
-
|
|
1390
|
+
ie = !0, b("Ready"), m(!1);
|
|
1355
1391
|
break;
|
|
1356
1392
|
}
|
|
1357
1393
|
case "error": {
|
|
1358
|
-
|
|
1394
|
+
ie = !0, b("STT Failed"), m(!1);
|
|
1359
1395
|
break;
|
|
1360
1396
|
}
|
|
1361
1397
|
default:
|
|
@@ -1363,226 +1399,227 @@ const Jn = ({
|
|
|
1363
1399
|
}
|
|
1364
1400
|
};
|
|
1365
1401
|
for (; ; ) {
|
|
1366
|
-
const { done:
|
|
1367
|
-
|
|
1368
|
-
const
|
|
1402
|
+
const { done: pe, value: B } = await T.read();
|
|
1403
|
+
B && (Z += C.decode(B, { stream: !0 }));
|
|
1404
|
+
const ge = Z.split(`
|
|
1369
1405
|
|
|
1370
1406
|
`);
|
|
1371
|
-
Z =
|
|
1372
|
-
for (const
|
|
1373
|
-
const
|
|
1374
|
-
|
|
1407
|
+
Z = ge.pop() ?? "";
|
|
1408
|
+
for (const Le of ge) {
|
|
1409
|
+
const Qe = et(Le);
|
|
1410
|
+
Qe && await $(Qe.event, Qe.data);
|
|
1375
1411
|
}
|
|
1376
|
-
if (
|
|
1412
|
+
if (pe) {
|
|
1377
1413
|
if (Z.trim()) {
|
|
1378
|
-
const
|
|
1379
|
-
|
|
1414
|
+
const Le = et(Z.trim());
|
|
1415
|
+
Le && await $(Le.event, Le.data);
|
|
1380
1416
|
}
|
|
1381
|
-
|
|
1417
|
+
ie || (b("Ready"), m(!1));
|
|
1382
1418
|
break;
|
|
1383
1419
|
}
|
|
1384
1420
|
}
|
|
1385
1421
|
};
|
|
1386
|
-
} catch (
|
|
1387
|
-
console.error("Audio Submission Error:",
|
|
1422
|
+
} catch (r) {
|
|
1423
|
+
console.error("Audio Submission Error:", r), b("STT Failed"), m(!1);
|
|
1388
1424
|
}
|
|
1389
|
-
},
|
|
1390
|
-
e && e.preventDefault(),
|
|
1391
|
-
},
|
|
1392
|
-
const
|
|
1393
|
-
let
|
|
1394
|
-
for (const
|
|
1395
|
-
|
|
1396
|
-
if (!
|
|
1397
|
-
let
|
|
1398
|
-
if (
|
|
1425
|
+
}, _n = async (e) => {
|
|
1426
|
+
e && e.preventDefault(), K(!1), ue.current = "", _e(""), !(!q || ae) && await wn(q);
|
|
1427
|
+
}, et = (e) => {
|
|
1428
|
+
const r = e.split(/\r?\n/);
|
|
1429
|
+
let n = "", i = "";
|
|
1430
|
+
for (const s of r)
|
|
1431
|
+
s.startsWith("event:") ? n = s.slice(6).trim() : s.startsWith("data:") && (i = s.slice(5).trim());
|
|
1432
|
+
if (!n) return null;
|
|
1433
|
+
let t = {};
|
|
1434
|
+
if (i)
|
|
1399
1435
|
try {
|
|
1400
|
-
|
|
1436
|
+
t = JSON.parse(i);
|
|
1401
1437
|
} catch {
|
|
1402
|
-
|
|
1438
|
+
t = { raw: i };
|
|
1403
1439
|
}
|
|
1404
|
-
return { event:
|
|
1405
|
-
},
|
|
1440
|
+
return { event: n, data: t };
|
|
1441
|
+
}, gt = (e, r) => {
|
|
1406
1442
|
switch (e) {
|
|
1407
1443
|
case "connected":
|
|
1408
|
-
|
|
1444
|
+
x.current = "", ce.current = !1;
|
|
1409
1445
|
break;
|
|
1410
1446
|
case "text": {
|
|
1411
|
-
const
|
|
1412
|
-
|
|
1447
|
+
const n = r.delta ?? "";
|
|
1448
|
+
n && Ft(n);
|
|
1413
1449
|
break;
|
|
1414
1450
|
}
|
|
1415
1451
|
case "audio": {
|
|
1416
|
-
const
|
|
1417
|
-
|
|
1452
|
+
const n = r.chunk, i = r.visemes ?? [];
|
|
1453
|
+
n && At(n, i);
|
|
1418
1454
|
break;
|
|
1419
1455
|
}
|
|
1420
1456
|
case "done": {
|
|
1421
|
-
const
|
|
1422
|
-
...
|
|
1423
|
-
{ role: "user", content:
|
|
1424
|
-
{ role: "assistant", content:
|
|
1457
|
+
const n = Pt(), i = ue.current.trim(), t = [
|
|
1458
|
+
...n,
|
|
1459
|
+
{ role: "user", content: q || "..." },
|
|
1460
|
+
{ role: "assistant", content: i }
|
|
1425
1461
|
];
|
|
1426
|
-
|
|
1462
|
+
ln(t), ct.current = [...Me.current], b("Ready"), m(!1), se("");
|
|
1427
1463
|
break;
|
|
1428
1464
|
}
|
|
1429
1465
|
case "error": {
|
|
1430
|
-
const
|
|
1431
|
-
|
|
1466
|
+
const n = r.message ?? "Unknown error";
|
|
1467
|
+
ue.current = n, _e(n), b("Agent Failed"), m(!1);
|
|
1432
1468
|
break;
|
|
1433
1469
|
}
|
|
1434
1470
|
}
|
|
1435
|
-
},
|
|
1436
|
-
|
|
1471
|
+
}, $t = async (e, r) => {
|
|
1472
|
+
m(!0), b("Thinking..."), ue.current = "", x.current = "", ce.current = !1, st(), de.current = 0, it(0);
|
|
1437
1473
|
try {
|
|
1438
|
-
const
|
|
1474
|
+
const n = await fetch(e, {
|
|
1439
1475
|
method: "POST",
|
|
1440
1476
|
headers: { "Content-Type": "application/json" },
|
|
1441
|
-
body: JSON.stringify(
|
|
1477
|
+
body: JSON.stringify(r)
|
|
1442
1478
|
});
|
|
1443
|
-
if (
|
|
1444
|
-
|
|
1479
|
+
if (n.status === 429) {
|
|
1480
|
+
b("Busy"), m(!1);
|
|
1445
1481
|
return;
|
|
1446
1482
|
}
|
|
1447
|
-
if (!
|
|
1448
|
-
const
|
|
1449
|
-
if (!
|
|
1450
|
-
|
|
1483
|
+
if (!n.ok) throw new Error("Request failed");
|
|
1484
|
+
const i = n.body;
|
|
1485
|
+
if (!i) {
|
|
1486
|
+
b("Failed"), m(!1);
|
|
1451
1487
|
return;
|
|
1452
1488
|
}
|
|
1453
|
-
const
|
|
1454
|
-
|
|
1455
|
-
const
|
|
1456
|
-
let
|
|
1489
|
+
const t = i.getReader();
|
|
1490
|
+
ke.current = !1;
|
|
1491
|
+
const s = new TextDecoder();
|
|
1492
|
+
let f = "";
|
|
1457
1493
|
for (; ; ) {
|
|
1458
|
-
const { done:
|
|
1459
|
-
k && (
|
|
1460
|
-
const
|
|
1494
|
+
const { done: w, value: k } = await t.read();
|
|
1495
|
+
k && (f += s.decode(k, { stream: !0 }));
|
|
1496
|
+
const E = f.split(`
|
|
1461
1497
|
|
|
1462
1498
|
`);
|
|
1463
|
-
|
|
1464
|
-
for (const
|
|
1465
|
-
const
|
|
1466
|
-
|
|
1499
|
+
f = E.pop() ?? "";
|
|
1500
|
+
for (const T of E) {
|
|
1501
|
+
const C = et(T);
|
|
1502
|
+
C && gt(C.event, C.data);
|
|
1467
1503
|
}
|
|
1468
|
-
if (
|
|
1469
|
-
if (
|
|
1470
|
-
const
|
|
1471
|
-
|
|
1504
|
+
if (w) {
|
|
1505
|
+
if (f.trim()) {
|
|
1506
|
+
const T = et(f.trim());
|
|
1507
|
+
T && gt(T.event, T.data);
|
|
1472
1508
|
}
|
|
1473
|
-
|
|
1509
|
+
b("Ready"), m(!1);
|
|
1474
1510
|
break;
|
|
1475
1511
|
}
|
|
1476
1512
|
}
|
|
1477
|
-
} catch (
|
|
1478
|
-
console.error("Streaming Error:",
|
|
1513
|
+
} catch (n) {
|
|
1514
|
+
console.error("Streaming Error:", n), b("Failed"), m(!1);
|
|
1479
1515
|
}
|
|
1480
|
-
},
|
|
1481
|
-
const
|
|
1482
|
-
await
|
|
1483
|
-
}, []),
|
|
1484
|
-
const
|
|
1485
|
-
await
|
|
1486
|
-
}, []),
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
}, [
|
|
1490
|
-
const
|
|
1491
|
-
|
|
1492
|
-
const
|
|
1493
|
-
|
|
1516
|
+
}, Ht = tt(async (e, r, n) => {
|
|
1517
|
+
const i = `${nt}/avatar_tts`;
|
|
1518
|
+
await $t(i, { text: e, userQuery: r, llmPrompt: n });
|
|
1519
|
+
}, []), jt = tt(async (e, r, n, i) => {
|
|
1520
|
+
const t = `${nt}/avatar_ttsWithKnowledge`;
|
|
1521
|
+
await $t(t, { userQuery: e, llmPrompt: r, knowledge: n, history: i });
|
|
1522
|
+
}, []), Gt = c(!1);
|
|
1523
|
+
W(() => {
|
|
1524
|
+
L && !Gt.current && (L({ avatarSpeak: Ht, avatarRespond: jt }), Gt.current = !0);
|
|
1525
|
+
}, [L, Ht, jt]);
|
|
1526
|
+
const wn = async (e) => {
|
|
1527
|
+
m(!0), b("Thinking..."), ue.current = "", x.current = "", ce.current = !1, st(), de.current = 0, it(0);
|
|
1528
|
+
const r = `${nt}/agent/chat?token=${encodeURIComponent(
|
|
1529
|
+
We
|
|
1494
1530
|
)}`;
|
|
1495
1531
|
try {
|
|
1496
|
-
const
|
|
1497
|
-
let
|
|
1498
|
-
|
|
1532
|
+
const n = Pt();
|
|
1533
|
+
let i = sessionStorage.getItem("STREAMOJI_LEADS_SESSION_LEAD_ID");
|
|
1534
|
+
i || (In(
|
|
1499
1535
|
"[CHAT] Session UID missing at send time! Generating emergency backup."
|
|
1500
|
-
),
|
|
1501
|
-
const
|
|
1502
|
-
history:
|
|
1536
|
+
), i = "emergency-" + Math.random().toString(36).substring(7), sessionStorage.setItem("STREAMOJI_LEADS_SESSION_LEAD_ID", i));
|
|
1537
|
+
const t = {
|
|
1538
|
+
history: n,
|
|
1503
1539
|
question: e,
|
|
1504
|
-
lead_id:
|
|
1540
|
+
lead_id: i,
|
|
1541
|
+
agentId: y
|
|
1505
1542
|
};
|
|
1506
|
-
N("[CHAT] Sending payload:",
|
|
1507
|
-
const
|
|
1543
|
+
N("[CHAT] Sending payload:", t);
|
|
1544
|
+
const s = await fetch(r, {
|
|
1508
1545
|
method: "POST",
|
|
1509
1546
|
headers: {
|
|
1510
1547
|
"Content-Type": "application/json"
|
|
1511
1548
|
},
|
|
1512
|
-
body: JSON.stringify(
|
|
1549
|
+
body: JSON.stringify(t),
|
|
1513
1550
|
cache: "default"
|
|
1514
1551
|
});
|
|
1515
|
-
if (
|
|
1552
|
+
if (s.status === 429) {
|
|
1516
1553
|
try {
|
|
1517
|
-
const
|
|
1518
|
-
N("[CHAT] 429 agent at capacity:",
|
|
1554
|
+
const T = await s.json();
|
|
1555
|
+
N("[CHAT] 429 agent at capacity:", T?.detail);
|
|
1519
1556
|
} catch {
|
|
1520
1557
|
}
|
|
1521
|
-
|
|
1558
|
+
se(""), b("Busy"), m(!1);
|
|
1522
1559
|
return;
|
|
1523
1560
|
}
|
|
1524
|
-
if (!
|
|
1561
|
+
if (!s.ok)
|
|
1525
1562
|
throw new Error("Agent request failed");
|
|
1526
|
-
const
|
|
1527
|
-
if (!
|
|
1528
|
-
|
|
1563
|
+
const f = s.body;
|
|
1564
|
+
if (!f) {
|
|
1565
|
+
b("Agent Failed"), m(!1);
|
|
1529
1566
|
return;
|
|
1530
1567
|
}
|
|
1531
|
-
const
|
|
1532
|
-
|
|
1568
|
+
const w = f.getReader();
|
|
1569
|
+
ke.current = !1;
|
|
1533
1570
|
const k = new TextDecoder();
|
|
1534
|
-
let
|
|
1571
|
+
let E = "";
|
|
1535
1572
|
for (; ; ) {
|
|
1536
|
-
const { done:
|
|
1573
|
+
const { done: T, value: C } = await w.read();
|
|
1537
1574
|
N(
|
|
1538
|
-
`[SSE] Chunk received. done=${
|
|
1539
|
-
),
|
|
1540
|
-
const Z =
|
|
1575
|
+
`[SSE] Chunk received. done=${T}, length=${C?.length || 0}`
|
|
1576
|
+
), C && (E += k.decode(C, { stream: !0 }));
|
|
1577
|
+
const Z = E.split(`
|
|
1541
1578
|
|
|
1542
1579
|
`);
|
|
1543
|
-
|
|
1544
|
-
for (const
|
|
1545
|
-
N(`[SSE] Processing block: ${
|
|
1546
|
-
const
|
|
1547
|
-
|
|
1580
|
+
E = Z.pop() ?? "";
|
|
1581
|
+
for (const ie of Z) {
|
|
1582
|
+
N(`[SSE] Processing block: ${ie.slice(0, 50)}...`);
|
|
1583
|
+
const $ = et(ie);
|
|
1584
|
+
$ && (N(`[SSE] Event: ${$.event}`), gt($.event, $.data));
|
|
1548
1585
|
}
|
|
1549
|
-
if (
|
|
1550
|
-
if (N("[SSE] Stream finished"),
|
|
1551
|
-
const
|
|
1552
|
-
|
|
1586
|
+
if (T) {
|
|
1587
|
+
if (N("[SSE] Stream finished"), E.trim()) {
|
|
1588
|
+
const ie = et(E.trim());
|
|
1589
|
+
ie && gt(ie.event, ie.data);
|
|
1553
1590
|
}
|
|
1554
|
-
|
|
1591
|
+
b("Ready"), m(!1), se("");
|
|
1555
1592
|
break;
|
|
1556
1593
|
}
|
|
1557
1594
|
}
|
|
1558
|
-
} catch (
|
|
1559
|
-
console.error("Chat Error:",
|
|
1595
|
+
} catch (n) {
|
|
1596
|
+
console.error("Chat Error:", n), b("Agent Failed"), m(!1);
|
|
1560
1597
|
}
|
|
1561
|
-
},
|
|
1598
|
+
}, yn = M.trim(), Jt = on(yn), Et = Jt && O ? Jt.slice(
|
|
1562
1599
|
0,
|
|
1563
|
-
|
|
1600
|
+
ot != null && ot > 0 ? ot : 0
|
|
1564
1601
|
) : "";
|
|
1565
|
-
|
|
1566
|
-
const e =
|
|
1567
|
-
e !== "exiting" && (
|
|
1568
|
-
}, [
|
|
1569
|
-
const
|
|
1570
|
-
const e =
|
|
1571
|
-
e === "entering" ?
|
|
1602
|
+
W(() => {
|
|
1603
|
+
const e = Fe.current;
|
|
1604
|
+
e !== "exiting" && (Et ? (Lt(Et), e === "hidden" && ze("entering")) : (e === "visible" || e === "entering") && ze("exiting"));
|
|
1605
|
+
}, [Et, oe]);
|
|
1606
|
+
const Sn = tt(() => {
|
|
1607
|
+
const e = Fe.current;
|
|
1608
|
+
e === "entering" ? ze("visible") : e === "exiting" && ze("hidden");
|
|
1572
1609
|
}, []);
|
|
1573
|
-
|
|
1574
|
-
const e =
|
|
1610
|
+
An(() => {
|
|
1611
|
+
const e = dt.current;
|
|
1575
1612
|
e && (e.scrollTop = e.scrollHeight);
|
|
1576
|
-
}, [
|
|
1577
|
-
const
|
|
1578
|
-
return /* @__PURE__ */
|
|
1579
|
-
/* @__PURE__ */
|
|
1580
|
-
|
|
1613
|
+
}, [ft]);
|
|
1614
|
+
const Ln = G === "female" ? Vn : Wn;
|
|
1615
|
+
return rt ? /* @__PURE__ */ be("div", { className: "avatar-widget-container", children: [
|
|
1616
|
+
/* @__PURE__ */ be("div", { className: "avatar-input-area", children: [
|
|
1617
|
+
Ce !== "hidden" ? /* @__PURE__ */ l(
|
|
1581
1618
|
"div",
|
|
1582
1619
|
{
|
|
1583
|
-
className: `avatar-thinking-tab${
|
|
1584
|
-
onAnimationEnd:
|
|
1585
|
-
children:
|
|
1620
|
+
className: `avatar-thinking-tab${Ce === "exiting" ? " avatar-thinking-tab--exiting" : Ce === "entering" ? " avatar-thinking-tab--entering" : ""}`,
|
|
1621
|
+
onAnimationEnd: sn,
|
|
1622
|
+
children: R === rn ? /* @__PURE__ */ l(
|
|
1586
1623
|
"a",
|
|
1587
1624
|
{
|
|
1588
1625
|
href: "https://leads.streamoji.com",
|
|
@@ -1590,10 +1627,10 @@ const Jn = ({
|
|
|
1590
1627
|
rel: "noopener noreferrer",
|
|
1591
1628
|
children: "Made by Streamoji Leads"
|
|
1592
1629
|
}
|
|
1593
|
-
) :
|
|
1630
|
+
) : R
|
|
1594
1631
|
}
|
|
1595
1632
|
) : null,
|
|
1596
|
-
/* @__PURE__ */
|
|
1633
|
+
/* @__PURE__ */ l("div", { className: "avatar-input-container", children: /* @__PURE__ */ l(
|
|
1597
1634
|
"div",
|
|
1598
1635
|
{
|
|
1599
1636
|
style: {
|
|
@@ -1602,15 +1639,15 @@ const Jn = ({
|
|
|
1602
1639
|
width: "100%",
|
|
1603
1640
|
height: "100%"
|
|
1604
1641
|
},
|
|
1605
|
-
children:
|
|
1606
|
-
/* @__PURE__ */
|
|
1642
|
+
children: kt ? /* @__PURE__ */ be("div", { className: "avatar-input-recording", children: [
|
|
1643
|
+
/* @__PURE__ */ l(
|
|
1607
1644
|
"button",
|
|
1608
1645
|
{
|
|
1609
1646
|
type: "button",
|
|
1610
1647
|
className: "avatar-recording-cancel",
|
|
1611
|
-
onClick:
|
|
1648
|
+
onClick: pn,
|
|
1612
1649
|
title: "Cancel",
|
|
1613
|
-
children: /* @__PURE__ */
|
|
1650
|
+
children: /* @__PURE__ */ be(
|
|
1614
1651
|
"svg",
|
|
1615
1652
|
{
|
|
1616
1653
|
width: "18",
|
|
@@ -1623,14 +1660,14 @@ const Jn = ({
|
|
|
1623
1660
|
strokeLinejoin: "round",
|
|
1624
1661
|
style: { display: "block" },
|
|
1625
1662
|
children: [
|
|
1626
|
-
/* @__PURE__ */
|
|
1627
|
-
/* @__PURE__ */
|
|
1663
|
+
/* @__PURE__ */ l("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1664
|
+
/* @__PURE__ */ l("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1628
1665
|
]
|
|
1629
1666
|
}
|
|
1630
1667
|
)
|
|
1631
1668
|
}
|
|
1632
1669
|
),
|
|
1633
|
-
/* @__PURE__ */
|
|
1670
|
+
/* @__PURE__ */ be(
|
|
1634
1671
|
"div",
|
|
1635
1672
|
{
|
|
1636
1673
|
style: {
|
|
@@ -1642,8 +1679,8 @@ const Jn = ({
|
|
|
1642
1679
|
minWidth: 0
|
|
1643
1680
|
},
|
|
1644
1681
|
children: [
|
|
1645
|
-
/* @__PURE__ */
|
|
1646
|
-
/* @__PURE__ */
|
|
1682
|
+
/* @__PURE__ */ l("div", { style: { flex: 1, height: "100%" }, children: /* @__PURE__ */ l(Yt, { analyser: dn }) }),
|
|
1683
|
+
/* @__PURE__ */ be(
|
|
1647
1684
|
"span",
|
|
1648
1685
|
{
|
|
1649
1686
|
style: {
|
|
@@ -1656,23 +1693,23 @@ const Jn = ({
|
|
|
1656
1693
|
fontVariantNumeric: "tabular-nums"
|
|
1657
1694
|
},
|
|
1658
1695
|
children: [
|
|
1659
|
-
Math.floor(
|
|
1696
|
+
Math.floor(Bt / 60),
|
|
1660
1697
|
":",
|
|
1661
|
-
String(
|
|
1698
|
+
String(Bt % 60).padStart(2, "0")
|
|
1662
1699
|
]
|
|
1663
1700
|
}
|
|
1664
1701
|
)
|
|
1665
1702
|
]
|
|
1666
1703
|
}
|
|
1667
1704
|
),
|
|
1668
|
-
/* @__PURE__ */
|
|
1705
|
+
/* @__PURE__ */ l(
|
|
1669
1706
|
"button",
|
|
1670
1707
|
{
|
|
1671
1708
|
type: "button",
|
|
1672
1709
|
className: "avatar-recording-confirm",
|
|
1673
|
-
onClick:
|
|
1710
|
+
onClick: mn,
|
|
1674
1711
|
title: "Send",
|
|
1675
|
-
children: /* @__PURE__ */
|
|
1712
|
+
children: /* @__PURE__ */ l(
|
|
1676
1713
|
"svg",
|
|
1677
1714
|
{
|
|
1678
1715
|
width: "18",
|
|
@@ -1684,13 +1721,13 @@ const Jn = ({
|
|
|
1684
1721
|
strokeLinecap: "round",
|
|
1685
1722
|
strokeLinejoin: "round",
|
|
1686
1723
|
style: { display: "block" },
|
|
1687
|
-
children: /* @__PURE__ */
|
|
1724
|
+
children: /* @__PURE__ */ l("polyline", { points: "20 6 9 17 4 12" })
|
|
1688
1725
|
}
|
|
1689
1726
|
)
|
|
1690
1727
|
}
|
|
1691
1728
|
)
|
|
1692
|
-
] }) :
|
|
1693
|
-
/* @__PURE__ */
|
|
1729
|
+
] }) : O && !_ ? /* @__PURE__ */ be("div", { className: "avatar-input-speaking", children: [
|
|
1730
|
+
/* @__PURE__ */ l(
|
|
1694
1731
|
"div",
|
|
1695
1732
|
{
|
|
1696
1733
|
style: {
|
|
@@ -1700,20 +1737,20 @@ const Jn = ({
|
|
|
1700
1737
|
alignItems: "center",
|
|
1701
1738
|
paddingRight: "8px"
|
|
1702
1739
|
},
|
|
1703
|
-
children: /* @__PURE__ */
|
|
1740
|
+
children: /* @__PURE__ */ l(Yt, { analyser: Vt })
|
|
1704
1741
|
}
|
|
1705
1742
|
),
|
|
1706
|
-
/* @__PURE__ */
|
|
1743
|
+
/* @__PURE__ */ l(
|
|
1707
1744
|
"button",
|
|
1708
1745
|
{
|
|
1709
1746
|
type: "button",
|
|
1710
1747
|
className: "avatar-speaking-stop",
|
|
1711
|
-
onClick: () =>
|
|
1748
|
+
onClick: () => st(!0),
|
|
1712
1749
|
title: "Stop",
|
|
1713
|
-
children: /* @__PURE__ */
|
|
1750
|
+
children: /* @__PURE__ */ l("span", { className: "avatar-speaking-stop__icon", "aria-hidden": !0 })
|
|
1714
1751
|
}
|
|
1715
1752
|
)
|
|
1716
|
-
] }) :
|
|
1753
|
+
] }) : ae ? /* @__PURE__ */ l(
|
|
1717
1754
|
"div",
|
|
1718
1755
|
{
|
|
1719
1756
|
style: {
|
|
@@ -1723,12 +1760,12 @@ const Jn = ({
|
|
|
1723
1760
|
alignItems: "center",
|
|
1724
1761
|
justifyContent: "center"
|
|
1725
1762
|
},
|
|
1726
|
-
children: /* @__PURE__ */
|
|
1763
|
+
children: /* @__PURE__ */ l("div", { className: "avatar-input-loader" })
|
|
1727
1764
|
}
|
|
1728
|
-
) : /* @__PURE__ */
|
|
1765
|
+
) : /* @__PURE__ */ be(
|
|
1729
1766
|
"form",
|
|
1730
1767
|
{
|
|
1731
|
-
onSubmit:
|
|
1768
|
+
onSubmit: _n,
|
|
1732
1769
|
style: {
|
|
1733
1770
|
flex: 1,
|
|
1734
1771
|
display: "flex",
|
|
@@ -1736,20 +1773,20 @@ const Jn = ({
|
|
|
1736
1773
|
alignItems: "center"
|
|
1737
1774
|
},
|
|
1738
1775
|
children: [
|
|
1739
|
-
/* @__PURE__ */
|
|
1776
|
+
/* @__PURE__ */ l(
|
|
1740
1777
|
"input",
|
|
1741
1778
|
{
|
|
1742
1779
|
id: "avatar-text-input",
|
|
1743
1780
|
type: "text",
|
|
1744
|
-
value:
|
|
1745
|
-
onChange: (e) =>
|
|
1746
|
-
placeholder:
|
|
1747
|
-
disabled:
|
|
1781
|
+
value: q,
|
|
1782
|
+
onChange: (e) => se(e.target.value),
|
|
1783
|
+
placeholder: H === "Busy" ? "Assisting another user" : F || "Ask me anything",
|
|
1784
|
+
disabled: ae || H === "Busy",
|
|
1748
1785
|
autoComplete: "off",
|
|
1749
1786
|
style: { width: "100%", height: "100%" }
|
|
1750
1787
|
}
|
|
1751
1788
|
),
|
|
1752
|
-
|
|
1789
|
+
H === "Busy" ? /* @__PURE__ */ l(
|
|
1753
1790
|
"button",
|
|
1754
1791
|
{
|
|
1755
1792
|
type: "button",
|
|
@@ -1757,7 +1794,7 @@ const Jn = ({
|
|
|
1757
1794
|
disabled: !0,
|
|
1758
1795
|
style: { backgroundColor: "#1e4a5e" },
|
|
1759
1796
|
title: "Agent at capacity",
|
|
1760
|
-
children: /* @__PURE__ */
|
|
1797
|
+
children: /* @__PURE__ */ l(
|
|
1761
1798
|
"svg",
|
|
1762
1799
|
{
|
|
1763
1800
|
width: "24",
|
|
@@ -1766,7 +1803,7 @@ const Jn = ({
|
|
|
1766
1803
|
fill: "none",
|
|
1767
1804
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1768
1805
|
"aria-hidden": "true",
|
|
1769
|
-
children: /* @__PURE__ */
|
|
1806
|
+
children: /* @__PURE__ */ l(
|
|
1770
1807
|
"path",
|
|
1771
1808
|
{
|
|
1772
1809
|
d: "M4 2L20 2L12 10L4 2z M12 14L4 22L20 22L12 14z",
|
|
@@ -1776,15 +1813,15 @@ const Jn = ({
|
|
|
1776
1813
|
}
|
|
1777
1814
|
)
|
|
1778
1815
|
}
|
|
1779
|
-
) :
|
|
1816
|
+
) : q.trim() === "" ? /* @__PURE__ */ l(
|
|
1780
1817
|
"button",
|
|
1781
1818
|
{
|
|
1782
1819
|
type: "button",
|
|
1783
1820
|
className: "mic-button",
|
|
1784
|
-
onClick:
|
|
1785
|
-
disabled:
|
|
1821
|
+
onClick: fn,
|
|
1822
|
+
disabled: ae,
|
|
1786
1823
|
style: { backgroundColor: "#1e4a5e" },
|
|
1787
|
-
children: /* @__PURE__ */
|
|
1824
|
+
children: /* @__PURE__ */ be(
|
|
1788
1825
|
"svg",
|
|
1789
1826
|
{
|
|
1790
1827
|
width: "28",
|
|
@@ -1793,14 +1830,14 @@ const Jn = ({
|
|
|
1793
1830
|
fill: "none",
|
|
1794
1831
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1795
1832
|
children: [
|
|
1796
|
-
/* @__PURE__ */
|
|
1833
|
+
/* @__PURE__ */ l(
|
|
1797
1834
|
"path",
|
|
1798
1835
|
{
|
|
1799
1836
|
d: "M12 14C13.66 14 15 12.66 15 11V5C15 3.34 13.66 2 12 2C10.34 2 9 3.34 9 5V11C9 12.66 10.34 14 12 14Z",
|
|
1800
1837
|
fill: "white"
|
|
1801
1838
|
}
|
|
1802
1839
|
),
|
|
1803
|
-
/* @__PURE__ */
|
|
1840
|
+
/* @__PURE__ */ l(
|
|
1804
1841
|
"path",
|
|
1805
1842
|
{
|
|
1806
1843
|
d: "M17 11C17 13.76 14.76 16 12 16C9.24 16 7 13.76 7 11H5C5 14.53 7.61 17.43 11 17.93V21H13V17.93C16.39 17.43 19 14.53 19 11H17Z",
|
|
@@ -1811,15 +1848,15 @@ const Jn = ({
|
|
|
1811
1848
|
}
|
|
1812
1849
|
)
|
|
1813
1850
|
}
|
|
1814
|
-
) : /* @__PURE__ */
|
|
1851
|
+
) : /* @__PURE__ */ l(
|
|
1815
1852
|
"button",
|
|
1816
1853
|
{
|
|
1817
1854
|
type: "submit",
|
|
1818
1855
|
className: "mic-button",
|
|
1819
|
-
disabled:
|
|
1856
|
+
disabled: ae,
|
|
1820
1857
|
style: { backgroundColor: "#1e4a5e" },
|
|
1821
1858
|
title: "Send",
|
|
1822
|
-
children: /* @__PURE__ */
|
|
1859
|
+
children: /* @__PURE__ */ l(
|
|
1823
1860
|
"svg",
|
|
1824
1861
|
{
|
|
1825
1862
|
width: 24,
|
|
@@ -1827,7 +1864,7 @@ const Jn = ({
|
|
|
1827
1864
|
viewBox: "0 0 24 24",
|
|
1828
1865
|
fill: "none",
|
|
1829
1866
|
"aria-hidden": "true",
|
|
1830
|
-
children: /* @__PURE__ */
|
|
1867
|
+
children: /* @__PURE__ */ l(
|
|
1831
1868
|
"path",
|
|
1832
1869
|
{
|
|
1833
1870
|
d: "M19 12H5M19 12L14 17M19 12L14 7",
|
|
@@ -1847,22 +1884,22 @@ const Jn = ({
|
|
|
1847
1884
|
}
|
|
1848
1885
|
) })
|
|
1849
1886
|
] }),
|
|
1850
|
-
/* @__PURE__ */
|
|
1851
|
-
|
|
1887
|
+
/* @__PURE__ */ l("div", { className: "avatar-wrapper", children: /* @__PURE__ */ be("div", { className: "avatar-scene-wrapper", children: [
|
|
1888
|
+
oe !== "hidden" && /* @__PURE__ */ l(
|
|
1852
1889
|
"div",
|
|
1853
1890
|
{
|
|
1854
|
-
className: `avatar-bubble${
|
|
1855
|
-
onAnimationEnd:
|
|
1856
|
-
children: /* @__PURE__ */
|
|
1891
|
+
className: `avatar-bubble${oe === "entering" ? " avatar-bubble--entering" : oe === "exiting" ? " avatar-bubble--exiting" : ""}`,
|
|
1892
|
+
onAnimationEnd: Sn,
|
|
1893
|
+
children: /* @__PURE__ */ l("div", { ref: dt, className: `avatar-bubble__content${_ ? " avatar-bubble__content--nudge" : ""}`, children: ft })
|
|
1857
1894
|
}
|
|
1858
1895
|
),
|
|
1859
|
-
/* @__PURE__ */
|
|
1896
|
+
/* @__PURE__ */ l(
|
|
1860
1897
|
"div",
|
|
1861
1898
|
{
|
|
1862
1899
|
className: "avatar-canvas-layer",
|
|
1863
|
-
style: { width:
|
|
1864
|
-
children: /* @__PURE__ */
|
|
1865
|
-
|
|
1900
|
+
style: { width: J, height: J },
|
|
1901
|
+
children: /* @__PURE__ */ be(
|
|
1902
|
+
Rn,
|
|
1866
1903
|
{
|
|
1867
1904
|
shadows: !0,
|
|
1868
1905
|
camera: { position: [0.2, 1.4, 3], fov: 42 },
|
|
@@ -1870,30 +1907,30 @@ const Jn = ({
|
|
|
1870
1907
|
dpr: 1.8,
|
|
1871
1908
|
style: { pointerEvents: "none", width: "100%", height: "100%" },
|
|
1872
1909
|
children: [
|
|
1873
|
-
/* @__PURE__ */
|
|
1874
|
-
/* @__PURE__ */
|
|
1875
|
-
/* @__PURE__ */
|
|
1876
|
-
/* @__PURE__ */
|
|
1877
|
-
/* @__PURE__ */
|
|
1878
|
-
|
|
1910
|
+
/* @__PURE__ */ l(Yn, { target: Ln }),
|
|
1911
|
+
/* @__PURE__ */ l("ambientLight", { intensity: 0.7 }),
|
|
1912
|
+
/* @__PURE__ */ l("directionalLight", { position: [0, 2, 2], intensity: 1 }),
|
|
1913
|
+
/* @__PURE__ */ l(vn, { preset: "city" }),
|
|
1914
|
+
/* @__PURE__ */ l(En, { fallback: null, children: Ae !== null && /* @__PURE__ */ l(
|
|
1915
|
+
Kn,
|
|
1879
1916
|
{
|
|
1880
|
-
avatarUrl:
|
|
1881
|
-
isPlayingRef:
|
|
1882
|
-
visemeQueueRef:
|
|
1883
|
-
audioContextRef:
|
|
1884
|
-
responseAudioStartTimeRef:
|
|
1885
|
-
adjustments:
|
|
1886
|
-
mood:
|
|
1887
|
-
expression:
|
|
1888
|
-
agentResponse:
|
|
1889
|
-
isSpeaking:
|
|
1890
|
-
nextStartTimeRef:
|
|
1891
|
-
stopPlayback:
|
|
1892
|
-
setIsSpeaking:
|
|
1893
|
-
expressionUrl:
|
|
1894
|
-
onExpressionFinished:
|
|
1895
|
-
isNudgeResponse:
|
|
1896
|
-
avatarGender:
|
|
1917
|
+
avatarUrl: Ae,
|
|
1918
|
+
isPlayingRef: Ve,
|
|
1919
|
+
visemeQueueRef: Me,
|
|
1920
|
+
audioContextRef: we,
|
|
1921
|
+
responseAudioStartTimeRef: De,
|
|
1922
|
+
adjustments: Bn,
|
|
1923
|
+
mood: h,
|
|
1924
|
+
expression: o,
|
|
1925
|
+
agentResponse: M,
|
|
1926
|
+
isSpeaking: O,
|
|
1927
|
+
nextStartTimeRef: $e,
|
|
1928
|
+
stopPlayback: st,
|
|
1929
|
+
setIsSpeaking: z,
|
|
1930
|
+
expressionUrl: D,
|
|
1931
|
+
onExpressionFinished: un,
|
|
1932
|
+
isNudgeResponse: _,
|
|
1933
|
+
avatarGender: G
|
|
1897
1934
|
}
|
|
1898
1935
|
) })
|
|
1899
1936
|
]
|
|
@@ -1902,23 +1939,21 @@ const Jn = ({
|
|
|
1902
1939
|
}
|
|
1903
1940
|
)
|
|
1904
1941
|
] }) })
|
|
1905
|
-
] });
|
|
1906
|
-
},
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
Jn,
|
|
1942
|
+
] }) : null;
|
|
1943
|
+
}, or = ({
|
|
1944
|
+
agentId: g,
|
|
1945
|
+
onNavigationRequested: y,
|
|
1946
|
+
presetUserDetails: S,
|
|
1947
|
+
onAvatarReady: L
|
|
1948
|
+
}) => /* @__PURE__ */ l(
|
|
1949
|
+
Xn,
|
|
1914
1950
|
{
|
|
1915
|
-
|
|
1916
|
-
onNavigationRequested:
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
onAvatarReady: v
|
|
1951
|
+
agentId: g,
|
|
1952
|
+
onNavigationRequested: y,
|
|
1953
|
+
presetUserDetails: S,
|
|
1954
|
+
onAvatarReady: L
|
|
1920
1955
|
}
|
|
1921
1956
|
);
|
|
1922
1957
|
export {
|
|
1923
|
-
|
|
1958
|
+
or as AvatarWidget
|
|
1924
1959
|
};
|