@burdenoff/fe-libs 2026.1014.5 → 2026.1015.2

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.
Files changed (45) hide show
  1. package/dist/shared/assistant/avatar/avatarPreferences.d.ts +61 -14
  2. package/dist/shared/assistant/avatar/avatarPreferences.js +54 -21
  3. package/dist/shared/assistant/avatar/live/LiveAvatarTabView.d.ts +33 -0
  4. package/dist/shared/assistant/avatar/live/LiveAvatarTabView.js +278 -0
  5. package/dist/shared/assistant/avatar/live/avatarSessionClient.d.ts +5 -0
  6. package/dist/shared/assistant/avatar/live/avatarSessionClient.js +25 -6
  7. package/dist/shared/assistant/avatar/live/avatarVoice.d.ts +43 -0
  8. package/dist/shared/assistant/avatar/live/avatarVoice.js +45 -0
  9. package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.d.ts +21 -1
  10. package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.js +74 -24
  11. package/dist/shared/assistant/avatar/live/liveAvatarController.d.ts +47 -8
  12. package/dist/shared/assistant/avatar/live/liveAvatarController.js +244 -161
  13. package/dist/shared/assistant/avatar/live/liveAvatarStatus.d.ts +2 -2
  14. package/dist/shared/assistant/avatar/live/liveAvatarStatus.js +11 -4
  15. package/dist/shared/assistant/avatar/useAvatarCopy.d.ts +50 -21
  16. package/dist/shared/assistant/avatar/useAvatarCopy.js +93 -49
  17. package/dist/shared/assistant/i18nManifest.d.ts +23 -2
  18. package/dist/shared/assistant/i18nManifest.js +23 -2
  19. package/dist/shared/assistant/index.d.ts +6 -0
  20. package/dist/shared/assistant/speech/hostedVoiceCatalogue.d.ts +19 -0
  21. package/dist/shared/assistant/speech/hostedVoiceCatalogue.js +25 -18
  22. package/dist/shared/assistant/ui/AIAssistantPanel.js +134 -101
  23. package/dist/shared/assistant/ui/AssistantAvatarTabs.d.ts +10 -0
  24. package/dist/shared/assistant/ui/AssistantAvatarTabs.js +48 -0
  25. package/dist/shared/assistant/ui/AssistantChatArea.js +1261 -1202
  26. package/dist/shared/assistant/ui/assistantLiveAvatarSeam.d.ts +137 -5
  27. package/dist/shared/assistant/ui/assistantLiveAvatarSeam.js +114 -55
  28. package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.d.ts +13 -0
  29. package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.js +70 -0
  30. package/dist/shared/assistant/ui/composer/AssistantComposer.d.ts +18 -0
  31. package/dist/shared/assistant/ui/composer/AssistantComposer.js +121 -102
  32. package/dist/shared/assistant/ui/panelOverlays.d.ts +24 -3
  33. package/dist/shared/assistant/ui/panelOverlays.js +11 -10
  34. package/dist/shared/assistant/ui/useVoiceSession.d.ts +20 -5
  35. package/dist/shared/assistant/ui/useVoiceSession.js +11 -4
  36. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +8 -2
  37. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +172 -160
  38. package/dist/shared/assistant/ui/voice/voiceStartGate.d.ts +57 -0
  39. package/dist/shared/assistant/ui/voice/voiceStartGate.js +9 -0
  40. package/dist/shared/assistant/voice/voiceReply.d.ts +23 -0
  41. package/dist/shared/assistant/voice/voiceReply.js +13 -0
  42. package/dist/shared/assistant/voice/voiceSession.d.ts +10 -0
  43. package/dist/shared/assistant/voice/voiceSession.js +7 -0
  44. package/dist/shared-assistant.js +260 -254
  45. package/package.json +1 -1
@@ -3,9 +3,13 @@ import { createAvatarTransportPort as n } from "./avatarTransportPort.js";
3
3
  import { createAvatarReplyOutputs as r } from "./avatarReplyOutputs.js";
4
4
  import { AvatarApiError as i, avatarAvailabilityRefusal as a, avatarRefusalFor as o } from "./avatarSessionClient.js";
5
5
  //#region src/shared/assistant/avatar/live/liveAvatarController.ts
