@burdenoff/website-sdk 2026.1101.3 → 2026.1102.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.
Files changed (40) hide show
  1. package/README.md +234 -14
  2. package/dist/avatar-live-view/index.d.mts +1 -1
  3. package/dist/avatar-live-view/index.d.ts +1 -1
  4. package/dist/avatar-live-view/index.js +71 -24
  5. package/dist/avatar-live-view/index.js.map +1 -1
  6. package/dist/avatar-live-view/index.mjs +69 -22
  7. package/dist/avatar-live-view/index.mjs.map +1 -1
  8. package/dist/{chunk-Y4V5CEWD.mjs → chunk-2LPDCXQH.mjs} +7 -4
  9. package/dist/chunk-2LPDCXQH.mjs.map +1 -0
  10. package/dist/{chunk-FFADMVIK.mjs → chunk-ETI2HQEC.mjs} +7 -5
  11. package/dist/chunk-ETI2HQEC.mjs.map +1 -0
  12. package/dist/{chunk-23H4JUL4.js → chunk-OIQHIGGU.js} +20 -3
  13. package/dist/chunk-OIQHIGGU.js.map +1 -0
  14. package/dist/{chunk-OYEUNZJY.js → chunk-PIXTBL63.js} +7 -3
  15. package/dist/chunk-PIXTBL63.js.map +1 -0
  16. package/dist/{chunk-BX2USEWF.mjs → chunk-QOHPLTGT.mjs} +19 -4
  17. package/dist/chunk-QOHPLTGT.mjs.map +1 -0
  18. package/dist/{chunk-O76QDGRM.js → chunk-R742FS5E.js} +8 -4
  19. package/dist/chunk-R742FS5E.js.map +1 -0
  20. package/dist/components/explore-cta.d.mts +7 -0
  21. package/dist/components/explore-cta.d.ts +7 -0
  22. package/dist/components/explore-cta.js +2 -2
  23. package/dist/components/explore-cta.mjs +1 -1
  24. package/dist/components/explore.js +13 -13
  25. package/dist/components/explore.mjs +1 -1
  26. package/dist/{explore-avatar-live-config-B171o1Yo.d.ts → explore-avatar-live-config-C1ILEcY8.d.ts} +16 -4
  27. package/dist/{explore-avatar-live-config-BGsGwbcq.d.mts → explore-avatar-live-config-D-hO90-A.d.mts} +16 -4
  28. package/dist/index.d.mts +107 -4
  29. package/dist/index.d.ts +107 -4
  30. package/dist/index.js +209 -43
  31. package/dist/index.js.map +1 -1
  32. package/dist/index.mjs +173 -7
  33. package/dist/index.mjs.map +1 -1
  34. package/package.json +1 -1
  35. package/dist/chunk-23H4JUL4.js.map +0 -1
  36. package/dist/chunk-BX2USEWF.mjs.map +0 -1
  37. package/dist/chunk-FFADMVIK.mjs.map +0 -1
  38. package/dist/chunk-O76QDGRM.js.map +0 -1
  39. package/dist/chunk-OYEUNZJY.js.map +0 -1
  40. package/dist/chunk-Y4V5CEWD.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { isAvatarSite, isAvatarLiveLocaleReviewed, isAvatarVersion } from '../chunk-BX2USEWF.mjs';
1
+ import { turnstileSiteKeyOf, isAvatarSite, isAvatarLiveLocaleReviewed, isAvatarVersion } from '../chunk-QOHPLTGT.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
@@ -455,7 +473,8 @@ var CONSENT = /* @__PURE__ */ new Map([
455
473
  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
474
  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
475
  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"
476
+ privacyLink: "How we handle this",
477
+ botCheck: "turnstile"
459
478
  }
460
479
  }
461
480
  ],
@@ -469,7 +488,8 @@ var CONSENT = /* @__PURE__ */ new Map([
469
488
  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
489
  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
490
  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"
491
+ privacyLink: "How we handle this",
492
+ botCheck: "turnstile"
473
493
  }
474
494
  }
