@burdenoff/website-sdk 2026.1102.2 → 2026.1104.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -8
- package/dist/avatar-live-view/index.d.mts +29 -5
- package/dist/avatar-live-view/index.d.ts +29 -5
- package/dist/avatar-live-view/index.js +1319 -271
- package/dist/avatar-live-view/index.js.map +1 -1
- package/dist/avatar-live-view/index.mjs +1317 -269
- package/dist/avatar-live-view/index.mjs.map +1 -1
- package/dist/{chunk-R742FS5E.js → chunk-22OT6E26.js} +61 -27
- package/dist/chunk-22OT6E26.js.map +1 -0
- package/dist/{chunk-ETI2HQEC.mjs → chunk-5JQGE3XI.mjs} +46 -14
- package/dist/chunk-5JQGE3XI.mjs.map +1 -0
- package/dist/{chunk-FQH3AJN3.js → chunk-7O2I32ZN.js} +2 -2
- package/dist/chunk-7O2I32ZN.js.map +1 -0
- package/dist/{chunk-SFT3WHN5.mjs → chunk-K3QZGJEH.mjs} +2 -2
- package/dist/chunk-K3QZGJEH.mjs.map +1 -0
- package/dist/{chunk-SK5UGG6A.js → chunk-P5GMVPR6.js} +76 -20
- package/dist/chunk-P5GMVPR6.js.map +1 -0
- package/dist/{chunk-EUPFS6MZ.mjs → chunk-SMD7MEEA.mjs} +76 -20
- package/dist/chunk-SMD7MEEA.mjs.map +1 -0
- package/dist/components/explore.d.mts +2 -2
- package/dist/components/explore.d.ts +2 -2
- package/dist/components/explore.js +14 -14
- package/dist/components/explore.mjs +2 -2
- package/dist/{explore-DUTNYUOm.d.mts → explore-BV4dRwoC.d.ts} +8 -1
- package/dist/{explore-DjQE7Xia.d.ts → explore-BgEeGPvY.d.mts} +8 -1
- package/dist/{explore-avatar-live-config-Cetx8-Zu.d.ts → explore-avatar-live-config-CAfN5eAX.d.ts} +6 -3
- package/dist/{explore-avatar-live-config-Bp3kQbU2.d.mts → explore-avatar-live-config-N4WhJzgS.d.mts} +6 -3
- package/dist/{explore-types-Bb2Ih3d8.d.mts → explore-types-Ol1Mm3dW.d.mts} +12 -1
- package/dist/{explore-types-Bb2Ih3d8.d.ts → explore-types-Ol1Mm3dW.d.ts} +12 -1
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +9 -9
- package/dist/hooks/index.mjs +1 -1
- package/dist/index.d.mts +14 -8
- package/dist/index.d.ts +14 -8
- package/dist/index.js +100 -63
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +43 -6
- package/dist/index.mjs.map +1 -1
- package/dist/{use-explore-chat-DunjG-3p.d.ts → use-explore-chat-B3dOOvJN.d.ts} +43 -3
- package/dist/{use-explore-chat-zRuoAin6.d.mts → use-explore-chat-CbfohA9O.d.mts} +43 -3
- package/package.json +1 -1
- package/dist/chunk-ETI2HQEC.mjs.map +0 -1
- package/dist/chunk-EUPFS6MZ.mjs.map +0 -1
- package/dist/chunk-FQH3AJN3.js.map +0 -1
- package/dist/chunk-R742FS5E.js.map +0 -1
- package/dist/chunk-SFT3WHN5.mjs.map +0 -1
- package/dist/chunk-SK5UGG6A.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { turnstileSiteKeyOf,
|
|
1
|
+
import { turnstileSiteKeyOf, isAvatarLiveLocaleReviewed, isAvatarSite, isAvatarVersion } from '../chunk-K3QZGJEH.mjs';
|
|
2
2
|
import { fill } from '../chunk-TT3MHN42.mjs';
|
|
3
3
|
import { cn } from '../chunk-R7G6TWIS.mjs';
|
|
4
4
|
import '../chunk-VNS5WDWO.mjs';
|
|
@@ -47,6 +47,15 @@ function readBotCheck(value) {
|
|
|
47
47
|
}
|
|
48
48
|
return mode === "off" ? "off" : "turnstile";
|
|
49
49
|
}
|
|
50
|
+
var QUESTION_MODES = /* @__PURE__ */ new Set([
|
|
51
|
+
"any",
|
|
52
|
+
"suggested"
|
|
53
|
+
]);
|
|
54
|
+
function readQuestions(value) {
|
|
55
|
+
if (value === void 0) return "suggested";
|
|
56
|
+
if (typeof value !== "string" || !QUESTION_MODES.has(value)) return null;
|
|
57
|
+
return value === "any" ? "any" : "suggested";
|
|
58
|
+
}
|
|
50
59
|
function readAvailability(status, body) {
|
|
51
60
|
if (status !== 200 || !isRecord(body)) return INERT;
|
|
52
61
|
const { available, reason } = body;
|
|
@@ -56,16 +65,21 @@ function readAvailability(status, body) {
|
|
|
56
65
|
if (reason === "ok") {
|
|
57
66
|
const { consentVersion, maxSessionSeconds } = body;
|
|
58
67
|
const botCheck = readBotCheck(body.botCheck);
|
|
59
|
-
|
|
68
|
+
const questions = readQuestions(body.questions);
|
|
69
|
+
if (available !== true || typeof consentVersion !== "string" || !isAvatarVersion(consentVersion) || typeof maxSessionSeconds !== "number" || !Number.isInteger(maxSessionSeconds) || maxSessionSeconds < 1 || botCheck === null || questions === null) {
|
|
60
70
|
return INERT;
|
|
61
71
|
}
|
|
62
72
|
return {
|
|
63
73
|
kind: "available",
|
|
64
|
-
offer: { consentVersion, maxSessionSeconds, botCheck }
|
|
74
|
+
offer: { consentVersion, maxSessionSeconds, botCheck, questions }
|
|
65
75
|
};
|
|
66
76
|
}
|
|
67
77
|
const meaning = available ? void 0 : AVAILABILITY_REASONS.get(reason);
|
|
68
|
-
return meaning === void 0 || meaning === "inert" ? INERT : {
|
|
78
|
+
return meaning === void 0 || meaning === "inert" ? INERT : {
|
|
79
|
+
kind: "refused",
|
|
80
|
+
reason: meaning,
|
|
81
|
+
questions: body.questions === "any" ? "any" : "suggested"
|
|
82
|
+
};
|
|
69
83
|
}
|
|
70
84
|
var CREATE_REFUSALS = /* @__PURE__ */ new Map([
|
|
71
85
|
["busy", "busy"],
|
|
@@ -285,7 +299,31 @@ var EN = {
|
|
|
285
299
|
locale: "The live avatar isn't offered in this language yet.",
|
|
286
300
|
paused: "The live avatar is paused right now.",
|
|
287
301
|
notEligible: "The avatar reads the first answer to a suggested question, within fifteen minutes. Start a new chat and choose a suggested question.",
|
|
288
|
-
answerClaimed: "The avatar has already read this answer."
|
|
302
|
+
answerClaimed: "The avatar has already read this answer.",
|
|
303
|
+
askHeadline: "Ask a question, and the avatar reads the answer aloud.",
|
|
304
|
+
askLabel: "Question for the avatar",
|
|
305
|
+
askPlaceholder: "Ask the avatar\u2026",
|
|
306
|
+
askFooter: "Answers are AI-generated and can be wrong. Don't include personal details.",
|
|
307
|
+
askNoFiles: "To attach files, use Chat.",
|
|
308
|
+
askBusy: "You can ask when the current answer is ready.",
|
|
309
|
+
askUnavailable: "Chat isn't available right now.",
|
|
310
|
+
gettingAnswer: "Getting the answer\u2026",
|
|
311
|
+
startWhenReady: "Start when ready",
|
|
312
|
+
armed: "The avatar will start when the answer is ready.",
|
|
313
|
+
cancel: "Cancel",
|
|
314
|
+
armedCancelled: "The avatar didn't start. Press Start when ready to try again.",
|
|
315
|
+
notSpoken: "This answer stays in Chat as text. The avatar reads only answers that pass its speech checks.",
|
|
316
|
+
answerFailed: "The assistant couldn't answer. Try asking again.",
|
|
317
|
+
declined: "No problem. The answer is in Chat.",
|
|
318
|
+
askHere: "To hear an answer, ask it here.",
|
|
319
|
+
newChatForAvatar: "New chat for the avatar",
|
|
320
|
+
newChatNote: "Your current chat stays in History.",
|
|
321
|
+
newChatStarted: "Started a new chat for the avatar.",
|
|
322
|
+
readInChat: "Read the answer and sources in Chat",
|
|
323
|
+
usedToday: "You've had today's avatar session. Answers will show here as text.",
|
|
324
|
+
needsAnswerAny: "Ask a question here, and the avatar reads the answer aloud.",
|
|
325
|
+
startNewChatDetailAny: "The avatar reads aloud only the first answer in a new chat started in the Avatar tab, provided it passes the speech checks.",
|
|
326
|
+
notEligibleAny: "The avatar can't read this answer aloud. The answer and sources are in Chat."
|
|
289
327
|
};
|
|
290
328
|
var ZH = {
|
|
291
329
|
checking: "\u6B63\u5728\u68C0\u67E5\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61\u662F\u5426\u53EF\u7528\u2026",
|
|
@@ -319,7 +357,32 @@ var ZH = {
|
|
|
319
357
|
paused: "\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61\u76EE\u524D\u5DF2\u6682\u505C\u3002",
|
|
320
358
|
// TRANSLATION REVIEW PENDING (BOFF-9797): draft.
|
|
321
359
|
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",
|
|
322
|
-
answerClaimed: "\u865A\u62DF\u5F62\u8C61\u5DF2\u7ECF\u6717\u8BFB\u8FC7\u8FD9\u4E2A\u56DE\u7B54\u3002"
|
|
360
|
+
answerClaimed: "\u865A\u62DF\u5F62\u8C61\u5DF2\u7ECF\u6717\u8BFB\u8FC7\u8FD9\u4E2A\u56DE\u7B54\u3002",
|
|
361
|
+
// TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.
|
|
362
|
+
askHeadline: "\u63D0\u51FA\u95EE\u9898\uFF0C\u865A\u62DF\u5F62\u8C61\u4F1A\u6717\u8BFB\u56DE\u7B54\u3002",
|
|
363
|
+
askLabel: "\u5411\u865A\u62DF\u5F62\u8C61\u63D0\u7684\u95EE\u9898",
|
|
364
|
+
askPlaceholder: "\u5411\u865A\u62DF\u5F62\u8C61\u63D0\u95EE\u2026",
|
|
365
|
+
askFooter: "\u56DE\u7B54\u7531 AI \u751F\u6210\uFF0C\u53EF\u80FD\u6709\u8BEF\u3002\u8BF7\u52FF\u5305\u542B\u4E2A\u4EBA\u4FE1\u606F\u3002",
|
|
366
|
+
askNoFiles: "\u5982\u9700\u9644\u52A0\u6587\u4EF6\uFF0C\u8BF7\u4F7F\u7528\u804A\u5929\u3002",
|
|
367
|
+
askBusy: "\u5F53\u524D\u56DE\u7B54\u51C6\u5907\u597D\u540E\u5373\u53EF\u63D0\u95EE\u3002",
|
|
368
|
+
askUnavailable: "\u804A\u5929\u76EE\u524D\u4E0D\u53EF\u7528\u3002",
|
|
369
|
+
gettingAnswer: "\u6B63\u5728\u83B7\u53D6\u56DE\u7B54\u2026",
|
|
370
|
+
startWhenReady: "\u51C6\u5907\u597D\u540E\u5F00\u59CB",
|
|
371
|
+
armed: "\u56DE\u7B54\u51C6\u5907\u597D\u540E\uFF0C\u865A\u62DF\u5F62\u8C61\u5C06\u5F00\u59CB\u3002",
|
|
372
|
+
cancel: "\u53D6\u6D88",
|
|
373
|
+
armedCancelled: "\u865A\u62DF\u5F62\u8C61\u672A\u542F\u52A8\u3002\u53EF\u518D\u6B21\u6309\u201C\u51C6\u5907\u597D\u540E\u5F00\u59CB\u201D\u3002",
|
|
374
|
+
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",
|
|
375
|
+
answerFailed: "\u52A9\u624B\u65E0\u6CD5\u56DE\u7B54\u3002\u8BF7\u91CD\u65B0\u63D0\u95EE\u3002",
|
|
376
|
+
declined: "\u6CA1\u5173\u7CFB\u3002\u56DE\u7B54\u5728\u804A\u5929\u4E2D\u3002",
|
|
377
|
+
askHere: "\u5982\u9700\u542C\u53D6\u56DE\u7B54\uFF0C\u8BF7\u5728\u8FD9\u91CC\u63D0\u95EE\u3002",
|
|
378
|
+
newChatForAvatar: "\u4E3A\u865A\u62DF\u5F62\u8C61\u5F00\u59CB\u65B0\u804A\u5929",
|
|
379
|
+
newChatNote: "\u5F53\u524D\u804A\u5929\u4F1A\u4FDD\u7559\u5728\u5386\u53F2\u8BB0\u5F55\u4E2D\u3002",
|
|
380
|
+
newChatStarted: "\u5DF2\u4E3A\u865A\u62DF\u5F62\u8C61\u5F00\u59CB\u65B0\u7684\u804A\u5929\u3002",
|
|
381
|
+
readInChat: "\u5728\u804A\u5929\u4E2D\u67E5\u770B\u56DE\u7B54\u548C\u6765\u6E90",
|
|
382
|
+
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",
|
|
383
|
+
needsAnswerAny: "\u5728\u8FD9\u91CC\u63D0\u95EE\uFF0C\u865A\u62DF\u5F62\u8C61\u4F1A\u6717\u8BFB\u56DE\u7B54\u3002",
|
|
384
|
+
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",
|
|
385
|
+
notEligibleAny: "\u865A\u62DF\u5F62\u8C61\u65E0\u6CD5\u6717\u8BFB\u6B64\u56DE\u7B54\u3002\u56DE\u7B54\u548C\u6765\u6E90\u5728\u804A\u5929\u4E2D\u3002"
|
|
323
386
|
};
|
|
324
387
|
var HI = {
|
|
325
388
|
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",
|
|
@@ -353,7 +416,32 @@ var HI = {
|
|
|
353
416
|
paused: "\u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930 \u0905\u092D\u0940 \u0930\u0941\u0915\u093E \u0939\u0941\u0906 \u0939\u0948\u0964",
|
|
354
417
|
// TRANSLATION REVIEW PENDING (BOFF-9797): draft.
|
|
355
418
|
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",
|
|
356
|
-
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"
|
|
419
|
+
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",
|
|
420
|
+
// TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.
|
|
421
|
+
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",
|
|
422
|
+
askLabel: "\u0905\u0935\u0924\u093E\u0930 \u0915\u0947 \u0932\u093F\u090F \u092A\u094D\u0930\u0936\u094D\u0928",
|
|
423
|
+
askPlaceholder: "\u0905\u0935\u0924\u093E\u0930 \u0938\u0947 \u092A\u0942\u091B\u0947\u0902\u2026",
|
|
424
|
+
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",
|
|
425
|
+
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",
|
|
426
|
+
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",
|
|
427
|
+
askUnavailable: "\u091A\u0948\u091F \u0905\u092D\u0940 \u0909\u092A\u0932\u092C\u094D\u0927 \u0928\u0939\u0940\u0902 \u0939\u0948\u0964",
|
|
428
|
+
gettingAnswer: "\u0909\u0924\u094D\u0924\u0930 \u0932\u093E\u092F\u093E \u091C\u093E \u0930\u0939\u093E \u0939\u0948\u2026",
|
|
429
|
+
startWhenReady: "\u0924\u0948\u092F\u093E\u0930 \u0939\u094B\u0928\u0947 \u092A\u0930 \u0936\u0941\u0930\u0942 \u0915\u0930\u0947\u0902",
|
|
430
|
+
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",
|
|
431
|
+
cancel: "\u0930\u0926\u094D\u0926 \u0915\u0930\u0947\u0902",
|
|
432
|
+
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",
|
|
433
|
+
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",
|
|
434
|
+
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",
|
|
435
|
+
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",
|
|
436
|
+
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",
|
|
437
|
+
newChatForAvatar: "\u0905\u0935\u0924\u093E\u0930 \u0915\u0947 \u0932\u093F\u090F \u0928\u0908 \u091A\u0948\u091F",
|
|
438
|
+
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",
|
|
439
|
+
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",
|
|
440
|
+
readInChat: "\u0909\u0924\u094D\u0924\u0930 \u0914\u0930 \u0938\u094D\u0930\u094B\u0924 \u091A\u0948\u091F \u092E\u0947\u0902 \u092A\u0922\u093C\u0947\u0902",
|
|
441
|
+
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",
|
|
442
|
+
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",
|
|
443
|
+
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",
|
|
444
|
+
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"
|
|
357
445
|
};
|
|
358
446
|
var ES = {
|
|
359
447
|
checking: "Comprobando si el avatar en vivo est\xE1 disponible\u2026",
|
|
@@ -387,7 +475,32 @@ var ES = {
|
|
|
387
475
|
paused: "El avatar en vivo est\xE1 en pausa en este momento.",
|
|
388
476
|
// TRANSLATION REVIEW PENDING (BOFF-9797): draft.
|
|
389
477
|
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.",
|
|
390
|
-
answerClaimed: "El avatar ya ha le\xEDdo esta respuesta."
|
|
478
|
+
answerClaimed: "El avatar ya ha le\xEDdo esta respuesta.",
|
|
479
|
+
// TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.
|
|
480
|
+
askHeadline: "Haz una pregunta y el avatar leer\xE1 la respuesta en voz alta.",
|
|
481
|
+
askLabel: "Pregunta para el avatar",
|
|
482
|
+
askPlaceholder: "Pregunta al avatar\u2026",
|
|
483
|
+
askFooter: "Las respuestas las genera la IA y pueden contener errores. No incluyas datos personales.",
|
|
484
|
+
askNoFiles: "Para adjuntar archivos, usa el chat.",
|
|
485
|
+
askBusy: "Podr\xE1s preguntar cuando la respuesta actual est\xE9 lista.",
|
|
486
|
+
askUnavailable: "El chat no est\xE1 disponible en este momento.",
|
|
487
|
+
gettingAnswer: "Obteniendo la respuesta\u2026",
|
|
488
|
+
startWhenReady: "Iniciar cuando est\xE9 lista",
|
|
489
|
+
armed: "El avatar empezar\xE1 cuando la respuesta est\xE9 lista.",
|
|
490
|
+
cancel: "Cancelar",
|
|
491
|
+
armedCancelled: "El avatar no se ha iniciado. Pulsa Iniciar cuando est\xE9 lista para volver a intentarlo.",
|
|
492
|
+
notSpoken: "Esta respuesta se queda en el chat como texto. El avatar solo lee respuestas que superan sus comprobaciones de voz.",
|
|
493
|
+
answerFailed: "El asistente no pudo responder. Vuelve a preguntar.",
|
|
494
|
+
declined: "De acuerdo. La respuesta est\xE1 en el chat.",
|
|
495
|
+
askHere: "Para escuchar una respuesta, pregunta aqu\xED.",
|
|
496
|
+
newChatForAvatar: "Chat nuevo para el avatar",
|
|
497
|
+
newChatNote: "Tu chat actual se queda en el historial.",
|
|
498
|
+
newChatStarted: "Se ha iniciado un chat nuevo para el avatar.",
|
|
499
|
+
readInChat: "Leer la respuesta y las fuentes en el chat",
|
|
500
|
+
usedToday: "Ya has usado la sesi\xF3n de avatar de hoy. Las respuestas se mostrar\xE1n aqu\xED como texto.",
|
|
501
|
+
needsAnswerAny: "Haz una pregunta aqu\xED y el avatar leer\xE1 la respuesta en voz alta.",
|
|
502
|
+
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.",
|
|
503
|
+
notEligibleAny: "El avatar no puede leer esta respuesta en voz alta. La respuesta y las fuentes est\xE1n en el chat."
|
|
391
504
|
};
|
|
392
505
|
var AR = {
|
|
393
506
|
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",
|
|
@@ -421,7 +534,32 @@ var AR = {
|
|
|
421
534
|
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.",
|
|
422
535
|
// TRANSLATION REVIEW PENDING (BOFF-9797): draft.
|
|
423
536
|
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.",
|
|
424
|
-
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."
|
|
537
|
+
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.",
|
|
538
|
+
// TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.
|
|
539
|
+
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.",
|
|
540
|
+
askLabel: "\u0633\u0624\u0627\u0644 \u0644\u0644\u0623\u0641\u0627\u062A\u0627\u0631",
|
|
541
|
+
askPlaceholder: "\u0627\u0633\u0623\u0644 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631\u2026",
|
|
542
|
+
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.",
|
|
543
|
+
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.",
|
|
544
|
+
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.",
|
|
545
|
+
askUnavailable: "\u0627\u0644\u062F\u0631\u062F\u0634\u0629 \u063A\u064A\u0631 \u0645\u062A\u0627\u062D\u0629 \u0627\u0644\u0622\u0646.",
|
|
546
|
+
gettingAnswer: "\u062C\u0627\u0631\u064D \u0627\u0644\u062D\u0635\u0648\u0644 \u0639\u0644\u0649 \u0627\u0644\u0625\u062C\u0627\u0628\u0629\u2026",
|
|
547
|
+
startWhenReady: "\u0627\u0644\u0628\u062F\u0621 \u0639\u0646\u062F \u0627\u0644\u062C\u0627\u0647\u0632\u064A\u0629",
|
|
548
|
+
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.",
|
|
549
|
+
cancel: "\u0625\u0644\u063A\u0627\u0621",
|
|
550
|
+
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.",
|
|
551
|
+
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.",
|
|
552
|
+
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.",
|
|
553
|
+
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.",
|
|
554
|
+
askHere: "\u0644\u0633\u0645\u0627\u0639 \u0625\u062C\u0627\u0628\u0629\u060C \u0627\u0633\u0623\u0644 \u0647\u0646\u0627.",
|
|
555
|
+
newChatForAvatar: "\u062F\u0631\u062F\u0634\u0629 \u062C\u062F\u064A\u062F\u0629 \u0644\u0644\u0623\u0641\u0627\u062A\u0627\u0631",
|
|
556
|
+
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.",
|
|
557
|
+
newChatStarted: "\u0628\u062F\u0623\u062A \u062F\u0631\u062F\u0634\u0629 \u062C\u062F\u064A\u062F\u0629 \u0644\u0644\u0623\u0641\u0627\u062A\u0627\u0631.",
|
|
558
|
+
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",
|
|
559
|
+
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.",
|
|
560
|
+
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.",
|
|
561
|
+
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.",
|
|
562
|
+
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."
|
|
425
563
|
};
|
|
426
564
|
var TA = {
|
|
427
565
|
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",
|
|
@@ -455,7 +593,32 @@ var TA = {
|
|
|
455
593
|
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.",
|
|
456
594
|
// TRANSLATION REVIEW PENDING (BOFF-9797): draft.
|
|
457
595
|
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.",
|
|
458
|
-
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."
|
|
596
|
+
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.",
|
|
597
|
+
// TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.
|
|
598
|
+
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.",
|
|
599
|
+
askLabel: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF",
|
|
600
|
+
askPlaceholder: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BBF\u0B9F\u0BAE\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD\u2026",
|
|
601
|
+
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.",
|
|
602
|
+
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.",
|
|
603
|
+
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.",
|
|
604
|
+
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.",
|
|
605
|
+
gettingAnswer: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BC8\u0BAA\u0BCD \u0BAA\u0BC6\u0BB1\u0BC1\u0B95\u0BBF\u0BB1\u0BA4\u0BC1\u2026",
|
|
606
|
+
startWhenReady: "\u0BA4\u0BAF\u0BBE\u0BB0\u0BBE\u0BA9\u0BA4\u0BC1\u0BAE\u0BCD \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BC1",
|
|
607
|
+
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.",
|
|
608
|
+
cancel: "\u0BB0\u0BA4\u0BCD\u0BA4\u0BC1\u0B9A\u0BC6\u0BAF\u0BCD",
|
|
609
|
+
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.",
|
|
610
|
+
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.",
|
|
611
|
+
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.",
|
|
612
|
+
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.",
|
|
613
|
+
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.",
|
|
614
|
+
newChatForAvatar: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8",
|
|
615
|
+
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.",
|
|
616
|
+
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.",
|
|
617
|
+
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",
|
|
618
|
+
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.",
|
|
619
|
+
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.",
|
|
620
|
+
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.",
|
|
621
|
+
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."
|
|
459
622
|
};
|
|
460
623
|
var STRINGS = {
|
|
461
624
|
en: EN,
|
|
@@ -479,7 +642,8 @@ var CONSENT = /* @__PURE__ */ new Map([
|
|
|
479
642
|
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.",
|
|
480
643
|
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.",
|
|
481
644
|
privacyLink: "How we handle this",
|
|
482
|
-
botCheck: "turnstile"
|
|
645
|
+
botCheck: "turnstile",
|
|
646
|
+
questions: "suggested"
|
|
483
647
|
}
|
|
484
648
|
}
|
|
485
649
|
],
|
|
@@ -494,7 +658,8 @@ var CONSENT = /* @__PURE__ */ new Map([
|
|
|
494
658
|
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.",
|
|
495
659
|
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.",
|
|
496
660
|
privacyLink: "How we handle this",
|
|
497
|
-
botCheck: "turnstile"
|
|
661
|
+
botCheck: "turnstile",
|
|
662
|
+
questions: "suggested"
|
|
498
663
|
}
|
|
499
664
|
}
|
|
500
665
|
],
|
|
@@ -510,7 +675,8 @@ var CONSENT = /* @__PURE__ */ new Map([
|
|
|
510
675
|
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.",
|
|
511
676
|
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.",
|
|
512
677
|
privacyLink: "How we handle this",
|
|
513
|
-
botCheck: "turnstile"
|
|
678
|
+
botCheck: "turnstile",
|
|
679
|
+
questions: "suggested"
|
|
514
680
|
}
|
|
515
681
|
}
|
|
516
682
|
],
|
|
@@ -526,7 +692,44 @@ var CONSENT = /* @__PURE__ */ new Map([
|
|
|
526
692
|
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.",
|
|
527
693
|
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.",
|
|
528
694
|
privacyLink: "How we handle this",
|
|
529
|
-
botCheck: "off"
|
|
695
|
+
botCheck: "off",
|
|
696
|
+
questions: "suggested"
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
],
|
|
700
|
+
[
|
|
701
|
+
// The Avatar tab's own question box (contract v1.3, `questions: "any"`): the first answer in a new chat started in
|
|
702
|
+
// the Avatar tab is read whether the visitor chose a suggested question or typed their own, so the intro says so and
|
|
703
|
+
// warns against personal details in a typed one. Product-neutral, with the bot check: one notice and one digest for
|
|
704
|
+
// every site (gitops docs/avatar-web/en-web-consent-2026-11-05.txt).
|
|
705
|
+
"web-consent-2026-11-05",
|
|
706
|
+
{
|
|
707
|
+
en: {
|
|
708
|
+
title: "Live AI avatar (beta)",
|
|
709
|
+
introProduct: null,
|
|
710
|
+
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.",
|
|
711
|
+
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.",
|
|
712
|
+
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.",
|
|
713
|
+
privacyLink: "How we handle this",
|
|
714
|
+
botCheck: "turnstile",
|
|
715
|
+
questions: "any"
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
],
|
|
719
|
+
[
|
|
720
|
+
// The words of web-consent-2026-11-05 without "When you start, Cloudflare checks for bots.", for a server that runs
|
|
721
|
+
// no bot check (gitops docs/avatar-web/en-web-consent-2026-11-06.txt).
|
|
722
|
+
"web-consent-2026-11-06",
|
|
723
|
+
{
|
|
724
|
+
en: {
|
|
725
|
+
title: "Live AI avatar (beta)",
|
|
726
|
+
introProduct: null,
|
|
727
|
+
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.",
|
|
728
|
+
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.",
|
|
729
|
+
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.",
|
|
730
|
+
privacyLink: "How we handle this",
|
|
731
|
+
botCheck: "off",
|
|
732
|
+
questions: "any"
|
|
530
733
|
}
|
|
531
734
|
}
|
|
532
735
|
]
|
|
@@ -657,6 +860,9 @@ var CLOCK_TOLERANCE_MS = 5e3;
|
|
|
657
860
|
var SERVICE_MAX_AGE_MS = 15 * 6e4;
|
|
658
861
|
var ANSWER_OFFER_MS = SERVICE_MAX_AGE_MS - 6e4;
|
|
659
862
|
var MAX_TIMER_MS = 2147483647;
|
|
863
|
+
var ASK_MAX_LENGTH = 300;
|
|
864
|
+
var MAX_REFERENCES = 64;
|
|
865
|
+
var USED_ON_KEY = "boff.explore.avatarUsedOn";
|
|
660
866
|
var PRIMARY = '[data-avatar-primary], [data-boff-explore="panel-continue-chat"]';
|
|
661
867
|
var IDLE = { name: "idle" };
|
|
662
868
|
var INERT2 = { name: "inert" };
|
|
@@ -669,12 +875,26 @@ var REFUSAL_TEXT = {
|
|
|
669
875
|
not_eligible: "notEligible",
|
|
670
876
|
answer_claimed: "answerClaimed"
|
|
671
877
|
};
|
|
672
|
-
var
|
|
673
|
-
|
|
878
|
+
var EMPTY = {
|
|
879
|
+
kind: "empty",
|
|
674
880
|
answerId: null,
|
|
675
|
-
startOver:
|
|
676
|
-
offerUntil: NaN
|
|
881
|
+
startOver: false,
|
|
882
|
+
offerUntil: NaN,
|
|
883
|
+
question: null,
|
|
884
|
+
pendingAnswerId: null,
|
|
885
|
+
askedHere: false
|
|
886
|
+
};
|
|
887
|
+
var START_OVER = { ...EMPTY, kind: "start-over", startOver: true };
|
|
888
|
+
var SUGGESTED_RULES = {
|
|
889
|
+
any: false,
|
|
890
|
+
askedHere: null,
|
|
891
|
+
token: null,
|
|
892
|
+
inFlight: false
|
|
677
893
|
};
|
|
894
|
+
function isAskedHere(question, rules) {
|
|
895
|
+
const asked = rules.askedHere;
|
|
896
|
+
return rules.any && asked !== null && question.id === asked.messageId && asked.token === rules.token;
|
|
897
|
+
}
|
|
678
898
|
function createdAtOf(message) {
|
|
679
899
|
const raw = message.createdAt;
|
|
680
900
|
return typeof raw === "string" && raw !== "" ? Date.parse(raw) : NaN;
|
|
@@ -682,25 +902,110 @@ function createdAtOf(message) {
|
|
|
682
902
|
function offeredAt(exchange, now) {
|
|
683
903
|
return exchange.answerId !== null && !(now < exchange.offerUntil) ? START_OVER : exchange;
|
|
684
904
|
}
|
|
685
|
-
function
|
|
686
|
-
|
|
905
|
+
function readable(question, answer) {
|
|
906
|
+
const references = answer.references?.length ?? 0;
|
|
907
|
+
return answer.answered === true && references >= 1 && references <= MAX_REFERENCES && (question.attachments?.length ?? 0) === 0;
|
|
908
|
+
}
|
|
909
|
+
function firstExchange(messages, rules = SUGGESTED_RULES) {
|
|
910
|
+
if (!messages || messages.length === 0) return EMPTY;
|
|
687
911
|
if (messages.length > 2) return START_OVER;
|
|
688
912
|
const [question, answer] = messages;
|
|
689
913
|
if (question?.role !== "USER") return START_OVER;
|
|
690
|
-
|
|
914
|
+
const first = { question, askedHere: isAskedHere(question, rules) };
|
|
915
|
+
if (answer === void 0) {
|
|
916
|
+
if (rules.inFlight) return { ...EMPTY, ...first, kind: "asking" };
|
|
917
|
+
return rules.any ? { ...START_OVER, ...first, kind: "failed" } : EMPTY;
|
|
918
|
+
}
|
|
691
919
|
if (answer.role !== "ASSISTANT") return START_OVER;
|
|
692
920
|
if (answer.status === "PENDING" || answer.status === "RUNNING") {
|
|
693
|
-
return
|
|
921
|
+
return {
|
|
922
|
+
...EMPTY,
|
|
923
|
+
...first,
|
|
924
|
+
kind: "asking",
|
|
925
|
+
pendingAnswerId: isAvatarMessageId(answer.id) ? answer.id : null
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
if (rules.any && answer.status === "FAILED") {
|
|
929
|
+
return { ...START_OVER, ...first, kind: "failed" };
|
|
694
930
|
}
|
|
695
931
|
if (answer.status !== "COMPLETED" || answer.content.trim() === "" || !isAvatarMessageId(answer.id)) {
|
|
696
932
|
return START_OVER;
|
|
697
933
|
}
|
|
934
|
+
if (rules.any && !first.askedHere) {
|
|
935
|
+
return { ...START_OVER, ...first, kind: "ask-here" };
|
|
936
|
+
}
|
|
937
|
+
if (rules.any && !readable(question, answer)) {
|
|
938
|
+
return { ...START_OVER, ...first, kind: "text-only" };
|
|
939
|
+
}
|
|
698
940
|
return {
|
|
941
|
+
...EMPTY,
|
|
942
|
+
...first,
|
|
943
|
+
kind: "answer",
|
|
699
944
|
answerId: answer.id,
|
|
700
|
-
startOver: false,
|
|
701
945
|
offerUntil: createdAtOf(answer) + ANSWER_OFFER_MS
|
|
702
946
|
};
|
|
703
947
|
}
|
|
948
|
+
function inFlight(conversation) {
|
|
949
|
+
return conversation?.phase === "sending" || conversation?.phase === "streaming";
|
|
950
|
+
}
|
|
951
|
+
function utcToday() {
|
|
952
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
953
|
+
}
|
|
954
|
+
function usedTodayHere() {
|
|
955
|
+
try {
|
|
956
|
+
return window.localStorage.getItem(USED_ON_KEY) === utcToday();
|
|
957
|
+
} catch {
|
|
958
|
+
return false;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
function noteUsedToday() {
|
|
962
|
+
try {
|
|
963
|
+
window.localStorage.setItem(USED_ON_KEY, utcToday());
|
|
964
|
+
} catch {
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
var silence = null;
|
|
968
|
+
function silentWav() {
|
|
969
|
+
if (silence !== null) return silence;
|
|
970
|
+
const rate = 8e3;
|
|
971
|
+
const samples = rate / 10;
|
|
972
|
+
const bytes = new Uint8Array(44 + samples);
|
|
973
|
+
const view = new DataView(bytes.buffer);
|
|
974
|
+
const text = (at, value) => {
|
|
975
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
976
|
+
bytes[at + i] = value.charCodeAt(i);
|
|
977
|
+
}
|
|
978
|
+
};
|
|
979
|
+
text(0, "RIFF");
|
|
980
|
+
view.setUint32(4, 36 + samples, true);
|
|
981
|
+
text(8, "WAVE");
|
|
982
|
+
text(12, "fmt ");
|
|
983
|
+
view.setUint32(16, 16, true);
|
|
984
|
+
view.setUint16(20, 1, true);
|
|
985
|
+
view.setUint16(22, 1, true);
|
|
986
|
+
view.setUint32(24, rate, true);
|
|
987
|
+
view.setUint32(28, rate, true);
|
|
988
|
+
view.setUint16(32, 1, true);
|
|
989
|
+
view.setUint16(34, 8, true);
|
|
990
|
+
text(36, "data");
|
|
991
|
+
view.setUint32(40, samples, true);
|
|
992
|
+
bytes.fill(128, 44);
|
|
993
|
+
let binary = "";
|
|
994
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
995
|
+
silence = `data:audio/wav;base64,${btoa(binary)}`;
|
|
996
|
+
return silence;
|
|
997
|
+
}
|
|
998
|
+
function unlockSound(audio) {
|
|
999
|
+
if (audio === null || audio.srcObject) return;
|
|
1000
|
+
try {
|
|
1001
|
+
audio.src = silentWav();
|
|
1002
|
+
void Promise.resolve(audio.play()).then(
|
|
1003
|
+
() => audio.pause(),
|
|
1004
|
+
() => void 0
|
|
1005
|
+
);
|
|
1006
|
+
} catch {
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
704
1009
|
function offering(offer, messageId, claimed) {
|
|
705
1010
|
return claimed.has(messageId) ? { name: "refused", reason: "answer_claimed" } : { name: "consent", offer, messageId };
|
|
706
1011
|
}
|
|
@@ -719,13 +1024,20 @@ function clock(seconds) {
|
|
|
719
1024
|
function AvatarLiveView({
|
|
720
1025
|
live,
|
|
721
1026
|
active,
|
|
1027
|
+
open,
|
|
722
1028
|
locale,
|
|
723
1029
|
productName,
|
|
724
1030
|
still,
|
|
725
1031
|
fallback,
|
|
726
1032
|
onContinueInChat,
|
|
1033
|
+
onVoiceHold,
|
|
727
1034
|
continueInChat,
|
|
728
1035
|
newChat,
|
|
1036
|
+
send,
|
|
1037
|
+
tryAsking,
|
|
1038
|
+
prompts,
|
|
1039
|
+
touchFirst,
|
|
1040
|
+
currentPath,
|
|
729
1041
|
off,
|
|
730
1042
|
base,
|
|
731
1043
|
headers,
|
|
@@ -734,18 +1046,56 @@ function AvatarLiveView({
|
|
|
734
1046
|
const S = avatarLiveStrings(locale);
|
|
735
1047
|
const uid = useId();
|
|
736
1048
|
const consentTitleId = `${uid}-consent`;
|
|
737
|
-
const
|
|
1049
|
+
const [questions, setQuestions] = useState("suggested");
|
|
1050
|
+
const questionsRef = useRef("suggested");
|
|
1051
|
+
const askedHereRef = useRef(null);
|
|
1052
|
+
const askSeqRef = useRef(0);
|
|
1053
|
+
const [, setAskedHereTick] = useState(0);
|
|
1054
|
+
const setAskedHere = 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
|
+
});
|
|
738
1069
|
const [ageTick, setAgeTick] = useState(0);
|
|
739
|
-
const
|
|
1070
|
+
const shown = offeredAt(exchange, Date.now());
|
|
1071
|
+
const { answerId, startOver } = shown;
|
|
740
1072
|
const offerUntil = answerId === null ? null : exchange.offerUntil;
|
|
741
1073
|
const [phase, setPhase] = useState(IDLE);
|
|
742
1074
|
const [blocked, setBlocked] = useState(false);
|
|
743
1075
|
const [now, setNow] = useState(() => Date.now());
|
|
1076
|
+
const [draft, setDraft] = 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] = useState(null);
|
|
1080
|
+
const [usedToday, setUsedToday] = useState(false);
|
|
1081
|
+
const showing = active && !off;
|
|
1082
|
+
const behindChat = open && !active && !off;
|
|
744
1083
|
const phaseRef = useRef(IDLE);
|
|
745
|
-
const latest = useRef({
|
|
746
|
-
|
|
1084
|
+
const latest = useRef({
|
|
1085
|
+
live,
|
|
1086
|
+
locale,
|
|
1087
|
+
base,
|
|
1088
|
+
headers,
|
|
1089
|
+
off,
|
|
1090
|
+
currentPath,
|
|
1091
|
+
showing
|
|
1092
|
+
});
|
|
1093
|
+
latest.current = { live, locale, base, headers, off, currentPath, showing };
|
|
747
1094
|
const conversationRef = useRef(conversation);
|
|
748
1095
|
conversationRef.current = conversation;
|
|
1096
|
+
const waitRef = useRef(null);
|
|
1097
|
+
const sendingRef = useRef(false);
|
|
1098
|
+
const textBoxRef = useRef(false);
|
|
749
1099
|
const checkRef = useRef(null);
|
|
750
1100
|
const askedLocale = useRef(locale);
|
|
751
1101
|
const startRef = useRef(null);
|
|
@@ -759,8 +1109,32 @@ function AvatarLiveView({
|
|
|
759
1109
|
phaseRef.current = next;
|
|
760
1110
|
setPhase(next);
|
|
761
1111
|
}, []);
|
|
1112
|
+
const inSight = useCallback(
|
|
1113
|
+
() => latest.current.showing && (typeof document === "undefined" || document.visibilityState !== "hidden"),
|
|
1114
|
+
[]
|
|
1115
|
+
);
|
|
1116
|
+
const setMode = useCallback((next) => {
|
|
1117
|
+
questionsRef.current = next;
|
|
1118
|
+
setQuestions(next);
|
|
1119
|
+
}, []);
|
|
1120
|
+
const exchangeNow = useCallback(
|
|
1121
|
+
() => offeredAt(
|
|
1122
|
+
firstExchange(conversationRef.current?.messages, {
|
|
1123
|
+
any: questionsRef.current === "any",
|
|
1124
|
+
askedHere: askedHereRef.current,
|
|
1125
|
+
token: conversationRef.current?.getConversationToken() ?? null,
|
|
1126
|
+
inFlight: inFlight(conversationRef.current)
|
|
1127
|
+
}),
|
|
1128
|
+
Date.now()
|
|
1129
|
+
),
|
|
1130
|
+
[]
|
|
1131
|
+
);
|
|
762
1132
|
const offeredNow = useCallback(
|
|
763
|
-
() =>
|
|
1133
|
+
() => exchangeNow().answerId,
|
|
1134
|
+
[exchangeNow]
|
|
1135
|
+
);
|
|
1136
|
+
const pathNow = useCallback(
|
|
1137
|
+
() => latest.current.currentPath ?? (typeof window === "undefined" ? "" : window.location.pathname),
|
|
764
1138
|
[]
|
|
765
1139
|
);
|
|
766
1140
|
const reoffer = useCallback(
|
|
@@ -793,6 +1167,17 @@ function AvatarLiveView({
|
|
|
793
1167
|
},
|
|
794
1168
|
[go]
|
|
795
1169
|
);
|
|
1170
|
+
const goLive = useCallback(() => {
|
|
1171
|
+
const current = phaseRef.current;
|
|
1172
|
+
const handle = sessionRef.current;
|
|
1173
|
+
if (current.name !== "pending" || !handle) return;
|
|
1174
|
+
handle.speakerArrived = true;
|
|
1175
|
+
if (questionsRef.current === "any") {
|
|
1176
|
+
noteUsedToday();
|
|
1177
|
+
setUsedToday(true);
|
|
1178
|
+
}
|
|
1179
|
+
go({ name: "live", session: current.session });
|
|
1180
|
+
}, [go]);
|
|
796
1181
|
const cancelStart = useCallback((reason) => {
|
|
797
1182
|
const run = startRef.current;
|
|
798
1183
|
if (!run) return;
|
|
@@ -800,6 +1185,36 @@ function AvatarLiveView({
|
|
|
800
1185
|
run.cancelled = reason;
|
|
801
1186
|
run.turnstile?.cancel();
|
|
802
1187
|
}, []);
|
|
1188
|
+
const applyAvailability = useCallback(
|
|
1189
|
+
(result, locale2) => {
|
|
1190
|
+
const { live: live2 } = latest.current;
|
|
1191
|
+
if (result.kind === "inert") {
|
|
1192
|
+
setMode("suggested");
|
|
1193
|
+
go(INERT2);
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
if (result.kind === "refused") {
|
|
1197
|
+
setMode(result.questions);
|
|
1198
|
+
go({ name: "refused", reason: result.reason });
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
setUsedToday(usedTodayHere());
|
|
1202
|
+
const copy = avatarConsentCopy(result.offer.consentVersion, locale2);
|
|
1203
|
+
if (copy === null || copy.botCheck !== result.offer.botCheck || copy.questions !== result.offer.questions) {
|
|
1204
|
+
setMode("suggested");
|
|
1205
|
+
go(INERT2);
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
if (result.offer.botCheck === "turnstile" && turnstileSiteKeyOf(live2) === null) {
|
|
1209
|
+
setMode("suggested");
|
|
1210
|
+
go(INERT2);
|
|
1211
|
+
return;
|
|
1212
|
+
}
|
|
1213
|
+
setMode(result.offer.questions);
|
|
1214
|
+
go(reoffer({ ...result.offer, locale: locale2, copy }));
|
|
1215
|
+
},
|
|
1216
|
+
[go, reoffer, setMode]
|
|
1217
|
+
);
|
|
803
1218
|
const check = useCallback(() => {
|
|
804
1219
|
const { live: live2, locale: locale2, base: base2, headers: headers2, off: off2 } = latest.current;
|
|
805
1220
|
checkRef.current?.abort();
|
|
@@ -821,26 +1236,9 @@ function AvatarLiveView({
|
|
|
821
1236
|
}).then((result) => {
|
|
822
1237
|
if (checkRef.current !== controller) return;
|
|
823
1238
|
checkRef.current = null;
|
|
824
|
-
|
|
825
|
-
go(INERT2);
|
|
826
|
-
return;
|
|
827
|
-
}
|
|
828
|
-
if (result.kind === "refused") {
|
|
829
|
-
go({ name: "refused", reason: result.reason });
|
|
830
|
-
return;
|
|
831
|
-
}
|
|
832
|
-
const copy = avatarConsentCopy(result.offer.consentVersion, locale2);
|
|
833
|
-
if (copy === null || copy.botCheck !== result.offer.botCheck) {
|
|
834
|
-
go(INERT2);
|
|
835
|
-
return;
|
|
836
|
-
}
|
|
837
|
-
if (result.offer.botCheck === "turnstile" && turnstileSiteKeyOf(live2) === null) {
|
|
838
|
-
go(INERT2);
|
|
839
|
-
return;
|
|
840
|
-
}
|
|
841
|
-
go(reoffer({ ...result.offer, locale: locale2, copy }));
|
|
1239
|
+
applyAvailability(result, locale2);
|
|
842
1240
|
});
|
|
843
|
-
}, [
|
|
1241
|
+
}, [applyAvailability, go]);
|
|
844
1242
|
const begin = useCallback(
|
|
845
1243
|
(session, module, offer, target) => {
|
|
846
1244
|
const received = Date.now();
|
|
@@ -885,8 +1283,8 @@ function AvatarLiveView({
|
|
|
885
1283
|
reason: run.cancelled
|
|
886
1284
|
});
|
|
887
1285
|
}
|
|
888
|
-
const
|
|
889
|
-
if (claimed &&
|
|
1286
|
+
const shown2 = phaseRef.current;
|
|
1287
|
+
if (claimed && shown2.name === "consent" && shown2.messageId === context.messageId) {
|
|
890
1288
|
go({ name: "refused", reason: "answer_claimed" });
|
|
891
1289
|
}
|
|
892
1290
|
return;
|
|
@@ -921,86 +1319,186 @@ function AvatarLiveView({
|
|
|
921
1319
|
},
|
|
922
1320
|
[begin, check, go]
|
|
923
1321
|
);
|
|
1322
|
+
const launch = useCallback(
|
|
1323
|
+
(offer, messageId, preloaded) => {
|
|
1324
|
+
const { live: live2, base: base2, headers: headers2 } = latest.current;
|
|
1325
|
+
if (base2 === null) return;
|
|
1326
|
+
const exchangeAtStart = exchangeNow();
|
|
1327
|
+
if (exchangeAtStart.answerId !== messageId) {
|
|
1328
|
+
go(reoffer(offer));
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
if (claimedRef.current.has(messageId)) {
|
|
1332
|
+
go({ name: "refused", reason: "answer_claimed" });
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1335
|
+
const refusedFrom = exchangeAtStart.offerUntil - ANSWER_OFFER_MS + SERVICE_MAX_AGE_MS;
|
|
1336
|
+
const siteKey = offer.botCheck === "turnstile" ? turnstileSiteKeyOf(live2) : null;
|
|
1337
|
+
if (offer.botCheck === "turnstile" && (siteKey === null || !canBindBotCheck())) {
|
|
1338
|
+
go(INERT2);
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
const conversationToken = conversationRef.current?.getConversationToken() ?? null;
|
|
1342
|
+
const idempotencyKey = newIdempotencyKey();
|
|
1343
|
+
if (conversationToken === null || !isAvatarConversationToken(conversationToken) || idempotencyKey === null) {
|
|
1344
|
+
go({ name: "ended", how: "failed" });
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
const body2 = {
|
|
1348
|
+
site: live2.site,
|
|
1349
|
+
locale: offer.locale,
|
|
1350
|
+
conversationToken,
|
|
1351
|
+
messageId,
|
|
1352
|
+
consentVersion: offer.consentVersion,
|
|
1353
|
+
manifestVersion: live2.manifestVersion
|
|
1354
|
+
};
|
|
1355
|
+
const run = { cancelled: null, turnstile: null };
|
|
1356
|
+
startRef.current = run;
|
|
1357
|
+
const module = preloaded ?? loadModule(live2.load);
|
|
1358
|
+
let turnstile = null;
|
|
1359
|
+
if (siteKey === null) {
|
|
1360
|
+
go({ name: "creating" });
|
|
1361
|
+
} else {
|
|
1362
|
+
go({ name: "bot-check", offer, messageId });
|
|
1363
|
+
turnstile = runTurnstile(
|
|
1364
|
+
botBoxRef.current,
|
|
1365
|
+
siteKey,
|
|
1366
|
+
"avatar_start",
|
|
1367
|
+
avatarBotBinding(body2)
|
|
1368
|
+
);
|
|
1369
|
+
run.turnstile = turnstile;
|
|
1370
|
+
}
|
|
1371
|
+
void (async () => {
|
|
1372
|
+
let loaded;
|
|
1373
|
+
let botToken;
|
|
1374
|
+
try {
|
|
1375
|
+
[loaded, botToken] = await Promise.all([module, turnstile?.token]);
|
|
1376
|
+
} catch {
|
|
1377
|
+
turnstile?.cancel();
|
|
1378
|
+
if (run.cancelled === null) {
|
|
1379
|
+
startRef.current = null;
|
|
1380
|
+
go(INERT2);
|
|
1381
|
+
}
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
turnstile?.cancel();
|
|
1385
|
+
if (run.cancelled !== null) return;
|
|
1386
|
+
if (!(Date.now() < refusedFrom)) {
|
|
1387
|
+
startRef.current = null;
|
|
1388
|
+
go({ name: "needs-answer", offer });
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
if (turnstile !== null) go({ name: "creating" });
|
|
1392
|
+
const result = await requestCreate({
|
|
1393
|
+
base: base2,
|
|
1394
|
+
headers: headers2,
|
|
1395
|
+
idempotencyKey,
|
|
1396
|
+
botToken,
|
|
1397
|
+
body: body2
|
|
1398
|
+
});
|
|
1399
|
+
if (startRef.current === run) startRef.current = null;
|
|
1400
|
+
settle(result, run, {
|
|
1401
|
+
module: loaded,
|
|
1402
|
+
offer,
|
|
1403
|
+
messageId,
|
|
1404
|
+
base: base2,
|
|
1405
|
+
headers: headers2
|
|
1406
|
+
});
|
|
1407
|
+
})();
|
|
1408
|
+
},
|
|
1409
|
+
[exchangeNow, go, reoffer, settle]
|
|
1410
|
+
);
|
|
924
1411
|
const start = useCallback(() => {
|
|
925
1412
|
const current = phaseRef.current;
|
|
926
1413
|
if (current.name !== "consent") return;
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1414
|
+
if (current.offer.questions === "any") unlockSound(audioRef.current);
|
|
1415
|
+
launch(current.offer, current.messageId, null);
|
|
1416
|
+
}, [launch]);
|
|
1417
|
+
const cancelWaiting = useCallback(
|
|
1418
|
+
(told) => {
|
|
1419
|
+
const wait = waitRef.current;
|
|
1420
|
+
waitRef.current = null;
|
|
1421
|
+
wait?.check?.abort();
|
|
1422
|
+
const current = phaseRef.current;
|
|
1423
|
+
if (current.name !== "waiting") return;
|
|
1424
|
+
if (told) setNote("cancelled");
|
|
1425
|
+
go({ name: "needs-answer", offer: current.offer });
|
|
1426
|
+
},
|
|
1427
|
+
[go]
|
|
1428
|
+
);
|
|
1429
|
+
const bindingHolds = useCallback(
|
|
1430
|
+
(bound, exchange2) => {
|
|
1431
|
+
const { live: live2, locale: locale2 } = latest.current;
|
|
1432
|
+
return conversationRef.current?.getConversationToken() === bound.token && exchange2.question?.id === bound.questionId && live2.site === bound.site && locale2 === bound.locale && pathNow() === bound.path;
|
|
1433
|
+
},
|
|
1434
|
+
[pathNow]
|
|
1435
|
+
);
|
|
1436
|
+
const startWhenReady = useCallback(() => {
|
|
1437
|
+
const current = phaseRef.current;
|
|
1438
|
+
if (current.name !== "needs-answer") return;
|
|
1439
|
+
const { live: live2, locale: locale2 } = latest.current;
|
|
1440
|
+
const exchange2 = exchangeNow();
|
|
1441
|
+
const token2 = conversationRef.current?.getConversationToken() ?? null;
|
|
1442
|
+
if (exchange2.kind !== "asking" || !exchange2.askedHere || exchange2.question === null || exchange2.pendingAnswerId === null || token2 === null || !isAvatarConversationToken(token2)) {
|
|
944
1443
|
return;
|
|
945
1444
|
}
|
|
946
|
-
|
|
947
|
-
site: live2.site,
|
|
948
|
-
locale: offer.locale,
|
|
949
|
-
conversationToken,
|
|
950
|
-
messageId,
|
|
951
|
-
consentVersion: offer.consentVersion,
|
|
952
|
-
manifestVersion: live2.manifestVersion
|
|
953
|
-
};
|
|
954
|
-
const run = { cancelled: null, turnstile: null };
|
|
955
|
-
startRef.current = run;
|
|
1445
|
+
unlockSound(audioRef.current);
|
|
956
1446
|
const module = loadModule(live2.load);
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
}
|
|
981
|
-
return;
|
|
982
|
-
}
|
|
983
|
-
turnstile?.cancel();
|
|
984
|
-
if (run.cancelled !== null) return;
|
|
985
|
-
if (!(Date.now() < refusedFrom)) {
|
|
986
|
-
startRef.current = null;
|
|
987
|
-
go({ name: "needs-answer", offer });
|
|
1447
|
+
module.catch(() => void 0);
|
|
1448
|
+
waitRef.current = {
|
|
1449
|
+
bound: {
|
|
1450
|
+
token: token2,
|
|
1451
|
+
questionId: exchange2.question.id,
|
|
1452
|
+
answerId: exchange2.pendingAnswerId,
|
|
1453
|
+
site: live2.site,
|
|
1454
|
+
locale: locale2,
|
|
1455
|
+
path: pathNow(),
|
|
1456
|
+
consentVersion: current.offer.consentVersion,
|
|
1457
|
+
botCheck: current.offer.botCheck
|
|
1458
|
+
},
|
|
1459
|
+
module,
|
|
1460
|
+
check: null
|
|
1461
|
+
};
|
|
1462
|
+
setNote(null);
|
|
1463
|
+
go({ name: "waiting", offer: current.offer });
|
|
1464
|
+
}, [exchangeNow, go, pathNow]);
|
|
1465
|
+
const confirm = useCallback(
|
|
1466
|
+
(offer, wait) => {
|
|
1467
|
+
const { live: live2, locale: locale2, base: base2, headers: headers2 } = latest.current;
|
|
1468
|
+
if (base2 === null) {
|
|
1469
|
+
cancelWaiting(true);
|
|
988
1470
|
return;
|
|
989
1471
|
}
|
|
990
|
-
|
|
991
|
-
|
|
1472
|
+
const controller = new AbortController();
|
|
1473
|
+
wait.check = controller;
|
|
1474
|
+
void requestAvailability({
|
|
992
1475
|
base: base2,
|
|
993
1476
|
headers: headers2,
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1477
|
+
site: live2.site,
|
|
1478
|
+
locale: locale2,
|
|
1479
|
+
signal: controller.signal
|
|
1480
|
+
}).then((result) => {
|
|
1481
|
+
if (waitRef.current !== wait || phaseRef.current.name !== "waiting") {
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
waitRef.current = null;
|
|
1485
|
+
const exchange2 = exchangeNow();
|
|
1486
|
+
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);
|
|
1487
|
+
if (!same || result.kind !== "available") {
|
|
1488
|
+
applyAvailability(result, locale2);
|
|
1489
|
+
return;
|
|
1490
|
+
}
|
|
1491
|
+
launch({ ...offer, ...result.offer }, wait.bound.answerId, wait.module);
|
|
997
1492
|
});
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
}, [go, offeredNow, reoffer, settle]);
|
|
1493
|
+
},
|
|
1494
|
+
[applyAvailability, bindingHolds, cancelWaiting, exchangeNow, launch]
|
|
1495
|
+
);
|
|
1002
1496
|
const stop = useCallback(() => {
|
|
1003
1497
|
const current = phaseRef.current;
|
|
1498
|
+
if (current.name === "waiting") {
|
|
1499
|
+
cancelWaiting(false);
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1004
1502
|
if (current.name === "bot-check") {
|
|
1005
1503
|
cancelStart("user");
|
|
1006
1504
|
go(reoffer(current.offer));
|
|
@@ -1014,11 +1512,13 @@ function AvatarLiveView({
|
|
|
1014
1512
|
if (current.name === "pending" || current.name === "live") {
|
|
1015
1513
|
finish("stopped", "user");
|
|
1016
1514
|
}
|
|
1017
|
-
}, [cancelStart, finish, go, reoffer]);
|
|
1515
|
+
}, [cancelStart, cancelWaiting, finish, go, reoffer]);
|
|
1018
1516
|
const leave = useCallback(
|
|
1019
|
-
(
|
|
1517
|
+
(event) => {
|
|
1020
1518
|
const current = phaseRef.current;
|
|
1519
|
+
const reason = event === "user" || event === "chat" ? "user" : "page_hide";
|
|
1021
1520
|
const how = reason === "user" ? "stopped" : "interrupted";
|
|
1521
|
+
const keepsSession = event === "chat" || event === "hidden";
|
|
1022
1522
|
switch (current.name) {
|
|
1023
1523
|
case "checking": {
|
|
1024
1524
|
if (reason !== "user") return;
|
|
@@ -1028,49 +1528,63 @@ function AvatarLiveView({
|
|
|
1028
1528
|
go(IDLE);
|
|
1029
1529
|
return;
|
|
1030
1530
|
}
|
|
1531
|
+
case "waiting":
|
|
1532
|
+
cancelWaiting(true);
|
|
1533
|
+
return;
|
|
1031
1534
|
case "bot-check":
|
|
1032
1535
|
cancelStart(reason);
|
|
1033
1536
|
go(reason === "user" ? IDLE : reoffer(current.offer));
|
|
1034
1537
|
return;
|
|
1035
1538
|
case "creating":
|
|
1539
|
+
if (keepsSession) return;
|
|
1036
1540
|
cancelStart(reason);
|
|
1037
1541
|
go({ name: "ended", how });
|
|
1038
1542
|
return;
|
|
1039
1543
|
case "pending":
|
|
1040
1544
|
case "live":
|
|
1545
|
+
if (keepsSession) {
|
|
1546
|
+
if (current.name === "pending" && sessionRef.current?.speakerArrived) {
|
|
1547
|
+
goLive();
|
|
1548
|
+
}
|
|
1549
|
+
return;
|
|
1550
|
+
}
|
|
1041
1551
|
finish(how, reason);
|
|
1042
1552
|
return;
|
|
1043
1553
|
default:
|
|
1044
1554
|
return;
|
|
1045
1555
|
}
|
|
1046
1556
|
},
|
|
1047
|
-
[cancelStart, finish, go, reoffer]
|
|
1557
|
+
[cancelStart, cancelWaiting, finish, go, goLive, reoffer]
|
|
1048
1558
|
);
|
|
1049
|
-
const showing = active && !off;
|
|
1050
1559
|
useEffect(() => {
|
|
1051
1560
|
if (!showing) {
|
|
1052
|
-
leave("user");
|
|
1561
|
+
leave(behindChat ? "chat" : "user");
|
|
1053
1562
|
return;
|
|
1054
1563
|
}
|
|
1055
1564
|
const current = phaseRef.current;
|
|
1565
|
+
if (current.name === "creating" || current.name === "pending" || current.name === "live") {
|
|
1566
|
+
setNow(Date.now());
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1056
1569
|
const offered = offeredNow();
|
|
1057
1570
|
const used = offered !== null && claimedRef.current.has(offered);
|
|
1058
1571
|
if (current.name === "ended" && used) return;
|
|
1059
1572
|
if (current.name === "refused" && current.reason === "answer_claimed" && used) {
|
|
1060
1573
|
return;
|
|
1061
1574
|
}
|
|
1062
|
-
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
|
|
1575
|
+
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
|
|
1063
1576
|
// left, and the unmount in between dropped the question. (This view mounts already showing, the first time the
|
|
1064
1577
|
// Avatar view opens.)
|
|
1065
1578
|
current.name === "checking" && checkRef.current === null) {
|
|
1066
1579
|
check();
|
|
1067
1580
|
}
|
|
1068
|
-
}, [showing, check, leave, offeredNow]);
|
|
1581
|
+
}, [showing, behindChat, check, leave, offeredNow]);
|
|
1069
1582
|
useEffect(() => {
|
|
1070
1583
|
if (askedLocale.current === locale) return;
|
|
1071
1584
|
askedLocale.current = locale;
|
|
1585
|
+
if (phaseRef.current.name === "waiting") cancelWaiting(true);
|
|
1072
1586
|
const current = phaseRef.current.name;
|
|
1073
|
-
if (current !== "checking" && current !== "needs-answer" && current !== "consent" && current !== "refused" && current !== "inert") {
|
|
1587
|
+
if (current !== "checking" && current !== "needs-answer" && current !== "consent" && current !== "declined" && current !== "refused" && current !== "inert") {
|
|
1074
1588
|
return;
|
|
1075
1589
|
}
|
|
1076
1590
|
if (active) {
|
|
@@ -1080,7 +1594,8 @@ function AvatarLiveView({
|
|
|
1080
1594
|
checkRef.current = null;
|
|
1081
1595
|
go(IDLE);
|
|
1082
1596
|
}
|
|
1083
|
-
}, [active, check, go, locale]);
|
|
1597
|
+
}, [active, cancelWaiting, check, go, locale]);
|
|
1598
|
+
const kind = shown.kind;
|
|
1084
1599
|
useEffect(() => {
|
|
1085
1600
|
const current = phaseRef.current;
|
|
1086
1601
|
if (current.name === "needs-answer" && answerId !== null) {
|
|
@@ -1089,8 +1604,49 @@ function AvatarLiveView({
|
|
|
1089
1604
|
go(
|
|
1090
1605
|
answerId === null ? { name: "needs-answer", offer: current.offer } : { ...current, messageId: answerId }
|
|
1091
1606
|
);
|
|
1607
|
+
} else if (current.name === "declined" && answerId === null) {
|
|
1608
|
+
if (kind !== "asking") go({ name: "needs-answer", offer: current.offer });
|
|
1609
|
+
}
|
|
1610
|
+
}, [answerId, kind, go]);
|
|
1611
|
+
useEffect(() => {
|
|
1612
|
+
const current = phaseRef.current;
|
|
1613
|
+
const wait = waitRef.current;
|
|
1614
|
+
if (current.name !== "waiting" || wait === null || wait.check !== null) {
|
|
1615
|
+
return;
|
|
1616
|
+
}
|
|
1617
|
+
const now2 = exchangeNow();
|
|
1618
|
+
const holds = bindingHolds(wait.bound, now2);
|
|
1619
|
+
if (holds && now2.kind === "asking" && now2.pendingAnswerId === wait.bound.answerId) {
|
|
1620
|
+
return;
|
|
1621
|
+
}
|
|
1622
|
+
if (!holds || now2.kind !== "answer" || now2.answerId !== wait.bound.answerId) {
|
|
1623
|
+
cancelWaiting(now2.kind !== "failed" && now2.kind !== "text-only");
|
|
1624
|
+
return;
|
|
1625
|
+
}
|
|
1626
|
+
confirm(current.offer, wait);
|
|
1627
|
+
});
|
|
1628
|
+
const resent = conversation?.resent ?? null;
|
|
1629
|
+
useEffect(() => {
|
|
1630
|
+
const asked = askedHereRef.current;
|
|
1631
|
+
if (resent === null || asked === null || !resent.replacedMessageIds.includes(asked.messageId)) {
|
|
1632
|
+
return;
|
|
1092
1633
|
}
|
|
1093
|
-
|
|
1634
|
+
setAskedHere({
|
|
1635
|
+
messageId: resent.sent.userMessageId,
|
|
1636
|
+
token: resent.sent.conversationToken
|
|
1637
|
+
});
|
|
1638
|
+
}, [resent, setAskedHere]);
|
|
1639
|
+
const empty = (conversation?.messages.length ?? 0) === 0;
|
|
1640
|
+
useEffect(() => {
|
|
1641
|
+
if (empty) setAskedHere(null);
|
|
1642
|
+
}, [empty, setAskedHere]);
|
|
1643
|
+
useEffect(() => {
|
|
1644
|
+
const asked = askedHereRef.current;
|
|
1645
|
+
if (asked !== null && asked.token !== token) setAskedHere(null);
|
|
1646
|
+
}, [token, setAskedHere]);
|
|
1647
|
+
useEffect(() => {
|
|
1648
|
+
if (showing) setUsedToday(usedTodayHere());
|
|
1649
|
+
}, [showing]);
|
|
1094
1650
|
useEffect(() => {
|
|
1095
1651
|
if (offerUntil === null) return;
|
|
1096
1652
|
const timer = setTimeout(
|
|
@@ -1109,7 +1665,9 @@ function AvatarLiveView({
|
|
|
1109
1665
|
const wasLive = phaseRef.current.name === "live";
|
|
1110
1666
|
switch (event.type) {
|
|
1111
1667
|
case "speaker-track":
|
|
1112
|
-
if (event.kind
|
|
1668
|
+
if (event.kind !== "video") return;
|
|
1669
|
+
handle.speakerArrived = true;
|
|
1670
|
+
if (!inSight()) goLive();
|
|
1113
1671
|
return;
|
|
1114
1672
|
case "playback-blocked":
|
|
1115
1673
|
setBlocked(event.blocked);
|
|
@@ -1126,7 +1684,7 @@ function AvatarLiveView({
|
|
|
1126
1684
|
return;
|
|
1127
1685
|
}
|
|
1128
1686
|
},
|
|
1129
|
-
[finish]
|
|
1687
|
+
[finish, goLive, inSight]
|
|
1130
1688
|
);
|
|
1131
1689
|
useEffect(() => {
|
|
1132
1690
|
if (phase.name !== "pending") return;
|
|
@@ -1200,11 +1758,23 @@ function AvatarLiveView({
|
|
|
1200
1758
|
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
1201
1759
|
return () => clearInterval(timer);
|
|
1202
1760
|
}, [ticking]);
|
|
1761
|
+
const voiceLine = phase.name === "live" ? S.speaking : phase.name === "creating" || phase.name === "pending" ? S.connecting : null;
|
|
1762
|
+
const onVoiceHoldRef = useRef(onVoiceHold);
|
|
1763
|
+
onVoiceHoldRef.current = onVoiceHold;
|
|
1764
|
+
useEffect(() => {
|
|
1765
|
+
onVoiceHoldRef.current?.(voiceLine);
|
|
1766
|
+
}, [voiceLine]);
|
|
1767
|
+
useEffect(() => () => onVoiceHoldRef.current?.(null), []);
|
|
1203
1768
|
useEffect(() => {
|
|
1204
1769
|
if (typeof window === "undefined") return;
|
|
1205
1770
|
const onPageHide = () => leave("page_hide");
|
|
1206
1771
|
const onVisibility = () => {
|
|
1207
|
-
if (document.visibilityState === "hidden")
|
|
1772
|
+
if (document.visibilityState === "hidden") {
|
|
1773
|
+
leave("hidden");
|
|
1774
|
+
return;
|
|
1775
|
+
}
|
|
1776
|
+
const current = phaseRef.current.name;
|
|
1777
|
+
if (current === "pending" || current === "live") setNow(Date.now());
|
|
1208
1778
|
};
|
|
1209
1779
|
window.addEventListener("pagehide", onPageHide);
|
|
1210
1780
|
document.addEventListener("visibilitychange", onVisibility);
|
|
@@ -1224,6 +1794,9 @@ function AvatarLiveView({
|
|
|
1224
1794
|
run.cancelled = "user";
|
|
1225
1795
|
run.turnstile?.cancel();
|
|
1226
1796
|
}
|
|
1797
|
+
const wait = waitRef.current;
|
|
1798
|
+
waitRef.current = null;
|
|
1799
|
+
wait?.check?.abort();
|
|
1227
1800
|
const handle = sessionRef.current;
|
|
1228
1801
|
sessionRef.current = null;
|
|
1229
1802
|
if (handle && !handle.done) {
|
|
@@ -1240,19 +1813,74 @@ function AvatarLiveView({
|
|
|
1240
1813
|
},
|
|
1241
1814
|
[]
|
|
1242
1815
|
);
|
|
1816
|
+
const any = questions === "any";
|
|
1817
|
+
const textMode = any && (usedToday && (phase.name === "needs-answer" || phase.name === "consent" || phase.name === "declined" || phase.name === "ended") || phase.name === "refused" && phase.reason === "limits");
|
|
1818
|
+
textBoxRef.current = textMode;
|
|
1819
|
+
const askState = !any ? void 0 : textMode ? "text" : phase.name === "needs-answer" ? kind === "empty" ? "ready" : kind : phase.name;
|
|
1820
|
+
const notNow = useCallback(() => {
|
|
1821
|
+
const current = phaseRef.current;
|
|
1822
|
+
if ((current.name === "consent" || current.name === "needs-answer") && current.offer.questions === "any") {
|
|
1823
|
+
go({ name: "declined", offer: current.offer });
|
|
1824
|
+
return;
|
|
1825
|
+
}
|
|
1826
|
+
onContinueInChat();
|
|
1827
|
+
}, [go, onContinueInChat]);
|
|
1828
|
+
const ask = useCallback(
|
|
1829
|
+
(text) => {
|
|
1830
|
+
const conversation2 = conversationRef.current;
|
|
1831
|
+
const question = text.trim();
|
|
1832
|
+
if (conversation2 === null || question === "" || sendingRef.current) {
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
const spoken = !textBoxRef.current;
|
|
1836
|
+
if (spoken && conversation2.messages.length > 0) return;
|
|
1837
|
+
sendingRef.current = true;
|
|
1838
|
+
setAskedHere(null);
|
|
1839
|
+
const seq = askSeqRef.current;
|
|
1840
|
+
setNote(null);
|
|
1841
|
+
setDraft("");
|
|
1842
|
+
void conversation2.send(question, [], spoken ? { surface: "AVATAR" } : {}).then((added) => {
|
|
1843
|
+
if (added === null) {
|
|
1844
|
+
setDraft((current) => current === "" ? question : current);
|
|
1845
|
+
}
|
|
1846
|
+
if (!spoken || added === null || askSeqRef.current !== seq || added.conversationToken !== (conversationRef.current?.getConversationToken() ?? null)) {
|
|
1847
|
+
return;
|
|
1848
|
+
}
|
|
1849
|
+
setAskedHere({
|
|
1850
|
+
messageId: added.userMessageId,
|
|
1851
|
+
token: added.conversationToken
|
|
1852
|
+
});
|
|
1853
|
+
}).finally(() => {
|
|
1854
|
+
sendingRef.current = false;
|
|
1855
|
+
});
|
|
1856
|
+
},
|
|
1857
|
+
[setAskedHere]
|
|
1858
|
+
);
|
|
1859
|
+
const newChatForAvatar = useCallback(() => {
|
|
1860
|
+
const conversation2 = conversationRef.current;
|
|
1861
|
+
if (conversation2 === null) return;
|
|
1862
|
+
const now2 = exchangeNow();
|
|
1863
|
+
const failedQuestion = now2.kind === "failed" ? now2.question?.content ?? null : null;
|
|
1864
|
+
conversation2.reset();
|
|
1865
|
+
setAskedHere(null);
|
|
1866
|
+
setNote("new-chat");
|
|
1867
|
+
if (failedQuestion !== null) {
|
|
1868
|
+
setDraft((current2) => current2 === "" ? failedQuestion : current2);
|
|
1869
|
+
}
|
|
1870
|
+
const current = phaseRef.current;
|
|
1871
|
+
if (current.name === "needs-answer" || current.name === "consent" || current.name === "declined") {
|
|
1872
|
+
go({ name: "needs-answer", offer: current.offer });
|
|
1873
|
+
} else {
|
|
1874
|
+
check();
|
|
1875
|
+
}
|
|
1876
|
+
}, [check, exchangeNow, go, setAskedHere]);
|
|
1243
1877
|
useEffect(() => {
|
|
1244
1878
|
if (!active) return;
|
|
1245
1879
|
const focused = document.activeElement;
|
|
1246
1880
|
if (focused && focused !== document.body && focused.isConnected) return;
|
|
1247
1881
|
rootRef.current?.querySelector(PRIMARY)?.focus();
|
|
1248
|
-
}, [active, phase.name, blocked]);
|
|
1249
|
-
const onPlaying =
|
|
1250
|
-
const current = phaseRef.current;
|
|
1251
|
-
const handle = sessionRef.current;
|
|
1252
|
-
if (current.name !== "pending" || !handle) return;
|
|
1253
|
-
handle.speakerArrived = true;
|
|
1254
|
-
go({ name: "live", session: current.session });
|
|
1255
|
-
}, [go]);
|
|
1882
|
+
}, [active, phase.name, askState, shown.pendingAnswerId, blocked]);
|
|
1883
|
+
const onPlaying = goLive;
|
|
1256
1884
|
const enablePlayback = useCallback(() => {
|
|
1257
1885
|
void sessionRef.current?.joined?.enablePlayback().catch(() => void 0);
|
|
1258
1886
|
}, []);
|
|
@@ -1283,7 +1911,7 @@ function AvatarLiveView({
|
|
|
1283
1911
|
height: small ? 64 : 128,
|
|
1284
1912
|
className: cn(
|
|
1285
1913
|
"shrink-0 rounded-full border border-border object-cover shadow-sm",
|
|
1286
|
-
small ? "h-16 w-16" : "h-32 w-32"
|
|
1914
|
+
small ? "h-16 w-16" : any ? "h-[min(12rem,32dvh)] w-[min(12rem,32dvh)]" : "h-32 w-32"
|
|
1287
1915
|
)
|
|
1288
1916
|
}
|
|
1289
1917
|
);
|
|
@@ -1332,12 +1960,440 @@ function AvatarLiveView({
|
|
|
1332
1960
|
children: S.stop
|
|
1333
1961
|
}
|
|
1334
1962
|
);
|
|
1963
|
+
const readInChatButton = (primary) => /* @__PURE__ */ jsx(
|
|
1964
|
+
"button",
|
|
1965
|
+
{
|
|
1966
|
+
type: "button",
|
|
1967
|
+
"data-avatar-primary": primary ? "" : void 0,
|
|
1968
|
+
"data-boff-explore": "avatar-live-read-in-chat",
|
|
1969
|
+
className: primary ? primaryButton : secondaryButton,
|
|
1970
|
+
onClick: onContinueInChat,
|
|
1971
|
+
children: S.readInChat
|
|
1972
|
+
}
|
|
1973
|
+
);
|
|
1974
|
+
const consentCard = (copy) => /* @__PURE__ */ jsxs(
|
|
1975
|
+
"section",
|
|
1976
|
+
{
|
|
1977
|
+
"aria-labelledby": consentTitleId,
|
|
1978
|
+
"data-boff-explore": "avatar-live-consent",
|
|
1979
|
+
className: "w-full max-w-sm rounded-lg border border-border p-4 text-start",
|
|
1980
|
+
children: [
|
|
1981
|
+
/* @__PURE__ */ jsx("h2", { id: consentTitleId, className: "text-base font-semibold", children: copy.title }),
|
|
1982
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm", children: productName === null || copy.introProduct === null ? copy.intro : fill(copy.introProduct, { product: productName }) }),
|
|
1983
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: copy.processing }),
|
|
1984
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: copy.storage }),
|
|
1985
|
+
/* @__PURE__ */ jsxs(
|
|
1986
|
+
"a",
|
|
1987
|
+
{
|
|
1988
|
+
href: PRIVACY_HREF,
|
|
1989
|
+
target: "_blank",
|
|
1990
|
+
rel: "noopener noreferrer",
|
|
1991
|
+
"data-boff-explore": "avatar-live-privacy",
|
|
1992
|
+
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",
|
|
1993
|
+
children: [
|
|
1994
|
+
copy.privacyLink,
|
|
1995
|
+
/* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
|
|
1996
|
+
" ",
|
|
1997
|
+
S.opensInNewTab
|
|
1998
|
+
] })
|
|
1999
|
+
]
|
|
2000
|
+
}
|
|
2001
|
+
)
|
|
2002
|
+
]
|
|
2003
|
+
}
|
|
2004
|
+
);
|
|
2005
|
+
const consentActions = (whenReady) => /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
|
|
2006
|
+
/* @__PURE__ */ jsx(
|
|
2007
|
+
"button",
|
|
2008
|
+
{
|
|
2009
|
+
type: "button",
|
|
2010
|
+
"data-avatar-primary": "",
|
|
2011
|
+
"data-boff-explore": whenReady ? "avatar-live-start-when-ready" : "avatar-live-start",
|
|
2012
|
+
className: primaryButton,
|
|
2013
|
+
onClick: whenReady ? startWhenReady : start,
|
|
2014
|
+
children: whenReady ? S.startWhenReady : S.start
|
|
2015
|
+
}
|
|
2016
|
+
),
|
|
2017
|
+
/* @__PURE__ */ jsx(
|
|
2018
|
+
"button",
|
|
2019
|
+
{
|
|
2020
|
+
type: "button",
|
|
2021
|
+
"data-boff-explore": "avatar-live-not-now",
|
|
2022
|
+
className: secondaryButton,
|
|
2023
|
+
onClick: notNow,
|
|
2024
|
+
children: S.notNow
|
|
2025
|
+
}
|
|
2026
|
+
)
|
|
2027
|
+
] });
|
|
2028
|
+
const liveMedia = (playing) => /* @__PURE__ */ jsxs(
|
|
2029
|
+
"div",
|
|
2030
|
+
{
|
|
2031
|
+
className: cn(
|
|
2032
|
+
"relative shrink-0 overflow-hidden rounded-xl border border-border bg-muted",
|
|
2033
|
+
any ? "h-[min(12rem,32dvh)] w-[min(12rem,32dvh)]" : "h-48 w-48"
|
|
2034
|
+
),
|
|
2035
|
+
children: [
|
|
2036
|
+
/* @__PURE__ */ jsx(
|
|
2037
|
+
"video",
|
|
2038
|
+
{
|
|
2039
|
+
ref: videoRef,
|
|
2040
|
+
"aria-label": S.video,
|
|
2041
|
+
"data-boff-explore": "avatar-live-video",
|
|
2042
|
+
playsInline: true,
|
|
2043
|
+
autoPlay: true,
|
|
2044
|
+
muted: true,
|
|
2045
|
+
onPlaying,
|
|
2046
|
+
className: cn("h-full w-full object-cover", !playing && "opacity-0")
|
|
2047
|
+
}
|
|
2048
|
+
),
|
|
2049
|
+
playing ? null : /* @__PURE__ */ jsx(
|
|
2050
|
+
"img",
|
|
2051
|
+
{
|
|
2052
|
+
src: still.src,
|
|
2053
|
+
alt: "",
|
|
2054
|
+
decoding: "async",
|
|
2055
|
+
className: "absolute inset-0 h-full w-full object-cover"
|
|
2056
|
+
}
|
|
2057
|
+
),
|
|
2058
|
+
any ? null : /* @__PURE__ */ jsx("audio", { ref: audioRef, "data-boff-explore": "avatar-live-audio" })
|
|
2059
|
+
]
|
|
2060
|
+
}
|
|
2061
|
+
);
|
|
2062
|
+
const liveBody = (session) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2063
|
+
/* @__PURE__ */ jsx(
|
|
2064
|
+
"section",
|
|
2065
|
+
{
|
|
2066
|
+
"aria-label": S.captions,
|
|
2067
|
+
"data-boff-explore": "avatar-live-captions",
|
|
2068
|
+
lang: session.captions.locale || void 0,
|
|
2069
|
+
dir: "auto",
|
|
2070
|
+
tabIndex: 0,
|
|
2071
|
+
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",
|
|
2072
|
+
children: session.captions.text
|
|
2073
|
+
}
|
|
2074
|
+
),
|
|
2075
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: S.answerInChat }),
|
|
2076
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm tabular-nums text-muted-foreground", children: [
|
|
2077
|
+
S.timeLeft,
|
|
2078
|
+
" ",
|
|
2079
|
+
/* @__PURE__ */ jsx("span", { role: "timer", "data-boff-explore": "avatar-live-countdown", children: clock(Math.max(0, (session.endsAt - now) / 1e3)) })
|
|
2080
|
+
] })
|
|
2081
|
+
] });
|
|
2082
|
+
const liveActions = (back) => /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
|
|
2083
|
+
blocked ? /* @__PURE__ */ jsx(
|
|
2084
|
+
"button",
|
|
2085
|
+
{
|
|
2086
|
+
type: "button",
|
|
2087
|
+
"data-boff-explore": "avatar-live-sound",
|
|
2088
|
+
className: primaryButton,
|
|
2089
|
+
onClick: enablePlayback,
|
|
2090
|
+
children: S.tapForSound
|
|
2091
|
+
}
|
|
2092
|
+
) : null,
|
|
2093
|
+
stopButton,
|
|
2094
|
+
back
|
|
2095
|
+
] });
|
|
2096
|
+
const badge = /* @__PURE__ */ jsx(
|
|
2097
|
+
"p",
|
|
2098
|
+
{
|
|
2099
|
+
"data-boff-explore": "avatar-live-badge",
|
|
2100
|
+
className: "rounded-full bg-muted px-3 py-1 text-xs font-medium text-foreground",
|
|
2101
|
+
children: S.badge
|
|
2102
|
+
}
|
|
2103
|
+
);
|
|
2104
|
+
if (any) {
|
|
2105
|
+
let status = "";
|
|
2106
|
+
let outcome2 = false;
|
|
2107
|
+
let lead = null;
|
|
2108
|
+
let top2 = null;
|
|
2109
|
+
let media2 = stillPicture(false);
|
|
2110
|
+
let body2 = null;
|
|
2111
|
+
let actions2 = null;
|
|
2112
|
+
let newChatOffer = false;
|
|
2113
|
+
let box = null;
|
|
2114
|
+
const first = exchange.question;
|
|
2115
|
+
const questionLine = first === null ? null : /* @__PURE__ */ jsx(
|
|
2116
|
+
"p",
|
|
2117
|
+
{
|
|
2118
|
+
"data-boff-explore": "avatar-live-question",
|
|
2119
|
+
dir: "auto",
|
|
2120
|
+
className: "line-clamp-2 w-full max-w-sm break-words text-sm font-medium",
|
|
2121
|
+
children: first.content
|
|
2122
|
+
}
|
|
2123
|
+
);
|
|
2124
|
+
const activity = conversation?.activity ?? null;
|
|
2125
|
+
const activityLine = activity === null ? null : /* @__PURE__ */ jsx(
|
|
2126
|
+
"p",
|
|
2127
|
+
{
|
|
2128
|
+
"data-boff-explore": "avatar-live-activity",
|
|
2129
|
+
className: "text-xs text-muted-foreground",
|
|
2130
|
+
children: activity
|
|
2131
|
+
}
|
|
2132
|
+
);
|
|
2133
|
+
if (textMode) {
|
|
2134
|
+
const messages = conversation?.messages ?? [];
|
|
2135
|
+
let questionAt = messages.length - 1;
|
|
2136
|
+
while (questionAt >= 0 && messages[questionAt]?.role !== "USER") {
|
|
2137
|
+
questionAt -= 1;
|
|
2138
|
+
}
|
|
2139
|
+
const lastQuestion = questionAt === -1 ? void 0 : messages[questionAt];
|
|
2140
|
+
const after = questionAt === -1 ? void 0 : messages[questionAt + 1];
|
|
2141
|
+
const lastAnswer = after?.role === "ASSISTANT" ? after : void 0;
|
|
2142
|
+
const chatPhase = conversation?.phase;
|
|
2143
|
+
const unanswered = lastQuestion === void 0 || lastAnswer !== void 0 ? null : chatPhase === "sending" || chatPhase === "streaming" ? "waiting" : chatPhase === "error" || chatPhase === "limited" ? "failed" : null;
|
|
2144
|
+
if (phase.name === "refused") {
|
|
2145
|
+
status = S[REFUSAL_TEXT[phase.reason]];
|
|
2146
|
+
outcome2 = true;
|
|
2147
|
+
} else if (phase.name === "ended") {
|
|
2148
|
+
status = S[phase.how];
|
|
2149
|
+
outcome2 = true;
|
|
2150
|
+
}
|
|
2151
|
+
body2 = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2152
|
+
lastQuestion === void 0 ? null : /* @__PURE__ */ jsx(
|
|
2153
|
+
"p",
|
|
2154
|
+
{
|
|
2155
|
+
"data-boff-explore": "avatar-live-question",
|
|
2156
|
+
dir: "auto",
|
|
2157
|
+
className: "line-clamp-2 w-full max-w-sm break-words text-sm font-medium",
|
|
2158
|
+
children: lastQuestion.content
|
|
2159
|
+
}
|
|
2160
|
+
),
|
|
2161
|
+
lastAnswer === void 0 ? unanswered === "waiting" ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: activity ?? S.gettingAnswer }) : unanswered === "failed" ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: S.answerFailed }) : null : lastAnswer.status === "PENDING" || lastAnswer.status === "RUNNING" ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: activity ?? S.gettingAnswer }) : lastAnswer.status === "FAILED" ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: S.answerFailed }) : /* @__PURE__ */ jsx(
|
|
2162
|
+
"p",
|
|
2163
|
+
{
|
|
2164
|
+
"data-boff-explore": "avatar-live-text-answer",
|
|
2165
|
+
dir: "auto",
|
|
2166
|
+
className: "line-clamp-6 w-full max-w-sm whitespace-pre-wrap break-words text-start text-sm",
|
|
2167
|
+
children: lastAnswer.content
|
|
2168
|
+
}
|
|
2169
|
+
)
|
|
2170
|
+
] });
|
|
2171
|
+
const ended = phase.name === "ended";
|
|
2172
|
+
actions2 = lastAnswer === void 0 && unanswered !== "failed" && !ended ? null : readInChatButton(ended);
|
|
2173
|
+
box = "text";
|
|
2174
|
+
} else {
|
|
2175
|
+
switch (phase.name) {
|
|
2176
|
+
case "checking":
|
|
2177
|
+
status = S.checking;
|
|
2178
|
+
break;
|
|
2179
|
+
case "needs-answer":
|
|
2180
|
+
switch (shown.kind) {
|
|
2181
|
+
case "empty":
|
|
2182
|
+
status = note === "new-chat" ? S.newChatStarted : "";
|
|
2183
|
+
lead = /* @__PURE__ */ jsx("p", { className: "text-base font-semibold", children: S.askHeadline });
|
|
2184
|
+
box = "spoken";
|
|
2185
|
+
break;
|
|
2186
|
+
case "asking":
|
|
2187
|
+
case "answer": {
|
|
2188
|
+
const card = shown.askedHere && shown.pendingAnswerId !== null;
|
|
2189
|
+
status = note === "cancelled" ? S.armedCancelled : S.gettingAnswer;
|
|
2190
|
+
if (card) media2 = stillPicture(true);
|
|
2191
|
+
body2 = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2192
|
+
questionLine,
|
|
2193
|
+
activityLine,
|
|
2194
|
+
card ? consentCard(phase.offer.copy) : null
|
|
2195
|
+
] });
|
|
2196
|
+
actions2 = card ? consentActions(true) : null;
|
|
2197
|
+
break;
|
|
2198
|
+
}
|
|
2199
|
+
case "text-only":
|
|
2200
|
+
status = S.notSpoken;
|
|
2201
|
+
outcome2 = true;
|
|
2202
|
+
body2 = questionLine;
|
|
2203
|
+
actions2 = readInChatButton(false);
|
|
2204
|
+
newChatOffer = true;
|
|
2205
|
+
break;
|
|
2206
|
+
case "failed":
|
|
2207
|
+
status = S.answerFailed;
|
|
2208
|
+
outcome2 = true;
|
|
2209
|
+
body2 = questionLine;
|
|
2210
|
+
newChatOffer = true;
|
|
2211
|
+
break;
|
|
2212
|
+
case "ask-here":
|
|
2213
|
+
status = S.askHere;
|
|
2214
|
+
outcome2 = true;
|
|
2215
|
+
actions2 = readInChatButton(false);
|
|
2216
|
+
newChatOffer = true;
|
|
2217
|
+
break;
|
|
2218
|
+
default:
|
|
2219
|
+
status = S.startNewChat;
|
|
2220
|
+
outcome2 = true;
|
|
2221
|
+
body2 = /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: S.startNewChatDetailAny });
|
|
2222
|
+
actions2 = readInChatButton(false);
|
|
2223
|
+
newChatOffer = true;
|
|
2224
|
+
break;
|
|
2225
|
+
}
|
|
2226
|
+
break;
|
|
2227
|
+
case "consent":
|
|
2228
|
+
media2 = stillPicture(true);
|
|
2229
|
+
body2 = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2230
|
+
questionLine,
|
|
2231
|
+
consentCard(phase.offer.copy)
|
|
2232
|
+
] });
|
|
2233
|
+
actions2 = consentActions(false);
|
|
2234
|
+
break;
|
|
2235
|
+
case "declined":
|
|
2236
|
+
status = S.declined;
|
|
2237
|
+
actions2 = readInChatButton(true);
|
|
2238
|
+
break;
|
|
2239
|
+
case "waiting":
|
|
2240
|
+
status = S.armed;
|
|
2241
|
+
body2 = questionLine;
|
|
2242
|
+
actions2 = /* @__PURE__ */ jsx(
|
|
2243
|
+
"button",
|
|
2244
|
+
{
|
|
2245
|
+
type: "button",
|
|
2246
|
+
"data-avatar-primary": "",
|
|
2247
|
+
"data-boff-explore": "avatar-live-cancel",
|
|
2248
|
+
className: secondaryButton,
|
|
2249
|
+
onClick: stop,
|
|
2250
|
+
children: S.cancel
|
|
2251
|
+
}
|
|
2252
|
+
);
|
|
2253
|
+
break;
|
|
2254
|
+
case "refused":
|
|
2255
|
+
outcome2 = true;
|
|
2256
|
+
if (phase.reason === "not_eligible" || phase.reason === "answer_claimed") {
|
|
2257
|
+
status = phase.reason === "not_eligible" ? S.notEligibleAny : S.answerClaimed;
|
|
2258
|
+
actions2 = readInChatButton(false);
|
|
2259
|
+
newChatOffer = true;
|
|
2260
|
+
} else {
|
|
2261
|
+
status = S[REFUSAL_TEXT[phase.reason]];
|
|
2262
|
+
actions2 = continueButton;
|
|
2263
|
+
}
|
|
2264
|
+
break;
|
|
2265
|
+
case "bot-check":
|
|
2266
|
+
status = S.botCheck;
|
|
2267
|
+
actions2 = stopButton;
|
|
2268
|
+
break;
|
|
2269
|
+
case "creating":
|
|
2270
|
+
status = S.connecting;
|
|
2271
|
+
actions2 = stopButton;
|
|
2272
|
+
break;
|
|
2273
|
+
case "pending":
|
|
2274
|
+
case "live":
|
|
2275
|
+
status = phase.name === "live" ? S.speaking : S.connecting;
|
|
2276
|
+
top2 = badge;
|
|
2277
|
+
media2 = liveMedia(phase.name === "live");
|
|
2278
|
+
body2 = liveBody(phase.session);
|
|
2279
|
+
actions2 = liveActions(readInChatButton(false));
|
|
2280
|
+
break;
|
|
2281
|
+
case "ended":
|
|
2282
|
+
status = S[phase.how];
|
|
2283
|
+
outcome2 = true;
|
|
2284
|
+
actions2 = readInChatButton(true);
|
|
2285
|
+
newChatOffer = true;
|
|
2286
|
+
break;
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
const reason = inFlight(conversation) ? S.askBusy : conversation?.canSend ? null : S.askUnavailable;
|
|
2290
|
+
const chips = box !== null && shown.kind === "empty" && prompts.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2291
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground", children: tryAsking }),
|
|
2292
|
+
/* @__PURE__ */ jsx("div", { className: "flex max-h-28 flex-wrap gap-2 overflow-y-auto", children: prompts.map((prompt) => /* @__PURE__ */ jsx(
|
|
2293
|
+
"button",
|
|
2294
|
+
{
|
|
2295
|
+
type: "button",
|
|
2296
|
+
"data-boff-explore": "avatar-live-chip",
|
|
2297
|
+
"aria-disabled": reason !== null ? "true" : void 0,
|
|
2298
|
+
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",
|
|
2299
|
+
onClick: () => {
|
|
2300
|
+
if (reason === null) ask(prompt);
|
|
2301
|
+
},
|
|
2302
|
+
children: prompt
|
|
2303
|
+
},
|
|
2304
|
+
prompt
|
|
2305
|
+
)) })
|
|
2306
|
+
] }) : null;
|
|
2307
|
+
const foot = box === null && !newChatOffer ? null : /* @__PURE__ */ jsxs(
|
|
2308
|
+
"div",
|
|
2309
|
+
{
|
|
2310
|
+
"data-boff-explore": "avatar-live-foot",
|
|
2311
|
+
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))]",
|
|
2312
|
+
children: [
|
|
2313
|
+
newChatOffer ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 text-center", children: [
|
|
2314
|
+
/* @__PURE__ */ jsx(
|
|
2315
|
+
"button",
|
|
2316
|
+
{
|
|
2317
|
+
type: "button",
|
|
2318
|
+
"data-avatar-primary": "",
|
|
2319
|
+
"data-boff-explore": "avatar-live-new-chat-avatar",
|
|
2320
|
+
className: cn(primaryButton, "min-h-11"),
|
|
2321
|
+
onClick: newChatForAvatar,
|
|
2322
|
+
children: S.newChatForAvatar
|
|
2323
|
+
}
|
|
2324
|
+
),
|
|
2325
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: S.newChatNote })
|
|
2326
|
+
] }) : null,
|
|
2327
|
+
chips,
|
|
2328
|
+
box !== null && usedToday ? /* @__PURE__ */ jsx(
|
|
2329
|
+
"p",
|
|
2330
|
+
{
|
|
2331
|
+
"data-boff-explore": "avatar-live-used-today",
|
|
2332
|
+
className: "text-xs text-muted-foreground",
|
|
2333
|
+
children: S.usedToday
|
|
2334
|
+
}
|
|
2335
|
+
) : null,
|
|
2336
|
+
box === null ? null : /* @__PURE__ */ jsx(
|
|
2337
|
+
AskBox,
|
|
2338
|
+
{
|
|
2339
|
+
value: draft,
|
|
2340
|
+
maxLength: askMaxLength,
|
|
2341
|
+
onChange: setDraft,
|
|
2342
|
+
onAsk: ask,
|
|
2343
|
+
reason,
|
|
2344
|
+
label: S.askLabel,
|
|
2345
|
+
placeholder: S.askPlaceholder,
|
|
2346
|
+
send,
|
|
2347
|
+
footer: S.askFooter,
|
|
2348
|
+
noFiles: S.askNoFiles,
|
|
2349
|
+
hint: box === "spoken" ? S.needsAnswerAny : null,
|
|
2350
|
+
touchFirst
|
|
2351
|
+
}
|
|
2352
|
+
)
|
|
2353
|
+
]
|
|
2354
|
+
}
|
|
2355
|
+
);
|
|
2356
|
+
return /* @__PURE__ */ jsxs(
|
|
2357
|
+
"div",
|
|
2358
|
+
{
|
|
2359
|
+
ref: rootRef,
|
|
2360
|
+
"data-boff-explore": "avatar-live",
|
|
2361
|
+
"data-phase": phase.name,
|
|
2362
|
+
"data-ask": askState,
|
|
2363
|
+
className: "absolute inset-0 flex flex-col bg-background",
|
|
2364
|
+
children: [
|
|
2365
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col items-center gap-4 overflow-y-auto p-6 text-center", children: [
|
|
2366
|
+
top2,
|
|
2367
|
+
media2,
|
|
2368
|
+
lead,
|
|
2369
|
+
/* @__PURE__ */ jsx(
|
|
2370
|
+
"p",
|
|
2371
|
+
{
|
|
2372
|
+
role: "status",
|
|
2373
|
+
"data-boff-explore": "avatar-live-status",
|
|
2374
|
+
className: outcome2 ? "text-base font-semibold" : "text-sm text-muted-foreground",
|
|
2375
|
+
children: status
|
|
2376
|
+
}
|
|
2377
|
+
),
|
|
2378
|
+
body2,
|
|
2379
|
+
/* @__PURE__ */ jsx("div", { ref: botBoxRef, "data-boff-explore": "avatar-live-bot-check" }),
|
|
2380
|
+
actions2
|
|
2381
|
+
] }),
|
|
2382
|
+
foot,
|
|
2383
|
+
/* @__PURE__ */ jsx("audio", { ref: audioRef, "data-boff-explore": "avatar-live-audio" })
|
|
2384
|
+
]
|
|
2385
|
+
}
|
|
2386
|
+
);
|
|
2387
|
+
}
|
|
1335
2388
|
const headline = {
|
|
1336
2389
|
idle: "",
|
|
1337
2390
|
checking: S.checking,
|
|
1338
2391
|
inert: "",
|
|
1339
|
-
|
|
2392
|
+
// A question asked and its answer on its way: the answer is coming (the avatar is offered once it completes).
|
|
2393
|
+
"needs-answer": startOver ? S.startNewChat : shown.kind === "asking" ? S.gettingAnswer : S.needsAnswer,
|
|
1340
2394
|
consent: "",
|
|
2395
|
+
declined: S.declined,
|
|
2396
|
+
waiting: S.armed,
|
|
1341
2397
|
refused: phase.name === "refused" ? S[REFUSAL_TEXT[phase.reason]] : "",
|
|
1342
2398
|
"bot-check": S.botCheck,
|
|
1343
2399
|
creating: S.connecting,
|
|
@@ -1355,65 +2411,11 @@ function AvatarLiveView({
|
|
|
1355
2411
|
body = /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: startOver ? S.startNewChatDetail : S.needsAnswerDetail });
|
|
1356
2412
|
actions = startOver ? startOverActions : continueButton;
|
|
1357
2413
|
break;
|
|
1358
|
-
case "consent":
|
|
1359
|
-
const { copy } = phase.offer;
|
|
2414
|
+
case "consent":
|
|
1360
2415
|
media = stillPicture(true);
|
|
1361
|
-
body =
|
|
1362
|
-
|
|
1363
|
-
{
|
|
1364
|
-
"aria-labelledby": consentTitleId,
|
|
1365
|
-
"data-boff-explore": "avatar-live-consent",
|
|
1366
|
-
className: "w-full max-w-sm rounded-lg border border-border p-4 text-start",
|
|
1367
|
-
children: [
|
|
1368
|
-
/* @__PURE__ */ jsx("h2", { id: consentTitleId, className: "text-base font-semibold", children: copy.title }),
|
|
1369
|
-
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm", children: productName === null || copy.introProduct === null ? copy.intro : fill(copy.introProduct, { product: productName }) }),
|
|
1370
|
-
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: copy.processing }),
|
|
1371
|
-
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: copy.storage }),
|
|
1372
|
-
/* @__PURE__ */ jsxs(
|
|
1373
|
-
"a",
|
|
1374
|
-
{
|
|
1375
|
-
href: PRIVACY_HREF,
|
|
1376
|
-
target: "_blank",
|
|
1377
|
-
rel: "noopener noreferrer",
|
|
1378
|
-
"data-boff-explore": "avatar-live-privacy",
|
|
1379
|
-
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",
|
|
1380
|
-
children: [
|
|
1381
|
-
copy.privacyLink,
|
|
1382
|
-
/* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
|
|
1383
|
-
" ",
|
|
1384
|
-
S.opensInNewTab
|
|
1385
|
-
] })
|
|
1386
|
-
]
|
|
1387
|
-
}
|
|
1388
|
-
)
|
|
1389
|
-
]
|
|
1390
|
-
}
|
|
1391
|
-
);
|
|
1392
|
-
actions = /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
|
|
1393
|
-
/* @__PURE__ */ jsx(
|
|
1394
|
-
"button",
|
|
1395
|
-
{
|
|
1396
|
-
type: "button",
|
|
1397
|
-
"data-avatar-primary": "",
|
|
1398
|
-
"data-boff-explore": "avatar-live-start",
|
|
1399
|
-
className: primaryButton,
|
|
1400
|
-
onClick: start,
|
|
1401
|
-
children: S.start
|
|
1402
|
-
}
|
|
1403
|
-
),
|
|
1404
|
-
/* @__PURE__ */ jsx(
|
|
1405
|
-
"button",
|
|
1406
|
-
{
|
|
1407
|
-
type: "button",
|
|
1408
|
-
"data-boff-explore": "avatar-live-not-now",
|
|
1409
|
-
className: secondaryButton,
|
|
1410
|
-
onClick: onContinueInChat,
|
|
1411
|
-
children: S.notNow
|
|
1412
|
-
}
|
|
1413
|
-
)
|
|
1414
|
-
] });
|
|
2416
|
+
body = consentCard(phase.offer.copy);
|
|
2417
|
+
actions = consentActions(false);
|
|
1415
2418
|
break;
|
|
1416
|
-
}
|
|
1417
2419
|
case "refused":
|
|
1418
2420
|
actions = phase.reason === "not_eligible" ? startOverActions : continueButton;
|
|
1419
2421
|
break;
|
|
@@ -1422,77 +2424,11 @@ function AvatarLiveView({
|
|
|
1422
2424
|
actions = stopButton;
|
|
1423
2425
|
break;
|
|
1424
2426
|
case "pending":
|
|
1425
|
-
case "live":
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
{
|
|
1431
|
-
"data-boff-explore": "avatar-live-badge",
|
|
1432
|
-
className: "rounded-full bg-muted px-3 py-1 text-xs font-medium text-foreground",
|
|
1433
|
-
children: S.badge
|
|
1434
|
-
}
|
|
1435
|
-
);
|
|
1436
|
-
media = /* @__PURE__ */ jsxs("div", { className: "relative h-48 w-48 shrink-0 overflow-hidden rounded-xl border border-border bg-muted", children: [
|
|
1437
|
-
/* @__PURE__ */ jsx(
|
|
1438
|
-
"video",
|
|
1439
|
-
{
|
|
1440
|
-
ref: videoRef,
|
|
1441
|
-
"aria-label": S.video,
|
|
1442
|
-
"data-boff-explore": "avatar-live-video",
|
|
1443
|
-
playsInline: true,
|
|
1444
|
-
autoPlay: true,
|
|
1445
|
-
muted: true,
|
|
1446
|
-
onPlaying,
|
|
1447
|
-
className: cn(
|
|
1448
|
-
"h-full w-full object-cover",
|
|
1449
|
-
!playing && "opacity-0"
|
|
1450
|
-
)
|
|
1451
|
-
}
|
|
1452
|
-
),
|
|
1453
|
-
playing ? null : /* @__PURE__ */ jsx(
|
|
1454
|
-
"img",
|
|
1455
|
-
{
|
|
1456
|
-
src: still.src,
|
|
1457
|
-
alt: "",
|
|
1458
|
-
decoding: "async",
|
|
1459
|
-
className: "absolute inset-0 h-full w-full object-cover"
|
|
1460
|
-
}
|
|
1461
|
-
),
|
|
1462
|
-
/* @__PURE__ */ jsx("audio", { ref: audioRef, "data-boff-explore": "avatar-live-audio" })
|
|
1463
|
-
] });
|
|
1464
|
-
body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1465
|
-
/* @__PURE__ */ jsx(
|
|
1466
|
-
"section",
|
|
1467
|
-
{
|
|
1468
|
-
"aria-label": S.captions,
|
|
1469
|
-
"data-boff-explore": "avatar-live-captions",
|
|
1470
|
-
lang: phase.session.captions.locale || void 0,
|
|
1471
|
-
dir: "auto",
|
|
1472
|
-
tabIndex: 0,
|
|
1473
|
-
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",
|
|
1474
|
-
children: phase.session.captions.text
|
|
1475
|
-
}
|
|
1476
|
-
),
|
|
1477
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: S.answerInChat }),
|
|
1478
|
-
/* @__PURE__ */ jsxs("p", { className: "text-sm tabular-nums text-muted-foreground", children: [
|
|
1479
|
-
S.timeLeft,
|
|
1480
|
-
" ",
|
|
1481
|
-
/* @__PURE__ */ jsx("span", { role: "timer", "data-boff-explore": "avatar-live-countdown", children: clock(left) })
|
|
1482
|
-
] })
|
|
1483
|
-
] });
|
|
1484
|
-
actions = /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
|
|
1485
|
-
blocked ? /* @__PURE__ */ jsx(
|
|
1486
|
-
"button",
|
|
1487
|
-
{
|
|
1488
|
-
type: "button",
|
|
1489
|
-
"data-boff-explore": "avatar-live-sound",
|
|
1490
|
-
className: primaryButton,
|
|
1491
|
-
onClick: enablePlayback,
|
|
1492
|
-
children: S.tapForSound
|
|
1493
|
-
}
|
|
1494
|
-
) : null,
|
|
1495
|
-
stopButton,
|
|
2427
|
+
case "live":
|
|
2428
|
+
top = badge;
|
|
2429
|
+
media = liveMedia(phase.name === "live");
|
|
2430
|
+
body = liveBody(phase.session);
|
|
2431
|
+
actions = liveActions(
|
|
1496
2432
|
/* @__PURE__ */ jsx(
|
|
1497
2433
|
"button",
|
|
1498
2434
|
{
|
|
@@ -1503,9 +2439,8 @@ function AvatarLiveView({
|
|
|
1503
2439
|
children: continueInChat
|
|
1504
2440
|
}
|
|
1505
2441
|
)
|
|
1506
|
-
|
|
2442
|
+
);
|
|
1507
2443
|
break;
|
|
1508
|
-
}
|
|
1509
2444
|
case "ended":
|
|
1510
2445
|
body = /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: S.answerInChat });
|
|
1511
2446
|
actions = /* @__PURE__ */ jsx(
|
|
@@ -1547,6 +2482,119 @@ function AvatarLiveView({
|
|
|
1547
2482
|
}
|
|
1548
2483
|
);
|
|
1549
2484
|
}
|
|
2485
|
+
function AskBox({
|
|
2486
|
+
value,
|
|
2487
|
+
maxLength,
|
|
2488
|
+
onChange,
|
|
2489
|
+
onAsk,
|
|
2490
|
+
reason,
|
|
2491
|
+
label,
|
|
2492
|
+
placeholder,
|
|
2493
|
+
send,
|
|
2494
|
+
footer,
|
|
2495
|
+
noFiles,
|
|
2496
|
+
hint,
|
|
2497
|
+
touchFirst
|
|
2498
|
+
}) {
|
|
2499
|
+
const uid = useId();
|
|
2500
|
+
const reasonId = `${uid}-reason`;
|
|
2501
|
+
const hintId = `${uid}-hint`;
|
|
2502
|
+
const footerId = `${uid}-footer`;
|
|
2503
|
+
const [refusedFiles, setRefusedFiles] = useState(false);
|
|
2504
|
+
const empty = value.trim() === "";
|
|
2505
|
+
const submit = () => {
|
|
2506
|
+
if (reason !== null || empty) return;
|
|
2507
|
+
onAsk(value);
|
|
2508
|
+
};
|
|
2509
|
+
const onKeyDown = (event) => {
|
|
2510
|
+
if (event.nativeEvent.isComposing || event.keyCode === 229) {
|
|
2511
|
+
if (event.key === "Escape") event.stopPropagation();
|
|
2512
|
+
return;
|
|
2513
|
+
}
|
|
2514
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
2515
|
+
event.preventDefault();
|
|
2516
|
+
submit();
|
|
2517
|
+
}
|
|
2518
|
+
};
|
|
2519
|
+
const onPaste = (event) => {
|
|
2520
|
+
if (event.clipboardData.files.length === 0) return;
|
|
2521
|
+
event.preventDefault();
|
|
2522
|
+
setRefusedFiles(true);
|
|
2523
|
+
};
|
|
2524
|
+
const onDrop = (event) => {
|
|
2525
|
+
if (!Array.from(event.dataTransfer.types).includes("Files")) return;
|
|
2526
|
+
event.preventDefault();
|
|
2527
|
+
setRefusedFiles(true);
|
|
2528
|
+
};
|
|
2529
|
+
return /* @__PURE__ */ jsxs(
|
|
2530
|
+
"form",
|
|
2531
|
+
{
|
|
2532
|
+
"data-boff-explore": "avatar-live-ask",
|
|
2533
|
+
className: "flex w-full flex-col gap-1",
|
|
2534
|
+
onSubmit: (event) => {
|
|
2535
|
+
event.preventDefault();
|
|
2536
|
+
submit();
|
|
2537
|
+
},
|
|
2538
|
+
children: [
|
|
2539
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-end gap-2", children: [
|
|
2540
|
+
/* @__PURE__ */ jsx(
|
|
2541
|
+
"textarea",
|
|
2542
|
+
{
|
|
2543
|
+
value,
|
|
2544
|
+
rows: 1,
|
|
2545
|
+
maxLength,
|
|
2546
|
+
"aria-label": label,
|
|
2547
|
+
"aria-describedby": hint === null ? footerId : `${hintId} ${footerId}`,
|
|
2548
|
+
placeholder,
|
|
2549
|
+
dir: "auto",
|
|
2550
|
+
"data-avatar-primary": touchFirst ? void 0 : "",
|
|
2551
|
+
"data-boff-explore": "avatar-live-ask-input",
|
|
2552
|
+
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",
|
|
2553
|
+
onChange: (event) => {
|
|
2554
|
+
setRefusedFiles(false);
|
|
2555
|
+
onChange(event.target.value);
|
|
2556
|
+
},
|
|
2557
|
+
onKeyDown,
|
|
2558
|
+
onPaste,
|
|
2559
|
+
onDrop
|
|
2560
|
+
}
|
|
2561
|
+
),
|
|
2562
|
+
/* @__PURE__ */ jsx(
|
|
2563
|
+
"button",
|
|
2564
|
+
{
|
|
2565
|
+
type: "submit",
|
|
2566
|
+
"aria-disabled": reason !== null || empty ? "true" : void 0,
|
|
2567
|
+
"aria-describedby": reason !== null ? reasonId : void 0,
|
|
2568
|
+
"data-avatar-primary": touchFirst ? "" : void 0,
|
|
2569
|
+
"data-boff-explore": "avatar-live-ask-send",
|
|
2570
|
+
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",
|
|
2571
|
+
children: send
|
|
2572
|
+
}
|
|
2573
|
+
)
|
|
2574
|
+
] }),
|
|
2575
|
+
reason === null ? null : /* @__PURE__ */ jsx(
|
|
2576
|
+
"p",
|
|
2577
|
+
{
|
|
2578
|
+
id: reasonId,
|
|
2579
|
+
"data-boff-explore": "avatar-live-ask-reason",
|
|
2580
|
+
className: "text-xs text-muted-foreground",
|
|
2581
|
+
children: reason
|
|
2582
|
+
}
|
|
2583
|
+
),
|
|
2584
|
+
refusedFiles ? /* @__PURE__ */ jsx(
|
|
2585
|
+
"p",
|
|
2586
|
+
{
|
|
2587
|
+
"data-boff-explore": "avatar-live-ask-files",
|
|
2588
|
+
className: "text-xs text-muted-foreground",
|
|
2589
|
+
children: noFiles
|
|
2590
|
+
}
|
|
2591
|
+
) : null,
|
|
2592
|
+
hint === null ? null : /* @__PURE__ */ jsx("p", { id: hintId, className: "sr-only", children: hint }),
|
|
2593
|
+
/* @__PURE__ */ jsx("p", { id: footerId, className: "text-xs text-muted-foreground", children: footer })
|
|
2594
|
+
]
|
|
2595
|
+
}
|
|
2596
|
+
);
|
|
2597
|
+
}
|
|
1550
2598
|
|
|
1551
2599
|
export { AvatarLiveView };
|
|
1552
2600
|
//# sourceMappingURL=index.mjs.map
|