6
- var s = 12e4, c = 1e4, l = 8e3, u = 5e3, d = 2e4, f = {
6
+ var s = 12e4, c = 1e4, l = 8e3, ee = 5e3, u = 2e4, d = 1e3, f = {
7
7
  voiceLive: !1,
8
8
  offered: !1,
9
+ tabOpen: !1,
10
+ tabOffered: !1,
11
+ retryAt: null,
12
+ heldByVoice: !1,
9
13
  phase: "off",
10
14
  avatars: [],
11
15
  selectedAvatarId: null,
@@ -56,48 +60,64 @@ var m = new Set(["playback-blocked", "needs-hosted-voice"]), h = {
56
60
  hide: !0
57
61
  };
58
62
  function g(s) {
59
- let { scheduler: c, preferences: l } = s, d = s.idleMs ?? 12e4, g = s.endBeforeDeadlineMs ?? 1e4, _ = s.connectTimeoutMs ?? 2e4, v = s.requestTimeoutMs ?? 8e3, y = f, b = /* @__PURE__ */ new Set(), x = !1, S = null, C = 0, w = !1, T = !1, E = 0, D = null, O = null, k = null, A = 0, j = !1, M = null, N = null, P = !1;
60
- function F(e) {
63
+ let { scheduler: c, preferences: l } = s, u = s.idleMs ?? 12e4, d = s.endBeforeDeadlineMs ?? 1e4, g = s.connectTimeoutMs ?? 2e4, _ = s.requestTimeoutMs ?? 8e3, v = {
64
+ ...f,
65
+ tabOffered: s.browserSupported()
66
+ }, y = /* @__PURE__ */ new Set(), b = !1, x = null, S = 0, C = !1, w = !1, T = 0, E = null, D = null, O = [], k = 0, A = !1, te = "user", j = !1, M = !1, N = null, P = null, F = null, I = null, L = !1;
67
+ function R(e) {
61
68
  try {
62
69
  s.onLog?.(e);
63
70
  } catch {}
64
71
  }
65
- function I(e) {
66
- return e && !x && s.browserSupported();
72
+ function z() {
73
+ return !b && s.browserSupported();
67
74
  }
68
- function L(e) {
75
+ function ne(e, t) {
76
+ return (e || t) && z();
77
+ }
78
+ function B() {
79
+ return v.retryAt !== null && s.now() < v.retryAt;
80
+ }
81
+ function V(e) {
69
82
  let t = {
70
- ...y,
83
+ ...v,
71
84
  ...e
72
- }, n = I(t.voiceLive), r = {
85
+ };
86
+ e.problem !== void 0 && e.retryAt === void 0 && e.problem !== v.problem && (t.retryAt = null);
87
+ let n = {
73
88
  ...t,
74
- offered: n
89
+ offered: ne(t.voiceLive, t.tabOpen),
90
+ tabOffered: z(),
91
+ heldByVoice: M && t.voiceLive
75
92
  };
76
- if (!Object.keys(r).every((e) => r[e] === y[e])) {
77
- y = r;
78
- for (let e of [...b]) try {
93
+ if (!Object.keys(n).every((e) => n[e] === v[e])) {
94
+ n.retryAt !== v.retryAt && (I?.(), I = null), v = n;
95
+ for (let e of [...y]) try {
79
96
  e();
80
97
  } catch {}
81
98
  }
82
99
  }
83
- function R() {
84
- l.getState().avatarEnabled !== w && l.setAvatarEnabled(w);
100
+ function H() {
101
+ return A && !j ? "voice_end" : "user";
102
+ }
103
+ function U() {
104
+ l.getState().avatarEnabled !== C && l.setAvatarEnabled(C);
85
105
  }
86
- let z = {
106
+ let re = {
87
107
  positionSec: null,
88
108
  synthetic: !0,
89
109
  rpc: "none"
90
- }, B = r({
110
+ }, W = r({
91
111
  port: {
92
- isActive: () => O !== null && O.port.isActive(),
93
- isAudioBlocked: () => O?.port.isAudioBlocked() ?? !1,
94
- connectionId: () => O?.port.connectionId() ?? 0,
95
- isMeterHealthy: () => O?.port.isMeterHealthy() ?? !1,
96
- isMeterAudible: () => O?.port.isMeterAudible() ?? !1,
97
- openSegment: () => O ? O.port.openSegment() : Promise.reject(new e("connection")),
98
- clearBuffer: (e) => O ? O.port.clearBuffer(e) : Promise.resolve(z),
99
- setOutputMuted: (e) => O?.port.setOutputMuted(e),
100
- subscribe: (e) => O ? O.port.subscribe(e) : () => void 0
112
+ isActive: () => D !== null && D.port.isActive(),
113
+ isAudioBlocked: () => D?.port.isAudioBlocked() ?? !1,
114
+ connectionId: () => D?.port.connectionId() ?? 0,
115
+ isMeterHealthy: () => D?.port.isMeterHealthy() ?? !1,
116
+ isMeterAudible: () => D?.port.isMeterAudible() ?? !1,
117
+ openSegment: () => D ? D.port.openSegment() : Promise.reject(new e("connection")),
118
+ clearBuffer: (e) => D ? D.port.clearBuffer(e) : Promise.resolve(re),
119
+ setOutputMuted: (e) => D?.port.setOutputMuted(e),
120
+ subscribe: (e) => D ? D.port.subscribe(e) : () => void 0
101
121
  },
102
122
  scheduler: c,
103
123
  decode: s.decode,
@@ -105,18 +125,18 @@ function g(s) {
105
125
  ...s.maxDrainMs === void 0 ? {} : { maxDrainMs: s.maxDrainMs },
106
126
  ...s.stallMs === void 0 ? {} : { stallMs: s.stallMs },
107
127
  onNotice: (e) => {
108
- switch (F({
128
+ switch (R({
109
129
  event: "notice",
110
130
  notice: e
111
131
  }), e.kind) {
112
132
  case "interrupted":
113
- L({ notice: "interrupted" });
133
+ V({ notice: "interrupted" });
114
134
  return;
115
135
  case "voice-fallback":
116
- w && L({ notice: "voice-only" });
136
+ C && V({ notice: "voice-only" });
117
137
  return;
118
138
  case "audio-blocked":
119
- L({
139
+ V({
120
140
  audioBlocked: !0,
121
141
  problem: "playback-blocked"
122
142
  });
@@ -126,28 +146,28 @@ function g(s) {
126
146
  },
127
147
  onActivity: (e) => {
128
148
  if (e) {
129
- M?.(), M = null;
149
+ P?.(), P = null;
130
150
  return;
131
151
  }
132
- if (T) {
133
- W("user", { notice: "time-limit" });
152
+ if (w) {
153
+ K("user", { notice: "time-limit" });
134
154
  return;
135
155
  }
136
- V();
156
+ G();
137
157
  }
138
158
  });
139
- function V() {
140
- M?.(), M = null, y.phase === "ready" && (M = c.setTimeout(() => {
141
- M = null, y.phase === "ready" && !B.isBusy() && W("idle", {});
142
- }, d));
159
+ function G() {
160
+ P?.(), P = null, v.phase === "ready" && (P = c.setTimeout(() => {
161
+ P = null, v.phase === "ready" && !W.isBusy() && K("idle", {});
162
+ }, u));
143
163
  }
144
- function H() {
145
- M?.(), M = null, N?.(), N = null;
164
+ function ie() {
165
+ P?.(), P = null, F?.(), F = null;
146
166
  }
147
- function U() {
148
- B.leave();
149
- let e = O;
150
- if (O = null, e !== null) {
167
+ function ae() {
168
+ W.leave();
169
+ let e = D;
170
+ if (D = null, e !== null) {
151
171
  if (e.unsubscribe?.(), e.meter !== null) {
152
172
  if (e.meterAudible) {
153
173
  e.meterAudible = !1;
@@ -158,88 +178,96 @@ function g(s) {
158
178
  e.videoTrack?.detach(), e.transport.dispose(), e.audioElement !== null && s.releaseAudioElement(e.audioElement);
159
179
  }
160
180
  }
161
- function W(e, t) {
162
- E += 1, w = !1, T = !1, U(), H();
163
- let n = D;
164
- D = null, R(), n !== null && (F({
181
+ function K(e, t) {
182
+ T += 1, te = e, C = !1, w = !1, M = !1, N = null, ae(), ie();
183
+ let n = E;
184
+ E = null, U(), n !== null && (R({
165
185
  event: "session-ended",
166
186
  reason: e
167
187
  }), s.client()?.end(n, {
168
188
  reason: e,
169
189
  keepalive: t.keepalive === !0
170
- }).catch(() => void 0)), L({
190
+ }).catch(() => void 0)), V({
171
191
  phase: "off",
172
192
  audioBlocked: !1,
173
193
  videoReady: !1,
174
- ...t.problem === void 0 ? y.problem !== null && m.has(y.problem) ? { problem: null } : {} : { problem: t.problem },
194
+ ...t.problem === void 0 ? v.problem !== null && m.has(v.problem) ? { problem: null } : {} : { problem: t.problem },
175
195
  ...t.notice === void 0 ? {} : { notice: t.notice }
176
196
  });
177
197
  }
178
- function G(e) {
198
+ function q(e) {
179
199
  let t = o(e);
180
- return t.hide && (x = !0), e instanceof i && F({
200
+ t.hide && (b = !0), e instanceof i && R({
181
201
  event: "refused",
182
202
  status: e.status,
183
203
  code: e.code
184
- }), w = !1, R(), L({
204
+ }), C = !1, M = !1, N = null, U();
205
+ let n = t.retryAfterSeconds !== void 0 && t.retryAfterSeconds > 0 ? t.retryAfterSeconds * 1e3 : 0, r = n > 0 ? s.now() + n : null;
206
+ return V({
185
207
  phase: "off",
186
- problem: t.problem
187
- }), t;
208
+ problem: t.problem,
209
+ retryAt: r
210
+ }), r !== null && v.retryAt === r && (I = c.setTimeout(() => {
211
+ I = null, v.retryAt === r && V({
212
+ problem: null,
213
+ retryAt: null
214
+ });
215
+ }, n)), t;
188
216
  }
189
- function K(e = h) {
190
- e.hide && (x = !0), w = !1, R(), L({
217
+ function J(e = h) {
218
+ e.hide && (b = !0), C = !1, M = !1, N = null, U(), V({
191
219
  phase: "off",
192
220
  problem: e.problem,
193
221
  avatars: []
194
222
  });
195
223
  }
196
- function q(e) {
224
+ function oe(e) {
197
225
  switch (e.type) {
198
226
  case "audioPlayback":
199
- e.canPlay ? y.problem === "playback-blocked" ? L({
227
+ e.canPlay ? v.problem === "playback-blocked" ? V({
200
228
  audioBlocked: !1,
201
229
  problem: null
202
- }) : L({ audioBlocked: !1 }) : L({
230
+ }) : V({ audioBlocked: !1 }) : V({
203
231
  audioBlocked: !0,
204
232
  problem: "playback-blocked"
205
233
  });
206
234
  return;
207
235
  case "avatarLeft":
208
236
  case "disconnected":
209
- J();
237
+ se();
210
238
  return;
211
239
  default: return;
212
240
  }
213
241
  }
214
- async function J() {
215
- let e = D;
216
- if (e === null || y.phase === "ending" || y.phase === "off") return;
217
- let t = E;
218
- L({ phase: "ending" });
242
+ async function se() {
243
+ let e = E;
244
+ if (e === null || v.phase === "ending" || v.phase === "off") return;
245
+ let t = T;
246
+ V({ phase: "ending" });
219
247
  let n = null, r = !1;
220
248
  try {
221
- let t = s.client(), i = t === null ? void 0 : await X((n) => t.status(e, n));
249
+ let t = s.client(), i = t === null ? void 0 : await Y((n) => t.status(e, n));
222
250
  n = i?.endedReason ?? null, r = i !== void 0 && [
223
251
  "ended",
224
252
  "failed",
225
253
  "canceled"
226
254
  ].includes(i.state);
227
255
  } catch {}
228
- if (E !== t) return;
256
+ if (T !== t) return;
229
257
  let i = p(n);
230
- i.hide && (x = !0), r && (D = null, F({
258
+ i.hide && (b = !0), r && (E = null, R({
231
259
  event: "session-ended",
232
260
  reason: "server"
233
- })), W("client_error", i);
261
+ })), K("client_error", i);
234
262
  }
235
- async function Y(e, r) {
263
+ async function ce(e, r) {
236
264
  let i = s.client();
237
265
  if (i === null) {
238
- K();
266
+ J();
239
267
  return;
240
268
  }
241
- let a = ++E;
242
- L({
269
+ let a = ++T;
270
+ V({
243
271
  phase: "starting",
244
272
  problem: null,
245
273
  notice: null
@@ -248,17 +276,17 @@ function g(s) {
248
276
  try {
249
277
  o = await s.openRoom();
250
278
  } catch {
251
- E === a && K();
279
+ T === a && J();
252
280
  return;
253
281
  }
254
282
  let l = () => {
255
283
  o.disconnect().catch(() => void 0);
256
284
  };
257
- if (E !== a) {
285
+ if (T !== a) {
258
286
  l();
259
287
  return;
260
288
  }
261
- let d = c.now(), f;
289
+ let u = c.now(), f;
262
290
  try {
263
291
  f = await i.create({
264
292
  avatarId: e,
@@ -266,15 +294,15 @@ function g(s) {
266
294
  idempotencyKey: s.newIdempotencyKey()
267
295
  });
268
296
  } catch (e) {
269
- if (l(), E !== a) return;
270
- G(e).showDisclosure && (S = null, $.requestOn());
297
+ if (l(), T !== a) return;
298
+ q(e).showDisclosure && (x = null, $.requestOn({ start: !1 }));
271
299
  return;
272
300
  }
273
- if (E !== a) {
274
- l(), i.end(f.sessionId, { reason: j ? "voice_end" : "user" }).catch(() => void 0);
301
+ if (T !== a) {
302
+ l(), i.end(f.sessionId, { reason: te === "voice_end" ? "voice_end" : "user" }).catch(() => void 0);
275
303
  return;
276
304
  }
277
- D = f.sessionId, L({ phase: "connecting" });
305
+ E = f.sessionId, V({ phase: "connecting" });
278
306
  let p = new t({
279
307
  room: o,
280
308
  avatarIdentity: f.avatarIdentity,
@@ -291,16 +319,16 @@ function g(s) {
291
319
  unsubscribe: null,
292
320
  port: n({
293
321
  transport: p,
294
- isEnabled: () => w && !T,
322
+ isEnabled: () => C && !w,
295
323
  subscribeMeter: (e) => (m.add(e), () => {
296
324
  m.delete(e);
297
325
  }),
298
326
  isMeterHealthy: () => h.meter?.isRunning() ?? !1
299
327
  })
300
328
  };
301
- O = h, h.unsubscribe = p.subscribe(q);
329
+ D = h, h.unsubscribe = p.subscribe(oe);
302
330
  try {
303
- await Z(p.connect({
331
+ await le(p.connect({
304
332
  url: f.livekitUrl,
305
333
  token: f.participantToken,
306
334
  audioElement: h.audioElement,
@@ -315,34 +343,36 @@ function g(s) {
315
343
  }
316
344
  },
317
345
  onAvatarVideo: (e) => {
318
- h.videoTrack = e, k !== null && e.attach(k), O === h && L({ videoReady: !0 });
346
+ h.videoTrack = e;
347
+ let t = X();
348
+ t !== null && e.attach(t), D === h && V({ videoReady: !0 });
319
349
  }
320
- }), _);
350
+ }), g);
321
351
  } catch (e) {
322
- if (E !== a) return;
323
- F({
352
+ if (T !== a) return;
353
+ R({
324
354
  event: "connect-failed",
325
355
  error: e instanceof Error ? e.name : "error"
326
- }), W("client_error", { problem: "connection" });
356
+ }), K("client_error", { problem: "connection" });
327
357
  return;
328
358
  }
329
- if (E !== a || O !== h) return;
330
- L({
359
+ if (T !== a || D !== h) return;
360
+ V({
331
361
  phase: "ready",
332
362
  audioBlocked: p.audioBlocked,
333
363
  ...p.audioBlocked ? { problem: "playback-blocked" } : {}
334
- }), V();
335
- let v = C > 0 ? d + C - u - c.now() : f.endsAt - s.now(), y = Math.max(0, v - g);
336
- N = c.setTimeout(() => {
337
- N = null, E === a && (T = !0, B.isBusy() || W("user", { notice: "time-limit" }));
338
- }, y);
364
+ }), G();
365
+ let _ = S > 0 ? u + S - ee - c.now() : f.endsAt - s.now(), v = Math.max(0, _ - d);
366
+ F = c.setTimeout(() => {
367
+ F = null, T === a && (w = !0, W.isBusy() || K("user", { notice: "time-limit" }));
368
+ }, v);
339
369
  }
340
- function X(t) {
370
+ function Y(t) {
341
371
  let n = new AbortController();
342
372
  return new Promise((r, i) => {
343
373
  let a = c.setTimeout(() => {
344
374
  n.abort(), i(new e("connection"));
345
- }, v);
375
+ }, _);
346
376
  t(n.signal).then((e) => {
347
377
  a(), r(e);
348
378
  }, (e) => {
@@ -350,7 +380,7 @@ function g(s) {
350
380
  });
351
381
  });
352
382
  }
353
- function Z(t, n) {
383
+ function le(t, n) {
354
384
  return new Promise((r, i) => {
355
385
  let a = c.setTimeout(() => i(new e("connection")), n);
356
386
  t.then((e) => {
@@ -360,138 +390,191 @@ function g(s) {
360
390
  });
361
391
  });
362
392
  }
393
+ function X() {
394
+ return O[O.length - 1] ?? null;
395
+ }
396
+ function Z(e) {
397
+ let t = O.indexOf(e);
398
+ if (t === -1) return;
399
+ let n = t === O.length - 1;
400
+ O.splice(t, 1);
401
+ let r = D?.videoTrack ?? null;
402
+ if (!n || r === null) return;
403
+ r.detach();
404
+ let i = X();
405
+ i !== null && r.attach(i);
406
+ }
363
407
  let Q = [];
364
408
  Q.push(l.subscribe(() => {
365
409
  let e = l.getState().avatarEnabled;
366
- if (e !== w) {
410
+ if (e !== C) {
367
411
  if (e) {
368
412
  l.setAvatarEnabled(!1);
369
413
  return;
370
414
  }
371
- y.phase !== "off" && y.phase !== "checking" && y.phase !== "choosing" ? W(j ? "voice_end" : "user", {}) : w = !1;
415
+ v.phase !== "off" && v.phase !== "checking" && v.phase !== "choosing" ? K(H(), {}) : C = !1;
372
416
  }
373
417
  })), s.subscribeWorkspaceChange && Q.push(s.subscribeWorkspaceChange(() => {
374
- if (x = !1, y.phase === "off") {
375
- L({
376
- problem: null,
377
- avatars: [],
378
- consentVersion: null
379
- });
380
- return;
381
- }
382
- W("workspace_switch", { problem: null }), L({
418
+ if (b = !1, v.phase === "off" ? V({
419
+ problem: null,
383
420
  avatars: [],
384
421
  consentVersion: null
385
- });
422
+ }) : (K("workspace_switch", { problem: null }), V({
423
+ avatars: [],
424
+ consentVersion: null
425
+ })), j) {
426
+ let e = T;
427
+ c.setTimeout(() => {
428
+ j && T === e && $.requestOn({ start: !1 });
429
+ }, 0);
430
+ }
386
431
  })), s.subscribePageHide && Q.push(s.subscribePageHide(() => {
387
- (D !== null || y.phase !== "off") && W("page_hide", { keepalive: !0 });
432
+ (E !== null || v.phase !== "off") && K("page_hide", { keepalive: !0 });
388
433
  }));
389
434
  let $ = {
390
435
  subscribe(e) {
391
- return b.add(e), () => {
392
- b.delete(e);
436
+ return y.add(e), () => {
437
+ y.delete(e);
393
438
  };
394
439
  },
395
- getSnapshot: () => y,
440
+ getSnapshot: () => v,
396
441
  setVoiceLive(e) {
397
- if (j = !e, e) {
398
- L({
442
+ if (A = !e, e) {
443
+ V({
399
444
  voiceLive: !0,
400
- problem: x ? y.problem : null,
445
+ problem: b || j && B() ? v.problem : null,
401
446
  notice: null
402
447
  });
403
448
  return;
404
449
  }
405
- (D !== null || y.phase !== "off") && (y.phase === "checking" || y.phase === "choosing" ? (E += 1, L({ phase: "off" })) : W("voice_end", {})), L({
450
+ if (M = !1, j) {
451
+ V({ voiceLive: !1 });
452
+ return;
453
+ }
454
+ (E !== null || v.phase !== "off") && (v.phase === "checking" || v.phase === "choosing" ? (T += 1, V({ phase: "off" })) : K("voice_end", {})), V({
406
455
  voiceLive: !1,
407
456
  notice: null
408
457
  });
409
458
  },
410
- requestOn() {
411
- if (P || !y.offered || y.phase !== "off") return;
412
- let e = s.client();
413
- if (e === null) {
414
- K();
459
+ requestOn(e = {}) {
460
+ if (L || !v.offered || v.phase !== "off") return;
461
+ let t = e.start === void 0 ? "auto" : e.start ? "start" : "choose";
462
+ if (t === "start" && B()) return;
463
+ let n = e.avatarId ?? v.selectedAvatarId, r = v.consentVersion, i = s.client();
464
+ if (i === null) {
465
+ J();
415
466
  return;
416
467
  }
417
- let t = ++E;
418
- L({
468
+ t === "start" && (N = c.now());
469
+ let o = ++T;
470
+ V({
419
471
  phase: "checking",
420
472
  problem: null,
421
473
  notice: null
422
- }), X((t) => e.availability(t)).then((e) => {
423
- if (E !== t) return;
474
+ }), Y((e) => i.availability(e)).then((e) => {
475
+ if (T !== o) return;
424
476
  if (!e.available) {
425
- K(a(e.reason));
477
+ J(a(e.reason));
426
478
  return;
427
479
  }
428
- C = e.maxSessionSeconds * 1e3;
429
- let n = l.getState().avatarId, r = n !== null && e.avatars.includes(n) ? n : e.avatars[0] ?? null;
430
- L({
480
+ S = e.maxSessionSeconds * 1e3;
481
+ let i = t === "start" && n !== null && e.avatars.includes(n), s = l.getState().avatarId, c = i ? n : s !== null && e.avatars.includes(s) ? s : e.avatars[0] ?? null;
482
+ switch (V({
431
483
  phase: "choosing",
432
484
  avatars: e.avatars,
433
- selectedAvatarId: r,
485
+ selectedAvatarId: c,
434
486
  consentVersion: e.consentVersion
435
- }), S === e.consentVersion && e.avatars.length === 1 && $.confirm();
487
+ }), t) {
488
+ case "auto":
489
+ x === e.consentVersion && e.avatars.length === 1 && $.confirm();
490
+ return;
491
+ case "start":
492
+ i && r === e.consentVersion ? $.confirm() : N = null;
493
+ return;
494
+ case "choose": return;
495
+ }
436
496
  }, (e) => {
437
- E === t && G(e);
497
+ T === o && q(e);
438
498
  });
439
499
  },
440
500
  confirm() {
441
- if (y.phase !== "choosing" || !y.voiceLive) return;
442
- let e = y.selectedAvatarId, t = y.consentVersion;
443
- e === null || t === null || (S = t, l.setAvatarId(e), w = !0, R(), Y(e, t));
501
+ if (v.phase !== "choosing" || !(v.voiceLive || j)) return;
502
+ let e = v.selectedAvatarId, t = v.consentVersion;
503
+ e === null || t === null || (x = t, l.setAvatarId(e), C = !0, M = !j, j && (N ??= c.now()), U(), ce(e, t));
444
504
  },
445
505
  cancelChoice() {
446
- y.phase === "choosing" && (E += 1, L({ phase: "off" }));
447
- },
448
- selectAvatar(e) {
449
- y.avatars.includes(e) && L({ selectedAvatarId: e });
506
+ v.phase === "choosing" && (T += 1, N = null, V({ phase: "off" }));
450
507
  },
451
- switchOff() {
452
- if (y.phase === "checking" || y.phase === "choosing") {
453
- E += 1, L({ phase: "off" });
508
+ setTabOpen(e) {
509
+ if (L || e === j) return;
510
+ if (j = e, e) {
511
+ V({ tabOpen: !0 }), v.phase === "checking" && (T += 1, V({ phase: "off" }), $.requestOn({ start: !1 }));
454
512
  return;
455
513
  }
456
- if (y.phase === "off" && !w) {
457
- R();
514
+ N = null;
515
+ let t = v.phase;
516
+ if (t === "checking" || t === "choosing") {
517
+ T += 1, V({
518
+ tabOpen: !1,
519
+ phase: "off"
520
+ });
458
521
  return;
459
522
  }
460
- W(j ? "voice_end" : "user", {});
523
+ (E !== null || t !== "off") && !v.heldByVoice && K("user", {}), V({ tabOpen: !1 });
524
+ },
525
+ selectAvatar(e) {
526
+ v.avatars.includes(e) && V({ selectedAvatarId: e });
527
+ },
528
+ switchOff() {
529
+ let { phase: e } = v;
530
+ if (!(j && N !== null && (e === "checking" || e === "starting" || e === "connecting") && c.now() - N < 1e3)) {
531
+ if (e === "checking" || e === "choosing") {
532
+ T += 1, N = null, V({ phase: "off" });
533
+ return;
534
+ }
535
+ if (e === "off" && !C) {
536
+ U();
537
+ return;
538
+ }
539
+ K(H(), {});
540
+ }
461
541
  },
462
542
  resumeAudio() {
463
- let e = O;
543
+ let e = D;
464
544
  e !== null && (e.transport.resumeAudio().catch(() => void 0), e.meter?.resume().catch(() => void 0));
465
545
  },
466
546
  setStageMounted(e) {
467
- A = Math.max(0, A + (e ? 1 : -1));
547
+ k = Math.max(0, k + (e ? 1 : -1));
468
548
  },
469
549
  attachVideo(e) {
470
- let t = O?.videoTrack ?? null;
471
550
  if (e === null) {
472
- k !== null && t?.detach(), k = null;
551
+ let e = X();
552
+ e !== null && Z(e);
473
553
  return;
474
554
  }
475
- k = e, t?.attach(e);
555
+ let t = O.indexOf(e);
556
+ t !== -1 && O.splice(t, 1), O.push(e);
557
+ let n = D?.videoTrack ?? null;
558
+ return n !== null && (n.detach(), n.attach(e)), () => Z(e);
476
559
  },
477
560
  route(e, t) {
478
- if (y.phase !== "ready" || T || !w || A === 0 || O === null || O.port.isAudioBlocked() || e.fallback === !1) return "speakers";
561
+ if (v.phase !== "ready" || w || !C || k === 0 || D === null || D.port.isAudioBlocked() || e.fallback === !1) return "speakers";
479
562
  let n = e.voice;
480
- return n !== null && n.source !== "hosted" || !t.listVoices().some((e) => e.source === "hosted") ? (F({
563
+ return n !== null && n.source !== "hosted" || !t.listVoices().some((e) => e.source === "hosted") ? (R({
481
564
  event: "notice",
482
565
  notice: { kind: "needs-hosted-voice" }
483
- }), L({ problem: "needs-hosted-voice" }), "speakers") : (y.problem === "needs-hosted-voice" && L({ problem: null }), "avatar");
566
+ }), V({ problem: "needs-hosted-voice" }), "speakers") : (v.problem === "needs-hosted-voice" && V({ problem: null }), "avatar");
484
567
  },
485
- createOutput: () => B.createOutput(),
568
+ createOutput: () => W.createOutput(),
486
569
  dispose() {
487
- if (!P) {
488
- P = !0, (D !== null || y.phase !== "off") && W("user", {});
570
+ if (!L) {
571
+ L = !0, (E !== null || v.phase !== "off") && K("user", {}), I?.(), I = null;
489
572
  for (let e of Q.splice(0)) e();
490
- b.clear();
573
+ y.clear();
491
574
  }
492
575
  }
493
576
  };
494
577
  return $;
495
578
  }
496
579
  //#endregion
497
- export { d as LIVE_AVATAR_CONNECT_TIMEOUT_MS, c as LIVE_AVATAR_END_BEFORE_DEADLINE_MS, s as LIVE_AVATAR_IDLE_MS, l as LIVE_AVATAR_REQUEST_TIMEOUT_MS, g as createLiveAvatarController };
580
+ export { u as LIVE_AVATAR_CONNECT_TIMEOUT_MS, c as LIVE_AVATAR_END_BEFORE_DEADLINE_MS, s as LIVE_AVATAR_IDLE_MS, l as LIVE_AVATAR_REQUEST_TIMEOUT_MS, d as LIVE_AVATAR_TAB_OFF_GUARD_MS, g as createLiveAvatarController };
@@ -1,4 +1,4 @@
1
1
  import { AvatarCopy } from '../useAvatarCopy';
2
2
  import { LiveAvatarSnapshot } from './liveAvatarController';
3
- /** The words for the avatar's state line: what went wrong, what it is doing, or null. */
4
- export declare function liveAvatarStatusText(snapshot: LiveAvatarSnapshot, copy: AvatarCopy): string | null;
3
+ /** The words for the avatar's state line: what went wrong, what it is doing, or null. `now`: wall-clock ms, for the retry time. */
4
+ export declare function liveAvatarStatusText(snapshot: LiveAvatarSnapshot, copy: AvatarCopy, now?: number): string | null;