@burdenoff/website-sdk 2026.1102.2 → 2026.1102.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +41 -2
  2. package/dist/avatar-live-view/index.d.mts +13 -4
  3. package/dist/avatar-live-view/index.d.ts +13 -4
  4. package/dist/avatar-live-view/index.js +1262 -257
  5. package/dist/avatar-live-view/index.js.map +1 -1
  6. package/dist/avatar-live-view/index.mjs +1260 -255
  7. package/dist/avatar-live-view/index.mjs.map +1 -1
  8. package/dist/{chunk-FQH3AJN3.js → chunk-7O2I32ZN.js} +2 -2
  9. package/dist/chunk-7O2I32ZN.js.map +1 -0
  10. package/dist/{chunk-R742FS5E.js → chunk-DZLUZKOX.js} +19 -17
  11. package/dist/{chunk-R742FS5E.js.map → chunk-DZLUZKOX.js.map} +1 -1
  12. package/dist/{chunk-SFT3WHN5.mjs → chunk-K3QZGJEH.mjs} +2 -2
  13. package/dist/chunk-K3QZGJEH.mjs.map +1 -0
  14. package/dist/{chunk-SK5UGG6A.js → chunk-P5GMVPR6.js} +76 -20
  15. package/dist/chunk-P5GMVPR6.js.map +1 -0
  16. package/dist/{chunk-EUPFS6MZ.mjs → chunk-SMD7MEEA.mjs} +76 -20
  17. package/dist/chunk-SMD7MEEA.mjs.map +1 -0
  18. package/dist/{chunk-ETI2HQEC.mjs → chunk-ZWEEBHXJ.mjs} +4 -4
  19. package/dist/{chunk-ETI2HQEC.mjs.map → chunk-ZWEEBHXJ.mjs.map} +1 -1
  20. package/dist/components/explore.d.mts +2 -2
  21. package/dist/components/explore.d.ts +2 -2
  22. package/dist/components/explore.js +14 -14
  23. package/dist/components/explore.mjs +2 -2
  24. package/dist/{explore-DUTNYUOm.d.mts → explore-DaSNdm4O.d.mts} +1 -1
  25. package/dist/{explore-DjQE7Xia.d.ts → explore-DtSPdlEy.d.ts} +1 -1
  26. package/dist/{explore-avatar-live-config-Cetx8-Zu.d.ts → explore-avatar-live-config-CAfN5eAX.d.ts} +6 -3
  27. package/dist/{explore-avatar-live-config-Bp3kQbU2.d.mts → explore-avatar-live-config-N4WhJzgS.d.mts} +6 -3
  28. package/dist/{explore-types-Bb2Ih3d8.d.mts → explore-types-Ol1Mm3dW.d.mts} +12 -1
  29. package/dist/{explore-types-Bb2Ih3d8.d.ts → explore-types-Ol1Mm3dW.d.ts} +12 -1
  30. package/dist/hooks/index.d.mts +2 -2
  31. package/dist/hooks/index.d.ts +2 -2
  32. package/dist/hooks/index.js +9 -9
  33. package/dist/hooks/index.mjs +1 -1
  34. package/dist/index.d.mts +15 -9
  35. package/dist/index.d.ts +15 -9
  36. package/dist/index.js +92 -63
  37. package/dist/index.js.map +1 -1
  38. package/dist/index.mjs +35 -6
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/{use-explore-chat-DunjG-3p.d.ts → use-explore-chat-B3dOOvJN.d.ts} +43 -3
  41. package/dist/{use-explore-chat-zRuoAin6.d.mts → use-explore-chat-CbfohA9O.d.mts} +43 -3
  42. package/package.json +1 -1
  43. package/dist/chunk-EUPFS6MZ.mjs.map +0 -1
  44. package/dist/chunk-FQH3AJN3.js.map +0 -1
  45. package/dist/chunk-SFT3WHN5.mjs.map +0 -1
  46. package/dist/chunk-SK5UGG6A.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkFQH3AJN3_js = require('../chunk-FQH3AJN3.js');
3
+ var chunk7O2I32ZN_js = require('../chunk-7O2I32ZN.js');
4
4
  var chunkO4GS3XPZ_js = require('../chunk-O4GS3XPZ.js');
5
5
  var chunkC6OJIHNO_js = require('../chunk-C6OJIHNO.js');
6
6
  require('../chunk-ZSTFX7FV.js');
@@ -49,6 +49,15 @@ function readBotCheck(value) {
49
49
  }
50
50
  return mode === "off" ? "off" : "turnstile";
51
51
  }