475
495
  ],
@@ -484,7 +504,24 @@ var CONSENT = /* @__PURE__ */ new Map([
484
504
  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
505
  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
506
  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"
507
+ privacyLink: "How we handle this",
508
+ botCheck: "turnstile"
509
+ }
510
+ }
511
+ ],
512
+ [
513
+ // The words of web-consent-2026-11-02 without "When you start, Cloudflare checks for bots.", for a server that runs
514
+ // no bot check (its availability's botCheck is `off`). Product-neutral too: one notice and one digest for every site.
515
+ "web-consent-2026-11-03",
516
+ {
517
+ en: {
518
+ title: "Live AI avatar (beta)",
519
+ introProduct: null,
520
+ 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.",
521
+ 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.",
522
+ 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.",
523
+ privacyLink: "How we handle this",
524
+ botCheck: "off"
488
525
  }
489
526
  }
490
527
  ]
@@ -755,7 +792,11 @@ function AvatarLiveView({
755
792
  return;
756
793
  }
757
794
  const copy = avatarConsentCopy(result.offer.consentVersion, locale2);
758
- if (copy === null) {
795
+ if (copy === null || copy.botCheck !== result.offer.botCheck) {
796
+ go(INERT2);
797
+ return;
798
+ }
799
+ if (result.offer.botCheck === "turnstile" && turnstileSiteKeyOf(live2) === null) {
759
800
  go(INERT2);
760
801
  return;
761
802
  }
@@ -851,11 +892,12 @@ function AvatarLiveView({
851
892
  if (current.name !== "consent") return;
852
893
  const { live: live2, base: base2, headers: headers2 } = latest.current;
853
894
  if (base2 === null) return;
854
- if (!canBindBotCheck()) {
895
+ const { offer, messageId } = current;
896
+ const siteKey = offer.botCheck === "turnstile" ? turnstileSiteKeyOf(live2) : null;
897
+ if (offer.botCheck === "turnstile" && (siteKey === null || !canBindBotCheck())) {
855
898
  go(INERT2);
856
899
  return;
857
900
  }
858
- const { offer, messageId } = current;
859
901
  const conversationToken = conversationRef.current?.getConversationToken() ?? null;
860
902
  const idempotencyKey = newIdempotencyKey();
861
903
  if (conversationToken === null || !isAvatarConversationToken(conversationToken) || idempotencyKey === null) {
@@ -872,31 +914,36 @@ function AvatarLiveView({
872
914
  };
873
915
  const run = { cancelled: null, turnstile: null };
874
916
  startRef.current = run;
875
- go({ name: "bot-check", offer, messageId });
876
917
  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;
918
+ let turnstile = null;
919
+ if (siteKey === null) {
920
+ go({ name: "creating" });
921
+ } else {
922
+ go({ name: "bot-check", offer, messageId });
923
+ turnstile = runTurnstile(
924
+ botBoxRef.current,
925
+ siteKey,
926
+ "avatar_start",
927
+ avatarBotBinding(body2)
928
+ );
929
+ run.turnstile = turnstile;
930
+ }
884
931
  void (async () => {
885
932
  let loaded;
886
933
  let botToken;
887
934
  try {
888
- [loaded, botToken] = await Promise.all([module, turnstile.token]);
935
+ [loaded, botToken] = await Promise.all([module, turnstile?.token]);
889
936
  } catch {
890
- turnstile.cancel();
937
+ turnstile?.cancel();
891
938
  if (run.cancelled === null) {
892
939
  startRef.current = null;
893
940
  go(INERT2);
894
941
  }
895
942
  return;
896
943
  }
897
- turnstile.cancel();
944
+ turnstile?.cancel();
898
945
  if (run.cancelled !== null) return;
899
- go({ name: "creating" });
946
+ if (turnstile !== null) go({ name: "creating" });
900
947
  const result = await requestCreate({
901
948
  base: base2,
902
949
  headers: headers2,