@burdenoff/website-sdk 2026.1101.4 → 2026.1102.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { isAvatarSite, isAvatarLiveLocaleReviewed, isAvatarVersion } from '../chunk-BX2USEWF.mjs';
1
+ import { turnstileSiteKeyOf, isAvatarSite, isAvatarLiveLocaleReviewed, isAvatarVersion } from '../chunk-SFT3WHN5.mjs';
2
2
  import { fill } from '../chunk-TT3MHN42.mjs';
3
3
  import { cn } from '../chunk-R7G6TWIS.mjs';
4
4
  import '../chunk-VNS5WDWO.mjs';
@@ -33,6 +33,20 @@ var AVAILABILITY_REASONS = /* @__PURE__ */ new Map([
33
33
  ["busy", "busy"],
34
34
  ["limits", "limits"]
35
35
  ]);
36
+ var BOT_CHECK_MODES = /* @__PURE__ */ new Set([
37
+ "off",
38
+ "turnstile"
39
+ ]);
40
+ function readBotCheck(value) {
41
+ if (value === void 0) return "turnstile";
42
+ if (!isRecord(value)) return null;
43
+ const keys = Object.keys(value);
44
+ const { mode } = value;
45
+ if (keys.length !== 1 || keys[0] !== "mode" || typeof mode !== "string" || !BOT_CHECK_MODES.has(mode)) {
46
+ return null;
47
+ }
48
+ return mode === "off" ? "off" : "turnstile";
49
+ }
36
50
  function readAvailability(status, body) {
37
51
  if (status !== 200 || !isRecord(body)) return INERT;
38
52
  const { available, reason } = body;
@@ -41,10 +55,14 @@ function readAvailability(status, body) {
41
55
  }
42
56
  if (reason === "ok") {
43
57
  const { consentVersion, maxSessionSeconds } = body;
44
- if (available !== true || typeof consentVersion !== "string" || !isAvatarVersion(consentVersion) || typeof maxSessionSeconds !== "number" || !Number.isInteger(maxSessionSeconds) || maxSessionSeconds < 1) {
58
+ const botCheck = readBotCheck(body.botCheck);
59
+ if (available !== true || typeof consentVersion !== "string" || !isAvatarVersion(consentVersion) || typeof maxSessionSeconds !== "number" || !Number.isInteger(maxSessionSeconds) || maxSessionSeconds < 1 || botCheck === null) {
45
60
  return INERT;
46
61
  }
47
- return { kind: "available", offer: { consentVersion, maxSessionSeconds } };
62
+ return {
63
+ kind: "available",
64
+ offer: { consentVersion, maxSessionSeconds, botCheck }
65
+ };
48
66
  }
49
67
  const meaning = available ? void 0 : AVAILABILITY_REASONS.get(reason);
50
68
  return meaning === void 0 || meaning === "inert" ? INERT : { kind: "refused", reason: meaning };
@@ -167,7 +185,7 @@ async function requestCreate(target) {
167
185
  ...target.headers,
168
186
  "Content-Type": "application/json",
169
187
  "Idempotency-Key": target.idempotencyKey,
170
- "x-web-avatar-bot-token": target.botToken
188
+ ...target.botToken === void 0 ? {} : { "x-web-avatar-bot-token": target.botToken }
171
189
  },
172
190
  body: payload,
173
191
  signal: timer.signal
@@ -242,7 +260,7 @@ var EN = {
242
260
  needsAnswer: "Choose a suggested question in Chat first.",
243
261
  needsAnswerDetail: "The avatar can read only the first answer aloud.",
244
262
  startNewChat: "Start a new chat to use the avatar.",
245
- startNewChatDetail: "The avatar reads aloud only the first answer in a chat, and only to a suggested question. Start a new chat and choose a suggested question.",
263
+ startNewChatDetail: "The avatar reads aloud only the first answer in a chat, to a suggested question, within fifteen minutes. Start a new chat and choose a suggested question.",
246
264
  start: "Start live avatar",
247
265
  notNow: "Not now",
248
266
  opensInNewTab: "(opens in a new tab)",
@@ -266,7 +284,7 @@ var EN = {
266
284
  region: "The live avatar isn't offered in your region yet.",
267
285
  locale: "The live avatar isn't offered in this language yet.",
268
286
  paused: "The live avatar is paused right now.",
269
- notEligible: "The avatar can read answers to the suggested questions.",
287
+ notEligible: "The avatar reads the first answer to a suggested question, within fifteen minutes. Start a new chat and choose a suggested question.",
270
288
  answerClaimed: "The avatar has already read this answer."
271
289
  };
272
290
  var ZH = {
@@ -275,7 +293,7 @@ var ZH = {
275
293
  needsAnswerDetail: "\u865A\u62DF\u5F62\u8C61\u53EA\u80FD\u6717\u8BFB\u7B2C\u4E00\u4E2A\u56DE\u7B54\u3002",
276
294
  // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
277
295
  startNewChat: "\u8BF7\u5F00\u59CB\u65B0\u7684\u804A\u5929\uFF0C\u518D\u4F7F\u7528\u865A\u62DF\u5F62\u8C61\u3002",
278
- startNewChatDetail: "\u865A\u62DF\u5F62\u8C61\u53EA\u6717\u8BFB\u4E00\u6B21\u804A\u5929\u4E2D\u7684\u7B2C\u4E00\u4E2A\u56DE\u7B54\uFF0C\u4E14\u4EC5\u9650\u56DE\u7B54\u63A8\u8350\u95EE\u9898\u3002\u8BF7\u5F00\u59CB\u65B0\u7684\u804A\u5929\uFF0C\u5E76\u9009\u62E9\u4E00\u4E2A\u63A8\u8350\u95EE\u9898\u3002",
296
+ startNewChatDetail: "\u865A\u62DF\u5F62\u8C61\u53EA\u6717\u8BFB\u4E00\u6B21\u804A\u5929\u4E2D\u7684\u7B2C\u4E00\u4E2A\u56DE\u7B54\uFF0C\u4E14\u4EC5\u9650\u63A8\u8350\u95EE\u9898\u7684\u56DE\u7B54\u3001\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",
279
297
  start: "\u542F\u52A8\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61",
280
298
  notNow: "\u6682\u4E0D",
281
299
  opensInNewTab: "\uFF08\u5728\u65B0\u6807\u7B7E\u9875\u4E2D\u6253\u5F00\uFF09",
@@ -299,7 +317,8 @@ var ZH = {
299
317
  region: "\u60A8\u6240\u5728\u7684\u5730\u533A\u6682\u4E0D\u63D0\u4F9B\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61\u3002",
300
318
  locale: "\u6B64\u8BED\u8A00\u6682\u4E0D\u63D0\u4F9B\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61\u3002",
301
319
  paused: "\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61\u76EE\u524D\u5DF2\u6682\u505C\u3002",
302
- notEligible: "\u865A\u62DF\u5F62\u8C61\u53EF\u4EE5\u6717\u8BFB\u63A8\u8350\u95EE\u9898\u7684\u56DE\u7B54\u3002",
320
+ // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
321
+ 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",
303
322
  answerClaimed: "\u865A\u62DF\u5F62\u8C61\u5DF2\u7ECF\u6717\u8BFB\u8FC7\u8FD9\u4E2A\u56DE\u7B54\u3002"
304
323
  };
305
324
  var HI = {
@@ -308,7 +327,7 @@ var HI = {
308
327
  needsAnswerDetail: "\u0905\u0935\u0924\u093E\u0930 \u0915\u0947\u0935\u0932 \u092A\u0939\u0932\u093E \u0909\u0924\u094D\u0924\u0930 \u091C\u093C\u094B\u0930 \u0938\u0947 \u092A\u0922\u093C \u0938\u0915\u0924\u093E \u0939\u0948\u0964",
309
328
  // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
310
329
  startNewChat: "\u0905\u0935\u0924\u093E\u0930 \u0915\u093E \u0909\u092A\u092F\u094B\u0917 \u0915\u0930\u0928\u0947 \u0915\u0947 \u0932\u093F\u090F \u0928\u0908 \u091A\u0948\u091F \u0936\u0941\u0930\u0942 \u0915\u0930\u0947\u0902\u0964",
311
- startNewChatDetail: "\u0905\u0935\u0924\u093E\u0930 \u0915\u093F\u0938\u0940 \u091A\u0948\u091F \u0915\u093E \u0915\u0947\u0935\u0932 \u092A\u0939\u0932\u093E \u0909\u0924\u094D\u0924\u0930 \u091C\u093C\u094B\u0930 \u0938\u0947 \u092A\u0922\u093C\u0924\u093E \u0939\u0948, \u0914\u0930 \u0935\u0939 \u092D\u0940 \u0938\u0941\u091D\u093E\u090F \u0917\u090F \u092A\u094D\u0930\u0936\u094D\u0928 \u0915\u093E \u0939\u0940\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",
330
+ startNewChatDetail: "\u0905\u0935\u0924\u093E\u0930 \u0915\u093F\u0938\u0940 \u091A\u0948\u091F \u0915\u093E \u0915\u0947\u0935\u0932 \u092A\u0939\u0932\u093E \u0909\u0924\u094D\u0924\u0930 \u091C\u093C\u094B\u0930 \u0938\u0947 \u092A\u0922\u093C\u0924\u093E \u0939\u0948, \u0935\u0939 \u092D\u0940 \u0938\u0941\u091D\u093E\u090F \u0917\u090F \u092A\u094D\u0930\u0936\u094D\u0928 \u0915\u093E \u0914\u0930 \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",
312
331
  start: "\u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930 \u0936\u0941\u0930\u0942 \u0915\u0930\u0947\u0902",
313
332
  notNow: "\u0905\u092D\u0940 \u0928\u0939\u0940\u0902",
314
333
  opensInNewTab: "(\u0928\u090F \u091F\u0948\u092C \u092E\u0947\u0902 \u0916\u0941\u0932\u0924\u093E \u0939\u0948)",
@@ -332,7 +351,8 @@ var HI = {
332
351
  region: "\u0906\u092A\u0915\u0947 \u0915\u094D\u0937\u0947\u0924\u094D\u0930 \u092E\u0947\u0902 \u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930 \u0905\u092D\u0940 \u0909\u092A\u0932\u092C\u094D\u0927 \u0928\u0939\u0940\u0902 \u0939\u0948\u0964",
333
352
  locale: "\u0907\u0938 \u092D\u093E\u0937\u093E \u092E\u0947\u0902 \u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930 \u0905\u092D\u0940 \u0909\u092A\u0932\u092C\u094D\u0927 \u0928\u0939\u0940\u0902 \u0939\u0948\u0964",
334
353
  paused: "\u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930 \u0905\u092D\u0940 \u0930\u0941\u0915\u093E \u0939\u0941\u0906 \u0939\u0948\u0964",
335
- notEligible: "\u0905\u0935\u0924\u093E\u0930 \u0938\u0941\u091D\u093E\u090F \u0917\u090F \u092A\u094D\u0930\u0936\u094D\u0928\u094B\u0902 \u0915\u0947 \u0909\u0924\u094D\u0924\u0930 \u092A\u0922\u093C \u0938\u0915\u0924\u093E \u0939\u0948\u0964",
354
+ // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
355
+ 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",
336
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"
337
357
  };
338
358
  var ES = {
@@ -341,7 +361,7 @@ var ES = {
341
361
  needsAnswerDetail: "El avatar solo puede leer en voz alta la primera respuesta.",
342
362
  // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
343
363
  startNewChat: "Inicia un chat nuevo para usar el avatar.",
344
- startNewChatDetail: "El avatar solo lee en voz alta la primera respuesta de un chat, y solo si es la de una pregunta sugerida. Inicia un chat nuevo y elige una pregunta sugerida.",
364
+ startNewChatDetail: "El avatar solo lee en voz alta la primera respuesta de un chat, si es la de una pregunta sugerida y en un plazo de quince minutos. Inicia un chat nuevo y elige una pregunta sugerida.",
345
365
  start: "Iniciar el avatar en vivo",
346
366
  notNow: "Ahora no",
347
367
  opensInNewTab: "(se abre en una pesta\xF1a nueva)",
@@ -365,7 +385,8 @@ var ES = {
365
385
  region: "El avatar en vivo a\xFAn no est\xE1 disponible en tu regi\xF3n.",
366
386
  locale: "El avatar en vivo a\xFAn no est\xE1 disponible en este idioma.",
367
387
  paused: "El avatar en vivo est\xE1 en pausa en este momento.",
368
- notEligible: "El avatar puede leer las respuestas a las preguntas sugeridas.",
388
+ // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
389
+ 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.",
369
390
  answerClaimed: "El avatar ya ha le\xEDdo esta respuesta."
370
391
  };
371
392
  var AR = {
@@ -374,7 +395,7 @@ var AR = {
374
395
  needsAnswerDetail: "\u064A\u0645\u0643\u0646 \u0644\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0642\u0631\u0627\u0621\u0629 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0627\u0644\u0623\u0648\u0644\u0649 \u0641\u0642\u0637 \u0628\u0635\u0648\u062A \u0639\u0627\u0644\u064D.",
375
396
  // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
376
397
  startNewChat: "\u0627\u0628\u062F\u0623 \u062F\u0631\u062F\u0634\u0629 \u062C\u062F\u064A\u062F\u0629 \u0644\u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631.",
377
- startNewChatDetail: "\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\u064A \u0627\u0644\u062F\u0631\u062F\u0634\u0629 \u0641\u0642\u0637\u060C \u0648\u0641\u0642\u0637 \u0625\u0630\u0627 \u0643\u0627\u0646\u062A \u0625\u062C\u0627\u0628\u0629 \u0639\u0646 \u0633\u0624\u0627\u0644 \u0645\u0642\u062A\u0631\u062D. \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.",
398
+ startNewChatDetail: "\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\u064A \u0627\u0644\u062F\u0631\u062F\u0634\u0629 \u0641\u0642\u0637\u060C \u0625\u0630\u0627 \u0643\u0627\u0646\u062A \u0625\u062C\u0627\u0628\u0629 \u0639\u0646 \u0633\u0624\u0627\u0644 \u0645\u0642\u062A\u0631\u062D \u0648\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.",
378
399
  start: "\u0628\u062F\u0621 \u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631",
379
400
  notNow: "\u0644\u064A\u0633 \u0627\u0644\u0622\u0646",
380
401
  opensInNewTab: "(\u064A\u064F\u0641\u062A\u062D \u0641\u064A \u0639\u0644\u0627\u0645\u0629 \u062A\u0628\u0648\u064A\u0628 \u062C\u062F\u064A\u062F\u0629)",
@@ -398,7 +419,8 @@ var AR = {
398
419
  region: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631 \u063A\u064A\u0631 \u0645\u062A\u0627\u062D \u0641\u064A \u0645\u0646\u0637\u0642\u062A\u0643 \u0628\u0639\u062F.",
399
420
  locale: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631 \u063A\u064A\u0631 \u0645\u062A\u0627\u062D \u0628\u0647\u0630\u0647 \u0627\u0644\u0644\u063A\u0629 \u0628\u0639\u062F.",
400
421
  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.",
401
- notEligible: "\u064A\u0645\u0643\u0646 \u0644\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0642\u0631\u0627\u0621\u0629 \u0625\u062C\u0627\u0628\u0627\u062A \u0627\u0644\u0623\u0633\u0626\u0644\u0629 \u0627\u0644\u0645\u0642\u062A\u0631\u062D\u0629.",
422
+ // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
423
+ 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.",
402
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."
403
425
  };
404
426
  var TA = {
@@ -407,7 +429,7 @@ var TA = {
407
429
  needsAnswerDetail: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BAE\u0BC1\u0BA4\u0BB2\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0BAE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAE\u0BC7 \u0B89\u0BB0\u0B95\u0BCD\u0B95\u0BAA\u0BCD \u0BAA\u0B9F\u0BBF\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BC1\u0BAE\u0BCD.",
408
430
  // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
409
431
  startNewChat: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BC8\u0BAA\u0BCD \u0BAA\u0BAF\u0BA9\u0BCD\u0BAA\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4 \u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BC8\u0BA4\u0BCD \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD.",
410
- startNewChatDetail: "\u0B93\u0BB0\u0BCD \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\u0BB5\u0BC1\u0BAE\u0BCD \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 \u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0BAE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAE\u0BC7 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0B89\u0BB0\u0B95\u0BCD\u0B95\u0BAA\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.",
432
+ startNewChatDetail: "\u0B93\u0BB0\u0BCD \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\u0BB5\u0BC1\u0BAE\u0BCD \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 \u0BAA\u0BA4\u0BBF\u0BB2\u0BC8, \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 \u0BAE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAE\u0BC7 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0B89\u0BB0\u0B95\u0BCD\u0B95\u0BAA\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.",
411
433
  start: "\u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BC8\u0BA4\u0BCD \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BC1",
412
434
  notNow: "\u0B87\u0BAA\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1 \u0BB5\u0BC7\u0BA3\u0BCD\u0B9F\u0BBE\u0BAE\u0BCD",
413
435
  opensInNewTab: "(\u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0BA4\u0BBE\u0BB5\u0BB2\u0BBF\u0BB2\u0BCD \u0BA4\u0BBF\u0BB1\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD)",
@@ -431,7 +453,8 @@ var TA = {
431
453
  region: "\u0B89\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BAA\u0B95\u0BC1\u0BA4\u0BBF\u0BAF\u0BBF\u0BB2\u0BCD \u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0B87\u0BA9\u0BCD\u0BA9\u0BC1\u0BAE\u0BCD \u0B95\u0BBF\u0B9F\u0BC8\u0B95\u0BCD\u0B95\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8.",
432
454
  locale: "\u0B87\u0BA8\u0BCD\u0BA4 \u0BAE\u0BCA\u0BB4\u0BBF\u0BAF\u0BBF\u0BB2\u0BCD \u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0B87\u0BA9\u0BCD\u0BA9\u0BC1\u0BAE\u0BCD \u0B95\u0BBF\u0B9F\u0BC8\u0B95\u0BCD\u0B95\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8.",
433
455
  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.",
434
- 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\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BAA\u0B9F\u0BBF\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BC1\u0BAE\u0BCD.",
456
+ // TRANSLATION REVIEW PENDING (BOFF-9797): draft.
457
+ 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.",
435
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."
436
459
  };
437
460
  var STRINGS = {
@@ -455,7 +478,8 @@ var CONSENT = /* @__PURE__ */ new Map([
455
478
  intro: "This is an AI avatar, not a real person. It reads the assistant's first eligible answer to a suggested question aloud for up to a minute. The answer is AI-generated and can be wrong.",
456
479
  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.",
457
480
  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.",
458
- privacyLink: "How we handle this"
481
+ privacyLink: "How we handle this",
482
+ botCheck: "turnstile"
459
483
  }
460
484
  }
461
485
  ],
@@ -469,7 +493,8 @@ var CONSENT = /* @__PURE__ */ new Map([
469
493
  intro: "This is an AI avatar, not a real person. It reads the assistant's first eligible answer to a suggested question aloud for up to a minute. The answer is AI-generated and can be wrong.",
470
494
  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.",
471
495
  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.",
472
- privacyLink: "How we handle this"
496
+ privacyLink: "How we handle this",
497
+ botCheck: "turnstile"
473
498
  }
474
499
  }
475
500
  ],
@@ -484,7 +509,24 @@ var CONSENT = /* @__PURE__ */ new Map([
484
509
  intro: "This is an AI avatar, not a real person. It reads the assistant's first eligible answer to a suggested question aloud for up to a minute. The answer is AI-generated and can be wrong.",
485
510
  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.",
486
511
  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.",
487
- privacyLink: "How we handle this"
512
+ privacyLink: "How we handle this",
513
+ botCheck: "turnstile"
514
+ }
515
+ }
516
+ ],
517
+ [
518
+ // The words of web-consent-2026-11-02 without "When you start, Cloudflare checks for bots.", for a server that runs
519
+ // no bot check (its availability's botCheck is `off`). Product-neutral too: one notice and one digest for every site.
520
+ "web-consent-2026-11-03",
521
+ {
522
+ en: {
523
+ title: "Live AI avatar (beta)",
524
+ introProduct: null,
525
+ intro: "This is an AI avatar, not a real person. It reads the assistant's first eligible answer to a suggested question aloud for up to a minute. The answer is AI-generated and can be wrong.",
526
+ 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
+ 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
+ privacyLink: "How we handle this",
529
+ botCheck: "off"
488
530
  }
489
531
  }
490
532
  ]
@@ -612,6 +654,9 @@ var PRIVACY_HREF = "/privacy#live-avatar";
612
654
  var SPEAKER_WAIT_MS = 3e4;
613
655
  var END_GRACE_MS = 1e4;
614
656
  var CLOCK_TOLERANCE_MS = 5e3;
657
+ var SERVICE_MAX_AGE_MS = 15 * 6e4;
658
+ var ANSWER_OFFER_MS = SERVICE_MAX_AGE_MS - 6e4;
659
+ var MAX_TIMER_MS = 2147483647;
615
660
  var PRIMARY = '[data-avatar-primary], [data-boff-explore="panel-continue-chat"]';
616
661
  var IDLE = { name: "idle" };
617
662
  var INERT2 = { name: "inert" };
@@ -624,8 +669,19 @@ var REFUSAL_TEXT = {
624
669
  not_eligible: "notEligible",
625
670
  answer_claimed: "answerClaimed"
626
671
  };
627
- var WAITING = { answerId: null, startOver: false };
628
- var START_OVER = { answerId: null, startOver: true };
672
+ var WAITING = { answerId: null, startOver: false, offerUntil: NaN };
673
+ var START_OVER = {
674
+ answerId: null,
675
+ startOver: true,
676
+ offerUntil: NaN
677
+ };
678
+ function createdAtOf(message) {
679
+ const raw = message.createdAt;
680
+ return typeof raw === "string" && raw !== "" ? Date.parse(raw) : NaN;
681
+ }
682
+ function offeredAt(exchange, now) {
683
+ return exchange.answerId !== null && !(now < exchange.offerUntil) ? START_OVER : exchange;
684
+ }
629
685
  function firstExchange(messages) {
630
686
  if (!messages || messages.length === 0) return WAITING;
631
687
  if (messages.length > 2) return START_OVER;
@@ -639,7 +695,11 @@ function firstExchange(messages) {
639
695
  if (answer.status !== "COMPLETED" || answer.content.trim() === "" || !isAvatarMessageId(answer.id)) {
640
696
  return START_OVER;
641
697
  }
642
- return { answerId: answer.id, startOver: false };
698
+ return {
699
+ answerId: answer.id,
700
+ startOver: false,
701
+ offerUntil: createdAtOf(answer) + ANSWER_OFFER_MS
702
+ };
643
703
  }
644
704
  function offering(offer, messageId, claimed) {
645
705
  return claimed.has(messageId) ? { name: "refused", reason: "answer_claimed" } : { name: "consent", offer, messageId };
@@ -665,6 +725,7 @@ function AvatarLiveView({
665
725
  fallback,
666
726
  onContinueInChat,
667
727
  continueInChat,
728
+ newChat,
668
729
  off,
669
730
  base,
670
731
  headers,
@@ -673,13 +734,16 @@ function AvatarLiveView({
673
734
  const S = avatarLiveStrings(locale);
674
735
  const uid = useId();
675
736
  const consentTitleId = `${uid}-consent`;
676
- const { answerId, startOver } = firstExchange(conversation?.messages);
737
+ const exchange = firstExchange(conversation?.messages);
738
+ const [ageTick, setAgeTick] = useState(0);
739
+ const { answerId, startOver } = offeredAt(exchange, Date.now());
740
+ const offerUntil = answerId === null ? null : exchange.offerUntil;
677
741
  const [phase, setPhase] = useState(IDLE);
678
742
  const [blocked, setBlocked] = useState(false);
679
743
  const [now, setNow] = useState(() => Date.now());
680
744
  const phaseRef = useRef(IDLE);
681
- const latest = useRef({ live, locale, base, headers, answerId, off });
682
- latest.current = { live, locale, base, headers, answerId, off };
745
+ const latest = useRef({ live, locale, base, headers, exchange, off });
746
+ latest.current = { live, locale, base, headers, exchange, off };
683
747
  const conversationRef = useRef(conversation);
684
748
  conversationRef.current = conversation;
685
749
  const checkRef = useRef(null);
@@ -695,6 +759,17 @@ function AvatarLiveView({
695
759
  phaseRef.current = next;
696
760
  setPhase(next);
697
761
  }, []);
762
+ const offeredNow = useCallback(
763
+ () => offeredAt(latest.current.exchange, Date.now()).answerId,
764
+ []
765
+ );
766
+ const reoffer = useCallback(
767
+ (offer) => {
768
+ const messageId = offeredNow();
769
+ return messageId === null ? { name: "needs-answer", offer } : offering(offer, messageId, claimedRef.current);
770
+ },
771
+ [offeredNow]
772
+ );
698
773
  const finish = useCallback(
699
774
  (how, reason) => {
700
775
  const handle = sessionRef.current;
@@ -755,17 +830,17 @@ function AvatarLiveView({
755
830
  return;
756
831
  }
757
832
  const copy = avatarConsentCopy(result.offer.consentVersion, locale2);
758
- if (copy === null) {
833
+ if (copy === null || copy.botCheck !== result.offer.botCheck) {
759
834
  go(INERT2);
760
835
  return;
761
836
  }
762
- const offer = { ...result.offer, locale: locale2, copy };
763
- const messageId = latest.current.answerId;
764
- go(
765
- messageId === null ? { name: "needs-answer", offer } : offering(offer, messageId, claimedRef.current)
766
- );
837
+ if (result.offer.botCheck === "turnstile" && turnstileSiteKeyOf(live2) === null) {
838
+ go(INERT2);
839
+ return;
840
+ }
841
+ go(reoffer({ ...result.offer, locale: locale2, copy }));
767
842
  });
768
- }, [go]);
843
+ }, [go, reoffer]);
769
844
  const begin = useCallback(
770
845
  (session, module, offer, target) => {
771
846
  const received = Date.now();
@@ -851,11 +926,17 @@ function AvatarLiveView({
851
926
  if (current.name !== "consent") return;
852
927
  const { live: live2, base: base2, headers: headers2 } = latest.current;
853
928
  if (base2 === null) return;
854
- if (!canBindBotCheck()) {
929
+ const { offer, messageId } = current;
930
+ if (offeredNow() !== messageId) {
931
+ go(reoffer(offer));
932
+ return;
933
+ }
934
+ const refusedFrom = latest.current.exchange.offerUntil - ANSWER_OFFER_MS + SERVICE_MAX_AGE_MS;
935
+ const siteKey = offer.botCheck === "turnstile" ? turnstileSiteKeyOf(live2) : null;
936
+ if (offer.botCheck === "turnstile" && (siteKey === null || !canBindBotCheck())) {
855
937
  go(INERT2);
856
938
  return;
857
939
  }
858
- const { offer, messageId } = current;
859
940
  const conversationToken = conversationRef.current?.getConversationToken() ?? null;
860
941
  const idempotencyKey = newIdempotencyKey();
861
942
  if (conversationToken === null || !isAvatarConversationToken(conversationToken) || idempotencyKey === null) {
@@ -872,31 +953,41 @@ function AvatarLiveView({
872
953
  };
873
954
  const run = { cancelled: null, turnstile: null };
874
955
  startRef.current = run;
875
- go({ name: "bot-check", offer, messageId });
876
956
  const module = loadModule(live2.load);
877
- const turnstile = runTurnstile(
878
- botBoxRef.current,
879
- live2.turnstileSiteKey,
880
- "avatar_start",
881
- avatarBotBinding(body2)
882
- );
883
- run.turnstile = turnstile;
957
+ let turnstile = null;
958
+ if (siteKey === null) {
959
+ go({ name: "creating" });
960
+ } else {
961
+ go({ name: "bot-check", offer, messageId });
962
+ turnstile = runTurnstile(
963
+ botBoxRef.current,
964
+ siteKey,
965
+ "avatar_start",
966
+ avatarBotBinding(body2)
967
+ );
968
+ run.turnstile = turnstile;
969
+ }
884
970
  void (async () => {
885
971
  let loaded;
886
972
  let botToken;
887
973
  try {
888
- [loaded, botToken] = await Promise.all([module, turnstile.token]);
974
+ [loaded, botToken] = await Promise.all([module, turnstile?.token]);
889
975
  } catch {
890
- turnstile.cancel();
976
+ turnstile?.cancel();
891
977
  if (run.cancelled === null) {
892
978
  startRef.current = null;
893
979
  go(INERT2);
894
980
  }
895
981
  return;
896
982
  }
897
- turnstile.cancel();
983
+ turnstile?.cancel();
898
984
  if (run.cancelled !== null) return;
899
- go({ name: "creating" });
985
+ if (!(Date.now() < refusedFrom)) {
986
+ startRef.current = null;
987
+ go({ name: "needs-answer", offer });
988
+ return;
989
+ }
990
+ if (turnstile !== null) go({ name: "creating" });
900
991
  const result = await requestCreate({
901
992
  base: base2,
902
993
  headers: headers2,
@@ -907,12 +998,12 @@ function AvatarLiveView({
907
998
  if (startRef.current === run) startRef.current = null;
908
999
  settle(result, run, { module: loaded, offer, messageId, base: base2, headers: headers2 });
909
1000
  })();
910
- }, [go, settle]);
1001
+ }, [go, offeredNow, reoffer, settle]);
911
1002
  const stop = useCallback(() => {
912
1003
  const current = phaseRef.current;
913
1004
  if (current.name === "bot-check") {
914
1005
  cancelStart("user");
915
- go(offering(current.offer, current.messageId, claimedRef.current));
1006
+ go(reoffer(current.offer));
916
1007
  return;
917
1008
  }
918
1009
  if (current.name === "creating") {
@@ -923,7 +1014,7 @@ function AvatarLiveView({
923
1014
  if (current.name === "pending" || current.name === "live") {
924
1015
  finish("stopped", "user");
925
1016
  }
926
- }, [cancelStart, finish, go]);
1017
+ }, [cancelStart, finish, go, reoffer]);
927
1018
  const leave = useCallback(
928
1019
  (reason) => {
929
1020
  const current = phaseRef.current;
@@ -939,9 +1030,7 @@ function AvatarLiveView({
939
1030
  }
940
1031
  case "bot-check":
941
1032
  cancelStart(reason);
942
- go(
943
- reason === "user" ? IDLE : offering(current.offer, current.messageId, claimedRef.current)
944
- );
1033
+ go(reason === "user" ? IDLE : reoffer(current.offer));
945
1034
  return;
946
1035
  case "creating":
947
1036
  cancelStart(reason);
@@ -955,7 +1044,7 @@ function AvatarLiveView({
955
1044
  return;
956
1045
  }
957
1046
  },
958
- [cancelStart, finish, go]
1047
+ [cancelStart, finish, go, reoffer]
959
1048
  );
960
1049
  const showing = active && !off;
961
1050
  useEffect(() => {
@@ -964,7 +1053,7 @@ function AvatarLiveView({
964
1053
  return;
965
1054
  }
966
1055
  const current = phaseRef.current;
967
- const { answerId: offered } = latest.current;
1056
+ const offered = offeredNow();
968
1057
  const used = offered !== null && claimedRef.current.has(offered);
969
1058
  if (current.name === "ended" && used) return;
970
1059
  if (current.name === "refused" && current.reason === "answer_claimed" && used) {
@@ -976,7 +1065,7 @@ function AvatarLiveView({
976
1065
  current.name === "checking" && checkRef.current === null) {
977
1066
  check();
978
1067
  }
979
- }, [showing, check, leave]);
1068
+ }, [showing, check, leave, offeredNow]);
980
1069
  useEffect(() => {
981
1070
  if (askedLocale.current === locale) return;
982
1071
  askedLocale.current = locale;
@@ -1002,6 +1091,18 @@ function AvatarLiveView({
1002
1091
  );
1003
1092
  }
1004
1093
  }, [answerId, go]);
1094
+ useEffect(() => {
1095
+ if (offerUntil === null) return;
1096
+ const timer = setTimeout(
1097
+ () => setAgeTick((tick) => tick + 1),
1098
+ Math.min(MAX_TIMER_MS, Math.max(0, offerUntil - Date.now()))
1099
+ );
1100
+ return () => clearTimeout(timer);
1101
+ }, [offerUntil, ageTick]);
1102
+ const startNewChat = useCallback(() => {
1103
+ conversationRef.current?.reset();
1104
+ onContinueInChat();
1105
+ }, [onContinueInChat]);
1005
1106
  const onRoomEvent = useCallback(
1006
1107
  (handle, event) => {
1007
1108
  if (handle.done || sessionRef.current !== handle) return;
@@ -1197,6 +1298,29 @@ function AvatarLiveView({
1197
1298
  children: continueInChat
1198
1299
  }
1199
1300
  );
1301
+ const startOverActions = /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
1302
+ /* @__PURE__ */ jsx(
1303
+ "button",
1304
+ {
1305
+ type: "button",
1306
+ "data-avatar-primary": "",
1307
+ "data-boff-explore": "avatar-live-new-chat",
1308
+ className: primaryButton,
1309
+ onClick: startNewChat,
1310
+ children: newChat
1311
+ }
1312
+ ),
1313
+ /* @__PURE__ */ jsx(
1314
+ "button",
1315
+ {
1316
+ type: "button",
1317
+ "data-boff-explore": "avatar-live-continue",
1318
+ className: secondaryButton,
1319
+ onClick: onContinueInChat,
1320
+ children: continueInChat
1321
+ }
1322
+ )
1323
+ ] });
1200
1324
  const stopButton = /* @__PURE__ */ jsx(
1201
1325
  "button",
1202
1326
  {
@@ -1229,7 +1353,7 @@ function AvatarLiveView({
1229
1353
  switch (phase.name) {
1230
1354
  case "needs-answer":
1231
1355
  body = /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: startOver ? S.startNewChatDetail : S.needsAnswerDetail });
1232
- actions = continueButton;
1356
+ actions = startOver ? startOverActions : continueButton;
1233
1357
  break;
1234
1358
  case "consent": {
1235
1359
  const { copy } = phase.offer;
@@ -1291,7 +1415,7 @@ function AvatarLiveView({
1291
1415
  break;
1292
1416
  }
1293
1417
  case "refused":
1294
- actions = continueButton;
1418
+ actions = phase.reason === "not_eligible" ? startOverActions : continueButton;
1295
1419
  break;
1296
1420
  case "bot-check":
1297
1421
  case "creating":