52
+ var QUESTION_MODES = /* @__PURE__ */ new Set([
53
+ "any",
54
+ "suggested"
55
+ ]);
56
+ function readQuestions(value) {
57
+ if (value === void 0) return "suggested";
58
+ if (typeof value !== "string" || !QUESTION_MODES.has(value)) return null;
59
+ return value === "any" ? "any" : "suggested";
60
+ }
52
61
  function readAvailability(status, body) {
53
62
  if (status !== 200 || !isRecord(body)) return INERT;
54
63
  const { available, reason } = body;
@@ -58,16 +67,21 @@ function readAvailability(status, body) {
58
67
  if (reason === "ok") {
59
68
  const { consentVersion, maxSessionSeconds } = body;
60
69
  const botCheck = readBotCheck(body.botCheck);
61
- if (available !== true || typeof consentVersion !== "string" || !chunkFQH3AJN3_js.isAvatarVersion(consentVersion) || typeof maxSessionSeconds !== "number" || !Number.isInteger(maxSessionSeconds) || maxSessionSeconds < 1 || botCheck === null) {
70
+ const questions = readQuestions(body.questions);
71
+ if (available !== true || typeof consentVersion !== "string" || !chunk7O2I32ZN_js.isAvatarVersion(consentVersion) || typeof maxSessionSeconds !== "number" || !Number.isInteger(maxSessionSeconds) || maxSessionSeconds < 1 || botCheck === null || questions === null) {
62
72
  return INERT;
63
73
  }
64
74
  return {
65
75
  kind: "available",
66
- offer: { consentVersion, maxSessionSeconds, botCheck }
76
+ offer: { consentVersion, maxSessionSeconds, botCheck, questions }
67
77
  };
68
78
  }
69
79
  const meaning = available ? void 0 : AVAILABILITY_REASONS.get(reason);
70
- return meaning === void 0 || meaning === "inert" ? INERT : { kind: "refused", reason: meaning };
80
+ return meaning === void 0 || meaning === "inert" ? INERT : {
81
+ kind: "refused",
82
+ reason: meaning,
83
+ questions: body.questions === "any" ? "any" : "suggested"
84
+ };
71
85
  }
72
86
  var CREATE_REFUSALS = /* @__PURE__ */ new Map([
73
87
  ["busy", "busy"],
@@ -146,7 +160,7 @@ function deadline(timeoutMs, outer) {
146
160
  };
147
161
  }
148
162
  async function requestAvailability(target) {
149
- if (!chunkFQH3AJN3_js.isAvatarSite(target.site) || !LOCALE.test(target.locale)) return INERT;
163
+ if (!chunk7O2I32ZN_js.isAvatarSite(target.site) || !LOCALE.test(target.locale)) return INERT;
150
164
  const query = new URLSearchParams({
151
165
  site: target.site,
152
166
  locale: target.locale
@@ -287,7 +301,31 @@ var EN = {
287
301
  locale: "The live avatar isn't offered in this language yet.",
288
302
  paused: "The live avatar is paused right now.",
289
303
  notEligible: "The avatar reads the first answer to a suggested question, within fifteen minutes. Start a new chat and choose a suggested question.",
290
- answerClaimed: "The avatar has already read this answer."
304
+ answerClaimed: "The avatar has already read this answer.",
305
+ askHeadline: "Ask a question, and the avatar reads the answer aloud.",
306
+ askLabel: "Question for the avatar",
307
+ askPlaceholder: "Ask the avatar\u2026",
308
+ askFooter: "Answers are AI-generated and can be wrong. Don't include personal details.",
309
+ askNoFiles: "To attach files, use Chat.",
310
+ askBusy: "You can ask when the current answer is ready.",
311
+ askUnavailable: "Chat isn't available right now.",
312
+ gettingAnswer: "Getting the answer\u2026",
313
+ startWhenReady: "Start when ready",
314
+ armed: "The avatar will start when the answer is ready.",
315
+ cancel: "Cancel",
316
+ armedCancelled: "The avatar didn't start. Press Start when ready to try again.",
317
+ notSpoken: "This answer stays in Chat as text. The avatar reads only answers that pass its speech checks.",
318
+ answerFailed: "The assistant couldn't answer. Try asking again.",
319
+ declined: "No problem. The answer is in Chat.",
320
+ askHere: "To hear an answer, ask it here.",
321
+ newChatForAvatar: "New chat for the avatar",
322
+ newChatNote: "Your current chat stays in History.",
323
+ newChatStarted: "Started a new chat for the avatar.",
324
+ readInChat: "Read the answer and sources in Chat",
325
+ usedToday: "You've had today's avatar session. Answers will show here as text.",
326
+ needsAnswerAny: "Ask a question here, and the avatar reads the answer aloud.",
327
+ startNewChatDetailAny: "The avatar reads aloud only the first answer in a new chat started in the Avatar tab, provided it passes the speech checks.",
328
+ notEligibleAny: "The avatar can't read this answer aloud. The answer and sources are in Chat."
291
329
  };
292
330
  var ZH = {
293
331
  checking: "\u6B63\u5728\u68C0\u67E5\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61\u662F\u5426\u53EF\u7528\u2026",
@@ -321,7 +359,32 @@ var ZH = {
321
359
  paused: "\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61\u76EE\u524D\u5DF2\u6682\u505C\u3002",
322
360
  // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
323
361
  notEligible: "\u865A\u62DF\u5F62\u8C61\u53EA\u6717\u8BFB\u63A8\u8350\u95EE\u9898\u7684\u7B2C\u4E00\u4E2A\u56DE\u7B54\uFF0C\u4E14\u987B\u5728\u5341\u4E94\u5206\u949F\u5185\u3002\u8BF7\u5F00\u59CB\u65B0\u7684\u804A\u5929\uFF0C\u5E76\u9009\u62E9\u4E00\u4E2A\u63A8\u8350\u95EE\u9898\u3002",
324
- answerClaimed: "\u865A\u62DF\u5F62\u8C61\u5DF2\u7ECF\u6717\u8BFB\u8FC7\u8FD9\u4E2A\u56DE\u7B54\u3002"
362
+ answerClaimed: "\u865A\u62DF\u5F62\u8C61\u5DF2\u7ECF\u6717\u8BFB\u8FC7\u8FD9\u4E2A\u56DE\u7B54\u3002",
363
+ // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.
364
+ askHeadline: "\u63D0\u51FA\u95EE\u9898\uFF0C\u865A\u62DF\u5F62\u8C61\u4F1A\u6717\u8BFB\u56DE\u7B54\u3002",
365
+ askLabel: "\u5411\u865A\u62DF\u5F62\u8C61\u63D0\u7684\u95EE\u9898",
366
+ askPlaceholder: "\u5411\u865A\u62DF\u5F62\u8C61\u63D0\u95EE\u2026",
367
+ askFooter: "\u56DE\u7B54\u7531 AI \u751F\u6210\uFF0C\u53EF\u80FD\u6709\u8BEF\u3002\u8BF7\u52FF\u5305\u542B\u4E2A\u4EBA\u4FE1\u606F\u3002",
368
+ askNoFiles: "\u5982\u9700\u9644\u52A0\u6587\u4EF6\uFF0C\u8BF7\u4F7F\u7528\u804A\u5929\u3002",
369
+ askBusy: "\u5F53\u524D\u56DE\u7B54\u51C6\u5907\u597D\u540E\u5373\u53EF\u63D0\u95EE\u3002",
370
+ askUnavailable: "\u804A\u5929\u76EE\u524D\u4E0D\u53EF\u7528\u3002",
371
+ gettingAnswer: "\u6B63\u5728\u83B7\u53D6\u56DE\u7B54\u2026",
372
+ startWhenReady: "\u51C6\u5907\u597D\u540E\u5F00\u59CB",
373
+ armed: "\u56DE\u7B54\u51C6\u5907\u597D\u540E\uFF0C\u865A\u62DF\u5F62\u8C61\u5C06\u5F00\u59CB\u3002",
374
+ cancel: "\u53D6\u6D88",
375
+ armedCancelled: "\u865A\u62DF\u5F62\u8C61\u672A\u542F\u52A8\u3002\u53EF\u518D\u6B21\u6309\u201C\u51C6\u5907\u597D\u540E\u5F00\u59CB\u201D\u3002",
376
+ notSpoken: "\u6B64\u56DE\u7B54\u4EE5\u6587\u5B57\u5F62\u5F0F\u4FDD\u7559\u5728\u804A\u5929\u4E2D\u3002\u865A\u62DF\u5F62\u8C61\u53EA\u6717\u8BFB\u901A\u8FC7\u5176\u8BED\u97F3\u68C0\u67E5\u7684\u56DE\u7B54\u3002",
377
+ answerFailed: "\u52A9\u624B\u65E0\u6CD5\u56DE\u7B54\u3002\u8BF7\u91CD\u65B0\u63D0\u95EE\u3002",
378
+ declined: "\u6CA1\u5173\u7CFB\u3002\u56DE\u7B54\u5728\u804A\u5929\u4E2D\u3002",
379
+ askHere: "\u5982\u9700\u542C\u53D6\u56DE\u7B54\uFF0C\u8BF7\u5728\u8FD9\u91CC\u63D0\u95EE\u3002",
380
+ newChatForAvatar: "\u4E3A\u865A\u62DF\u5F62\u8C61\u5F00\u59CB\u65B0\u804A\u5929",
381
+ newChatNote: "\u5F53\u524D\u804A\u5929\u4F1A\u4FDD\u7559\u5728\u5386\u53F2\u8BB0\u5F55\u4E2D\u3002",
382
+ newChatStarted: "\u5DF2\u4E3A\u865A\u62DF\u5F62\u8C61\u5F00\u59CB\u65B0\u7684\u804A\u5929\u3002",
383
+ readInChat: "\u5728\u804A\u5929\u4E2D\u67E5\u770B\u56DE\u7B54\u548C\u6765\u6E90",
384
+ usedToday: "\u60A8\u4ECA\u5929\u5DF2\u4F7F\u7528\u8FC7\u865A\u62DF\u5F62\u8C61\u3002\u56DE\u7B54\u5C06\u4EE5\u6587\u5B57\u663E\u793A\u5728\u8FD9\u91CC\u3002",
385
+ needsAnswerAny: "\u5728\u8FD9\u91CC\u63D0\u95EE\uFF0C\u865A\u62DF\u5F62\u8C61\u4F1A\u6717\u8BFB\u56DE\u7B54\u3002",
386
+ startNewChatDetailAny: "\u865A\u62DF\u5F62\u8C61\u53EA\u6717\u8BFB\u5728\u201C\u865A\u62DF\u5F62\u8C61\u201D\u6807\u7B7E\u9875\u4E2D\u5F00\u59CB\u7684\u65B0\u804A\u5929\u7684\u7B2C\u4E00\u4E2A\u56DE\u7B54\uFF0C\u4E14\u8BE5\u56DE\u7B54\u987B\u901A\u8FC7\u8BED\u97F3\u68C0\u67E5\u3002",
387
+ notEligibleAny: "\u865A\u62DF\u5F62\u8C61\u65E0\u6CD5\u6717\u8BFB\u6B64\u56DE\u7B54\u3002\u56DE\u7B54\u548C\u6765\u6E90\u5728\u804A\u5929\u4E2D\u3002"
325
388
  };
326
389
  var HI = {
327
390
  checking: "\u091C\u093E\u0901\u091A \u0939\u094B \u0930\u0939\u0940 \u0939\u0948 \u0915\u093F \u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930 \u0909\u092A\u0932\u092C\u094D\u0927 \u0939\u0948 \u092F\u093E \u0928\u0939\u0940\u0902\u2026",
@@ -355,7 +418,32 @@ var HI = {
355
418
  paused: "\u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930 \u0905\u092D\u0940 \u0930\u0941\u0915\u093E \u0939\u0941\u0906 \u0939\u0948\u0964",
356
419
  // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
357
420
  notEligible: "\u0905\u0935\u0924\u093E\u0930 \u0938\u0941\u091D\u093E\u090F \u0917\u090F \u092A\u094D\u0930\u0936\u094D\u0928 \u0915\u093E \u092A\u0939\u0932\u093E \u0909\u0924\u094D\u0924\u0930 \u0939\u0940 \u092A\u0922\u093C\u0924\u093E \u0939\u0948, \u092A\u0902\u0926\u094D\u0930\u0939 \u092E\u093F\u0928\u091F \u0915\u0947 \u092D\u0940\u0924\u0930\u0964 \u0928\u0908 \u091A\u0948\u091F \u0936\u0941\u0930\u0942 \u0915\u0930\u0947\u0902 \u0914\u0930 \u0915\u094B\u0908 \u0938\u0941\u091D\u093E\u092F\u093E \u0917\u092F\u093E \u092A\u094D\u0930\u0936\u094D\u0928 \u091A\u0941\u0928\u0947\u0902\u0964",
358
- answerClaimed: "\u0905\u0935\u0924\u093E\u0930 \u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u092A\u0939\u0932\u0947 \u0939\u0940 \u092A\u0922\u093C \u091A\u0941\u0915\u093E \u0939\u0948\u0964"
421
+ answerClaimed: "\u0905\u0935\u0924\u093E\u0930 \u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u092A\u0939\u0932\u0947 \u0939\u0940 \u092A\u0922\u093C \u091A\u0941\u0915\u093E \u0939\u0948\u0964",
422
+ // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.
423
+ askHeadline: "\u0915\u094B\u0908 \u092A\u094D\u0930\u0936\u094D\u0928 \u092A\u0942\u091B\u0947\u0902, \u0914\u0930 \u0905\u0935\u0924\u093E\u0930 \u0909\u0938\u0915\u093E \u0909\u0924\u094D\u0924\u0930 \u091C\u093C\u094B\u0930 \u0938\u0947 \u092A\u0922\u093C\u0947\u0917\u093E\u0964",
424
+ askLabel: "\u0905\u0935\u0924\u093E\u0930 \u0915\u0947 \u0932\u093F\u090F \u092A\u094D\u0930\u0936\u094D\u0928",
425
+ askPlaceholder: "\u0905\u0935\u0924\u093E\u0930 \u0938\u0947 \u092A\u0942\u091B\u0947\u0902\u2026",
426
+ askFooter: "\u0909\u0924\u094D\u0924\u0930 AI \u0926\u094D\u0935\u093E\u0930\u093E \u092C\u0928\u093E\u090F \u091C\u093E\u0924\u0947 \u0939\u0948\u0902 \u0914\u0930 \u0917\u0932\u0924 \u0939\u094B \u0938\u0915\u0924\u0947 \u0939\u0948\u0902\u0964 \u0928\u093F\u091C\u0940 \u091C\u093E\u0928\u0915\u093E\u0930\u0940 \u0936\u093E\u092E\u093F\u0932 \u0928 \u0915\u0930\u0947\u0902\u0964",
427
+ askNoFiles: "\u092B\u093C\u093E\u0907\u0932\u0947\u0902 \u091C\u094B\u0921\u093C\u0928\u0947 \u0915\u0947 \u0932\u093F\u090F \u091A\u0948\u091F \u0915\u093E \u0909\u092A\u092F\u094B\u0917 \u0915\u0930\u0947\u0902\u0964",
428
+ askBusy: "\u092E\u094C\u091C\u0942\u0926\u093E \u0909\u0924\u094D\u0924\u0930 \u0924\u0948\u092F\u093E\u0930 \u0939\u094B\u0928\u0947 \u092A\u0930 \u0906\u092A \u092A\u0942\u091B \u0938\u0915\u0924\u0947 \u0939\u0948\u0902\u0964",
429
+ askUnavailable: "\u091A\u0948\u091F \u0905\u092D\u0940 \u0909\u092A\u0932\u092C\u094D\u0927 \u0928\u0939\u0940\u0902 \u0939\u0948\u0964",
430
+ gettingAnswer: "\u0909\u0924\u094D\u0924\u0930 \u0932\u093E\u092F\u093E \u091C\u093E \u0930\u0939\u093E \u0939\u0948\u2026",
431
+ startWhenReady: "\u0924\u0948\u092F\u093E\u0930 \u0939\u094B\u0928\u0947 \u092A\u0930 \u0936\u0941\u0930\u0942 \u0915\u0930\u0947\u0902",
432
+ armed: "\u0909\u0924\u094D\u0924\u0930 \u0924\u0948\u092F\u093E\u0930 \u0939\u094B\u0924\u0947 \u0939\u0940 \u0905\u0935\u0924\u093E\u0930 \u0936\u0941\u0930\u0942 \u0939\u094B\u0917\u093E\u0964",
433
+ cancel: "\u0930\u0926\u094D\u0926 \u0915\u0930\u0947\u0902",
434
+ armedCancelled: "\u0905\u0935\u0924\u093E\u0930 \u0936\u0941\u0930\u0942 \u0928\u0939\u0940\u0902 \u0939\u0941\u0906\u0964 \u092B\u093F\u0930 \u0938\u0947 \u0915\u094B\u0936\u093F\u0936 \u0915\u0930\u0928\u0947 \u0915\u0947 \u0932\u093F\u090F \u201C\u0924\u0948\u092F\u093E\u0930 \u0939\u094B\u0928\u0947 \u092A\u0930 \u0936\u0941\u0930\u0942 \u0915\u0930\u0947\u0902\u201D \u0926\u092C\u093E\u090F\u0901\u0964",
435
+ notSpoken: "\u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u091A\u0948\u091F \u092E\u0947\u0902 \u091F\u0947\u0915\u094D\u0938\u094D\u091F \u0915\u0947 \u0930\u0942\u092A \u092E\u0947\u0902 \u0930\u0939\u0947\u0917\u093E\u0964 \u0905\u0935\u0924\u093E\u0930 \u0915\u0947\u0935\u0932 \u0935\u0939\u0940 \u0909\u0924\u094D\u0924\u0930 \u092A\u0922\u093C\u0924\u093E \u0939\u0948 \u091C\u094B \u0909\u0938\u0915\u0940 \u0935\u093E\u0923\u0940 \u091C\u093E\u0901\u091A \u092E\u0947\u0902 \u092A\u093E\u0938 \u0939\u094B\u0924\u0947 \u0939\u0948\u0902\u0964",
436
+ answerFailed: "\u0938\u0939\u093E\u092F\u0915 \u0909\u0924\u094D\u0924\u0930 \u0928\u0939\u0940\u0902 \u0926\u0947 \u0938\u0915\u093E\u0964 \u092B\u093F\u0930 \u0938\u0947 \u092A\u0942\u091B\u0915\u0930 \u0926\u0947\u0916\u0947\u0902\u0964",
437
+ declined: "\u0915\u094B\u0908 \u092C\u093E\u0924 \u0928\u0939\u0940\u0902\u0964 \u0909\u0924\u094D\u0924\u0930 \u091A\u0948\u091F \u092E\u0947\u0902 \u0939\u0948\u0964",
438
+ askHere: "\u0909\u0924\u094D\u0924\u0930 \u0938\u0941\u0928\u0928\u0947 \u0915\u0947 \u0932\u093F\u090F, \u092F\u0939\u093E\u0901 \u092A\u0942\u091B\u0947\u0902\u0964",
439
+ newChatForAvatar: "\u0905\u0935\u0924\u093E\u0930 \u0915\u0947 \u0932\u093F\u090F \u0928\u0908 \u091A\u0948\u091F",
440
+ newChatNote: "\u0906\u092A\u0915\u0940 \u092E\u094C\u091C\u0942\u0926\u093E \u091A\u0948\u091F \u0907\u0924\u093F\u0939\u093E\u0938 \u092E\u0947\u0902 \u0930\u0939\u0947\u0917\u0940\u0964",
441
+ newChatStarted: "\u0905\u0935\u0924\u093E\u0930 \u0915\u0947 \u0932\u093F\u090F \u0928\u0908 \u091A\u0948\u091F \u0936\u0941\u0930\u0942 \u0915\u0940 \u0917\u0908\u0964",
442
+ readInChat: "\u0909\u0924\u094D\u0924\u0930 \u0914\u0930 \u0938\u094D\u0930\u094B\u0924 \u091A\u0948\u091F \u092E\u0947\u0902 \u092A\u0922\u093C\u0947\u0902",
443
+ usedToday: "\u0906\u091C \u0915\u093E \u0905\u0935\u0924\u093E\u0930 \u0938\u0924\u094D\u0930 \u0906\u092A \u0932\u0947 \u091A\u0941\u0915\u0947 \u0939\u0948\u0902\u0964 \u0909\u0924\u094D\u0924\u0930 \u092F\u0939\u093E\u0901 \u091F\u0947\u0915\u094D\u0938\u094D\u091F \u0915\u0947 \u0930\u0942\u092A \u092E\u0947\u0902 \u0926\u093F\u0916\u0947\u0902\u0917\u0947\u0964",
444
+ needsAnswerAny: "\u092F\u0939\u093E\u0901 \u092A\u094D\u0930\u0936\u094D\u0928 \u092A\u0942\u091B\u0947\u0902, \u0914\u0930 \u0905\u0935\u0924\u093E\u0930 \u0909\u0924\u094D\u0924\u0930 \u091C\u093C\u094B\u0930 \u0938\u0947 \u092A\u0922\u093C\u0947\u0917\u093E\u0964",
445
+ startNewChatDetailAny: "\u0905\u0935\u0924\u093E\u0930 \u0915\u0947\u0935\u0932 \u0905\u0935\u0924\u093E\u0930 \u091F\u0948\u092C \u092E\u0947\u0902 \u0936\u0941\u0930\u0942 \u0915\u0940 \u0917\u0908 \u0928\u0908 \u091A\u0948\u091F \u0915\u093E \u092A\u0939\u0932\u093E \u0909\u0924\u094D\u0924\u0930 \u091C\u093C\u094B\u0930 \u0938\u0947 \u092A\u0922\u093C\u0924\u093E \u0939\u0948, \u092C\u0936\u0930\u094D\u0924\u0947 \u0935\u0939 \u0935\u093E\u0923\u0940 \u091C\u093E\u0901\u091A \u092E\u0947\u0902 \u092A\u093E\u0938 \u0939\u094B\u0964",
446
+ notEligibleAny: "\u0905\u0935\u0924\u093E\u0930 \u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u091C\u093C\u094B\u0930 \u0938\u0947 \u0928\u0939\u0940\u0902 \u092A\u0922\u093C \u0938\u0915\u0924\u093E\u0964 \u0909\u0924\u094D\u0924\u0930 \u0914\u0930 \u0938\u094D\u0930\u094B\u0924 \u091A\u0948\u091F \u092E\u0947\u0902 \u0939\u0948\u0902\u0964"
359
447
  };
360
448
  var ES = {
361
449
  checking: "Comprobando si el avatar en vivo est\xE1 disponible\u2026",
@@ -389,7 +477,32 @@ var ES = {
389
477
  paused: "El avatar en vivo est\xE1 en pausa en este momento.",
390
478
  // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
391
479
  notEligible: "El avatar lee la primera respuesta a una pregunta sugerida, en un plazo de quince minutos. Inicia un chat nuevo y elige una pregunta sugerida.",
392
- answerClaimed: "El avatar ya ha le\xEDdo esta respuesta."
480
+ answerClaimed: "El avatar ya ha le\xEDdo esta respuesta.",
481
+ // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.
482
+ askHeadline: "Haz una pregunta y el avatar leer\xE1 la respuesta en voz alta.",
483
+ askLabel: "Pregunta para el avatar",
484
+ askPlaceholder: "Pregunta al avatar\u2026",
485
+ askFooter: "Las respuestas las genera la IA y pueden contener errores. No incluyas datos personales.",
486
+ askNoFiles: "Para adjuntar archivos, usa el chat.",
487
+ askBusy: "Podr\xE1s preguntar cuando la respuesta actual est\xE9 lista.",
488
+ askUnavailable: "El chat no est\xE1 disponible en este momento.",
489
+ gettingAnswer: "Obteniendo la respuesta\u2026",
490
+ startWhenReady: "Iniciar cuando est\xE9 lista",
491
+ armed: "El avatar empezar\xE1 cuando la respuesta est\xE9 lista.",
492
+ cancel: "Cancelar",
493
+ armedCancelled: "El avatar no se ha iniciado. Pulsa Iniciar cuando est\xE9 lista para volver a intentarlo.",
494
+ notSpoken: "Esta respuesta se queda en el chat como texto. El avatar solo lee respuestas que superan sus comprobaciones de voz.",
495
+ answerFailed: "El asistente no pudo responder. Vuelve a preguntar.",
496
+ declined: "De acuerdo. La respuesta est\xE1 en el chat.",
497
+ askHere: "Para escuchar una respuesta, pregunta aqu\xED.",
498
+ newChatForAvatar: "Chat nuevo para el avatar",
499
+ newChatNote: "Tu chat actual se queda en el historial.",
500
+ newChatStarted: "Se ha iniciado un chat nuevo para el avatar.",
501
+ readInChat: "Leer la respuesta y las fuentes en el chat",
502
+ usedToday: "Ya has usado la sesi\xF3n de avatar de hoy. Las respuestas se mostrar\xE1n aqu\xED como texto.",
503
+ needsAnswerAny: "Haz una pregunta aqu\xED y el avatar leer\xE1 la respuesta en voz alta.",
504
+ startNewChatDetailAny: "El avatar solo lee en voz alta la primera respuesta de un chat nuevo iniciado en la pesta\xF1a Avatar, si supera las comprobaciones de voz.",
505
+ notEligibleAny: "El avatar no puede leer esta respuesta en voz alta. La respuesta y las fuentes est\xE1n en el chat."
393
506
  };
394
507
  var AR = {
395
508
  checking: "\u062C\u0627\u0631\u064D \u0627\u0644\u062A\u062D\u0642\u0642 \u0645\u0646 \u062A\u0648\u0641\u0631 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631\u2026",
@@ -423,7 +536,32 @@ var AR = {
423
536
  paused: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631 \u0645\u062A\u0648\u0642\u0641 \u0645\u0624\u0642\u062A\u064B\u0627 \u0627\u0644\u0622\u0646.",
424
537
  // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
425
538
  notEligible: "\u064A\u0642\u0631\u0623 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0627\u0644\u0623\u0648\u0644\u0649 \u0639\u0646 \u0633\u0624\u0627\u0644 \u0645\u0642\u062A\u0631\u062D\u060C \u062E\u0644\u0627\u0644 \u062E\u0645\u0633 \u0639\u0634\u0631\u0629 \u062F\u0642\u064A\u0642\u0629. \u0627\u0628\u062F\u0623 \u062F\u0631\u062F\u0634\u0629 \u062C\u062F\u064A\u062F\u0629 \u0648\u0627\u062E\u062A\u0631 \u0633\u0624\u0627\u0644\u064B\u0627 \u0645\u0642\u062A\u0631\u062D\u064B\u0627.",
426
- answerClaimed: "\u0642\u0631\u0623 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0645\u0646 \u0642\u0628\u0644."
539
+ answerClaimed: "\u0642\u0631\u0623 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0645\u0646 \u0642\u0628\u0644.",
540
+ // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.
541
+ askHeadline: "\u0627\u0637\u0631\u062D \u0633\u0624\u0627\u0644\u064B\u0627\u060C \u0648\u0633\u064A\u0642\u0631\u0623 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0628\u0635\u0648\u062A \u0639\u0627\u0644\u064D.",
542
+ askLabel: "\u0633\u0624\u0627\u0644 \u0644\u0644\u0623\u0641\u0627\u062A\u0627\u0631",
543
+ askPlaceholder: "\u0627\u0633\u0623\u0644 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631\u2026",
544
+ askFooter: "\u0627\u0644\u0625\u062C\u0627\u0628\u0627\u062A \u0645\u064F\u0648\u0644\u064E\u0651\u062F\u0629 \u0628\u0627\u0644\u0630\u0643\u0627\u0621 \u0627\u0644\u0627\u0635\u0637\u0646\u0627\u0639\u064A \u0648\u0642\u062F \u062A\u0643\u0648\u0646 \u062E\u0627\u0637\u0626\u0629. \u0644\u0627 \u062A\u0636\u0645\u0651\u0646 \u0628\u064A\u0627\u0646\u0627\u062A \u0634\u062E\u0635\u064A\u0629.",
545
+ askNoFiles: "\u0644\u0625\u0631\u0641\u0627\u0642 \u0645\u0644\u0641\u0627\u062A\u060C \u0627\u0633\u062A\u062E\u062F\u0645 \u0627\u0644\u062F\u0631\u062F\u0634\u0629.",
546
+ askBusy: "\u064A\u0645\u0643\u0646\u0643 \u0627\u0644\u0633\u0624\u0627\u0644 \u0639\u0646\u062F\u0645\u0627 \u062A\u0635\u0628\u062D \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0627\u0644\u062D\u0627\u0644\u064A\u0629 \u062C\u0627\u0647\u0632\u0629.",
547
+ askUnavailable: "\u0627\u0644\u062F\u0631\u062F\u0634\u0629 \u063A\u064A\u0631 \u0645\u062A\u0627\u062D\u0629 \u0627\u0644\u0622\u0646.",
548
+ gettingAnswer: "\u062C\u0627\u0631\u064D \u0627\u0644\u062D\u0635\u0648\u0644 \u0639\u0644\u0649 \u0627\u0644\u0625\u062C\u0627\u0628\u0629\u2026",
549
+ startWhenReady: "\u0627\u0644\u0628\u062F\u0621 \u0639\u0646\u062F \u0627\u0644\u062C\u0627\u0647\u0632\u064A\u0629",
550
+ armed: "\u0633\u064A\u0628\u062F\u0623 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0639\u0646\u062F\u0645\u0627 \u062A\u0635\u0628\u062D \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u062C\u0627\u0647\u0632\u0629.",
551
+ cancel: "\u0625\u0644\u063A\u0627\u0621",
552
+ armedCancelled: "\u0644\u0645 \u064A\u0628\u062F\u0623 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631. \u0627\u0636\u063A\u0637 \u0639\u0644\u0649 \u0627\u0644\u0628\u062F\u0621 \u0639\u0646\u062F \u0627\u0644\u062C\u0627\u0647\u0632\u064A\u0629 \u0644\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.",
553
+ notSpoken: "\u062A\u0628\u0642\u0649 \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0641\u064A \u0627\u0644\u062F\u0631\u062F\u0634\u0629 \u0646\u0635\u064B\u0627. \u064A\u0642\u0631\u0623 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0641\u0642\u0637 \u0627\u0644\u0625\u062C\u0627\u0628\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u062C\u062A\u0627\u0632 \u0641\u062D\u0648\u0635 \u0627\u0644\u0646\u0637\u0642.",
554
+ answerFailed: "\u062A\u0639\u0630\u0651\u0631 \u0639\u0644\u0649 \u0627\u0644\u0645\u0633\u0627\u0639\u062F \u0627\u0644\u0625\u062C\u0627\u0628\u0629. \u062D\u0627\u0648\u0644 \u0627\u0644\u0633\u0624\u0627\u0644 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.",
555
+ declined: "\u0644\u0627 \u0628\u0623\u0633. \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0645\u0648\u062C\u0648\u062F\u0629 \u0641\u064A \u0627\u0644\u062F\u0631\u062F\u0634\u0629.",
556
+ askHere: "\u0644\u0633\u0645\u0627\u0639 \u0625\u062C\u0627\u0628\u0629\u060C \u0627\u0633\u0623\u0644 \u0647\u0646\u0627.",
557
+ newChatForAvatar: "\u062F\u0631\u062F\u0634\u0629 \u062C\u062F\u064A\u062F\u0629 \u0644\u0644\u0623\u0641\u0627\u062A\u0627\u0631",
558
+ newChatNote: "\u062A\u0628\u0642\u0649 \u062F\u0631\u062F\u0634\u062A\u0643 \u0627\u0644\u062D\u0627\u0644\u064A\u0629 \u0641\u064A \u0627\u0644\u0633\u062C\u0644.",
559
+ newChatStarted: "\u0628\u062F\u0623\u062A \u062F\u0631\u062F\u0634\u0629 \u062C\u062F\u064A\u062F\u0629 \u0644\u0644\u0623\u0641\u0627\u062A\u0627\u0631.",
560
+ readInChat: "\u0627\u0642\u0631\u0623 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0648\u0627\u0644\u0645\u0635\u0627\u062F\u0631 \u0641\u064A \u0627\u0644\u062F\u0631\u062F\u0634\u0629",
561
+ usedToday: "\u0644\u0642\u062F \u0627\u0633\u062A\u062E\u062F\u0645\u062A \u062C\u0644\u0633\u0629 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0644\u0647\u0630\u0627 \u0627\u0644\u064A\u0648\u0645. \u0633\u062A\u0638\u0647\u0631 \u0627\u0644\u0625\u062C\u0627\u0628\u0627\u062A \u0647\u0646\u0627 \u0646\u0635\u064B\u0627.",
562
+ needsAnswerAny: "\u0627\u0637\u0631\u062D \u0633\u0624\u0627\u0644\u064B\u0627 \u0647\u0646\u0627\u060C \u0648\u0633\u064A\u0642\u0631\u0623 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0628\u0635\u0648\u062A \u0639\u0627\u0644\u064D.",
563
+ startNewChatDetailAny: "\u064A\u0642\u0631\u0623 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0628\u0635\u0648\u062A \u0639\u0627\u0644\u064D \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0627\u0644\u0623\u0648\u0644\u0649 \u0641\u0642\u0637 \u0641\u064A \u062F\u0631\u062F\u0634\u0629 \u062C\u062F\u064A\u062F\u0629 \u0628\u062F\u0623\u062A \u0641\u064A \u0639\u0644\u0627\u0645\u0629 \u062A\u0628\u0648\u064A\u0628 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631\u060C \u0628\u0634\u0631\u0637 \u0623\u0646 \u062A\u062C\u062A\u0627\u0632 \u0641\u062D\u0648\u0635 \u0627\u0644\u0646\u0637\u0642.",
564
+ notEligibleAny: "\u0644\u0627 \u064A\u0645\u0643\u0646 \u0644\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0642\u0631\u0627\u0621\u0629 \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0628\u0635\u0648\u062A \u0639\u0627\u0644\u064D. \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0648\u0627\u0644\u0645\u0635\u0627\u062F\u0631 \u0645\u0648\u062C\u0648\u062F\u0629 \u0641\u064A \u0627\u0644\u062F\u0631\u062F\u0634\u0629."
427
565
  };
428
566
  var TA = {
429
567
  checking: "\u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0B95\u0BBF\u0B9F\u0BC8\u0B95\u0BCD\u0B95\u0BBF\u0BB1\u0BA4\u0BBE \u0B8E\u0BA9\u0B9A\u0BCD \u0B9A\u0BB0\u0BBF\u0BAA\u0BBE\u0BB0\u0BCD\u0B95\u0BCD\u0B95\u0BBF\u0BB1\u0BA4\u0BC1\u2026",
@@ -457,7 +595,32 @@ var TA = {
457
595
  paused: "\u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0B87\u0BAA\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1 \u0B87\u0B9F\u0BC8\u0BA8\u0BBF\u0BB1\u0BC1\u0BA4\u0BCD\u0BA4\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F\u0BC1\u0BB3\u0BCD\u0BB3\u0BA4\u0BC1.",
458
596
  // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
459
597
  notEligible: "\u0BAA\u0BB0\u0BBF\u0BA8\u0BCD\u0BA4\u0BC1\u0BB0\u0BC8\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0BA4\u0BB2\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0BAE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAE\u0BC7, \u0BAA\u0BA4\u0BBF\u0BA9\u0BC8\u0BA8\u0BCD\u0BA4\u0BC1 \u0BA8\u0BBF\u0BAE\u0BBF\u0B9F\u0B99\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BC1\u0BB3\u0BCD, \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BAA\u0B9F\u0BBF\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD. \u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BC8\u0BA4\u0BCD \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BBF, \u0BAA\u0BB0\u0BBF\u0BA8\u0BCD\u0BA4\u0BC1\u0BB0\u0BC8\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F \u0B92\u0BB0\u0BC1 \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0BAF\u0BC8\u0BA4\u0BCD \u0BA4\u0BC7\u0BB0\u0BCD\u0BA8\u0BCD\u0BA4\u0BC6\u0B9F\u0BC1\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD.",
460
- answerClaimed: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0B8F\u0BB1\u0BCD\u0B95\u0BC6\u0BA9\u0BB5\u0BC7 \u0BAA\u0B9F\u0BBF\u0BA4\u0BCD\u0BA4\u0BC1\u0BB5\u0BBF\u0B9F\u0BCD\u0B9F\u0BA4\u0BC1."
598
+ answerClaimed: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0B8F\u0BB1\u0BCD\u0B95\u0BC6\u0BA9\u0BB5\u0BC7 \u0BAA\u0B9F\u0BBF\u0BA4\u0BCD\u0BA4\u0BC1\u0BB5\u0BBF\u0B9F\u0BCD\u0B9F\u0BA4\u0BC1.",
599
+ // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.
600
+ askHeadline: "\u0B92\u0BB0\u0BC1 \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0BAF\u0BC8\u0B95\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD, \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0B89\u0BB0\u0B95\u0BCD\u0B95\u0BAA\u0BCD \u0BAA\u0B9F\u0BBF\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD.",
601
+ askLabel: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF",
602
+ askPlaceholder: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BBF\u0B9F\u0BAE\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD\u2026",
603
+ askFooter: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BCD AI \u0B89\u0BB0\u0BC1\u0BB5\u0BBE\u0B95\u0BCD\u0B95\u0BBF\u0BAF\u0BB5\u0BC8, \u0BA4\u0BB5\u0BB1\u0BBE\u0B95 \u0B87\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BB2\u0BBE\u0BAE\u0BCD. \u0BA4\u0BA9\u0BBF\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F \u0BB5\u0BBF\u0BB5\u0BB0\u0B99\u0BCD\u0B95\u0BB3\u0BC8\u0B9A\u0BCD \u0B9A\u0BC7\u0BB0\u0BCD\u0B95\u0BCD\u0B95 \u0BB5\u0BC7\u0BA3\u0BCD\u0B9F\u0BBE\u0BAE\u0BCD.",
604
+ askNoFiles: "\u0B95\u0BCB\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BC8 \u0B87\u0BA3\u0BC8\u0B95\u0BCD\u0B95, \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BC8\u0BAA\u0BCD \u0BAA\u0BAF\u0BA9\u0BCD\u0BAA\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BB5\u0BC1\u0BAE\u0BCD.",
605
+ askBusy: "\u0BA4\u0BB1\u0BCD\u0BAA\u0BCB\u0BA4\u0BC8\u0BAF \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0BA4\u0BAF\u0BBE\u0BB0\u0BBE\u0BA9\u0BA4\u0BC1\u0BAE\u0BCD \u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B95\u0BB2\u0BBE\u0BAE\u0BCD.",
606
+ askUnavailable: "\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8 \u0B87\u0BAA\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1 \u0B95\u0BBF\u0B9F\u0BC8\u0B95\u0BCD\u0B95\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8.",
607
+ gettingAnswer: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BC8\u0BAA\u0BCD \u0BAA\u0BC6\u0BB1\u0BC1\u0B95\u0BBF\u0BB1\u0BA4\u0BC1\u2026",
608
+ startWhenReady: "\u0BA4\u0BAF\u0BBE\u0BB0\u0BBE\u0BA9\u0BA4\u0BC1\u0BAE\u0BCD \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BC1",
609
+ armed: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0BA4\u0BAF\u0BBE\u0BB0\u0BBE\u0BA9\u0BA4\u0BC1\u0BAE\u0BCD \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BC1\u0BAE\u0BCD.",
610
+ cancel: "\u0BB0\u0BA4\u0BCD\u0BA4\u0BC1\u0B9A\u0BC6\u0BAF\u0BCD",
611
+ armedCancelled: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8. \u0BAE\u0BC0\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD \u0BAE\u0BC1\u0BAF\u0BB2, \u0BA4\u0BAF\u0BBE\u0BB0\u0BBE\u0BA9\u0BA4\u0BC1\u0BAE\u0BCD \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BC1 \u0B8E\u0BA9\u0BCD\u0BAA\u0BA4\u0BC8 \u0B85\u0BB4\u0BC1\u0BA4\u0BCD\u0BA4\u0BB5\u0BC1\u0BAE\u0BCD.",
612
+ notSpoken: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0B89\u0BB0\u0BC8\u0BAF\u0BBE\u0B95\u0BB5\u0BC7 \u0B87\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD. \u0BAA\u0BC7\u0B9A\u0BCD\u0B9A\u0BC1\u0B9A\u0BCD \u0B9A\u0BB0\u0BBF\u0BAA\u0BBE\u0BB0\u0BCD\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BBF\u0BB2\u0BCD \u0BA4\u0BC7\u0BB1\u0BC1\u0BAE\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BC8 \u0BAE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAE\u0BC7 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BAA\u0B9F\u0BBF\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD.",
613
+ answerFailed: "\u0B89\u0BA4\u0BB5\u0BBF\u0BAF\u0BBE\u0BB3\u0BB0\u0BBE\u0BB2\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BB3\u0BBF\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8. \u0BAE\u0BC0\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B9F\u0BC1\u0BAA\u0BCD \u0BAA\u0BBE\u0BB0\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD.",
614
+ declined: "\u0BAA\u0BB0\u0BB5\u0BBE\u0BAF\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8. \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0B89\u0BB3\u0BCD\u0BB3\u0BA4\u0BC1.",
615
+ askHere: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BC8\u0B95\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B95, \u0B87\u0B99\u0BCD\u0B95\u0BC7 \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD.",
616
+ newChatForAvatar: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8",
617
+ newChatNote: "\u0B89\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BA4\u0BB1\u0BCD\u0BAA\u0BCB\u0BA4\u0BC8\u0BAF \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8 \u0BB5\u0BB0\u0BB2\u0BBE\u0BB1\u0BCD\u0BB1\u0BBF\u0BB2\u0BCD \u0B87\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD.",
618
+ newChatStarted: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0B95\u0BAA\u0BCD \u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8 \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F\u0BA4\u0BC1.",
619
+ readInChat: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BC8\u0BAF\u0BC1\u0BAE\u0BCD \u0B86\u0BA4\u0BBE\u0BB0\u0B99\u0BCD\u0B95\u0BB3\u0BC8\u0BAF\u0BC1\u0BAE\u0BCD \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0BAA\u0B9F\u0BBF\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD",
620
+ usedToday: "\u0B87\u0BA9\u0BCD\u0BB1\u0BC8\u0BAF \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0B85\u0BAE\u0BB0\u0BCD\u0BB5\u0BC8 \u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BAA\u0BAF\u0BA9\u0BCD\u0BAA\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BBF\u0BB5\u0BBF\u0B9F\u0BCD\u0B9F\u0BC0\u0BB0\u0BCD\u0B95\u0BB3\u0BCD. \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BCD \u0B87\u0B99\u0BCD\u0B95\u0BC7 \u0B89\u0BB0\u0BC8\u0BAF\u0BBE\u0B95\u0B95\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BC1\u0BAE\u0BCD.",
621
+ needsAnswerAny: "\u0B87\u0B99\u0BCD\u0B95\u0BC7 \u0B92\u0BB0\u0BC1 \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0BAF\u0BC8\u0B95\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD, \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0B89\u0BB0\u0B95\u0BCD\u0B95\u0BAA\u0BCD \u0BAA\u0B9F\u0BBF\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD.",
622
+ startNewChatDetailAny: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BA4\u0BBE\u0BB5\u0BB2\u0BBF\u0BB2\u0BCD \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BBF\u0BAF \u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BBF\u0BA9\u0BCD \u0BAE\u0BC1\u0BA4\u0BB2\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0BAE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAE\u0BC7, \u0B85\u0BA4\u0BC1 \u0BAA\u0BC7\u0B9A\u0BCD\u0B9A\u0BC1\u0B9A\u0BCD \u0B9A\u0BB0\u0BBF\u0BAA\u0BBE\u0BB0\u0BCD\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BBF\u0BB2\u0BCD \u0BA4\u0BC7\u0BB1\u0BBF\u0BA9\u0BBE\u0BB2\u0BCD, \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0B89\u0BB0\u0B95\u0BCD\u0B95\u0BAA\u0BCD \u0BAA\u0B9F\u0BBF\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD.",
623
+ notEligibleAny: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BBE\u0BB2\u0BCD \u0B89\u0BB0\u0B95\u0BCD\u0B95\u0BAA\u0BCD \u0BAA\u0B9F\u0BBF\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BBE\u0BA4\u0BC1. \u0BAA\u0BA4\u0BBF\u0BB2\u0BC1\u0BAE\u0BCD \u0B86\u0BA4\u0BBE\u0BB0\u0B99\u0BCD\u0B95\u0BB3\u0BC1\u0BAE\u0BCD \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0B89\u0BB3\u0BCD\u0BB3\u0BA9."
461
624
  };
462
625
  var STRINGS = {
463
626
  en: EN,
@@ -481,7 +644,8 @@ var CONSENT = /* @__PURE__ */ new Map([
481
644
  processing: "When you start, Cloudflare checks for bots. The answer text goes to Google to create the voice. Your browser connects to LiveKit, which sees your IP address. LiveKit fetches our temporary audio file and passes the voice to Protoface, which makes the avatar video streamed through LiveKit.",
482
645
  storage: "Your microphone and camera are not used. We do not record the live session. We temporarily store the generated voice file and keep a record of this consent. The privacy notice explains our safeguards, storage periods and the providers' processing. For people aged eighteen and over.",
483
646
  privacyLink: "How we handle this",
484
- botCheck: "turnstile"
647
+ botCheck: "turnstile",
648
+ questions: "suggested"
485
649
  }
486
650
  }
487
651
  ],
@@ -496,7 +660,8 @@ var CONSENT = /* @__PURE__ */ new Map([
496
660
  processing: "When you start, Cloudflare checks for bots. The answer text goes to Google to create the voice. Our server sends that voice through LiveKit to Protoface, which makes the avatar video streamed through LiveKit. Your browser connects to LiveKit, which sees your IP address.",
497
661
  storage: "Your microphone and camera are not used. We do not record the live session or store the generated voice. We keep a record of this consent. The privacy notice explains our safeguards, storage periods and the providers' processing. For people aged eighteen and over.",
498
662
  privacyLink: "How we handle this",
499
- botCheck: "turnstile"
663
+ botCheck: "turnstile",
664
+ questions: "suggested"
500
665
  }
501
666
  }
502
667
  ],
@@ -512,7 +677,8 @@ var CONSENT = /* @__PURE__ */ new Map([
512
677
  processing: "When you start, Cloudflare checks for bots. The answer text goes to Google to create the voice. Our server sends that voice through LiveKit to Protoface, which makes the avatar video streamed through LiveKit. Your browser connects to LiveKit, which sees your IP address.",
513
678
  storage: "Your microphone and camera are not used. We do not record the live session or store the generated voice. We keep a record of this consent. The privacy notice explains our safeguards, storage periods and the providers' processing. For people aged eighteen and over.",
514
679
  privacyLink: "How we handle this",
515
- botCheck: "turnstile"
680
+ botCheck: "turnstile",
681
+ questions: "suggested"
516
682
  }
517
683
  }
518
684
  ],
@@ -528,13 +694,50 @@ var CONSENT = /* @__PURE__ */ new Map([
528
694
  processing: "The answer text goes to Google to create the voice. Our server sends that voice through LiveKit to Protoface, which makes the avatar video streamed through LiveKit. Your browser connects to LiveKit, which sees your IP address.",
529
695
  storage: "Your microphone and camera are not used. We do not record the live session or store the generated voice. We keep a record of this consent. The privacy notice explains our safeguards, storage periods and the providers' processing. For people aged eighteen and over.",
530
696
  privacyLink: "How we handle this",
531
- botCheck: "off"
697
+ botCheck: "off",
698
+ questions: "suggested"
699
+ }
700
+ }
701
+ ],
702
+ [
703
+ // The Avatar tab's own question box (contract v1.3, `questions: "any"`): the first answer in a new chat started in
704
+ // the Avatar tab is read whether the visitor chose a suggested question or typed their own, so the intro says so and
705
+ // warns against personal details in a typed one. Product-neutral, with the bot check: one notice and one digest for
706
+ // every site (gitops docs/avatar-web/en-web-consent-2026-11-05.txt).
707
+ "web-consent-2026-11-05",
708
+ {
709
+ en: {
710
+ title: "Live AI avatar (beta)",
711
+ introProduct: null,
712
+ intro: "This is an AI avatar, not a real person. It reads aloud, for up to a minute, the first answer in a new chat started in the Avatar tab, provided it passes the speech checks, whether you chose a suggested question or typed your own. The answer is AI-generated and can be wrong. Don't put personal details in a question you type.",
713
+ processing: "When you start, Cloudflare checks for bots. The answer text goes to Google to create the voice. Our server sends that voice through LiveKit to Protoface, which makes the avatar video streamed through LiveKit. Your browser connects to LiveKit, which sees your IP address.",
714
+ storage: "Your microphone and camera are not used. We do not record the live session or store the generated voice. We keep a record of this consent. The privacy notice explains our safeguards, storage periods and the providers' processing. For people aged eighteen and over.",
715
+ privacyLink: "How we handle this",
716
+ botCheck: "turnstile",
717
+ questions: "any"
718
+ }
719
+ }
720
+ ],
721
+ [
722
+ // The words of web-consent-2026-11-05 without "When you start, Cloudflare checks for bots.", for a server that runs
723
+ // no bot check (gitops docs/avatar-web/en-web-consent-2026-11-06.txt).
724
+ "web-consent-2026-11-06",
725
+ {
726
+ en: {
727
+ title: "Live AI avatar (beta)",
728
+ introProduct: null,
729
+ intro: "This is an AI avatar, not a real person. It reads aloud, for up to a minute, the first answer in a new chat started in the Avatar tab, provided it passes the speech checks, whether you chose a suggested question or typed your own. The answer is AI-generated and can be wrong. Don't put personal details in a question you type.",
730
+ processing: "The answer text goes to Google to create the voice. Our server sends that voice through LiveKit to Protoface, which makes the avatar video streamed through LiveKit. Your browser connects to LiveKit, which sees your IP address.",
731
+ storage: "Your microphone and camera are not used. We do not record the live session or store the generated voice. We keep a record of this consent. The privacy notice explains our safeguards, storage periods and the providers' processing. For people aged eighteen and over.",
732
+ privacyLink: "How we handle this",
733
+ botCheck: "off",
734
+ questions: "any"
532
735
  }
533
736
  }
534
737
  ]
535
738
  ]);
536
739
  function avatarConsentCopy(version, locale) {
537
- if (!chunkFQH3AJN3_js.isAvatarLiveLocaleReviewed(locale)) return null;
740
+ if (!chunk7O2I32ZN_js.isAvatarLiveLocaleReviewed(locale)) return null;
538
741
  return CONSENT.get(version)?.[locale] ?? null;
539
742
  }
540
743
 
@@ -659,6 +862,9 @@ var CLOCK_TOLERANCE_MS = 5e3;
659
862
  var SERVICE_MAX_AGE_MS = 15 * 6e4;
660
863
  var ANSWER_OFFER_MS = SERVICE_MAX_AGE_MS - 6e4;
661
864
  var MAX_TIMER_MS = 2147483647;
865
+ var ASK_MAX_LENGTH = 300;
866
+ var MAX_REFERENCES = 64;
867
+ var USED_ON_KEY = "boff.explore.avatarUsedOn";
662
868
  var PRIMARY = '[data-avatar-primary], [data-boff-explore="panel-continue-chat"]';
663
869
  var IDLE = { name: "idle" };
664
870
  var INERT2 = { name: "inert" };
@@ -671,12 +877,26 @@ var REFUSAL_TEXT = {
671
877
  not_eligible: "notEligible",
672
878
  answer_claimed: "answerClaimed"
673
879
  };
674
- var WAITING = { answerId: null, startOver: false, offerUntil: NaN };
675
- var START_OVER = {
880
+ var EMPTY = {
881
+ kind: "empty",
676
882
  answerId: null,
677
- startOver: true,
678
- offerUntil: NaN
883
+ startOver: false,
884
+ offerUntil: NaN,
885
+ question: null,
886
+ pendingAnswerId: null,
887
+ askedHere: false
679
888
  };
889
+ var START_OVER = { ...EMPTY, kind: "start-over", startOver: true };
890
+ var SUGGESTED_RULES = {
891
+ any: false,
892
+ askedHere: null,
893
+ token: null,
894
+ inFlight: false
895
+ };
896
+ function isAskedHere(question, rules) {
897
+ const asked = rules.askedHere;
898
+ return rules.any && asked !== null && question.id === asked.messageId && asked.token === rules.token;
899
+ }
680
900
  function createdAtOf(message) {
681
901
  const raw = message.createdAt;
682
902
  return typeof raw === "string" && raw !== "" ? Date.parse(raw) : NaN;
@@ -684,25 +904,110 @@ function createdAtOf(message) {
684
904
  function offeredAt(exchange, now) {
685
905
  return exchange.answerId !== null && !(now < exchange.offerUntil) ? START_OVER : exchange;
686
906
  }
687
- function firstExchange(messages) {
688
- if (!messages || messages.length === 0) return WAITING;
907
+ function readable(question, answer) {
908
+ const references = answer.references?.length ?? 0;
909
+ return answer.answered === true && references >= 1 && references <= MAX_REFERENCES && (question.attachments?.length ?? 0) === 0;
910
+ }
911
+ function firstExchange(messages, rules = SUGGESTED_RULES) {
912
+ if (!messages || messages.length === 0) return EMPTY;
689
913
  if (messages.length > 2) return START_OVER;
690
914
  const [question, answer] = messages;
691
915
  if (question?.role !== "USER") return START_OVER;
692
- if (answer === void 0) return WAITING;
916
+ const first = { question, askedHere: isAskedHere(question, rules) };
917
+ if (answer === void 0) {
918
+ if (rules.inFlight) return { ...EMPTY, ...first, kind: "asking" };
919
+ return rules.any ? { ...START_OVER, ...first, kind: "failed" } : EMPTY;
920
+ }
693
921
  if (answer.role !== "ASSISTANT") return START_OVER;
694
922
  if (answer.status === "PENDING" || answer.status === "RUNNING") {
695
- return WAITING;
923
+ return {
924
+ ...EMPTY,
925
+ ...first,
926
+ kind: "asking",
927
+ pendingAnswerId: isAvatarMessageId(answer.id) ? answer.id : null
928
+ };
929
+ }
930
+ if (rules.any && answer.status === "FAILED") {
931
+ return { ...START_OVER, ...first, kind: "failed" };
696
932
  }
697
933
  if (answer.status !== "COMPLETED" || answer.content.trim() === "" || !isAvatarMessageId(answer.id)) {
698
934
  return START_OVER;
699
935
  }
936
+ if (rules.any && !first.askedHere) {
937
+ return { ...START_OVER, ...first, kind: "ask-here" };
938
+ }
939
+ if (rules.any && !readable(question, answer)) {
940
+ return { ...START_OVER, ...first, kind: "text-only" };
941
+ }
700
942
  return {
943
+ ...EMPTY,
944
+ ...first,
945
+ kind: "answer",
701
946
  answerId: answer.id,
702
- startOver: false,
703
947
  offerUntil: createdAtOf(answer) + ANSWER_OFFER_MS
704
948
  };
705
949
  }
950
+ function inFlight(conversation) {
951
+ return conversation?.phase === "sending" || conversation?.phase === "streaming";
952
+ }
953
+ function utcToday() {
954
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
955
+ }
956
+ function usedTodayHere() {
957
+ try {
958
+ return window.localStorage.getItem(USED_ON_KEY) === utcToday();
959
+ } catch {
960
+ return false;
961
+ }
962
+ }
963
+ function noteUsedToday() {
964
+ try {
965
+ window.localStorage.setItem(USED_ON_KEY, utcToday());
966
+ } catch {
967
+ }
968
+ }
969
+ var silence = null;
970
+ function silentWav() {
971
+ if (silence !== null) return silence;
972
+ const rate = 8e3;
973
+ const samples = rate / 10;
974
+ const bytes = new Uint8Array(44 + samples);
975
+ const view = new DataView(bytes.buffer);
976
+ const text = (at, value) => {
977
+ for (let i = 0; i < value.length; i += 1) {
978
+ bytes[at + i] = value.charCodeAt(i);
979
+ }
980
+ };
981
+ text(0, "RIFF");
982
+ view.setUint32(4, 36 + samples, true);
983
+ text(8, "WAVE");
984
+ text(12, "fmt ");
985
+ view.setUint32(16, 16, true);
986
+ view.setUint16(20, 1, true);
987
+ view.setUint16(22, 1, true);
988
+ view.setUint32(24, rate, true);
989
+ view.setUint32(28, rate, true);
990
+ view.setUint16(32, 1, true);
991
+ view.setUint16(34, 8, true);
992
+ text(36, "data");
993
+ view.setUint32(40, samples, true);
994
+ bytes.fill(128, 44);
995
+ let binary = "";
996
+ for (const byte of bytes) binary += String.fromCharCode(byte);
997
+ silence = `data:audio/wav;base64,${btoa(binary)}`;
998
+ return silence;
999
+ }
1000
+ function unlockSound(audio) {
1001
+ if (audio === null || audio.srcObject) return;
1002
+ try {
1003
+ audio.src = silentWav();
1004
+ void Promise.resolve(audio.play()).then(
1005
+ () => audio.pause(),
1006
+ () => void 0
1007
+ );
1008
+ } catch {
1009
+ }
1010
+ }
706
1011
  function offering(offer, messageId, claimed) {
707
1012
  return claimed.has(messageId) ? { name: "refused", reason: "answer_claimed" } : { name: "consent", offer, messageId };
708
1013
  }
@@ -728,6 +1033,11 @@ function AvatarLiveView({
728
1033
  onContinueInChat,
729
1034
  continueInChat,
730
1035
  newChat,
1036
+ send,
1037
+ tryAsking,
1038
+ prompts,
1039
+ touchFirst,
1040
+ currentPath,
731
1041
  off,
732
1042
  base,
733
1043
  headers,
@@ -736,18 +1046,46 @@ function AvatarLiveView({
736
1046
  const S = avatarLiveStrings(locale);
737
1047
  const uid = react.useId();
738
1048
  const consentTitleId = `${uid}-consent`;
739
- const exchange = firstExchange(conversation?.messages);
1049
+ const [questions, setQuestions] = react.useState("suggested");
1050
+ const questionsRef = react.useRef("suggested");
1051
+ const askedHereRef = react.useRef(null);
1052
+ const askSeqRef = react.useRef(0);
1053
+ const [, setAskedHereTick] = react.useState(0);
1054
+ const setAskedHere = react.useCallback((next) => {
1055
+ if (next === null) {
1056
+ askSeqRef.current += 1;
1057
+ if (askedHereRef.current === null) return;
1058
+ }
1059
+ askedHereRef.current = next;
1060
+ setAskedHereTick((tick) => tick + 1);
1061
+ }, []);
1062
+ const token = conversation?.getConversationToken() ?? null;
1063
+ const exchange = firstExchange(conversation?.messages, {
1064
+ any: questions === "any",
1065
+ askedHere: askedHereRef.current,
1066
+ token,
1067
+ inFlight: inFlight(conversation)
1068
+ });
740
1069
  const [ageTick, setAgeTick] = react.useState(0);
741
- const { answerId, startOver } = offeredAt(exchange, Date.now());
1070
+ const shown = offeredAt(exchange, Date.now());
1071
+ const { answerId, startOver } = shown;
742
1072
  const offerUntil = answerId === null ? null : exchange.offerUntil;
743
1073
  const [phase, setPhase] = react.useState(IDLE);
744
1074
  const [blocked, setBlocked] = react.useState(false);
745
1075
  const [now, setNow] = react.useState(() => Date.now());
1076
+ const [draft, setDraft] = react.useState("");
1077
+ const chatMaxLength = conversation?.catalog.limits.maxMessageLength;
1078
+ const askMaxLength = chatMaxLength !== void 0 && Number.isFinite(chatMaxLength) && chatMaxLength >= 1 ? Math.min(ASK_MAX_LENGTH, Math.floor(chatMaxLength)) : ASK_MAX_LENGTH;
1079
+ const [note, setNote] = react.useState(null);
1080
+ const [usedToday, setUsedToday] = react.useState(false);
746
1081
  const phaseRef = react.useRef(IDLE);
747
- const latest = react.useRef({ live, locale, base, headers, exchange, off });
748
- latest.current = { live, locale, base, headers, exchange, off };
1082
+ const latest = react.useRef({ live, locale, base, headers, off, currentPath });
1083
+ latest.current = { live, locale, base, headers, off, currentPath };
749
1084
  const conversationRef = react.useRef(conversation);
750
1085
  conversationRef.current = conversation;
1086
+ const waitRef = react.useRef(null);
1087
+ const sendingRef = react.useRef(false);
1088
+ const textBoxRef = react.useRef(false);
751
1089
  const checkRef = react.useRef(null);
752
1090
  const askedLocale = react.useRef(locale);
753
1091
  const startRef = react.useRef(null);
@@ -761,8 +1099,28 @@ function AvatarLiveView({
761
1099
  phaseRef.current = next;
762
1100
  setPhase(next);
763
1101
  }, []);
1102
+ const setMode = react.useCallback((next) => {
1103
+ questionsRef.current = next;
1104
+ setQuestions(next);
1105
+ }, []);
1106
+ const exchangeNow = react.useCallback(
1107
+ () => offeredAt(
1108
+ firstExchange(conversationRef.current?.messages, {
1109
+ any: questionsRef.current === "any",
1110
+ askedHere: askedHereRef.current,
1111
+ token: conversationRef.current?.getConversationToken() ?? null,
1112
+ inFlight: inFlight(conversationRef.current)
1113
+ }),
1114
+ Date.now()
1115
+ ),
1116
+ []
1117
+ );
764
1118
  const offeredNow = react.useCallback(
765
- () => offeredAt(latest.current.exchange, Date.now()).answerId,
1119
+ () => exchangeNow().answerId,
1120
+ [exchangeNow]
1121
+ );
1122
+ const pathNow = react.useCallback(
1123
+ () => latest.current.currentPath ?? (typeof window === "undefined" ? "" : window.location.pathname),
766
1124
  []
767
1125
  );
768
1126
  const reoffer = react.useCallback(
@@ -802,6 +1160,36 @@ function AvatarLiveView({
802
1160
  run.cancelled = reason;
803
1161
  run.turnstile?.cancel();
804
1162
  }, []);
1163
+ const applyAvailability = react.useCallback(
1164
+ (result, locale2) => {
1165
+ const { live: live2 } = latest.current;
1166
+ if (result.kind === "inert") {
1167
+ setMode("suggested");
1168
+ go(INERT2);
1169
+ return;
1170
+ }
1171
+ if (result.kind === "refused") {
1172
+ setMode(result.questions);
1173
+ go({ name: "refused", reason: result.reason });
1174
+ return;
1175
+ }
1176
+ setUsedToday(usedTodayHere());
1177
+ const copy = avatarConsentCopy(result.offer.consentVersion, locale2);
1178
+ if (copy === null || copy.botCheck !== result.offer.botCheck || copy.questions !== result.offer.questions) {
1179
+ setMode("suggested");
1180
+ go(INERT2);
1181
+ return;
1182
+ }
1183
+ if (result.offer.botCheck === "turnstile" && chunk7O2I32ZN_js.turnstileSiteKeyOf(live2) === null) {
1184
+ setMode("suggested");
1185
+ go(INERT2);
1186
+ return;
1187
+ }
1188
+ setMode(result.offer.questions);
1189
+ go(reoffer({ ...result.offer, locale: locale2, copy }));
1190
+ },
1191
+ [go, reoffer, setMode]
1192
+ );
805
1193
  const check = react.useCallback(() => {
806
1194
  const { live: live2, locale: locale2, base: base2, headers: headers2, off: off2 } = latest.current;
807
1195
  checkRef.current?.abort();
@@ -823,26 +1211,9 @@ function AvatarLiveView({
823
1211
  }).then((result) => {
824
1212
  if (checkRef.current !== controller) return;
825
1213
  checkRef.current = null;
826
- if (result.kind === "inert") {
827
- go(INERT2);
828
- return;
829
- }
830
- if (result.kind === "refused") {
831
- go({ name: "refused", reason: result.reason });
832
- return;
833
- }
834
- const copy = avatarConsentCopy(result.offer.consentVersion, locale2);
835
- if (copy === null || copy.botCheck !== result.offer.botCheck) {
836
- go(INERT2);
837
- return;
838
- }
839
- if (result.offer.botCheck === "turnstile" && chunkFQH3AJN3_js.turnstileSiteKeyOf(live2) === null) {
840
- go(INERT2);
841
- return;
842
- }
843
- go(reoffer({ ...result.offer, locale: locale2, copy }));
1214
+ applyAvailability(result, locale2);
844
1215
  });
845
- }, [go, reoffer]);
1216
+ }, [applyAvailability, go]);
846
1217
  const begin = react.useCallback(
847
1218
  (session, module, offer, target) => {
848
1219
  const received = Date.now();
@@ -887,8 +1258,8 @@ function AvatarLiveView({
887
1258
  reason: run.cancelled
888
1259
  });
889
1260
  }
890
- const shown = phaseRef.current;
891
- if (claimed && shown.name === "consent" && shown.messageId === context.messageId) {
1261
+ const shown2 = phaseRef.current;
1262
+ if (claimed && shown2.name === "consent" && shown2.messageId === context.messageId) {
892
1263
  go({ name: "refused", reason: "answer_claimed" });
893
1264
  }
894
1265
  return;
@@ -923,86 +1294,186 @@ function AvatarLiveView({
923
1294
  },
924
1295
  [begin, check, go]
925
1296
  );
1297
+ const launch = react.useCallback(
1298
+ (offer, messageId, preloaded) => {
1299
+ const { live: live2, base: base2, headers: headers2 } = latest.current;
1300
+ if (base2 === null) return;
1301
+ const exchangeAtStart = exchangeNow();
1302
+ if (exchangeAtStart.answerId !== messageId) {
1303
+ go(reoffer(offer));
1304
+ return;
1305
+ }
1306
+ if (claimedRef.current.has(messageId)) {
1307
+ go({ name: "refused", reason: "answer_claimed" });
1308
+ return;
1309
+ }
1310
+ const refusedFrom = exchangeAtStart.offerUntil - ANSWER_OFFER_MS + SERVICE_MAX_AGE_MS;
1311
+ const siteKey = offer.botCheck === "turnstile" ? chunk7O2I32ZN_js.turnstileSiteKeyOf(live2) : null;
1312
+ if (offer.botCheck === "turnstile" && (siteKey === null || !canBindBotCheck())) {
1313
+ go(INERT2);
1314
+ return;
1315
+ }
1316
+ const conversationToken = conversationRef.current?.getConversationToken() ?? null;
1317
+ const idempotencyKey = newIdempotencyKey();
1318
+ if (conversationToken === null || !isAvatarConversationToken(conversationToken) || idempotencyKey === null) {
1319
+ go({ name: "ended", how: "failed" });
1320
+ return;
1321
+ }
1322
+ const body2 = {
1323
+ site: live2.site,
1324
+ locale: offer.locale,
1325
+ conversationToken,
1326
+ messageId,
1327
+ consentVersion: offer.consentVersion,
1328
+ manifestVersion: live2.manifestVersion
1329
+ };
1330
+ const run = { cancelled: null, turnstile: null };
1331
+ startRef.current = run;
1332
+ const module = preloaded ?? loadModule(live2.load);
1333
+ let turnstile = null;
1334
+ if (siteKey === null) {
1335
+ go({ name: "creating" });
1336
+ } else {
1337
+ go({ name: "bot-check", offer, messageId });
1338
+ turnstile = runTurnstile(
1339
+ botBoxRef.current,
1340
+ siteKey,
1341
+ "avatar_start",
1342
+ avatarBotBinding(body2)
1343
+ );
1344
+ run.turnstile = turnstile;
1345
+ }
1346
+ void (async () => {
1347
+ let loaded;
1348
+ let botToken;
1349
+ try {
1350
+ [loaded, botToken] = await Promise.all([module, turnstile?.token]);
1351
+ } catch {
1352
+ turnstile?.cancel();
1353
+ if (run.cancelled === null) {
1354
+ startRef.current = null;
1355
+ go(INERT2);
1356
+ }
1357
+ return;
1358
+ }
1359
+ turnstile?.cancel();
1360
+ if (run.cancelled !== null) return;
1361
+ if (!(Date.now() < refusedFrom)) {
1362
+ startRef.current = null;
1363
+ go({ name: "needs-answer", offer });
1364
+ return;
1365
+ }
1366
+ if (turnstile !== null) go({ name: "creating" });
1367
+ const result = await requestCreate({
1368
+ base: base2,
1369
+ headers: headers2,
1370
+ idempotencyKey,
1371
+ botToken,
1372
+ body: body2
1373
+ });
1374
+ if (startRef.current === run) startRef.current = null;
1375
+ settle(result, run, {
1376
+ module: loaded,
1377
+ offer,
1378
+ messageId,
1379
+ base: base2,
1380
+ headers: headers2
1381
+ });
1382
+ })();
1383
+ },
1384
+ [exchangeNow, go, reoffer, settle]
1385
+ );
926
1386
  const start = react.useCallback(() => {
927
1387
  const current = phaseRef.current;
928
1388
  if (current.name !== "consent") return;
929
- const { live: live2, base: base2, headers: headers2 } = latest.current;
930
- if (base2 === null) return;
931
- const { offer, messageId } = current;
932
- if (offeredNow() !== messageId) {
933
- go(reoffer(offer));
934
- return;
935
- }
936
- const refusedFrom = latest.current.exchange.offerUntil - ANSWER_OFFER_MS + SERVICE_MAX_AGE_MS;
937
- const siteKey = offer.botCheck === "turnstile" ? chunkFQH3AJN3_js.turnstileSiteKeyOf(live2) : null;
938
- if (offer.botCheck === "turnstile" && (siteKey === null || !canBindBotCheck())) {
939
- go(INERT2);
940
- return;
941
- }
942
- const conversationToken = conversationRef.current?.getConversationToken() ?? null;
943
- const idempotencyKey = newIdempotencyKey();
944
- if (conversationToken === null || !isAvatarConversationToken(conversationToken) || idempotencyKey === null) {
945
- go({ name: "ended", how: "failed" });
1389
+ if (current.offer.questions === "any") unlockSound(audioRef.current);
1390
+ launch(current.offer, current.messageId, null);
1391
+ }, [launch]);
1392
+ const cancelWaiting = react.useCallback(
1393
+ (told) => {
1394
+ const wait = waitRef.current;
1395
+ waitRef.current = null;
1396
+ wait?.check?.abort();
1397
+ const current = phaseRef.current;
1398
+ if (current.name !== "waiting") return;
1399
+ if (told) setNote("cancelled");
1400
+ go({ name: "needs-answer", offer: current.offer });
1401
+ },
1402
+ [go]
1403
+ );
1404
+ const bindingHolds = react.useCallback(
1405
+ (bound, exchange2) => {
1406
+ const { live: live2, locale: locale2 } = latest.current;
1407
+ return conversationRef.current?.getConversationToken() === bound.token && exchange2.question?.id === bound.questionId && live2.site === bound.site && locale2 === bound.locale && pathNow() === bound.path;
1408
+ },
1409
+ [pathNow]
1410
+ );
1411
+ const startWhenReady = react.useCallback(() => {
1412
+ const current = phaseRef.current;
1413
+ if (current.name !== "needs-answer") return;
1414
+ const { live: live2, locale: locale2 } = latest.current;
1415
+ const exchange2 = exchangeNow();
1416
+ const token2 = conversationRef.current?.getConversationToken() ?? null;
1417
+ if (exchange2.kind !== "asking" || !exchange2.askedHere || exchange2.question === null || exchange2.pendingAnswerId === null || token2 === null || !isAvatarConversationToken(token2)) {
946
1418
  return;
947
1419
  }
948
- const body2 = {
949
- site: live2.site,
950
- locale: offer.locale,
951
- conversationToken,
952
- messageId,
953
- consentVersion: offer.consentVersion,
954
- manifestVersion: live2.manifestVersion
955
- };
956
- const run = { cancelled: null, turnstile: null };
957
- startRef.current = run;
1420
+ unlockSound(audioRef.current);
958
1421
  const module = loadModule(live2.load);
959
- let turnstile = null;
960
- if (siteKey === null) {
961
- go({ name: "creating" });
962
- } else {
963
- go({ name: "bot-check", offer, messageId });
964
- turnstile = runTurnstile(
965
- botBoxRef.current,
966
- siteKey,
967
- "avatar_start",
968
- avatarBotBinding(body2)
969
- );
970
- run.turnstile = turnstile;
971
- }
972
- void (async () => {
973
- let loaded;
974
- let botToken;
975
- try {
976
- [loaded, botToken] = await Promise.all([module, turnstile?.token]);
977
- } catch {
978
- turnstile?.cancel();
979
- if (run.cancelled === null) {
980
- startRef.current = null;
981
- go(INERT2);
982
- }
983
- return;
984
- }
985
- turnstile?.cancel();
986
- if (run.cancelled !== null) return;
987
- if (!(Date.now() < refusedFrom)) {
988
- startRef.current = null;
989
- go({ name: "needs-answer", offer });
1422
+ module.catch(() => void 0);
1423
+ waitRef.current = {
1424
+ bound: {
1425
+ token: token2,
1426
+ questionId: exchange2.question.id,
1427
+ answerId: exchange2.pendingAnswerId,
1428
+ site: live2.site,
1429
+ locale: locale2,
1430
+ path: pathNow(),
1431
+ consentVersion: current.offer.consentVersion,
1432
+ botCheck: current.offer.botCheck
1433
+ },
1434
+ module,
1435
+ check: null
1436
+ };
1437
+ setNote(null);
1438
+ go({ name: "waiting", offer: current.offer });
1439
+ }, [exchangeNow, go, pathNow]);
1440
+ const confirm = react.useCallback(
1441
+ (offer, wait) => {
1442
+ const { live: live2, locale: locale2, base: base2, headers: headers2 } = latest.current;
1443
+ if (base2 === null) {
1444
+ cancelWaiting(true);
990
1445
  return;
991
1446
  }
992
- if (turnstile !== null) go({ name: "creating" });
993
- const result = await requestCreate({
1447
+ const controller = new AbortController();
1448
+ wait.check = controller;
1449
+ void requestAvailability({
994
1450
  base: base2,
995
1451
  headers: headers2,
996
- idempotencyKey,
997
- botToken,
998
- body: body2
1452
+ site: live2.site,
1453
+ locale: locale2,
1454
+ signal: controller.signal
1455
+ }).then((result) => {
1456
+ if (waitRef.current !== wait || phaseRef.current.name !== "waiting") {
1457
+ return;
1458
+ }
1459
+ waitRef.current = null;
1460
+ const exchange2 = exchangeNow();
1461
+ const same = result.kind === "available" && result.offer.consentVersion === wait.bound.consentVersion && result.offer.botCheck === wait.bound.botCheck && result.offer.questions === "any" && exchange2.kind === "answer" && exchange2.answerId === wait.bound.answerId && bindingHolds(wait.bound, exchange2);
1462
+ if (!same || result.kind !== "available") {
1463
+ applyAvailability(result, locale2);
1464
+ return;
1465
+ }
1466
+ launch({ ...offer, ...result.offer }, wait.bound.answerId, wait.module);
999
1467
  });
1000
- if (startRef.current === run) startRef.current = null;
1001
- settle(result, run, { module: loaded, offer, messageId, base: base2, headers: headers2 });
1002
- })();
1003
- }, [go, offeredNow, reoffer, settle]);
1468
+ },
1469
+ [applyAvailability, bindingHolds, cancelWaiting, exchangeNow, launch]
1470
+ );
1004
1471
  const stop = react.useCallback(() => {
1005
1472
  const current = phaseRef.current;
1473
+ if (current.name === "waiting") {
1474
+ cancelWaiting(false);
1475
+ return;
1476
+ }
1006
1477
  if (current.name === "bot-check") {
1007
1478
  cancelStart("user");
1008
1479
  go(reoffer(current.offer));
@@ -1016,7 +1487,7 @@ function AvatarLiveView({
1016
1487
  if (current.name === "pending" || current.name === "live") {
1017
1488
  finish("stopped", "user");
1018
1489
  }
1019
- }, [cancelStart, finish, go, reoffer]);
1490
+ }, [cancelStart, cancelWaiting, finish, go, reoffer]);
1020
1491
  const leave = react.useCallback(
1021
1492
  (reason) => {
1022
1493
  const current = phaseRef.current;
@@ -1030,6 +1501,9 @@ function AvatarLiveView({
1030
1501
  go(IDLE);
1031
1502
  return;
1032
1503
  }
1504
+ case "waiting":
1505
+ cancelWaiting(true);
1506
+ return;
1033
1507
  case "bot-check":
1034
1508
  cancelStart(reason);
1035
1509
  go(reason === "user" ? IDLE : reoffer(current.offer));
@@ -1046,7 +1520,7 @@ function AvatarLiveView({
1046
1520
  return;
1047
1521
  }
1048
1522
  },
1049
- [cancelStart, finish, go, reoffer]
1523
+ [cancelStart, cancelWaiting, finish, go, reoffer]
1050
1524
  );
1051
1525
  const showing = active && !off;
1052
1526
  react.useEffect(() => {
@@ -1061,7 +1535,7 @@ function AvatarLiveView({
1061
1535
  if (current.name === "refused" && current.reason === "answer_claimed" && used) {
1062
1536
  return;
1063
1537
  }
1064
- if (current.name === "idle" || current.name === "inert" || current.name === "refused" || current.name === "needs-answer" || current.name === "consent" || current.name === "ended" || // Asking, with nothing actually asking: React's strict mode unmounts and mounts a component again with the state it
1538
+ if (current.name === "idle" || current.name === "inert" || current.name === "refused" || current.name === "needs-answer" || current.name === "consent" || current.name === "declined" || current.name === "ended" || // Asking, with nothing actually asking: React's strict mode unmounts and mounts a component again with the state it
1065
1539
  // left, and the unmount in between dropped the question. (This view mounts already showing, the first time the
1066
1540
  // Avatar view opens.)
1067
1541
  current.name === "checking" && checkRef.current === null) {
@@ -1071,8 +1545,9 @@ function AvatarLiveView({
1071
1545
  react.useEffect(() => {
1072
1546
  if (askedLocale.current === locale) return;
1073
1547
  askedLocale.current = locale;
1548
+ if (phaseRef.current.name === "waiting") cancelWaiting(true);
1074
1549
  const current = phaseRef.current.name;
1075
- if (current !== "checking" && current !== "needs-answer" && current !== "consent" && current !== "refused" && current !== "inert") {
1550
+ if (current !== "checking" && current !== "needs-answer" && current !== "consent" && current !== "declined" && current !== "refused" && current !== "inert") {
1076
1551
  return;
1077
1552
  }
1078
1553
  if (active) {
@@ -1082,7 +1557,8 @@ function AvatarLiveView({
1082
1557
  checkRef.current = null;
1083
1558
  go(IDLE);
1084
1559
  }
1085
- }, [active, check, go, locale]);
1560
+ }, [active, cancelWaiting, check, go, locale]);
1561
+ const kind = shown.kind;
1086
1562
  react.useEffect(() => {
1087
1563
  const current = phaseRef.current;
1088
1564
  if (current.name === "needs-answer" && answerId !== null) {
@@ -1091,8 +1567,49 @@ function AvatarLiveView({
1091
1567
  go(
1092
1568
  answerId === null ? { name: "needs-answer", offer: current.offer } : { ...current, messageId: answerId }
1093
1569
  );
1570
+ } else if (current.name === "declined" && answerId === null) {
1571
+ if (kind !== "asking") go({ name: "needs-answer", offer: current.offer });
1094
1572
  }
1095
- }, [answerId, go]);
1573
+ }, [answerId, kind, go]);
1574
+ react.useEffect(() => {
1575
+ const current = phaseRef.current;
1576
+ const wait = waitRef.current;
1577
+ if (current.name !== "waiting" || wait === null || wait.check !== null) {
1578
+ return;
1579
+ }
1580
+ const now2 = exchangeNow();
1581
+ const holds = bindingHolds(wait.bound, now2);
1582
+ if (holds && now2.kind === "asking" && now2.pendingAnswerId === wait.bound.answerId) {
1583
+ return;
1584
+ }
1585
+ if (!holds || now2.kind !== "answer" || now2.answerId !== wait.bound.answerId) {
1586
+ cancelWaiting(now2.kind !== "failed" && now2.kind !== "text-only");
1587
+ return;
1588
+ }
1589
+ confirm(current.offer, wait);
1590
+ });
1591
+ const resent = conversation?.resent ?? null;
1592
+ react.useEffect(() => {
1593
+ const asked = askedHereRef.current;
1594
+ if (resent === null || asked === null || !resent.replacedMessageIds.includes(asked.messageId)) {
1595
+ return;
1596
+ }
1597
+ setAskedHere({
1598
+ messageId: resent.sent.userMessageId,
1599
+ token: resent.sent.conversationToken
1600
+ });
1601
+ }, [resent, setAskedHere]);
1602
+ const empty = (conversation?.messages.length ?? 0) === 0;
1603
+ react.useEffect(() => {
1604
+ if (empty) setAskedHere(null);
1605
+ }, [empty, setAskedHere]);
1606
+ react.useEffect(() => {
1607
+ const asked = askedHereRef.current;
1608
+ if (asked !== null && asked.token !== token) setAskedHere(null);
1609
+ }, [token, setAskedHere]);
1610
+ react.useEffect(() => {
1611
+ if (showing) setUsedToday(usedTodayHere());
1612
+ }, [showing]);
1096
1613
  react.useEffect(() => {
1097
1614
  if (offerUntil === null) return;
1098
1615
  const timer = setTimeout(
@@ -1226,6 +1743,9 @@ function AvatarLiveView({
1226
1743
  run.cancelled = "user";
1227
1744
  run.turnstile?.cancel();
1228
1745
  }
1746
+ const wait = waitRef.current;
1747
+ waitRef.current = null;
1748
+ wait?.check?.abort();
1229
1749
  const handle = sessionRef.current;
1230
1750
  sessionRef.current = null;
1231
1751
  if (handle && !handle.done) {
@@ -1242,17 +1762,82 @@ function AvatarLiveView({
1242
1762
  },
1243
1763
  []
1244
1764
  );
1765
+ const any = questions === "any";
1766
+ const textMode = any && (usedToday && (phase.name === "needs-answer" || phase.name === "consent" || phase.name === "declined" || phase.name === "ended") || phase.name === "refused" && phase.reason === "limits");
1767
+ textBoxRef.current = textMode;
1768
+ const askState = !any ? void 0 : textMode ? "text" : phase.name === "needs-answer" ? kind === "empty" ? "ready" : kind : phase.name;
1769
+ const notNow = react.useCallback(() => {
1770
+ const current = phaseRef.current;
1771
+ if ((current.name === "consent" || current.name === "needs-answer") && current.offer.questions === "any") {
1772
+ go({ name: "declined", offer: current.offer });
1773
+ return;
1774
+ }
1775
+ onContinueInChat();
1776
+ }, [go, onContinueInChat]);
1777
+ const ask = react.useCallback(
1778
+ (text) => {
1779
+ const conversation2 = conversationRef.current;
1780
+ const question = text.trim();
1781
+ if (conversation2 === null || question === "" || sendingRef.current) {
1782
+ return;
1783
+ }
1784
+ const spoken = !textBoxRef.current;
1785
+ if (spoken && conversation2.messages.length > 0) return;
1786
+ sendingRef.current = true;
1787
+ setAskedHere(null);
1788
+ const seq = askSeqRef.current;
1789
+ setNote(null);
1790
+ setDraft("");
1791
+ void conversation2.send(question, [], spoken ? { surface: "AVATAR" } : {}).then((added) => {
1792
+ if (added === null) {
1793
+ setDraft((current) => current === "" ? question : current);
1794
+ }
1795
+ if (!spoken || added === null || askSeqRef.current !== seq || added.conversationToken !== (conversationRef.current?.getConversationToken() ?? null)) {
1796
+ return;
1797
+ }
1798
+ setAskedHere({
1799
+ messageId: added.userMessageId,
1800
+ token: added.conversationToken
1801
+ });
1802
+ }).finally(() => {
1803
+ sendingRef.current = false;
1804
+ });
1805
+ },
1806
+ [setAskedHere]
1807
+ );
1808
+ const newChatForAvatar = react.useCallback(() => {
1809
+ const conversation2 = conversationRef.current;
1810
+ if (conversation2 === null) return;
1811
+ const now2 = exchangeNow();
1812
+ const failedQuestion = now2.kind === "failed" ? now2.question?.content ?? null : null;
1813
+ conversation2.reset();
1814
+ setAskedHere(null);
1815
+ setNote("new-chat");
1816
+ if (failedQuestion !== null) {
1817
+ setDraft((current2) => current2 === "" ? failedQuestion : current2);
1818
+ }
1819
+ const current = phaseRef.current;
1820
+ if (current.name === "needs-answer" || current.name === "consent" || current.name === "declined") {
1821
+ go({ name: "needs-answer", offer: current.offer });
1822
+ } else {
1823
+ check();
1824
+ }
1825
+ }, [check, exchangeNow, go, setAskedHere]);
1245
1826
  react.useEffect(() => {
1246
1827
  if (!active) return;
1247
1828
  const focused = document.activeElement;
1248
1829
  if (focused && focused !== document.body && focused.isConnected) return;
1249
1830
  rootRef.current?.querySelector(PRIMARY)?.focus();
1250
- }, [active, phase.name, blocked]);
1831
+ }, [active, phase.name, askState, shown.pendingAnswerId, blocked]);
1251
1832
  const onPlaying = react.useCallback(() => {
1252
1833
  const current = phaseRef.current;
1253
1834
  const handle = sessionRef.current;
1254
1835
  if (current.name !== "pending" || !handle) return;
1255
1836
  handle.speakerArrived = true;
1837
+ if (questionsRef.current === "any") {
1838
+ noteUsedToday();
1839
+ setUsedToday(true);
1840
+ }
1256
1841
  go({ name: "live", session: current.session });
1257
1842
  }, [go]);
1258
1843
  const enablePlayback = react.useCallback(() => {
@@ -1285,7 +1870,7 @@ function AvatarLiveView({
1285
1870
  height: small ? 64 : 128,
1286
1871
  className: chunkC6OJIHNO_js.cn(
1287
1872
  "shrink-0 rounded-full border border-border object-cover shadow-sm",
1288
- small ? "h-16 w-16" : "h-32 w-32"
1873
+ small ? "h-16 w-16" : any ? "h-[min(12rem,32dvh)] w-[min(12rem,32dvh)]" : "h-32 w-32"
1289
1874
  )
1290
1875
  }
1291
1876
  );
@@ -1334,12 +1919,440 @@ function AvatarLiveView({
1334
1919
  children: S.stop
1335
1920
  }
1336
1921
  );
1922
+ const readInChatButton = (primary) => /* @__PURE__ */ jsxRuntime.jsx(
1923
+ "button",
1924
+ {
1925
+ type: "button",
1926
+ "data-avatar-primary": primary ? "" : void 0,
1927
+ "data-boff-explore": "avatar-live-read-in-chat",
1928
+ className: primary ? primaryButton : secondaryButton,
1929
+ onClick: onContinueInChat,
1930
+ children: S.readInChat
1931
+ }
1932
+ );
1933
+ const consentCard = (copy) => /* @__PURE__ */ jsxRuntime.jsxs(
1934
+ "section",
1935
+ {
1936
+ "aria-labelledby": consentTitleId,
1937
+ "data-boff-explore": "avatar-live-consent",
1938
+ className: "w-full max-w-sm rounded-lg border border-border p-4 text-start",
1939
+ children: [
1940
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { id: consentTitleId, className: "text-base font-semibold", children: copy.title }),
1941
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm", children: productName === null || copy.introProduct === null ? copy.intro : chunkO4GS3XPZ_js.fill(copy.introProduct, { product: productName }) }),
1942
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: copy.processing }),
1943
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: copy.storage }),
1944
+ /* @__PURE__ */ jsxRuntime.jsxs(
1945
+ "a",
1946
+ {
1947
+ href: PRIVACY_HREF,
1948
+ target: "_blank",
1949
+ rel: "noopener noreferrer",
1950
+ "data-boff-explore": "avatar-live-privacy",
1951
+ className: "mt-2 inline-block text-sm font-medium text-primary underline underline-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1952
+ children: [
1953
+ copy.privacyLink,
1954
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sr-only", children: [
1955
+ " ",
1956
+ S.opensInNewTab
1957
+ ] })
1958
+ ]
1959
+ }
1960
+ )
1961
+ ]
1962
+ }
1963
+ );
1964
+ const consentActions = (whenReady) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
1965
+ /* @__PURE__ */ jsxRuntime.jsx(
1966
+ "button",
1967
+ {
1968
+ type: "button",
1969
+ "data-avatar-primary": "",
1970
+ "data-boff-explore": whenReady ? "avatar-live-start-when-ready" : "avatar-live-start",
1971
+ className: primaryButton,
1972
+ onClick: whenReady ? startWhenReady : start,
1973
+ children: whenReady ? S.startWhenReady : S.start
1974
+ }
1975
+ ),
1976
+ /* @__PURE__ */ jsxRuntime.jsx(
1977
+ "button",
1978
+ {
1979
+ type: "button",
1980
+ "data-boff-explore": "avatar-live-not-now",
1981
+ className: secondaryButton,
1982
+ onClick: notNow,
1983
+ children: S.notNow
1984
+ }
1985
+ )
1986
+ ] });
1987
+ const liveMedia = (playing) => /* @__PURE__ */ jsxRuntime.jsxs(
1988
+ "div",
1989
+ {
1990
+ className: chunkC6OJIHNO_js.cn(
1991
+ "relative shrink-0 overflow-hidden rounded-xl border border-border bg-muted",
1992
+ any ? "h-[min(12rem,32dvh)] w-[min(12rem,32dvh)]" : "h-48 w-48"
1993
+ ),
1994
+ children: [
1995
+ /* @__PURE__ */ jsxRuntime.jsx(
1996
+ "video",
1997
+ {
1998
+ ref: videoRef,
1999
+ "aria-label": S.video,
2000
+ "data-boff-explore": "avatar-live-video",
2001
+ playsInline: true,
2002
+ autoPlay: true,
2003
+ muted: true,
2004
+ onPlaying,
2005
+ className: chunkC6OJIHNO_js.cn("h-full w-full object-cover", !playing && "opacity-0")
2006
+ }
2007
+ ),
2008
+ playing ? null : /* @__PURE__ */ jsxRuntime.jsx(
2009
+ "img",
2010
+ {
2011
+ src: still.src,
2012
+ alt: "",
2013
+ decoding: "async",
2014
+ className: "absolute inset-0 h-full w-full object-cover"
2015
+ }
2016
+ ),
2017
+ any ? null : /* @__PURE__ */ jsxRuntime.jsx("audio", { ref: audioRef, "data-boff-explore": "avatar-live-audio" })
2018
+ ]
2019
+ }
2020
+ );
2021
+ const liveBody = (session) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2022
+ /* @__PURE__ */ jsxRuntime.jsx(
2023
+ "section",
2024
+ {
2025
+ "aria-label": S.captions,
2026
+ "data-boff-explore": "avatar-live-captions",
2027
+ lang: session.captions.locale || void 0,
2028
+ dir: "auto",
2029
+ tabIndex: 0,
2030
+ className: "max-h-32 w-full max-w-sm overflow-y-auto rounded-lg bg-muted p-3 text-start text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2031
+ children: session.captions.text
2032
+ }
2033
+ ),
2034
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: S.answerInChat }),
2035
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm tabular-nums text-muted-foreground", children: [
2036
+ S.timeLeft,
2037
+ " ",
2038
+ /* @__PURE__ */ jsxRuntime.jsx("span", { role: "timer", "data-boff-explore": "avatar-live-countdown", children: clock(Math.max(0, (session.endsAt - now) / 1e3)) })
2039
+ ] })
2040
+ ] });
2041
+ const liveActions = (back) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
2042
+ blocked ? /* @__PURE__ */ jsxRuntime.jsx(
2043
+ "button",
2044
+ {
2045
+ type: "button",
2046
+ "data-boff-explore": "avatar-live-sound",
2047
+ className: primaryButton,
2048
+ onClick: enablePlayback,
2049
+ children: S.tapForSound
2050
+ }
2051
+ ) : null,
2052
+ stopButton,
2053
+ back
2054
+ ] });
2055
+ const badge = /* @__PURE__ */ jsxRuntime.jsx(
2056
+ "p",
2057
+ {
2058
+ "data-boff-explore": "avatar-live-badge",
2059
+ className: "rounded-full bg-muted px-3 py-1 text-xs font-medium text-foreground",
2060
+ children: S.badge
2061
+ }
2062
+ );
2063
+ if (any) {
2064
+ let status = "";
2065
+ let outcome2 = false;
2066
+ let lead = null;
2067
+ let top2 = null;
2068
+ let media2 = stillPicture(false);
2069
+ let body2 = null;
2070
+ let actions2 = null;
2071
+ let newChatOffer = false;
2072
+ let box = null;
2073
+ const first = exchange.question;
2074
+ const questionLine = first === null ? null : /* @__PURE__ */ jsxRuntime.jsx(
2075
+ "p",
2076
+ {
2077
+ "data-boff-explore": "avatar-live-question",
2078
+ dir: "auto",
2079
+ className: "line-clamp-2 w-full max-w-sm break-words text-sm font-medium",
2080
+ children: first.content
2081
+ }
2082
+ );
2083
+ const activity = conversation?.activity ?? null;
2084
+ const activityLine = activity === null ? null : /* @__PURE__ */ jsxRuntime.jsx(
2085
+ "p",
2086
+ {
2087
+ "data-boff-explore": "avatar-live-activity",
2088
+ className: "text-xs text-muted-foreground",
2089
+ children: activity
2090
+ }
2091
+ );
2092
+ if (textMode) {
2093
+ const messages = conversation?.messages ?? [];
2094
+ let questionAt = messages.length - 1;
2095
+ while (questionAt >= 0 && messages[questionAt]?.role !== "USER") {
2096
+ questionAt -= 1;
2097
+ }
2098
+ const lastQuestion = questionAt === -1 ? void 0 : messages[questionAt];
2099
+ const after = questionAt === -1 ? void 0 : messages[questionAt + 1];
2100
+ const lastAnswer = after?.role === "ASSISTANT" ? after : void 0;
2101
+ const chatPhase = conversation?.phase;
2102
+ const unanswered = lastQuestion === void 0 || lastAnswer !== void 0 ? null : chatPhase === "sending" || chatPhase === "streaming" ? "waiting" : chatPhase === "error" || chatPhase === "limited" ? "failed" : null;
2103
+ if (phase.name === "refused") {
2104
+ status = S[REFUSAL_TEXT[phase.reason]];
2105
+ outcome2 = true;
2106
+ } else if (phase.name === "ended") {
2107
+ status = S[phase.how];
2108
+ outcome2 = true;
2109
+ }
2110
+ body2 = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2111
+ lastQuestion === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(
2112
+ "p",
2113
+ {
2114
+ "data-boff-explore": "avatar-live-question",
2115
+ dir: "auto",
2116
+ className: "line-clamp-2 w-full max-w-sm break-words text-sm font-medium",
2117
+ children: lastQuestion.content
2118
+ }
2119
+ ),
2120
+ lastAnswer === void 0 ? unanswered === "waiting" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: activity ?? S.gettingAnswer }) : unanswered === "failed" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: S.answerFailed }) : null : lastAnswer.status === "PENDING" || lastAnswer.status === "RUNNING" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: activity ?? S.gettingAnswer }) : lastAnswer.status === "FAILED" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: S.answerFailed }) : /* @__PURE__ */ jsxRuntime.jsx(
2121
+ "p",
2122
+ {
2123
+ "data-boff-explore": "avatar-live-text-answer",
2124
+ dir: "auto",
2125
+ className: "line-clamp-6 w-full max-w-sm whitespace-pre-wrap break-words text-start text-sm",
2126
+ children: lastAnswer.content
2127
+ }
2128
+ )
2129
+ ] });
2130
+ const ended = phase.name === "ended";
2131
+ actions2 = lastAnswer === void 0 && unanswered !== "failed" && !ended ? null : readInChatButton(ended);
2132
+ box = "text";
2133
+ } else {
2134
+ switch (phase.name) {
2135
+ case "checking":
2136
+ status = S.checking;
2137
+ break;
2138
+ case "needs-answer":
2139
+ switch (shown.kind) {
2140
+ case "empty":
2141
+ status = note === "new-chat" ? S.newChatStarted : "";
2142
+ lead = /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold", children: S.askHeadline });
2143
+ box = "spoken";
2144
+ break;
2145
+ case "asking":
2146
+ case "answer": {
2147
+ const card = shown.askedHere && shown.pendingAnswerId !== null;
2148
+ status = note === "cancelled" ? S.armedCancelled : S.gettingAnswer;
2149
+ if (card) media2 = stillPicture(true);
2150
+ body2 = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2151
+ questionLine,
2152
+ activityLine,
2153
+ card ? consentCard(phase.offer.copy) : null
2154
+ ] });
2155
+ actions2 = card ? consentActions(true) : null;
2156
+ break;
2157
+ }
2158
+ case "text-only":
2159
+ status = S.notSpoken;
2160
+ outcome2 = true;
2161
+ body2 = questionLine;
2162
+ actions2 = readInChatButton(false);
2163
+ newChatOffer = true;
2164
+ break;
2165
+ case "failed":
2166
+ status = S.answerFailed;
2167
+ outcome2 = true;
2168
+ body2 = questionLine;
2169
+ newChatOffer = true;
2170
+ break;
2171
+ case "ask-here":
2172
+ status = S.askHere;
2173
+ outcome2 = true;
2174
+ actions2 = readInChatButton(false);
2175
+ newChatOffer = true;
2176
+ break;
2177
+ default:
2178
+ status = S.startNewChat;
2179
+ outcome2 = true;
2180
+ body2 = /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: S.startNewChatDetailAny });
2181
+ actions2 = readInChatButton(false);
2182
+ newChatOffer = true;
2183
+ break;
2184
+ }
2185
+ break;
2186
+ case "consent":
2187
+ media2 = stillPicture(true);
2188
+ body2 = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2189
+ questionLine,
2190
+ consentCard(phase.offer.copy)
2191
+ ] });
2192
+ actions2 = consentActions(false);
2193
+ break;
2194
+ case "declined":
2195
+ status = S.declined;
2196
+ actions2 = readInChatButton(true);
2197
+ break;
2198
+ case "waiting":
2199
+ status = S.armed;
2200
+ body2 = questionLine;
2201
+ actions2 = /* @__PURE__ */ jsxRuntime.jsx(
2202
+ "button",
2203
+ {
2204
+ type: "button",
2205
+ "data-avatar-primary": "",
2206
+ "data-boff-explore": "avatar-live-cancel",
2207
+ className: secondaryButton,
2208
+ onClick: stop,
2209
+ children: S.cancel
2210
+ }
2211
+ );
2212
+ break;
2213
+ case "refused":
2214
+ outcome2 = true;
2215
+ if (phase.reason === "not_eligible" || phase.reason === "answer_claimed") {
2216
+ status = phase.reason === "not_eligible" ? S.notEligibleAny : S.answerClaimed;
2217
+ actions2 = readInChatButton(false);
2218
+ newChatOffer = true;
2219
+ } else {
2220
+ status = S[REFUSAL_TEXT[phase.reason]];
2221
+ actions2 = continueButton;
2222
+ }
2223
+ break;
2224
+ case "bot-check":
2225
+ status = S.botCheck;
2226
+ actions2 = stopButton;
2227
+ break;
2228
+ case "creating":
2229
+ status = S.connecting;
2230
+ actions2 = stopButton;
2231
+ break;
2232
+ case "pending":
2233
+ case "live":
2234
+ status = phase.name === "live" ? S.speaking : S.connecting;
2235
+ top2 = badge;
2236
+ media2 = liveMedia(phase.name === "live");
2237
+ body2 = liveBody(phase.session);
2238
+ actions2 = liveActions(readInChatButton(false));
2239
+ break;
2240
+ case "ended":
2241
+ status = S[phase.how];
2242
+ outcome2 = true;
2243
+ actions2 = readInChatButton(true);
2244
+ newChatOffer = true;
2245
+ break;
2246
+ }
2247
+ }
2248
+ const reason = inFlight(conversation) ? S.askBusy : conversation?.canSend ? null : S.askUnavailable;
2249
+ const chips = box !== null && shown.kind === "empty" && prompts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
2250
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium text-muted-foreground", children: tryAsking }),
2251
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex max-h-28 flex-wrap gap-2 overflow-y-auto", children: prompts.map((prompt) => /* @__PURE__ */ jsxRuntime.jsx(
2252
+ "button",
2253
+ {
2254
+ type: "button",
2255
+ "data-boff-explore": "avatar-live-chip",
2256
+ "aria-disabled": reason !== null ? "true" : void 0,
2257
+ className: "min-h-11 rounded-full border border-border bg-background px-3 py-2 text-start text-sm text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring aria-disabled:cursor-not-allowed aria-disabled:opacity-50 motion-reduce:transition-none",
2258
+ onClick: () => {
2259
+ if (reason === null) ask(prompt);
2260
+ },
2261
+ children: prompt
2262
+ },
2263
+ prompt
2264
+ )) })
2265
+ ] }) : null;
2266
+ const foot = box === null && !newChatOffer ? null : /* @__PURE__ */ jsxRuntime.jsxs(
2267
+ "div",
2268
+ {
2269
+ "data-boff-explore": "avatar-live-foot",
2270
+ className: "flex shrink-0 flex-col gap-2 border-t border-border bg-background p-3 pb-[max(0.75rem,env(safe-area-inset-bottom))]",
2271
+ children: [
2272
+ newChatOffer ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1 text-center", children: [
2273
+ /* @__PURE__ */ jsxRuntime.jsx(
2274
+ "button",
2275
+ {
2276
+ type: "button",
2277
+ "data-avatar-primary": "",
2278
+ "data-boff-explore": "avatar-live-new-chat-avatar",
2279
+ className: chunkC6OJIHNO_js.cn(primaryButton, "min-h-11"),
2280
+ onClick: newChatForAvatar,
2281
+ children: S.newChatForAvatar
2282
+ }
2283
+ ),
2284
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: S.newChatNote })
2285
+ ] }) : null,
2286
+ chips,
2287
+ box !== null && usedToday ? /* @__PURE__ */ jsxRuntime.jsx(
2288
+ "p",
2289
+ {
2290
+ "data-boff-explore": "avatar-live-used-today",
2291
+ className: "text-xs text-muted-foreground",
2292
+ children: S.usedToday
2293
+ }
2294
+ ) : null,
2295
+ box === null ? null : /* @__PURE__ */ jsxRuntime.jsx(
2296
+ AskBox,
2297
+ {
2298
+ value: draft,
2299
+ maxLength: askMaxLength,
2300
+ onChange: setDraft,
2301
+ onAsk: ask,
2302
+ reason,
2303
+ label: S.askLabel,
2304
+ placeholder: S.askPlaceholder,
2305
+ send,
2306
+ footer: S.askFooter,
2307
+ noFiles: S.askNoFiles,
2308
+ hint: box === "spoken" ? S.needsAnswerAny : null,
2309
+ touchFirst
2310
+ }
2311
+ )
2312
+ ]
2313
+ }
2314
+ );
2315
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2316
+ "div",
2317
+ {
2318
+ ref: rootRef,
2319
+ "data-boff-explore": "avatar-live",
2320
+ "data-phase": phase.name,
2321
+ "data-ask": askState,
2322
+ className: "absolute inset-0 flex flex-col bg-background",
2323
+ children: [
2324
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 flex-col items-center gap-4 overflow-y-auto p-6 text-center", children: [
2325
+ top2,
2326
+ media2,
2327
+ lead,
2328
+ /* @__PURE__ */ jsxRuntime.jsx(
2329
+ "p",
2330
+ {
2331
+ role: "status",
2332
+ "data-boff-explore": "avatar-live-status",
2333
+ className: outcome2 ? "text-base font-semibold" : "text-sm text-muted-foreground",
2334
+ children: status
2335
+ }
2336
+ ),
2337
+ body2,
2338
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: botBoxRef, "data-boff-explore": "avatar-live-bot-check" }),
2339
+ actions2
2340
+ ] }),
2341
+ foot,
2342
+ /* @__PURE__ */ jsxRuntime.jsx("audio", { ref: audioRef, "data-boff-explore": "avatar-live-audio" })
2343
+ ]
2344
+ }
2345
+ );
2346
+ }
1337
2347
  const headline = {
1338
2348
  idle: "",
1339
2349
  checking: S.checking,
1340
2350
  inert: "",
1341
- "needs-answer": startOver ? S.startNewChat : S.needsAnswer,
2351
+ // A question asked and its answer on its way: the answer is coming (the avatar is offered once it completes).
2352
+ "needs-answer": startOver ? S.startNewChat : shown.kind === "asking" ? S.gettingAnswer : S.needsAnswer,
1342
2353
  consent: "",
2354
+ declined: S.declined,
2355
+ waiting: S.armed,
1343
2356
  refused: phase.name === "refused" ? S[REFUSAL_TEXT[phase.reason]] : "",
1344
2357
  "bot-check": S.botCheck,
1345
2358
  creating: S.connecting,
@@ -1357,65 +2370,11 @@ function AvatarLiveView({
1357
2370
  body = /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: startOver ? S.startNewChatDetail : S.needsAnswerDetail });
1358
2371
  actions = startOver ? startOverActions : continueButton;
1359
2372
  break;
1360
- case "consent": {
1361
- const { copy } = phase.offer;
2373
+ case "consent":
1362
2374
  media = stillPicture(true);
1363
- body = /* @__PURE__ */ jsxRuntime.jsxs(
1364
- "section",
1365
- {
1366
- "aria-labelledby": consentTitleId,
1367
- "data-boff-explore": "avatar-live-consent",
1368
- className: "w-full max-w-sm rounded-lg border border-border p-4 text-start",
1369
- children: [
1370
- /* @__PURE__ */ jsxRuntime.jsx("h2", { id: consentTitleId, className: "text-base font-semibold", children: copy.title }),
1371
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm", children: productName === null || copy.introProduct === null ? copy.intro : chunkO4GS3XPZ_js.fill(copy.introProduct, { product: productName }) }),
1372
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: copy.processing }),
1373
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: copy.storage }),
1374
- /* @__PURE__ */ jsxRuntime.jsxs(
1375
- "a",
1376
- {
1377
- href: PRIVACY_HREF,
1378
- target: "_blank",
1379
- rel: "noopener noreferrer",
1380
- "data-boff-explore": "avatar-live-privacy",
1381
- className: "mt-2 inline-block text-sm font-medium text-primary underline underline-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1382
- children: [
1383
- copy.privacyLink,
1384
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sr-only", children: [
1385
- " ",
1386
- S.opensInNewTab
1387
- ] })
1388
- ]
1389
- }
1390
- )
1391
- ]
1392
- }
1393
- );
1394
- actions = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
1395
- /* @__PURE__ */ jsxRuntime.jsx(
1396
- "button",
1397
- {
1398
- type: "button",
1399
- "data-avatar-primary": "",
1400
- "data-boff-explore": "avatar-live-start",
1401
- className: primaryButton,
1402
- onClick: start,
1403
- children: S.start
1404
- }
1405
- ),
1406
- /* @__PURE__ */ jsxRuntime.jsx(
1407
- "button",
1408
- {
1409
- type: "button",
1410
- "data-boff-explore": "avatar-live-not-now",
1411
- className: secondaryButton,
1412
- onClick: onContinueInChat,
1413
- children: S.notNow
1414
- }
1415
- )
1416
- ] });
2375
+ body = consentCard(phase.offer.copy);
2376
+ actions = consentActions(false);
1417
2377
  break;
