@streamoji/avatar-widget 0.1.0

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.
@@ -0,0 +1,1053 @@
1
+ import { jsx as f, jsxs as ne } from "react/jsx-runtime";
2
+ import { memo as kt, useMemo as ze, useRef as c, useState as k, useEffect as z, useCallback as Ue, useLayoutEffect as Rt, Suspense as Lt } from "react";
3
+ import { useFrame as At, Canvas as Mt, useThree as Et } from "@react-three/fiber";
4
+ import { useGLTF as Ge, Environment as Tt } from "@react-three/drei";
5
+ import * as Ie from "three";
6
+ import { GLTFLoader as It } from "three/examples/jsm/loaders/GLTFLoader.js";
7
+ const H = (...d) => {
8
+ }, Ct = (...d) => {
9
+ }, ot = ({ analyser: d }) => {
10
+ const y = c(null), v = c(null);
11
+ return z(() => {
12
+ const p = y.current;
13
+ if (!p) return;
14
+ const I = p.getContext("2d", { alpha: !0 });
15
+ if (!I) return;
16
+ let E, R = null;
17
+ d && (d.fftSize = 128, R = new Uint8Array(d.frequencyBinCount));
18
+ const ge = () => {
19
+ E = requestAnimationFrame(ge), (p.width !== p.offsetWidth || p.height !== p.offsetHeight) && (p.width = p.offsetWidth, p.height = p.offsetHeight);
20
+ const re = p.width, C = p.height;
21
+ if (re === 0 || C === 0) return;
22
+ const L = C / 2;
23
+ I.clearRect(0, 0, re, C), I.fillStyle = "#1e293b";
24
+ const Q = 2, A = Q + 2, le = re * 0.95, m = Math.floor(le / A);
25
+ (!v.current || v.current.length !== m) && (v.current = new Float32Array(m).fill(2));
26
+ const be = m * A, ie = (re - be) / 2;
27
+ d && R && d.getByteFrequencyData(R);
28
+ const ue = R ? R.length : 0, N = Math.floor(ue * 0.7) / m, O = new Float32Array(m);
29
+ for (let b = 0; b < m; b++) {
30
+ let P = 0;
31
+ if (R && N > 0) {
32
+ const _ = Math.floor(b * N), Z = Math.floor((b + 1) * N);
33
+ for (let ee = _; ee < Z; ee++) {
34
+ const de = R[ee] || 0;
35
+ de > P && (P = de);
36
+ }
37
+ }
38
+ P < 10 && (P = 0);
39
+ const M = P / 255, g = P > 0 ? Math.max(2, Math.pow(M, 1.4) * C * 0.25) : 2;
40
+ O[b] = g;
41
+ }
42
+ for (let b = 0; b < m; b++) {
43
+ const P = m - 1 - b, M = Math.max(O[b], O[P]), g = v.current[b] + (M - v.current[b]) * 0.3;
44
+ v.current[b] = g;
45
+ const _ = ie + b * A, Z = L - g / 2;
46
+ I.beginPath(), I.roundRect ? I.roundRect(_, Z, Q, g, 4) : I.fillRect(_, Z, Q, g), I.fill();
47
+ }
48
+ };
49
+ return ge(), () => {
50
+ cancelAnimationFrame(E);
51
+ };
52
+ }, [d]), /* @__PURE__ */ f("canvas", { ref: y, style: { width: "100%", height: "100%", display: "block" } });
53
+ }, at = "https://ai.streamoji.com", Ot = "https://pub-48df6f7d60d6440bbd01676ea5d90e55.r2.dev";
54
+ async function Dt(d) {
55
+ const y = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(d));
56
+ return Array.from(new Uint8Array(y)).map((v) => v.toString(16).padStart(2, "0")).join("");
57
+ }
58
+ function Ft(d) {
59
+ const [y, v] = k(null);
60
+ return z(() => {
61
+ if (!d) {
62
+ v(null);
63
+ return;
64
+ }
65
+ let p = !1;
66
+ return Dt(d).then((I) => {
67
+ if (p) return;
68
+ const E = `${Ot}/${I}.glb`;
69
+ fetch(E, { method: "HEAD" }).then((R) => {
70
+ p || v(R.ok ? E : null);
71
+ }).catch(() => {
72
+ p || v(null);
73
+ });
74
+ }), () => {
75
+ p = !0;
76
+ };
77
+ }, [d]), y;
78
+ }
79
+ const Ut = [
80
+ "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/M_Standing_Idle_Variations_001.glb",
81
+ "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/M_Standing_Idle_Variations_002.glb",
82
+ "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/M_Standing_Idle_002.glb",
83
+ "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/idle/M_Standing_Idle_Variations_005.glb"
84
+ ], Nt = [
85
+ {
86
+ id: "m_expr_01",
87
+ name: "Friendly Wave",
88
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_001.glb"
89
+ },
90
+ {
91
+ id: "m_expr_02",
92
+ name: "You There",
93
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_002.glb"
94
+ },
95
+ {
96
+ id: "m_expr_04",
97
+ name: "Awkward Agreement",
98
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_004.glb"
99
+ },
100
+ {
101
+ id: "m_expr_05",
102
+ name: "What's Going On?",
103
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_005.glb"
104
+ },
105
+ {
106
+ id: "m_expr_06",
107
+ name: "Tired Stretch",
108
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_006.glb"
109
+ },
110
+ {
111
+ id: "m_expr_07",
112
+ name: "Conceilied Laughter",
113
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_007.glb"
114
+ },
115
+ {
116
+ id: "m_expr_08",
117
+ name: "You Come Here",
118
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_008.glb"
119
+ },
120
+ {
121
+ id: "m_expr_09",
122
+ name: "Come Here Kid",
123
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_009.glb"
124
+ },
125
+ {
126
+ id: "m_expr_10",
127
+ name: "Come Here Everyone",
128
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_010.glb"
129
+ },
130
+ {
131
+ id: "m_expr_11",
132
+ name: "No Freaking Way",
133
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_011.glb"
134
+ },
135
+ {
136
+ id: "m_expr_12",
137
+ name: "Cheerful Approval",
138
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_012.glb"
139
+ },
140
+ {
141
+ id: "m_expr_13",
142
+ name: "Waving Hello",
143
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_013.glb"
144
+ },
145
+ {
146
+ id: "m_expr_14",
147
+ name: "Checking Surroundings",
148
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_014.glb"
149
+ },
150
+ {
151
+ id: "m_expr_15",
152
+ name: "Referee Warning",
153
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_015.glb"
154
+ },
155
+ {
156
+ id: "m_expr_16",
157
+ name: "You Thumbs Down",
158
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_016.glb"
159
+ },
160
+ {
161
+ id: "m_expr_17",
162
+ name: "Side Thumbs Down",
163
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_017.glb"
164
+ },
165
+ {
166
+ id: "m_expr_18",
167
+ name: "You're Finished",
168
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Standing_Expressions_018.glb"
169
+ },
170
+ {
171
+ id: "m_talk_01",
172
+ name: "Oh God, Why Me?",
173
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_001.glb"
174
+ },
175
+ {
176
+ id: "m_talk_02",
177
+ name: "What Are You Doing?",
178
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_002.glb"
179
+ },
180
+ {
181
+ id: "m_talk_03",
182
+ name: "What Am I doing?",
183
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_003.glb"
184
+ },
185
+ {
186
+ id: "m_talk_04",
187
+ name: "No Way",
188
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_004.glb"
189
+ },
190
+ {
191
+ id: "m_talk_05",
192
+ name: "What's Going On?",
193
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_005.glb"
194
+ },
195
+ {
196
+ id: "m_talk_06",
197
+ name: "I have no idea",
198
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_006.glb"
199
+ },
200
+ {
201
+ id: "m_talk_07",
202
+ name: "What's going on here?",
203
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_007.glb"
204
+ },
205
+ {
206
+ id: "m_talk_08",
207
+ name: "Let's stop",
208
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_008.glb"
209
+ },
210
+ {
211
+ id: "m_talk_09",
212
+ name: "Fed Up Moment",
213
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_009.glb"
214
+ },
215
+ {
216
+ id: "m_talk_10",
217
+ name: "What's This? Hold On",
218
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_010.glb"
219
+ },
220
+ {
221
+ id: "f_talk_01",
222
+ name: "Great Job Clap",
223
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_001.glb"
224
+ },
225
+ {
226
+ id: "f_talk_02",
227
+ name: "Chill Stretch",
228
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_002.glb"
229
+ },
230
+ {
231
+ id: "f_talk_03",
232
+ name: "This Is Me",
233
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_003.glb"
234
+ },
235
+ {
236
+ id: "f_talk_04",
237
+ name: "Empathize",
238
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_004.glb"
239
+ },
240
+ {
241
+ id: "f_talk_05",
242
+ name: "Loose Hands Stretch",
243
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_005.glb"
244
+ },
245
+ {
246
+ id: "f_talk_06",
247
+ name: "Take It Easy",
248
+ url: "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/F_Talking_Variations_006.glb"
249
+ }
250
+ ], Wt = [
251
+ "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_005.glb",
252
+ "https://pub-be53cae7bd99457a8c1f11b4d38f1672.r2.dev/masculine/expression/M_Talking_Variations_007.glb"
253
+ ], Pt = {
254
+ zoom: 0.85,
255
+ position: [0.15, -0.8, 0],
256
+ scale: 1.5,
257
+ rotation: [0.15, 0.02, 0]
258
+ }, Vt = [-0.45, 1.9, 0.1], Bt = {
259
+ browInnerUp: 0.2
260
+ }, Ye = 0.18, $t = 1, Ne = {
261
+ neutral: { eyeLookDownLeft: 0.1, eyeLookDownRight: 0.1 },
262
+ happy: { mouthSmileLeft: 0.2, mouthSmileRight: 0.2, eyeLookDownLeft: 0.1, eyeLookDownRight: 0.1 },
263
+ sad: { eyeLookDownLeft: 0.2, eyeLookDownRight: 0.2, browDownRight: 0.1, browInnerUp: 0.6, browOuterUpRight: 0.2, eyeSquintLeft: 0.7, eyeSquintRight: 0.7, mouthFrownLeft: 0.8, mouthFrownRight: 0.8, mouthLeft: 0.2, mouthPucker: 0.5, mouthRollLower: 0.2, mouthRollUpper: 0.2, mouthShrugLower: 0.2, mouthShrugUpper: 0.2, mouthStretchLeft: 0.4 },
264
+ angry: { eyeLookDownLeft: 0.1, eyeLookDownRight: 0.1, browDownLeft: 0.6, browDownRight: 0.6, jawForward: 0.3, mouthFrownLeft: 0.7, mouthFrownRight: 0.7, mouthRollLower: 0.2, mouthShrugLower: 0.3 },
265
+ fear: { browInnerUp: 0.7, eyeSquintLeft: 0.5, eyeSquintRight: 0.5, eyeWideLeft: 0.6, eyeWideRight: 0.6, mouthClose: 0.1, mouthFunnel: 0.3, mouthShrugLower: 0.5, mouthShrugUpper: 0.5 },
266
+ disgust: { browDownLeft: 0.7, browDownRight: 0.1, browInnerUp: 0.3, eyeSquintLeft: 1, eyeSquintRight: 1, eyeWideLeft: 0.5, eyeWideRight: 0.5, mouthLeft: 0.4, mouthPressLeft: 0.3, mouthRollLower: 0.3, mouthShrugLower: 0.3, mouthShrugUpper: 0.8, mouthUpperUpLeft: 0.3, noseSneerLeft: 1, noseSneerRight: 0.7 },
267
+ love: { browInnerUp: 0.4, browOuterUpLeft: 0.2, browOuterUpRight: 0.2, mouthSmileLeft: 0.2, mouthSmileRight: 0.2, eyeBlinkLeft: 0.6, eyeBlinkRight: 0.6, eyeWideLeft: 0.7, eyeWideRight: 0.7, mouthDimpleLeft: 0.1, mouthDimpleRight: 0.1, mouthPressLeft: 0.2, mouthShrugUpper: 0.2, mouthUpperUpLeft: 0.1, mouthUpperUpRight: 0.1 }
268
+ }, Ht = [
269
+ { key: "viseme_aa", mix: { jawOpen: 0.6 } },
270
+ { key: "viseme_E", mix: { mouthPressLeft: 0.8, mouthPressRight: 0.8, mouthDimpleLeft: 1, mouthDimpleRight: 1, jawOpen: 0.3 } },
271
+ { key: "viseme_I", mix: { mouthPressLeft: 0.6, mouthPressRight: 0.6, mouthDimpleLeft: 0.6, mouthDimpleRight: 0.6, jawOpen: 0.2 } },
272
+ { key: "viseme_O", mix: { mouthPucker: 1, jawForward: 0.6, jawOpen: 0.2 } },
273
+ { key: "viseme_U", mix: { mouthFunnel: 1 } },
274
+ { key: "viseme_PP", mix: { mouthRollLower: 0.3, mouthRollUpper: 0.3, mouthUpperUpLeft: 0.3, mouthUpperUpRight: 0.3 } },
275
+ { key: "viseme_FF", mix: { mouthPucker: 1, mouthShrugUpper: 1, mouthLowerDownLeft: 0.2, mouthLowerDownRight: 0.2, mouthDimpleLeft: 1, mouthDimpleRight: 1, mouthRollLower: 0.3 } },
276
+ { key: "viseme_DD", mix: { mouthPressLeft: 0.8, mouthPressRight: 0.8, mouthFunnel: 0.5, jawOpen: 0.2 } },
277
+ { key: "viseme_SS", mix: { mouthPressLeft: 0.8, mouthPressRight: 0.8, mouthLowerDownLeft: 0.5, mouthLowerDownRight: 0.5, jawOpen: 0.1 } },
278
+ { key: "viseme_TH", mix: { mouthRollUpper: 0.3, jawOpen: 0.2, tongueOut: 0.4 } },
279
+ { key: "viseme_CH", mix: { mouthPucker: 0.5, jawOpen: 0.2 } },
280
+ { key: "viseme_RR", mix: { mouthPucker: 0.5, jawOpen: 0.2 } },
281
+ { key: "viseme_kk", mix: { mouthLowerDownLeft: 0.4, mouthLowerDownRight: 0.4, mouthDimpleLeft: 0.3, mouthDimpleRight: 0.3, mouthFunnel: 0.3, mouthPucker: 0.3, jawOpen: 0.15 } },
282
+ { key: "viseme_nn", mix: { mouthLowerDownLeft: 0.4, mouthLowerDownRight: 0.4, mouthDimpleLeft: 0.3, mouthDimpleRight: 0.3, mouthFunnel: 0.3, mouthPucker: 0.3, jawOpen: 0.15, tongueOut: 0.2 } },
283
+ { key: "viseme_sil", mix: {} }
284
+ ], jt = {
285
+ aei: [{ v: "E", w: 0.8 }, { v: "I", w: 0.2 }],
286
+ ee: [{ v: "I", w: 1 }],
287
+ oo: [{ v: "O", w: 1 }],
288
+ u: [{ v: "U", w: 1 }],
289
+ aa: [{ v: "aa", w: 1 }],
290
+ ah: [{ v: "aa", w: 0.7 }, { v: "O", w: 0.3 }],
291
+ bmp: [{ v: "PP", w: 1 }],
292
+ fv: [{ v: "FF", w: 1 }],
293
+ th: [{ v: "TH", w: 1 }],
294
+ l: [{ v: "nn", w: 1 }],
295
+ r: [{ v: "RR", w: 1 }],
296
+ qw: [{ v: "U", w: 0.6 }, { v: "O", w: 0.4 }],
297
+ chjsh: [{ v: "CH", w: 1 }],
298
+ cdgknstxyz: [{ v: "DD", w: 0.6 }, { v: "SS", w: 0.4 }],
299
+ sil: [{ v: "sil", w: 1 }]
300
+ };
301
+ function Jt(d) {
302
+ if (!d) return [{ v: "sil", w: 1 }];
303
+ const y = d.toLowerCase();
304
+ return jt[y] ?? [{ v: "sil", w: 1 }];
305
+ }
306
+ function qt({ target: d }) {
307
+ const { camera: y } = Et();
308
+ return z(() => {
309
+ y.lookAt(...d);
310
+ }, [y, d]), null;
311
+ }
312
+ function q(d, y, v) {
313
+ if (!d || !d.morphTargetDictionary) return;
314
+ const p = d, I = p.morphTargetDictionary, E = p.morphTargetInfluences;
315
+ if (E)
316
+ for (const R in I)
317
+ R.toLowerCase() === y.toLowerCase() && (E[I[R]] = v);
318
+ }
319
+ function ct(d, y = 0.97) {
320
+ if (!d) return;
321
+ const v = d;
322
+ if (v.morphTargetInfluences)
323
+ for (let p = 0; p < v.morphTargetInfluences.length; p++)
324
+ v.morphTargetInfluences[p] *= y;
325
+ }
326
+ const Gt = kt(({ avatarUrl: d, isPlayingRef: y, visemeQueueRef: v, audioContextRef: p, responseAudioStartTimeRef: I, adjustments: E, mood: R, expression: ge, agentResponse: re, isSpeaking: C, nextStartTimeRef: L, stopPlayback: Q, setIsSpeaking: W, expressionUrl: A, onExpressionFinished: le }) => {
327
+ const { scene: m } = Ge(d), be = Ge(Ut), ie = ze(() => be.flatMap((h) => h.animations), [be]), ue = Ge(Wt), se = ze(() => ue.flatMap((h) => h.animations), [ue]), N = c(null), O = c(null), b = c(null), P = c([]), [M] = k(() => new Ie.AnimationMixer(m)), g = c({}), _ = c(null), Z = c(0), ee = c(!1), de = c(0), _e = c(null);
328
+ z(() => {
329
+ if (!(!ie || !m)) {
330
+ if (ie.forEach((h, o) => {
331
+ const r = `idle_${o}`;
332
+ if (!g.current[r]) {
333
+ const t = M.clipAction(h, m);
334
+ t.name = r, t.setLoop(Ie.LoopOnce, 1), t.clampWhenFinished = !0, g.current[r] = t;
335
+ }
336
+ }), se.forEach((h, o) => {
337
+ const r = `talk_${o}`;
338
+ if (!g.current[r]) {
339
+ const t = M.clipAction(h, m);
340
+ t.name = r, t.setLoop(Ie.LoopOnce, 1), t.clampWhenFinished = !0, g.current[r] = t;
341
+ }
342
+ }), ie.length > 0) {
343
+ const h = g.current.idle_0, o = _.current && M.existingAction(_.current.getClip());
344
+ h && !o && (h.reset().fadeIn(0.5).play(), _.current = h);
345
+ }
346
+ return () => {
347
+ M.stopAllAction(), g.current = {}, _.current = null;
348
+ };
349
+ }
350
+ }, [ie, se, m, M]);
351
+ const Ce = c("");
352
+ z(() => {
353
+ if (!A || !m || A === Ce.current) return;
354
+ Ce.current = A, _e.current = A, new It().load(A, (o) => {
355
+ if (o.animations && o.animations.length > 0) {
356
+ const r = o.animations[0], t = M.clipAction(r, m);
357
+ if (t.name = `EXPR_${A}`, t.setLoop(Ie.LoopOnce, 1), t.clampWhenFinished = !0, g.current[`EXPR_${A}`] = t, C && _e.current === A) {
358
+ const l = _.current;
359
+ t.reset().fadeIn(0.3).play(), l && l !== t && l.crossFadeTo(t, 0.3, !0), _.current = t, _e.current = null;
360
+ }
361
+ }
362
+ }, void 0, (o) => {
363
+ console.error(`[ANIMATION] Failed to load ${A}`, o);
364
+ });
365
+ }, [A, m, M, C]), z(() => {
366
+ const h = (o) => {
367
+ const r = o.action, t = r.name || "";
368
+ if (t.startsWith("idle_")) {
369
+ const j = (parseInt(t.split("_")[1]) + 1) % ie.length, D = g.current[`idle_${j}`];
370
+ D && (D.reset().fadeIn(0.5).play(), r.crossFadeTo(D, 0.5, !0), _.current = D);
371
+ } else if (t.startsWith("EXPR_")) {
372
+ if (C) {
373
+ const l = g.current.talk_0;
374
+ l && (l.reset().fadeIn(0.5).play(), r.crossFadeTo(l, 0.5, !0), _.current = l);
375
+ } else {
376
+ const l = g.current.idle_0;
377
+ l && (l.reset().fadeIn(0.5).play(), r.crossFadeTo(l, 0.5, !0), _.current = l);
378
+ }
379
+ le && le();
380
+ } else if (t.startsWith("talk_"))
381
+ if (C) {
382
+ const j = (parseInt(t.split("_")[1]) + 1) % se.length, D = g.current[`talk_${j}`];
383
+ D && (D.reset().fadeIn(0.3).play(), r.crossFadeTo(D, 0.3, !0), _.current = D);
384
+ } else {
385
+ const l = g.current.idle_0;
386
+ l && (l.reset().fadeIn(0.5).play(), r.crossFadeTo(l, 0.5, !0), _.current = l);
387
+ }
388
+ };
389
+ return M.addEventListener("finished", h), () => M.removeEventListener("finished", h);
390
+ }, [M, ie, se, C, le]), z(() => {
391
+ if (C && m) {
392
+ const h = _.current, o = h?.name || "";
393
+ if (o.startsWith("idle_") || o.startsWith("talk_") || o === "") {
394
+ const r = _e.current;
395
+ if (r) {
396
+ const t = g.current[`EXPR_${r}`];
397
+ if (t) {
398
+ t.reset().fadeIn(0.3).play(), h && h !== t && h.crossFadeTo(t, 0.3, !0), _.current = t, _e.current = null;
399
+ return;
400
+ }
401
+ }
402
+ if (o.startsWith("idle_") || o === "") {
403
+ const t = g.current.talk_0;
404
+ t && (t.reset().fadeIn(0.5).play(), h && h.crossFadeTo(t, 0.5, !0), _.current = t);
405
+ }
406
+ }
407
+ } else if (!C && m) {
408
+ const h = _.current, o = h?.name || "";
409
+ if (o.startsWith("talk_") || o.startsWith("EXPR_")) {
410
+ const r = g.current.idle_0;
411
+ r && (r.reset().fadeIn(0.5).play(), h && h.crossFadeTo(r, 0.5, !0), _.current = r);
412
+ }
413
+ }
414
+ }, [C, m, A]), z(() => {
415
+ if (!m) return;
416
+ m.traverse((r) => {
417
+ if (r.isMesh && r.morphTargetDictionary) {
418
+ const t = r.name.toLowerCase();
419
+ (t.includes("head") || t.includes("avatar")) && (O.current = r, H(`[ANIMATION] Found head mesh: ${r.name}`)), t.includes("teeth") && (b.current = r, H(`[ANIMATION] Found teeth mesh: ${r.name}`));
420
+ }
421
+ });
422
+ const h = O.current?.morphTargetDictionary;
423
+ h && Object.keys(h).filter((r) => r.toLowerCase().includes("brow"));
424
+ const o = [];
425
+ m.traverse((r) => {
426
+ if (r.isMesh) {
427
+ const l = r.morphTargetDictionary;
428
+ l && Object.keys(l).some((j) => j.toLowerCase().includes("brow")) && o.push(r);
429
+ }
430
+ }), P.current = o, o.length > 0 && H("[ANIMATION] Meshes with brow morphs:", o.length);
431
+ }, [m]);
432
+ const We = (h, o = 1) => {
433
+ const r = `viseme_${h}`.toLowerCase(), t = Ht.find((l) => l.key.toLowerCase() === r);
434
+ if (t)
435
+ for (const l in t.mix) {
436
+ const j = t.mix[l] * o;
437
+ q(O.current, l, j), q(b.current, l, j);
438
+ }
439
+ }, Pe = (h) => {
440
+ const o = Ne[h] ?? Ne.neutral;
441
+ for (const r in o)
442
+ q(O.current, r, o[r]), q(b.current, r, o[r]);
443
+ };
444
+ return At((h, o) => {
445
+ const r = Math.pow(0.88, 60 * o);
446
+ ct(O.current, r), ct(b.current, r), Pe(R);
447
+ const t = h.clock.elapsedTime;
448
+ let l = 0;
449
+ if (Math.floor(t) % 5 === 0 && Math.floor((t - o) % 5) !== 0) {
450
+ let J = null;
451
+ m.traverse((G) => {
452
+ G.name.toLowerCase().includes("hips") && (J = G);
453
+ });
454
+ const fe = J ? `Hips Y: ${J.position.y.toFixed(4)}` : "Hips not found";
455
+ H(`[ANIMATION] Mixer Time: ${M.time.toFixed(2)}, ${fe}`);
456
+ }
457
+ if (M.update(o), t > Z.current && !ee.current && (ee.current = !0, de.current = t), ee.current) {
458
+ const fe = (t - de.current) / 0.3;
459
+ if (fe >= 1)
460
+ ee.current = !1, Z.current = t + 2 + Math.random() * 5;
461
+ else {
462
+ const G = fe < 0.5 ? fe * 2 : (1 - fe) * 2;
463
+ q(O.current, "eyeBlinkLeft", G), q(O.current, "eyeBlinkRight", G), q(b.current, "eyeBlinkLeft", G), q(b.current, "eyeBlinkRight", G), l = G * Bt.browInnerUp;
464
+ }
465
+ }
466
+ const j = Ne[R] ?? Ne.neutral, D = j.browInnerUp ?? 0, we = j.browOuterUpLeft ?? 0, Le = j.browOuterUpRight ?? 0, xe = t * $t, Ae = Ye * Math.sin(xe), Me = Ye * 0.7 * Math.sin(xe + 0.7), Xe = Ye * 0.7 * Math.sin(xe + 1.3), ke = (J) => Math.max(0, Math.min(1, J)), Ee = ke(D + Ae), Te = ke(we + Me), he = ke(Le + Xe), ve = ke(Ee + l);
467
+ if (q(O.current, "browInnerUp", ve), q(b.current, "browInnerUp", ve), q(O.current, "browOuterUpLeft", Te), q(b.current, "browOuterUpLeft", Te), q(O.current, "browOuterUpRight", he), q(b.current, "browOuterUpRight", he), N.current) {
468
+ const J = y.current ? 0 : E.rotation[1];
469
+ N.current.rotation.y = Ie.MathUtils.lerp(N.current.rotation.y, J, 0.1), N.current.position.set(...E.position), N.current.scale.setScalar(E.scale), N.current.rotation.x = E.rotation[0], N.current.rotation.z = E.rotation[2];
470
+ }
471
+ if (y.current && p.current) {
472
+ const J = p.current.currentTime, X = (J - I.current) * 1e3 - -150;
473
+ for (let oe = 0; oe < v.current.length; oe++) {
474
+ const K = v.current[oe];
475
+ X >= K.vtime && X < K.vtime + K.vduration && We(K.viseme, K.weight ?? 1);
476
+ }
477
+ J > L.current + 0.5 && (Q(), W(!1));
478
+ }
479
+ }), /* @__PURE__ */ f("group", { ref: N, children: /* @__PURE__ */ f("primitive", { object: m }) });
480
+ });
481
+ function Yt(d) {
482
+ return d ? d.charAt(0).toUpperCase() + d.slice(1).toLowerCase() : "";
483
+ }
484
+ const zt = ({ token: d, agentToken: y, onNavigationRequested: v } = {}) => {
485
+ const p = d ?? y ?? "", I = Ft(p || void 0), [E, R] = k(""), [ge, re] = k(""), [C, L] = k("Ready"), [Q, W] = k(!1), [A, le] = k(!1), m = c(!1), be = c([]), ie = c(0), ue = c(!1), se = c([]), N = c(null), O = c([]);
486
+ c([]);
487
+ const b = c([]), P = c(0), M = c(0), g = c(0), _ = c(0), [Z, ee] = k(null), de = c(null), [_e, Ce] = k("neutral"), [We, Pe] = k(""), [h, o] = k(""), [r, t] = k("Chat with us"), [l, j] = k(null), [D, we] = k("hidden"), [Le, xe] = k(""), Ae = c(null), Me = c(D);
488
+ Me.current = D;
489
+ const [Xe, ke] = k(null), Ee = c(null), Te = c(null), [he, ve] = k("hidden"), [J, fe] = k(""), G = c(he);
490
+ G.current = he;
491
+ const X = c(""), oe = c(!1), K = c(""), Re = ze(() => C === "Thinking..." || C === "Processing Voice..." ? C : l != null && l !== "" && l !== "none" && l !== "<none>" ? `Enter ${Yt(l)}` : null, [C, l]), Oe = Re != null && Re !== "";
492
+ z(() => {
493
+ const e = Me.current;
494
+ if (!(e === "exiting" || e === "entering")) {
495
+ if (e === "hidden") {
496
+ Oe && (xe(Re ?? ""), we("entering"));
497
+ return;
498
+ }
499
+ e === "visible" && (!Oe || Re !== Le) && (Ae.current = Oe ? Re : null, we("exiting"));
500
+ }
501
+ }, [Oe, Re, D, Le]);
502
+ const lt = Ue(() => {
503
+ const e = Me.current;
504
+ if (e === "exiting") {
505
+ we("hidden");
506
+ const i = Ae.current;
507
+ Ae.current = null, i != null && i !== "" && (xe(i), we("entering"));
508
+ } else e === "entering" && we("visible");
509
+ }, []), ut = (e) => {
510
+ if (!e) return;
511
+ if (e.mood != null) {
512
+ const n = String(e.mood).toLowerCase();
513
+ Ce(n);
514
+ }
515
+ if (e.expression != null) {
516
+ const n = String(e.expression).trim();
517
+ Pe(n);
518
+ const u = Nt.find((w) => w.name.toLowerCase() === n.toLowerCase());
519
+ H(`[STREAM] Animation match for "${n}": ${u ? u.name : "NONE"}`), o(u?.url ?? "");
520
+ }
521
+ if (e.navigation != null) {
522
+ const n = String(e.navigation).trim();
523
+ n !== "" && (v ? v(n) : window.open(n, "_blank"));
524
+ }
525
+ const i = e.ask_for || e.lead_capture?.ask_for, s = i ? String(i).trim().toLowerCase() : "", a = s === "none" || s === "<none>";
526
+ if (i && !a) {
527
+ const n = s;
528
+ j(n || null), t(n === "email" ? "Enter your email" : n === "name" ? "Enter your name" : n === "phone" ? "Enter your phone number" : "Chat with us");
529
+ } else (a || e.ask_for === null || e.lead_capture && e.lead_capture.ask_for === null || e.ask_for === "none") && (j(null), r !== "Chat with us" && t("Chat with us"));
530
+ e.collected, e.valid;
531
+ }, dt = (e) => {
532
+ const i = e.trim();
533
+ if (!i) return null;
534
+ if (i.startsWith("{"))
535
+ try {
536
+ return JSON.parse(i);
537
+ } catch {
538
+ return null;
539
+ }
540
+ if (i.includes(":")) {
541
+ const s = i.split(":"), a = s[0].trim().toLowerCase(), n = s.slice(1).join(":").trim();
542
+ return { [a]: n };
543
+ }
544
+ return null;
545
+ }, ht = Ue(() => {
546
+ }, []), Ke = (e) => {
547
+ if (oe.current)
548
+ e === "§" ? oe.current = !1 : (K.current += e, re((i) => i + e));
549
+ else if (e === "§") {
550
+ oe.current = !0;
551
+ return;
552
+ } else
553
+ for (X.current += e; X.current.includes(`
554
+ `); ) {
555
+ const i = X.current.indexOf(`
556
+ `), s = X.current.slice(0, i).trim();
557
+ X.current = X.current.slice(i + 1);
558
+ const a = dt(s);
559
+ a && ut(a);
560
+ }
561
+ };
562
+ z(() => {
563
+ (async () => {
564
+ if (!sessionStorage.getItem("STREAMOJI_LEADS_SESSION_LEAD_ID")) {
565
+ const s = "secret", a = Math.floor(Date.now() / 1e3).toString();
566
+ try {
567
+ const n = new TextEncoder(), u = await crypto.subtle.importKey(
568
+ "raw",
569
+ n.encode(s),
570
+ { name: "HMAC", hash: "SHA-256" },
571
+ !1,
572
+ ["sign"]
573
+ ), w = await crypto.subtle.sign(
574
+ "HMAC",
575
+ u,
576
+ n.encode(a)
577
+ ), V = Array.from(new Uint8Array(w)).map((S) => S.toString(16).padStart(2, "0")).join("");
578
+ sessionStorage.setItem("STREAMOJI_LEADS_SESSION_LEAD_ID", V), H("[SESSION] New HMAC UID generated and saved:", V);
579
+ } catch (n) {
580
+ console.error("[SESSION] HMAC generation failed:", n);
581
+ const u = Math.random().toString(36) + Date.now().toString();
582
+ sessionStorage.setItem("STREAMOJI_LEADS_SESSION_LEAD_ID", u);
583
+ }
584
+ }
585
+ sessionStorage.getItem("STREAMOJI_LEADS_SESSION_MESSAGES") || sessionStorage.setItem("STREAMOJI_LEADS_SESSION_MESSAGES", JSON.stringify([]));
586
+ })();
587
+ }, []);
588
+ const Qe = () => {
589
+ try {
590
+ return JSON.parse(sessionStorage.getItem("STREAMOJI_LEADS_SESSION_MESSAGES") || "[]");
591
+ } catch {
592
+ return [];
593
+ }
594
+ }, ft = (e) => {
595
+ sessionStorage.setItem("STREAMOJI_LEADS_SESSION_MESSAGES", JSON.stringify(e));
596
+ }, [Ve, Be] = k(!1), [Ze, $e] = k(0), ae = c(null), De = c([]), et = c(0), [tt, pt] = k(null), [mt, He] = k(null), pe = c(null), Se = c(null), je = Ue(() => {
597
+ se.current = [], ue.current = !1, le(!1), P.current = 0, M.current = 0, g.current = 0, O.current.forEach((e) => {
598
+ try {
599
+ e.stop();
600
+ } catch {
601
+ }
602
+ }), Ee.current && (clearTimeout(Ee.current), Ee.current = null), ke(null), o(""), O.current = [];
603
+ }, []), gt = async () => {
604
+ try {
605
+ const e = await navigator.mediaDevices.getUserMedia({ audio: !0 }), i = window.AudioContext || window.webkitAudioContext, s = new i(), a = s.createMediaStreamSource(e), n = s.createAnalyser();
606
+ n.fftSize = 64, a.connect(n), pe.current = s, Se.current = a, He(n);
607
+ const u = new MediaRecorder(e);
608
+ ae.current = u, De.current = [], u.ondataavailable = (w) => {
609
+ w.data.size > 0 && De.current.push(w.data);
610
+ }, u.onstop = async () => {
611
+ const w = Date.now() - et.current;
612
+ if (He(null), Se.current && (Se.current.disconnect(), Se.current = null), pe.current && pe.current.state !== "closed" && (pe.current.close(), pe.current = null), w < 1e3) {
613
+ L("Recording too short. Hold or click longer."), W(!1);
614
+ return;
615
+ }
616
+ const x = new Blob(De.current, { type: "audio/wav" });
617
+ await vt(x);
618
+ }, et.current = Date.now(), u.start(100), Be(!0), L("Listening...");
619
+ } catch (e) {
620
+ console.error("Error accessing microphone:", e), L("Mic Access Error");
621
+ }
622
+ }, bt = () => {
623
+ ae.current && ae.current.state !== "inactive" && (ae.current.stop(), ae.current.stream.getTracks().forEach((e) => e.stop()), Be(!1));
624
+ }, _t = () => {
625
+ ae.current && ae.current.state !== "inactive" && (ae.current.onstop = null, ae.current.stop(), ae.current.stream.getTracks().forEach((e) => e.stop()), He(null), Se.current && (Se.current.disconnect(), Se.current = null), pe.current && pe.current.state !== "closed" && (pe.current.close(), pe.current = null), Be(!1), De.current = [], L("Ready"));
626
+ };
627
+ z(() => {
628
+ if (!A) return;
629
+ const e = () => {
630
+ const i = g.current;
631
+ if (i <= 0) return;
632
+ const s = N.current, a = P.current;
633
+ if (!s) return;
634
+ const n = s.currentTime - a, u = Math.min(Math.max(0, n), i), w = ge.trim().length;
635
+ if (w <= 0) return;
636
+ const x = Math.min(
637
+ Math.round(u / i * w),
638
+ w
639
+ );
640
+ ee(x);
641
+ };
642
+ return clearInterval(de.current ?? void 0), de.current = setInterval(e, 90), () => clearInterval(de.current ?? void 0);
643
+ }, [A, ge, g.current]), z(() => {
644
+ let e;
645
+ return Ve ? ($e(0), e = window.setInterval(() => {
646
+ $e((i) => i + 1);
647
+ }, 1e3)) : $e(0), () => clearInterval(e);
648
+ }, [Ve]);
649
+ const wt = (e) => {
650
+ const i = e.numberOfChannels, s = e.length * i * 2 + 44, a = new ArrayBuffer(s), n = new DataView(a);
651
+ let u = 0;
652
+ const w = (F) => {
653
+ n.setUint16(u, F, !0), u += 2;
654
+ }, x = (F) => {
655
+ n.setUint32(u, F, !0), u += 4;
656
+ };
657
+ x(1179011410), x(s - 8), x(1163280727), x(544501094), x(16), w(1), w(i), x(e.sampleRate), x(e.sampleRate * 2 * i), w(i * 2), w(16), x(1635017060), x(s - u - 4);
658
+ const V = [];
659
+ for (let F = 0; F < i; F++) V.push(e.getChannelData(F));
660
+ let S = 0;
661
+ for (; u < s; ) {
662
+ for (let F = 0; F < i; F++) {
663
+ let B = Math.max(-1, Math.min(1, V[F][S]));
664
+ B = B < 0 ? B * 32768 : B * 32767, n.setInt16(u, B, !0), u += 2;
665
+ }
666
+ S++;
667
+ }
668
+ return new Blob([a], { type: "audio/wav" });
669
+ }, Je = async (e, i, s = !1) => {
670
+ if (m.current) {
671
+ be.current.push({ audio: e, visemes: i, isNewSegment: s });
672
+ return;
673
+ }
674
+ m.current = !0;
675
+ try {
676
+ const a = window.AudioContext || window.webkitAudioContext, n = N.current ?? new a();
677
+ n.state === "suspended" && await n.resume(), N.current = n;
678
+ const u = window.atob(e), w = new Uint8Array(u.length);
679
+ for (let U = 0; U < u.length; U++) w[U] = u.charCodeAt(U);
680
+ const x = await n.decodeAudioData(w.buffer.slice(0));
681
+ g.current += x.duration;
682
+ const V = n.currentTime;
683
+ let S = M.current;
684
+ const F = !ue.current;
685
+ S < V && (S = V + 0.1), M.current = S + x.duration;
686
+ const B = n.createBufferSource();
687
+ B.buffer = x;
688
+ let $ = tt;
689
+ if ((!$ || $.context !== n) && ($ = n.createAnalyser(), $.fftSize = 64, $.connect(n.destination), pt($)), B.connect($), O.current.push(B), F) {
690
+ ue.current = !0, le(!0), H(`[AUDIO] setIsSpeaking(true) - First chunk starting at ${S.toFixed(3)}`), P.current = S;
691
+ const U = (S - V) * 1e3;
692
+ ie.current = performance.now() + U, H(`[AUDIO] Response started. Initial startTime: ${S.toFixed(3)}, CT: ${V.toFixed(3)}`);
693
+ }
694
+ B.start(S);
695
+ const Y = (S - P.current) * 1e3;
696
+ s && (_.current = Y, H(`[AUDIO] New segment detected at +${Y.toFixed(0)}ms. Resetting segment offset.`)), i.forEach((U, me) => {
697
+ const T = U.symbol ?? "";
698
+ if (T) {
699
+ const te = Jt(T), ce = Math.round(U.start * 1e3), ye = Math.round((U.duration ?? 0) * 1e3), it = _.current + ce;
700
+ me < 3 && H(`[AUDIO] Viseme "${T}": segment_relative=${ce}ms, segment_offset=${_.current.toFixed(0)}ms => vtime=${it}ms`), te.forEach((st) => {
701
+ se.current.push({ viseme: st.v, weight: st.w, vtime: it, vduration: ye });
702
+ });
703
+ }
704
+ }), L("Speaking...");
705
+ } finally {
706
+ if (m.current = !1, be.current.length > 0) {
707
+ const a = be.current.shift();
708
+ a && Je(a.audio, a.visemes, a.isNewSegment);
709
+ }
710
+ }
711
+ }, vt = async (e) => {
712
+ try {
713
+ W(!0), K.current = "", re(""), L("Processing Voice...");
714
+ const i = await e.arrayBuffer(), a = await new (window.AudioContext || window.webkitAudioContext)().decodeAudioData(i), n = wt(a), u = new FileReader();
715
+ u.readAsDataURL(n), u.onloadend = async () => {
716
+ const w = u.result.split(",")[1];
717
+ je(), R(""), X.current = "", oe.current = !1;
718
+ const x = `${at}/stt?token=${encodeURIComponent(p)}`, V = await fetch(x, {
719
+ method: "POST",
720
+ headers: { "Content-Type": "application/json" },
721
+ body: JSON.stringify({ audio_base64: w, audio_format: "wav" })
722
+ });
723
+ if (!V.ok) {
724
+ const me = await V.text();
725
+ let T = "STT Failed";
726
+ try {
727
+ T = JSON.parse(me).error || T;
728
+ } catch {
729
+ me && (T = me.slice(0, 200));
730
+ }
731
+ throw new Error(T);
732
+ }
733
+ const S = V.body;
734
+ if (H("this is body" + S), !S) {
735
+ L("STT Failed"), W(!1);
736
+ return;
737
+ }
738
+ const F = S.getReader(), B = new TextDecoder();
739
+ let $ = "", Y = !1;
740
+ const U = async (me, T) => {
741
+ switch (me) {
742
+ case "transcript":
743
+ T.transcript != null && R(String(T.transcript));
744
+ break;
745
+ case "text": {
746
+ const te = T.delta ?? T.text ?? "";
747
+ te && Ke(te);
748
+ break;
749
+ }
750
+ case "audio": {
751
+ const te = T.chunk, ce = T.visemes ?? [], ye = !!T.is_new_segment;
752
+ te && await Je(te, ce, ye);
753
+ break;
754
+ }
755
+ case "done": {
756
+ Y = !0, L("Ready"), W(!1);
757
+ break;
758
+ }
759
+ case "error": {
760
+ Y = !0, L("STT Failed"), W(!1);
761
+ break;
762
+ }
763
+ default:
764
+ break;
765
+ }
766
+ };
767
+ for (; ; ) {
768
+ const { done: me, value: T } = await F.read();
769
+ T && ($ += B.decode(T, { stream: !0 }));
770
+ const te = $.split(`
771
+
772
+ `);
773
+ $ = te.pop() ?? "";
774
+ for (const ce of te) {
775
+ const ye = Fe(ce);
776
+ ye && await U(ye.event, ye.data);
777
+ }
778
+ if (me) {
779
+ if ($.trim()) {
780
+ const ce = Fe($.trim());
781
+ ce && await U(ce.event, ce.data);
782
+ }
783
+ Y || (L("Ready"), W(!1));
784
+ break;
785
+ }
786
+ }
787
+ };
788
+ } catch (i) {
789
+ console.error("Audio Submission Error:", i), L("STT Failed"), W(!1);
790
+ }
791
+ }, St = async (e) => {
792
+ e && e.preventDefault(), K.current = "", re(""), !(!E || Q) && await yt(E);
793
+ }, Fe = (e) => {
794
+ const i = e.split(/\r?\n/);
795
+ let s = "", a = "";
796
+ for (const u of i)
797
+ u.startsWith("event:") ? s = u.slice(6).trim() : u.startsWith("data:") && (a = u.slice(5).trim());
798
+ if (!s) return null;
799
+ let n = {};
800
+ if (a)
801
+ try {
802
+ n = JSON.parse(a);
803
+ } catch {
804
+ n = { raw: a };
805
+ }
806
+ return { event: s, data: n };
807
+ }, nt = (e, i) => {
808
+ switch (e) {
809
+ case "connected":
810
+ X.current = "", oe.current = !1;
811
+ break;
812
+ case "text": {
813
+ const s = i.delta ?? "";
814
+ s && Ke(s);
815
+ break;
816
+ }
817
+ case "audio": {
818
+ const s = i.chunk, a = i.visemes ?? [];
819
+ s && Je(s, a);
820
+ break;
821
+ }
822
+ case "done": {
823
+ const s = Qe(), a = K.current.trim(), n = [
824
+ ...s,
825
+ { role: "user", content: E || "..." },
826
+ { role: "assistant", content: a }
827
+ ];
828
+ ft(n), b.current = [...se.current], L("Ready"), W(!1), R("");
829
+ break;
830
+ }
831
+ case "error": {
832
+ const s = i.message ?? "Unknown error";
833
+ K.current = s, re(s), L("Agent Failed"), W(!1);
834
+ break;
835
+ }
836
+ }
837
+ }, yt = async (e) => {
838
+ W(!0), L("Thinking..."), K.current = "", X.current = "", oe.current = !1, je(), g.current = 0, ee(0);
839
+ const i = `${at}/agent/chat?token=${encodeURIComponent(p)}`;
840
+ try {
841
+ const s = Qe();
842
+ let a = sessionStorage.getItem("STREAMOJI_LEADS_SESSION_LEAD_ID");
843
+ a || (Ct("[CHAT] Session UID missing at send time! Generating emergency backup."), a = "emergency-" + Math.random().toString(36).substring(7), sessionStorage.setItem("STREAMOJI_LEADS_SESSION_LEAD_ID", a));
844
+ const n = {
845
+ history: s,
846
+ question: e,
847
+ lead_id: a
848
+ };
849
+ H("[CHAT] Sending payload:", n);
850
+ const u = await fetch(i, {
851
+ method: "POST",
852
+ headers: { "Content-Type": "application/json" },
853
+ body: JSON.stringify(n)
854
+ });
855
+ if (!u.ok)
856
+ throw new Error("Agent request failed");
857
+ const w = u.body;
858
+ if (!w) {
859
+ L("Agent Failed"), W(!1);
860
+ return;
861
+ }
862
+ const x = w.getReader(), V = new TextDecoder();
863
+ let S = "";
864
+ for (; ; ) {
865
+ const { done: F, value: B } = await x.read();
866
+ H(`[SSE] Chunk received. done=${F}, length=${B?.length || 0}`), B && (S += V.decode(B, { stream: !0 }));
867
+ const $ = S.split(`
868
+
869
+ `);
870
+ S = $.pop() ?? "";
871
+ for (const Y of $) {
872
+ H(`[SSE] Processing block: ${Y.slice(0, 50)}...`);
873
+ const U = Fe(Y);
874
+ U && (H(`[SSE] Event: ${U.event}`), nt(U.event, U.data));
875
+ }
876
+ if (F) {
877
+ if (H("[SSE] Stream finished"), S.trim()) {
878
+ const Y = Fe(S.trim());
879
+ Y && nt(Y.event, Y.data);
880
+ }
881
+ L("Ready"), W(!1), R("");
882
+ break;
883
+ }
884
+ }
885
+ } catch (s) {
886
+ console.error("Chat Error:", s), L("Agent Failed"), W(!1);
887
+ }
888
+ }, rt = ge.trim(), qe = rt && A ? rt.slice(0, Z != null && Z > 0 ? Z : 0) : "";
889
+ z(() => {
890
+ const e = G.current;
891
+ e !== "exiting" && (qe ? (fe(qe), e === "hidden" && ve("entering")) : (e === "visible" || e === "entering") && ve("exiting"));
892
+ }, [qe, he]);
893
+ const xt = Ue(() => {
894
+ const e = G.current;
895
+ e === "entering" ? ve("visible") : e === "exiting" && ve("hidden");
896
+ }, []);
897
+ return Rt(() => {
898
+ const e = Te.current;
899
+ e && (e.scrollTop = e.scrollHeight);
900
+ }, [J]), /* @__PURE__ */ ne("div", { className: "avatar-widget-container", children: [
901
+ /* @__PURE__ */ ne("div", { className: "avatar-input-area", children: [
902
+ D !== "hidden" ? /* @__PURE__ */ f(
903
+ "div",
904
+ {
905
+ className: `avatar-thinking-tab${D === "exiting" ? " avatar-thinking-tab--exiting" : D === "entering" ? " avatar-thinking-tab--entering" : ""}`,
906
+ onAnimationEnd: lt,
907
+ children: Le
908
+ }
909
+ ) : null,
910
+ /* @__PURE__ */ f("div", { className: "avatar-input-container", children: /* @__PURE__ */ f("div", { style: { display: "flex", alignItems: "center", width: "100%", height: "100%" }, children: Ve ? /* @__PURE__ */ ne("div", { className: "avatar-input-recording", children: [
911
+ /* @__PURE__ */ f(
912
+ "button",
913
+ {
914
+ type: "button",
915
+ className: "avatar-recording-cancel",
916
+ onClick: _t,
917
+ title: "Cancel",
918
+ children: /* @__PURE__ */ ne("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", style: { display: "block" }, children: [
919
+ /* @__PURE__ */ f("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
920
+ /* @__PURE__ */ f("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
921
+ ] })
922
+ }
923
+ ),
924
+ /* @__PURE__ */ ne("div", { style: { flex: 1, height: "100%", position: "relative", display: "flex", alignItems: "center", minWidth: 0 }, children: [
925
+ /* @__PURE__ */ f("div", { style: { flex: 1, height: "100%" }, children: /* @__PURE__ */ f(ot, { analyser: mt }) }),
926
+ /* @__PURE__ */ ne("span", { style: {
927
+ fontSize: "0.75rem",
928
+ color: "#64748b",
929
+ fontWeight: 500,
930
+ marginLeft: "4px",
931
+ minWidth: "32px",
932
+ textAlign: "right",
933
+ fontVariantNumeric: "tabular-nums"
934
+ }, children: [
935
+ Math.floor(Ze / 60),
936
+ ":",
937
+ String(Ze % 60).padStart(2, "0")
938
+ ] })
939
+ ] }),
940
+ /* @__PURE__ */ f(
941
+ "button",
942
+ {
943
+ type: "button",
944
+ className: "avatar-recording-confirm",
945
+ onClick: bt,
946
+ title: "Send",
947
+ children: /* @__PURE__ */ f("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", style: { display: "block" }, children: /* @__PURE__ */ f("polyline", { points: "20 6 9 17 4 12" }) })
948
+ }
949
+ )
950
+ ] }) : A ? /* @__PURE__ */ f("div", { style: { flex: 1, height: "100%", display: "flex", alignItems: "center", paddingRight: "8px" }, children: /* @__PURE__ */ f(ot, { analyser: tt }) }) : Q ? /* @__PURE__ */ f("div", { style: { flex: 1, height: "100%", display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ f("div", { className: "avatar-input-loader" }) }) : /* @__PURE__ */ ne("form", { onSubmit: St, style: { flex: 1, display: "flex", height: "100%", alignItems: "center" }, children: [
951
+ /* @__PURE__ */ f(
952
+ "input",
953
+ {
954
+ id: "avatar-text-input",
955
+ type: "text",
956
+ value: E,
957
+ onChange: (e) => R(e.target.value),
958
+ placeholder: "Ask me anything",
959
+ disabled: Q,
960
+ autoComplete: "off",
961
+ style: { width: "100%", height: "100%" }
962
+ }
963
+ ),
964
+ E.trim() === "" ? /* @__PURE__ */ f(
965
+ "button",
966
+ {
967
+ type: "button",
968
+ className: "mic-button",
969
+ onClick: gt,
970
+ disabled: Q,
971
+ style: { backgroundColor: "#1e4a5e" },
972
+ children: /* @__PURE__ */ ne("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
973
+ /* @__PURE__ */ f("path", { 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", fill: "white" }),
974
+ /* @__PURE__ */ f("path", { 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", fill: "white" })
975
+ ] })
976
+ }
977
+ ) : /* @__PURE__ */ f(
978
+ "button",
979
+ {
980
+ type: "submit",
981
+ className: "mic-button",
982
+ disabled: Q,
983
+ style: { backgroundColor: "#1e4a5e" },
984
+ title: "Send",
985
+ children: /* @__PURE__ */ ne("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
986
+ /* @__PURE__ */ f("path", { d: "M22 2L11 13", stroke: "white", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
987
+ /* @__PURE__ */ f("path", { d: "M22 2L15 22L11 13L2 9L22 2Z", stroke: "white", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
988
+ ] })
989
+ }
990
+ )
991
+ ] }) }) })
992
+ ] }),
993
+ /* @__PURE__ */ f("div", { className: "avatar-wrapper", children: /* @__PURE__ */ ne("div", { className: "avatar-scene-wrapper", children: [
994
+ he !== "hidden" && /* @__PURE__ */ f(
995
+ "div",
996
+ {
997
+ className: `avatar-bubble${he === "entering" ? " avatar-bubble--entering" : he === "exiting" ? " avatar-bubble--exiting" : ""}`,
998
+ onAnimationEnd: xt,
999
+ children: /* @__PURE__ */ f("div", { ref: Te, className: "avatar-bubble__content", children: J })
1000
+ }
1001
+ ),
1002
+ /* @__PURE__ */ f("div", { className: "avatar-canvas-layer", style: { width: 600, height: 600 }, children: /* @__PURE__ */ ne(
1003
+ Mt,
1004
+ {
1005
+ shadows: !0,
1006
+ camera: { position: [0.2, 1.4, 3], fov: 42 },
1007
+ gl: { alpha: !0 },
1008
+ dpr: 1.8,
1009
+ style: { pointerEvents: "none", width: "100%", height: "100%" },
1010
+ children: [
1011
+ /* @__PURE__ */ f(qt, { target: Vt }),
1012
+ /* @__PURE__ */ f("ambientLight", { intensity: 0.7 }),
1013
+ /* @__PURE__ */ f("directionalLight", { position: [0, 2, 2], intensity: 1 }),
1014
+ /* @__PURE__ */ f(Tt, { preset: "city" }),
1015
+ /* @__PURE__ */ f(Lt, { fallback: null, children: I !== null && /* @__PURE__ */ f(
1016
+ Gt,
1017
+ {
1018
+ avatarUrl: I,
1019
+ isPlayingRef: ue,
1020
+ visemeQueueRef: se,
1021
+ audioContextRef: N,
1022
+ responseAudioStartTimeRef: P,
1023
+ adjustments: Pt,
1024
+ mood: _e,
1025
+ expression: We,
1026
+ agentResponse: ge,
1027
+ isSpeaking: A,
1028
+ nextStartTimeRef: M,
1029
+ stopPlayback: je,
1030
+ setIsSpeaking: le,
1031
+ expressionUrl: h,
1032
+ onExpressionFinished: ht
1033
+ }
1034
+ ) })
1035
+ ]
1036
+ }
1037
+ ) })
1038
+ ] }) })
1039
+ ] });
1040
+ }, tn = ({
1041
+ token: d,
1042
+ onNavigationRequested: y
1043
+ }) => /* @__PURE__ */ f(
1044
+ zt,
1045
+ {
1046
+ token: d,
1047
+ onNavigationRequested: y
1048
+ }
1049
+ );
1050
+ export {
1051
+ tn as AvatarWidget
1052
+ };
1053
+ //# sourceMappingURL=avatar-widget.js.map