1418
- }
1419
2378
  case "refused":
1420
2379
  actions = phase.reason === "not_eligible" ? startOverActions : continueButton;
1421
2380
  break;
@@ -1424,77 +2383,11 @@ function AvatarLiveView({
1424
2383
  actions = stopButton;
1425
2384
  break;
1426
2385
  case "pending":
1427
- case "live": {
1428
- const playing = phase.name === "live";
1429
- const left = Math.max(0, (phase.session.endsAt - now) / 1e3);
1430
- top = /* @__PURE__ */ jsxRuntime.jsx(
1431
- "p",
1432
- {
1433
- "data-boff-explore": "avatar-live-badge",
1434
- className: "rounded-full bg-muted px-3 py-1 text-xs font-medium text-foreground",
1435
- children: S.badge
1436
- }
1437
- );
1438
- media = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-48 w-48 shrink-0 overflow-hidden rounded-xl border border-border bg-muted", children: [
1439
- /* @__PURE__ */ jsxRuntime.jsx(
1440
- "video",
1441
- {
1442
- ref: videoRef,
1443
- "aria-label": S.video,
1444
- "data-boff-explore": "avatar-live-video",
1445
- playsInline: true,
1446
- autoPlay: true,
1447
- muted: true,
1448
- onPlaying,
1449
- className: chunkC6OJIHNO_js.cn(
1450
- "h-full w-full object-cover",
1451
- !playing && "opacity-0"
1452
- )
1453
- }
1454
- ),
1455
- playing ? null : /* @__PURE__ */ jsxRuntime.jsx(
1456
- "img",
1457
- {
1458
- src: still.src,
1459
- alt: "",
1460
- decoding: "async",
1461
- className: "absolute inset-0 h-full w-full object-cover"
1462
- }
1463
- ),
1464
- /* @__PURE__ */ jsxRuntime.jsx("audio", { ref: audioRef, "data-boff-explore": "avatar-live-audio" })
1465
- ] });
1466
- body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1467
- /* @__PURE__ */ jsxRuntime.jsx(
1468
- "section",
1469
- {
1470
- "aria-label": S.captions,
1471
- "data-boff-explore": "avatar-live-captions",
1472
- lang: phase.session.captions.locale || void 0,
1473
- dir: "auto",
1474
- tabIndex: 0,
1475
- className: "max-h-32 w-full max-w-sm overflow-y-auto rounded-lg bg-muted p-3 text-start text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1476
- children: phase.session.captions.text
1477
- }
1478
- ),
1479
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: S.answerInChat }),
1480
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm tabular-nums text-muted-foreground", children: [
1481
- S.timeLeft,
1482
- " ",
1483
- /* @__PURE__ */ jsxRuntime.jsx("span", { role: "timer", "data-boff-explore": "avatar-live-countdown", children: clock(left) })
1484
- ] })
1485
- ] });
1486
- actions = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
1487
- blocked ? /* @__PURE__ */ jsxRuntime.jsx(
1488
- "button",
1489
- {
1490
- type: "button",
1491
- "data-boff-explore": "avatar-live-sound",
1492
- className: primaryButton,
1493
- onClick: enablePlayback,
1494
- children: S.tapForSound
1495
- }
1496
- ) : null,
1497
- stopButton,
2386
+ case "live":
2387
+ top = badge;
2388
+ media = liveMedia(phase.name === "live");
2389
+ body = liveBody(phase.session);
2390
+ actions = liveActions(
1498
2391
  /* @__PURE__ */ jsxRuntime.jsx(
1499
2392
  "button",
1500
2393
  {
@@ -1505,9 +2398,8 @@ function AvatarLiveView({
1505
2398
  children: continueInChat
1506
2399
  }
1507
2400
  )
1508
- ] });
2401
+ );
1509
2402
  break;
1510
- }
1511
2403
  case "ended":
1512
2404
  body = /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: S.answerInChat });
1513
2405
  actions = /* @__PURE__ */ jsxRuntime.jsx(
@@ -1549,6 +2441,119 @@ function AvatarLiveView({
1549
2441
  }
1550
2442
  );
1551
2443
  }
2444
+ function AskBox({
2445
+ value,
2446
+ maxLength,
2447
+ onChange,
2448
+ onAsk,
2449
+ reason,
2450
+ label,
2451
+ placeholder,
2452
+ send,
2453
+ footer,
2454
+ noFiles,
2455
+ hint,
2456
+ touchFirst
2457
+ }) {
2458
+ const uid = react.useId();
2459
+ const reasonId = `${uid}-reason`;
2460
+ const hintId = `${uid}-hint`;
2461
+ const footerId = `${uid}-footer`;
2462
+ const [refusedFiles, setRefusedFiles] = react.useState(false);
2463
+ const empty = value.trim() === "";
2464
+ const submit = () => {
2465
+ if (reason !== null || empty) return;
2466
+ onAsk(value);
2467
+ };
2468
+ const onKeyDown = (event) => {
2469
+ if (event.nativeEvent.isComposing || event.keyCode === 229) {
2470
+ if (event.key === "Escape") event.stopPropagation();
2471
+ return;
2472
+ }
2473
+ if (event.key === "Enter" && !event.shiftKey) {
2474
+ event.preventDefault();
2475
+ submit();
2476
+ }
2477
+ };
2478
+ const onPaste = (event) => {
2479
+ if (event.clipboardData.files.length === 0) return;
2480
+ event.preventDefault();
2481
+ setRefusedFiles(true);
2482
+ };
2483
+ const onDrop = (event) => {
2484
+ if (!Array.from(event.dataTransfer.types).includes("Files")) return;
2485
+ event.preventDefault();
2486
+ setRefusedFiles(true);
2487
+ };
2488
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2489
+ "form",
2490
+ {
2491
+ "data-boff-explore": "avatar-live-ask",
2492
+ className: "flex w-full flex-col gap-1",
2493
+ onSubmit: (event) => {
2494
+ event.preventDefault();
2495
+ submit();
2496
+ },
2497
+ children: [
2498
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-2", children: [
2499
+ /* @__PURE__ */ jsxRuntime.jsx(
2500
+ "textarea",
2501
+ {
2502
+ value,
2503
+ rows: 1,
2504
+ maxLength,
2505
+ "aria-label": label,
2506
+ "aria-describedby": hint === null ? footerId : `${hintId} ${footerId}`,
2507
+ placeholder,
2508
+ dir: "auto",
2509
+ "data-avatar-primary": touchFirst ? void 0 : "",
2510
+ "data-boff-explore": "avatar-live-ask-input",
2511
+ className: "max-h-32 min-h-11 flex-1 resize-none rounded-md border border-border bg-background px-3 py-2.5 text-base text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring sm:text-sm",
2512
+ onChange: (event) => {
2513
+ setRefusedFiles(false);
2514
+ onChange(event.target.value);
2515
+ },
2516
+ onKeyDown,
2517
+ onPaste,
2518
+ onDrop
2519
+ }
2520
+ ),
2521
+ /* @__PURE__ */ jsxRuntime.jsx(
2522
+ "button",
2523
+ {
2524
+ type: "submit",
2525
+ "aria-disabled": reason !== null || empty ? "true" : void 0,
2526
+ "aria-describedby": reason !== null ? reasonId : void 0,
2527
+ "data-avatar-primary": touchFirst ? "" : void 0,
2528
+ "data-boff-explore": "avatar-live-ask-send",
2529
+ className: "inline-flex h-11 min-w-11 shrink-0 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background aria-disabled:cursor-not-allowed aria-disabled:opacity-50 motion-reduce:transition-none",
2530
+ children: send
2531
+ }
2532
+ )
2533
+ ] }),
2534
+ reason === null ? null : /* @__PURE__ */ jsxRuntime.jsx(
2535
+ "p",
2536
+ {
2537
+ id: reasonId,
2538
+ "data-boff-explore": "avatar-live-ask-reason",
2539
+ className: "text-xs text-muted-foreground",
2540
+ children: reason
2541
+ }
2542
+ ),
2543
+ refusedFiles ? /* @__PURE__ */ jsxRuntime.jsx(
2544
+ "p",
2545
+ {
2546
+ "data-boff-explore": "avatar-live-ask-files",
2547
+ className: "text-xs text-muted-foreground",
2548
+ children: noFiles
2549
+ }
2550
+ ) : null,
2551
+ hint === null ? null : /* @__PURE__ */ jsxRuntime.jsx("p", { id: hintId, className: "sr-only", children: hint }),
2552
+ /* @__PURE__ */ jsxRuntime.jsx("p", { id: footerId, className: "text-xs text-muted-foreground", children: footer })
2553
+ ]
2554
+ }
2555
+ );
2556
+ }
1552
2557
 
1553
2558
  exports.AvatarLiveView = AvatarLiveView;
1554
2559
  //# sourceMappingURL=index.js.map