@burdenoff/website-sdk 2026.1105.1 → 2026.1105.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.
- package/README.md +40 -1
- package/dist/avatar-live/index.d.mts +2 -2
- package/dist/avatar-live/index.d.ts +2 -2
- package/dist/avatar-live/index.js +11 -1
- package/dist/avatar-live/index.js.map +1 -1
- package/dist/avatar-live/index.mjs +11 -1
- package/dist/avatar-live/index.mjs.map +1 -1
- package/dist/avatar-live-view/index.d.mts +2 -2
- package/dist/avatar-live-view/index.d.ts +2 -2
- package/dist/avatar-live-view/index.js +653 -32
- package/dist/avatar-live-view/index.js.map +1 -1
- package/dist/avatar-live-view/index.mjs +653 -32
- package/dist/avatar-live-view/index.mjs.map +1 -1
- package/dist/{explore-avatar-live-config-OO0hvQCK.d.mts → explore-avatar-live-config-BL8FTm0I.d.mts} +1 -1
- package/dist/{explore-avatar-live-config-C-OwXNje.d.ts → explore-avatar-live-config-auLKxSzx.d.ts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/{types-CXqaLlNB.d.mts → types-CTUJNvQu.d.mts} +10 -0
- package/dist/{types-CXqaLlNB.d.ts → types-CTUJNvQu.d.ts} +10 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/explore-avatar-api.ts","../../src/components/explore-avatar-i18n.ts","../../src/components/explore-avatar-mic.tsx","../../src/components/explore-avatar-turnstile.ts","../../src/components/explore-avatar-live-view.tsx"],"names":["loading","PRIVACY_HREF","IDLE","INERT","clock","useId","useState","useRef","useCallback","locale","live","base","headers","off","shown","body","exchange","token","useEffect","now","conversation","current","jsx","jsxs","Fragment","outcome","top","media","actions"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * BOFF-9797. The website live avatar's three requests, as a visitor's browser makes them.\n *\n * They go to the global gateway's web branch, under the SDK's configured gateway (`/api/web-avatar/v1/*` on its\n * origin), and follow the website avatar web API, v1:\n *\n * GET /availability?site=…&locale=… when the Avatar tab opens, never on page load\n * POST /sessions after the visitor's consent (and the bot check, where the server runs one)\n * POST /sessions/{id}/end Stop, leaving the tab, closing the panel, hiding the page\n *\n * - **Never with credentials** (`credentials: 'omit'`): a website visitor has no account, no cookie and no workspace\n * here.\n * - **The bot check's token** goes in the `x-web-avatar-bot-token` header, on create only, and only when the server\n * checks for bots: availability says whether it does (`botCheck`, contract v1.2). The gateway verifies it and drops\n * it; the body is exactly the contract's six fields. The check itself is bound to that body (contract v1.1): see\n * {@link avatarBotBinding}. A server that runs no bot check gets no header at all.\n * - **The end is a simple request** (see {@link sendEnd}): no `Content-Type` of our own, so a page being hidden has no\n * CORS preflight to wait for.\n * - **Every answer is read into one of a few outcomes** the Avatar tab can show. A missing route, a forbidden one, a\n * refused origin and an availability request that fails are all `inert`: the tab shows what it showed before there\n * was a live avatar. A create that has been sent and gets no answer is `failed`, never `inert`: the server may have\n * created the session (see {@link requestCreate}). Nothing a server says is shown as it was said.\n * - Nothing here logs. The conversation token goes into the create body and nowhere else, and the session's secret\n * only into the end body.\n */\n\nimport { isAvatarSite, isAvatarVersion } from \"./explore-avatar-live-config\";\n\n// The few helpers the panel itself needs (where the requests go, and the shapes a config may take) live in\n// `explore-avatar-live-config.ts`, so that they do not drag this file into every site's bundle; they are re-exported\n// here, where the rest of the contract's grammar is.\nexport {\n AVATAR_WEB_API_PATH,\n avatarApiBase,\n isAvatarSite,\n isAvatarVersion,\n} from \"./explore-avatar-live-config\";\n\n/** How long the Avatar tab waits to hear whether the live avatar is offered. */\nconst AVAILABILITY_TIMEOUT_MS = 8_000;\n/**\n * How long a create may take before it is given up on as `failed` (see {@link requestCreate}): past the gateway's own\n * deadline for it, so the gateway's answer is what decides.\n */\nconst CREATE_TIMEOUT_MS = 30_000;\n\n/** The refusals the Avatar tab explains, each in a short sentence of its own. */\nexport type AvatarRefusal =\n | \"busy\"\n | \"limits\"\n | \"region\"\n | \"locale\"\n | \"paused\"\n | \"not_eligible\"\n | \"answer_claimed\";\n\n/** Why the browser ends a session. Analytics only: the secret is what ends it. */\nexport type AvatarEndReason = \"user\" | \"page_hide\" | \"client_error\";\n\n/**\n * Whether the server checks for bots when a session is created: `turnstile` (a Cloudflare Turnstile token is required on\n * create) or `off` (none is; the server's own caps decide). A server older than contract v1.2 names no mode and always\n * checks, so it is read as `turnstile`.\n */\nexport type AvatarBotCheck = \"off\" | \"turnstile\";\n\n/**\n * Which first questions the server reads the answer to (contract v1.3, BOFF-9797): `suggested` (only the exact\n * suggested questions of the site's manifest) or `any` (a question the visitor typed too). A server older than v1.3\n * names none and reads suggested questions only, so it is read as `suggested`. The Avatar tab offers its own question\n * box only under `any`, and only with consent copy written for it.\n */\nexport type AvatarQuestions = \"any\" | \"suggested\";\n\n/**\n * What an `ok` availability offers the Avatar tab's mic (BOFF-9797 Stage C): a token that opens one website\n * speech-to-text stream, and when the gateway says it expires (epoch milliseconds, the gateway's clock). The gateway adds\n * it, minted for this visitor, only while its website speech-to-text is on, and only to an answer that says the avatar\n * can start now.\n */\nexport interface AvatarSttOffer {\n token: string;\n expiresAt: number;\n}\n\n/** What an `ok` availability offers. */\nexport interface AvatarOffer {\n /** The consent version the visitor must agree to: the panel shows only copy written for exactly this version. */\n consentVersion: string;\n /** The longest a session can last, in seconds. */\n maxSessionSeconds: number;\n /** Whether a bot check runs before the create request. */\n botCheck: AvatarBotCheck;\n /** Which first questions the server reads the answer to. */\n questions: AvatarQuestions;\n /**\n * The mic's offer, present only when the answer carries one this browser can use (see {@link readSttOffer}). Absent,\n * the Avatar tab offers no mic; nothing else changes.\n */\n stt?: AvatarSttOffer;\n}\n\nexport type AvatarAvailability =\n | { kind: \"available\"; offer: AvatarOffer }\n /**\n * `questions` is the server's (contract v1.3 reports it with every answer): under `any` a `limits` refusal leaves the\n * Avatar tab's box asking in text. Read leniently here, since a refusal offers nothing: anything but `any` is\n * `suggested`.\n */\n | { kind: \"refused\"; reason: AvatarRefusal; questions: AvatarQuestions }\n /** Not offered here, or not reachable: the Avatar tab stays as it was before the live avatar. */\n | { kind: \"inert\" };\n\n/** A created session: what the browser needs to watch it and to end it. */\nexport interface AvatarSession {\n sessionId: string;\n /** Returned once; ends this session and nothing else. Kept out of the page's markup. */\n endSecret: string;\n /** When the server ends the session, in epoch milliseconds. */\n endsAt: number;\n join: {\n livekitUrl: string;\n /** Subscribe-only and short-lived. Kept out of the page's markup. */\n participantToken: string;\n workerIdentity: string;\n };\n captions: { locale: string; text: string };\n /**\n * The server speaks only a whole-sentence first part of the answer, labelled as such, because the whole answer does\n * not fit the session (contract v1.4, Stage B: only under the server's `AVATAR_WEB_SIZE_BY_AUDIO`). The full answer\n * stays in Chat. False when the 201 says false, says nothing (an older server, or the setting off) or says anything\n * but `true`: the field is additive, so a value it cannot read never makes a session unusable.\n */\n excerpt: boolean;\n}\n\nexport type AvatarCreateResult =\n | { kind: \"created\"; session: AvatarSession }\n /** A session was created, but its answer cannot be used: the browser ends it at once. */\n | { kind: \"unusable\"; sessionId: string; endSecret: string }\n | { kind: \"refused\"; reason: AvatarRefusal }\n /** The consent version moved on since availability: ask again, and show the consent that is current. */\n | { kind: \"consent\" }\n | { kind: \"inert\" }\n | { kind: \"failed\" };\n\n/** The create body: exactly these six fields, in the contract's order. */\nexport interface AvatarCreateBody {\n site: string;\n locale: string;\n conversationToken: string;\n messageId: string;\n consentVersion: string;\n manifestVersion: string;\n}\n\nconst MESSAGE_ID = /^[A-Za-z0-9_-]{1,64}$/;\n/** What a WebSocket subprotocol entry may hold, as the gateway checks it: the mic's token travels as `offer.<token>`. */\nconst STT_TOKEN = /^[A-Za-z0-9._~-]{1,4096}$/;\nconst CONVERSATION_TOKEN = /^[A-Za-z0-9._~+/=-]{16,512}$/;\nconst LOCALE = /^[A-Za-z0-9-]{1,16}$/;\nconst SESSION_ID = /^avs_[0-9a-f]{32}$/;\nconst END_SECRET = /^[A-Za-z0-9_-]{43}$/;\n\nconst INERT = { kind: \"inert\" } as const;\nconst FAILED = { kind: \"failed\" } as const;\n\n/** An answer id the contract accepts. */\nexport function isAvatarMessageId(value: string): boolean {\n return MESSAGE_ID.test(value);\n}\n\n/** A conversation token the contract accepts. */\nexport function isAvatarConversationToken(value: string): boolean {\n return CONVERSATION_TOKEN.test(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/** What each availability `reason` other than `ok` means for the Avatar tab. A reason not listed is inert. */\nconst AVAILABILITY_REASONS: ReadonlyMap<string, AvatarRefusal | \"inert\"> =\n new Map<string, AvatarRefusal | \"inert\">([\n [\"site\", \"inert\"],\n [\"unavailable\", \"inert\"],\n [\"region\", \"region\"],\n [\"locale\", \"locale\"],\n [\"paused\", \"paused\"],\n [\"busy\", \"busy\"],\n [\"limits\", \"limits\"],\n ]);\n\nconst BOT_CHECK_MODES: ReadonlySet<string> = new Set<AvatarBotCheck>([\n \"off\",\n \"turnstile\",\n]);\n\n/**\n * An `ok` answer's `botCheck` (contract v1.2): exactly `{\"mode\":\"off\"}` or `{\"mode\":\"turnstile\"}`. Absent, from a\n * server older than v1.2: `turnstile`, as that server always checks. Anything else (an unknown mode, another field, a\n * value of another type) is null: the browser cannot tell what the server will require, so it offers nothing.\n */\nfunction readBotCheck(value: unknown): AvatarBotCheck | null {\n if (value === undefined) return \"turnstile\";\n if (!isRecord(value)) return null;\n const keys = Object.keys(value);\n const { mode } = value;\n if (\n keys.length !== 1 ||\n keys[0] !== \"mode\" ||\n typeof mode !== \"string\" ||\n !BOT_CHECK_MODES.has(mode)\n ) {\n return null;\n }\n return mode === \"off\" ? \"off\" : \"turnstile\";\n}\n\nconst QUESTION_MODES: ReadonlySet<string> = new Set<AvatarQuestions>([\n \"any\",\n \"suggested\",\n]);\n\n/**\n * An `ok` answer's `questions` (contract v1.3): exactly `\"any\"` or `\"suggested\"`. Absent, from a server older than v1.3:\n * `suggested`, which is all that server reads. Anything else is null: the browser cannot tell which questions the\n * server will read, so it offers nothing.\n */\nfunction readQuestions(value: unknown): AvatarQuestions | null {\n if (value === undefined) return \"suggested\";\n if (typeof value !== \"string\" || !QUESTION_MODES.has(value)) return null;\n return value === \"any\" ? \"any\" : \"suggested\";\n}\n\n/**\n * An `ok` answer's `stt` (BOFF-9797 Stage C): exactly `{token, expiresAt}`, a token that can travel as a WebSocket\n * subprotocol entry and a positive whole number of milliseconds. Absent (the gateway's website speech-to-text off, or a\n * gateway older than it) or anything else (another field, another shape): undefined, and the Avatar tab offers no mic.\n * Additive: a value it cannot read never makes the rest of the offer unusable.\n */\nfunction readSttOffer(value: unknown): AvatarSttOffer | undefined {\n if (!isRecord(value)) return undefined;\n const keys = Object.keys(value).sort();\n const { token, expiresAt } = value;\n if (\n keys.length !== 2 ||\n keys[0] !== \"expiresAt\" ||\n keys[1] !== \"token\" ||\n typeof token !== \"string\" ||\n !STT_TOKEN.test(token) ||\n typeof expiresAt !== \"number\" ||\n !Number.isSafeInteger(expiresAt) ||\n expiresAt <= 0\n ) {\n return undefined;\n }\n return { token, expiresAt };\n}\n\n/**\n * Read an availability answer: its HTTP status and its parsed JSON body (or null). Only an `ok` answer's `botCheck` is\n * read, and only an `ok` answer's `questions` strictly: a refusal offers nothing for them to change. The same goes for\n * `stt`, which only an `ok` answer can carry.\n */\nexport function readAvailability(\n status: number,\n body: unknown,\n): AvatarAvailability {\n if (status !== 200 || !isRecord(body)) return INERT;\n const { available, reason } = body;\n if (typeof available !== \"boolean\" || typeof reason !== \"string\") {\n return INERT;\n }\n if (reason === \"ok\") {\n const { consentVersion, maxSessionSeconds } = body;\n const botCheck = readBotCheck(body.botCheck);\n const questions = readQuestions(body.questions);\n if (\n available !== true ||\n typeof consentVersion !== \"string\" ||\n !isAvatarVersion(consentVersion) ||\n typeof maxSessionSeconds !== \"number\" ||\n !Number.isInteger(maxSessionSeconds) ||\n maxSessionSeconds < 1 ||\n botCheck === null ||\n questions === null\n ) {\n return INERT;\n }\n const stt = readSttOffer(body.stt);\n return {\n kind: \"available\",\n offer: {\n consentVersion,\n maxSessionSeconds,\n botCheck,\n questions,\n ...(stt === undefined ? {} : { stt }),\n },\n };\n }\n const meaning = available ? undefined : AVAILABILITY_REASONS.get(reason);\n return meaning === undefined || meaning === \"inert\"\n ? INERT\n : {\n kind: \"refused\",\n reason: meaning,\n questions: body.questions === \"any\" ? \"any\" : \"suggested\",\n };\n}\n\n/** The create error codes the Avatar tab explains. */\nconst CREATE_REFUSALS: ReadonlyMap<string, AvatarRefusal> = new Map<\n string,\n AvatarRefusal\n>([\n [\"busy\", \"busy\"],\n [\"limits\", \"limits\"],\n [\"region\", \"region\"],\n [\"locale\", \"locale\"],\n [\"paused\", \"paused\"],\n [\"not_eligible\", \"not_eligible\"],\n [\"answer_claimed\", \"answer_claimed\"],\n]);\n\nfunction errorCode(body: unknown): string | null {\n if (!isRecord(body) || !isRecord(body.error)) return null;\n const { code } = body.error;\n return typeof code === \"string\" ? code : null;\n}\n\nfunction readCreated(body: unknown): AvatarCreateResult {\n if (!isRecord(body)) return FAILED;\n const { sessionId, endSecret } = body;\n if (\n typeof sessionId !== \"string\" ||\n !SESSION_ID.test(sessionId) ||\n typeof endSecret !== \"string\" ||\n !END_SECRET.test(endSecret)\n ) {\n return FAILED;\n }\n const unusable = { kind: \"unusable\", sessionId, endSecret } as const;\n const { state, join, captions } = body;\n const endsAt =\n typeof body.endsAt === \"string\" ? Date.parse(body.endsAt) : NaN;\n if (\n state !== \"pending\" ||\n !Number.isFinite(endsAt) ||\n !isRecord(join) ||\n !isRecord(captions)\n ) {\n return unusable;\n }\n const { livekitUrl, participantToken, workerIdentity } = join;\n const { locale, text } = captions;\n if (\n typeof livekitUrl !== \"string\" ||\n !livekitUrl.startsWith(\"wss://\") ||\n typeof participantToken !== \"string\" ||\n participantToken === \"\" ||\n typeof workerIdentity !== \"string\" ||\n workerIdentity === \"\" ||\n typeof locale !== \"string\" ||\n typeof text !== \"string\"\n ) {\n return unusable;\n }\n return {\n kind: \"created\",\n session: {\n sessionId,\n endSecret,\n endsAt,\n join: { livekitUrl, participantToken, workerIdentity },\n captions: { locale, text },\n excerpt: body.excerpt === true,\n },\n };\n}\n\n/**\n * Read a create answer: its HTTP status and its parsed JSON body (or null).\n *\n * - 201: the session, or `unusable` when its fields cannot be used (the browser then ends it).\n * - `busy`, `limits`, `region`, `locale`, `paused`, `not_eligible`, `answer_claimed`: a refusal the tab explains.\n * - `consent`: the consent version moved on.\n * - Any other 401, 403, 404 or 405 (`untrusted_caller`, `bot_check`, `site`, `invalid_route`, `method_not_allowed`):\n * inert, as if there were no live avatar here.\n * - Anything else (`invalid_request`, `conflict`, `idempotency_mismatch`, `unavailable`, a gateway error page):\n * failed.\n */\nexport function readCreate(status: number, body: unknown): AvatarCreateResult {\n if (status === 201) return readCreated(body);\n const code = errorCode(body);\n if (code !== null) {\n const refusal = CREATE_REFUSALS.get(code);\n if (refusal !== undefined) return { kind: \"refused\", reason: refusal };\n if (code === \"consent\") return { kind: \"consent\" };\n }\n if (status === 401 || status === 403 || status === 404 || status === 405) {\n return INERT;\n }\n return FAILED;\n}\n\n/**\n * An answer's body as JSON, or null when it is not JSON or cannot be read (cut off on the way). The status still says\n * what the answer was: a create's 201 without a readable body is `failed` (no secret to end it with), a 404 without one\n * is still `inert`.\n */\nasync function readJson(response: Response): Promise<unknown> {\n try {\n return (await response.json()) as unknown;\n } catch {\n return null;\n }\n}\n\n/** An abort signal for `timeoutMs`, also aborted with `outer`; `done` clears its timer. */\nfunction deadline(\n timeoutMs: number,\n outer?: AbortSignal,\n): { signal: AbortSignal; done: () => void } {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const onOuter = () => controller.abort();\n if (outer?.aborted) controller.abort();\n else outer?.addEventListener(\"abort\", onOuter, { once: true });\n return {\n signal: controller.signal,\n done: () => {\n clearTimeout(timer);\n outer?.removeEventListener(\"abort\", onOuter);\n },\n };\n}\n\nexport interface AvatarRequestTarget {\n /** {@link avatarApiBase} of the SDK's gateway. */\n base: string;\n /** Headers every request carries: the alpha gateway's access headers, and nothing on production. */\n headers: Readonly<Record<string, string>>;\n}\n\n/** What an availability request names: the gateway, the site and the locale, and an abort of its own. */\nexport type AvatarAvailabilityTarget = AvatarRequestTarget & {\n site: string;\n locale: string;\n signal?: AbortSignal;\n};\n\n/** Ask whether the live avatar is offered for `site` in `locale`. Never throws: a failure is `inert`. */\nexport async function requestAvailability(\n target: AvatarAvailabilityTarget,\n): Promise<AvatarAvailability> {\n try {\n return await requestAvailabilityAnswer(target);\n } catch {\n return INERT;\n }\n}\n\n/**\n * {@link requestAvailability}, except that a request that gets no answer (a network or CORS failure, an abort, nothing\n * by its deadline) rejects instead of being `inert`. For the Avatar tab's mic (BOFF-9797 Stage C), which must tell an\n * answer that offers it nothing (the mic goes for the page) from no answer at all (the press says to try again). An\n * answer, whatever it says, is read as {@link requestAvailability} reads it.\n */\nexport async function requestAvailabilityAnswer(\n target: AvatarAvailabilityTarget,\n): Promise<AvatarAvailability> {\n if (!isAvatarSite(target.site) || !LOCALE.test(target.locale)) return INERT;\n const query = new URLSearchParams({\n site: target.site,\n locale: target.locale,\n });\n const timer = deadline(AVAILABILITY_TIMEOUT_MS, target.signal);\n try {\n const response = await fetch(`${target.base}/availability?${query}`, {\n method: \"GET\",\n credentials: \"omit\",\n cache: \"no-store\",\n headers: { ...target.headers },\n signal: timer.signal,\n });\n return readAvailability(response.status, await readJson(response));\n } finally {\n timer.done();\n }\n}\n\n/**\n * Create a session. `botToken` is the bot check's token, for the gateway alone, and is sent only when there is one: a\n * server that runs no bot check gets no `x-web-avatar-bot-token` header. Never throws, and never retries: the bot\n * check's token is good for one create, and a second create could be a second session to pay for.\n *\n * - **An answer** is read as the contract says ({@link readCreate}): a 401, 403, 404 or 405 is still `inert`.\n * - **No answer is `failed`, never `inert`.** Once this is called the request may have reached the gateway, and the\n * server may have created the session and be paying for it, with only its answer lost: a network failure, a body\n * cut off, a request held up past {@link CREATE_TIMEOUT_MS}. The Avatar tab then says the live avatar couldn't\n * start, never that there is none.\n * - **It settles by its deadline, whatever the network does.** The deadline is a timer raced against the request: a\n * fetch that does not settle (one held by something between the page and the network) still leaves this `failed`\n * then. A `failed` past the deadline says nothing about whether a session was created.\n * - **Only a request with no answer yet is aborted at the deadline.** An answer whose status is in by then is read to\n * its end, however long its body takes, for `onLate`: cut off, a 201 is a session made with its secret lost. A\n * request aborted with no answer yet is lost the same way where the browser honours the abort (its fetch rejects,\n * and `onLate` has only `failed`): a session the server made for it runs until the server's own deadlines end it.\n * - **An answer that comes past the deadline all the same** goes to `onLate`, and nowhere else. A session it created\n * is the caller's to end at once with its secret ({@link sendEnd}), never to join: the visitor has been told it\n * couldn't start.\n */\nexport function requestCreate(\n target: AvatarRequestTarget & {\n body: AvatarCreateBody;\n idempotencyKey: string;\n botToken?: string;\n onLate?: (result: AvatarCreateResult) => void;\n },\n): Promise<AvatarCreateResult> {\n const { body } = target;\n // Exactly the contract's six fields, in its order: nothing else of the page's goes along.\n const payload = JSON.stringify({\n site: body.site,\n locale: body.locale,\n conversationToken: body.conversationToken,\n messageId: body.messageId,\n consentVersion: body.consentVersion,\n manifestVersion: body.manifestVersion,\n });\n const controller = new AbortController();\n // Whether the answer has begun: its status is in, and its body is on its way.\n let answered = false;\n const answer = (async (): Promise<AvatarCreateResult> => {\n try {\n const response = await fetch(`${target.base}/sessions`, {\n method: \"POST\",\n credentials: \"omit\",\n cache: \"no-store\",\n headers: {\n ...target.headers,\n \"Content-Type\": \"application/json\",\n \"Idempotency-Key\": target.idempotencyKey,\n ...(target.botToken === undefined\n ? {}\n : { \"x-web-avatar-bot-token\": target.botToken }),\n },\n body: payload,\n signal: controller.signal,\n });\n answered = true;\n return readCreate(response.status, await readJson(response));\n } catch {\n return FAILED;\n }\n })();\n return new Promise<AvatarCreateResult>((resolve) => {\n let late = false;\n const timer = setTimeout(() => {\n late = true;\n // The same signal cuts off the body: an answer that has begun is left to finish, for `onLate`.\n if (!answered) controller.abort();\n resolve(FAILED);\n }, CREATE_TIMEOUT_MS);\n void answer.then((result) => {\n if (late) {\n target.onLate?.(result);\n return;\n }\n clearTimeout(timer);\n resolve(result);\n });\n });\n}\n\n/**\n * Ask the server to end a session, without waiting for it: a `keepalive` request, sent in this same tick, so it still\n * goes when the page is being hidden or unloaded. The server ends the session on its own deadlines whether or not this\n * arrives.\n *\n * **A simple CORS request.** The body is a plain string and this sets no `Content-Type`, so the browser sends it as\n * `text/plain;charset=UTF-8`: a type the gateway's end route reads as JSON for exactly this reason. The session id is\n * in the URL, so a preflight could never be answered from the browser's cache, and one that has to complete while the\n * page unloads may never finish. On production nothing else is added, so no preflight is made. (On the alpha gateway\n * hosts the Access headers in `target.headers` are custom headers, which do bring a preflight there: see the README.)\n */\nexport function sendEnd(\n target: AvatarRequestTarget & {\n sessionId: string;\n secret: string;\n reason: AvatarEndReason;\n },\n): void {\n try {\n void fetch(\n `${target.base}/sessions/${encodeURIComponent(target.sessionId)}/end`,\n {\n method: \"POST\",\n keepalive: true,\n credentials: \"omit\",\n cache: \"no-store\",\n headers: { ...target.headers },\n body: JSON.stringify({ secret: target.secret, reason: target.reason }),\n },\n ).catch(() => undefined);\n } catch {\n // No fetch at all: the server's own deadlines end the session.\n }\n}\n\n/** What scopes the bot check's binding to this contract, and its version. */\nconst BOT_BINDING_PREFIX = \"boff-web-avatar-cdata/v1\";\n\n/** The browser's WebCrypto `subtle`, or null where it has none to offer (a page that is not a secure context). */\nfunction webCryptoSubtle(): SubtleCrypto | null {\n const subtle = globalThis.crypto?.subtle;\n return typeof subtle?.digest === \"function\" ? subtle : null;\n}\n\n/**\n * Whether this browser can make the bot check's binding ({@link avatarBotBinding}): it needs WebCrypto's SHA-256.\n * Without it no live avatar can start here, so a start asks first, before it loads anything for one.\n */\nexport function canBindBotCheck(): boolean {\n return webCryptoSubtle() !== null;\n}\n\nfunction base64UrlNoPad(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n/**\n * The value the bot check is bound to, for Turnstile's `cData` (web API contract v1.1, additive):\n *\n * base64url_nopad( SHA-256( UTF-8( \"boff-web-avatar-cdata/v1\\n\" + site + \"\\n\" + locale + \"\\n\"\n * + conversationToken + \"\\n\" + messageId ) ) )\n *\n * The gateway recomputes it from the create body and checks it against the one Cloudflare returns with the verified\n * token, so a token minted for one request cannot be used for another. It must be made from the very values the create\n * body will carry, and before the widget is rendered: the caller builds the body once and hands the same one to this\n * and to {@link requestCreate}.\n *\n * Rejects where the browser has no WebCrypto (a page that is not a secure context): the bot check cannot be bound\n * there, so the live avatar does not start. {@link canBindBotCheck} says so beforehand, so that nothing is loaded for\n * a start that cannot happen.\n */\nexport async function avatarBotBinding(\n values: Pick<\n AvatarCreateBody,\n \"site\" | \"locale\" | \"conversationToken\" | \"messageId\"\n >,\n): Promise<string> {\n const subtle = webCryptoSubtle();\n if (subtle === null) {\n throw new Error(\"The bot check cannot be bound here: no WebCrypto.\");\n }\n const text = [\n BOT_BINDING_PREFIX,\n values.site,\n values.locale,\n values.conversationToken,\n values.messageId,\n ].join(\"\\n\");\n const digest = await subtle.digest(\"SHA-256\", new TextEncoder().encode(text));\n return base64UrlNoPad(new Uint8Array(digest));\n}\n\n/** A random UUID v4 for `Idempotency-Key`, or null where the browser has no cryptographic random source. */\nexport function newIdempotencyKey(): string | null {\n const crypto = globalThis.crypto;\n if (typeof crypto?.randomUUID === \"function\") return crypto.randomUUID();\n if (typeof crypto?.getRandomValues !== \"function\") return null;\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x40;\n bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80;\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\n \"\",\n );\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n","/**\n * BOFF-9797. The words of the live avatar's Avatar tab, in the six product locales, bundled like the rest of\n * Explore's copy (see `explore-i18n.ts` for why a marketing site bundles its strings).\n *\n * ## Review\n *\n * English is the reviewed copy. The other five locales are drafts awaiting translation review: each is a complete\n * object (a missing key is a type error), but the live avatar runs only in a locale that\n * {@link isAvatarLiveLocaleReviewed} lists. In any other, the Avatar tab stays as it was before the live avatar and\n * asks the server nothing. A locale is added there (in `explore-avatar-live-config.ts`) once its strings, and its\n * consent copy, have been reviewed.\n *\n * ## Consent\n *\n * The consent card's copy is versioned: the server names the version it will accept (`consentVersion`), and the panel\n * shows a consent card only when it holds copy written for exactly that version in the visitor's locale\n * ({@link avatarConsentCopy}). A version the SDK does not know, or a locale without reviewed copy for it, offers no\n * consent card at all, so a visitor never agrees to words other than the ones the server records. Each version also says\n * which bot check its words describe ({@link AvatarConsentCopy.botCheck}), and the card is shown only where the server\n * runs that one.\n *\n * ## The mic\n *\n * The Avatar tab's mic (Stage C) has words of its own, English only ({@link avatarMicStrings}), and a notice shown on\n * its first tap, versioned like the consent copy ({@link avatarMicNotice}): the SDK shows\n * {@link AVATAR_MIC_NOTICE_VERSION}, names it in every press, and the speech service takes the press only when that is\n * the version it records.\n */\n\nimport { isAvatarLiveLocaleReviewed } from \"./explore-avatar-live-config\";\n\nimport type { AvatarBotCheck, AvatarQuestions } from \"./explore-avatar-api\";\nimport type { ExploreLocale } from \"./explore-i18n\";\n\n// The reviewed locales are decided in `explore-avatar-live-config.ts`, which the panel reads without loading this file.\nexport { isAvatarLiveLocaleReviewed };\n\nexport interface AvatarLiveStrings {\n /** Status while the tab asks whether the live avatar is offered. Announced politely. */\n checking: string;\n /** No answer to read yet. */\n needsAnswer: string;\n needsAnswerDetail: string;\n /**\n * The conversation can never be read: its first answer failed, it has gone past the first question and answer, or\n * the answer is too old. Only a new chat can. The headline (announced politely), then the explanation, then a New\n * chat button. The avatar service reads exactly one answer: the first, completed, to a suggested question, within\n * fifteen minutes.\n */\n startNewChat: string;\n startNewChatDetail: string;\n /** The consent card's buttons. */\n start: string;\n notNow: string;\n /** After the privacy link, for screen readers: it opens in a new tab. */\n opensInNewTab: string;\n /** Status while the bot check runs. Announced politely. */\n botCheck: string;\n /** Status while the session is created and the room joined. Announced politely. */\n connecting: string;\n /** Status once the avatar's video plays. Announced politely. */\n speaking: string;\n /** Shown over the live video, always: the visitor is watching an AI, not a person. */\n badge: string;\n /** The video's accessible name. */\n video: string;\n /** The captions' accessible name. */\n captions: string;\n /** Before the countdown, which is never announced. */\n timeLeft: string;\n stop: string;\n /** Where the browser holds sound back until a tap (Safari, iOS). */\n tapForSound: string;\n /**\n * How a session ended. Announced politely. `finished` is \"the server closed the room, or the session's time ran out\n * with the room still open\": the browser cannot tell the avatar reading to the end from a server-side stop or a\n * hand-over, so it says only that the live avatar has ended.\n */\n finished: string;\n stopped: string;\n failed: string;\n interrupted: string;\n /** Under the captions and after a session: the answer itself is still in the conversation. */\n answerInChat: string;\n /**\n * In the status line while the avatar speaks, in place of `speaking`, when the server speaks only the first part of\n * the answer because the whole of it does not fit the session (the 201's `excerpt`, contract v1.4, Stage B).\n */\n excerpt: string;\n backToChat: string;\n /**\n * The refusals, one short sentence each, with no numbers in them (a number is spelled out). `notEligible` is the one\n * with a second sentence: it comes with a New chat button, and says what to do with it.\n */\n busy: string;\n limits: string;\n region: string;\n locale: string;\n paused: string;\n notEligible: string;\n answerClaimed: string;\n /**\n * The Avatar tab's own question box (BOFF-9797, contract v1.3): shown only where the server reads the answer to a\n * question the visitor typed too (`questions: \"any\"`), with consent copy written for that. The headline over the\n * suggested questions, the box's accessible name, its placeholder and the line under it, always visible with the box.\n */\n askHeadline: string;\n askLabel: string;\n askPlaceholder: string;\n askFooter: string;\n /** A file pasted or dropped on the box: the box takes text only. */\n askNoFiles: string;\n /** Why Send cannot be pressed: an answer is on its way, or the chat cannot take a question. */\n askBusy: string;\n askUnavailable: string;\n /** While the answer is written, when the chat reports no progress line of its own. Announced politely. */\n gettingAnswer: string;\n /**\n * The consent card's button while the answer is still being written: pressed, the avatar starts once the answer is\n * ready (`armed`), unless the visitor presses `cancel` or the start is called off (`armedCancelled`: the tab left,\n * the page hidden, the chat or the page changed, and the like).\n */\n startWhenReady: string;\n armed: string;\n cancel: string;\n armedCancelled: string;\n /** A first answer the avatar does not read (it fails the speech checks this browser can make): it stays in Chat. */\n notSpoken: string;\n /** The first answer failed. */\n answerFailed: string;\n /** Not now, under `any`: the card is offered again, while the answer is fresh, when the tab opens again. */\n declined: string;\n /** An answer to a question that was not the first of a new chat asked in this tab. */\n askHere: string;\n /**\n * Where the conversation can no longer be read: the button that starts a new chat for the avatar (the chat's own New\n * chat, staying on the Avatar tab), the note beside it, and the line once it has.\n */\n newChatForAvatar: string;\n newChatNote: string;\n newChatStarted: string;\n /** The button to the Chat tab, where the answer and its sources are. */\n readInChat: string;\n /** Over the box on the day this browser has had a live session. No number: the limits are the server's. */\n usedToday: string;\n /**\n * Under `any`, in place of `needsAnswer` (the box's description), `startNewChatDetail` and `notEligible`, which\n * speak of suggested questions only.\n */\n needsAnswerAny: string;\n startNewChatDetailAny: string;\n notEligibleAny: string;\n}\n\nconst EN: AvatarLiveStrings = {\n checking: \"Checking whether the live avatar is available…\",\n needsAnswer: \"Choose a suggested question in Chat first.\",\n needsAnswerDetail: \"The avatar can read only the first answer aloud.\",\n startNewChat: \"Start a new chat to use the avatar.\",\n startNewChatDetail:\n \"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.\",\n start: \"Start live avatar\",\n notNow: \"Not now\",\n opensInNewTab: \"(opens in a new tab)\",\n botCheck: \"Checking your browser…\",\n connecting: \"Connecting to the live avatar…\",\n speaking: \"The avatar is speaking.\",\n badge: \"AI avatar · not a real person\",\n video: \"Live AI avatar video\",\n captions: \"Captions\",\n timeLeft: \"Time left\",\n stop: \"Stop\",\n tapForSound: \"Tap to turn on sound\",\n finished: \"The live avatar has ended.\",\n stopped: \"You stopped the avatar.\",\n failed: \"The live avatar couldn't start.\",\n interrupted: \"The live avatar stopped early.\",\n answerInChat: \"The full answer is in Chat.\",\n excerpt:\n \"The avatar reads the first part of this answer. The full answer is in Chat.\",\n backToChat: \"Back to Chat\",\n busy: \"The live avatar is busy right now. Please try again in a few minutes.\",\n limits:\n \"The live avatar has reached its limit for now. Please try again later.\",\n region: \"The live avatar isn't offered in your region yet.\",\n locale: \"The live avatar isn't offered in this language yet.\",\n paused: \"The live avatar is paused right now.\",\n notEligible:\n \"The avatar reads the first answer to a suggested question, within fifteen minutes. Start a new chat and choose a suggested question.\",\n answerClaimed: \"The avatar has already read this answer.\",\n askHeadline: \"Ask a question, and the avatar reads the answer aloud.\",\n askLabel: \"Question for the avatar\",\n askPlaceholder: \"Ask the avatar…\",\n askFooter:\n \"Answers are AI-generated and can be wrong. Don't include personal details.\",\n askNoFiles: \"To attach files, use Chat.\",\n askBusy: \"You can ask when the current answer is ready.\",\n askUnavailable: \"Chat isn't available right now.\",\n gettingAnswer: \"Getting the answer…\",\n startWhenReady: \"Start when ready\",\n armed: \"The avatar will start when the answer is ready.\",\n cancel: \"Cancel\",\n armedCancelled:\n \"The avatar didn't start. Press Start when ready to try again.\",\n notSpoken:\n \"This answer stays in Chat as text. The avatar reads only answers that pass its speech checks.\",\n answerFailed: \"The assistant couldn't answer. Try asking again.\",\n declined: \"No problem. The answer is in Chat.\",\n askHere: \"To hear an answer, ask it here.\",\n newChatForAvatar: \"New chat for the avatar\",\n newChatNote: \"Your current chat stays in History.\",\n newChatStarted: \"Started a new chat for the avatar.\",\n readInChat: \"Read the answer and sources in Chat\",\n usedToday:\n \"You've had today's avatar session. Answers will show here as text.\",\n needsAnswerAny: \"Ask a question here, and the avatar reads the answer aloud.\",\n startNewChatDetailAny:\n \"The avatar reads aloud only the first answer in a new chat started in the Avatar tab, provided it passes the speech checks.\",\n notEligibleAny:\n \"The avatar can't read this answer aloud. The answer and sources are in Chat.\",\n};\n\n// TRANSLATION REVIEW PENDING (BOFF-9797): a draft, not yet reviewed. Not shown until \"zh\" is in REVIEWED.\nconst ZH: AvatarLiveStrings = {\n checking: \"正在检查实时虚拟形象是否可用…\",\n needsAnswer: \"请先在聊天中选择一个推荐问题。\",\n needsAnswerDetail: \"虚拟形象只能朗读第一个回答。\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n startNewChat: \"请开始新的聊天,再使用虚拟形象。\",\n startNewChatDetail:\n \"虚拟形象只朗读一次聊天中的第一个回答,且仅限推荐问题的回答、在十五分钟内。请开始新的聊天,并选择一个推荐问题。\",\n start: \"启动实时虚拟形象\",\n notNow: \"暂不\",\n opensInNewTab: \"(在新标签页中打开)\",\n botCheck: \"正在检查您的浏览器…\",\n connecting: \"正在连接实时虚拟形象…\",\n speaking: \"虚拟形象正在讲话。\",\n badge: \"AI 虚拟形象 · 不是真人\",\n video: \"实时 AI 虚拟形象视频\",\n captions: \"字幕\",\n timeLeft: \"剩余时间\",\n stop: \"停止\",\n tapForSound: \"点按以开启声音\",\n finished: \"实时虚拟形象已结束。\",\n stopped: \"您已停止虚拟形象。\",\n failed: \"实时虚拟形象无法启动。\",\n interrupted: \"实时虚拟形象提前停止了。\",\n answerInChat: \"完整回答在聊天中。\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the note for a part-read answer (Stage B).\n excerpt: \"虚拟形象朗读这个回答的第一部分。完整回答在聊天中。\",\n backToChat: \"返回聊天\",\n busy: \"实时虚拟形象目前繁忙,请几分钟后再试。\",\n limits: \"实时虚拟形象暂时已达到使用上限,请稍后再试。\",\n region: \"您所在的地区暂不提供实时虚拟形象。\",\n locale: \"此语言暂不提供实时虚拟形象。\",\n paused: \"实时虚拟形象目前已暂停。\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n notEligible:\n \"虚拟形象只朗读推荐问题的第一个回答,且须在十五分钟内。请开始新的聊天,并选择一个推荐问题。\",\n answerClaimed: \"虚拟形象已经朗读过这个回答。\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.\n askHeadline: \"提出问题,虚拟形象会朗读回答。\",\n askLabel: \"向虚拟形象提的问题\",\n askPlaceholder: \"向虚拟形象提问…\",\n askFooter: \"回答由 AI 生成,可能有误。请勿包含个人信息。\",\n askNoFiles: \"如需附加文件,请使用聊天。\",\n askBusy: \"当前回答准备好后即可提问。\",\n askUnavailable: \"聊天目前不可用。\",\n gettingAnswer: \"正在获取回答…\",\n startWhenReady: \"准备好后开始\",\n armed: \"回答准备好后,虚拟形象将开始。\",\n cancel: \"取消\",\n armedCancelled: \"虚拟形象未启动。可再次按“准备好后开始”。\",\n notSpoken:\n \"此回答以文字形式保留在聊天中。虚拟形象只朗读通过其语音检查的回答。\",\n answerFailed: \"助手无法回答。请重新提问。\",\n declined: \"没关系。回答在聊天中。\",\n askHere: \"如需听取回答,请在这里提问。\",\n newChatForAvatar: \"为虚拟形象开始新聊天\",\n newChatNote: \"当前聊天会保留在历史记录中。\",\n newChatStarted: \"已为虚拟形象开始新的聊天。\",\n readInChat: \"在聊天中查看回答和来源\",\n usedToday: \"您今天已使用过虚拟形象。回答将以文字显示在这里。\",\n needsAnswerAny: \"在这里提问,虚拟形象会朗读回答。\",\n startNewChatDetailAny:\n \"虚拟形象只朗读在“虚拟形象”标签页中开始的新聊天的第一个回答,且该回答须通过语音检查。\",\n notEligibleAny: \"虚拟形象无法朗读此回答。回答和来源在聊天中。\",\n};\n\n// TRANSLATION REVIEW PENDING (BOFF-9797): a draft, not yet reviewed. Not shown until \"hi\" is in REVIEWED.\nconst HI: AvatarLiveStrings = {\n checking: \"जाँच हो रही है कि लाइव अवतार उपलब्ध है या नहीं…\",\n needsAnswer: \"पहले चैट में कोई सुझाया गया प्रश्न चुनें।\",\n needsAnswerDetail: \"अवतार केवल पहला उत्तर ज़ोर से पढ़ सकता है।\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n startNewChat: \"अवतार का उपयोग करने के लिए नई चैट शुरू करें।\",\n startNewChatDetail:\n \"अवतार किसी चैट का केवल पहला उत्तर ज़ोर से पढ़ता है, वह भी सुझाए गए प्रश्न का और पंद्रह मिनट के भीतर। नई चैट शुरू करें और कोई सुझाया गया प्रश्न चुनें।\",\n start: \"लाइव अवतार शुरू करें\",\n notNow: \"अभी नहीं\",\n opensInNewTab: \"(नए टैब में खुलता है)\",\n botCheck: \"आपके ब्राउज़र की जाँच हो रही है…\",\n connecting: \"लाइव अवतार से जुड़ रहे हैं…\",\n speaking: \"अवतार बोल रहा है।\",\n badge: \"AI अवतार · असली व्यक्ति नहीं\",\n video: \"लाइव AI अवतार वीडियो\",\n captions: \"कैप्शन\",\n timeLeft: \"बचा हुआ समय\",\n stop: \"रोकें\",\n tapForSound: \"आवाज़ चालू करने के लिए टैप करें\",\n finished: \"लाइव अवतार समाप्त हो गया है।\",\n stopped: \"आपने अवतार को रोक दिया।\",\n failed: \"लाइव अवतार शुरू नहीं हो सका।\",\n interrupted: \"लाइव अवतार बीच में ही रुक गया।\",\n answerInChat: \"पूरा उत्तर चैट में है।\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the note for a part-read answer (Stage B).\n excerpt: \"अवतार इस उत्तर का पहला भाग पढ़ता है। पूरा उत्तर चैट में है।\",\n backToChat: \"चैट पर वापस जाएँ\",\n busy: \"लाइव अवतार अभी व्यस्त है। कृपया कुछ मिनट बाद फिर कोशिश करें।\",\n limits:\n \"लाइव अवतार अभी अपनी सीमा तक पहुँच गया है। कृपया बाद में फिर कोशिश करें।\",\n region: \"आपके क्षेत्र में लाइव अवतार अभी उपलब्ध नहीं है।\",\n locale: \"इस भाषा में लाइव अवतार अभी उपलब्ध नहीं है।\",\n paused: \"लाइव अवतार अभी रुका हुआ है।\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n notEligible:\n \"अवतार सुझाए गए प्रश्न का पहला उत्तर ही पढ़ता है, पंद्रह मिनट के भीतर। नई चैट शुरू करें और कोई सुझाया गया प्रश्न चुनें।\",\n answerClaimed: \"अवतार यह उत्तर पहले ही पढ़ चुका है।\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.\n askHeadline: \"कोई प्रश्न पूछें, और अवतार उसका उत्तर ज़ोर से पढ़ेगा।\",\n askLabel: \"अवतार के लिए प्रश्न\",\n askPlaceholder: \"अवतार से पूछें…\",\n askFooter:\n \"उत्तर AI द्वारा बनाए जाते हैं और गलत हो सकते हैं। निजी जानकारी शामिल न करें।\",\n askNoFiles: \"फ़ाइलें जोड़ने के लिए चैट का उपयोग करें।\",\n askBusy: \"मौजूदा उत्तर तैयार होने पर आप पूछ सकते हैं।\",\n askUnavailable: \"चैट अभी उपलब्ध नहीं है।\",\n gettingAnswer: \"उत्तर लाया जा रहा है…\",\n startWhenReady: \"तैयार होने पर शुरू करें\",\n armed: \"उत्तर तैयार होते ही अवतार शुरू होगा।\",\n cancel: \"रद्द करें\",\n armedCancelled:\n \"अवतार शुरू नहीं हुआ। फिर से कोशिश करने के लिए “तैयार होने पर शुरू करें” दबाएँ।\",\n notSpoken:\n \"यह उत्तर चैट में टेक्स्ट के रूप में रहेगा। अवतार केवल वही उत्तर पढ़ता है जो उसकी वाणी जाँच में पास होते हैं।\",\n answerFailed: \"सहायक उत्तर नहीं दे सका। फिर से पूछकर देखें।\",\n declined: \"कोई बात नहीं। उत्तर चैट में है।\",\n askHere: \"उत्तर सुनने के लिए, यहाँ पूछें।\",\n newChatForAvatar: \"अवतार के लिए नई चैट\",\n newChatNote: \"आपकी मौजूदा चैट इतिहास में रहेगी।\",\n newChatStarted: \"अवतार के लिए नई चैट शुरू की गई।\",\n readInChat: \"उत्तर और स्रोत चैट में पढ़ें\",\n usedToday:\n \"आज का अवतार सत्र आप ले चुके हैं। उत्तर यहाँ टेक्स्ट के रूप में दिखेंगे।\",\n needsAnswerAny: \"यहाँ प्रश्न पूछें, और अवतार उत्तर ज़ोर से पढ़ेगा।\",\n startNewChatDetailAny:\n \"अवतार केवल अवतार टैब में शुरू की गई नई चैट का पहला उत्तर ज़ोर से पढ़ता है, बशर्ते वह वाणी जाँच में पास हो।\",\n notEligibleAny:\n \"अवतार यह उत्तर ज़ोर से नहीं पढ़ सकता। उत्तर और स्रोत चैट में हैं।\",\n};\n\n// TRANSLATION REVIEW PENDING (BOFF-9797): a draft, not yet reviewed. Not shown until \"es\" is in REVIEWED.\nconst ES: AvatarLiveStrings = {\n checking: \"Comprobando si el avatar en vivo está disponible…\",\n needsAnswer: \"Primero elige una pregunta sugerida en el chat.\",\n needsAnswerDetail:\n \"El avatar solo puede leer en voz alta la primera respuesta.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n startNewChat: \"Inicia un chat nuevo para usar el avatar.\",\n startNewChatDetail:\n \"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.\",\n start: \"Iniciar el avatar en vivo\",\n notNow: \"Ahora no\",\n opensInNewTab: \"(se abre en una pestaña nueva)\",\n botCheck: \"Comprobando tu navegador…\",\n connecting: \"Conectando con el avatar en vivo…\",\n speaking: \"El avatar está hablando.\",\n badge: \"Avatar de IA · no es una persona real\",\n video: \"Vídeo del avatar de IA en vivo\",\n captions: \"Subtítulos\",\n timeLeft: \"Tiempo restante\",\n stop: \"Detener\",\n tapForSound: \"Toca para activar el sonido\",\n finished: \"El avatar en vivo ha terminado.\",\n stopped: \"Has detenido el avatar.\",\n failed: \"No se pudo iniciar el avatar en vivo.\",\n interrupted: \"El avatar en vivo se detuvo antes de tiempo.\",\n answerInChat: \"La respuesta completa está en el chat.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the note for a part-read answer (Stage B).\n excerpt:\n \"El avatar lee la primera parte de esta respuesta. La respuesta completa está en el chat.\",\n backToChat: \"Volver al chat\",\n busy: \"El avatar en vivo está ocupado en este momento. Vuelve a intentarlo en unos minutos.\",\n limits:\n \"El avatar en vivo ha alcanzado su límite por ahora. Vuelve a intentarlo más tarde.\",\n region: \"El avatar en vivo aún no está disponible en tu región.\",\n locale: \"El avatar en vivo aún no está disponible en este idioma.\",\n paused: \"El avatar en vivo está en pausa en este momento.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n notEligible:\n \"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.\",\n answerClaimed: \"El avatar ya ha leído esta respuesta.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.\n askHeadline: \"Haz una pregunta y el avatar leerá la respuesta en voz alta.\",\n askLabel: \"Pregunta para el avatar\",\n askPlaceholder: \"Pregunta al avatar…\",\n askFooter:\n \"Las respuestas las genera la IA y pueden contener errores. No incluyas datos personales.\",\n askNoFiles: \"Para adjuntar archivos, usa el chat.\",\n askBusy: \"Podrás preguntar cuando la respuesta actual esté lista.\",\n askUnavailable: \"El chat no está disponible en este momento.\",\n gettingAnswer: \"Obteniendo la respuesta…\",\n startWhenReady: \"Iniciar cuando esté lista\",\n armed: \"El avatar empezará cuando la respuesta esté lista.\",\n cancel: \"Cancelar\",\n armedCancelled:\n \"El avatar no se ha iniciado. Pulsa Iniciar cuando esté lista para volver a intentarlo.\",\n notSpoken:\n \"Esta respuesta se queda en el chat como texto. El avatar solo lee respuestas que superan sus comprobaciones de voz.\",\n answerFailed: \"El asistente no pudo responder. Vuelve a preguntar.\",\n declined: \"De acuerdo. La respuesta está en el chat.\",\n askHere: \"Para escuchar una respuesta, pregunta aquí.\",\n newChatForAvatar: \"Chat nuevo para el avatar\",\n newChatNote: \"Tu chat actual se queda en el historial.\",\n newChatStarted: \"Se ha iniciado un chat nuevo para el avatar.\",\n readInChat: \"Leer la respuesta y las fuentes en el chat\",\n usedToday:\n \"Ya has usado la sesión de avatar de hoy. Las respuestas se mostrarán aquí como texto.\",\n needsAnswerAny:\n \"Haz una pregunta aquí y el avatar leerá la respuesta en voz alta.\",\n startNewChatDetailAny:\n \"El avatar solo lee en voz alta la primera respuesta de un chat nuevo iniciado en la pestaña Avatar, si supera las comprobaciones de voz.\",\n notEligibleAny:\n \"El avatar no puede leer esta respuesta en voz alta. La respuesta y las fuentes están en el chat.\",\n};\n\n// TRANSLATION REVIEW PENDING (BOFF-9797): a draft, not yet reviewed, including its right-to-left layout. Not shown\n// until \"ar\" is in REVIEWED.\nconst AR: AvatarLiveStrings = {\n checking: \"جارٍ التحقق من توفر الأفاتار المباشر…\",\n needsAnswer: \"اختر أولًا سؤالًا مقترحًا في الدردشة.\",\n needsAnswerDetail: \"يمكن للأفاتار قراءة الإجابة الأولى فقط بصوت عالٍ.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n startNewChat: \"ابدأ دردشة جديدة لاستخدام الأفاتار.\",\n startNewChatDetail:\n \"يقرأ الأفاتار بصوت عالٍ الإجابة الأولى في الدردشة فقط، إذا كانت إجابة عن سؤال مقترح وخلال خمس عشرة دقيقة. ابدأ دردشة جديدة واختر سؤالًا مقترحًا.\",\n start: \"بدء الأفاتار المباشر\",\n notNow: \"ليس الآن\",\n opensInNewTab: \"(يُفتح في علامة تبويب جديدة)\",\n botCheck: \"جارٍ التحقق من متصفحك…\",\n connecting: \"جارٍ الاتصال بالأفاتار المباشر…\",\n speaking: \"الأفاتار يتحدث الآن.\",\n badge: \"أفاتار بالذكاء الاصطناعي · ليس شخصًا حقيقيًا\",\n video: \"فيديو الأفاتار المباشر بالذكاء الاصطناعي\",\n captions: \"التسميات التوضيحية\",\n timeLeft: \"الوقت المتبقي\",\n stop: \"إيقاف\",\n tapForSound: \"انقر لتشغيل الصوت\",\n finished: \"انتهى الأفاتار المباشر.\",\n stopped: \"لقد أوقفت الأفاتار.\",\n failed: \"تعذّر بدء الأفاتار المباشر.\",\n interrupted: \"توقف الأفاتار المباشر قبل أن ينتهي.\",\n answerInChat: \"الإجابة الكاملة موجودة في الدردشة.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the note for a part-read answer (Stage B).\n excerpt:\n \"يقرأ الأفاتار الجزء الأول من هذه الإجابة. الإجابة الكاملة موجودة في الدردشة.\",\n backToChat: \"العودة إلى الدردشة\",\n busy: \"الأفاتار المباشر مشغول الآن. يُرجى المحاولة مرة أخرى بعد بضع دقائق.\",\n limits: \"بلغ الأفاتار المباشر حدّه في الوقت الحالي. يُرجى المحاولة لاحقًا.\",\n region: \"الأفاتار المباشر غير متاح في منطقتك بعد.\",\n locale: \"الأفاتار المباشر غير متاح بهذه اللغة بعد.\",\n paused: \"الأفاتار المباشر متوقف مؤقتًا الآن.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n notEligible:\n \"يقرأ الأفاتار الإجابة الأولى عن سؤال مقترح، خلال خمس عشرة دقيقة. ابدأ دردشة جديدة واختر سؤالًا مقترحًا.\",\n answerClaimed: \"قرأ الأفاتار هذه الإجابة من قبل.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.\n askHeadline: \"اطرح سؤالًا، وسيقرأ الأفاتار الإجابة بصوت عالٍ.\",\n askLabel: \"سؤال للأفاتار\",\n askPlaceholder: \"اسأل الأفاتار…\",\n askFooter:\n \"الإجابات مُولَّدة بالذكاء الاصطناعي وقد تكون خاطئة. لا تضمّن بيانات شخصية.\",\n askNoFiles: \"لإرفاق ملفات، استخدم الدردشة.\",\n askBusy: \"يمكنك السؤال عندما تصبح الإجابة الحالية جاهزة.\",\n askUnavailable: \"الدردشة غير متاحة الآن.\",\n gettingAnswer: \"جارٍ الحصول على الإجابة…\",\n startWhenReady: \"البدء عند الجاهزية\",\n armed: \"سيبدأ الأفاتار عندما تصبح الإجابة جاهزة.\",\n cancel: \"إلغاء\",\n armedCancelled:\n \"لم يبدأ الأفاتار. اضغط على البدء عند الجاهزية للمحاولة مرة أخرى.\",\n notSpoken:\n \"تبقى هذه الإجابة في الدردشة نصًا. يقرأ الأفاتار فقط الإجابات التي تجتاز فحوص النطق.\",\n answerFailed: \"تعذّر على المساعد الإجابة. حاول السؤال مرة أخرى.\",\n declined: \"لا بأس. الإجابة موجودة في الدردشة.\",\n askHere: \"لسماع إجابة، اسأل هنا.\",\n newChatForAvatar: \"دردشة جديدة للأفاتار\",\n newChatNote: \"تبقى دردشتك الحالية في السجل.\",\n newChatStarted: \"بدأت دردشة جديدة للأفاتار.\",\n readInChat: \"اقرأ الإجابة والمصادر في الدردشة\",\n usedToday: \"لقد استخدمت جلسة الأفاتار لهذا اليوم. ستظهر الإجابات هنا نصًا.\",\n needsAnswerAny: \"اطرح سؤالًا هنا، وسيقرأ الأفاتار الإجابة بصوت عالٍ.\",\n startNewChatDetailAny:\n \"يقرأ الأفاتار بصوت عالٍ الإجابة الأولى فقط في دردشة جديدة بدأت في علامة تبويب الأفاتار، بشرط أن تجتاز فحوص النطق.\",\n notEligibleAny:\n \"لا يمكن للأفاتار قراءة هذه الإجابة بصوت عالٍ. الإجابة والمصادر موجودة في الدردشة.\",\n};\n\n// TRANSLATION REVIEW PENDING (BOFF-9797): a draft, not yet reviewed. Not shown until \"ta\" is in REVIEWED.\nconst TA: AvatarLiveStrings = {\n checking: \"நேரலை அவதார் கிடைக்கிறதா எனச் சரிபார்க்கிறது…\",\n needsAnswer:\n \"முதலில் அரட்டையில் பரிந்துரைக்கப்பட்ட ஒரு கேள்வியைத் தேர்ந்தெடுக்கவும்.\",\n needsAnswerDetail: \"அவதார் முதல் பதிலை மட்டுமே உரக்கப் படிக்க முடியும்.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n startNewChat: \"அவதாரைப் பயன்படுத்த புதிய அரட்டையைத் தொடங்கவும்.\",\n startNewChatDetail:\n \"ஓர் அரட்டையின் முதல் பதிலை மட்டுமே, அதுவும் பரிந்துரைக்கப்பட்ட கேள்விக்கான பதிலை, பதினைந்து நிமிடங்களுக்குள் மட்டுமே அவதார் உரக்கப் படிக்கும். புதிய அரட்டையைத் தொடங்கி, பரிந்துரைக்கப்பட்ட ஒரு கேள்வியைத் தேர்ந்தெடுக்கவும்.\",\n start: \"நேரலை அவதாரைத் தொடங்கு\",\n notNow: \"இப்போது வேண்டாம்\",\n opensInNewTab: \"(புதிய தாவலில் திறக்கும்)\",\n botCheck: \"உங்கள் உலாவியைச் சரிபார்க்கிறது…\",\n connecting: \"நேரலை அவதாருடன் இணைக்கிறது…\",\n speaking: \"அவதார் பேசுகிறது.\",\n badge: \"AI அவதார் · உண்மையான நபர் அல்ல\",\n video: \"நேரலை AI அவதார் வீடியோ\",\n captions: \"வசனங்கள்\",\n timeLeft: \"மீதமுள்ள நேரம்\",\n stop: \"நிறுத்து\",\n tapForSound: \"ஒலியை இயக்கத் தட்டவும்\",\n finished: \"நேரலை அவதார் முடிவடைந்தது.\",\n stopped: \"நீங்கள் அவதாரை நிறுத்தினீர்கள்.\",\n failed: \"நேரலை அவதாரைத் தொடங்க முடியவில்லை.\",\n interrupted: \"நேரலை அவதார் இடையிலேயே நின்றுவிட்டது.\",\n answerInChat: \"முழுப் பதில் அரட்டையில் உள்ளது.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the note for a part-read answer (Stage B).\n excerpt:\n \"அவதார் இந்தப் பதிலின் முதல் பகுதியைப் படிக்கிறது. முழுப் பதில் அரட்டையில் உள்ளது.\",\n backToChat: \"அரட்டைக்குத் திரும்பு\",\n busy: \"நேரலை அவதார் இப்போது வேறு பயன்பாட்டில் உள்ளது. சில நிமிடங்களில் மீண்டும் முயலவும்.\",\n limits:\n \"நேரலை அவதார் தற்போதைக்குத் தன் வரம்பை எட்டிவிட்டது. பிறகு மீண்டும் முயலவும்.\",\n region: \"உங்கள் பகுதியில் நேரலை அவதார் இன்னும் கிடைக்கவில்லை.\",\n locale: \"இந்த மொழியில் நேரலை அவதார் இன்னும் கிடைக்கவில்லை.\",\n paused: \"நேரலை அவதார் இப்போது இடைநிறுத்தப்பட்டுள்ளது.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n notEligible:\n \"பரிந்துரைக்கப்பட்ட கேள்விக்கான முதல் பதிலை மட்டுமே, பதினைந்து நிமிடங்களுக்குள், அவதார் படிக்கும். புதிய அரட்டையைத் தொடங்கி, பரிந்துரைக்கப்பட்ட ஒரு கேள்வியைத் தேர்ந்தெடுக்கவும்.\",\n answerClaimed: \"இந்தப் பதிலை அவதார் ஏற்கெனவே படித்துவிட்டது.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.\n askHeadline: \"ஒரு கேள்வியைக் கேளுங்கள், அவதார் பதிலை உரக்கப் படிக்கும்.\",\n askLabel: \"அவதாருக்கான கேள்வி\",\n askPlaceholder: \"அவதாரிடம் கேளுங்கள்…\",\n askFooter:\n \"பதில்கள் AI உருவாக்கியவை, தவறாக இருக்கலாம். தனிப்பட்ட விவரங்களைச் சேர்க்க வேண்டாம்.\",\n askNoFiles: \"கோப்புகளை இணைக்க, அரட்டையைப் பயன்படுத்தவும்.\",\n askBusy: \"தற்போதைய பதில் தயாரானதும் நீங்கள் கேட்கலாம்.\",\n askUnavailable: \"அரட்டை இப்போது கிடைக்கவில்லை.\",\n gettingAnswer: \"பதிலைப் பெறுகிறது…\",\n startWhenReady: \"தயாரானதும் தொடங்கு\",\n armed: \"பதில் தயாரானதும் அவதார் தொடங்கும்.\",\n cancel: \"ரத்துசெய்\",\n armedCancelled:\n \"அவதார் தொடங்கவில்லை. மீண்டும் முயல, தயாரானதும் தொடங்கு என்பதை அழுத்தவும்.\",\n notSpoken:\n \"இந்தப் பதில் அரட்டையில் உரையாகவே இருக்கும். பேச்சுச் சரிபார்ப்புகளில் தேறும் பதில்களை மட்டுமே அவதார் படிக்கும்.\",\n answerFailed:\n \"உதவியாளரால் பதிலளிக்க முடியவில்லை. மீண்டும் கேட்டுப் பாருங்கள்.\",\n declined: \"பரவாயில்லை. பதில் அரட்டையில் உள்ளது.\",\n askHere: \"பதிலைக் கேட்க, இங்கே கேளுங்கள்.\",\n newChatForAvatar: \"அவதாருக்கான புதிய அரட்டை\",\n newChatNote: \"உங்கள் தற்போதைய அரட்டை வரலாற்றில் இருக்கும்.\",\n newChatStarted: \"அவதாருக்காகப் புதிய அரட்டை தொடங்கப்பட்டது.\",\n readInChat: \"பதிலையும் ஆதாரங்களையும் அரட்டையில் படிக்கவும்\",\n usedToday:\n \"இன்றைய அவதார் அமர்வை நீங்கள் பயன்படுத்திவிட்டீர்கள். பதில்கள் இங்கே உரையாகக் காட்டப்படும்.\",\n needsAnswerAny:\n \"இங்கே ஒரு கேள்வியைக் கேளுங்கள், அவதார் பதிலை உரக்கப் படிக்கும்.\",\n startNewChatDetailAny:\n \"அவதார் தாவலில் தொடங்கிய புதிய அரட்டையின் முதல் பதிலை மட்டுமே, அது பேச்சுச் சரிபார்ப்புகளில் தேறினால், அவதார் உரக்கப் படிக்கும்.\",\n notEligibleAny:\n \"இந்தப் பதிலை அவதாரால் உரக்கப் படிக்க முடியாது. பதிலும் ஆதாரங்களும் அரட்டையில் உள்ளன.\",\n};\n\nconst STRINGS: Record<ExploreLocale, AvatarLiveStrings> = {\n en: EN,\n zh: ZH,\n hi: HI,\n es: ES,\n ar: AR,\n ta: TA,\n};\n\nexport function avatarLiveStrings(locale: ExploreLocale): AvatarLiveStrings {\n return STRINGS[locale] ?? EN;\n}\n\n/** One version of the consent card's copy, in one locale. */\nexport interface AvatarConsentCopy {\n title: string;\n /**\n * What the avatar is and does, for a site with a product name. Takes `{product}`. Null in a product-neutral version:\n * every site, named or not, shows {@link AvatarConsentCopy.intro}, so the card's words are the same on every site.\n */\n introProduct: string | null;\n /** The same without a product name, and the only intro of a product-neutral version. */\n intro: string;\n /** Who processes what when the visitor starts. */\n processing: string;\n /** What is and is not used, recorded and kept, and who it is for. */\n storage: string;\n /** The link to the site's privacy notice, `/privacy#live-avatar`. */\n privacyLink: string;\n /**\n * The bot check `processing` tells the visitor about: `turnstile` where it says Cloudflare checks for bots, `off`\n * where it says nothing of one. The card is shown only where the server's `botCheck` is the same, so the notice a\n * visitor agrees to never describes a check that does not run, or leaves out one that does.\n */\n botCheck: AvatarBotCheck;\n /**\n * Which first questions the words describe: `suggested` where they speak of a suggested question only, `any` where\n * they say a question the visitor typed is read too. The card is shown only where the server's `questions` is the\n * same (contract v1.3), and the Avatar tab's own question box only under `any`.\n */\n questions: AvatarQuestions;\n}\n\n/**\n * The consent copy the server's `consentVersion` names, by version and then by locale. A version is added here, never\n * edited: changed wording is a new version, which the server starts asking for at the same time.\n */\nconst CONSENT: ReadonlyMap<\n string,\n Readonly<Partial<Record<ExploreLocale, AvatarConsentCopy>>>\n> = new Map([\n [\n \"web-consent-2026-11\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct:\n \"This is an AI avatar, not a real person. It reads the assistant's first eligible answer to a suggested {product} question aloud for up to a minute. The answer is AI-generated and can be wrong.\",\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"suggested\",\n },\n },\n ],\n [\n // The voice is no longer a stored file: the server holds it in memory and plays it into the LiveKit room for Protoface.\n \"web-consent-2026-10-31\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct:\n \"This is an AI avatar, not a real person. It reads the assistant's first eligible answer to a suggested {product} question aloud for up to a minute. The answer is AI-generated and can be wrong.\",\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"suggested\",\n },\n },\n ],\n [\n // The words of web-consent-2026-10-31 with no product name in them: one notice, byte for byte, on every product's\n // site, because the server binds one consent version and one notice digest for all of them.\n \"web-consent-2026-11-02\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"suggested\",\n },\n },\n ],\n [\n // The words of web-consent-2026-11-02 without \"When you start, Cloudflare checks for bots.\", for a server that runs\n // no bot check (its availability's botCheck is `off`). Product-neutral too: one notice and one digest for every site.\n \"web-consent-2026-11-03\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"off\",\n questions: \"suggested\",\n },\n },\n ],\n [\n // The Avatar tab's own question box (contract v1.3, `questions: \"any\"`): the first answer in a new chat started in\n // the Avatar tab is read whether the visitor chose a suggested question or typed their own, so the intro says so and\n // warns against personal details in a typed one. Product-neutral, with the bot check: one notice and one digest for\n // every site (gitops docs/avatar-web/en-web-consent-2026-11-05.txt).\n \"web-consent-2026-11-05\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"any\",\n },\n },\n ],\n [\n // The words of web-consent-2026-11-05 without \"When you start, Cloudflare checks for bots.\", for a server that runs\n // no bot check (gitops docs/avatar-web/en-web-consent-2026-11-06.txt).\n \"web-consent-2026-11-06\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"off\",\n questions: \"any\",\n },\n },\n ],\n [\n // Stage B (operator decision 2026-11-04): web-consent-2026-11-05 with only its timing sentence changed. A session\n // lasts up to three minutes, sized by the server to the answer's audio; an answer longer than that is read in part,\n // which the avatar says and the Avatar tab notes (`excerpt`), and the full answer stays in Chat. A cap still\n // applies, so the words never say every answer is read whole (gitops docs/avatar-web/en-web-consent-2026-11-12-b.txt).\n \"web-consent-2026-11-12-b\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"This is an AI avatar, not a real person. It reads aloud 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. It reads for up to three minutes; if an answer is longer, it reads the first part, says so, and the full answer stays in Chat. The answer is AI-generated and can be wrong. Don't put personal details in a question you type.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"any\",\n },\n },\n ],\n [\n // The words of web-consent-2026-11-12-b without \"When you start, Cloudflare checks for bots.\", for a server that runs\n // no bot check (gitops docs/avatar-web/en-web-consent-2026-11-13-b.txt).\n \"web-consent-2026-11-13-b\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"This is an AI avatar, not a real person. It reads aloud 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. It reads for up to three minutes; if an answer is longer, it reads the first part, says so, and the full answer stays in Chat. The answer is AI-generated and can be wrong. Don't put personal details in a question you type.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"off\",\n questions: \"any\",\n },\n },\n ],\n]);\n\n/** The consent copy for exactly `version` in `locale`, or null when the SDK has none to show for it. */\nexport function avatarConsentCopy(\n version: string,\n locale: ExploreLocale,\n): AvatarConsentCopy | null {\n if (!isAvatarLiveLocaleReviewed(locale)) return null;\n return CONSENT.get(version)?.[locale] ?? null;\n}\n\n/**\n * The words of the Avatar tab's mic (BOFF-9797 Stage C): its button, the line that shows while it listens, and what a\n * press that gives no text says. English only, like the reviewed live-avatar copy: in any other locale the mic is not\n * offered (the box stays for typing).\n */\nexport interface AvatarMicStrings {\n /** The mic button's accessible name and title, when a tap starts a press. */\n micStart: string;\n /** The same while the mic opens or listens, when a tap stops it. */\n micStop: string;\n /** The mic notice's buttons: go on to the browser's permission prompt, or not. */\n micAllow: string;\n micNotNow: string;\n /** The status line while the microphone opens and the stream connects. Announced politely. */\n micStarting: string;\n /** The status line while it records. Announced politely; the time beside it never is. */\n micListening: string;\n /** The time recorded against the limit: takes `{elapsed}` and `{limit}` (`0:07`, `0:30`). */\n micElapsed: string;\n /** The status line once the recording has stopped, while the last of the text comes. */\n micFinishing: string;\n /** Once the text is in the box. The visitor corrects it and presses Send: nothing is sent by itself. */\n micDone: string;\n /** The same when the recording stopped at the limit. No number: it is spelled out. */\n micDoneLimit: string;\n /** No words were heard. */\n micNoSpeech: string;\n /** Why a press gave no text (`AvatarMicFailure`), each with the way on: typing in the box. */\n micDenied: string;\n micUnsupported: string;\n micUnavailable: string;\n micLimit: string;\n micBusy: string;\n micFailed: string;\n}\n\nconst MIC_EN: AvatarMicStrings = {\n micStart: \"Ask by voice\",\n micStop: \"Stop recording\",\n micAllow: \"Use the microphone\",\n micNotNow: \"Not now\",\n micStarting: \"Starting the microphone…\",\n micListening: \"Listening…\",\n micElapsed: \"{elapsed} of {limit}\",\n micFinishing: \"Getting the text…\",\n micDone: \"Check the text, then press Send.\",\n micDoneLimit:\n \"The recording stopped at thirty seconds. Check the text, then press Send.\",\n micNoSpeech: \"No words were heard. Try again, or type your question.\",\n micDenied:\n \"The microphone is blocked in this browser. You can type your question instead.\",\n micUnsupported:\n \"The microphone can't be used here. You can type your question instead.\",\n micUnavailable:\n \"Voice questions aren't available right now. You can type your question instead.\",\n micLimit:\n \"Voice questions have reached their limit for now. You can type your question instead.\",\n micBusy:\n \"Voice questions are busy right now. Try again in a moment, or type your question.\",\n micFailed:\n \"The microphone stopped before the text came. Try again, or type your question.\",\n};\n\nconst MIC_STRINGS: Readonly<Partial<Record<ExploreLocale, AvatarMicStrings>>> =\n { en: MIC_EN };\n\n/** The mic's words in `locale`, or null where there are none (the mic is then not offered). */\nexport function avatarMicStrings(\n locale: ExploreLocale,\n): AvatarMicStrings | null {\n if (!isAvatarLiveLocaleReviewed(locale)) return null;\n return MIC_STRINGS[locale] ?? null;\n}\n\n/** One version of the mic notice's copy, in one locale: shown on the first tap of the mic, before the browser asks. */\nexport interface AvatarMicNoticeCopy {\n title: string;\n /** Where the voice goes while the visitor speaks, and who turns it into text. */\n processing: string;\n /** What is and is not kept of the audio and the text. */\n storage: string;\n /** Where the text is before Send, that nothing is sent by itself, and what it is after Send. */\n text: string;\n /** How long one recording may be, and that there are daily limits. No numbers: they are spelled out. */\n limits: string;\n /** The link to the site's privacy notice, `/privacy#live-avatar`. */\n privacyLink: string;\n}\n\n/**\n * The mic notice version this SDK shows and names in every press (`notice` in the press's `config`). The speech service\n * takes a press only when this is its own `AVATAR_WEB_STT_NOTICE_VERSION`, and refuses any other (`notice-version`):\n * the SDK then offers the mic no more on that page, because it has no copy for the version the server records. A new\n * wording is a new version here and on the server at the same time, never an edit.\n */\nexport const AVATAR_MIC_NOTICE_VERSION = \"web-mic-2026-11-05\";\n\n/**\n * The mic notice's copy, by version and then by locale. A version is added here, never edited.\n *\n * PRIVACY REVIEW PENDING (BOFF-9797): `web-mic-2026-11-05` is a DRAFT for the operator's privacy review. Nothing shows\n * it until a site sets `avatar.live.mic` and the gateway's website speech-to-text is on (neither is anywhere), and it\n * must not be merged before the review: changed words are a new version. Its EU sentence needs the speech service's\n * region confirmed first (global-speech-svc `docs/SPEECH_STT.md`, \"Where speech is processed\").\n */\nconst MIC_NOTICE: ReadonlyMap<\n string,\n Readonly<Partial<Record<ExploreLocale, AvatarMicNoticeCopy>>>\n> = new Map([\n [\n AVATAR_MIC_NOTICE_VERSION,\n {\n en: {\n title: \"Ask with your voice\",\n processing:\n \"While you speak, your voice is streamed to our speech service, and Google Cloud Speech-to-Text turns it into text in Google's EU region.\",\n storage: \"We don't store or log your audio, or the text made from it.\",\n text: \"The text appears in the box and stays in this browser until you press Send. Nothing is sent by itself. Once you send it, it is a chat message, kept like any other.\",\n limits:\n \"Each recording stops after thirty seconds, and voice questions have daily limits.\",\n privacyLink: \"How we handle this\",\n },\n },\n ],\n]);\n\n/** The mic notice for exactly `version` in `locale`, or null when the SDK has none to show for it. */\nexport function avatarMicNotice(\n version: string,\n locale: ExploreLocale,\n): AvatarMicNoticeCopy | null {\n if (!isAvatarLiveLocaleReviewed(locale)) return null;\n return MIC_NOTICE.get(version)?.[locale] ?? null;\n}\n","/**\n * The Avatar tab's mic (BOFF-9797, Stage C): its button, its notice and its status line, in the live avatar's view.\n *\n * Tap to start and tap to stop, thirty seconds at most; what is heard shows as it is recognised, and the final text goes\n * into the Avatar tab's own question box, where the visitor corrects it and presses Send. Nothing is ever sent by itself:\n * the text goes into the box, and the box's Send (the view's single-flight `ask`) is the only way it leaves.\n *\n * - **Offered only** where the site opts in (`avatar.live.mic`), the server's availability answer carries a usable\n * `stt` offer, the box takes a question now (the view's `acceptsQuestion`), this SDK has the mic's words and its notice\n * for the visitor's locale, and the browser can capture at all. Anywhere else nothing of it renders.\n * - **The first tap shows the mic notice** (its version is {@link AVATAR_MIC_NOTICE_VERSION}), then, on \"Use the\n * microphone\", the browser's permission prompt. Agreed once, the notice is not shown again on this page.\n * - **Loaded only when used.** The capture, the stream and the press state machine are a chunk of their own\n * (`dist/avatar-mic/`, from `src/avatar-mic/`), loaded with a dynamic `import()` when the notice shows: this file\n * holds only the button, the words and that loader (`scripts/validate-avatar-live.mjs` checks the build).\n * - **Released on every way out** (the view calls `cancel`): the Chat tab, closing the panel, the page hidden or left,\n * the view going, the box no longer taking a question, and Stop. A press that refuses for good (the server's notice is\n * another version, a pause, a spent limit) takes the mic away for the rest of the page.\n */\n\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\n\nimport { Mic, Square } from \"lucide-react\";\n\nimport {\n AVATAR_MIC_NOTICE_VERSION,\n avatarMicNotice,\n avatarMicStrings,\n type AvatarMicStrings,\n} from \"./explore-avatar-i18n\";\nimport { fill } from \"./explore-fill\";\nimport { cn } from \"../utils/cn\";\n\nimport type { ExploreLocale } from \"./explore-i18n\";\nimport type {\n AvatarMic,\n AvatarMicFailure,\n AvatarMicModule,\n AvatarMicOffer,\n AvatarMicState,\n} from \"../avatar-mic/types\";\n\n/** Where the notice's privacy link goes: the site's privacy notice, at its live avatar section. */\nconst PRIVACY_HREF = \"/privacy#live-avatar\";\n/** The longest press, as the visitor sees it: the mic's own limit (`MAX_PRESS_MS` in `src/avatar-mic/press.ts`). */\nconst LIMIT_SECONDS = 30;\n/** How often the time recorded is brought up to date while it listens. */\nconst TICK_MS = 250;\n\nconst IDLE: AvatarMicState = { name: \"idle\" };\n\n/** The refusals after which the mic is offered no more on this page: the server will not take a press from it. */\nconst FOR_GOOD: ReadonlySet<AvatarMicFailure> = new Set<AvatarMicFailure>([\n \"unavailable\",\n \"limit\",\n]);\n\nconst FAILURE_TEXT: Record<AvatarMicFailure, keyof AvatarMicStrings> = {\n denied: \"micDenied\",\n unsupported: \"micUnsupported\",\n unavailable: \"micUnavailable\",\n limit: \"micLimit\",\n busy: \"micBusy\",\n failed: \"micFailed\",\n};\n\n/**\n * Load the mic's chunk. The package build leaves this `import()` as it is, pointing at the file it builds beside the\n * view's (`tsup.config.ts`), so a site's bundler splits it into a chunk of its own; `scripts/validate-avatar-live.mjs`\n * checks that it did.\n */\nexport function loadAvatarMic(): Promise<AvatarMicModule> {\n return import(\"../avatar-mic\").then((loaded) => ({\n createAvatarMic: loaded.createAvatarMic,\n }));\n}\n\n/**\n * Whether this browser can capture and stream here at all: a microphone API (only in a secure context), an\n * AudioWorklet, and WebSockets. Read without loading the mic's chunk.\n */\nexport function canUseAvatarMic(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n typeof navigator.mediaDevices?.getUserMedia === \"function\" &&\n typeof AudioContext !== \"undefined\" &&\n typeof AudioWorkletNode !== \"undefined\" &&\n typeof WebSocket !== \"undefined\"\n );\n}\n\n/** `m:ss`, counting up. */\nfunction clock(seconds: number): string {\n const whole = Math.max(0, Math.floor(seconds));\n return `${Math.floor(whole / 60)}:${String(whole % 60).padStart(2, \"0\")}`;\n}\n\n/** The box's text with `heard` added: after what is already there, and never past `maxLength`. */\nexport function withHeardText(\n current: string,\n heard: string,\n maxLength: number,\n): string {\n const text = heard.trim();\n if (text === \"\") return current;\n const joined =\n current.trim() === \"\" ? text : `${current.replace(/\\s+$/, \"\")} ${text}`;\n return joined.slice(0, Math.max(0, maxLength));\n}\n\nexport interface UseAvatarMicOptions {\n /**\n * Everything the view decides: the site opts in, the server's availability carries an offer, and the box takes a\n * question now. The words, the notice, the browser and the mic's own refusals are this hook's.\n */\n enabled: boolean;\n locale: ExploreLocale;\n /** `avatarApiBase` of the SDK's gateway, null when there is none to use. */\n base: string | null;\n /** The latest offer the view holds (null when its last availability answer carried none). */\n offer: AvatarMicOffer | null;\n /** Ask availability again for a new offer, and hold it: null when the answer carries none; rejects with no answer. */\n refreshOffer: () => Promise<AvatarMicOffer | null>;\n /** The final text of a press: the view puts it in the box. Never called with nothing. */\n onText: (text: string) => void;\n}\n\nexport interface AvatarMicControls {\n /** The mic button, for the box's row; null when the mic is not offered. */\n button: ReactNode;\n /** The notice, shown on the first tap, for over the box; null otherwise. */\n notice: ReactNode;\n /**\n * The status line, the time recorded and what is heard, for under the box's row; null when the box can have no mic\n * now. (After a refusal for good, only the line saying so.)\n */\n lines: ReactNode;\n /** Call off whatever the mic has under way and release the microphone. For every way out of the view. */\n cancel: () => void;\n}\n\n/** The mic of the Avatar tab's box. See the file's comment. */\nexport function useAvatarMic({\n enabled,\n locale,\n base,\n offer,\n refreshOffer,\n onText,\n}: UseAvatarMicOptions): AvatarMicControls {\n const S = avatarMicStrings(locale);\n const copy = avatarMicNotice(AVATAR_MIC_NOTICE_VERSION, locale);\n const uid = useId();\n const noticeTitleId = `${uid}-mic-notice`;\n\n /** Why a press was refused for good, which takes the mic away for the rest of the page (and still says why). */\n const [withdrawn, setWithdrawn] = useState<AvatarMicFailure | null>(null);\n // Read once on the client: no microphone API while rendering on a server, and the first client render matches it.\n const [supported, setSupported] = useState(false);\n useEffect(() => setSupported(canUseAvatarMic()), []);\n\n /** The box could have a mic now: its lines show (a refusal for good is still said there). */\n const possible =\n enabled && supported && base !== null && S !== null && copy !== null;\n /** The mic itself is offered: its button shows. */\n const offered = possible && withdrawn === null;\n\n const [state, setState] = useState<AvatarMicState>(IDLE);\n const [noticeOpen, setNoticeOpen] = useState(false);\n /** The visitor agreed to the notice on this page (for this version). */\n const agreedRef = useRef(false);\n /** The mic's chunk is loading for a tap (the time before there is a press to report). */\n const [loading, setLoading] = useState(false);\n /** Why the last attempt gave nothing, where it never became a press (the chunk could not be loaded). */\n const [loadFailed, setLoadFailed] = useState(false);\n const [now, setNow] = useState(() => Date.now());\n\n const micRef = useRef<{ base: string; mic: AvatarMic } | null>(null);\n /** Counts every tap and every cancel: a chunk that arrives after either starts nothing. */\n const seqRef = useRef(0);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const allowRef = useRef<HTMLButtonElement>(null);\n /** The press whose text has gone into the box, so a re-render never puts it in twice. */\n const usedEpochRef = useRef(0);\n\n const latest = useRef({ offer, refreshOffer, onText, base });\n latest.current = { offer, refreshOffer, onText, base };\n\n const cancel = useCallback(() => {\n seqRef.current += 1;\n setLoading(false);\n setLoadFailed(false);\n setNoticeOpen(false);\n micRef.current?.mic.cancel();\n }, []);\n\n // No longer offered (the box took a question, the server's offer went, the view went off): what is under way ends.\n useEffect(() => {\n if (!offered) cancel();\n }, [offered, cancel]);\n // The view going: the same, and a tap whose chunk is still on its way starts nothing when it arrives.\n useEffect(\n () => () => {\n seqRef.current += 1;\n micRef.current?.mic.cancel();\n },\n [],\n );\n\n /** The mic for `base`: made once its chunk is loaded, and again only for another gateway. */\n const micFor = useCallback(async (target: string): Promise<AvatarMic> => {\n const held = micRef.current;\n if (held !== null && held.base === target) return held.mic;\n held?.mic.cancel();\n const loaded = await loadAvatarMic();\n const mic = loaded.createAvatarMic({\n base: target,\n notice: AVATAR_MIC_NOTICE_VERSION,\n offer: () => latest.current.offer,\n refreshOffer: () => latest.current.refreshOffer(),\n onState: setState,\n });\n micRef.current = { base: target, mic };\n return mic;\n }, []);\n\n /** A press, once the notice is agreed to: the chunk (loaded already, as a rule, while the notice showed), then start. */\n const press = useCallback(() => {\n const target = latest.current.base;\n if (target === null) return;\n seqRef.current += 1;\n const seq = seqRef.current;\n setLoadFailed(false);\n setLoading(true);\n void micFor(target).then(\n (mic) => {\n if (seqRef.current !== seq) return;\n setLoading(false);\n mic.start();\n },\n () => {\n if (seqRef.current !== seq) return;\n setLoading(false);\n setLoadFailed(true);\n },\n );\n }, [micFor]);\n\n const recording =\n loading || state.name === \"starting\" || state.name === \"listening\";\n\n const tap = useCallback(() => {\n if (state.name === \"listening\" || state.name === \"starting\") {\n micRef.current?.mic.stop();\n return;\n }\n if (loading) {\n cancel();\n return;\n }\n if (!agreedRef.current) {\n setNoticeOpen(true);\n // The chunk, while the notice is read: the tap on \"Use the microphone\" then starts at once.\n void loadAvatarMic().catch(() => undefined);\n return;\n }\n press();\n }, [cancel, loading, press, state.name]);\n\n const allow = useCallback(() => {\n agreedRef.current = true;\n setNoticeOpen(false);\n buttonRef.current?.focus();\n press();\n }, [press]);\n\n const notNow = useCallback(() => {\n setNoticeOpen(false);\n buttonRef.current?.focus();\n }, []);\n\n // The notice takes focus as it opens: its first control is the way on.\n useEffect(() => {\n if (noticeOpen) allowRef.current?.focus();\n }, [noticeOpen]);\n\n // The time recorded, while it listens.\n const listeningSince = state.name === \"listening\" ? state.startedAt : null;\n useEffect(() => {\n if (listeningSince === null) return;\n setNow(Date.now());\n const timer = setInterval(() => setNow(Date.now()), TICK_MS);\n return () => clearInterval(timer);\n }, [listeningSince]);\n\n // A press's final text goes into the box, once; a refusal for good takes the mic away.\n useEffect(() => {\n if (state.name === \"done\" && state.epoch !== usedEpochRef.current) {\n usedEpochRef.current = state.epoch;\n if (state.text !== \"\") latest.current.onText(state.text);\n } else if (state.name === \"failed\" && FOR_GOOD.has(state.reason)) {\n setWithdrawn(state.reason);\n }\n }, [state]);\n\n if (!possible || S === null || copy === null) {\n return { button: null, notice: null, lines: null, cancel };\n }\n\n const status =\n withdrawn !== null\n ? S[FAILURE_TEXT[withdrawn]]\n : loading\n ? S.micStarting\n : loadFailed\n ? S.micFailed\n : state.name === \"starting\"\n ? S.micStarting\n : state.name === \"listening\"\n ? S.micListening\n : state.name === \"finishing\"\n ? S.micFinishing\n : state.name === \"done\"\n ? state.text === \"\"\n ? S.micNoSpeech\n : state.limit\n ? S.micDoneLimit\n : S.micDone\n : state.name === \"failed\"\n ? S[FAILURE_TEXT[state.reason]]\n : \"\";\n const heard =\n offered && (state.name === \"listening\" || state.name === \"finishing\")\n ? state.text\n : \"\";\n\n const button = !offered ? null : (\n <button\n ref={buttonRef}\n type=\"button\"\n aria-label={recording ? S.micStop : S.micStart}\n aria-pressed={recording}\n title={recording ? S.micStop : S.micStart}\n data-boff-explore=\"avatar-live-mic\"\n data-mic={loading ? \"starting\" : state.name}\n className={cn(\n \"inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-md border transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background motion-reduce:transition-none\",\n recording\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-border bg-background text-foreground hover:bg-accent hover:text-accent-foreground\",\n )}\n onClick={tap}\n >\n {recording ? (\n <Square aria-hidden=\"true\" className=\"h-4 w-4\" />\n ) : (\n <Mic aria-hidden=\"true\" className=\"h-4 w-4\" />\n )}\n </button>\n );\n\n const notice =\n offered && noticeOpen ? (\n <section\n aria-labelledby={noticeTitleId}\n data-boff-explore=\"avatar-live-mic-notice\"\n className=\"w-full rounded-lg border border-border p-3 text-start\"\n >\n <h3 id={noticeTitleId} className=\"text-sm font-semibold\">\n {copy.title}\n </h3>\n <p className=\"mt-1 text-xs text-muted-foreground\">{copy.processing}</p>\n <p className=\"mt-1 text-xs text-muted-foreground\">{copy.storage}</p>\n <p className=\"mt-1 text-xs text-muted-foreground\">{copy.text}</p>\n <p className=\"mt-1 text-xs text-muted-foreground\">{copy.limits}</p>\n <a\n href={PRIVACY_HREF}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-boff-explore=\"avatar-live-mic-privacy\"\n className=\"mt-1 inline-block text-xs font-medium text-primary underline underline-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {copy.privacyLink}\n </a>\n <div className=\"mt-2 flex flex-wrap gap-2\">\n <button\n ref={allowRef}\n type=\"button\"\n data-boff-explore=\"avatar-live-mic-allow\"\n className=\"inline-flex min-h-11 items-center justify-center rounded-md bg-primary px-4 py-2 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 motion-reduce:transition-none\"\n onClick={allow}\n >\n {S.micAllow}\n </button>\n <button\n type=\"button\"\n data-boff-explore=\"avatar-live-mic-not-now\"\n className=\"inline-flex min-h-11 items-center justify-center rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background motion-reduce:transition-none\"\n onClick={notNow}\n >\n {S.micNotNow}\n </button>\n </div>\n </section>\n ) : null;\n\n const listening = offered && state.name === \"listening\";\n const lines = (\n <>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n {listening ? (\n <span aria-hidden=\"true\" className=\"relative flex h-2 w-2 shrink-0\">\n <span className=\"absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75 motion-reduce:animate-none\" />\n <span className=\"relative inline-flex h-2 w-2 rounded-full bg-primary\" />\n </span>\n ) : null}\n <p role=\"status\" data-boff-explore=\"avatar-live-mic-status\">\n {status}\n </p>\n {listening ? (\n <span\n role=\"timer\"\n data-boff-explore=\"avatar-live-mic-elapsed\"\n className=\"tabular-nums\"\n >\n {fill(S.micElapsed, {\n elapsed: clock(\n Math.min(LIMIT_SECONDS, (now - (listeningSince ?? now)) / 1000),\n ),\n limit: clock(LIMIT_SECONDS),\n })}\n </span>\n ) : null}\n </div>\n {heard === \"\" ? null : (\n <p\n data-boff-explore=\"avatar-live-mic-heard\"\n dir=\"auto\"\n className=\"line-clamp-3 break-words text-sm italic text-muted-foreground\"\n >\n {heard}\n </p>\n )}\n </>\n );\n\n return { button, notice, lines, cancel };\n}\n","/**\n * BOFF-9797. Cloudflare Turnstile, for the live avatar's start only.\n *\n * Nothing here runs until the visitor presses Start on the live avatar's consent card: the script is added to the page\n * then, once, and a widget is rendered for that one start (action `avatar_start`). The widget stays invisible unless\n * Cloudflare needs the visitor to interact with it. The token it returns goes to the gateway in a header and is used\n * once.\n *\n * The widget is rendered with `cData`, the binding of this check to the create request it is for (web API contract\n * v1.1: see `avatarBotBinding` in `explore-avatar-api.ts`), so it cannot be rendered before the binding is known.\n */\n\nconst SCRIPT_SRC =\n \"https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit\";\n/** How long the script may take to load before the start is given up. */\nconst SCRIPT_TIMEOUT_MS = 15_000;\n\n/** The part of Turnstile's render options used here. */\ninterface TurnstileRenderOptions {\n sitekey: string;\n action: string;\n /** Customer data Turnstile returns with the verified token: the binding to the create request. */\n cData: string;\n appearance: \"interaction-only\";\n size: \"flexible\";\n \"response-field\": false;\n callback: (token: string) => void;\n \"error-callback\": () => boolean;\n \"expired-callback\": () => void;\n \"timeout-callback\": () => void;\n}\n\n/** The part of `window.turnstile` used here. */\ninterface TurnstileApi {\n render: (\n container: HTMLElement,\n options: TurnstileRenderOptions,\n ) => string | null | undefined;\n remove: (widgetId: string) => void;\n}\n\nfunction readApi(): TurnstileApi | null {\n if (typeof window === \"undefined\") return null;\n const api = (window as unknown as { turnstile?: Partial<TurnstileApi> })\n .turnstile;\n return api &&\n typeof api.render === \"function\" &&\n typeof api.remove === \"function\"\n ? (api as TurnstileApi)\n : null;\n}\n\nlet loading: Promise<TurnstileApi> | null = null;\n\n/** Turnstile's API, adding its script to the page the first time. A failed load can be tried again later. */\nexport function loadTurnstile(): Promise<TurnstileApi> {\n const ready = readApi();\n if (ready) return Promise.resolve(ready);\n if (loading) return loading;\n loading = new Promise<TurnstileApi>((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = SCRIPT_SRC;\n script.async = true;\n script.setAttribute(\"data-boff-explore\", \"avatar-live-turnstile\");\n const fail = () => {\n clearTimeout(timer);\n loading = null;\n script.remove();\n reject(new Error(\"The bot check could not be loaded.\"));\n };\n const timer = setTimeout(fail, SCRIPT_TIMEOUT_MS);\n script.addEventListener(\"load\", () => {\n const api = readApi();\n if (!api) {\n fail();\n return;\n }\n clearTimeout(timer);\n resolve(api);\n });\n script.addEventListener(\"error\", fail);\n document.head.appendChild(script);\n });\n return loading;\n}\n\nexport interface TurnstileRun {\n /** The token, once Cloudflare has one; rejects when the check fails, expires, times out or is cancelled. */\n token: Promise<string>;\n /** Remove the widget, and reject `token` if it is still waiting. Safe to call more than once. */\n cancel: () => void;\n}\n\n/**\n * Run one bot check in `container` with `siteKey`, for `action`, bound to `cData` (or to what it resolves to: the widget\n * is rendered once its script has loaded AND the binding is known, and a binding that cannot be made fails the check).\n */\nexport function runTurnstile(\n container: HTMLElement | null,\n siteKey: string,\n action: string,\n cData: string | Promise<string>,\n): TurnstileRun {\n // A binding that cannot be made fails `token`; it is never an unhandled rejection of its own.\n Promise.resolve(cData).catch(() => undefined);\n let settled = false;\n let cancelled = false;\n let widget: { api: TurnstileApi; id: string } | null = null;\n let rejectToken: (error: Error) => void = () => undefined;\n\n const removeWidget = () => {\n if (!widget) return;\n const { api, id } = widget;\n widget = null;\n try {\n api.remove(id);\n } catch {\n // Already gone with its container.\n }\n };\n\n const token = new Promise<string>((resolve, reject) => {\n rejectToken = (error: Error) => {\n if (settled) return;\n settled = true;\n reject(error);\n };\n if (!container) {\n rejectToken(new Error(\"No place for the bot check.\"));\n return;\n }\n Promise.all([loadTurnstile(), cData]).then(\n ([api, binding]) => {\n if (cancelled || settled) return;\n const failed = () => {\n removeWidget();\n rejectToken(new Error(\"The bot check did not pass.\"));\n };\n const id = api.render(container, {\n sitekey: siteKey,\n action,\n cData: binding,\n appearance: \"interaction-only\",\n size: \"flexible\",\n \"response-field\": false,\n callback: (value: string) => {\n if (settled) return;\n settled = true;\n resolve(value);\n },\n \"error-callback\": () => {\n failed();\n // Handled here: Turnstile need not report it again.\n return true;\n },\n \"expired-callback\": failed,\n \"timeout-callback\": failed,\n });\n if (typeof id === \"string\" && id !== \"\") {\n widget = { api, id };\n if (settled) removeWidget();\n } else if (!settled) {\n rejectToken(new Error(\"The bot check could not start.\"));\n }\n },\n (error: unknown) => {\n rejectToken(\n error instanceof Error\n ? error\n : new Error(\"The bot check could not be loaded.\"),\n );\n },\n );\n });\n\n // A cancelled check nobody waits on any more is not an error worth reporting.\n token.catch(() => undefined);\n\n return {\n token,\n cancel: () => {\n cancelled = true;\n removeWidget();\n rejectToken(new Error(\"The bot check was cancelled.\"));\n },\n };\n}\n","/**\n * AvatarLiveView — the Avatar tab's live avatar (BOFF-9797), opt-in: its view and its state machine.\n *\n * `ExploreAvatarLive` (`explore-avatar-live.tsx`) renders this, and only once the Avatar view has been opened on a panel\n * whose host passes `avatar.live`. This file, and the requests, the words and the bot check it brings with it, is a\n * chunk of its own that a site downloads at that moment and not before; a site that never passes `avatar.live` never\n * does. It reads nothing from the page's React contexts (the package builds each entry on its own, so a context read\n * here would be a second, empty one): everything it needs comes in as props from `ExploreAvatarLive`.\n *\n * The visitor watches and listens; their browser never sends the avatar anything to say. What happens, in order:\n *\n * 1. **The tab opens** (never on page load): one availability request to the gateway's web branch. Nothing else is\n * loaded or asked for until the visitor agrees.\n * 2. **Offered, with the conversation's first answer:** a consent card (its copy is versioned; the panel shows only\n * copy written for the version the server names), Start, Not now and a link to the privacy notice. The avatar reads\n * one answer only: a conversation that is exactly a suggested question and its completed answer, while that answer\n * is fresh (see {@link ANSWER_OFFER_MS}). A failed first answer, a second question or an answer that is too old asks\n * the visitor to start a new chat instead, with a New chat button.\n * 3. **Start:** the live module (`live.load`) and, where the server checks for bots (availability's `botCheck`, contract\n * v1.2), the bot check load, then one create request: the contract's six fields, an `Idempotency-Key` and the bot\n * check's token, without credentials. The bot check is bound to that very request (`cData`, contract v1.1), so the\n * body is made once, before the widget is rendered. Where the server runs no bot check, no Cloudflare script or\n * widget is loaded and the request carries no token.\n * 4. **Created:** the room is joined to watch only. The avatar's video, its captions, a badge saying it is an AI and\n * not a person, a countdown (never announced), Stop and Continue in Chat.\n * 5. **Ending:** Stop, closing the panel, leaving the page (`pagehide`) or the live avatar going off asks the server to\n * end the session with a `keepalive` request. The server ends it on its own deadlines either way. Once the create has\n * been sent, switching to the Chat tab or to another browser tab does not end it: the pane is only hidden, so the\n * room's video and audio stay attached and the avatar speaks to its planned end (see `leave`). Before the create,\n * both still call off what is under way, with nothing created. Where the host sets `live.endUnattended`, a session\n * out of sight also ends once its answer has played out, and soon when the browser holds its sound back (see\n * `attend`): an idle tail after an answer runs only while the Avatar view is in sight.\n *\n * **Asking in the Avatar tab** (contract v1.3): where the server reads the answer to a question the visitor typed too\n * (availability's `questions` is `any`) and this SDK holds consent copy written for that, the tab has a question box of\n * its own, with the suggested questions as chips. A question asked there (`surface: \"AVATAR\"`) is the first of a new\n * chat, and its first answer is the only one offered: the consent card shows while the answer is written, with \"Start\n * when ready\", which waits for the answer, asks availability again and checks the answer as the service will, and only\n * then creates the session. Any other conversation is never read: the tab offers \"New chat for the avatar\", and never\n * resets a conversation by itself. After the day's session (a `limits` refusal, or this browser's own note of one) the\n * box asks ordinary questions, and the answer shows as text. Under `suggested`, or with a server older than v1.3, the\n * tab is as it was.\n *\n * **The mic** (Stage C, `explore-avatar-mic.tsx`): where the host sets `live.mic`, the last availability answer carried\n * a mic offer (`stt`) and the box takes the first question of a new chat ({@link acceptsQuestion}), the box has a mic:\n * tap to start, tap to stop, thirty seconds at most, after a notice of its own on the first tap. Its final text goes into\n * the box for the visitor to correct and Send; nothing is sent by itself. Every way out of the view (`leave`, Stop, the\n * view going) stops it and releases the microphone first. Its capture and stream are a chunk of their own, loaded when\n * it is first used.\n *\n * Any refusal is one short sentence and \"Continue in Chat\". A route that is not there, a refused origin or a network\n * failure shows the tab as it was before the live avatar, except once the create request has been sent: the server may\n * have made the session by then, so a create that gets no answer (by its deadline, which the wait never outlasts) says\n * the live avatar couldn't start, and a session its answer brings after that is ended at once, never joined. The\n * conversation token goes into the create request and nowhere else; the session's secret and room token are kept in\n * refs, never in the page.\n */\n\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ClipboardEvent as ReactClipboardEvent,\n type DragEvent as ReactDragEvent,\n type KeyboardEvent as ReactKeyboardEvent,\n type ReactNode,\n} from \"react\";\n\nimport { answerDisplayText } from \"./explore-answer-text\";\nimport {\n avatarBotBinding,\n canBindBotCheck,\n isAvatarConversationToken,\n isAvatarMessageId,\n newIdempotencyKey,\n requestAvailability,\n requestAvailabilityAnswer,\n requestCreate,\n sendEnd,\n type AvatarAvailability,\n type AvatarBotCheck,\n type AvatarCreateBody,\n type AvatarCreateResult,\n type AvatarEndReason,\n type AvatarOffer,\n type AvatarQuestions,\n type AvatarRefusal,\n type AvatarSession,\n} from \"./explore-avatar-api\";\nimport {\n avatarConsentCopy,\n avatarLiveStrings,\n type AvatarConsentCopy,\n type AvatarLiveStrings,\n} from \"./explore-avatar-i18n\";\nimport { turnstileSiteKeyOf } from \"./explore-avatar-live-config\";\nimport { useAvatarMic, withHeardText } from \"./explore-avatar-mic\";\nimport { runTurnstile, type TurnstileRun } from \"./explore-avatar-turnstile\";\nimport { fill } from \"./explore-fill\";\nimport { cn } from \"../utils/cn\";\n\nimport type {\n AvatarConversation,\n ExplorePanelAvatarLive,\n} from \"./explore-avatar-live-config\";\nimport type { ExploreLocale } from \"./explore-i18n\";\nimport type { ExploreMessage } from \"./explore-types\";\nimport type {\n AvatarLiveModule,\n ReceiveOnlyEvent,\n ReceiveOnlySession,\n} from \"../avatar-live/types\";\nimport type { AvatarMicOffer } from \"../avatar-mic/types\";\n\n/** Where the consent card's privacy link goes: the site's privacy notice, at its live avatar section. */\nconst PRIVACY_HREF = \"/privacy#live-avatar\";\n\n/** How long a joined room waits for the avatar's video before the session is given up. */\nconst SPEAKER_WAIT_MS = 30_000;\n/** Past a session's end, how long before the browser leaves a room that is somehow still open. */\nconst END_GRACE_MS = 10_000;\n/** How far the server's end may sit from this browser's clock before the browser counts down on its own clock. */\nconst CLOCK_TOLERANCE_MS = 5_000;\n/**\n * Under `endUnattended`: out of sight, how long a session whose sound the browser holds back goes on before it is ended\n * (see `attend`). Long enough for a visitor who has just switched to the Chat tab or another browser tab to come back\n * and find \"Tap to turn on sound\"; short enough that a session nobody can hear is not paid for to its end.\n */\nconst UNHEARD_GRACE_MS = 5_000;\n/**\n * Under `endUnattended`: from the end of the speech at its source (`speech-ended`) to the answer's playout as the\n * visitor hears it. The worker's voice lags its source, and the server keeps a session for that lag: its planned end is\n * the speech's first frame + its length + a 3 s tail allowance (global-speech-svc `docs/AVATAR_WEB_API.md`, \"Timing\").\n * This is that allowance plus 2 s, so the last words are never cut, and the server's own end, which counts as a natural\n * finish only when no end request came before it, comes first while the server ends a session after its answer.\n */\nconst PLAYOUT_TAIL_MS = 5_000;\n\n/**\n * The avatar service refuses an answer more than fifteen minutes old (`not_eligible`; `MAX_AGE_MS` in global-speech-svc\n * `src/avatar/web/eligibility.ts`, measured from the answer's `createdAt` on the service's clock). If it changes, this\n * and the \"fifteen minutes\" in the `notEligible` and `startNewChatDetail` strings change with it.\n */\nconst SERVICE_MAX_AGE_MS = 15 * 60_000;\n/**\n * How long after an answer was created the view offers the avatar for it: a minute less than the service allows, so\n * that a visitor who reads the consent card near the edge is not sent through Start and a create request the service\n * will refuse. A visitor on the consent card when the answer crosses this age is moved to the start-over step (one\n * timer, set for that moment). Once Start is pressed, the create is skipped only past the service's own limit.\n */\nconst ANSWER_OFFER_MS = SERVICE_MAX_AGE_MS - 60_000;\n/** The longest delay a browser's `setTimeout` keeps (about 24.8 days): a longer one fires at once. */\nconst MAX_TIMER_MS = 2_147_483_647;\n\n/**\n * The longest question the Avatar tab's own box takes: the avatar service's limit for a question the visitor typed (the\n * chat's own limit is longer).\n */\nconst ASK_MAX_LENGTH = 300;\n/** The most references an answer the avatar service reads may cite (`eligibility.ts`); it needs at least one. */\nconst MAX_REFERENCES = 64;\n/**\n * Where this browser notes the day (UTC) it had a live session, so the box can say the day's session is used and ask in\n * text. A hint only: the limits are the server's.\n */\nconst USED_ON_KEY = \"boff.explore.avatarUsedOn\";\n\n/** The control each step puts focus on when the one the visitor was on has gone. */\nconst PRIMARY =\n '[data-avatar-primary], [data-boff-explore=\"panel-continue-chat\"]';\n\ninterface Offer extends AvatarOffer {\n /** The locale availability was asked for: the consent copy shown and the create request are both in this one. */\n locale: ExploreLocale;\n copy: AvatarConsentCopy;\n}\n\n/** What the page shows of a session: never its secret or its room token. */\ninterface ShownSession {\n /** When this browser counts the session as over, on its own clock. */\n endsAt: number;\n captions: { locale: string; text: string };\n /** Only the first part of the answer is spoken (the 201's `excerpt`): the status line says so while it plays. */\n excerpt: boolean;\n}\n\n/**\n * How a session ended. `finished` means the server closed the room (the worker left, or the room was closed by the\n * server) while the avatar was live, or the session's time ran out with the room still open: the browser cannot tell the\n * avatar reading to the end from a server-side stop or a hand-over, so the words for it say only that the live avatar\n * has ended.\n */\ntype EndedHow = \"finished\" | \"stopped\" | \"failed\" | \"interrupted\";\n\ntype Phase =\n | { name: \"idle\" }\n | { name: \"checking\" }\n | { name: \"inert\" }\n | { name: \"needs-answer\"; offer: Offer }\n | { name: \"consent\"; offer: Offer; messageId: string }\n /** Under `any`: Not now. The card is offered again when the tab next opens, while the answer is fresh. */\n | { name: \"declined\"; offer: Offer }\n /** Under `any`: \"Start when ready\" pressed while the answer is still being written (see {@link WaitRun}). */\n | { name: \"waiting\"; offer: Offer }\n | { name: \"refused\"; reason: AvatarRefusal }\n | { name: \"bot-check\"; offer: Offer; messageId: string }\n | { name: \"creating\" }\n | { name: \"pending\"; session: ShownSession }\n | { name: \"live\"; session: ShownSession }\n | { name: \"ended\"; how: EndedHow };\n\nconst IDLE: Phase = { name: \"idle\" };\nconst INERT: Phase = { name: \"inert\" };\n\n/** One press of Start, until its create request has answered. */\ninterface StartRun {\n /** Set when the visitor (or the page) gave up on it, with the reason to end a session it still creates. */\n cancelled: AvatarEndReason | null;\n turnstile: TurnstileRun | null;\n}\n\n/**\n * One press of \"Start when ready\", until the answer is ready and checked (or the start is called off). The press is the\n * visitor's consent for exactly what it is bound to: this conversation, its first question and the answer on its way,\n * the site, the locale and the page, and the consent version and bot check that availability named. Any of them\n * changing calls it off with nothing created; once the answer is ready, availability is asked again and the answer\n * checked again, and anything that differs shows the card again instead of creating.\n */\ninterface WaitRun {\n bound: {\n token: string;\n questionId: string;\n answerId: string;\n site: string;\n locale: ExploreLocale;\n path: string;\n consentVersion: string;\n botCheck: AvatarBotCheck;\n };\n /** The room module, loading while the answer is written. */\n module: Promise<AvatarLiveModule>;\n /** The availability question asked again once the answer is ready; null until then. */\n check: AbortController | null;\n}\n\n/** A created session, from its 201 until it ends. */\ninterface SessionHandle {\n session: AvatarSession;\n base: string;\n headers: Readonly<Record<string, string>>;\n module: AvatarLiveModule;\n /** The join, once started. */\n room: Promise<ReceiveOnlySession | null> | null;\n /** The joined room, once joined: `enablePlayback` must be called inside the visitor's tap, so not via a promise. */\n joined: ReceiveOnlySession | null;\n /** When this browser counts the session as over, on its own clock (see `begin`). */\n endsAt: number;\n /** The avatar's video has arrived. */\n speakerArrived: boolean;\n /**\n * The avatar's voice (its audio track) has arrived. Until then a held-back sound is the room's guess (it reports a\n * suspended audio context as soon as it connects, and takes it back once the voice actually plays), not a voice\n * speaking to nobody.\n */\n voiceArrived: boolean;\n /** The browser holds the avatar's sound back (`playback-blocked`'s `sound`): nobody hears it until a tap. */\n soundHeld: boolean;\n /** The answer has played out: its speech ended at the source, and {@link PLAYOUT_TAIL_MS} has passed since. */\n playedOut: boolean;\n /** The attention rule's timers (see `attend`): the grace for held-back sound, and the playout tail. */\n unheard: ReturnType<typeof setTimeout> | null;\n tail: ReturnType<typeof setTimeout> | null;\n done: boolean;\n}\n\n/** Clear the attention rule's timers (see `attend`): the session has ended, or the view has gone. */\nfunction stopAttending(handle: SessionHandle): void {\n if (handle.unheard !== null) clearTimeout(handle.unheard);\n if (handle.tail !== null) clearTimeout(handle.tail);\n handle.unheard = null;\n handle.tail = null;\n}\n\nconst REFUSAL_TEXT: Record<AvatarRefusal, keyof AvatarLiveStrings> = {\n busy: \"busy\",\n limits: \"limits\",\n region: \"region\",\n locale: \"locale\",\n paused: \"paused\",\n not_eligible: \"notEligible\",\n answer_claimed: \"answerClaimed\",\n};\n\n/**\n * What the first exchange is. `answer` is the one the avatar may read; the others say why there is none yet, or never in\n * this conversation:\n *\n * - `empty`: nothing asked yet; `asking`: the first question, its answer on its way;\n * - `text-only` (under `any`): a completed first answer that fails a check the service makes and this browser can make\n * too (it cites none of the site's documentation, more references than the service takes, files with the question);\n * - `failed` (under `any`): the first answer failed;\n * - `ask-here` (under `any`): the first answer to a question that was not asked in this tab as the first of a new chat;\n * - `start-over`: anything else (a second question, an answer whose id the service cannot take, one too old).\n */\ntype ExchangeKind =\n | \"empty\"\n | \"asking\"\n | \"answer\"\n | \"text-only\"\n | \"failed\"\n | \"ask-here\"\n | \"start-over\";\n\n/** What the conversation offers the avatar to read. */\ninterface Exchange {\n kind: ExchangeKind;\n /** The answer the avatar may read, or null: set for `answer` only. */\n answerId: string | null;\n /**\n * The conversation can never be read: its first answer failed or is unusable, or it has gone past the first\n * exchange. Only a new chat can be. False while there is simply nothing to read yet.\n */\n startOver: boolean;\n /**\n * With an answer: until when (this browser's clock, in milliseconds) it is offered, {@link ANSWER_OFFER_MS} after its\n * `createdAt`. `NaN` for an answer whose `createdAt` is missing or cannot be read, which is never offered (the\n * service would refuse it). `NaN` without an answer too.\n */\n offerUntil: number;\n /** The first question, while the conversation is its first exchange; null otherwise. */\n question: ExploreMessage | null;\n /** Asking: the id the server gave the answer on its way (the one it keeps once complete), or null before then. */\n pendingAnswerId: string | null;\n /** Under `any`: the first question was asked in this tab, as the first of a new chat, in this page's visit. */\n askedHere: boolean;\n}\n\nconst EMPTY: Exchange = {\n kind: \"empty\",\n answerId: null,\n startOver: false,\n offerUntil: NaN,\n question: null,\n pendingAnswerId: null,\n askedHere: false,\n};\nconst START_OVER: Exchange = { ...EMPTY, kind: \"start-over\", startOver: true };\n\n/**\n * A question this tab asked as the first of a new chat, recorded only once the chat's `send` has actually added it: the\n * id of the USER message it added, and the conversation's token as that send ended (null when the server never named\n * one: a send that failed before the server took it). Not its text: the server stores the question normalized (line\n * endings, control characters, runs of blank lines: `normalizeExploreMessage` in global-support-svc), so the words in\n * the chat can differ from the ones the box sent, and the id alone already names the one message.\n */\ninterface AskedHere {\n messageId: string;\n token: string | null;\n}\n\n/**\n * Which rules the exchange is read by: the server's `questions`, the question this tab asked as the first of a new\n * chat (null when none), the conversation's token now, and whether the chat has a question on its way (`sending` or\n * `streaming`).\n */\ninterface ExchangeRules {\n any: boolean;\n askedHere: AskedHere | null;\n token: string | null;\n inFlight: boolean;\n}\n\nconst SUGGESTED_RULES: ExchangeRules = {\n any: false,\n askedHere: null,\n token: null,\n inFlight: false,\n};\n\n/**\n * Whether `question` is the one this tab asked: the very USER message its send added (its id), in the conversation that\n * send ended in. A question asked in Chat is never it, whatever it says (the same words included), and neither is a\n * conversation opened from History whose first question happens to read the same.\n */\nfunction isAskedHere(question: ExploreMessage, rules: ExchangeRules): boolean {\n const asked = rules.askedHere;\n return (\n rules.any &&\n asked !== null &&\n question.id === asked.messageId &&\n asked.token === rules.token\n );\n}\n\n/** A message's `createdAt` in milliseconds, or `NaN` when it is missing or not a date. */\nfunction createdAtOf(message: ExploreMessage): number {\n const raw: unknown = message.createdAt;\n return typeof raw === \"string\" && raw !== \"\" ? Date.parse(raw) : NaN;\n}\n\n/**\n * The exchange as it stands at `now`: an answer past its {@link Exchange.offerUntil} (or with no readable time) is\n * no longer offered, and only a new chat can be.\n */\nfunction offeredAt(exchange: Exchange, now: number): Exchange {\n // `!(now < …)` and not `now >= …`: with a `NaN` deadline (no readable `createdAt`) it is true, so the answer is not\n // offered.\n return exchange.answerId !== null && !(now < exchange.offerUntil)\n ? START_OVER\n : exchange;\n}\n\n/**\n * The checks on a first answer that the avatar service makes and this browser can make as well (`eligibility.ts` in\n * global-speech-svc): it is an answer (`answered`), it cites between one and {@link MAX_REFERENCES} references, and no\n * files came with the question. The service stays the judge: this only keeps the card from offering what it refuses.\n */\nfunction readable(question: ExploreMessage, answer: ExploreMessage): boolean {\n const references = answer.references?.length ?? 0;\n return (\n answer.answered === true &&\n references >= 1 &&\n references <= MAX_REFERENCES &&\n (question.attachments?.length ?? 0) === 0\n );\n}\n\n/**\n * The one answer the avatar may read, and why there is none. The avatar service accepts a conversation only when it\n * holds EXACTLY two messages: the first USER message and the first ASSISTANT answer, COMPLETED. This is the same rule,\n * so the avatar is never offered, and the visitor never goes through consent and the bot check, for a conversation the\n * service would refuse:\n *\n * - exactly that exchange: its answer;\n * - nothing asked yet, or the question asked and its answer still on its way: nothing yet (the view says to choose a\n * suggested question, or that the answer is coming, and offers the avatar once the answer completes);\n * - anything else (a failed or empty first answer, a second question, whatever came after a failed answer asked\n * again without Retry): never, in this conversation (the view says to start a new chat).\n *\n * The service also refuses an answer more than fifteen minutes old: a conversation restored from this browser's\n * history, say. That depends on the time as well as the messages, so it is applied on top of this (`offeredAt`), with\n * the answer's {@link Exchange.offerUntil}.\n *\n * Under `suggested`, that the question is one of the suggested ones is the service's to judge (`not_eligible`), not the\n * browser's. Under `any` (the Avatar tab's own box), the answer is offered only to a question this tab asked as the\n * first of a new chat, and only when it passes the checks this browser can make too ({@link readable}); a failed\n * first answer is told apart, so the tab can say so.\n */\nfunction firstExchange(\n messages: readonly ExploreMessage[] | undefined,\n rules: ExchangeRules = SUGGESTED_RULES,\n): Exchange {\n if (!messages || messages.length === 0) return EMPTY;\n if (messages.length > 2) return START_OVER;\n const [question, answer] = messages;\n if (question?.role !== \"USER\") return START_OVER;\n const first = { question, askedHere: isAskedHere(question, rules) };\n if (answer === undefined) {\n // The question alone. On its way: the answer is coming. Otherwise none is: the chat drops a failed answer that\n // had no text (and one a reload cut short), so under `any` the tab says the answer failed; under `suggested`, as\n // before, nothing has been answered yet.\n if (rules.inFlight) return { ...EMPTY, ...first, kind: \"asking\" };\n return rules.any ? { ...START_OVER, ...first, kind: \"failed\" } : EMPTY;\n }\n if (answer.role !== \"ASSISTANT\") return START_OVER;\n if (answer.status === \"PENDING\" || answer.status === \"RUNNING\") {\n return {\n ...EMPTY,\n ...first,\n kind: \"asking\",\n pendingAnswerId: isAvatarMessageId(answer.id) ? answer.id : null,\n };\n }\n if (rules.any && answer.status === \"FAILED\") {\n return { ...START_OVER, ...first, kind: \"failed\" };\n }\n if (\n answer.status !== \"COMPLETED\" ||\n answer.content.trim() === \"\" ||\n !isAvatarMessageId(answer.id)\n ) {\n return START_OVER;\n }\n if (rules.any && !first.askedHere) {\n return { ...START_OVER, ...first, kind: \"ask-here\" };\n }\n if (rules.any && !readable(question, answer)) {\n return { ...START_OVER, ...first, kind: \"text-only\" };\n }\n return {\n ...EMPTY,\n ...first,\n kind: \"answer\",\n answerId: answer.id,\n offerUntil: createdAtOf(answer) + ANSWER_OFFER_MS,\n };\n}\n\n/** Whether the chat has a question on its way. */\nfunction inFlight(conversation: AvatarConversation | null): boolean {\n return (\n conversation?.phase === \"sending\" || conversation?.phase === \"streaming\"\n );\n}\n\n/** What the Avatar tab's mic reads of the tab to tell whether its box takes a question now. */\ninterface AskSlot {\n /** The server reads typed questions (`questions: \"any\"`): the tab has a box of its own. */\n any: boolean;\n phase: Phase[\"name\"];\n /** The exchange as offered now. */\n kind: ExchangeKind;\n /** The box asks ordinary questions, whose answers stay text (see `textMode`). */\n textMode: boolean;\n /** Why the box's Send cannot be pressed now, or null when it can. */\n reason: string | null;\n}\n\n/**\n * Whether the Avatar tab's own box takes a question right now, for the avatar: the one rule the mic is offered by (with\n * the site's opt-in and the server's offer). Stage C: only the box that asks the avatar the first question of a new\n * chat (nothing asked yet, not asking in text) while the chat can take one. Stage D widens this rule, and only this\n * rule, to a follow-up question in a live session.\n */\nfunction acceptsQuestion(slot: AskSlot): boolean {\n return (\n slot.any &&\n !slot.textMode &&\n slot.phase === \"needs-answer\" &&\n slot.kind === \"empty\" &&\n slot.reason === null\n );\n}\n\n/** The mic's offer from an availability answer, stamped with this browser's clock; null without one. */\nfunction micOfferOf(result: AvatarAvailability): AvatarMicOffer | null {\n return result.kind === \"available\" && result.offer.stt !== undefined\n ? { ...result.offer.stt, receivedAt: Date.now() }\n : null;\n}\n\n/** Today, as UTC: the day the box's note of a used session is for. */\nfunction utcToday(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\n/** Whether this browser noted a live session today. Storage that cannot be read (a private window) is no note. */\nfunction usedTodayHere(): boolean {\n try {\n return window.localStorage.getItem(USED_ON_KEY) === utcToday();\n } catch {\n return false;\n }\n}\n\n/** Note today's live session, where this browser lets the page keep it. */\nfunction noteUsedToday(): void {\n try {\n window.localStorage.setItem(USED_ON_KEY, utcToday());\n } catch {\n // Storage blocked: the box simply does not know, and the server's limits still hold.\n }\n}\n\n/** A tenth of a second of silence, as a WAV data URI, made once, the first time a Start needs it. */\nlet silence: string | null = null;\n\nfunction silentWav(): string {\n if (silence !== null) return silence;\n // 8 kHz, 8-bit mono: 800 samples at the mid level (128) is silence.\n const rate = 8_000;\n const samples = rate / 10;\n const bytes = new Uint8Array(44 + samples);\n const view = new DataView(bytes.buffer);\n const text = (at: number, value: string) => {\n for (let i = 0; i < value.length; i += 1) {\n bytes[at + i] = value.charCodeAt(i);\n }\n };\n text(0, \"RIFF\");\n view.setUint32(4, 36 + samples, true);\n text(8, \"WAVE\");\n text(12, \"fmt \");\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true); // PCM\n view.setUint16(22, 1, true); // mono\n view.setUint32(24, rate, true);\n view.setUint32(28, rate, true); // bytes a second\n view.setUint16(32, 1, true); // bytes a frame\n view.setUint16(34, 8, true); // bits a sample\n text(36, \"data\");\n view.setUint32(40, samples, true);\n bytes.fill(128, 44);\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n silence = `data:audio/wav;base64,${btoa(binary)}`;\n return silence;\n}\n\n/**\n * Let the page play sound later: called straight from the visitor's tap on Start (browsers allow sound only from inside\n * a gesture, and Safari on iOS keeps an element locked until then), it plays a tenth of a second of silence on the\n * element the room's audio will use, and pauses it. \"Tap to turn on sound\" stays for a browser that still holds sound\n * back. An element already playing a room's audio is left alone.\n */\nfunction unlockSound(audio: HTMLAudioElement | null): void {\n if (audio === null || audio.srcObject) return;\n try {\n audio.src = silentWav();\n void Promise.resolve(audio.play()).then(\n () => audio.pause(),\n () => undefined,\n );\n } catch {\n // A browser that cannot play it now: the room's own playback, and the sound button, still work.\n }\n}\n\n/**\n * The step that offers `messageId` to the visitor: the consent card, unless this visit has already used that answer\n * (`claimed` holds every answer a session was created for, or that the server said it already has one for), in which\n * case it says so instead. The ways back to a consent card for an answer that may have been used in the meantime go\n * through here: the availability answer, and returning from a bot check.\n */\nfunction offering(\n offer: Offer,\n messageId: string,\n claimed: ReadonlySet<string>,\n): Phase {\n return claimed.has(messageId)\n ? { name: \"refused\", reason: \"answer_claimed\" }\n : { name: \"consent\", offer, messageId };\n}\n\nasync function loadModule(\n load: () => Promise<AvatarLiveModule>,\n): Promise<AvatarLiveModule> {\n const loaded: unknown = await load();\n const join =\n loaded !== null && typeof loaded === \"object\"\n ? (loaded as Partial<AvatarLiveModule>).joinReceiveOnly\n : undefined;\n if (typeof join !== \"function\") {\n throw new Error(\"The live avatar module could not be loaded.\");\n }\n return loaded as AvatarLiveModule;\n}\n\n/** `m:ss`. */\nfunction clock(seconds: number): string {\n const whole = Math.max(0, Math.ceil(seconds));\n return `${Math.floor(whole / 60)}:${String(whole % 60).padStart(2, \"0\")}`;\n}\n\nexport interface AvatarLiveViewProps {\n live: ExplorePanelAvatarLive;\n /** The Avatar view is showing: the panel is open and its Avatar tab is selected. */\n active: boolean;\n /**\n * The panel is open, whichever tab it shows. With `active` it tells the Chat tab (open, not active: the pane is only\n * hidden, and a session under way keeps playing) from the panel closing (not open: what is under way ends).\n */\n open: boolean;\n locale: ExploreLocale;\n /** The product the panel speaks for, when it is one product's own; null on the portfolio's. */\n productName: string | null;\n /** The approved still picture. */\n still: { src: string; alt: string };\n /** The Avatar tab as it was before the live avatar: shown whenever the live avatar is not offered or not reachable. */\n fallback: ReactNode;\n /**\n * Back to the Chat tab. Like the Chat tab itself, it calls off a start that has not been sent yet, and leaves a\n * session under way speaking.\n */\n onContinueInChat: () => void;\n /**\n * Told whenever the avatar's voice starts or stops being the page's: its status line while a session is being\n * created, joined or played (\"Connecting to the live avatar…\", \"The avatar is speaking.\"), and null otherwise (and\n * when the view goes). The panel holds Chat's own read-aloud and dictation meanwhile, so the page never speaks in two\n * voices and the microphone never takes down the avatar's.\n */\n onVoiceHold?: (line: string | null) => void;\n /** \"Continue in Chat\" in the panel's language: the panel's own word for it, so this chunk carries none of the panel's. */\n continueInChat: string;\n /**\n * \"New chat\" in the panel's language, the panel's own word for it: the button that starts over (the conversation's\n * `reset`, as the chat's own New chat button does, then the Chat tab) where this conversation can never be read.\n */\n newChat: string;\n /** \"Send\" and \"Try asking\" in the panel's language, for the Avatar tab's own question box. */\n send: string;\n tryAsking: string;\n /** The suggested questions the chat view shows: the box's chips. */\n prompts: readonly string[];\n /** No precise pointer: the box is not focused by itself, so the keyboard does not cover the view. */\n touchFirst: boolean;\n /** The host router's path, when it has one: a \"Start when ready\" is called off when it changes. */\n currentPath: string | undefined;\n /**\n * Nothing to ask the server about: an incomplete config, no gateway, no shared conversation to read (no provider, or a\n * read-only shared one), or a locale whose strings have not been reviewed. The tab stays as it was. Decided by\n * `ExploreAvatarLive`, which also decides whether this view is loaded at all; it can change while this view is\n * mounted (the panel's locale switching), and what is under way then ends.\n */\n off: boolean;\n /** {@link avatarApiBase} of the SDK's gateway, null when there is none to use. */\n base: string | null;\n /** Headers every request carries: the alpha gateway's access headers, and nothing on production. */\n headers: Readonly<Record<string, string>>;\n /** The panel's conversation, null when there is no provider. */\n conversation: AvatarConversation | null;\n}\n\nexport function AvatarLiveView({\n live,\n active,\n open,\n locale,\n productName,\n still,\n fallback,\n onContinueInChat,\n onVoiceHold,\n continueInChat,\n newChat,\n send,\n tryAsking,\n prompts,\n touchFirst,\n currentPath,\n off,\n base,\n headers,\n conversation,\n}: AvatarLiveViewProps) {\n const S = avatarLiveStrings(locale);\n const uid = useId();\n const consentTitleId = `${uid}-consent`;\n\n /**\n * Which first questions the server reads the answer to, as its last availability answer said (`suggested` until one\n * says `any`). Kept in a ref as well, for the steps that read it between renders.\n */\n const [questions, setQuestions] = useState<AvatarQuestions>(\"suggested\");\n const questionsRef = useRef<AvatarQuestions>(\"suggested\");\n /**\n * The question this tab asked as the first of a new chat, in this page's visit; null when none. Recorded only once the\n * chat's `send` says which message it added (see `ask`), and set and cleared through {@link setAskedHere} alone.\n */\n const askedHereRef = useRef<AskedHere | null>(null);\n /**\n * Counts every ask from the box and every clearing of {@link askedHereRef}: an ask whose send resolves after a New\n * chat, a reset, another conversation or a later ask records nothing.\n */\n const askSeqRef = useRef(0);\n /** Re-renders the view when {@link askedHereRef} changes: a ref alone would leave the card unshown. */\n const [, setAskedHereTick] = useState(0);\n const setAskedHere = useCallback((next: AskedHere | null) => {\n if (next === null) {\n askSeqRef.current += 1;\n if (askedHereRef.current === null) return;\n }\n askedHereRef.current = next;\n setAskedHereTick((tick) => tick + 1);\n }, []);\n\n // Compared, never shown: see `getConversationToken`.\n const token = conversation?.getConversationToken() ?? null;\n const exchange = firstExchange(conversation?.messages, {\n any: questions === \"any\",\n askedHere: askedHereRef.current,\n token,\n inFlight: inFlight(conversation),\n });\n // Re-rendered by the timer below at the moment the answer stops being offered: the time is read here, on each render.\n const [ageTick, setAgeTick] = useState(0);\n const shown = offeredAt(exchange, Date.now());\n const { answerId, startOver } = shown;\n /** Until when the answer is offered, while one is. */\n const offerUntil = answerId === null ? null : exchange.offerUntil;\n\n const [phase, setPhase] = useState<Phase>(IDLE);\n const [blocked, setBlocked] = useState(false);\n const [now, setNow] = useState(() => Date.now());\n /** The box's text: the view's own, never the chat's draft. */\n const [draft, setDraft] = useState(\"\");\n /**\n * The longest question the box takes: the avatar service's limit, or the chat's own (the live catalog's) where that is\n * shorter, since the chat refuses a longer one without adding it.\n */\n const chatMaxLength = conversation?.catalog.limits.maxMessageLength;\n const askMaxLength =\n chatMaxLength !== undefined &&\n Number.isFinite(chatMaxLength) &&\n chatMaxLength >= 1\n ? Math.min(ASK_MAX_LENGTH, Math.floor(chatMaxLength))\n : ASK_MAX_LENGTH;\n /** A line the view owes the visitor: a new chat was started for the avatar, or a \"Start when ready\" was called off. */\n const [note, setNote] = useState<\"new-chat\" | \"cancelled\" | null>(null);\n /** This browser noted a live session today (read once the view is on the page). */\n const [usedToday, setUsedToday] = useState(false);\n\n /**\n * The live view is on the page: the Avatar tab is selected in an open panel, and the live avatar is on. It is also\n * hidden while `off` puts the fallback in its place (the panel's locale switching to one whose strings have not been\n * reviewed, say), which unmounts the video and audio elements a room is attached to.\n */\n const showing = active && !off;\n /**\n * Hidden only because the open panel shows its Chat tab: the pane is CSS-hidden, its video and audio elements stay\n * mounted and attached, so a session under way can keep playing (see `leave`).\n */\n const behindChat = open && !active && !off;\n\n const phaseRef = useRef<Phase>(IDLE);\n /** This render's view of everything the asynchronous steps read, so they never act on a stale one. */\n const latest = useRef({\n live,\n locale,\n base,\n headers,\n off,\n currentPath,\n showing,\n });\n latest.current = { live, locale, base, headers, off, currentPath, showing };\n const conversationRef = useRef(conversation);\n conversationRef.current = conversation;\n const waitRef = useRef<WaitRun | null>(null);\n /** A question from the box is on its way to the chat: a second press sends nothing. */\n const sendingRef = useRef(false);\n /** The box asks ordinary questions, whose answers stay text (set each render; see `textBox`). */\n const textBoxRef = useRef(false);\n /** The mic's offer from the last availability answer (Stage C): null when it carried none. */\n const [micOffer, setMicOffer] = useState<AvatarMicOffer | null>(null);\n /** Ends whatever the mic has under way and releases the microphone: every way out of the view calls it. */\n const micCancelRef = useRef<() => void>(() => undefined);\n\n const checkRef = useRef<AbortController | null>(null);\n /**\n * The locale the last availability question was asked for (or settled without asking): a later change of locale asks\n * again (see the effect on `locale`), and a view that has just asked for the new locale does not ask twice.\n */\n const askedLocale = useRef(locale);\n const startRef = useRef<StartRun | null>(null);\n const sessionRef = useRef<SessionHandle | null>(null);\n /**\n * Every answer whose session this visit has already created (or found already read): none of them is offered again.\n * A set and not the latest one: a create the visitor gave up on can answer long after they moved to another chat and\n * used its first answer, and what it reports is added to what is known, never put in its place.\n */\n const claimedRef = useRef<Set<string>>(new Set());\n\n const rootRef = useRef<HTMLDivElement>(null);\n const videoRef = useRef<HTMLVideoElement>(null);\n const audioRef = useRef<HTMLAudioElement>(null);\n const botBoxRef = useRef<HTMLDivElement>(null);\n\n const go = useCallback((next: Phase) => {\n phaseRef.current = next;\n setPhase(next);\n }, []);\n\n /**\n * Whether the visitor can see the view: it is showing, and the page is not hidden. Out of sight, a browser may hold a\n * muted video back (Chrome pauses one that is off screen or in a background tab), so its `playing` cannot be waited\n * for there (see `goLive`).\n */\n const inSight = useCallback(\n (): boolean =>\n latest.current.showing &&\n (typeof document === \"undefined\" ||\n document.visibilityState !== \"hidden\"),\n [],\n );\n\n const setMode = useCallback((next: AvatarQuestions) => {\n questionsRef.current = next;\n setQuestions(next);\n }, []);\n\n /**\n * The exchange right now, read when a step needs it rather than from the last render: the answer may have stopped\n * being offered since (it grew too old while nothing re-rendered), and the server's `questions` may have just changed.\n */\n const exchangeNow = useCallback(\n (): Exchange =>\n offeredAt(\n firstExchange(conversationRef.current?.messages, {\n any: questionsRef.current === \"any\",\n askedHere: askedHereRef.current,\n token: conversationRef.current?.getConversationToken() ?? null,\n inFlight: inFlight(conversationRef.current),\n }),\n Date.now(),\n ),\n [],\n );\n\n /** The answer offered right now (see {@link exchangeNow}). */\n const offeredNow = useCallback(\n (): string | null => exchangeNow().answerId,\n [exchangeNow],\n );\n\n /** The page the visitor is on: the host router's path, else the window's. */\n const pathNow = useCallback(\n (): string =>\n latest.current.currentPath ??\n (typeof window === \"undefined\" ? \"\" : window.location.pathname),\n [],\n );\n\n /** Back to what the offer shows for the answer offered now: its consent card, or the step without one. */\n const reoffer = useCallback(\n (offer: Offer): Phase => {\n const messageId = offeredNow();\n return messageId === null\n ? { name: \"needs-answer\", offer }\n : offering(offer, messageId, claimedRef.current);\n },\n [offeredNow],\n );\n\n /** End the session: tell the server (unless it ended it), leave the room, and show how it ended. */\n const finish = useCallback(\n (how: EndedHow, reason: AvatarEndReason | null) => {\n const handle = sessionRef.current;\n if (!handle || handle.done) return;\n handle.done = true;\n stopAttending(handle);\n sessionRef.current = null;\n if (reason !== null) {\n sendEnd({\n base: handle.base,\n headers: handle.headers,\n sessionId: handle.session.sessionId,\n secret: handle.session.endSecret,\n reason,\n });\n }\n const room = handle.joined;\n handle.joined = null;\n if (room) void room.leave().catch(() => undefined);\n setBlocked(false);\n go({ name: \"ended\", how });\n },\n [go],\n );\n\n /**\n * The avatar is on: its video plays (`playing`), or, while the view is out of sight (the Chat tab, a hidden page),\n * its video has arrived. A browser may hold a muted video back out of sight and play it only once it shows again, so\n * waiting for `playing` there would leave a session that is speaking counted as never started, and ended as failed\n * when the server closes it. Under `any`, the box notes the day's session as used (a hint for the visitor: the limits\n * are the server's).\n */\n const goLive = useCallback(() => {\n const current = phaseRef.current;\n const handle = sessionRef.current;\n if (current.name !== \"pending\" || !handle) return;\n handle.speakerArrived = true;\n if (questionsRef.current === \"any\") {\n noteUsedToday();\n setUsedToday(true);\n }\n go({ name: \"live\", session: current.session });\n }, [go]);\n\n /**\n * The attention rule, under `live.endUnattended` (without it, nothing here runs and nothing changes): a paid session\n * never outlives the visitor's attention. Out of sight (behind the Chat tab, on a hidden page) the answer under way\n * still plays to its end; past that, nothing is paid for that nobody can see or hear:\n *\n * - **Played out** (its speech ended at the source, and {@link PLAYOUT_TAIL_MS} has passed): a live session out of\n * sight ends at once, as finished. This is the lifecycle rule every later stage keeps: **an idle tail after an\n * answer runs only while the Avatar view is in sight**, and going out of sight during it ends the session then. (A\n * session still waiting for the avatar's video is the speaker wait's, {@link SPEAKER_WAIT_MS}.)\n * - **Sound held back** (`playback-blocked`'s `sound`: autoplay refused, or the room's audio context suspended), once\n * the avatar's voice has arrived: in sight, \"Tap to turn on sound\" shows and nothing ends. Out of sight nobody can\n * tap it, so after {@link UNHEARD_GRACE_MS} the session ends early: \"The live avatar stopped early.\" and \"The full\n * answer is in Chat.\". Back in sight, or the sound let through, within the grace: nothing ends.\n *\n * Both send the end with reason `user`, and once (`finish`). Run whenever what it reads changes: the view's sight, the\n * page's, the sound and the playout.\n */\n const attend = useCallback(() => {\n const handle = sessionRef.current;\n if (!handle || handle.done || latest.current.live.endUnattended !== true) {\n return;\n }\n const current = phaseRef.current.name;\n if (current !== \"pending\" && current !== \"live\") return;\n const away = !inSight();\n if (away && handle.playedOut && current === \"live\") {\n finish(\"finished\", \"user\");\n return;\n }\n if (!(away && handle.soundHeld && handle.voiceArrived)) {\n if (handle.unheard !== null) {\n clearTimeout(handle.unheard);\n handle.unheard = null;\n }\n return;\n }\n if (handle.unheard !== null) return;\n handle.unheard = setTimeout(() => {\n handle.unheard = null;\n if (\n sessionRef.current === handle &&\n !handle.done &&\n latest.current.live.endUnattended === true &&\n handle.soundHeld &&\n handle.voiceArrived &&\n !inSight()\n ) {\n finish(\"interrupted\", \"user\");\n }\n }, UNHEARD_GRACE_MS);\n }, [finish, inSight]);\n\n /** Give up on a Start still on its way to a session. A session it still creates is ended with `reason`. */\n const cancelStart = useCallback((reason: AvatarEndReason) => {\n const run = startRef.current;\n if (!run) return;\n startRef.current = null;\n run.cancelled = reason;\n run.turnstile?.cancel();\n }, []);\n\n /**\n * Go to the step an availability answer, asked in `locale`, leads to. A `refused` answer still says which questions the\n * server reads, for the box (a `limits` refusal under `any` keeps the box, asking in text).\n */\n const applyAvailability = useCallback(\n (result: AvatarAvailability, locale: ExploreLocale) => {\n const { live } = latest.current;\n setMicOffer(micOfferOf(result));\n if (result.kind === \"inert\") {\n setMode(\"suggested\");\n go(INERT);\n return;\n }\n if (result.kind === \"refused\") {\n setMode(result.questions);\n go({ name: \"refused\", reason: result.reason });\n return;\n }\n // A fresh answer from the server, a fresh look at this browser's note of the day's session.\n setUsedToday(usedTodayHere());\n // The copy for the version the server named, in the locale it was asked about (a later locale change asks\n // again: see the effect on `locale`).\n const copy = avatarConsentCopy(result.offer.consentVersion, locale);\n // A consent version this SDK has no reviewed copy for: no card, rather than words the server does not record. Nor\n // copy that describes another bot check than the one the server runs, or other questions than the ones it reads:\n // the visitor would agree to a notice that is wrong about it.\n if (\n copy === null ||\n copy.botCheck !== result.offer.botCheck ||\n copy.questions !== result.offer.questions\n ) {\n setMode(\"suggested\");\n go(INERT);\n return;\n }\n // A server that checks for bots, and no site key this page may use for its check: no start could pass it.\n if (\n result.offer.botCheck === \"turnstile\" &&\n turnstileSiteKeyOf(live) === null\n ) {\n setMode(\"suggested\");\n go(INERT);\n return;\n }\n setMode(result.offer.questions);\n go(reoffer({ ...result.offer, locale, copy }));\n },\n [go, reoffer, setMode],\n );\n\n const check = useCallback(() => {\n const { live, locale, base, headers, off } = latest.current;\n checkRef.current?.abort();\n checkRef.current = null;\n askedLocale.current = locale;\n if (off || base === null) {\n go(INERT);\n return;\n }\n const controller = new AbortController();\n checkRef.current = controller;\n go({ name: \"checking\" });\n void requestAvailability({\n base,\n headers,\n site: live.site,\n locale,\n signal: controller.signal,\n }).then((result) => {\n if (checkRef.current !== controller) return;\n checkRef.current = null;\n applyAvailability(result, locale);\n });\n }, [applyAvailability, go]);\n\n const begin = useCallback(\n (\n session: AvatarSession,\n module: AvatarLiveModule,\n offer: Offer,\n target: { base: string; headers: Readonly<Record<string, string>> },\n ) => {\n // Count down on the server's end when this browser's clock agrees with it, else on this browser's own clock.\n const received = Date.now();\n const longest = offer.maxSessionSeconds * 1000;\n const ahead = session.endsAt - received;\n const endsAt =\n ahead > 0 && ahead <= longest + CLOCK_TOLERANCE_MS\n ? session.endsAt\n : received + longest;\n sessionRef.current = {\n session,\n base: target.base,\n headers: target.headers,\n module,\n room: null,\n joined: null,\n endsAt,\n speakerArrived: false,\n voiceArrived: false,\n soundHeld: false,\n playedOut: false,\n unheard: null,\n tail: null,\n done: false,\n };\n setBlocked(false);\n setNow(received);\n go({\n name: \"pending\",\n session: {\n endsAt,\n captions: session.captions,\n excerpt: session.excerpt,\n },\n });\n },\n [go],\n );\n\n /**\n * Act on a create's answer. `givenUp` is why the view no longer waits for it, or null while it does: the visitor (or\n * the page) gave the start up while the request was on its way (`StartRun.cancelled`), or the answer came after the\n * create's deadline, when the view had already said the live avatar couldn't start. Given up on, an answer changes\n * nothing on the page but what it says about the answer having been used: a session it created is ended at once with\n * `givenUp`, and never joined.\n */\n const settle = useCallback(\n (\n result: AvatarCreateResult,\n givenUp: AvatarEndReason | null,\n context: {\n module: AvatarLiveModule;\n offer: Offer;\n messageId: string;\n base: string;\n headers: Readonly<Record<string, string>>;\n },\n ) => {\n const created =\n result.kind === \"created\"\n ? {\n sessionId: result.session.sessionId,\n secret: result.session.endSecret,\n }\n : result.kind === \"unusable\"\n ? { sessionId: result.sessionId, secret: result.endSecret }\n : null;\n // A session now exists for this answer (this create made it, or the server says an earlier one did): it is used.\n const claimed =\n created !== null ||\n (result.kind === \"refused\" && result.reason === \"answer_claimed\");\n if (claimed) claimedRef.current.add(context.messageId);\n if (givenUp !== null) {\n // Given up while the request was on its way, or answered past its deadline: a session it created is ended at\n // once.\n if (created !== null) {\n sendEnd({\n base: context.base,\n headers: context.headers,\n sessionId: created.sessionId,\n secret: created.secret,\n reason: givenUp,\n });\n }\n // The visitor may be back on the consent card for this very answer by now (they left during the create and came\n // back before it answered): it has been read, so the card gives way to saying so rather than offering it again.\n const shown = phaseRef.current;\n if (\n claimed &&\n shown.name === \"consent\" &&\n shown.messageId === context.messageId\n ) {\n go({ name: \"refused\", reason: \"answer_claimed\" });\n }\n return;\n }\n switch (result.kind) {\n case \"created\":\n begin(result.session, context.module, context.offer, context);\n return;\n case \"unusable\":\n sendEnd({\n base: context.base,\n headers: context.headers,\n sessionId: result.sessionId,\n secret: result.endSecret,\n reason: \"client_error\",\n });\n go({ name: \"ended\", how: \"failed\" });\n return;\n case \"refused\":\n go({ name: \"refused\", reason: result.reason });\n return;\n case \"consent\":\n // The consent version moved on: ask again, and show the consent that is current now.\n check();\n return;\n case \"inert\":\n go(INERT);\n return;\n case \"failed\":\n go({ name: \"ended\", how: \"failed\" });\n return;\n }\n },\n [begin, check, go],\n );\n\n /**\n * From the visitor's consent to a session for `messageId`: Start on the card, or a \"Start when ready\" whose answer is\n * now ready and checked (with the room module it has been loading meanwhile, `preloaded`). One create request, never\n * sent again by itself: a failed create ends as failed, and only another tap can start again.\n */\n const launch = useCallback(\n (\n offer: Offer,\n messageId: string,\n preloaded: Promise<AvatarLiveModule> | null,\n ) => {\n const { live, base, headers } = latest.current;\n if (base === null) return;\n const exchangeAtStart = exchangeNow();\n // The answer has grown too old for the service since the card was shown (a timer that has not run yet: a throttled\n // background tab, say), or the conversation has moved on: no request the service would refuse.\n if (exchangeAtStart.answerId !== messageId) {\n go(reoffer(offer));\n return;\n }\n // Already read in this visit (a \"Start when ready\" whose answer a session elsewhere in this visit used): say so.\n if (claimedRef.current.has(messageId)) {\n go({ name: \"refused\", reason: \"answer_claimed\" });\n return;\n }\n // When the service will refuse this answer as too old: the module and a bot check can take a while, and a create\n // that starts after this is not sent.\n const refusedFrom =\n exchangeAtStart.offerUntil - ANSWER_OFFER_MS + SERVICE_MAX_AGE_MS;\n // The key for the bot check, where the server runs one; null where it runs none.\n const siteKey =\n offer.botCheck === \"turnstile\" ? turnstileSiteKeyOf(live) : null;\n // A bot check with no key this page may use, or with no WebCrypto (a page that is not a secure context) to bind it\n // to a create request: no live avatar can start here. Nothing is loaded for a start that cannot happen (no module,\n // no bot-check script), and the tab stays as it was.\n if (\n offer.botCheck === \"turnstile\" &&\n (siteKey === null || !canBindBotCheck())\n ) {\n go(INERT);\n return;\n }\n // The create request's values, read once, here. A bot check is bound to exactly these (`avatarBotBinding`, before its\n // widget is rendered), so the request that follows it carries this same body and reads nothing again.\n const conversationToken =\n conversationRef.current?.getConversationToken() ?? null;\n const idempotencyKey = newIdempotencyKey();\n if (\n conversationToken === null ||\n !isAvatarConversationToken(conversationToken) ||\n idempotencyKey === null\n ) {\n // Nothing to create a session for: no module, no bot check.\n go({ name: \"ended\", how: \"failed\" });\n return;\n }\n const body: AvatarCreateBody = {\n site: live.site,\n locale: offer.locale,\n conversationToken,\n messageId,\n consentVersion: offer.consentVersion,\n manifestVersion: live.manifestVersion,\n };\n const run: StartRun = { cancelled: null, turnstile: null };\n startRef.current = run;\n // Only now that the visitor has agreed: the live module (already loading, for a \"Start when ready\"), and the bot\n // check where the server runs one. Where it runs none, there is no Cloudflare script, no widget and no token: the\n // module loads and the request follows.\n const module = preloaded ?? loadModule(live.load);\n let turnstile: TurnstileRun | null = null;\n if (siteKey === null) {\n go({ name: \"creating\" });\n } else {\n go({ name: \"bot-check\", offer, messageId });\n turnstile = runTurnstile(\n botBoxRef.current,\n siteKey,\n \"avatar_start\",\n avatarBotBinding(body),\n );\n run.turnstile = turnstile;\n }\n void (async () => {\n let loaded: AvatarLiveModule;\n let botToken: string | undefined;\n try {\n [loaded, botToken] = await Promise.all([module, turnstile?.token]);\n } catch {\n turnstile?.cancel();\n if (run.cancelled === null) {\n startRef.current = null;\n go(INERT);\n }\n return;\n }\n // The widget has done its work.\n turnstile?.cancel();\n if (run.cancelled !== null) return;\n // The answer grew too old for the service while the module or the bot check took their time: nothing is created,\n // and the view says to start a new chat (it reads the answer as too old now).\n if (!(Date.now() < refusedFrom)) {\n startRef.current = null;\n go({ name: \"needs-answer\", offer });\n return;\n }\n if (turnstile !== null) go({ name: \"creating\" });\n const context = { module: loaded, offer, messageId, base, headers };\n // Sent: from here an answer that never comes is `failed` (the server may have made the session), and the wait\n // ends by the create's deadline whatever the network does (see `requestCreate`).\n const result = await requestCreate({\n base,\n headers,\n idempotencyKey,\n botToken,\n body,\n // An answer past the deadline, after the view has said the live avatar couldn't start: a session it made is\n // ended at once with its own secret, and never joined. The reason is the visitor's own where they gave the\n // start up first, else `client_error`. It reads `run` and never writes it, so the deadline's `failed` below is\n // shown whichever of the two is handled first.\n onLate: (late) =>\n settle(late, run.cancelled ?? \"client_error\", context),\n });\n if (startRef.current === run) startRef.current = null;\n settle(result, run.cancelled, context);\n })();\n },\n [exchangeNow, go, reoffer, settle],\n );\n\n /** Start, on the consent card. Under `any`, the tap also lets the page play the avatar's sound later. */\n const start = useCallback(() => {\n const current = phaseRef.current;\n if (current.name !== \"consent\") return;\n if (current.offer.questions === \"any\") unlockSound(audioRef.current);\n launch(current.offer, current.messageId, null);\n }, [launch]);\n\n /**\n * Call off a \"Start when ready\": nothing is created, and the view goes back to the answer being written (or to what\n * the conversation now is). `told`: the visitor did not cancel it themselves, so the view says it did not start.\n */\n const cancelWaiting = useCallback(\n (told: boolean) => {\n const wait = waitRef.current;\n waitRef.current = null;\n wait?.check?.abort();\n const current = phaseRef.current;\n if (current.name !== \"waiting\") return;\n if (told) setNote(\"cancelled\");\n go({ name: \"needs-answer\", offer: current.offer });\n },\n [go],\n );\n\n /** Whether what a \"Start when ready\" was bound to still holds, for the exchange as it is now. */\n const bindingHolds = useCallback(\n (bound: WaitRun[\"bound\"], exchange: Exchange): boolean => {\n const { live, locale } = latest.current;\n return (\n conversationRef.current?.getConversationToken() === bound.token &&\n exchange.question?.id === bound.questionId &&\n live.site === bound.site &&\n locale === bound.locale &&\n pathNow() === bound.path\n );\n },\n [pathNow],\n );\n\n /**\n * \"Start when ready\", on the card shown while the answer is written: the visitor's consent for this conversation's\n * first answer, once it is ready (see {@link WaitRun}). Pressed only for a question this tab asked as the first of a\n * new chat, once the server has taken it.\n */\n const startWhenReady = useCallback(() => {\n const current = phaseRef.current;\n if (current.name !== \"needs-answer\") return;\n const { live, locale } = latest.current;\n const exchange = exchangeNow();\n const token = conversationRef.current?.getConversationToken() ?? null;\n if (\n exchange.kind !== \"asking\" ||\n !exchange.askedHere ||\n exchange.question === null ||\n exchange.pendingAnswerId === null ||\n token === null ||\n !isAvatarConversationToken(token)\n ) {\n return;\n }\n unlockSound(audioRef.current);\n const module = loadModule(live.load);\n // Read when the answer is ready; a failure then is the start's. Until then, nothing is left unhandled.\n module.catch(() => undefined);\n waitRef.current = {\n bound: {\n token,\n questionId: exchange.question.id,\n answerId: exchange.pendingAnswerId,\n site: live.site,\n locale,\n path: pathNow(),\n consentVersion: current.offer.consentVersion,\n botCheck: current.offer.botCheck,\n },\n module,\n check: null,\n };\n setNote(null);\n go({ name: \"waiting\", offer: current.offer });\n }, [exchangeNow, go, pathNow]);\n\n /**\n * The answer a \"Start when ready\" waited for is ready: ask availability again (no cache) and check the answer again,\n * and create only if nothing differs. Anything that does (another consent version or bot check, a refusal, the answer\n * or the conversation) shows what is offered now instead: the card again, or why there is none.\n */\n const confirm = useCallback(\n (offer: Offer, wait: WaitRun) => {\n const { live, locale, base, headers } = latest.current;\n if (base === null) {\n cancelWaiting(true);\n return;\n }\n const controller = new AbortController();\n wait.check = controller;\n void requestAvailability({\n base,\n headers,\n site: live.site,\n locale,\n signal: controller.signal,\n }).then((result) => {\n if (waitRef.current !== wait || phaseRef.current.name !== \"waiting\") {\n return;\n }\n waitRef.current = null;\n // (A change of locale while this was asked has already called the start off, dropping this answer: see the\n // effect on `locale`. So it is the answer for the locale the panel is in.)\n const exchange = exchangeNow();\n const same =\n result.kind === \"available\" &&\n result.offer.consentVersion === wait.bound.consentVersion &&\n result.offer.botCheck === wait.bound.botCheck &&\n result.offer.questions === \"any\" &&\n exchange.kind === \"answer\" &&\n exchange.answerId === wait.bound.answerId &&\n bindingHolds(wait.bound, exchange);\n if (!same || result.kind !== \"available\") {\n applyAvailability(result, locale);\n return;\n }\n // The offer as it is now (the same version, bot check and questions; the session's length may have moved).\n launch({ ...offer, ...result.offer }, wait.bound.answerId, wait.module);\n });\n },\n [applyAvailability, bindingHolds, cancelWaiting, exchangeNow, launch],\n );\n\n /** The visitor's Stop, at any step from Start on (and Cancel, for a \"Start when ready\"). */\n const stop = useCallback(() => {\n micCancelRef.current();\n const current = phaseRef.current;\n if (current.name === \"waiting\") {\n cancelWaiting(false);\n return;\n }\n if (current.name === \"bot-check\") {\n // Nothing was created: back to the consent card, if its answer is still offered.\n cancelStart(\"user\");\n go(reoffer(current.offer));\n return;\n }\n if (current.name === \"creating\") {\n cancelStart(\"user\");\n go({ name: \"ended\", how: \"stopped\" });\n return;\n }\n if (current.name === \"pending\" || current.name === \"live\") {\n finish(\"stopped\", \"user\");\n }\n }, [cancelStart, cancelWaiting, finish, go, reoffer]);\n\n /**\n * The view going out of the visitor's sight, by what took it away:\n *\n * - `user`: the panel closing, or the live avatar going off (the fallback takes the view's place, unmounting the\n * video and audio a room is attached to, and Stop with them). Everything under way ends, a session with `user`.\n * - `chat`: the open panel showing its Chat tab instead. Before the create is sent nothing paid exists, so it is\n * called off as `user` would (C3): a check is dropped (opening the view asks again), a \"Start when ready\" and a bot\n * check are called off with nothing created. From the create on (`creating`, `pending`, `live`) nothing ends: the\n * pane is only hidden, the room's video and audio stay attached, and the avatar speaks to its planned end.\n * - `hidden`: the page hidden (another browser tab, another app). A \"Start when ready\" is called off and a bot check\n * goes back to the consent card, so the view is as the visitor left it when they come back; a check is kept. From\n * the create on nothing ends, as for `chat`: the server ends the session at its planned end, so a hidden page adds\n * no paid time.\n * - `page_hide`: the page being left (`pagehide`). Everything ends, a session with `page_hide`; a check is kept.\n *\n * Out of sight with a session whose video has already arrived, it is counted as live (see `goLive`). What a session\n * kept out of sight may still end on is the attention rule's (`attend`), under `live.endUnattended`.\n *\n * In every case, first, the mic (Stage C) stops whatever it has under way and releases the microphone: it never\n * records out of sight.\n */\n const leave = useCallback(\n (event: \"user\" | \"chat\" | \"hidden\" | \"page_hide\") => {\n micCancelRef.current();\n const current = phaseRef.current;\n const reason: AvatarEndReason =\n event === \"user\" || event === \"chat\" ? \"user\" : \"page_hide\";\n const how: EndedHow = reason === \"user\" ? \"stopped\" : \"interrupted\";\n /** Once the create has been sent, only the panel closing, the live avatar going off and leaving the page end it. */\n const keepsSession = event === \"chat\" || event === \"hidden\";\n switch (current.name) {\n case \"checking\": {\n if (reason !== \"user\") return;\n const controller = checkRef.current;\n checkRef.current = null;\n controller?.abort();\n go(IDLE);\n return;\n }\n case \"waiting\":\n // A \"Start when ready\" is for this view as the visitor left it: called off, with nothing created.\n cancelWaiting(true);\n return;\n case \"bot-check\":\n cancelStart(reason);\n go(reason === \"user\" ? IDLE : reoffer(current.offer));\n return;\n case \"creating\":\n if (keepsSession) return;\n cancelStart(reason);\n go({ name: \"ended\", how });\n return;\n case \"pending\":\n case \"live\":\n if (keepsSession) {\n if (\n current.name === \"pending\" &&\n sessionRef.current?.speakerArrived\n ) {\n goLive();\n }\n return;\n }\n finish(how, reason);\n return;\n default:\n return;\n }\n },\n [cancelStart, cancelWaiting, finish, go, goLive, reoffer],\n );\n\n // The Avatar view showing, and hiding. Opening it asks again, except where this visit has already used the answer,\n // and except during a session, which shows as it is, counting down to its end.\n //\n // Hidden behind the Chat tab, a session under way keeps playing (`leave(\"chat\")`). Anything else that hides the view\n // (the panel closing, the live avatar going off) ends whatever is under way (`leave(\"user\")`): a bot check is called\n // off, a create in flight is ended once it answers, a session is ended and its room left. Coming back asks again.\n useEffect(() => {\n if (!showing) {\n leave(behindChat ? \"chat\" : \"user\");\n return;\n }\n const current = phaseRef.current;\n if (\n current.name === \"creating\" ||\n current.name === \"pending\" ||\n current.name === \"live\"\n ) {\n // Back during a session, after the Chat tab: nothing is asked again and nothing reset. The countdown is to the\n // session's end as `begin` set it, and is brought up to date at once rather than at its next tick.\n setNow(Date.now());\n return;\n }\n const offered = offeredNow();\n const used = offered !== null && claimedRef.current.has(offered);\n if (current.name === \"ended\" && used) return;\n if (\n current.name === \"refused\" &&\n current.reason === \"answer_claimed\" &&\n used\n ) {\n return;\n }\n if (\n current.name === \"idle\" ||\n current.name === \"inert\" ||\n current.name === \"refused\" ||\n current.name === \"needs-answer\" ||\n current.name === \"consent\" ||\n current.name === \"declined\" ||\n current.name === \"ended\" ||\n // Asking, with nothing actually asking: React's strict mode unmounts and mounts a component again with the state it\n // left, and the unmount in between dropped the question. (This view mounts already showing, the first time the\n // Avatar view opens.)\n (current.name === \"checking\" && checkRef.current === null)\n ) {\n check();\n }\n }, [showing, behindChat, check, leave, offeredNow]);\n\n // The attention rule (`attend`), each time the view comes into sight or goes out of it, once the effect above has\n // dealt with the move (the page's own sight is the visibility handler's, below).\n useEffect(() => {\n attend();\n }, [showing, attend]);\n\n // The panel's locale changing before Start: an availability answer, and the consent copy chosen for it, belong to the\n // locale they were asked about, so the view asks again (or, hidden, starts over when it next opens). A session already\n // under way keeps its own. A \"Start when ready\" is bound to its locale: it is called off, with nothing created (and\n // the availability question it may be asking again for the old locale is dropped with it), and the view asks again\n // for the new one.\n useEffect(() => {\n if (askedLocale.current === locale) return;\n askedLocale.current = locale;\n if (phaseRef.current.name === \"waiting\") cancelWaiting(true);\n const current = phaseRef.current.name;\n if (\n current !== \"checking\" &&\n current !== \"needs-answer\" &&\n current !== \"consent\" &&\n current !== \"declined\" &&\n current !== \"refused\" &&\n current !== \"inert\"\n ) {\n return;\n }\n if (active) {\n check();\n } else {\n checkRef.current?.abort();\n checkRef.current = null;\n go(IDLE);\n }\n }, [active, cancelWaiting, check, go, locale]);\n\n // The first answer arriving (it may complete while the Avatar view shows), or the conversation starting over.\n const kind = shown.kind;\n useEffect(() => {\n const current = phaseRef.current;\n if (current.name === \"needs-answer\" && answerId !== null) {\n go({ name: \"consent\", offer: current.offer, messageId: answerId });\n } else if (current.name === \"consent\" && current.messageId !== answerId) {\n go(\n answerId === null\n ? { name: \"needs-answer\", offer: current.offer }\n : { ...current, messageId: answerId },\n );\n } else if (current.name === \"declined\" && answerId === null) {\n // Not now, and then the conversation moved on (a new chat, say): nothing is declined any more.\n if (kind !== \"asking\") go({ name: \"needs-answer\", offer: current.offer });\n }\n }, [answerId, kind, go]);\n\n // A \"Start when ready\" while its answer is written: on every render, whatever changed (the conversation, its answer,\n // the page, the locale). It holds while the answer it is bound to is on its way; once that answer is ready and passes\n // the checks this browser can make, it is confirmed (`confirm`); anything else calls it off, with nothing created. A\n // failed or unreadable answer then says why itself; anything else says the start was called off.\n useEffect(() => {\n const current = phaseRef.current;\n const wait = waitRef.current;\n if (current.name !== \"waiting\" || wait === null || wait.check !== null) {\n return;\n }\n const now = exchangeNow();\n const holds = bindingHolds(wait.bound, now);\n if (\n holds &&\n now.kind === \"asking\" &&\n now.pendingAnswerId === wait.bound.answerId\n ) {\n return;\n }\n if (\n !holds ||\n now.kind !== \"answer\" ||\n now.answerId !== wait.bound.answerId\n ) {\n cancelWaiting(now.kind !== \"failed\" && now.kind !== \"text-only\");\n return;\n }\n confirm(current.offer, wait);\n });\n\n // A question asked here that Chat's Retry sent again is still the one asked here: the retry's question replaces it\n // (first the one shown while it is on its way, then the server's own, with the token the server may have just\n // minted; each names every id the question had). Declared before the two effects below, which run in the same commit\n // as the change it follows: the record moves to the new question (and its token) before they compare it.\n const resent = conversation?.resent ?? null;\n useEffect(() => {\n const asked = askedHereRef.current;\n if (\n resent === null ||\n asked === null ||\n !resent.replacedMessageIds.includes(asked.messageId)\n ) {\n return;\n }\n setAskedHere({\n messageId: resent.sent.userMessageId,\n token: resent.sent.conversationToken,\n });\n }, [resent, setAskedHere]);\n\n // The question this tab asked is the first of its chat only while that chat lasts: a conversation that empties (New\n // chat, in either tab) has no question asked here.\n const empty = (conversation?.messages.length ?? 0) === 0;\n useEffect(() => {\n if (empty) setAskedHere(null);\n }, [empty, setAskedHere]);\n // And it belongs to the conversation its send ended in, and no other: another token (a conversation opened from\n // History, say, whatever its first question says) ends it.\n useEffect(() => {\n const asked = askedHereRef.current;\n if (asked !== null && asked.token !== token) setAskedHere(null);\n }, [token, setAskedHere]);\n\n // This browser's note of a session today, read each time the view shows (never while rendering on a server), so a\n // page left open past midnight (UTC) has the new day's session.\n useEffect(() => {\n if (showing) setUsedToday(usedTodayHere());\n }, [showing]);\n\n // The answer stops being offered at `offerUntil`: one timer for that moment, set again for a new answer, and cleared\n // when the answer changes or the view goes. It re-renders the view, which then reads the answer as too old (and the\n // effect above moves a consent card to the start-over step). A timer that ran early, or a deadline past the longest\n // delay a timer keeps, is simply set again (`ageTick`).\n useEffect(() => {\n if (offerUntil === null) return;\n const timer = setTimeout(\n () => setAgeTick((tick) => tick + 1),\n Math.min(MAX_TIMER_MS, Math.max(0, offerUntil - Date.now())),\n );\n return () => clearTimeout(timer);\n }, [offerUntil, ageTick]);\n\n /** Start over: the chat's own New chat (the conversation's `reset`), then the Chat tab and its suggested questions. */\n const startNewChat = useCallback(() => {\n conversationRef.current?.reset();\n onContinueInChat();\n }, [onContinueInChat]);\n\n const onRoomEvent = useCallback(\n (handle: SessionHandle, event: ReceiveOnlyEvent) => {\n if (handle.done || sessionRef.current !== handle) return;\n const wasLive = phaseRef.current.name === \"live\";\n switch (event.type) {\n case \"speaker-track\":\n if (event.kind !== \"video\") {\n handle.voiceArrived = true;\n attend();\n return;\n }\n handle.speakerArrived = true;\n // Out of sight, the video's own `playing` may not come until the view shows again.\n if (!inSight()) goLive();\n return;\n case \"playback-blocked\":\n setBlocked(event.blocked);\n handle.soundHeld = event.sound ?? event.blocked;\n attend();\n return;\n case \"speech-ended\":\n // Under `endUnattended` only: the answer counts as played out once the worker's lag has had its time.\n if (\n latest.current.live.endUnattended !== true ||\n handle.tail !== null ||\n handle.playedOut\n ) {\n return;\n }\n handle.tail = setTimeout(() => {\n handle.tail = null;\n if (sessionRef.current !== handle || handle.done) return;\n handle.playedOut = true;\n attend();\n }, PLAYOUT_TAIL_MS);\n return;\n case \"speaker-left\":\n finish(\n wasLive ? \"finished\" : \"failed\",\n wasLive ? null : \"client_error\",\n );\n return;\n case \"disconnected\":\n if (event.byServer) finish(wasLive ? \"finished\" : \"failed\", null);\n else finish(wasLive ? \"interrupted\" : \"failed\", \"client_error\");\n return;\n }\n },\n [attend, finish, goLive, inSight],\n );\n\n // A created session: join its room once the video and audio elements are on the page.\n useEffect(() => {\n if (phase.name !== \"pending\") return;\n const handle = sessionRef.current;\n if (!handle || handle.room !== null || handle.done) return;\n const video = videoRef.current;\n const audio = audioRef.current;\n if (!video || !audio) {\n finish(\"failed\", \"client_error\");\n return;\n }\n let joining: Promise<ReceiveOnlySession>;\n try {\n joining = handle.module.joinReceiveOnly({\n url: handle.session.join.livekitUrl,\n token: handle.session.join.participantToken,\n workerIdentity: handle.session.join.workerIdentity,\n video,\n audio,\n onEvent: (event) => onRoomEvent(handle, event),\n });\n } catch (error) {\n joining = Promise.reject(error);\n }\n handle.room = joining.then(\n (room) => {\n if (handle.done) {\n void room.leave().catch(() => undefined);\n return null;\n }\n handle.joined = room;\n return room;\n },\n () => {\n if (!handle.done) finish(\"failed\", \"client_error\");\n return null;\n },\n );\n }, [phase.name, finish, onRoomEvent]);\n\n // While a session lasts: give up on a speaker who never comes, and leave a room still open after the session's end.\n useEffect(() => {\n if (phase.name !== \"pending\" && phase.name !== \"live\") return;\n const handle = sessionRef.current;\n if (!handle) return;\n const timers: Array<ReturnType<typeof setTimeout>> = [];\n if (phase.name === \"pending\") {\n timers.push(\n setTimeout(() => {\n if (sessionRef.current === handle && !handle.speakerArrived) {\n finish(\"failed\", \"client_error\");\n }\n }, SPEAKER_WAIT_MS),\n );\n }\n timers.push(\n setTimeout(\n () => {\n if (sessionRef.current !== handle) return;\n finish(\n phaseRef.current.name === \"live\" ? \"finished\" : \"failed\",\n \"client_error\",\n );\n },\n Math.max(0, handle.endsAt + END_GRACE_MS - Date.now()),\n ),\n );\n return () => timers.forEach((timer) => clearTimeout(timer));\n }, [phase.name, finish]);\n\n // The countdown: once a second while a session lasts.\n const ticking = phase.name === \"pending\" || phase.name === \"live\";\n useEffect(() => {\n if (!ticking) return;\n const timer = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(timer);\n }, [ticking]);\n\n // The avatar's voice is the page's from the create until the session ends: the panel is told its status line then,\n // and null otherwise (and when the view goes), and holds Chat's own read-aloud and dictation meanwhile.\n const voiceLine =\n phase.name === \"live\"\n ? S.speaking\n : phase.name === \"creating\" || phase.name === \"pending\"\n ? S.connecting\n : null;\n const onVoiceHoldRef = useRef(onVoiceHold);\n onVoiceHoldRef.current = onVoiceHold;\n useEffect(() => {\n onVoiceHoldRef.current?.(voiceLine);\n }, [voiceLine]);\n useEffect(() => () => onVoiceHoldRef.current?.(null), []);\n\n // Leaving the page ends a session. Hiding it (another browser tab, another app) calls off only what has not been sent\n // yet: a session keeps playing to its planned end, which the server keeps either way (see `leave`), unless the\n // attention rule ends it sooner (`attend`). The page showing again brings the countdown up to date at once: a hidden\n // page's timers may have been held back.\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const onPageHide = () => leave(\"page_hide\");\n const onVisibility = () => {\n if (document.visibilityState === \"hidden\") {\n leave(\"hidden\");\n attend();\n return;\n }\n const current = phaseRef.current.name;\n if (current === \"pending\" || current === \"live\") setNow(Date.now());\n attend();\n };\n window.addEventListener(\"pagehide\", onPageHide);\n document.addEventListener(\"visibilitychange\", onVisibility);\n return () => {\n window.removeEventListener(\"pagehide\", onPageHide);\n document.removeEventListener(\"visibilitychange\", onVisibility);\n };\n }, [attend, leave]);\n\n // Unmounted with something under way: end it, as closing the panel would.\n useEffect(\n () => () => {\n const controller = checkRef.current;\n checkRef.current = null;\n controller?.abort();\n const run = startRef.current;\n startRef.current = null;\n if (run) {\n run.cancelled = \"user\";\n run.turnstile?.cancel();\n }\n const wait = waitRef.current;\n waitRef.current = null;\n wait?.check?.abort();\n const handle = sessionRef.current;\n sessionRef.current = null;\n if (handle && !handle.done) {\n handle.done = true;\n stopAttending(handle);\n sendEnd({\n base: handle.base,\n headers: handle.headers,\n sessionId: handle.session.sessionId,\n secret: handle.session.endSecret,\n reason: \"user\",\n });\n if (handle.joined) void handle.joined.leave().catch(() => undefined);\n }\n },\n [],\n );\n\n const any = questions === \"any\";\n /**\n * Under `any`, the tab asks in text: the day's session is used (this browser's note of it, which a session that\n * played and has now ended leaves too), or the server says its limit is reached. The box then sends ordinary\n * questions, without `surface`, and their answers show here as text (after a session, under how it ended).\n */\n const textMode =\n any &&\n ((usedToday &&\n (phase.name === \"needs-answer\" ||\n phase.name === \"consent\" ||\n phase.name === \"declined\" ||\n phase.name === \"ended\")) ||\n (phase.name === \"refused\" && phase.reason === \"limits\"));\n // The box asks in text exactly where the tab shows the answers as text (see `ask`).\n textBoxRef.current = textMode;\n /** Under `any`: which of the Avatar tab's states shows, on the view's root (for tests and a site's own checks). */\n const askState = !any\n ? undefined\n : textMode\n ? \"text\"\n : phase.name === \"needs-answer\"\n ? kind === \"empty\"\n ? \"ready\"\n : kind\n : phase.name;\n /** Why the box's Send cannot be pressed now (an answer on its way, a chat that cannot ask), or null when it can. */\n const askReason = inFlight(conversation)\n ? S.askBusy\n : conversation?.canSend\n ? null\n : S.askUnavailable;\n\n /**\n * The mic's offer again, for a press whose offer has expired or was refused (Stage C): availability asked again, its\n * new offer held. An answer without one leaves the held one as it was, and the press says the mic is not available.\n * No answer at all (the network, its deadline) rejects: the press says to try again, and the mic stays.\n */\n const refreshMicOffer =\n useCallback(async (): Promise<AvatarMicOffer | null> => {\n const { live, locale, base, headers } = latest.current;\n if (base === null) return null;\n const next = micOfferOf(\n await requestAvailabilityAnswer({\n base,\n headers,\n site: live.site,\n locale,\n }),\n );\n if (next !== null) setMicOffer(next);\n return next;\n }, []);\n\n /** A press's final text: into the box, after what the visitor typed, and the box focused to correct it and Send. */\n const onMicText = useCallback(\n (text: string) => {\n setDraft((current) => withHeardText(current, text, askMaxLength));\n if (touchFirst) return;\n rootRef.current\n ?.querySelector<HTMLTextAreaElement>(\n '[data-boff-explore=\"avatar-live-ask-input\"]',\n )\n ?.focus();\n },\n [askMaxLength, touchFirst],\n );\n\n // The Avatar tab's mic (Stage C): offered where the site opts in, the server's last availability answer carried an\n // offer, and the box takes a question now.\n const mic = useAvatarMic({\n enabled:\n live.mic === true &&\n micOffer !== null &&\n !off &&\n acceptsQuestion({\n any,\n phase: phase.name,\n kind,\n textMode,\n reason: askReason,\n }),\n locale,\n base,\n offer: micOffer,\n refreshOffer: refreshMicOffer,\n onText: onMicText,\n });\n micCancelRef.current = mic.cancel;\n\n /**\n * Not now. Under `any` the visitor stays on the tab, told the answer is in Chat (the card is offered again when the tab\n * next opens, while the answer is fresh); otherwise, as before, back to the Chat tab.\n */\n const notNow = useCallback(() => {\n const current = phaseRef.current;\n if (\n (current.name === \"consent\" || current.name === \"needs-answer\") &&\n current.offer.questions === \"any\"\n ) {\n go({ name: \"declined\", offer: current.offer });\n return;\n }\n onContinueInChat();\n }, [go, onContinueInChat]);\n\n /**\n * Ask `text` from the box (or a chip). For the avatar, it is the first question of a new chat, sent with `surface:\n * \"AVATAR\"`, so its answer is the one the card offers. It is remembered as asked here only once the chat's `send` says\n * it added it, bound to the USER message it added and the conversation it ended in; a send that added nothing (too\n * long a question, another question already on its way, a disabled chat) leaves nothing remembered, so the same words\n * asked later in Chat never get the card, and puts the question back in the box. In text (see `textMode`), an ordinary question, without `surface`, into the\n * chat as it is. Never resets the conversation: a chat that is not new is started over only by the visitor's own \"New\n * chat for the avatar\". One question at a time: a second press while the first is on its way sends nothing.\n */\n const ask = useCallback(\n (text: string) => {\n const conversation = conversationRef.current;\n const question = text.trim();\n if (conversation === null || question === \"\" || sendingRef.current) {\n return;\n }\n const spoken = !textBoxRef.current;\n if (spoken && conversation.messages.length > 0) return;\n sendingRef.current = true;\n // Whatever was remembered goes: only this ask's own send can put a question back.\n setAskedHere(null);\n const seq = askSeqRef.current;\n setNote(null);\n setDraft(\"\");\n void conversation\n .send(question, [], spoken ? { surface: \"AVATAR\" } : {})\n .then((added) => {\n // The chat added nothing (over its own length or turn limit, another question on its way, a disabled chat):\n // the question goes back into the box, unless the visitor has typed something else since, so it is never\n // silently lost.\n if (added === null) {\n setDraft((current) => (current === \"\" ? question : current));\n }\n if (\n !spoken ||\n added === null ||\n askSeqRef.current !== seq ||\n added.conversationToken !==\n (conversationRef.current?.getConversationToken() ?? null)\n ) {\n return;\n }\n setAskedHere({\n messageId: added.userMessageId,\n token: added.conversationToken,\n });\n })\n .finally(() => {\n sendingRef.current = false;\n });\n },\n [setAskedHere],\n );\n\n /**\n * \"New chat for the avatar\": the visitor's own start over, where this conversation can no longer be read. The chat's\n * New chat (the conversation's `reset`, so the chat being left stays in History), staying on the Avatar tab, whose\n * box then asks for the avatar. A failed question goes back into the box, if the box is empty.\n */\n const newChatForAvatar = useCallback(() => {\n const conversation = conversationRef.current;\n if (conversation === null) return;\n const now = exchangeNow();\n const failedQuestion =\n now.kind === \"failed\" ? (now.question?.content ?? null) : null;\n conversation.reset();\n setAskedHere(null);\n setNote(\"new-chat\");\n if (failedQuestion !== null) {\n setDraft((current) => (current === \"\" ? failedQuestion : current));\n }\n const current = phaseRef.current;\n if (\n current.name === \"needs-answer\" ||\n current.name === \"consent\" ||\n current.name === \"declined\"\n ) {\n go({ name: \"needs-answer\", offer: current.offer });\n } else {\n // From a refusal or a session's end: ask again whether the avatar is offered, for the new chat.\n check();\n }\n }, [check, exchangeNow, go, setAskedHere]);\n\n // Each step's own control takes focus when the one the visitor was on has gone (Start, once pressed, say): focus\n // left on the page's body would also take Escape out of the panel. \"Tap to turn on sound\" is one of those controls:\n // it goes the moment playback resumes (`blocked` clears), so focus moves on to Stop rather than falling to the body.\n useEffect(() => {\n if (!active) return;\n const focused = document.activeElement;\n if (focused && focused !== document.body && focused.isConnected) return;\n rootRef.current?.querySelector<HTMLElement>(PRIMARY)?.focus();\n // (The card's arrival while the answer is written is a step of its own here: its Start when ready takes focus from\n // the box the question was asked from, which has gone.)\n }, [active, phase.name, askState, shown.pendingAnswerId, blocked]);\n\n // The avatar's video plays: the session is live (`goLive`).\n const onPlaying = goLive;\n\n const enablePlayback = useCallback(() => {\n // Called straight from the tap: browsers allow sound only from inside the visitor's gesture.\n void sessionRef.current?.joined?.enablePlayback().catch(() => undefined);\n }, []);\n\n if (off || phase.name === \"inert\") {\n return (\n // `display: contents`: the earlier Avatar view's picture, line and button lay out in the pane exactly as before.\n <div\n ref={rootRef}\n style={{ display: \"contents\" }}\n data-boff-explore=\"avatar-live\"\n data-phase={off ? \"off\" : \"inert\"}\n >\n {fallback}\n </div>\n );\n }\n\n const primaryButton =\n \"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 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 motion-reduce:transition-none\";\n const secondaryButton =\n \"inline-flex items-center justify-center rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background motion-reduce:transition-none\";\n const stillPicture = (small: boolean) => (\n <img\n src={still.src}\n alt={still.alt}\n decoding=\"async\"\n width={small ? 64 : 128}\n height={small ? 64 : 128}\n className={cn(\n \"shrink-0 rounded-full border border-border object-cover shadow-sm\",\n small\n ? \"h-16 w-16\"\n : any\n ? \"h-[min(12rem,32dvh)] w-[min(12rem,32dvh)]\"\n : \"h-32 w-32\",\n )}\n />\n );\n const continueButton = (\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-continue\"\n className={primaryButton}\n onClick={onContinueInChat}\n >\n {continueInChat}\n </button>\n );\n /** Where this conversation can never be read: New chat first, and Continue in Chat beside it. */\n const startOverActions = (\n <div className=\"flex flex-wrap items-center justify-center gap-2\">\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-new-chat\"\n className={primaryButton}\n onClick={startNewChat}\n >\n {newChat}\n </button>\n <button\n type=\"button\"\n data-boff-explore=\"avatar-live-continue\"\n className={secondaryButton}\n onClick={onContinueInChat}\n >\n {continueInChat}\n </button>\n </div>\n );\n const stopButton = (\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-stop\"\n className={secondaryButton}\n onClick={stop}\n >\n {S.stop}\n </button>\n );\n /** Under `any`: to the Chat tab, where the answer and its sources are. */\n const readInChatButton = (primary: boolean) => (\n <button\n type=\"button\"\n data-avatar-primary={primary ? \"\" : undefined}\n data-boff-explore=\"avatar-live-read-in-chat\"\n className={primary ? primaryButton : secondaryButton}\n onClick={onContinueInChat}\n >\n {S.readInChat}\n </button>\n );\n /** The consent card: exactly its four lines and the privacy link (the notice's digest is taken over them). */\n const consentCard = (copy: AvatarConsentCopy) => (\n <section\n aria-labelledby={consentTitleId}\n data-boff-explore=\"avatar-live-consent\"\n className=\"w-full max-w-sm rounded-lg border border-border p-4 text-start\"\n >\n <h2 id={consentTitleId} className=\"text-base font-semibold\">\n {copy.title}\n </h2>\n <p className=\"mt-2 text-sm\">\n {productName === null || copy.introProduct === null\n ? copy.intro\n : fill(copy.introProduct, { product: productName })}\n </p>\n <p className=\"mt-2 text-sm text-muted-foreground\">{copy.processing}</p>\n <p className=\"mt-2 text-sm text-muted-foreground\">{copy.storage}</p>\n <a\n href={PRIVACY_HREF}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-boff-explore=\"avatar-live-privacy\"\n 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\"\n >\n {copy.privacyLink}\n <span className=\"sr-only\"> {S.opensInNewTab}</span>\n </a>\n </section>\n );\n /** The card's buttons: Start (or, while the answer is written, Start when ready) and Not now. */\n const consentActions = (whenReady: boolean) => (\n <div className=\"flex flex-wrap items-center justify-center gap-2\">\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore={\n whenReady ? \"avatar-live-start-when-ready\" : \"avatar-live-start\"\n }\n className={primaryButton}\n onClick={whenReady ? startWhenReady : start}\n >\n {whenReady ? S.startWhenReady : S.start}\n </button>\n <button\n type=\"button\"\n data-boff-explore=\"avatar-live-not-now\"\n className={secondaryButton}\n onClick={notNow}\n >\n {S.notNow}\n </button>\n </div>\n );\n const liveMedia = (playing: boolean) => (\n <div\n className={cn(\n \"relative shrink-0 overflow-hidden rounded-xl border border-border bg-muted\",\n any ? \"h-[min(12rem,32dvh)] w-[min(12rem,32dvh)]\" : \"h-48 w-48\",\n )}\n >\n <video\n ref={videoRef}\n aria-label={S.video}\n data-boff-explore=\"avatar-live-video\"\n playsInline\n autoPlay\n muted\n onPlaying={onPlaying}\n className={cn(\"h-full w-full object-cover\", !playing && \"opacity-0\")}\n />\n {playing ? null : (\n <img\n src={still.src}\n alt=\"\"\n decoding=\"async\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n )}\n {/* Under `any`, the audio element is the view's own, so that Start's tap can let it play (see `unlockSound`). */}\n {any ? null : (\n <audio ref={audioRef} data-boff-explore=\"avatar-live-audio\" />\n )}\n </div>\n );\n /**\n * The status line while the avatar speaks. Where the server speaks only the first part of the answer (Stage B), the\n * line says so, and that the full answer is in Chat, in place of \"The avatar is speaking.\": the same slot, so the\n * layout is the same whether or not a cap applies.\n */\n const speakingLine = (session: ShownSession) =>\n session.excerpt ? S.excerpt : S.speaking;\n const liveBody = (session: ShownSession) => (\n <>\n <section\n aria-label={S.captions}\n data-boff-explore=\"avatar-live-captions\"\n lang={session.captions.locale || undefined}\n dir=\"auto\"\n tabIndex={0}\n 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\"\n >\n {session.captions.text}\n </section>\n <p className=\"text-xs text-muted-foreground\">{S.answerInChat}</p>\n <p className=\"text-sm tabular-nums text-muted-foreground\">\n {S.timeLeft}{\" \"}\n <span role=\"timer\" data-boff-explore=\"avatar-live-countdown\">\n {clock(Math.max(0, (session.endsAt - now) / 1000))}\n </span>\n </p>\n </>\n );\n /** A session's buttons: the sound, where the browser holds it back, Stop, and the way back to the chat. */\n const liveActions = (back: ReactNode) => (\n <div className=\"flex flex-wrap items-center justify-center gap-2\">\n {blocked ? (\n <button\n type=\"button\"\n data-boff-explore=\"avatar-live-sound\"\n className={primaryButton}\n onClick={enablePlayback}\n >\n {S.tapForSound}\n </button>\n ) : null}\n {stopButton}\n {back}\n </div>\n );\n const badge = (\n <p\n data-boff-explore=\"avatar-live-badge\"\n className=\"rounded-full bg-muted px-3 py-1 text-xs font-medium text-foreground\"\n >\n {S.badge}\n </p>\n );\n\n if (any) {\n // The Avatar tab with its own question box: a stage that scrolls (the picture or the video, the status, the card or\n // the captions, the question) over a foot that stays (the chips, the box and the line under it).\n let status = \"\";\n let outcome = false;\n let lead: ReactNode = null;\n let top: ReactNode = null;\n let media: ReactNode = stillPicture(false);\n let body: ReactNode = null;\n let actions: ReactNode = null;\n let newChatOffer = false;\n let box: \"spoken\" | \"text\" | null = null;\n const first = exchange.question;\n const questionLine =\n first === null ? null : (\n <p\n data-boff-explore=\"avatar-live-question\"\n dir=\"auto\"\n className=\"line-clamp-2 w-full max-w-sm break-words text-sm font-medium\"\n >\n {first.content}\n </p>\n );\n const activity = conversation?.activity ?? null;\n const activityLine =\n activity === null ? null : (\n <p\n data-boff-explore=\"avatar-live-activity\"\n className=\"text-xs text-muted-foreground\"\n >\n {activity}\n </p>\n );\n\n if (textMode) {\n // The day's session is used (or the server says its limit is reached): the box asks ordinary questions, and the\n // answer shows here as text.\n const messages = conversation?.messages ?? [];\n let questionAt = messages.length - 1;\n while (questionAt >= 0 && messages[questionAt]?.role !== \"USER\") {\n questionAt -= 1;\n }\n const lastQuestion = questionAt === -1 ? undefined : messages[questionAt];\n // Only that question's own answer, the message right after it: the chat adds the question at once and its answer\n // only once the server takes it (and none when the send fails), so an earlier answer is never shown under it.\n const after = questionAt === -1 ? undefined : messages[questionAt + 1];\n const lastAnswer = after?.role === \"ASSISTANT\" ? after : undefined;\n const chatPhase = conversation?.phase;\n /** The question has no answer yet: on its way, failed (the chat's error is the send's), or neither. */\n const unanswered =\n lastQuestion === undefined || lastAnswer !== undefined\n ? null\n : chatPhase === \"sending\" || chatPhase === \"streaming\"\n ? \"waiting\"\n : chatPhase === \"error\" || chatPhase === \"limited\"\n ? \"failed\"\n : null;\n if (phase.name === \"refused\") {\n status = S[REFUSAL_TEXT[phase.reason]];\n outcome = true;\n } else if (phase.name === \"ended\") {\n // After the day's session: how it ended stays said, over the last question and its answer.\n status = S[phase.how];\n outcome = true;\n }\n body = (\n <>\n {lastQuestion === undefined ? null : (\n <p\n data-boff-explore=\"avatar-live-question\"\n dir=\"auto\"\n className=\"line-clamp-2 w-full max-w-sm break-words text-sm font-medium\"\n >\n {lastQuestion.content}\n </p>\n )}\n {lastAnswer === undefined ? (\n unanswered === \"waiting\" ? (\n <p className=\"text-xs text-muted-foreground\">\n {activity ?? S.gettingAnswer}\n </p>\n ) : unanswered === \"failed\" ? (\n <p className=\"text-sm text-muted-foreground\">{S.answerFailed}</p>\n ) : null\n ) : lastAnswer.status === \"PENDING\" ||\n lastAnswer.status === \"RUNNING\" ? (\n <p className=\"text-xs text-muted-foreground\">\n {activity ?? S.gettingAnswer}\n </p>\n ) : lastAnswer.status === \"FAILED\" ? (\n <p className=\"text-sm text-muted-foreground\">{S.answerFailed}</p>\n ) : (\n // The answer's words, not its markdown: `content` is written for the chat's renderer, and shown as it is\n // here a link reads `[label](https://…)`. In its spoken form, as the chat's read-aloud says it: a link is its\n // label (the address is in Chat, one tap away), a table its rows, and the markers of emphasis, headings,\n // quotes and list items go (`answerDisplayText`). The words are the ones the chat shows, citation markers\n // included, which the sources in Chat answer to.\n <p\n data-boff-explore=\"avatar-live-text-answer\"\n dir=\"auto\"\n className=\"line-clamp-6 w-full max-w-sm whitespace-pre-wrap break-words text-start text-sm\"\n >\n {answerDisplayText(lastAnswer.content)}\n </p>\n )}\n </>\n );\n // After a session, \"Read the answer and sources in Chat\" stays the step's own control, as it was before the box\n // asked anything (focus moves there from Stop).\n const ended = phase.name === \"ended\";\n // A send that failed before any answer came is retried in Chat, so the way there is offered for it too.\n actions =\n lastAnswer === undefined && unanswered !== \"failed\" && !ended\n ? null\n : readInChatButton(ended);\n box = \"text\";\n } else {\n switch (phase.name) {\n case \"checking\":\n status = S.checking;\n break;\n case \"needs-answer\":\n switch (shown.kind) {\n case \"empty\":\n status = note === \"new-chat\" ? S.newChatStarted : \"\";\n lead = <p className=\"text-base font-semibold\">{S.askHeadline}</p>;\n box = \"spoken\";\n break;\n case \"asking\":\n case \"answer\": {\n // The card shows while the answer is written, for a question asked here as the first of a new chat, once\n // the server has taken it.\n const card = shown.askedHere && shown.pendingAnswerId !== null;\n status =\n note === \"cancelled\" ? S.armedCancelled : S.gettingAnswer;\n if (card) media = stillPicture(true);\n body = (\n <>\n {questionLine}\n {activityLine}\n {card ? consentCard(phase.offer.copy) : null}\n </>\n );\n actions = card ? consentActions(true) : null;\n break;\n }\n case \"text-only\":\n status = S.notSpoken;\n outcome = true;\n body = questionLine;\n actions = readInChatButton(false);\n newChatOffer = true;\n break;\n case \"failed\":\n status = S.answerFailed;\n outcome = true;\n body = questionLine;\n newChatOffer = true;\n break;\n case \"ask-here\":\n status = S.askHere;\n outcome = true;\n actions = readInChatButton(false);\n newChatOffer = true;\n break;\n default:\n status = S.startNewChat;\n outcome = true;\n body = (\n <p className=\"text-sm text-muted-foreground\">\n {S.startNewChatDetailAny}\n </p>\n );\n actions = readInChatButton(false);\n newChatOffer = true;\n break;\n }\n break;\n case \"consent\":\n media = stillPicture(true);\n body = (\n <>\n {questionLine}\n {consentCard(phase.offer.copy)}\n </>\n );\n actions = consentActions(false);\n break;\n case \"declined\":\n status = S.declined;\n actions = readInChatButton(true);\n break;\n case \"waiting\":\n status = S.armed;\n body = questionLine;\n actions = (\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-cancel\"\n className={secondaryButton}\n onClick={stop}\n >\n {S.cancel}\n </button>\n );\n break;\n case \"refused\":\n outcome = true;\n if (\n phase.reason === \"not_eligible\" ||\n phase.reason === \"answer_claimed\"\n ) {\n // This chat's answer will not be read: a new chat for the avatar can be.\n status =\n phase.reason === \"not_eligible\"\n ? S.notEligibleAny\n : S.answerClaimed;\n actions = readInChatButton(false);\n newChatOffer = true;\n } else {\n status = S[REFUSAL_TEXT[phase.reason]];\n actions = continueButton;\n }\n break;\n case \"bot-check\":\n status = S.botCheck;\n actions = stopButton;\n break;\n case \"creating\":\n status = S.connecting;\n actions = stopButton;\n break;\n case \"pending\":\n case \"live\":\n status =\n phase.name === \"live\" ? speakingLine(phase.session) : S.connecting;\n top = badge;\n media = liveMedia(phase.name === \"live\");\n body = liveBody(phase.session);\n actions = liveActions(readInChatButton(false));\n break;\n case \"ended\":\n status = S[phase.how];\n outcome = true;\n actions = readInChatButton(true);\n // A session that never played leaves no note of the day's: a new chat for the avatar can still be. (One that\n // played is in text mode, above.)\n newChatOffer = true;\n break;\n default:\n break;\n }\n }\n\n const reason = askReason;\n const chips =\n box !== null && shown.kind === \"empty\" && prompts.length > 0 ? (\n <div className=\"flex flex-col gap-1\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n {tryAsking}\n </p>\n <div className=\"flex max-h-28 flex-wrap gap-2 overflow-y-auto\">\n {prompts.map((prompt) => (\n <button\n key={prompt}\n type=\"button\"\n data-boff-explore=\"avatar-live-chip\"\n aria-disabled={reason !== null ? \"true\" : undefined}\n 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\"\n onClick={() => {\n if (reason === null) ask(prompt);\n }}\n >\n {prompt}\n </button>\n ))}\n </div>\n </div>\n ) : null;\n const foot =\n box === null && !newChatOffer ? null : (\n <div\n data-boff-explore=\"avatar-live-foot\"\n 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))]\"\n >\n {newChatOffer ? (\n <div className=\"flex flex-col items-center gap-1 text-center\">\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-new-chat-avatar\"\n className={cn(primaryButton, \"min-h-11\")}\n onClick={newChatForAvatar}\n >\n {S.newChatForAvatar}\n </button>\n <p className=\"text-xs text-muted-foreground\">{S.newChatNote}</p>\n </div>\n ) : null}\n {chips}\n {box !== null && usedToday ? (\n <p\n data-boff-explore=\"avatar-live-used-today\"\n className=\"text-xs text-muted-foreground\"\n >\n {S.usedToday}\n </p>\n ) : null}\n {box === \"spoken\" ? mic.notice : null}\n {box === null ? null : (\n <AskBox\n value={draft}\n maxLength={askMaxLength}\n onChange={setDraft}\n onAsk={ask}\n reason={reason}\n label={S.askLabel}\n placeholder={S.askPlaceholder}\n send={send}\n footer={S.askFooter}\n noFiles={S.askNoFiles}\n hint={box === \"spoken\" ? S.needsAnswerAny : null}\n touchFirst={touchFirst}\n mic={box === \"spoken\" ? mic.button : null}\n micLines={box === \"spoken\" ? mic.lines : null}\n />\n )}\n </div>\n );\n\n return (\n <div\n ref={rootRef}\n data-boff-explore=\"avatar-live\"\n data-phase={phase.name}\n data-ask={askState}\n className=\"absolute inset-0 flex flex-col bg-background\"\n >\n <div className=\"flex min-h-0 flex-1 flex-col items-center gap-4 overflow-y-auto p-6 text-center\">\n {top}\n {media}\n {lead}\n <p\n role=\"status\"\n data-boff-explore=\"avatar-live-status\"\n className={\n outcome\n ? \"text-base font-semibold\"\n : \"text-sm text-muted-foreground\"\n }\n >\n {status}\n </p>\n {body}\n <div ref={botBoxRef} data-boff-explore=\"avatar-live-bot-check\" />\n {actions}\n </div>\n {foot}\n <audio ref={audioRef} data-boff-explore=\"avatar-live-audio\" />\n </div>\n );\n }\n\n // The headline of each step, in the one polite status region: announced as it changes, the countdown never.\n const headline: Record<Phase[\"name\"], string> = {\n idle: \"\",\n checking: S.checking,\n inert: \"\",\n // A question asked and its answer on its way: the answer is coming (the avatar is offered once it completes).\n \"needs-answer\": startOver\n ? S.startNewChat\n : shown.kind === \"asking\"\n ? S.gettingAnswer\n : S.needsAnswer,\n consent: \"\",\n declined: S.declined,\n waiting: S.armed,\n refused: phase.name === \"refused\" ? S[REFUSAL_TEXT[phase.reason]] : \"\",\n \"bot-check\": S.botCheck,\n creating: S.connecting,\n pending: S.connecting,\n live: phase.name === \"live\" ? speakingLine(phase.session) : \"\",\n ended: phase.name === \"ended\" ? S[phase.how] : \"\",\n };\n const outcome =\n phase.name === \"needs-answer\" ||\n phase.name === \"refused\" ||\n phase.name === \"ended\";\n\n let top: ReactNode = null;\n let media: ReactNode = stillPicture(false);\n let body: ReactNode = null;\n let actions: ReactNode = null;\n\n switch (phase.name) {\n case \"needs-answer\":\n // Nothing to read yet (choose a suggested question), or never in this conversation (start a new chat).\n body = (\n <p className=\"text-sm text-muted-foreground\">\n {startOver ? S.startNewChatDetail : S.needsAnswerDetail}\n </p>\n );\n actions = startOver ? startOverActions : continueButton;\n break;\n case \"consent\":\n media = stillPicture(true);\n body = consentCard(phase.offer.copy);\n actions = consentActions(false);\n break;\n case \"refused\":\n // An answer the service will not read (not one of the suggested questions, or too old by its clock): only a new\n // chat can be.\n actions =\n phase.reason === \"not_eligible\" ? startOverActions : continueButton;\n break;\n case \"bot-check\":\n case \"creating\":\n actions = stopButton;\n break;\n case \"pending\":\n case \"live\":\n top = badge;\n media = liveMedia(phase.name === \"live\");\n body = liveBody(phase.session);\n actions = liveActions(\n <button\n type=\"button\"\n data-boff-explore=\"avatar-live-continue\"\n className={secondaryButton}\n onClick={onContinueInChat}\n >\n {continueInChat}\n </button>,\n );\n break;\n case \"ended\":\n body = <p className=\"text-sm text-muted-foreground\">{S.answerInChat}</p>;\n actions = (\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-back\"\n className={primaryButton}\n onClick={onContinueInChat}\n >\n {S.backToChat}\n </button>\n );\n break;\n default:\n break;\n }\n\n // The same slots in every step, so the status region and the bot check's box stay the same elements throughout.\n return (\n <div\n ref={rootRef}\n data-boff-explore=\"avatar-live\"\n data-phase={phase.name}\n className=\"flex max-h-full w-full flex-col items-center gap-4 overflow-y-auto\"\n >\n {top}\n {media}\n <p\n role=\"status\"\n data-boff-explore=\"avatar-live-status\"\n className={\n outcome ? \"text-base font-semibold\" : \"text-sm text-muted-foreground\"\n }\n >\n {headline[phase.name]}\n </p>\n {body}\n <div ref={botBoxRef} data-boff-explore=\"avatar-live-bot-check\" />\n {actions}\n </div>\n );\n}\n\ninterface AskBoxProps {\n value: string;\n /** The longest question the box takes: {@link ASK_MAX_LENGTH}, or the chat's own limit where that is shorter. */\n maxLength: number;\n onChange: (value: string) => void;\n /** Ask `question`. Called only with text, and only while {@link AskBoxProps.reason} is null. */\n onAsk: (question: string) => void;\n /** Why Send cannot be pressed now (an answer on its way, a chat that cannot ask), or null when it can. */\n reason: string | null;\n label: string;\n placeholder: string;\n send: string;\n /** The line under the box, always shown with it. */\n footer: string;\n /** Said when a file is pasted or dropped on the box. */\n noFiles: string;\n /** What the box is for, read with it by a screen reader; null for nothing more than its name. */\n hint: string | null;\n touchFirst: boolean;\n /** The mic's button, between the box and Send (Stage C); null without a mic. */\n mic: ReactNode;\n /** The mic's status line and what it hears, under the box's row; null without a mic. */\n micLines: ReactNode;\n}\n\n/**\n * The Avatar tab's own question box. Its text is the view's (never the chat's draft); it takes text only, up to\n * {@link AskBoxProps.maxLength} characters. Send is never `disabled` (a disabled control cannot be focused or explained): it is\n * `aria-disabled`, described by why. Enter asks and Shift+Enter breaks the line; while an input method is composing,\n * Enter is the input method's, and so is Escape, which then does not reach the panel. 44 px controls.\n */\nfunction AskBox({\n value,\n maxLength,\n onChange,\n onAsk,\n reason,\n label,\n placeholder,\n send,\n footer,\n noFiles,\n hint,\n touchFirst,\n mic,\n micLines,\n}: AskBoxProps) {\n const uid = useId();\n const reasonId = `${uid}-reason`;\n const hintId = `${uid}-hint`;\n const footerId = `${uid}-footer`;\n const [refusedFiles, setRefusedFiles] = useState(false);\n const empty = value.trim() === \"\";\n\n const submit = () => {\n if (reason !== null || empty) return;\n onAsk(value);\n };\n const onKeyDown = (event: ReactKeyboardEvent<HTMLTextAreaElement>) => {\n if (event.nativeEvent.isComposing || event.keyCode === 229) {\n if (event.key === \"Escape\") event.stopPropagation();\n return;\n }\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n submit();\n }\n };\n // Files are the chat's: one pasted or dropped here is refused, with a word on where to attach it.\n const onPaste = (event: ReactClipboardEvent<HTMLTextAreaElement>) => {\n if (event.clipboardData.files.length === 0) return;\n event.preventDefault();\n setRefusedFiles(true);\n };\n const onDrop = (event: ReactDragEvent<HTMLTextAreaElement>) => {\n if (!Array.from(event.dataTransfer.types).includes(\"Files\")) return;\n event.preventDefault();\n setRefusedFiles(true);\n };\n\n return (\n <form\n data-boff-explore=\"avatar-live-ask\"\n className=\"flex w-full flex-col gap-1\"\n onSubmit={(event) => {\n event.preventDefault();\n submit();\n }}\n >\n <div className=\"flex items-end gap-2\">\n <textarea\n value={value}\n rows={1}\n maxLength={maxLength}\n aria-label={label}\n aria-describedby={hint === null ? footerId : `${hintId} ${footerId}`}\n placeholder={placeholder}\n dir=\"auto\"\n data-avatar-primary={touchFirst ? undefined : \"\"}\n data-boff-explore=\"avatar-live-ask-input\"\n 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\"\n onChange={(event) => {\n setRefusedFiles(false);\n onChange(event.target.value);\n }}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n onDrop={onDrop}\n />\n {mic}\n <button\n type=\"submit\"\n aria-disabled={reason !== null || empty ? \"true\" : undefined}\n aria-describedby={reason !== null ? reasonId : undefined}\n data-avatar-primary={touchFirst ? \"\" : undefined}\n data-boff-explore=\"avatar-live-ask-send\"\n 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\"\n >\n {send}\n </button>\n </div>\n {micLines}\n {reason === null ? null : (\n <p\n id={reasonId}\n data-boff-explore=\"avatar-live-ask-reason\"\n className=\"text-xs text-muted-foreground\"\n >\n {reason}\n </p>\n )}\n {refusedFiles ? (\n <p\n data-boff-explore=\"avatar-live-ask-files\"\n className=\"text-xs text-muted-foreground\"\n >\n {noFiles}\n </p>\n ) : null}\n {hint === null ? null : (\n <p id={hintId} className=\"sr-only\">\n {hint}\n </p>\n )}\n <p id={footerId} className=\"text-xs text-muted-foreground\">\n {footer}\n </p>\n </form>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/explore-avatar-api.ts","../../src/components/explore-avatar-i18n.ts","../../src/components/explore-avatar-mic.tsx","../../src/components/explore-avatar-turnstile.ts","../../src/components/explore-avatar-live-view.tsx"],"names":["loading","PRIVACY_HREF","IDLE","INERT","clock","useId","useState","useRef","useCallback","shown","followUp","kind","locale","live","base","headers","off","body","exchange","token","useEffect","now","conversation","current","unread","jsx","jsxs","Fragment","outcome","top","media","actions"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * BOFF-9797. The website live avatar's requests, as a visitor's browser makes them.\n *\n * They go to the global gateway's web branch, under the SDK's configured gateway (`/api/web-avatar/v1/*` on its\n * origin), and follow the website avatar web API, v1:\n *\n * GET /availability?site=…&locale=… when the Avatar tab opens, never on page load\n * POST /sessions after the visitor's consent (and the bot check, where the server runs one)\n * POST /sessions/{id}/end Stop, leaving the tab, closing the panel, hiding the page\n * POST /sessions/{id}/turn Stage D, only for a session whose 201 offers `followUps`: the visitor asks\n * again in the same conversation (see {@link requestTurn})\n *\n * - **Never with credentials** (`credentials: 'omit'`): a website visitor has no account, no cookie and no workspace\n * here.\n * - **The bot check's token** goes in the `x-web-avatar-bot-token` header, on create only, and only when the server\n * checks for bots: availability says whether it does (`botCheck`, contract v1.2). The gateway verifies it and drops\n * it; the body is exactly the contract's six fields. The check itself is bound to that body (contract v1.1): see\n * {@link avatarBotBinding}. A server that runs no bot check gets no header at all.\n * - **The end is a simple request** (see {@link sendEnd}): no `Content-Type` of our own, so a page being hidden has no\n * CORS preflight to wait for.\n * - **Every answer is read into one of a few outcomes** the Avatar tab can show. A missing route, a forbidden one, a\n * refused origin and an availability request that fails are all `inert`: the tab shows what it showed before there\n * was a live avatar. A create that has been sent and gets no answer is `failed`, never `inert`: the server may have\n * created the session (see {@link requestCreate}). Nothing a server says is shown as it was said.\n * - Nothing here logs. The conversation token goes into the create body and nowhere else, and the session's secret\n * only into the end and turn bodies.\n */\n\nimport { isAvatarSite, isAvatarVersion } from \"./explore-avatar-live-config\";\n\n// The few helpers the panel itself needs (where the requests go, and the shapes a config may take) live in\n// `explore-avatar-live-config.ts`, so that they do not drag this file into every site's bundle; they are re-exported\n// here, where the rest of the contract's grammar is.\nexport {\n AVATAR_WEB_API_PATH,\n avatarApiBase,\n isAvatarSite,\n isAvatarVersion,\n} from \"./explore-avatar-live-config\";\n\n/** How long the Avatar tab waits to hear whether the live avatar is offered. */\nconst AVAILABILITY_TIMEOUT_MS = 8_000;\n/**\n * How long a create may take before it is given up on as `failed` (see {@link requestCreate}): past the gateway's own\n * deadline for it, so the gateway's answer is what decides.\n */\nconst CREATE_TIMEOUT_MS = 30_000;\n/**\n * How long a turn may take before it is given up on (see {@link requestTurn}): past the gateway's own deadline for it\n * (2 s for a mark or an interrupt, 20 s for an answer, which the avatar service checks and synthesizes before it\n * replies), so the gateway's answer is what decides.\n */\nconst TURN_TIMEOUT_MS = 8_000;\nconst TURN_ANSWER_TIMEOUT_MS = 25_000;\n\n/** The refusals the Avatar tab explains, each in a short sentence of its own. */\nexport type AvatarRefusal =\n | \"busy\"\n | \"limits\"\n | \"region\"\n | \"locale\"\n | \"paused\"\n | \"not_eligible\"\n | \"answer_claimed\";\n\n/** Why the browser ends a session. Analytics only: the secret is what ends it. */\nexport type AvatarEndReason = \"user\" | \"page_hide\" | \"client_error\";\n\n/**\n * Whether the server checks for bots when a session is created: `turnstile` (a Cloudflare Turnstile token is required on\n * create) or `off` (none is; the server's own caps decide). A server older than contract v1.2 names no mode and always\n * checks, so it is read as `turnstile`.\n */\nexport type AvatarBotCheck = \"off\" | \"turnstile\";\n\n/**\n * Which first questions the server reads the answer to (contract v1.3, BOFF-9797): `suggested` (only the exact\n * suggested questions of the site's manifest) or `any` (a question the visitor typed too). A server older than v1.3\n * names none and reads suggested questions only, so it is read as `suggested`. The Avatar tab offers its own question\n * box only under `any`, and only with consent copy written for it.\n */\nexport type AvatarQuestions = \"any\" | \"suggested\";\n\n/**\n * What an `ok` availability offers the Avatar tab's mic (BOFF-9797 Stage C): a token that opens one website\n * speech-to-text stream, and when the gateway says it expires (epoch milliseconds, the gateway's clock). The gateway adds\n * it, minted for this visitor, only while its website speech-to-text is on, and only to an answer that says the avatar\n * can start now.\n */\nexport interface AvatarSttOffer {\n token: string;\n expiresAt: number;\n}\n\n/** What an `ok` availability offers. */\nexport interface AvatarOffer {\n /** The consent version the visitor must agree to: the panel shows only copy written for exactly this version. */\n consentVersion: string;\n /** The longest a session can last, in seconds. */\n maxSessionSeconds: number;\n /** Whether a bot check runs before the create request. */\n botCheck: AvatarBotCheck;\n /** Which first questions the server reads the answer to. */\n questions: AvatarQuestions;\n /**\n * The mic's offer, present only when the answer carries one this browser can use (see {@link readSttOffer}). Absent,\n * the Avatar tab offers no mic; nothing else changes.\n */\n stt?: AvatarSttOffer;\n}\n\nexport type AvatarAvailability =\n | { kind: \"available\"; offer: AvatarOffer }\n /**\n * `questions` is the server's (contract v1.3 reports it with every answer): under `any` a `limits` refusal leaves the\n * Avatar tab's box asking in text. Read leniently here, since a refusal offers nothing: anything but `any` is\n * `suggested`.\n */\n | { kind: \"refused\"; reason: AvatarRefusal; questions: AvatarQuestions }\n /** Not offered here, or not reachable: the Avatar tab stays as it was before the live avatar. */\n | { kind: \"inert\" };\n\n/** A created session: what the browser needs to watch it and to end it. */\nexport interface AvatarSession {\n sessionId: string;\n /** Returned once; ends this session and nothing else. Kept out of the page's markup. */\n endSecret: string;\n /** When the server ends the session, in epoch milliseconds. */\n endsAt: number;\n join: {\n livekitUrl: string;\n /** Subscribe-only and short-lived. Kept out of the page's markup. */\n participantToken: string;\n workerIdentity: string;\n };\n captions: { locale: string; text: string };\n /**\n * The server speaks only a whole-sentence first part of the answer, labelled as such, because the whole answer does\n * not fit the session (contract v1.4, Stage B: only under the server's `AVATAR_WEB_SIZE_BY_AUDIO`). The full answer\n * stays in Chat. False when the 201 says false, says nothing (an older server, or the setting off) or says anything\n * but `true`: the field is additive, so a value it cannot read never makes a session unusable.\n */\n excerpt: boolean;\n /**\n * The answers after the first (Stage D, only under the server's `AVATAR_WEB_MULTI_ANSWER`): present only when the 201\n * offers them (see {@link readFollowUps}). Absent, the session reads its one answer, exactly as before.\n */\n followUps?: AvatarFollowUps;\n}\n\n/**\n * What a 201 offers for the answers after the first (Stage D): the session lasts the whole conversation (its length is\n * fixed when it is created), and the visitor asks again in it through {@link requestTurn}.\n */\nexport interface AvatarFollowUps {\n /** The most answers the session speaks, the first included. */\n maxAnswers: number;\n /** After an answer, how long the session waits for the next question before the server ends it. */\n idleSeconds: number;\n /** The longest the server waits, after an `asking` mark, for that question's answer to be written. */\n maxAnswerWaitSeconds: number;\n}\n\nexport type AvatarCreateResult =\n | { kind: \"created\"; session: AvatarSession }\n /** A session was created, but its answer cannot be used: the browser ends it at once. */\n | { kind: \"unusable\"; sessionId: string; endSecret: string }\n | { kind: \"refused\"; reason: AvatarRefusal }\n /** The consent version moved on since availability: ask again, and show the consent that is current. */\n | { kind: \"consent\" }\n | { kind: \"inert\" }\n | { kind: \"failed\" };\n\n/** The create body: exactly these six fields, in the contract's order. */\nexport interface AvatarCreateBody {\n site: string;\n locale: string;\n conversationToken: string;\n messageId: string;\n consentVersion: string;\n manifestVersion: string;\n}\n\nconst MESSAGE_ID = /^[A-Za-z0-9_-]{1,64}$/;\n/** What a WebSocket subprotocol entry may hold, as the gateway checks it: the mic's token travels as `offer.<token>`. */\nconst STT_TOKEN = /^[A-Za-z0-9._~-]{1,4096}$/;\nconst CONVERSATION_TOKEN = /^[A-Za-z0-9._~+/=-]{16,512}$/;\nconst LOCALE = /^[A-Za-z0-9-]{1,16}$/;\nconst SESSION_ID = /^avs_[0-9a-f]{32}$/;\nconst END_SECRET = /^[A-Za-z0-9_-]{43}$/;\n\nconst INERT = { kind: \"inert\" } as const;\nconst FAILED = { kind: \"failed\" } as const;\n\n/** An answer id the contract accepts. */\nexport function isAvatarMessageId(value: string): boolean {\n return MESSAGE_ID.test(value);\n}\n\n/** A conversation token the contract accepts. */\nexport function isAvatarConversationToken(value: string): boolean {\n return CONVERSATION_TOKEN.test(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/** What each availability `reason` other than `ok` means for the Avatar tab. A reason not listed is inert. */\nconst AVAILABILITY_REASONS: ReadonlyMap<string, AvatarRefusal | \"inert\"> =\n new Map<string, AvatarRefusal | \"inert\">([\n [\"site\", \"inert\"],\n [\"unavailable\", \"inert\"],\n [\"region\", \"region\"],\n [\"locale\", \"locale\"],\n [\"paused\", \"paused\"],\n [\"busy\", \"busy\"],\n [\"limits\", \"limits\"],\n ]);\n\nconst BOT_CHECK_MODES: ReadonlySet<string> = new Set<AvatarBotCheck>([\n \"off\",\n \"turnstile\",\n]);\n\n/**\n * An `ok` answer's `botCheck` (contract v1.2): exactly `{\"mode\":\"off\"}` or `{\"mode\":\"turnstile\"}`. Absent, from a\n * server older than v1.2: `turnstile`, as that server always checks. Anything else (an unknown mode, another field, a\n * value of another type) is null: the browser cannot tell what the server will require, so it offers nothing.\n */\nfunction readBotCheck(value: unknown): AvatarBotCheck | null {\n if (value === undefined) return \"turnstile\";\n if (!isRecord(value)) return null;\n const keys = Object.keys(value);\n const { mode } = value;\n if (\n keys.length !== 1 ||\n keys[0] !== \"mode\" ||\n typeof mode !== \"string\" ||\n !BOT_CHECK_MODES.has(mode)\n ) {\n return null;\n }\n return mode === \"off\" ? \"off\" : \"turnstile\";\n}\n\nconst QUESTION_MODES: ReadonlySet<string> = new Set<AvatarQuestions>([\n \"any\",\n \"suggested\",\n]);\n\n/**\n * An `ok` answer's `questions` (contract v1.3): exactly `\"any\"` or `\"suggested\"`. Absent, from a server older than v1.3:\n * `suggested`, which is all that server reads. Anything else is null: the browser cannot tell which questions the\n * server will read, so it offers nothing.\n */\nfunction readQuestions(value: unknown): AvatarQuestions | null {\n if (value === undefined) return \"suggested\";\n if (typeof value !== \"string\" || !QUESTION_MODES.has(value)) return null;\n return value === \"any\" ? \"any\" : \"suggested\";\n}\n\n/**\n * An `ok` answer's `stt` (BOFF-9797 Stage C): exactly `{token, expiresAt}`, a token that can travel as a WebSocket\n * subprotocol entry and a positive whole number of milliseconds. Absent (the gateway's website speech-to-text off, or a\n * gateway older than it) or anything else (another field, another shape): undefined, and the Avatar tab offers no mic.\n * Additive: a value it cannot read never makes the rest of the offer unusable.\n */\nfunction readSttOffer(value: unknown): AvatarSttOffer | undefined {\n if (!isRecord(value)) return undefined;\n const keys = Object.keys(value).sort();\n const { token, expiresAt } = value;\n if (\n keys.length !== 2 ||\n keys[0] !== \"expiresAt\" ||\n keys[1] !== \"token\" ||\n typeof token !== \"string\" ||\n !STT_TOKEN.test(token) ||\n typeof expiresAt !== \"number\" ||\n !Number.isSafeInteger(expiresAt) ||\n expiresAt <= 0\n ) {\n return undefined;\n }\n return { token, expiresAt };\n}\n\n/**\n * Read an availability answer: its HTTP status and its parsed JSON body (or null). Only an `ok` answer's `botCheck` is\n * read, and only an `ok` answer's `questions` strictly: a refusal offers nothing for them to change. The same goes for\n * `stt`, which only an `ok` answer can carry.\n */\nexport function readAvailability(\n status: number,\n body: unknown,\n): AvatarAvailability {\n if (status !== 200 || !isRecord(body)) return INERT;\n const { available, reason } = body;\n if (typeof available !== \"boolean\" || typeof reason !== \"string\") {\n return INERT;\n }\n if (reason === \"ok\") {\n const { consentVersion, maxSessionSeconds } = body;\n const botCheck = readBotCheck(body.botCheck);\n const questions = readQuestions(body.questions);\n if (\n available !== true ||\n typeof consentVersion !== \"string\" ||\n !isAvatarVersion(consentVersion) ||\n typeof maxSessionSeconds !== \"number\" ||\n !Number.isInteger(maxSessionSeconds) ||\n maxSessionSeconds < 1 ||\n botCheck === null ||\n questions === null\n ) {\n return INERT;\n }\n const stt = readSttOffer(body.stt);\n return {\n kind: \"available\",\n offer: {\n consentVersion,\n maxSessionSeconds,\n botCheck,\n questions,\n ...(stt === undefined ? {} : { stt }),\n },\n };\n }\n const meaning = available ? undefined : AVAILABILITY_REASONS.get(reason);\n return meaning === undefined || meaning === \"inert\"\n ? INERT\n : {\n kind: \"refused\",\n reason: meaning,\n questions: body.questions === \"any\" ? \"any\" : \"suggested\",\n };\n}\n\n/** The create error codes the Avatar tab explains. */\nconst CREATE_REFUSALS: ReadonlyMap<string, AvatarRefusal> = new Map<\n string,\n AvatarRefusal\n>([\n [\"busy\", \"busy\"],\n [\"limits\", \"limits\"],\n [\"region\", \"region\"],\n [\"locale\", \"locale\"],\n [\"paused\", \"paused\"],\n [\"not_eligible\", \"not_eligible\"],\n [\"answer_claimed\", \"answer_claimed\"],\n]);\n\nfunction errorCode(body: unknown): string | null {\n if (!isRecord(body) || !isRecord(body.error)) return null;\n const { code } = body.error;\n return typeof code === \"string\" ? code : null;\n}\n\n/** The most answers a session record holds (global-speech-svc `WEB_MAX_SEGMENTS`). */\nconst MAX_FOLLOW_UP_ANSWERS = 16;\n/** The longest wait a 201 may name, in seconds: far past any session, which lasts minutes at most. */\nconst MAX_FOLLOW_UP_SECONDS = 600;\nconst FOLLOW_UP_KEYS = [\"idleSeconds\", \"maxAnswerWaitSeconds\", \"maxAnswers\"];\n\nfunction isWholeBetween(value: unknown, max: number): value is number {\n return (\n typeof value === \"number\" &&\n Number.isSafeInteger(value) &&\n value >= 1 &&\n value <= max\n );\n}\n\n/**\n * A 201's `followUps` (Stage D): exactly `{maxAnswers, idleSeconds, maxAnswerWaitSeconds}`, each a whole number from\n * one (`maxAnswers` up to {@link MAX_FOLLOW_UP_ANSWERS}, the seconds up to {@link MAX_FOLLOW_UP_SECONDS}). Absent (the\n * server's setting off, or a server older than Stage D) or anything else (another field, another shape): undefined,\n * and the session reads its one answer as before. Additive: a value it cannot read never makes the session unusable.\n */\nfunction readFollowUps(value: unknown): AvatarFollowUps | undefined {\n if (!isRecord(value)) return undefined;\n const keys = Object.keys(value).sort();\n const { maxAnswers, idleSeconds, maxAnswerWaitSeconds } = value;\n if (\n keys.length !== FOLLOW_UP_KEYS.length ||\n keys.some((key, at) => key !== FOLLOW_UP_KEYS[at]) ||\n !isWholeBetween(maxAnswers, MAX_FOLLOW_UP_ANSWERS) ||\n !isWholeBetween(idleSeconds, MAX_FOLLOW_UP_SECONDS) ||\n !isWholeBetween(maxAnswerWaitSeconds, MAX_FOLLOW_UP_SECONDS)\n ) {\n return undefined;\n }\n return { maxAnswers, idleSeconds, maxAnswerWaitSeconds };\n}\n\nfunction readCreated(body: unknown): AvatarCreateResult {\n if (!isRecord(body)) return FAILED;\n const { sessionId, endSecret } = body;\n if (\n typeof sessionId !== \"string\" ||\n !SESSION_ID.test(sessionId) ||\n typeof endSecret !== \"string\" ||\n !END_SECRET.test(endSecret)\n ) {\n return FAILED;\n }\n const unusable = { kind: \"unusable\", sessionId, endSecret } as const;\n const { state, join, captions } = body;\n const endsAt =\n typeof body.endsAt === \"string\" ? Date.parse(body.endsAt) : NaN;\n if (\n state !== \"pending\" ||\n !Number.isFinite(endsAt) ||\n !isRecord(join) ||\n !isRecord(captions)\n ) {\n return unusable;\n }\n const { livekitUrl, participantToken, workerIdentity } = join;\n const { locale, text } = captions;\n if (\n typeof livekitUrl !== \"string\" ||\n !livekitUrl.startsWith(\"wss://\") ||\n typeof participantToken !== \"string\" ||\n participantToken === \"\" ||\n typeof workerIdentity !== \"string\" ||\n workerIdentity === \"\" ||\n typeof locale !== \"string\" ||\n typeof text !== \"string\"\n ) {\n return unusable;\n }\n const followUps = readFollowUps(body.followUps);\n return {\n kind: \"created\",\n session: {\n sessionId,\n endSecret,\n endsAt,\n join: { livekitUrl, participantToken, workerIdentity },\n captions: { locale, text },\n excerpt: body.excerpt === true,\n ...(followUps === undefined ? {} : { followUps }),\n },\n };\n}\n\n/**\n * Read a create answer: its HTTP status and its parsed JSON body (or null).\n *\n * - 201: the session, or `unusable` when its fields cannot be used (the browser then ends it).\n * - `busy`, `limits`, `region`, `locale`, `paused`, `not_eligible`, `answer_claimed`: a refusal the tab explains.\n * - `consent`: the consent version moved on.\n * - Any other 401, 403, 404 or 405 (`untrusted_caller`, `bot_check`, `site`, `invalid_route`, `method_not_allowed`):\n * inert, as if there were no live avatar here.\n * - Anything else (`invalid_request`, `conflict`, `idempotency_mismatch`, `unavailable`, a gateway error page):\n * failed.\n */\nexport function readCreate(status: number, body: unknown): AvatarCreateResult {\n if (status === 201) return readCreated(body);\n const code = errorCode(body);\n if (code !== null) {\n const refusal = CREATE_REFUSALS.get(code);\n if (refusal !== undefined) return { kind: \"refused\", reason: refusal };\n if (code === \"consent\") return { kind: \"consent\" };\n }\n if (status === 401 || status === 403 || status === 404 || status === 405) {\n return INERT;\n }\n return FAILED;\n}\n\n/**\n * An answer's body as JSON, or null when it is not JSON or cannot be read (cut off on the way). The status still says\n * what the answer was: a create's 201 without a readable body is `failed` (no secret to end it with), a 404 without one\n * is still `inert`.\n */\nasync function readJson(response: Response): Promise<unknown> {\n try {\n return (await response.json()) as unknown;\n } catch {\n return null;\n }\n}\n\n/** An abort signal for `timeoutMs`, also aborted with `outer`; `done` clears its timer. */\nfunction deadline(\n timeoutMs: number,\n outer?: AbortSignal,\n): { signal: AbortSignal; done: () => void } {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const onOuter = () => controller.abort();\n if (outer?.aborted) controller.abort();\n else outer?.addEventListener(\"abort\", onOuter, { once: true });\n return {\n signal: controller.signal,\n done: () => {\n clearTimeout(timer);\n outer?.removeEventListener(\"abort\", onOuter);\n },\n };\n}\n\nexport interface AvatarRequestTarget {\n /** {@link avatarApiBase} of the SDK's gateway. */\n base: string;\n /** Headers every request carries: the alpha gateway's access headers, and nothing on production. */\n headers: Readonly<Record<string, string>>;\n}\n\n/** What an availability request names: the gateway, the site and the locale, and an abort of its own. */\nexport type AvatarAvailabilityTarget = AvatarRequestTarget & {\n site: string;\n locale: string;\n signal?: AbortSignal;\n};\n\n/** Ask whether the live avatar is offered for `site` in `locale`. Never throws: a failure is `inert`. */\nexport async function requestAvailability(\n target: AvatarAvailabilityTarget,\n): Promise<AvatarAvailability> {\n try {\n return await requestAvailabilityAnswer(target);\n } catch {\n return INERT;\n }\n}\n\n/**\n * {@link requestAvailability}, except that a request that gets no answer (a network or CORS failure, an abort, nothing\n * by its deadline) rejects instead of being `inert`. For the Avatar tab's mic (BOFF-9797 Stage C), which must tell an\n * answer that offers it nothing (the mic goes for the page) from no answer at all (the press says to try again). An\n * answer, whatever it says, is read as {@link requestAvailability} reads it.\n */\nexport async function requestAvailabilityAnswer(\n target: AvatarAvailabilityTarget,\n): Promise<AvatarAvailability> {\n if (!isAvatarSite(target.site) || !LOCALE.test(target.locale)) return INERT;\n const query = new URLSearchParams({\n site: target.site,\n locale: target.locale,\n });\n const timer = deadline(AVAILABILITY_TIMEOUT_MS, target.signal);\n try {\n const response = await fetch(`${target.base}/availability?${query}`, {\n method: \"GET\",\n credentials: \"omit\",\n cache: \"no-store\",\n headers: { ...target.headers },\n signal: timer.signal,\n });\n return readAvailability(response.status, await readJson(response));\n } finally {\n timer.done();\n }\n}\n\n/**\n * Create a session. `botToken` is the bot check's token, for the gateway alone, and is sent only when there is one: a\n * server that runs no bot check gets no `x-web-avatar-bot-token` header. Never throws, and never retries: the bot\n * check's token is good for one create, and a second create could be a second session to pay for.\n *\n * - **An answer** is read as the contract says ({@link readCreate}): a 401, 403, 404 or 405 is still `inert`.\n * - **No answer is `failed`, never `inert`.** Once this is called the request may have reached the gateway, and the\n * server may have created the session and be paying for it, with only its answer lost: a network failure, a body\n * cut off, a request held up past {@link CREATE_TIMEOUT_MS}. The Avatar tab then says the live avatar couldn't\n * start, never that there is none.\n * - **It settles by its deadline, whatever the network does.** The deadline is a timer raced against the request: a\n * fetch that does not settle (one held by something between the page and the network) still leaves this `failed`\n * then. A `failed` past the deadline says nothing about whether a session was created.\n * - **Only a request with no answer yet is aborted at the deadline.** An answer whose status is in by then is read to\n * its end, however long its body takes, for `onLate`: cut off, a 201 is a session made with its secret lost. A\n * request aborted with no answer yet is lost the same way where the browser honours the abort (its fetch rejects,\n * and `onLate` has only `failed`): a session the server made for it runs until the server's own deadlines end it.\n * - **An answer that comes past the deadline all the same** goes to `onLate`, and nowhere else. A session it created\n * is the caller's to end at once with its secret ({@link sendEnd}), never to join: the visitor has been told it\n * couldn't start.\n */\nexport function requestCreate(\n target: AvatarRequestTarget & {\n body: AvatarCreateBody;\n idempotencyKey: string;\n botToken?: string;\n onLate?: (result: AvatarCreateResult) => void;\n },\n): Promise<AvatarCreateResult> {\n const { body } = target;\n // Exactly the contract's six fields, in its order: nothing else of the page's goes along.\n const payload = JSON.stringify({\n site: body.site,\n locale: body.locale,\n conversationToken: body.conversationToken,\n messageId: body.messageId,\n consentVersion: body.consentVersion,\n manifestVersion: body.manifestVersion,\n });\n const controller = new AbortController();\n // Whether the answer has begun: its status is in, and its body is on its way.\n let answered = false;\n const answer = (async (): Promise<AvatarCreateResult> => {\n try {\n const response = await fetch(`${target.base}/sessions`, {\n method: \"POST\",\n credentials: \"omit\",\n cache: \"no-store\",\n headers: {\n ...target.headers,\n \"Content-Type\": \"application/json\",\n \"Idempotency-Key\": target.idempotencyKey,\n ...(target.botToken === undefined\n ? {}\n : { \"x-web-avatar-bot-token\": target.botToken }),\n },\n body: payload,\n signal: controller.signal,\n });\n answered = true;\n return readCreate(response.status, await readJson(response));\n } catch {\n return FAILED;\n }\n })();\n return new Promise<AvatarCreateResult>((resolve) => {\n let late = false;\n const timer = setTimeout(() => {\n late = true;\n // The same signal cuts off the body: an answer that has begun is left to finish, for `onLate`.\n if (!answered) controller.abort();\n resolve(FAILED);\n }, CREATE_TIMEOUT_MS);\n void answer.then((result) => {\n if (late) {\n target.onLate?.(result);\n return;\n }\n clearTimeout(timer);\n resolve(result);\n });\n });\n}\n\n/**\n * Ask the server to end a session, without waiting for it: a `keepalive` request, sent in this same tick, so it still\n * goes when the page is being hidden or unloaded. The server ends the session on its own deadlines whether or not this\n * arrives.\n *\n * **A simple CORS request.** The body is a plain string and this sets no `Content-Type`, so the browser sends it as\n * `text/plain;charset=UTF-8`: a type the gateway's end route reads as JSON for exactly this reason. The session id is\n * in the URL, so a preflight could never be answered from the browser's cache, and one that has to complete while the\n * page unloads may never finish. On production nothing else is added, so no preflight is made. (On the alpha gateway\n * hosts the Access headers in `target.headers` are custom headers, which do bring a preflight there: see the README.)\n */\nexport function sendEnd(\n target: AvatarRequestTarget & {\n sessionId: string;\n secret: string;\n reason: AvatarEndReason;\n },\n): void {\n try {\n void fetch(\n `${target.base}/sessions/${encodeURIComponent(target.sessionId)}/end`,\n {\n method: \"POST\",\n keepalive: true,\n credentials: \"omit\",\n cache: \"no-store\",\n headers: { ...target.headers },\n body: JSON.stringify({ secret: target.secret, reason: target.reason }),\n },\n ).catch(() => undefined);\n } catch {\n // No fetch at all: the server's own deadlines end the session.\n }\n}\n\n/** What a turn tells the session (Stage D): two activity marks, an answer to read, or an interrupt. */\nexport type AvatarTurnKind = \"asking\" | \"listening\" | \"answer\" | \"interrupt\";\n\n/** Why the server does not read a later answer (Stage D): the answer stays in Chat, and the tab says why in a line. */\nexport type AvatarTurnRefusal =\n | \"no_time\"\n | \"max_answers\"\n | \"not_eligible\"\n | \"answer_claimed\"\n | \"limits\"\n | \"paused\"\n | \"busy\";\n\nexport type AvatarTurnResult =\n /** An answer the server reads: its captions, and whether only its first part is spoken (as a 201's `excerpt`). */\n | {\n kind: \"accepted\";\n captions: { locale: string; text: string };\n excerpt: boolean;\n }\n /** A mark or an interrupt the server took. */\n | { kind: \"ok\" }\n /**\n * Not read. `retryAfterSeconds` where the refusal names when to ask again (a `busy` answer: the session reads one at a\n * time, and judges afresh a refusal that took nothing).\n */\n | { kind: \"refused\"; reason: AvatarTurnRefusal; retryAfterSeconds?: number }\n /** No such session for this secret, or no turn route (404): no turn will work for this session. */\n | { kind: \"gone\" }\n /**\n * Anything else. `lost` where the request may have been served with only its answer lost: no answer came at all (a\n * network failure, the deadline), a 200 whose body cannot be read, or a server error. Asked again with the same\n * `idempotencyKey`, an answer gets what its first request got, and is never synthesized twice.\n */\n | { kind: \"failed\"; lost: boolean };\n\nconst TURN_REFUSALS: ReadonlyMap<string, AvatarTurnRefusal> = new Map<\n string,\n AvatarTurnRefusal\n>([\n [\"no_time\", \"no_time\"],\n [\"max_answers\", \"max_answers\"],\n [\"not_eligible\", \"not_eligible\"],\n [\"answer_claimed\", \"answer_claimed\"],\n [\"limits\", \"limits\"],\n [\"paused\", \"paused\"],\n [\"busy\", \"busy\"],\n]);\n\n/** The longest wait a turn's refusal may name before asking again, in seconds: past any session. */\nconst MAX_TURN_RETRY_AFTER_SECONDS = 600;\n\n/** A refusal's `error.retryAfterSeconds`: a whole number of seconds from one, or undefined. */\nfunction retryAfterOf(body: unknown): number | undefined {\n if (!isRecord(body) || !isRecord(body.error)) return undefined;\n const { retryAfterSeconds } = body.error;\n return isWholeBetween(retryAfterSeconds, MAX_TURN_RETRY_AFTER_SECONDS)\n ? retryAfterSeconds\n : undefined;\n}\n\n/** A turn's idempotency key: within what the gateway and the avatar service both take (a UUID fits). */\nconst TURN_KEY = /^[A-Za-z0-9_-]{8,64}$/;\n\nconst LOST = { kind: \"failed\", lost: true } as const;\nconst TURN_FAILED = { kind: \"failed\", lost: false } as const;\n\n/** An answer's 200: `{accepted: true, captions: {locale, text}, excerpt}`. */\nfunction readAccepted(body: unknown): AvatarTurnResult {\n if (!isRecord(body) || body.accepted !== true || !isRecord(body.captions)) {\n return LOST;\n }\n const { locale, text } = body.captions;\n if (typeof locale !== \"string\" || typeof text !== \"string\") return LOST;\n return {\n kind: \"accepted\",\n captions: { locale, text },\n excerpt: body.excerpt === true,\n };\n}\n\n/**\n * Read a turn's answer (Stage D): its kind, its HTTP status and its parsed JSON body (or null).\n *\n * - 200: an answer's `{accepted: true, captions, excerpt}`, or a mark's or an interrupt's `{ok: true}`.\n * - `no_time`, `max_answers`, `not_eligible`, `answer_claimed`, `limits`, `paused`, `busy`: a refusal the tab explains,\n * with its `retryAfterSeconds` where it names one.\n * - 404 (`not_found`, `invalid_route`): `gone`.\n * - Anything else: `failed`, `lost` for a server error (5xx) and for a 200 that cannot be read.\n */\nexport function readTurn(\n kind: AvatarTurnKind,\n status: number,\n body: unknown,\n): AvatarTurnResult {\n if (status === 200) {\n if (kind === \"answer\") return readAccepted(body);\n return isRecord(body) && body.ok === true ? { kind: \"ok\" } : LOST;\n }\n const code = errorCode(body);\n const refusal = code === null ? undefined : TURN_REFUSALS.get(code);\n if (refusal !== undefined) {\n const retryAfterSeconds = retryAfterOf(body);\n return retryAfterSeconds === undefined\n ? { kind: \"refused\", reason: refusal }\n : { kind: \"refused\", reason: refusal, retryAfterSeconds };\n }\n if (status === 404) return { kind: \"gone\" };\n return status >= 500 ? LOST : TURN_FAILED;\n}\n\n/**\n * Tell a session what the visitor does next (Stage D, only for a session whose 201 offers `followUps`): `asking` (a\n * question sent from the Avatar tab, its answer being written) and `listening` (the tab's mic recording) defer the\n * server's idle end; `answer` asks the session to read `messageId`, the completed answer to that question; `interrupt`\n * stops the answer being spoken and keeps the session. Authenticated by the session's end secret, which goes in the body\n * and nowhere else. Never throws, and never asks twice by itself: the caller may ask an answer again with the same\n * `idempotencyKey` (a `lost` failure), and the server then answers what it answered the first time.\n *\n * - **A simple CORS request**, as {@link sendEnd} is: a plain string body and no `Content-Type` of its own, which the\n * gateway reads as JSON. Each request carries a fresh `nonce`.\n * - **It settles by its deadline** (past the gateway's own), whatever the network does: a timer raced against the\n * request, as for a create.\n */\nexport function requestTurn(\n target: AvatarRequestTarget & {\n sessionId: string;\n secret: string;\n kind: AvatarTurnKind;\n /** `answer` only, and required for it: the answer to read. */\n messageId?: string;\n /** `answer` only: the same key for the same answer asked again. */\n idempotencyKey?: string;\n },\n): Promise<AvatarTurnResult> {\n const { kind, messageId, idempotencyKey } = target;\n const nonce = newIdempotencyKey();\n if (\n !SESSION_ID.test(target.sessionId) ||\n !END_SECRET.test(target.secret) ||\n nonce === null ||\n (kind === \"answer\"\n ? messageId === undefined || !MESSAGE_ID.test(messageId)\n : messageId !== undefined || idempotencyKey !== undefined) ||\n (idempotencyKey !== undefined && !TURN_KEY.test(idempotencyKey))\n ) {\n return Promise.resolve(TURN_FAILED);\n }\n // The contract's fields, in its order: the session's secret, and nothing of the conversation.\n const payload = JSON.stringify({\n secret: target.secret,\n kind,\n nonce,\n ...(messageId === undefined ? {} : { messageId }),\n ...(idempotencyKey === undefined ? {} : { idempotencyKey }),\n });\n const controller = new AbortController();\n const answer = (async (): Promise<AvatarTurnResult> => {\n try {\n const response = await fetch(\n `${target.base}/sessions/${encodeURIComponent(target.sessionId)}/turn`,\n {\n method: \"POST\",\n credentials: \"omit\",\n cache: \"no-store\",\n headers: { ...target.headers },\n body: payload,\n signal: controller.signal,\n },\n );\n return readTurn(kind, response.status, await readJson(response));\n } catch {\n return LOST;\n }\n })();\n return new Promise<AvatarTurnResult>((resolve) => {\n const timer = setTimeout(\n () => {\n controller.abort();\n resolve(LOST);\n },\n kind === \"answer\" ? TURN_ANSWER_TIMEOUT_MS : TURN_TIMEOUT_MS,\n );\n void answer.then((result) => {\n clearTimeout(timer);\n resolve(result);\n });\n });\n}\n\n/** What scopes the bot check's binding to this contract, and its version. */\nconst BOT_BINDING_PREFIX = \"boff-web-avatar-cdata/v1\";\n\n/** The browser's WebCrypto `subtle`, or null where it has none to offer (a page that is not a secure context). */\nfunction webCryptoSubtle(): SubtleCrypto | null {\n const subtle = globalThis.crypto?.subtle;\n return typeof subtle?.digest === \"function\" ? subtle : null;\n}\n\n/**\n * Whether this browser can make the bot check's binding ({@link avatarBotBinding}): it needs WebCrypto's SHA-256.\n * Without it no live avatar can start here, so a start asks first, before it loads anything for one.\n */\nexport function canBindBotCheck(): boolean {\n return webCryptoSubtle() !== null;\n}\n\nfunction base64UrlNoPad(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n/**\n * The value the bot check is bound to, for Turnstile's `cData` (web API contract v1.1, additive):\n *\n * base64url_nopad( SHA-256( UTF-8( \"boff-web-avatar-cdata/v1\\n\" + site + \"\\n\" + locale + \"\\n\"\n * + conversationToken + \"\\n\" + messageId ) ) )\n *\n * The gateway recomputes it from the create body and checks it against the one Cloudflare returns with the verified\n * token, so a token minted for one request cannot be used for another. It must be made from the very values the create\n * body will carry, and before the widget is rendered: the caller builds the body once and hands the same one to this\n * and to {@link requestCreate}.\n *\n * Rejects where the browser has no WebCrypto (a page that is not a secure context): the bot check cannot be bound\n * there, so the live avatar does not start. {@link canBindBotCheck} says so beforehand, so that nothing is loaded for\n * a start that cannot happen.\n */\nexport async function avatarBotBinding(\n values: Pick<\n AvatarCreateBody,\n \"site\" | \"locale\" | \"conversationToken\" | \"messageId\"\n >,\n): Promise<string> {\n const subtle = webCryptoSubtle();\n if (subtle === null) {\n throw new Error(\"The bot check cannot be bound here: no WebCrypto.\");\n }\n const text = [\n BOT_BINDING_PREFIX,\n values.site,\n values.locale,\n values.conversationToken,\n values.messageId,\n ].join(\"\\n\");\n const digest = await subtle.digest(\"SHA-256\", new TextEncoder().encode(text));\n return base64UrlNoPad(new Uint8Array(digest));\n}\n\n/** A random UUID v4 for `Idempotency-Key`, or null where the browser has no cryptographic random source. */\nexport function newIdempotencyKey(): string | null {\n const crypto = globalThis.crypto;\n if (typeof crypto?.randomUUID === \"function\") return crypto.randomUUID();\n if (typeof crypto?.getRandomValues !== \"function\") return null;\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x40;\n bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80;\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\n \"\",\n );\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n","/**\n * BOFF-9797. The words of the live avatar's Avatar tab, in the six product locales, bundled like the rest of\n * Explore's copy (see `explore-i18n.ts` for why a marketing site bundles its strings).\n *\n * ## Review\n *\n * English is the reviewed copy. The other five locales are drafts awaiting translation review: each is a complete\n * object (a missing key is a type error), but the live avatar runs only in a locale that\n * {@link isAvatarLiveLocaleReviewed} lists. In any other, the Avatar tab stays as it was before the live avatar and\n * asks the server nothing. A locale is added there (in `explore-avatar-live-config.ts`) once its strings, and its\n * consent copy, have been reviewed.\n *\n * ## Consent\n *\n * The consent card's copy is versioned: the server names the version it will accept (`consentVersion`), and the panel\n * shows a consent card only when it holds copy written for exactly that version in the visitor's locale\n * ({@link avatarConsentCopy}). A version the SDK does not know, or a locale without reviewed copy for it, offers no\n * consent card at all, so a visitor never agrees to words other than the ones the server records. Each version also says\n * which bot check its words describe ({@link AvatarConsentCopy.botCheck}), and the card is shown only where the server\n * runs that one.\n *\n * ## The mic\n *\n * The Avatar tab's mic (Stage C) has words of its own, English only ({@link avatarMicStrings}), and a notice shown on\n * its first tap, versioned like the consent copy ({@link avatarMicNotice}): the SDK shows\n * {@link AVATAR_MIC_NOTICE_VERSION}, names it in every press, and the speech service takes the press only when that is\n * the version it records.\n */\n\nimport { isAvatarLiveLocaleReviewed } from \"./explore-avatar-live-config\";\n\nimport type { AvatarBotCheck, AvatarQuestions } from \"./explore-avatar-api\";\nimport type { ExploreLocale } from \"./explore-i18n\";\n\n// The reviewed locales are decided in `explore-avatar-live-config.ts`, which the panel reads without loading this file.\nexport { isAvatarLiveLocaleReviewed };\n\nexport interface AvatarLiveStrings {\n /** Status while the tab asks whether the live avatar is offered. Announced politely. */\n checking: string;\n /** No answer to read yet. */\n needsAnswer: string;\n needsAnswerDetail: string;\n /**\n * The conversation can never be read: its first answer failed, it has gone past the first question and answer, or\n * the answer is too old. Only a new chat can. The headline (announced politely), then the explanation, then a New\n * chat button. The avatar service reads exactly one answer: the first, completed, to a suggested question, within\n * fifteen minutes.\n */\n startNewChat: string;\n startNewChatDetail: string;\n /** The consent card's buttons. */\n start: string;\n notNow: string;\n /** After the privacy link, for screen readers: it opens in a new tab. */\n opensInNewTab: string;\n /** Status while the bot check runs. Announced politely. */\n botCheck: string;\n /** Status while the session is created and the room joined. Announced politely. */\n connecting: string;\n /** Status once the avatar's video plays. Announced politely. */\n speaking: string;\n /** Shown over the live video, always: the visitor is watching an AI, not a person. */\n badge: string;\n /** The video's accessible name. */\n video: string;\n /** The captions' accessible name. */\n captions: string;\n /** Before the countdown, which is never announced. */\n timeLeft: string;\n stop: string;\n /** Where the browser holds sound back until a tap (Safari, iOS). */\n tapForSound: string;\n /**\n * How a session ended. Announced politely. `finished` is \"the server closed the room, or the session's time ran out\n * with the room still open\": the browser cannot tell the avatar reading to the end from a server-side stop or a\n * hand-over, so it says only that the live avatar has ended.\n */\n finished: string;\n stopped: string;\n failed: string;\n interrupted: string;\n /** Under the captions and after a session: the answer itself is still in the conversation. */\n answerInChat: string;\n /**\n * In the status line while the avatar speaks, in place of `speaking`, when the server speaks only the first part of\n * the answer because the whole of it does not fit the session (the 201's `excerpt`, contract v1.4, Stage B).\n */\n excerpt: string;\n backToChat: string;\n /**\n * The refusals, one short sentence each, with no numbers in them (a number is spelled out). `notEligible` is the one\n * with a second sentence: it comes with a New chat button, and says what to do with it.\n */\n busy: string;\n limits: string;\n region: string;\n locale: string;\n paused: string;\n notEligible: string;\n answerClaimed: string;\n /**\n * The Avatar tab's own question box (BOFF-9797, contract v1.3): shown only where the server reads the answer to a\n * question the visitor typed too (`questions: \"any\"`), with consent copy written for that. The headline over the\n * suggested questions, the box's accessible name, its placeholder and the line under it, always visible with the box.\n */\n askHeadline: string;\n askLabel: string;\n askPlaceholder: string;\n askFooter: string;\n /** A file pasted or dropped on the box: the box takes text only. */\n askNoFiles: string;\n /** Why Send cannot be pressed: an answer is on its way, or the chat cannot take a question. */\n askBusy: string;\n askUnavailable: string;\n /** While the answer is written, when the chat reports no progress line of its own. Announced politely. */\n gettingAnswer: string;\n /**\n * The consent card's button while the answer is still being written: pressed, the avatar starts once the answer is\n * ready (`armed`), unless the visitor presses `cancel` or the start is called off (`armedCancelled`: the tab left,\n * the page hidden, the chat or the page changed, and the like).\n */\n startWhenReady: string;\n armed: string;\n cancel: string;\n armedCancelled: string;\n /** A first answer the avatar does not read (it fails the speech checks this browser can make): it stays in Chat. */\n notSpoken: string;\n /** The first answer failed. */\n answerFailed: string;\n /** Not now, under `any`: the card is offered again, while the answer is fresh, when the tab opens again. */\n declined: string;\n /** An answer to a question that was not the first of a new chat asked in this tab. */\n askHere: string;\n /**\n * Where the conversation can no longer be read: the button that starts a new chat for the avatar (the chat's own New\n * chat, staying on the Avatar tab), the note beside it, and the line once it has.\n */\n newChatForAvatar: string;\n newChatNote: string;\n newChatStarted: string;\n /** The button to the Chat tab, where the answer and its sources are. */\n readInChat: string;\n /** Over the box on the day this browser has had a live session. No number: the limits are the server's. */\n usedToday: string;\n /**\n * Under `any`, in place of `needsAnswer` (the box's description), `startNewChatDetail` and `notEligible`, which\n * speak of suggested questions only.\n */\n needsAnswerAny: string;\n startNewChatDetailAny: string;\n notEligibleAny: string;\n /**\n * A session that reads the answers after the first (Stage D, only where its create offers them and the consent the\n * visitor agreed to describes them). `followUpIdle` is the status line while it waits for the next question; the\n * others say, in a line each, why an answer was not read (it stays in Chat): no time left in the session, its answers\n * used up (`followUpMaxAnswers`, refused; `followUpLast`, once the last one it could read has played), the limits, a\n * pause, or anything else. No numbers: they are spelled out.\n */\n followUpIdle: string;\n followUpNoTime: string;\n followUpMaxAnswers: string;\n followUpLast: string;\n followUpLimits: string;\n followUpPaused: string;\n followUpUnread: string;\n}\n\nconst EN: AvatarLiveStrings = {\n checking: \"Checking whether the live avatar is available…\",\n needsAnswer: \"Choose a suggested question in Chat first.\",\n needsAnswerDetail: \"The avatar can read only the first answer aloud.\",\n startNewChat: \"Start a new chat to use the avatar.\",\n startNewChatDetail:\n \"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.\",\n start: \"Start live avatar\",\n notNow: \"Not now\",\n opensInNewTab: \"(opens in a new tab)\",\n botCheck: \"Checking your browser…\",\n connecting: \"Connecting to the live avatar…\",\n speaking: \"The avatar is speaking.\",\n badge: \"AI avatar · not a real person\",\n video: \"Live AI avatar video\",\n captions: \"Captions\",\n timeLeft: \"Time left\",\n stop: \"Stop\",\n tapForSound: \"Tap to turn on sound\",\n finished: \"The live avatar has ended.\",\n stopped: \"You stopped the avatar.\",\n failed: \"The live avatar couldn't start.\",\n interrupted: \"The live avatar stopped early.\",\n answerInChat: \"The full answer is in Chat.\",\n excerpt:\n \"The avatar reads the first part of this answer. The full answer is in Chat.\",\n backToChat: \"Back to Chat\",\n busy: \"The live avatar is busy right now. Please try again in a few minutes.\",\n limits:\n \"The live avatar has reached its limit for now. Please try again later.\",\n region: \"The live avatar isn't offered in your region yet.\",\n locale: \"The live avatar isn't offered in this language yet.\",\n paused: \"The live avatar is paused right now.\",\n notEligible:\n \"The avatar reads the first answer to a suggested question, within fifteen minutes. Start a new chat and choose a suggested question.\",\n answerClaimed: \"The avatar has already read this answer.\",\n askHeadline: \"Ask a question, and the avatar reads the answer aloud.\",\n askLabel: \"Question for the avatar\",\n askPlaceholder: \"Ask the avatar…\",\n askFooter:\n \"Answers are AI-generated and can be wrong. Don't include personal details.\",\n askNoFiles: \"To attach files, use Chat.\",\n askBusy: \"You can ask when the current answer is ready.\",\n askUnavailable: \"Chat isn't available right now.\",\n gettingAnswer: \"Getting the answer…\",\n startWhenReady: \"Start when ready\",\n armed: \"The avatar will start when the answer is ready.\",\n cancel: \"Cancel\",\n armedCancelled:\n \"The avatar didn't start. Press Start when ready to try again.\",\n notSpoken:\n \"This answer stays in Chat as text. The avatar reads only answers that pass its speech checks.\",\n answerFailed: \"The assistant couldn't answer. Try asking again.\",\n declined: \"No problem. The answer is in Chat.\",\n askHere: \"To hear an answer, ask it here.\",\n newChatForAvatar: \"New chat for the avatar\",\n newChatNote: \"Your current chat stays in History.\",\n newChatStarted: \"Started a new chat for the avatar.\",\n readInChat: \"Read the answer and sources in Chat\",\n usedToday:\n \"You've had today's avatar session. Answers will show here as text.\",\n needsAnswerAny: \"Ask a question here, and the avatar reads the answer aloud.\",\n startNewChatDetailAny:\n \"The avatar reads aloud only the first answer in a new chat started in the Avatar tab, provided it passes the speech checks.\",\n notEligibleAny:\n \"The avatar can't read this answer aloud. The answer and sources are in Chat.\",\n followUpIdle:\n \"The avatar ends after about thirty seconds without a question.\",\n followUpNoTime:\n \"There isn't enough time left in this session to read that answer. It's in Chat.\",\n followUpMaxAnswers:\n \"The avatar has read all the answers it can in this session. This one is in Chat.\",\n followUpLast: \"That was the last answer the avatar can read in this session.\",\n followUpLimits:\n \"The live avatar has reached its limit for now. This answer is in Chat.\",\n followUpPaused:\n \"The live avatar is paused right now. This answer is in Chat.\",\n followUpUnread: \"The avatar couldn't read that answer. It's in Chat.\",\n};\n\n// TRANSLATION REVIEW PENDING (BOFF-9797): a draft, not yet reviewed. Not shown until \"zh\" is in REVIEWED.\nconst ZH: AvatarLiveStrings = {\n checking: \"正在检查实时虚拟形象是否可用…\",\n needsAnswer: \"请先在聊天中选择一个推荐问题。\",\n needsAnswerDetail: \"虚拟形象只能朗读第一个回答。\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n startNewChat: \"请开始新的聊天,再使用虚拟形象。\",\n startNewChatDetail:\n \"虚拟形象只朗读一次聊天中的第一个回答,且仅限推荐问题的回答、在十五分钟内。请开始新的聊天,并选择一个推荐问题。\",\n start: \"启动实时虚拟形象\",\n notNow: \"暂不\",\n opensInNewTab: \"(在新标签页中打开)\",\n botCheck: \"正在检查您的浏览器…\",\n connecting: \"正在连接实时虚拟形象…\",\n speaking: \"虚拟形象正在讲话。\",\n badge: \"AI 虚拟形象 · 不是真人\",\n video: \"实时 AI 虚拟形象视频\",\n captions: \"字幕\",\n timeLeft: \"剩余时间\",\n stop: \"停止\",\n tapForSound: \"点按以开启声音\",\n finished: \"实时虚拟形象已结束。\",\n stopped: \"您已停止虚拟形象。\",\n failed: \"实时虚拟形象无法启动。\",\n interrupted: \"实时虚拟形象提前停止了。\",\n answerInChat: \"完整回答在聊天中。\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the note for a part-read answer (Stage B).\n excerpt: \"虚拟形象朗读这个回答的第一部分。完整回答在聊天中。\",\n backToChat: \"返回聊天\",\n busy: \"实时虚拟形象目前繁忙,请几分钟后再试。\",\n limits: \"实时虚拟形象暂时已达到使用上限,请稍后再试。\",\n region: \"您所在的地区暂不提供实时虚拟形象。\",\n locale: \"此语言暂不提供实时虚拟形象。\",\n paused: \"实时虚拟形象目前已暂停。\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n notEligible:\n \"虚拟形象只朗读推荐问题的第一个回答,且须在十五分钟内。请开始新的聊天,并选择一个推荐问题。\",\n answerClaimed: \"虚拟形象已经朗读过这个回答。\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.\n askHeadline: \"提出问题,虚拟形象会朗读回答。\",\n askLabel: \"向虚拟形象提的问题\",\n askPlaceholder: \"向虚拟形象提问…\",\n askFooter: \"回答由 AI 生成,可能有误。请勿包含个人信息。\",\n askNoFiles: \"如需附加文件,请使用聊天。\",\n askBusy: \"当前回答准备好后即可提问。\",\n askUnavailable: \"聊天目前不可用。\",\n gettingAnswer: \"正在获取回答…\",\n startWhenReady: \"准备好后开始\",\n armed: \"回答准备好后,虚拟形象将开始。\",\n cancel: \"取消\",\n armedCancelled: \"虚拟形象未启动。可再次按“准备好后开始”。\",\n notSpoken:\n \"此回答以文字形式保留在聊天中。虚拟形象只朗读通过其语音检查的回答。\",\n answerFailed: \"助手无法回答。请重新提问。\",\n declined: \"没关系。回答在聊天中。\",\n askHere: \"如需听取回答,请在这里提问。\",\n newChatForAvatar: \"为虚拟形象开始新聊天\",\n newChatNote: \"当前聊天会保留在历史记录中。\",\n newChatStarted: \"已为虚拟形象开始新的聊天。\",\n readInChat: \"在聊天中查看回答和来源\",\n usedToday: \"您今天已使用过虚拟形象。回答将以文字显示在这里。\",\n needsAnswerAny: \"在这里提问,虚拟形象会朗读回答。\",\n startNewChatDetailAny:\n \"虚拟形象只朗读在“虚拟形象”标签页中开始的新聊天的第一个回答,且该回答须通过语音检查。\",\n notEligibleAny: \"虚拟形象无法朗读此回答。回答和来源在聊天中。\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the lines of a session that reads the answers after the first\n // (Stage D).\n followUpIdle: \"如果约三十秒内没有新问题,虚拟形象就会结束。\",\n followUpNoTime: \"本次会话剩余时间不足,无法朗读该回答。回答在聊天中。\",\n followUpMaxAnswers:\n \"虚拟形象已朗读本次会话可朗读的全部回答。此回答在聊天中。\",\n followUpLast: \"这是虚拟形象在本次会话中可朗读的最后一个回答。\",\n followUpLimits: \"实时虚拟形象暂时已达到使用上限。此回答在聊天中。\",\n followUpPaused: \"实时虚拟形象目前已暂停。此回答在聊天中。\",\n followUpUnread: \"虚拟形象无法朗读该回答。回答在聊天中。\",\n};\n\n// TRANSLATION REVIEW PENDING (BOFF-9797): a draft, not yet reviewed. Not shown until \"hi\" is in REVIEWED.\nconst HI: AvatarLiveStrings = {\n checking: \"जाँच हो रही है कि लाइव अवतार उपलब्ध है या नहीं…\",\n needsAnswer: \"पहले चैट में कोई सुझाया गया प्रश्न चुनें।\",\n needsAnswerDetail: \"अवतार केवल पहला उत्तर ज़ोर से पढ़ सकता है।\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n startNewChat: \"अवतार का उपयोग करने के लिए नई चैट शुरू करें।\",\n startNewChatDetail:\n \"अवतार किसी चैट का केवल पहला उत्तर ज़ोर से पढ़ता है, वह भी सुझाए गए प्रश्न का और पंद्रह मिनट के भीतर। नई चैट शुरू करें और कोई सुझाया गया प्रश्न चुनें।\",\n start: \"लाइव अवतार शुरू करें\",\n notNow: \"अभी नहीं\",\n opensInNewTab: \"(नए टैब में खुलता है)\",\n botCheck: \"आपके ब्राउज़र की जाँच हो रही है…\",\n connecting: \"लाइव अवतार से जुड़ रहे हैं…\",\n speaking: \"अवतार बोल रहा है।\",\n badge: \"AI अवतार · असली व्यक्ति नहीं\",\n video: \"लाइव AI अवतार वीडियो\",\n captions: \"कैप्शन\",\n timeLeft: \"बचा हुआ समय\",\n stop: \"रोकें\",\n tapForSound: \"आवाज़ चालू करने के लिए टैप करें\",\n finished: \"लाइव अवतार समाप्त हो गया है।\",\n stopped: \"आपने अवतार को रोक दिया।\",\n failed: \"लाइव अवतार शुरू नहीं हो सका।\",\n interrupted: \"लाइव अवतार बीच में ही रुक गया।\",\n answerInChat: \"पूरा उत्तर चैट में है।\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the note for a part-read answer (Stage B).\n excerpt: \"अवतार इस उत्तर का पहला भाग पढ़ता है। पूरा उत्तर चैट में है।\",\n backToChat: \"चैट पर वापस जाएँ\",\n busy: \"लाइव अवतार अभी व्यस्त है। कृपया कुछ मिनट बाद फिर कोशिश करें।\",\n limits:\n \"लाइव अवतार अभी अपनी सीमा तक पहुँच गया है। कृपया बाद में फिर कोशिश करें।\",\n region: \"आपके क्षेत्र में लाइव अवतार अभी उपलब्ध नहीं है।\",\n locale: \"इस भाषा में लाइव अवतार अभी उपलब्ध नहीं है।\",\n paused: \"लाइव अवतार अभी रुका हुआ है।\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n notEligible:\n \"अवतार सुझाए गए प्रश्न का पहला उत्तर ही पढ़ता है, पंद्रह मिनट के भीतर। नई चैट शुरू करें और कोई सुझाया गया प्रश्न चुनें।\",\n answerClaimed: \"अवतार यह उत्तर पहले ही पढ़ चुका है।\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.\n askHeadline: \"कोई प्रश्न पूछें, और अवतार उसका उत्तर ज़ोर से पढ़ेगा।\",\n askLabel: \"अवतार के लिए प्रश्न\",\n askPlaceholder: \"अवतार से पूछें…\",\n askFooter:\n \"उत्तर AI द्वारा बनाए जाते हैं और गलत हो सकते हैं। निजी जानकारी शामिल न करें।\",\n askNoFiles: \"फ़ाइलें जोड़ने के लिए चैट का उपयोग करें।\",\n askBusy: \"मौजूदा उत्तर तैयार होने पर आप पूछ सकते हैं।\",\n askUnavailable: \"चैट अभी उपलब्ध नहीं है।\",\n gettingAnswer: \"उत्तर लाया जा रहा है…\",\n startWhenReady: \"तैयार होने पर शुरू करें\",\n armed: \"उत्तर तैयार होते ही अवतार शुरू होगा।\",\n cancel: \"रद्द करें\",\n armedCancelled:\n \"अवतार शुरू नहीं हुआ। फिर से कोशिश करने के लिए “तैयार होने पर शुरू करें” दबाएँ।\",\n notSpoken:\n \"यह उत्तर चैट में टेक्स्ट के रूप में रहेगा। अवतार केवल वही उत्तर पढ़ता है जो उसकी वाणी जाँच में पास होते हैं।\",\n answerFailed: \"सहायक उत्तर नहीं दे सका। फिर से पूछकर देखें।\",\n declined: \"कोई बात नहीं। उत्तर चैट में है।\",\n askHere: \"उत्तर सुनने के लिए, यहाँ पूछें।\",\n newChatForAvatar: \"अवतार के लिए नई चैट\",\n newChatNote: \"आपकी मौजूदा चैट इतिहास में रहेगी।\",\n newChatStarted: \"अवतार के लिए नई चैट शुरू की गई।\",\n readInChat: \"उत्तर और स्रोत चैट में पढ़ें\",\n usedToday:\n \"आज का अवतार सत्र आप ले चुके हैं। उत्तर यहाँ टेक्स्ट के रूप में दिखेंगे।\",\n needsAnswerAny: \"यहाँ प्रश्न पूछें, और अवतार उत्तर ज़ोर से पढ़ेगा।\",\n startNewChatDetailAny:\n \"अवतार केवल अवतार टैब में शुरू की गई नई चैट का पहला उत्तर ज़ोर से पढ़ता है, बशर्ते वह वाणी जाँच में पास हो।\",\n notEligibleAny:\n \"अवतार यह उत्तर ज़ोर से नहीं पढ़ सकता। उत्तर और स्रोत चैट में हैं।\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the lines of a session that reads the answers after the first\n // (Stage D).\n followUpIdle:\n \"बिना किसी प्रश्न के लगभग तीस सेकंड बाद अवतार समाप्त हो जाता है।\",\n followUpNoTime:\n \"इस सत्र में वह उत्तर पढ़ने के लिए पर्याप्त समय नहीं बचा है। उत्तर चैट में है।\",\n followUpMaxAnswers:\n \"अवतार इस सत्र में जितने उत्तर पढ़ सकता है, सब पढ़ चुका है। यह उत्तर चैट में है।\",\n followUpLast: \"यह इस सत्र में अवतार द्वारा पढ़ा जा सकने वाला अंतिम उत्तर था।\",\n followUpLimits:\n \"लाइव अवतार अभी अपनी सीमा तक पहुँच गया है। यह उत्तर चैट में है।\",\n followUpPaused: \"लाइव अवतार अभी रुका हुआ है। यह उत्तर चैट में है।\",\n followUpUnread: \"अवतार वह उत्तर नहीं पढ़ सका। उत्तर चैट में है।\",\n};\n\n// TRANSLATION REVIEW PENDING (BOFF-9797): a draft, not yet reviewed. Not shown until \"es\" is in REVIEWED.\nconst ES: AvatarLiveStrings = {\n checking: \"Comprobando si el avatar en vivo está disponible…\",\n needsAnswer: \"Primero elige una pregunta sugerida en el chat.\",\n needsAnswerDetail:\n \"El avatar solo puede leer en voz alta la primera respuesta.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n startNewChat: \"Inicia un chat nuevo para usar el avatar.\",\n startNewChatDetail:\n \"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.\",\n start: \"Iniciar el avatar en vivo\",\n notNow: \"Ahora no\",\n opensInNewTab: \"(se abre en una pestaña nueva)\",\n botCheck: \"Comprobando tu navegador…\",\n connecting: \"Conectando con el avatar en vivo…\",\n speaking: \"El avatar está hablando.\",\n badge: \"Avatar de IA · no es una persona real\",\n video: \"Vídeo del avatar de IA en vivo\",\n captions: \"Subtítulos\",\n timeLeft: \"Tiempo restante\",\n stop: \"Detener\",\n tapForSound: \"Toca para activar el sonido\",\n finished: \"El avatar en vivo ha terminado.\",\n stopped: \"Has detenido el avatar.\",\n failed: \"No se pudo iniciar el avatar en vivo.\",\n interrupted: \"El avatar en vivo se detuvo antes de tiempo.\",\n answerInChat: \"La respuesta completa está en el chat.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the note for a part-read answer (Stage B).\n excerpt:\n \"El avatar lee la primera parte de esta respuesta. La respuesta completa está en el chat.\",\n backToChat: \"Volver al chat\",\n busy: \"El avatar en vivo está ocupado en este momento. Vuelve a intentarlo en unos minutos.\",\n limits:\n \"El avatar en vivo ha alcanzado su límite por ahora. Vuelve a intentarlo más tarde.\",\n region: \"El avatar en vivo aún no está disponible en tu región.\",\n locale: \"El avatar en vivo aún no está disponible en este idioma.\",\n paused: \"El avatar en vivo está en pausa en este momento.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n notEligible:\n \"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.\",\n answerClaimed: \"El avatar ya ha leído esta respuesta.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.\n askHeadline: \"Haz una pregunta y el avatar leerá la respuesta en voz alta.\",\n askLabel: \"Pregunta para el avatar\",\n askPlaceholder: \"Pregunta al avatar…\",\n askFooter:\n \"Las respuestas las genera la IA y pueden contener errores. No incluyas datos personales.\",\n askNoFiles: \"Para adjuntar archivos, usa el chat.\",\n askBusy: \"Podrás preguntar cuando la respuesta actual esté lista.\",\n askUnavailable: \"El chat no está disponible en este momento.\",\n gettingAnswer: \"Obteniendo la respuesta…\",\n startWhenReady: \"Iniciar cuando esté lista\",\n armed: \"El avatar empezará cuando la respuesta esté lista.\",\n cancel: \"Cancelar\",\n armedCancelled:\n \"El avatar no se ha iniciado. Pulsa Iniciar cuando esté lista para volver a intentarlo.\",\n notSpoken:\n \"Esta respuesta se queda en el chat como texto. El avatar solo lee respuestas que superan sus comprobaciones de voz.\",\n answerFailed: \"El asistente no pudo responder. Vuelve a preguntar.\",\n declined: \"De acuerdo. La respuesta está en el chat.\",\n askHere: \"Para escuchar una respuesta, pregunta aquí.\",\n newChatForAvatar: \"Chat nuevo para el avatar\",\n newChatNote: \"Tu chat actual se queda en el historial.\",\n newChatStarted: \"Se ha iniciado un chat nuevo para el avatar.\",\n readInChat: \"Leer la respuesta y las fuentes en el chat\",\n usedToday:\n \"Ya has usado la sesión de avatar de hoy. Las respuestas se mostrarán aquí como texto.\",\n needsAnswerAny:\n \"Haz una pregunta aquí y el avatar leerá la respuesta en voz alta.\",\n startNewChatDetailAny:\n \"El avatar solo lee en voz alta la primera respuesta de un chat nuevo iniciado en la pestaña Avatar, si supera las comprobaciones de voz.\",\n notEligibleAny:\n \"El avatar no puede leer esta respuesta en voz alta. La respuesta y las fuentes están en el chat.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the lines of a session that reads the answers after the first\n // (Stage D).\n followUpIdle: \"El avatar termina tras unos treinta segundos sin preguntas.\",\n followUpNoTime:\n \"No queda tiempo suficiente en esta sesión para leer esa respuesta. Está en el chat.\",\n followUpMaxAnswers:\n \"El avatar ya ha leído todas las respuestas que puede en esta sesión. Esta está en el chat.\",\n followUpLast:\n \"Esa fue la última respuesta que el avatar puede leer en esta sesión.\",\n followUpLimits:\n \"El avatar en vivo ha alcanzado su límite por ahora. Esta respuesta está en el chat.\",\n followUpPaused:\n \"El avatar en vivo está en pausa ahora mismo. Esta respuesta está en el chat.\",\n followUpUnread: \"El avatar no pudo leer esa respuesta. Está en el chat.\",\n};\n\n// TRANSLATION REVIEW PENDING (BOFF-9797): a draft, not yet reviewed, including its right-to-left layout. Not shown\n// until \"ar\" is in REVIEWED.\nconst AR: AvatarLiveStrings = {\n checking: \"جارٍ التحقق من توفر الأفاتار المباشر…\",\n needsAnswer: \"اختر أولًا سؤالًا مقترحًا في الدردشة.\",\n needsAnswerDetail: \"يمكن للأفاتار قراءة الإجابة الأولى فقط بصوت عالٍ.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n startNewChat: \"ابدأ دردشة جديدة لاستخدام الأفاتار.\",\n startNewChatDetail:\n \"يقرأ الأفاتار بصوت عالٍ الإجابة الأولى في الدردشة فقط، إذا كانت إجابة عن سؤال مقترح وخلال خمس عشرة دقيقة. ابدأ دردشة جديدة واختر سؤالًا مقترحًا.\",\n start: \"بدء الأفاتار المباشر\",\n notNow: \"ليس الآن\",\n opensInNewTab: \"(يُفتح في علامة تبويب جديدة)\",\n botCheck: \"جارٍ التحقق من متصفحك…\",\n connecting: \"جارٍ الاتصال بالأفاتار المباشر…\",\n speaking: \"الأفاتار يتحدث الآن.\",\n badge: \"أفاتار بالذكاء الاصطناعي · ليس شخصًا حقيقيًا\",\n video: \"فيديو الأفاتار المباشر بالذكاء الاصطناعي\",\n captions: \"التسميات التوضيحية\",\n timeLeft: \"الوقت المتبقي\",\n stop: \"إيقاف\",\n tapForSound: \"انقر لتشغيل الصوت\",\n finished: \"انتهى الأفاتار المباشر.\",\n stopped: \"لقد أوقفت الأفاتار.\",\n failed: \"تعذّر بدء الأفاتار المباشر.\",\n interrupted: \"توقف الأفاتار المباشر قبل أن ينتهي.\",\n answerInChat: \"الإجابة الكاملة موجودة في الدردشة.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the note for a part-read answer (Stage B).\n excerpt:\n \"يقرأ الأفاتار الجزء الأول من هذه الإجابة. الإجابة الكاملة موجودة في الدردشة.\",\n backToChat: \"العودة إلى الدردشة\",\n busy: \"الأفاتار المباشر مشغول الآن. يُرجى المحاولة مرة أخرى بعد بضع دقائق.\",\n limits: \"بلغ الأفاتار المباشر حدّه في الوقت الحالي. يُرجى المحاولة لاحقًا.\",\n region: \"الأفاتار المباشر غير متاح في منطقتك بعد.\",\n locale: \"الأفاتار المباشر غير متاح بهذه اللغة بعد.\",\n paused: \"الأفاتار المباشر متوقف مؤقتًا الآن.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n notEligible:\n \"يقرأ الأفاتار الإجابة الأولى عن سؤال مقترح، خلال خمس عشرة دقيقة. ابدأ دردشة جديدة واختر سؤالًا مقترحًا.\",\n answerClaimed: \"قرأ الأفاتار هذه الإجابة من قبل.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.\n askHeadline: \"اطرح سؤالًا، وسيقرأ الأفاتار الإجابة بصوت عالٍ.\",\n askLabel: \"سؤال للأفاتار\",\n askPlaceholder: \"اسأل الأفاتار…\",\n askFooter:\n \"الإجابات مُولَّدة بالذكاء الاصطناعي وقد تكون خاطئة. لا تضمّن بيانات شخصية.\",\n askNoFiles: \"لإرفاق ملفات، استخدم الدردشة.\",\n askBusy: \"يمكنك السؤال عندما تصبح الإجابة الحالية جاهزة.\",\n askUnavailable: \"الدردشة غير متاحة الآن.\",\n gettingAnswer: \"جارٍ الحصول على الإجابة…\",\n startWhenReady: \"البدء عند الجاهزية\",\n armed: \"سيبدأ الأفاتار عندما تصبح الإجابة جاهزة.\",\n cancel: \"إلغاء\",\n armedCancelled:\n \"لم يبدأ الأفاتار. اضغط على البدء عند الجاهزية للمحاولة مرة أخرى.\",\n notSpoken:\n \"تبقى هذه الإجابة في الدردشة نصًا. يقرأ الأفاتار فقط الإجابات التي تجتاز فحوص النطق.\",\n answerFailed: \"تعذّر على المساعد الإجابة. حاول السؤال مرة أخرى.\",\n declined: \"لا بأس. الإجابة موجودة في الدردشة.\",\n askHere: \"لسماع إجابة، اسأل هنا.\",\n newChatForAvatar: \"دردشة جديدة للأفاتار\",\n newChatNote: \"تبقى دردشتك الحالية في السجل.\",\n newChatStarted: \"بدأت دردشة جديدة للأفاتار.\",\n readInChat: \"اقرأ الإجابة والمصادر في الدردشة\",\n usedToday: \"لقد استخدمت جلسة الأفاتار لهذا اليوم. ستظهر الإجابات هنا نصًا.\",\n needsAnswerAny: \"اطرح سؤالًا هنا، وسيقرأ الأفاتار الإجابة بصوت عالٍ.\",\n startNewChatDetailAny:\n \"يقرأ الأفاتار بصوت عالٍ الإجابة الأولى فقط في دردشة جديدة بدأت في علامة تبويب الأفاتار، بشرط أن تجتاز فحوص النطق.\",\n notEligibleAny:\n \"لا يمكن للأفاتار قراءة هذه الإجابة بصوت عالٍ. الإجابة والمصادر موجودة في الدردشة.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the lines of a session that reads the answers after the first\n // (Stage D).\n followUpIdle: \"ينتهي الأفاتار بعد نحو ثلاثين ثانية من دون سؤال.\",\n followUpNoTime:\n \"لم يتبقَّ وقت كافٍ في هذه الجلسة لقراءة تلك الإجابة. إنها في الدردشة.\",\n followUpMaxAnswers:\n \"قرأ الأفاتار كل الإجابات التي يمكنه قراءتها في هذه الجلسة. هذه الإجابة في الدردشة.\",\n followUpLast: \"كانت تلك آخر إجابة يمكن للأفاتار قراءتها في هذه الجلسة.\",\n followUpLimits: \"بلغ الأفاتار المباشر حده الآن. هذه الإجابة في الدردشة.\",\n followUpPaused: \"الأفاتار المباشر متوقف مؤقتًا الآن. هذه الإجابة في الدردشة.\",\n followUpUnread: \"تعذّر على الأفاتار قراءة تلك الإجابة. إنها في الدردشة.\",\n};\n\n// TRANSLATION REVIEW PENDING (BOFF-9797): a draft, not yet reviewed. Not shown until \"ta\" is in REVIEWED.\nconst TA: AvatarLiveStrings = {\n checking: \"நேரலை அவதார் கிடைக்கிறதா எனச் சரிபார்க்கிறது…\",\n needsAnswer:\n \"முதலில் அரட்டையில் பரிந்துரைக்கப்பட்ட ஒரு கேள்வியைத் தேர்ந்தெடுக்கவும்.\",\n needsAnswerDetail: \"அவதார் முதல் பதிலை மட்டுமே உரக்கப் படிக்க முடியும்.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n startNewChat: \"அவதாரைப் பயன்படுத்த புதிய அரட்டையைத் தொடங்கவும்.\",\n startNewChatDetail:\n \"ஓர் அரட்டையின் முதல் பதிலை மட்டுமே, அதுவும் பரிந்துரைக்கப்பட்ட கேள்விக்கான பதிலை, பதினைந்து நிமிடங்களுக்குள் மட்டுமே அவதார் உரக்கப் படிக்கும். புதிய அரட்டையைத் தொடங்கி, பரிந்துரைக்கப்பட்ட ஒரு கேள்வியைத் தேர்ந்தெடுக்கவும்.\",\n start: \"நேரலை அவதாரைத் தொடங்கு\",\n notNow: \"இப்போது வேண்டாம்\",\n opensInNewTab: \"(புதிய தாவலில் திறக்கும்)\",\n botCheck: \"உங்கள் உலாவியைச் சரிபார்க்கிறது…\",\n connecting: \"நேரலை அவதாருடன் இணைக்கிறது…\",\n speaking: \"அவதார் பேசுகிறது.\",\n badge: \"AI அவதார் · உண்மையான நபர் அல்ல\",\n video: \"நேரலை AI அவதார் வீடியோ\",\n captions: \"வசனங்கள்\",\n timeLeft: \"மீதமுள்ள நேரம்\",\n stop: \"நிறுத்து\",\n tapForSound: \"ஒலியை இயக்கத் தட்டவும்\",\n finished: \"நேரலை அவதார் முடிவடைந்தது.\",\n stopped: \"நீங்கள் அவதாரை நிறுத்தினீர்கள்.\",\n failed: \"நேரலை அவதாரைத் தொடங்க முடியவில்லை.\",\n interrupted: \"நேரலை அவதார் இடையிலேயே நின்றுவிட்டது.\",\n answerInChat: \"முழுப் பதில் அரட்டையில் உள்ளது.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the note for a part-read answer (Stage B).\n excerpt:\n \"அவதார் இந்தப் பதிலின் முதல் பகுதியைப் படிக்கிறது. முழுப் பதில் அரட்டையில் உள்ளது.\",\n backToChat: \"அரட்டைக்குத் திரும்பு\",\n busy: \"நேரலை அவதார் இப்போது வேறு பயன்பாட்டில் உள்ளது. சில நிமிடங்களில் மீண்டும் முயலவும்.\",\n limits:\n \"நேரலை அவதார் தற்போதைக்குத் தன் வரம்பை எட்டிவிட்டது. பிறகு மீண்டும் முயலவும்.\",\n region: \"உங்கள் பகுதியில் நேரலை அவதார் இன்னும் கிடைக்கவில்லை.\",\n locale: \"இந்த மொழியில் நேரலை அவதார் இன்னும் கிடைக்கவில்லை.\",\n paused: \"நேரலை அவதார் இப்போது இடைநிறுத்தப்பட்டுள்ளது.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft.\n notEligible:\n \"பரிந்துரைக்கப்பட்ட கேள்விக்கான முதல் பதிலை மட்டுமே, பதினைந்து நிமிடங்களுக்குள், அவதார் படிக்கும். புதிய அரட்டையைத் தொடங்கி, பரிந்துரைக்கப்பட்ட ஒரு கேள்வியைத் தேர்ந்தெடுக்கவும்.\",\n answerClaimed: \"இந்தப் பதிலை அவதார் ஏற்கெனவே படித்துவிட்டது.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the Avatar tab's question box.\n askHeadline: \"ஒரு கேள்வியைக் கேளுங்கள், அவதார் பதிலை உரக்கப் படிக்கும்.\",\n askLabel: \"அவதாருக்கான கேள்வி\",\n askPlaceholder: \"அவதாரிடம் கேளுங்கள்…\",\n askFooter:\n \"பதில்கள் AI உருவாக்கியவை, தவறாக இருக்கலாம். தனிப்பட்ட விவரங்களைச் சேர்க்க வேண்டாம்.\",\n askNoFiles: \"கோப்புகளை இணைக்க, அரட்டையைப் பயன்படுத்தவும்.\",\n askBusy: \"தற்போதைய பதில் தயாரானதும் நீங்கள் கேட்கலாம்.\",\n askUnavailable: \"அரட்டை இப்போது கிடைக்கவில்லை.\",\n gettingAnswer: \"பதிலைப் பெறுகிறது…\",\n startWhenReady: \"தயாரானதும் தொடங்கு\",\n armed: \"பதில் தயாரானதும் அவதார் தொடங்கும்.\",\n cancel: \"ரத்துசெய்\",\n armedCancelled:\n \"அவதார் தொடங்கவில்லை. மீண்டும் முயல, தயாரானதும் தொடங்கு என்பதை அழுத்தவும்.\",\n notSpoken:\n \"இந்தப் பதில் அரட்டையில் உரையாகவே இருக்கும். பேச்சுச் சரிபார்ப்புகளில் தேறும் பதில்களை மட்டுமே அவதார் படிக்கும்.\",\n answerFailed:\n \"உதவியாளரால் பதிலளிக்க முடியவில்லை. மீண்டும் கேட்டுப் பாருங்கள்.\",\n declined: \"பரவாயில்லை. பதில் அரட்டையில் உள்ளது.\",\n askHere: \"பதிலைக் கேட்க, இங்கே கேளுங்கள்.\",\n newChatForAvatar: \"அவதாருக்கான புதிய அரட்டை\",\n newChatNote: \"உங்கள் தற்போதைய அரட்டை வரலாற்றில் இருக்கும்.\",\n newChatStarted: \"அவதாருக்காகப் புதிய அரட்டை தொடங்கப்பட்டது.\",\n readInChat: \"பதிலையும் ஆதாரங்களையும் அரட்டையில் படிக்கவும்\",\n usedToday:\n \"இன்றைய அவதார் அமர்வை நீங்கள் பயன்படுத்திவிட்டீர்கள். பதில்கள் இங்கே உரையாகக் காட்டப்படும்.\",\n needsAnswerAny:\n \"இங்கே ஒரு கேள்வியைக் கேளுங்கள், அவதார் பதிலை உரக்கப் படிக்கும்.\",\n startNewChatDetailAny:\n \"அவதார் தாவலில் தொடங்கிய புதிய அரட்டையின் முதல் பதிலை மட்டுமே, அது பேச்சுச் சரிபார்ப்புகளில் தேறினால், அவதார் உரக்கப் படிக்கும்.\",\n notEligibleAny:\n \"இந்தப் பதிலை அவதாரால் உரக்கப் படிக்க முடியாது. பதிலும் ஆதாரங்களும் அரட்டையில் உள்ளன.\",\n // TRANSLATION REVIEW PENDING (BOFF-9797): draft, the lines of a session that reads the answers after the first\n // (Stage D).\n followUpIdle:\n \"கேள்வி இல்லாமல் சுமார் முப்பது வினாடிகள் கழித்து அவதார் முடிவடையும்.\",\n followUpNoTime:\n \"அந்தப் பதிலைப் படிக்க இந்த அமர்வில் போதுமான நேரம் இல்லை. அது அரட்டையில் உள்ளது.\",\n followUpMaxAnswers:\n \"இந்த அமர்வில் படிக்கக்கூடிய எல்லாப் பதில்களையும் அவதார் படித்துவிட்டது. இந்தப் பதில் அரட்டையில் உள்ளது.\",\n followUpLast: \"இந்த அமர்வில் அவதார் படிக்கக்கூடிய கடைசி பதில் அதுதான்.\",\n followUpLimits:\n \"நேரலை அவதார் தற்போது அதன் வரம்பை எட்டிவிட்டது. இந்தப் பதில் அரட்டையில் உள்ளது.\",\n followUpPaused:\n \"நேரலை அவதார் தற்போது இடைநிறுத்தப்பட்டுள்ளது. இந்தப் பதில் அரட்டையில் உள்ளது.\",\n followUpUnread:\n \"அந்தப் பதிலை அவதாரால் படிக்க முடியவில்லை. அது அரட்டையில் உள்ளது.\",\n};\n\nconst STRINGS: Record<ExploreLocale, AvatarLiveStrings> = {\n en: EN,\n zh: ZH,\n hi: HI,\n es: ES,\n ar: AR,\n ta: TA,\n};\n\nexport function avatarLiveStrings(locale: ExploreLocale): AvatarLiveStrings {\n return STRINGS[locale] ?? EN;\n}\n\n/** One version of the consent card's copy, in one locale. */\nexport interface AvatarConsentCopy {\n title: string;\n /**\n * What the avatar is and does, for a site with a product name. Takes `{product}`. Null in a product-neutral version:\n * every site, named or not, shows {@link AvatarConsentCopy.intro}, so the card's words are the same on every site.\n */\n introProduct: string | null;\n /** The same without a product name, and the only intro of a product-neutral version. */\n intro: string;\n /** Who processes what when the visitor starts. */\n processing: string;\n /** What is and is not used, recorded and kept, and who it is for. */\n storage: string;\n /** The link to the site's privacy notice, `/privacy#live-avatar`. */\n privacyLink: string;\n /**\n * The bot check `processing` tells the visitor about: `turnstile` where it says Cloudflare checks for bots, `off`\n * where it says nothing of one. The card is shown only where the server's `botCheck` is the same, so the notice a\n * visitor agrees to never describes a check that does not run, or leaves out one that does.\n */\n botCheck: AvatarBotCheck;\n /**\n * Which first questions the words describe: `suggested` where they speak of a suggested question only, `any` where\n * they say a question the visitor typed is read too. The card is shown only where the server's `questions` is the\n * same (contract v1.3), and the Avatar tab's own question box only under `any`.\n */\n questions: AvatarQuestions;\n /**\n * The words describe the answers after the first (Stage D): the avatar reads the answer to each question asked in the\n * Avatar tab, waits a while for the next one, then ends. Only then does a session whose create offers `followUps` read\n * them; under any other version it reads its one answer, as before. Absent in every version before Stage D.\n */\n followUps?: boolean;\n}\n\n/**\n * The consent copy the server's `consentVersion` names, by version and then by locale. A version is added here, never\n * edited: changed wording is a new version, which the server starts asking for at the same time.\n */\nconst CONSENT: ReadonlyMap<\n string,\n Readonly<Partial<Record<ExploreLocale, AvatarConsentCopy>>>\n> = new Map([\n [\n \"web-consent-2026-11\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct:\n \"This is an AI avatar, not a real person. It reads the assistant's first eligible answer to a suggested {product} question aloud for up to a minute. The answer is AI-generated and can be wrong.\",\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"suggested\",\n },\n },\n ],\n [\n // The voice is no longer a stored file: the server holds it in memory and plays it into the LiveKit room for Protoface.\n \"web-consent-2026-10-31\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct:\n \"This is an AI avatar, not a real person. It reads the assistant's first eligible answer to a suggested {product} question aloud for up to a minute. The answer is AI-generated and can be wrong.\",\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"suggested\",\n },\n },\n ],\n [\n // The words of web-consent-2026-10-31 with no product name in them: one notice, byte for byte, on every product's\n // site, because the server binds one consent version and one notice digest for all of them.\n \"web-consent-2026-11-02\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"suggested\",\n },\n },\n ],\n [\n // The words of web-consent-2026-11-02 without \"When you start, Cloudflare checks for bots.\", for a server that runs\n // no bot check (its availability's botCheck is `off`). Product-neutral too: one notice and one digest for every site.\n \"web-consent-2026-11-03\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"off\",\n questions: \"suggested\",\n },\n },\n ],\n [\n // The Avatar tab's own question box (contract v1.3, `questions: \"any\"`): the first answer in a new chat started in\n // the Avatar tab is read whether the visitor chose a suggested question or typed their own, so the intro says so and\n // warns against personal details in a typed one. Product-neutral, with the bot check: one notice and one digest for\n // every site (gitops docs/avatar-web/en-web-consent-2026-11-05.txt).\n \"web-consent-2026-11-05\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"any\",\n },\n },\n ],\n [\n // The words of web-consent-2026-11-05 without \"When you start, Cloudflare checks for bots.\", for a server that runs\n // no bot check (gitops docs/avatar-web/en-web-consent-2026-11-06.txt).\n \"web-consent-2026-11-06\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"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.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"off\",\n questions: \"any\",\n },\n },\n ],\n [\n // Stage B (operator decision 2026-11-04): web-consent-2026-11-05 with only its timing sentence changed. A session\n // lasts up to three minutes, sized by the server to the answer's audio; an answer longer than that is read in part,\n // which the avatar says and the Avatar tab notes (`excerpt`), and the full answer stays in Chat. A cap still\n // applies, so the words never say every answer is read whole (gitops docs/avatar-web/en-web-consent-2026-11-12-b.txt).\n \"web-consent-2026-11-12-b\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"This is an AI avatar, not a real person. It reads aloud 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. It reads for up to three minutes; if an answer is longer, it reads the first part, says so, and the full answer stays in Chat. The answer is AI-generated and can be wrong. Don't put personal details in a question you type.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"any\",\n },\n },\n ],\n [\n // The words of web-consent-2026-11-12-b without \"When you start, Cloudflare checks for bots.\", for a server that runs\n // no bot check (gitops docs/avatar-web/en-web-consent-2026-11-13-b.txt).\n \"web-consent-2026-11-13-b\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"This is an AI avatar, not a real person. It reads aloud 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. It reads for up to three minutes; if an answer is longer, it reads the first part, says so, and the full answer stays in Chat. The answer is AI-generated and can be wrong. Don't put personal details in a question you type.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"off\",\n questions: \"any\",\n },\n },\n ],\n [\n // Stage D (BOFF-9797), a DRAFT for the operator's review that no environment uses yet (global-speech-svc reserves the\n // same two versions): web-consent-2026-11-12-b with only its intro changed. The avatar reads the answer to each\n // question asked in the Avatar tab, in one session, waits about thirty seconds after an answer for the next question,\n // then ends; the session lasts at most three minutes, and an answer that does not fit the time left is read in part\n // (and said so) or not read, and stays in Chat. The notice files of record and their digests are a gitops change of\n // their own, made with the review.\n \"web-consent-2026-11-19-d\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"This is an AI avatar, not a real person. It reads aloud the answers to the questions you ask in the Avatar tab, provided each passes the speech checks. After an answer, it waits about thirty seconds for your next question, then ends. A session lasts at most three minutes; if an answer doesn't fit in the time left, it reads only the first part and says so, or doesn't read it, and the full answer stays in Chat. The answers are AI-generated and can be wrong. Don't put personal details in a question you type.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"turnstile\",\n questions: \"any\",\n followUps: true,\n },\n },\n ],\n [\n // The words of web-consent-2026-11-19-d without \"When you start, Cloudflare checks for bots.\", for a server that runs\n // no bot check. A DRAFT, like it.\n \"web-consent-2026-11-20-d\",\n {\n en: {\n title: \"Live AI avatar (beta)\",\n introProduct: null,\n intro:\n \"This is an AI avatar, not a real person. It reads aloud the answers to the questions you ask in the Avatar tab, provided each passes the speech checks. After an answer, it waits about thirty seconds for your next question, then ends. A session lasts at most three minutes; if an answer doesn't fit in the time left, it reads only the first part and says so, or doesn't read it, and the full answer stays in Chat. The answers are AI-generated and can be wrong. Don't put personal details in a question you type.\",\n processing:\n \"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.\",\n storage:\n \"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.\",\n privacyLink: \"How we handle this\",\n botCheck: \"off\",\n questions: \"any\",\n followUps: true,\n },\n },\n ],\n]);\n\n/** The consent copy for exactly `version` in `locale`, or null when the SDK has none to show for it. */\nexport function avatarConsentCopy(\n version: string,\n locale: ExploreLocale,\n): AvatarConsentCopy | null {\n if (!isAvatarLiveLocaleReviewed(locale)) return null;\n return CONSENT.get(version)?.[locale] ?? null;\n}\n\n/**\n * The words of the Avatar tab's mic (BOFF-9797 Stage C): its button, the line that shows while it listens, and what a\n * press that gives no text says. English only, like the reviewed live-avatar copy: in any other locale the mic is not\n * offered (the box stays for typing).\n */\nexport interface AvatarMicStrings {\n /** The mic button's accessible name and title, when a tap starts a press. */\n micStart: string;\n /** The same while the mic opens or listens, when a tap stops it. */\n micStop: string;\n /** The mic notice's buttons: go on to the browser's permission prompt, or not. */\n micAllow: string;\n micNotNow: string;\n /** The status line while the microphone opens and the stream connects. Announced politely. */\n micStarting: string;\n /** The status line while it records. Announced politely; the time beside it never is. */\n micListening: string;\n /** The time recorded against the limit: takes `{elapsed}` and `{limit}` (`0:07`, `0:30`). */\n micElapsed: string;\n /** The status line once the recording has stopped, while the last of the text comes. */\n micFinishing: string;\n /** Once the text is in the box. The visitor corrects it and presses Send: nothing is sent by itself. */\n micDone: string;\n /** The same when the recording stopped at the limit. No number: it is spelled out. */\n micDoneLimit: string;\n /** No words were heard. */\n micNoSpeech: string;\n /** Why a press gave no text (`AvatarMicFailure`), each with the way on: typing in the box. */\n micDenied: string;\n micUnsupported: string;\n micUnavailable: string;\n micLimit: string;\n micBusy: string;\n micFailed: string;\n}\n\nconst MIC_EN: AvatarMicStrings = {\n micStart: \"Ask by voice\",\n micStop: \"Stop recording\",\n micAllow: \"Use the microphone\",\n micNotNow: \"Not now\",\n micStarting: \"Starting the microphone…\",\n micListening: \"Listening…\",\n micElapsed: \"{elapsed} of {limit}\",\n micFinishing: \"Getting the text…\",\n micDone: \"Check the text, then press Send.\",\n micDoneLimit:\n \"The recording stopped at thirty seconds. Check the text, then press Send.\",\n micNoSpeech: \"No words were heard. Try again, or type your question.\",\n micDenied:\n \"The microphone is blocked in this browser. You can type your question instead.\",\n micUnsupported:\n \"The microphone can't be used here. You can type your question instead.\",\n micUnavailable:\n \"Voice questions aren't available right now. You can type your question instead.\",\n micLimit:\n \"Voice questions have reached their limit for now. You can type your question instead.\",\n micBusy:\n \"Voice questions are busy right now. Try again in a moment, or type your question.\",\n micFailed:\n \"The microphone stopped before the text came. Try again, or type your question.\",\n};\n\nconst MIC_STRINGS: Readonly<Partial<Record<ExploreLocale, AvatarMicStrings>>> =\n { en: MIC_EN };\n\n/** The mic's words in `locale`, or null where there are none (the mic is then not offered). */\nexport function avatarMicStrings(\n locale: ExploreLocale,\n): AvatarMicStrings | null {\n if (!isAvatarLiveLocaleReviewed(locale)) return null;\n return MIC_STRINGS[locale] ?? null;\n}\n\n/** One version of the mic notice's copy, in one locale: shown on the first tap of the mic, before the browser asks. */\nexport interface AvatarMicNoticeCopy {\n title: string;\n /** Where the voice goes while the visitor speaks, and who turns it into text. */\n processing: string;\n /** What is and is not kept of the audio and the text. */\n storage: string;\n /** Where the text is before Send, that nothing is sent by itself, and what it is after Send. */\n text: string;\n /** How long one recording may be, and that there are daily limits. No numbers: they are spelled out. */\n limits: string;\n /** The link to the site's privacy notice, `/privacy#live-avatar`. */\n privacyLink: string;\n}\n\n/**\n * The mic notice version this SDK shows and names in every press (`notice` in the press's `config`). The speech service\n * takes a press only when this is its own `AVATAR_WEB_STT_NOTICE_VERSION`, and refuses any other (`notice-version`):\n * the SDK then offers the mic no more on that page, because it has no copy for the version the server records. A new\n * wording is a new version here and on the server at the same time, never an edit.\n */\nexport const AVATAR_MIC_NOTICE_VERSION = \"web-mic-2026-11-05\";\n\n/**\n * The mic notice's copy, by version and then by locale. A version is added here, never edited.\n *\n * PRIVACY REVIEW PENDING (BOFF-9797): `web-mic-2026-11-05` is a DRAFT for the operator's privacy review. Nothing shows\n * it until a site sets `avatar.live.mic` and the gateway's website speech-to-text is on (neither is anywhere), and it\n * must not be merged before the review: changed words are a new version. Its EU sentence needs the speech service's\n * region confirmed first (global-speech-svc `docs/SPEECH_STT.md`, \"Where speech is processed\").\n */\nconst MIC_NOTICE: ReadonlyMap<\n string,\n Readonly<Partial<Record<ExploreLocale, AvatarMicNoticeCopy>>>\n> = new Map([\n [\n AVATAR_MIC_NOTICE_VERSION,\n {\n en: {\n title: \"Ask with your voice\",\n processing:\n \"While you speak, your voice is streamed to our speech service, and Google Cloud Speech-to-Text turns it into text in Google's EU region.\",\n storage: \"We don't store or log your audio, or the text made from it.\",\n text: \"The text appears in the box and stays in this browser until you press Send. Nothing is sent by itself. Once you send it, it is a chat message, kept like any other.\",\n limits:\n \"Each recording stops after thirty seconds, and voice questions have daily limits.\",\n privacyLink: \"How we handle this\",\n },\n },\n ],\n]);\n\n/** The mic notice for exactly `version` in `locale`, or null when the SDK has none to show for it. */\nexport function avatarMicNotice(\n version: string,\n locale: ExploreLocale,\n): AvatarMicNoticeCopy | null {\n if (!isAvatarLiveLocaleReviewed(locale)) return null;\n return MIC_NOTICE.get(version)?.[locale] ?? null;\n}\n","/**\n * The Avatar tab's mic (BOFF-9797, Stage C): its button, its notice and its status line, in the live avatar's view.\n *\n * Tap to start and tap to stop, thirty seconds at most; what is heard shows as it is recognised, and the final text goes\n * into the Avatar tab's own question box, where the visitor corrects it and presses Send. Nothing is ever sent by itself:\n * the text goes into the box, and the box's Send (the view's single-flight `ask`) is the only way it leaves.\n *\n * - **Offered only** where the site opts in (`avatar.live.mic`), the server's availability answer carries a usable\n * `stt` offer, the box takes a question now (the view's `acceptsQuestion`), this SDK has the mic's words and its notice\n * for the visitor's locale, and the browser can capture at all. Anywhere else nothing of it renders.\n * - **The first tap shows the mic notice** (its version is {@link AVATAR_MIC_NOTICE_VERSION}), then, on \"Use the\n * microphone\", the browser's permission prompt. Agreed once, the notice is not shown again on this page.\n * - **Loaded only when used.** The capture, the stream and the press state machine are a chunk of their own\n * (`dist/avatar-mic/`, from `src/avatar-mic/`), loaded with a dynamic `import()` when the notice shows: this file\n * holds only the button, the words and that loader (`scripts/validate-avatar-live.mjs` checks the build).\n * - **Released on every way out** (the view calls `cancel`): the Chat tab, closing the panel, the page hidden or left,\n * the view going, the box no longer taking a question, and Stop. A press that refuses for good (the server's notice is\n * another version, a pause, a spent limit) takes the mic away for the rest of the page.\n */\n\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\n\nimport { Mic, Square } from \"lucide-react\";\n\nimport {\n AVATAR_MIC_NOTICE_VERSION,\n avatarMicNotice,\n avatarMicStrings,\n type AvatarMicStrings,\n} from \"./explore-avatar-i18n\";\nimport { fill } from \"./explore-fill\";\nimport { cn } from \"../utils/cn\";\n\nimport type { ExploreLocale } from \"./explore-i18n\";\nimport type {\n AvatarMic,\n AvatarMicFailure,\n AvatarMicModule,\n AvatarMicOffer,\n AvatarMicState,\n} from \"../avatar-mic/types\";\n\n/** Where the notice's privacy link goes: the site's privacy notice, at its live avatar section. */\nconst PRIVACY_HREF = \"/privacy#live-avatar\";\n/** The longest press, as the visitor sees it: the mic's own limit (`MAX_PRESS_MS` in `src/avatar-mic/press.ts`). */\nconst LIMIT_SECONDS = 30;\n/** How often the time recorded is brought up to date while it listens. */\nconst TICK_MS = 250;\n\nconst IDLE: AvatarMicState = { name: \"idle\" };\n\n/** The refusals after which the mic is offered no more on this page: the server will not take a press from it. */\nconst FOR_GOOD: ReadonlySet<AvatarMicFailure> = new Set<AvatarMicFailure>([\n \"unavailable\",\n \"limit\",\n]);\n\nconst FAILURE_TEXT: Record<AvatarMicFailure, keyof AvatarMicStrings> = {\n denied: \"micDenied\",\n unsupported: \"micUnsupported\",\n unavailable: \"micUnavailable\",\n limit: \"micLimit\",\n busy: \"micBusy\",\n failed: \"micFailed\",\n};\n\n/**\n * Load the mic's chunk. The package build leaves this `import()` as it is, pointing at the file it builds beside the\n * view's (`tsup.config.ts`), so a site's bundler splits it into a chunk of its own; `scripts/validate-avatar-live.mjs`\n * checks that it did.\n */\nexport function loadAvatarMic(): Promise<AvatarMicModule> {\n return import(\"../avatar-mic\").then((loaded) => ({\n createAvatarMic: loaded.createAvatarMic,\n }));\n}\n\n/**\n * Whether this browser can capture and stream here at all: a microphone API (only in a secure context), an\n * AudioWorklet, and WebSockets. Read without loading the mic's chunk.\n */\nexport function canUseAvatarMic(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n typeof navigator.mediaDevices?.getUserMedia === \"function\" &&\n typeof AudioContext !== \"undefined\" &&\n typeof AudioWorkletNode !== \"undefined\" &&\n typeof WebSocket !== \"undefined\"\n );\n}\n\n/** `m:ss`, counting up. */\nfunction clock(seconds: number): string {\n const whole = Math.max(0, Math.floor(seconds));\n return `${Math.floor(whole / 60)}:${String(whole % 60).padStart(2, \"0\")}`;\n}\n\n/** The box's text with `heard` added: after what is already there, and never past `maxLength`. */\nexport function withHeardText(\n current: string,\n heard: string,\n maxLength: number,\n): string {\n const text = heard.trim();\n if (text === \"\") return current;\n const joined =\n current.trim() === \"\" ? text : `${current.replace(/\\s+$/, \"\")} ${text}`;\n return joined.slice(0, Math.max(0, maxLength));\n}\n\nexport interface UseAvatarMicOptions {\n /**\n * Everything the view decides: the site opts in, the server's availability carries an offer, and the box takes a\n * question now. The words, the notice, the browser and the mic's own refusals are this hook's.\n */\n enabled: boolean;\n locale: ExploreLocale;\n /** `avatarApiBase` of the SDK's gateway, null when there is none to use. */\n base: string | null;\n /** The latest offer the view holds (null when its last availability answer carried none). */\n offer: AvatarMicOffer | null;\n /** Ask availability again for a new offer, and hold it: null when the answer carries none; rejects with no answer. */\n refreshOffer: () => Promise<AvatarMicOffer | null>;\n /** The final text of a press: the view puts it in the box. Never called with nothing. */\n onText: (text: string) => void;\n /**\n * Told on a tap that starts the mic (one that opens its notice, or starts a press), before anything of it starts, and\n * never on a tap that stops it: in a session that reads the answers after the first (Stage D), the view interrupts\n * the answer being spoken with it.\n */\n onStart?: () => void;\n}\n\nexport interface AvatarMicControls {\n /** The mic button, for the box's row; null when the mic is not offered. */\n button: ReactNode;\n /** The notice, shown on the first tap, for over the box; null otherwise. */\n notice: ReactNode;\n /**\n * The status line, the time recorded and what is heard, for under the box's row; null when the box can have no mic\n * now. (After a refusal for good, only the line saying so.)\n */\n lines: ReactNode;\n /** Call off whatever the mic has under way and release the microphone. For every way out of the view. */\n cancel: () => void;\n /**\n * The mic is recording: the microphone is open and its stream ready (the press listens), until the recording stops.\n * Stage D tells the session meanwhile that the visitor is speaking. Not before: the chunk loading, the browser's\n * permission prompt (which may stay unanswered) and the stream connecting record nothing.\n */\n recording: boolean;\n}\n\n/** The mic of the Avatar tab's box. See the file's comment. */\nexport function useAvatarMic({\n enabled,\n locale,\n base,\n offer,\n refreshOffer,\n onText,\n onStart,\n}: UseAvatarMicOptions): AvatarMicControls {\n const S = avatarMicStrings(locale);\n const copy = avatarMicNotice(AVATAR_MIC_NOTICE_VERSION, locale);\n const uid = useId();\n const noticeTitleId = `${uid}-mic-notice`;\n\n /** Why a press was refused for good, which takes the mic away for the rest of the page (and still says why). */\n const [withdrawn, setWithdrawn] = useState<AvatarMicFailure | null>(null);\n // Read once on the client: no microphone API while rendering on a server, and the first client render matches it.\n const [supported, setSupported] = useState(false);\n useEffect(() => setSupported(canUseAvatarMic()), []);\n\n /** The box could have a mic now: its lines show (a refusal for good is still said there). */\n const possible =\n enabled && supported && base !== null && S !== null && copy !== null;\n /** The mic itself is offered: its button shows. */\n const offered = possible && withdrawn === null;\n\n const [state, setState] = useState<AvatarMicState>(IDLE);\n const [noticeOpen, setNoticeOpen] = useState(false);\n /** The visitor agreed to the notice on this page (for this version). */\n const agreedRef = useRef(false);\n /** The mic's chunk is loading for a tap (the time before there is a press to report). */\n const [loading, setLoading] = useState(false);\n /** Why the last attempt gave nothing, where it never became a press (the chunk could not be loaded). */\n const [loadFailed, setLoadFailed] = useState(false);\n const [now, setNow] = useState(() => Date.now());\n\n const micRef = useRef<{ base: string; mic: AvatarMic } | null>(null);\n /** Counts every tap and every cancel: a chunk that arrives after either starts nothing. */\n const seqRef = useRef(0);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const allowRef = useRef<HTMLButtonElement>(null);\n /** The press whose text has gone into the box, so a re-render never puts it in twice. */\n const usedEpochRef = useRef(0);\n\n const latest = useRef({ offer, refreshOffer, onText, onStart, base });\n latest.current = { offer, refreshOffer, onText, onStart, base };\n\n const cancel = useCallback(() => {\n seqRef.current += 1;\n setLoading(false);\n setLoadFailed(false);\n setNoticeOpen(false);\n micRef.current?.mic.cancel();\n }, []);\n\n // No longer offered (the box took a question, the server's offer went, the view went off): what is under way ends.\n useEffect(() => {\n if (!offered) cancel();\n }, [offered, cancel]);\n // The view going: the same, and a tap whose chunk is still on its way starts nothing when it arrives.\n useEffect(\n () => () => {\n seqRef.current += 1;\n micRef.current?.mic.cancel();\n },\n [],\n );\n\n /** The mic for `base`: made once its chunk is loaded, and again only for another gateway. */\n const micFor = useCallback(async (target: string): Promise<AvatarMic> => {\n const held = micRef.current;\n if (held !== null && held.base === target) return held.mic;\n held?.mic.cancel();\n const loaded = await loadAvatarMic();\n const mic = loaded.createAvatarMic({\n base: target,\n notice: AVATAR_MIC_NOTICE_VERSION,\n offer: () => latest.current.offer,\n refreshOffer: () => latest.current.refreshOffer(),\n onState: setState,\n });\n micRef.current = { base: target, mic };\n return mic;\n }, []);\n\n /** A press, once the notice is agreed to: the chunk (loaded already, as a rule, while the notice showed), then start. */\n const press = useCallback(() => {\n const target = latest.current.base;\n if (target === null) return;\n seqRef.current += 1;\n const seq = seqRef.current;\n setLoadFailed(false);\n setLoading(true);\n void micFor(target).then(\n (mic) => {\n if (seqRef.current !== seq) return;\n setLoading(false);\n mic.start();\n },\n () => {\n if (seqRef.current !== seq) return;\n setLoading(false);\n setLoadFailed(true);\n },\n );\n }, [micFor]);\n\n const recording =\n loading || state.name === \"starting\" || state.name === \"listening\";\n\n const tap = useCallback(() => {\n if (state.name === \"listening\" || state.name === \"starting\") {\n micRef.current?.mic.stop();\n return;\n }\n if (loading) {\n cancel();\n return;\n }\n latest.current.onStart?.();\n if (!agreedRef.current) {\n setNoticeOpen(true);\n // The chunk, while the notice is read: the tap on \"Use the microphone\" then starts at once.\n void loadAvatarMic().catch(() => undefined);\n return;\n }\n press();\n }, [cancel, loading, press, state.name]);\n\n const allow = useCallback(() => {\n agreedRef.current = true;\n setNoticeOpen(false);\n buttonRef.current?.focus();\n press();\n }, [press]);\n\n const notNow = useCallback(() => {\n setNoticeOpen(false);\n buttonRef.current?.focus();\n }, []);\n\n // The notice takes focus as it opens: its first control is the way on.\n useEffect(() => {\n if (noticeOpen) allowRef.current?.focus();\n }, [noticeOpen]);\n\n // The time recorded, while it listens.\n const listeningSince = state.name === \"listening\" ? state.startedAt : null;\n useEffect(() => {\n if (listeningSince === null) return;\n setNow(Date.now());\n const timer = setInterval(() => setNow(Date.now()), TICK_MS);\n return () => clearInterval(timer);\n }, [listeningSince]);\n\n // A press's final text goes into the box, once; a refusal for good takes the mic away.\n useEffect(() => {\n if (state.name === \"done\" && state.epoch !== usedEpochRef.current) {\n usedEpochRef.current = state.epoch;\n if (state.text !== \"\") latest.current.onText(state.text);\n } else if (state.name === \"failed\" && FOR_GOOD.has(state.reason)) {\n setWithdrawn(state.reason);\n }\n }, [state]);\n\n if (!possible || S === null || copy === null) {\n return {\n button: null,\n notice: null,\n lines: null,\n cancel,\n recording: false,\n };\n }\n\n const status =\n withdrawn !== null\n ? S[FAILURE_TEXT[withdrawn]]\n : loading\n ? S.micStarting\n : loadFailed\n ? S.micFailed\n : state.name === \"starting\"\n ? S.micStarting\n : state.name === \"listening\"\n ? S.micListening\n : state.name === \"finishing\"\n ? S.micFinishing\n : state.name === \"done\"\n ? state.text === \"\"\n ? S.micNoSpeech\n : state.limit\n ? S.micDoneLimit\n : S.micDone\n : state.name === \"failed\"\n ? S[FAILURE_TEXT[state.reason]]\n : \"\";\n const heard =\n offered && (state.name === \"listening\" || state.name === \"finishing\")\n ? state.text\n : \"\";\n\n const button = !offered ? null : (\n <button\n ref={buttonRef}\n type=\"button\"\n aria-label={recording ? S.micStop : S.micStart}\n aria-pressed={recording}\n title={recording ? S.micStop : S.micStart}\n data-boff-explore=\"avatar-live-mic\"\n data-mic={loading ? \"starting\" : state.name}\n className={cn(\n \"inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-md border transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background motion-reduce:transition-none\",\n recording\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-border bg-background text-foreground hover:bg-accent hover:text-accent-foreground\",\n )}\n onClick={tap}\n >\n {recording ? (\n <Square aria-hidden=\"true\" className=\"h-4 w-4\" />\n ) : (\n <Mic aria-hidden=\"true\" className=\"h-4 w-4\" />\n )}\n </button>\n );\n\n const notice =\n offered && noticeOpen ? (\n <section\n aria-labelledby={noticeTitleId}\n data-boff-explore=\"avatar-live-mic-notice\"\n className=\"w-full rounded-lg border border-border p-3 text-start\"\n >\n <h3 id={noticeTitleId} className=\"text-sm font-semibold\">\n {copy.title}\n </h3>\n <p className=\"mt-1 text-xs text-muted-foreground\">{copy.processing}</p>\n <p className=\"mt-1 text-xs text-muted-foreground\">{copy.storage}</p>\n <p className=\"mt-1 text-xs text-muted-foreground\">{copy.text}</p>\n <p className=\"mt-1 text-xs text-muted-foreground\">{copy.limits}</p>\n <a\n href={PRIVACY_HREF}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-boff-explore=\"avatar-live-mic-privacy\"\n className=\"mt-1 inline-block text-xs font-medium text-primary underline underline-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {copy.privacyLink}\n </a>\n <div className=\"mt-2 flex flex-wrap gap-2\">\n <button\n ref={allowRef}\n type=\"button\"\n data-boff-explore=\"avatar-live-mic-allow\"\n className=\"inline-flex min-h-11 items-center justify-center rounded-md bg-primary px-4 py-2 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 motion-reduce:transition-none\"\n onClick={allow}\n >\n {S.micAllow}\n </button>\n <button\n type=\"button\"\n data-boff-explore=\"avatar-live-mic-not-now\"\n className=\"inline-flex min-h-11 items-center justify-center rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background motion-reduce:transition-none\"\n onClick={notNow}\n >\n {S.micNotNow}\n </button>\n </div>\n </section>\n ) : null;\n\n const listening = offered && state.name === \"listening\";\n const lines = (\n <>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n {listening ? (\n <span aria-hidden=\"true\" className=\"relative flex h-2 w-2 shrink-0\">\n <span className=\"absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75 motion-reduce:animate-none\" />\n <span className=\"relative inline-flex h-2 w-2 rounded-full bg-primary\" />\n </span>\n ) : null}\n <p role=\"status\" data-boff-explore=\"avatar-live-mic-status\">\n {status}\n </p>\n {listening ? (\n <span\n role=\"timer\"\n data-boff-explore=\"avatar-live-mic-elapsed\"\n className=\"tabular-nums\"\n >\n {fill(S.micElapsed, {\n elapsed: clock(\n Math.min(LIMIT_SECONDS, (now - (listeningSince ?? now)) / 1000),\n ),\n limit: clock(LIMIT_SECONDS),\n })}\n </span>\n ) : null}\n </div>\n {heard === \"\" ? null : (\n <p\n data-boff-explore=\"avatar-live-mic-heard\"\n dir=\"auto\"\n className=\"line-clamp-3 break-words text-sm italic text-muted-foreground\"\n >\n {heard}\n </p>\n )}\n </>\n );\n\n return {\n button,\n notice,\n lines,\n cancel,\n recording: offered && state.name === \"listening\",\n };\n}\n","/**\n * BOFF-9797. Cloudflare Turnstile, for the live avatar's start only.\n *\n * Nothing here runs until the visitor presses Start on the live avatar's consent card: the script is added to the page\n * then, once, and a widget is rendered for that one start (action `avatar_start`). The widget stays invisible unless\n * Cloudflare needs the visitor to interact with it. The token it returns goes to the gateway in a header and is used\n * once.\n *\n * The widget is rendered with `cData`, the binding of this check to the create request it is for (web API contract\n * v1.1: see `avatarBotBinding` in `explore-avatar-api.ts`), so it cannot be rendered before the binding is known.\n */\n\nconst SCRIPT_SRC =\n \"https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit\";\n/** How long the script may take to load before the start is given up. */\nconst SCRIPT_TIMEOUT_MS = 15_000;\n\n/** The part of Turnstile's render options used here. */\ninterface TurnstileRenderOptions {\n sitekey: string;\n action: string;\n /** Customer data Turnstile returns with the verified token: the binding to the create request. */\n cData: string;\n appearance: \"interaction-only\";\n size: \"flexible\";\n \"response-field\": false;\n callback: (token: string) => void;\n \"error-callback\": () => boolean;\n \"expired-callback\": () => void;\n \"timeout-callback\": () => void;\n}\n\n/** The part of `window.turnstile` used here. */\ninterface TurnstileApi {\n render: (\n container: HTMLElement,\n options: TurnstileRenderOptions,\n ) => string | null | undefined;\n remove: (widgetId: string) => void;\n}\n\nfunction readApi(): TurnstileApi | null {\n if (typeof window === \"undefined\") return null;\n const api = (window as unknown as { turnstile?: Partial<TurnstileApi> })\n .turnstile;\n return api &&\n typeof api.render === \"function\" &&\n typeof api.remove === \"function\"\n ? (api as TurnstileApi)\n : null;\n}\n\nlet loading: Promise<TurnstileApi> | null = null;\n\n/** Turnstile's API, adding its script to the page the first time. A failed load can be tried again later. */\nexport function loadTurnstile(): Promise<TurnstileApi> {\n const ready = readApi();\n if (ready) return Promise.resolve(ready);\n if (loading) return loading;\n loading = new Promise<TurnstileApi>((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = SCRIPT_SRC;\n script.async = true;\n script.setAttribute(\"data-boff-explore\", \"avatar-live-turnstile\");\n const fail = () => {\n clearTimeout(timer);\n loading = null;\n script.remove();\n reject(new Error(\"The bot check could not be loaded.\"));\n };\n const timer = setTimeout(fail, SCRIPT_TIMEOUT_MS);\n script.addEventListener(\"load\", () => {\n const api = readApi();\n if (!api) {\n fail();\n return;\n }\n clearTimeout(timer);\n resolve(api);\n });\n script.addEventListener(\"error\", fail);\n document.head.appendChild(script);\n });\n return loading;\n}\n\nexport interface TurnstileRun {\n /** The token, once Cloudflare has one; rejects when the check fails, expires, times out or is cancelled. */\n token: Promise<string>;\n /** Remove the widget, and reject `token` if it is still waiting. Safe to call more than once. */\n cancel: () => void;\n}\n\n/**\n * Run one bot check in `container` with `siteKey`, for `action`, bound to `cData` (or to what it resolves to: the widget\n * is rendered once its script has loaded AND the binding is known, and a binding that cannot be made fails the check).\n */\nexport function runTurnstile(\n container: HTMLElement | null,\n siteKey: string,\n action: string,\n cData: string | Promise<string>,\n): TurnstileRun {\n // A binding that cannot be made fails `token`; it is never an unhandled rejection of its own.\n Promise.resolve(cData).catch(() => undefined);\n let settled = false;\n let cancelled = false;\n let widget: { api: TurnstileApi; id: string } | null = null;\n let rejectToken: (error: Error) => void = () => undefined;\n\n const removeWidget = () => {\n if (!widget) return;\n const { api, id } = widget;\n widget = null;\n try {\n api.remove(id);\n } catch {\n // Already gone with its container.\n }\n };\n\n const token = new Promise<string>((resolve, reject) => {\n rejectToken = (error: Error) => {\n if (settled) return;\n settled = true;\n reject(error);\n };\n if (!container) {\n rejectToken(new Error(\"No place for the bot check.\"));\n return;\n }\n Promise.all([loadTurnstile(), cData]).then(\n ([api, binding]) => {\n if (cancelled || settled) return;\n const failed = () => {\n removeWidget();\n rejectToken(new Error(\"The bot check did not pass.\"));\n };\n const id = api.render(container, {\n sitekey: siteKey,\n action,\n cData: binding,\n appearance: \"interaction-only\",\n size: \"flexible\",\n \"response-field\": false,\n callback: (value: string) => {\n if (settled) return;\n settled = true;\n resolve(value);\n },\n \"error-callback\": () => {\n failed();\n // Handled here: Turnstile need not report it again.\n return true;\n },\n \"expired-callback\": failed,\n \"timeout-callback\": failed,\n });\n if (typeof id === \"string\" && id !== \"\") {\n widget = { api, id };\n if (settled) removeWidget();\n } else if (!settled) {\n rejectToken(new Error(\"The bot check could not start.\"));\n }\n },\n (error: unknown) => {\n rejectToken(\n error instanceof Error\n ? error\n : new Error(\"The bot check could not be loaded.\"),\n );\n },\n );\n });\n\n // A cancelled check nobody waits on any more is not an error worth reporting.\n token.catch(() => undefined);\n\n return {\n token,\n cancel: () => {\n cancelled = true;\n removeWidget();\n rejectToken(new Error(\"The bot check was cancelled.\"));\n },\n };\n}\n","/**\n * AvatarLiveView — the Avatar tab's live avatar (BOFF-9797), opt-in: its view and its state machine.\n *\n * `ExploreAvatarLive` (`explore-avatar-live.tsx`) renders this, and only once the Avatar view has been opened on a panel\n * whose host passes `avatar.live`. This file, and the requests, the words and the bot check it brings with it, is a\n * chunk of its own that a site downloads at that moment and not before; a site that never passes `avatar.live` never\n * does. It reads nothing from the page's React contexts (the package builds each entry on its own, so a context read\n * here would be a second, empty one): everything it needs comes in as props from `ExploreAvatarLive`.\n *\n * The visitor watches and listens; their browser never sends the avatar anything to say. What happens, in order:\n *\n * 1. **The tab opens** (never on page load): one availability request to the gateway's web branch. Nothing else is\n * loaded or asked for until the visitor agrees.\n * 2. **Offered, with the conversation's first answer:** a consent card (its copy is versioned; the panel shows only\n * copy written for the version the server names), Start, Not now and a link to the privacy notice. The avatar reads\n * one answer only: a conversation that is exactly a suggested question and its completed answer, while that answer\n * is fresh (see {@link ANSWER_OFFER_MS}). A failed first answer, a second question or an answer that is too old asks\n * the visitor to start a new chat instead, with a New chat button.\n * 3. **Start:** the live module (`live.load`) and, where the server checks for bots (availability's `botCheck`, contract\n * v1.2), the bot check load, then one create request: the contract's six fields, an `Idempotency-Key` and the bot\n * check's token, without credentials. The bot check is bound to that very request (`cData`, contract v1.1), so the\n * body is made once, before the widget is rendered. Where the server runs no bot check, no Cloudflare script or\n * widget is loaded and the request carries no token.\n * 4. **Created:** the room is joined to watch only. The avatar's video, its captions, a badge saying it is an AI and\n * not a person, a countdown (never announced), Stop and Continue in Chat.\n * 5. **Ending:** Stop, closing the panel, leaving the page (`pagehide`) or the live avatar going off asks the server to\n * end the session with a `keepalive` request. The server ends it on its own deadlines either way. Once the create has\n * been sent, switching to the Chat tab or to another browser tab does not end it: the pane is only hidden, so the\n * room's video and audio stay attached and the avatar speaks to its planned end (see `leave`). Before the create,\n * both still call off what is under way, with nothing created. Where the host sets `live.endUnattended`, a session\n * out of sight also ends once its answer has played out, and soon when the browser holds its sound back (see\n * `attend`): an idle tail after an answer runs only while the Avatar view is in sight.\n *\n * **Asking in the Avatar tab** (contract v1.3): where the server reads the answer to a question the visitor typed too\n * (availability's `questions` is `any`) and this SDK holds consent copy written for that, the tab has a question box of\n * its own, with the suggested questions as chips. A question asked there (`surface: \"AVATAR\"`) is the first of a new\n * chat, and its first answer is the only one offered: the consent card shows while the answer is written, with \"Start\n * when ready\", which waits for the answer, asks availability again and checks the answer as the service will, and only\n * then creates the session. Any other conversation is never read: the tab offers \"New chat for the avatar\", and never\n * resets a conversation by itself. After the day's session (a `limits` refusal, or this browser's own note of one) the\n * box asks ordinary questions, and the answer shows as text. Under `suggested`, or with a server older than v1.3, the\n * tab is as it was.\n *\n * **The mic** (Stage C, `explore-avatar-mic.tsx`): where the host sets `live.mic`, the last availability answer carried\n * a mic offer (`stt`) and the box takes the first question of a new chat ({@link acceptsQuestion}), the box has a mic:\n * tap to start, tap to stop, thirty seconds at most, after a notice of its own on the first tap. Its final text goes into\n * the box for the visitor to correct and Send; nothing is sent by itself. Every way out of the view (`leave`, Stop, the\n * view going) stops it and releases the microphone first. Its capture and stream are a chunk of their own, loaded when\n * it is first used.\n *\n * **The answers after the first** (Stage D, `followUpRun`): only for a session whose create offers `followUps` (the\n * server's `AVATAR_WEB_MULTI_ANSWER`), under consent copy whose words describe them, with the tab's own box. The session\n * lasts the whole conversation, and the box stays under the live avatar: a question asked there (typed, or by the mic\n * where it is offered) is the next one of the same conversation, with `surface: \"AVATAR\"`, and the same session reads\n * its answer. The session is told what the visitor does (`requestTurn`): `asking` as Send is pressed, `listening` while\n * the mic records, the answer once it is written and the one before has played out (`answer`: the session reads one at\n * a time, and one it refuses as `busy` is asked again), and `interrupt` when the mic is tapped while the avatar speaks.\n * An answer the session will not read (no time left for all of it, its answers used up, a check, a limit) stays in\n * Chat, said in one line; one this browser can tell will not be read is still sent, so the session's idle end counts\n * from its refusal. The session ends by itself after a quiet spell (`idleSeconds`) with no question, and Stop ends it\n * as before. When an answer has played out is told by the worker's voice going quiet (the room's `speaking`).\n * Without `followUps`, nothing of this runs: the session reads its one answer, exactly as before.\n *\n * Any refusal is one short sentence and \"Continue in Chat\". A route that is not there, a refused origin or a network\n * failure shows the tab as it was before the live avatar, except once the create request has been sent: the server may\n * have made the session by then, so a create that gets no answer (by its deadline, which the wait never outlasts) says\n * the live avatar couldn't start, and a session its answer brings after that is ended at once, never joined. The\n * conversation token goes into the create request and nowhere else; the session's secret and room token are kept in\n * refs, never in the page.\n */\n\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ClipboardEvent as ReactClipboardEvent,\n type DragEvent as ReactDragEvent,\n type KeyboardEvent as ReactKeyboardEvent,\n type ReactNode,\n} from \"react\";\n\nimport { answerDisplayText } from \"./explore-answer-text\";\nimport {\n avatarBotBinding,\n canBindBotCheck,\n isAvatarConversationToken,\n isAvatarMessageId,\n newIdempotencyKey,\n requestAvailability,\n requestAvailabilityAnswer,\n requestCreate,\n requestTurn,\n sendEnd,\n type AvatarAvailability,\n type AvatarBotCheck,\n type AvatarCreateBody,\n type AvatarCreateResult,\n type AvatarEndReason,\n type AvatarFollowUps,\n type AvatarOffer,\n type AvatarQuestions,\n type AvatarRefusal,\n type AvatarSession,\n type AvatarTurnRefusal,\n} from \"./explore-avatar-api\";\nimport {\n avatarConsentCopy,\n avatarLiveStrings,\n type AvatarConsentCopy,\n type AvatarLiveStrings,\n} from \"./explore-avatar-i18n\";\nimport { turnstileSiteKeyOf } from \"./explore-avatar-live-config\";\nimport { useAvatarMic, withHeardText } from \"./explore-avatar-mic\";\nimport { runTurnstile, type TurnstileRun } from \"./explore-avatar-turnstile\";\nimport { fill } from \"./explore-fill\";\nimport { cn } from \"../utils/cn\";\n\nimport type {\n AvatarConversation,\n ExplorePanelAvatarLive,\n} from \"./explore-avatar-live-config\";\nimport type { ExploreLocale } from \"./explore-i18n\";\nimport type { ExploreMessage } from \"./explore-types\";\nimport type {\n AvatarLiveModule,\n ReceiveOnlyEvent,\n ReceiveOnlySession,\n} from \"../avatar-live/types\";\nimport type { AvatarMicOffer } from \"../avatar-mic/types\";\n\n/** Where the consent card's privacy link goes: the site's privacy notice, at its live avatar section. */\nconst PRIVACY_HREF = \"/privacy#live-avatar\";\n\n/** How long a joined room waits for the avatar's video before the session is given up. */\nconst SPEAKER_WAIT_MS = 30_000;\n/** Past a session's end, how long before the browser leaves a room that is somehow still open. */\nconst END_GRACE_MS = 10_000;\n/** How far the server's end may sit from this browser's clock before the browser counts down on its own clock. */\nconst CLOCK_TOLERANCE_MS = 5_000;\n/**\n * Under `endUnattended`: out of sight, how long a session whose sound the browser holds back goes on before it is ended\n * (see `attend`). Long enough for a visitor who has just switched to the Chat tab or another browser tab to come back\n * and find \"Tap to turn on sound\"; short enough that a session nobody can hear is not paid for to its end.\n */\nconst UNHEARD_GRACE_MS = 5_000;\n/**\n * Under `endUnattended`: from the end of the speech at its source (`speech-ended`) to the answer's playout as the\n * visitor hears it. The worker's voice lags its source, and the server keeps a session for that lag: its planned end is\n * the speech's first frame + its length + a 3 s tail allowance (global-speech-svc `docs/AVATAR_WEB_API.md`, \"Timing\").\n * This is that allowance plus 2 s, so the last words are never cut, and the server's own end, which counts as a natural\n * finish only when no end request came before it, comes first while the server ends a session after its answer.\n */\nconst PLAYOUT_TAIL_MS = 5_000;\n/**\n * Stage D: how long the worker's voice may be quiet (the room's `speaking`) before the answer it read counts as played\n * out. The room server reports a pause between sentences as quiet too; this is well past one.\n */\nconst QUIET_PLAYED_OUT_MS = 2_500;\n/**\n * Stage D: how long an answer the session accepted may take to be heard once the voice is quiet (the session plays it\n * after the one before, from its own queue) before it counts as played out all the same: the server dropped it\n * unplayed, or read it on from the one before with no pause the room could report.\n */\nconst OWED_VOICE_WAIT_MS = 15_000;\n/** Stage D: while the mic records, how often the session is told so again (a `listening` mark), at most. */\nconst LISTENING_MARK_MS = 10_000;\n/**\n * Stage D: the session reads one answer at a time, and refuses the next (`busy`, before it reads or spends anything)\n * while the one before is still played or checked. So the next is sent only once the one before has played out here,\n * and a `busy` is asked again with the same key (the session judges a refusal that took nothing afresh): after the\n * refusal's `retryAfterSeconds` ({@link BUSY_RETRY_MS} without one), doubling up to {@link BUSY_RETRY_MAX_MS}, at most\n * {@link MAX_BUSY_RETRIES} times. That outlasts the longest answer before it where no voice tells its end, well within\n * the session's turn limits, and the session's own end comes first.\n */\nconst BUSY_RETRY_MS = 2_000;\nconst BUSY_RETRY_MAX_MS = 8_000;\nconst MAX_BUSY_RETRIES = 24;\n\n/**\n * The avatar service refuses an answer more than fifteen minutes old (`not_eligible`; `MAX_AGE_MS` in global-speech-svc\n * `src/avatar/web/eligibility.ts`, measured from the answer's `createdAt` on the service's clock). If it changes, this\n * and the \"fifteen minutes\" in the `notEligible` and `startNewChatDetail` strings change with it.\n */\nconst SERVICE_MAX_AGE_MS = 15 * 60_000;\n/**\n * How long after an answer was created the view offers the avatar for it: a minute less than the service allows, so\n * that a visitor who reads the consent card near the edge is not sent through Start and a create request the service\n * will refuse. A visitor on the consent card when the answer crosses this age is moved to the start-over step (one\n * timer, set for that moment). Once Start is pressed, the create is skipped only past the service's own limit.\n */\nconst ANSWER_OFFER_MS = SERVICE_MAX_AGE_MS - 60_000;\n/** The longest delay a browser's `setTimeout` keeps (about 24.8 days): a longer one fires at once. */\nconst MAX_TIMER_MS = 2_147_483_647;\n\n/**\n * The longest question the Avatar tab's own box takes: the avatar service's limit for a question the visitor typed (the\n * chat's own limit is longer).\n */\nconst ASK_MAX_LENGTH = 300;\n/** The most references an answer the avatar service reads may cite (`eligibility.ts`); it needs at least one. */\nconst MAX_REFERENCES = 64;\n/**\n * Where this browser notes the day (UTC) it had a live session, so the box can say the day's session is used and ask in\n * text. A hint only: the limits are the server's.\n */\nconst USED_ON_KEY = \"boff.explore.avatarUsedOn\";\n\n/** The control each step puts focus on when the one the visitor was on has gone. */\nconst PRIMARY =\n '[data-avatar-primary], [data-boff-explore=\"panel-continue-chat\"]';\n\ninterface Offer extends AvatarOffer {\n /** The locale availability was asked for: the consent copy shown and the create request are both in this one. */\n locale: ExploreLocale;\n copy: AvatarConsentCopy;\n}\n\n/** What the page shows of a session: never its secret or its room token. */\ninterface ShownSession {\n /** When this browser counts the session as over, on its own clock. */\n endsAt: number;\n captions: { locale: string; text: string };\n /** Only the first part of the answer is spoken (the 201's `excerpt`): the status line says so while it plays. */\n excerpt: boolean;\n /**\n * A session that reads the answers after the first (Stage D): what it is doing between them, for the status line and\n * the box. Null for a session of one answer, which shows exactly as before.\n */\n followUp: ShownFollowUp | null;\n}\n\n/**\n * Why an answer after the first was not read (Stage D): the session's refusal, or the browser's own reason, the chat's\n * answer having failed (`answer_failed`) or the session having given no answer it could read (`failed`). Each is one\n * line ({@link FOLLOW_UP_TEXT}), and the answer stays in Chat.\n */\ntype FollowUpUnread = AvatarTurnRefusal | \"answer_failed\" | \"failed\";\n\n/** What a session that reads the answers after the first shows between them (Stage D). */\ninterface ShownFollowUp {\n /** An answer is being read: its voice is heard, or the session accepted it and it is still to be heard. */\n speaking: boolean;\n /**\n * The question asked from the box: its answer being written (`asking`), or sent to the session to read (`reading`).\n * The box takes no other meanwhile.\n */\n pending: \"asking\" | \"reading\" | null;\n /** Why the last answer was not read, until the next question. */\n unread: FollowUpUnread | null;\n /** The session reads no more answers: it has read all it may, or its turns no longer reach it. */\n closed: boolean;\n}\n\n/** A session's answers after the first (Stage D), from its 201 until it ends. */\ninterface FollowUpRun {\n limits: AvatarFollowUps;\n /** The conversation the session reads (compared, never shown): the box asks it only while the chat is this one. */\n token: string;\n /** The answers the session has read or accepted, the first included. */\n answers: number;\n /** The worker's voice, as the room last told it (`speaking`). */\n voice: boolean;\n /** The worker's voice has been told at all in this session: without it, the view cannot tell when an answer ends. */\n heard: boolean;\n /** Counts each time the worker's voice starts: an answer heard after its request was sent is not still owed. */\n starts: number;\n /** An answer the session read or accepted is still to be heard (the first, until its voice comes). */\n owed: boolean;\n /** The quiet hold ({@link QUIET_PLAYED_OUT_MS}), or the wait for an answer still to be heard. */\n quiet: ReturnType<typeof setTimeout> | null;\n /**\n * The question asked from the box, while its answer is written, with that answer's id once the chat has one (the\n * chat drops a failed answer that had no text, but the session is still asked for it: see `readFollowUp`); null\n * otherwise.\n */\n asked: (AskedHere & { answerId: string | null }) | null;\n /** The answer the session is asked to read, from its first request until it is read or not; null otherwise. */\n due: DueAnswer | null;\n /** The wait before an answer refused `busy` is asked again ({@link BUSY_RETRY_MS}); null otherwise. */\n retry: ReturnType<typeof setTimeout> | null;\n /** Every answer sent to the session to read: none is sent twice. */\n sent: Set<string>;\n /** Counts each question asked from the box: a send that resolves after a later one records nothing. */\n seq: number;\n}\n\n/** An answer a session that reads the answers after the first is asked to read (Stage D, `readFollowUp`). */\ninterface DueAnswer {\n messageId: string;\n /** The same for every request for it: the session answers a replay what it answered first, and never reads twice. */\n idempotencyKey: string;\n /**\n * Why this browser can already tell the session will not read it (a failed answer, one its checks refuse), or null.\n * It is sent all the same, so the session's idle end counts from its refusal (see `readFollowUp`), and this is the\n * line the tab shows when it is not read.\n */\n known: FollowUpUnread | null;\n /** The `busy` refusals it has had ({@link MAX_BUSY_RETRIES}). */\n busy: number;\n /** A request for it is on its way. */\n sending: boolean;\n}\n\n/**\n * How a session ended. `finished` means the server closed the room (the worker left, or the room was closed by the\n * server) while the avatar was live, or the session's time ran out with the room still open: the browser cannot tell the\n * avatar reading to the end from a server-side stop or a hand-over, so the words for it say only that the live avatar\n * has ended.\n */\ntype EndedHow = \"finished\" | \"stopped\" | \"failed\" | \"interrupted\";\n\ntype Phase =\n | { name: \"idle\" }\n | { name: \"checking\" }\n | { name: \"inert\" }\n | { name: \"needs-answer\"; offer: Offer }\n | { name: \"consent\"; offer: Offer; messageId: string }\n /** Under `any`: Not now. The card is offered again when the tab next opens, while the answer is fresh. */\n | { name: \"declined\"; offer: Offer }\n /** Under `any`: \"Start when ready\" pressed while the answer is still being written (see {@link WaitRun}). */\n | { name: \"waiting\"; offer: Offer }\n | { name: \"refused\"; reason: AvatarRefusal }\n | { name: \"bot-check\"; offer: Offer; messageId: string }\n | { name: \"creating\" }\n | { name: \"pending\"; session: ShownSession }\n | { name: \"live\"; session: ShownSession }\n | { name: \"ended\"; how: EndedHow };\n\nconst IDLE: Phase = { name: \"idle\" };\nconst INERT: Phase = { name: \"inert\" };\n\n/** One press of Start, until its create request has answered. */\ninterface StartRun {\n /** Set when the visitor (or the page) gave up on it, with the reason to end a session it still creates. */\n cancelled: AvatarEndReason | null;\n turnstile: TurnstileRun | null;\n}\n\n/**\n * One press of \"Start when ready\", until the answer is ready and checked (or the start is called off). The press is the\n * visitor's consent for exactly what it is bound to: this conversation, its first question and the answer on its way,\n * the site, the locale and the page, and the consent version and bot check that availability named. Any of them\n * changing calls it off with nothing created; once the answer is ready, availability is asked again and the answer\n * checked again, and anything that differs shows the card again instead of creating.\n */\ninterface WaitRun {\n bound: {\n token: string;\n questionId: string;\n answerId: string;\n site: string;\n locale: ExploreLocale;\n path: string;\n consentVersion: string;\n botCheck: AvatarBotCheck;\n };\n /** The room module, loading while the answer is written. */\n module: Promise<AvatarLiveModule>;\n /** The availability question asked again once the answer is ready; null until then. */\n check: AbortController | null;\n}\n\n/** A created session, from its 201 until it ends. */\ninterface SessionHandle {\n session: AvatarSession;\n base: string;\n headers: Readonly<Record<string, string>>;\n module: AvatarLiveModule;\n /** The join, once started. */\n room: Promise<ReceiveOnlySession | null> | null;\n /** The joined room, once joined: `enablePlayback` must be called inside the visitor's tap, so not via a promise. */\n joined: ReceiveOnlySession | null;\n /** When this browser counts the session as over, on its own clock (see `begin`). */\n endsAt: number;\n /** The avatar's video has arrived. */\n speakerArrived: boolean;\n /**\n * The avatar's voice (its audio track) has arrived. Until then a held-back sound is the room's guess (it reports a\n * suspended audio context as soon as it connects, and takes it back once the voice actually plays), not a voice\n * speaking to nobody.\n */\n voiceArrived: boolean;\n /** The browser holds the avatar's sound back (`playback-blocked`'s `sound`): nobody hears it until a tap. */\n soundHeld: boolean;\n /** The answer has played out: its speech ended at the source, and {@link PLAYOUT_TAIL_MS} has passed since. */\n playedOut: boolean;\n /** The attention rule's timers (see `attend`): the grace for held-back sound, and the playout tail. */\n unheard: ReturnType<typeof setTimeout> | null;\n tail: ReturnType<typeof setTimeout> | null;\n /** The answers after the first (Stage D); null for a session of one answer. */\n followUps: FollowUpRun | null;\n done: boolean;\n}\n\n/** What a create's answer is acted on with (see `settle`): what the start was for, and where its requests go. */\ninterface CreateContext {\n module: AvatarLiveModule;\n offer: Offer;\n messageId: string;\n /** The conversation the create names (compared, never shown). */\n conversationToken: string;\n base: string;\n headers: Readonly<Record<string, string>>;\n}\n\n/** Clear the attention rule's timers (see `attend`), and Stage D's: the session has ended, or the view has gone. */\nfunction stopAttending(handle: SessionHandle): void {\n if (handle.unheard !== null) clearTimeout(handle.unheard);\n if (handle.tail !== null) clearTimeout(handle.tail);\n handle.unheard = null;\n handle.tail = null;\n const run = handle.followUps;\n if (run === null) return;\n if (run.quiet !== null) clearTimeout(run.quiet);\n if (run.retry !== null) clearTimeout(run.retry);\n run.quiet = null;\n run.retry = null;\n}\n\nconst REFUSAL_TEXT: Record<AvatarRefusal, keyof AvatarLiveStrings> = {\n busy: \"busy\",\n limits: \"limits\",\n region: \"region\",\n locale: \"locale\",\n paused: \"paused\",\n not_eligible: \"notEligible\",\n answer_claimed: \"answerClaimed\",\n};\n\n/** Stage D: why an answer after the first was not read, one line each (see {@link FollowUpUnread}). */\nconst FOLLOW_UP_TEXT: Record<FollowUpUnread, keyof AvatarLiveStrings> = {\n no_time: \"followUpNoTime\",\n max_answers: \"followUpMaxAnswers\",\n // The same line as a first answer the checks refuse: it stays in Chat as text.\n not_eligible: \"notSpoken\",\n answer_claimed: \"answerClaimed\",\n limits: \"followUpLimits\",\n paused: \"followUpPaused\",\n busy: \"followUpUnread\",\n answer_failed: \"answerFailed\",\n failed: \"followUpUnread\",\n};\n\n/**\n * What the first exchange is. `answer` is the one the avatar may read; the others say why there is none yet, or never in\n * this conversation:\n *\n * - `empty`: nothing asked yet; `asking`: the first question, its answer on its way;\n * - `text-only` (under `any`): a completed first answer that fails a check the service makes and this browser can make\n * too (it cites none of the site's documentation, more references than the service takes, files with the question);\n * - `failed` (under `any`): the first answer failed;\n * - `ask-here` (under `any`): the first answer to a question that was not asked in this tab as the first of a new chat;\n * - `start-over`: anything else (a second question, an answer whose id the service cannot take, one too old).\n */\ntype ExchangeKind =\n | \"empty\"\n | \"asking\"\n | \"answer\"\n | \"text-only\"\n | \"failed\"\n | \"ask-here\"\n | \"start-over\";\n\n/** What the conversation offers the avatar to read. */\ninterface Exchange {\n kind: ExchangeKind;\n /** The answer the avatar may read, or null: set for `answer` only. */\n answerId: string | null;\n /**\n * The conversation can never be read: its first answer failed or is unusable, or it has gone past the first\n * exchange. Only a new chat can be. False while there is simply nothing to read yet.\n */\n startOver: boolean;\n /**\n * With an answer: until when (this browser's clock, in milliseconds) it is offered, {@link ANSWER_OFFER_MS} after its\n * `createdAt`. `NaN` for an answer whose `createdAt` is missing or cannot be read, which is never offered (the\n * service would refuse it). `NaN` without an answer too.\n */\n offerUntil: number;\n /** The first question, while the conversation is its first exchange; null otherwise. */\n question: ExploreMessage | null;\n /** Asking: the id the server gave the answer on its way (the one it keeps once complete), or null before then. */\n pendingAnswerId: string | null;\n /** Under `any`: the first question was asked in this tab, as the first of a new chat, in this page's visit. */\n askedHere: boolean;\n}\n\nconst EMPTY: Exchange = {\n kind: \"empty\",\n answerId: null,\n startOver: false,\n offerUntil: NaN,\n question: null,\n pendingAnswerId: null,\n askedHere: false,\n};\nconst START_OVER: Exchange = { ...EMPTY, kind: \"start-over\", startOver: true };\n\n/**\n * A question this tab asked as the first of a new chat, recorded only once the chat's `send` has actually added it: the\n * id of the USER message it added, and the conversation's token as that send ended (null when the server never named\n * one: a send that failed before the server took it). Not its text: the server stores the question normalized (line\n * endings, control characters, runs of blank lines: `normalizeExploreMessage` in global-support-svc), so the words in\n * the chat can differ from the ones the box sent, and the id alone already names the one message.\n */\ninterface AskedHere {\n messageId: string;\n token: string | null;\n}\n\n/**\n * Which rules the exchange is read by: the server's `questions`, the question this tab asked as the first of a new\n * chat (null when none), the conversation's token now, and whether the chat has a question on its way (`sending` or\n * `streaming`).\n */\ninterface ExchangeRules {\n any: boolean;\n askedHere: AskedHere | null;\n token: string | null;\n inFlight: boolean;\n}\n\nconst SUGGESTED_RULES: ExchangeRules = {\n any: false,\n askedHere: null,\n token: null,\n inFlight: false,\n};\n\n/**\n * Whether `question` is the one this tab asked: the very USER message its send added (its id), in the conversation that\n * send ended in. A question asked in Chat is never it, whatever it says (the same words included), and neither is a\n * conversation opened from History whose first question happens to read the same.\n */\nfunction isAskedHere(question: ExploreMessage, rules: ExchangeRules): boolean {\n const asked = rules.askedHere;\n return (\n rules.any &&\n asked !== null &&\n question.id === asked.messageId &&\n asked.token === rules.token\n );\n}\n\n/** A message's `createdAt` in milliseconds, or `NaN` when it is missing or not a date. */\nfunction createdAtOf(message: ExploreMessage): number {\n const raw: unknown = message.createdAt;\n return typeof raw === \"string\" && raw !== \"\" ? Date.parse(raw) : NaN;\n}\n\n/**\n * The exchange as it stands at `now`: an answer past its {@link Exchange.offerUntil} (or with no readable time) is\n * no longer offered, and only a new chat can be.\n */\nfunction offeredAt(exchange: Exchange, now: number): Exchange {\n // `!(now < …)` and not `now >= …`: with a `NaN` deadline (no readable `createdAt`) it is true, so the answer is not\n // offered.\n return exchange.answerId !== null && !(now < exchange.offerUntil)\n ? START_OVER\n : exchange;\n}\n\n/**\n * The checks on a first answer that the avatar service makes and this browser can make as well (`eligibility.ts` in\n * global-speech-svc): it is an answer (`answered`), it cites between one and {@link MAX_REFERENCES} references, and no\n * files came with the question. The service stays the judge: this only keeps the card from offering what it refuses.\n */\nfunction readable(question: ExploreMessage, answer: ExploreMessage): boolean {\n const references = answer.references?.length ?? 0;\n return (\n answer.answered === true &&\n references >= 1 &&\n references <= MAX_REFERENCES &&\n (question.attachments?.length ?? 0) === 0\n );\n}\n\n/**\n * The one answer the avatar may read, and why there is none. The avatar service accepts a conversation only when it\n * holds EXACTLY two messages: the first USER message and the first ASSISTANT answer, COMPLETED. This is the same rule,\n * so the avatar is never offered, and the visitor never goes through consent and the bot check, for a conversation the\n * service would refuse:\n *\n * - exactly that exchange: its answer;\n * - nothing asked yet, or the question asked and its answer still on its way: nothing yet (the view says to choose a\n * suggested question, or that the answer is coming, and offers the avatar once the answer completes);\n * - anything else (a failed or empty first answer, a second question, whatever came after a failed answer asked\n * again without Retry): never, in this conversation (the view says to start a new chat).\n *\n * The service also refuses an answer more than fifteen minutes old: a conversation restored from this browser's\n * history, say. That depends on the time as well as the messages, so it is applied on top of this (`offeredAt`), with\n * the answer's {@link Exchange.offerUntil}.\n *\n * Under `suggested`, that the question is one of the suggested ones is the service's to judge (`not_eligible`), not the\n * browser's. Under `any` (the Avatar tab's own box), the answer is offered only to a question this tab asked as the\n * first of a new chat, and only when it passes the checks this browser can make too ({@link readable}); a failed\n * first answer is told apart, so the tab can say so.\n */\nfunction firstExchange(\n messages: readonly ExploreMessage[] | undefined,\n rules: ExchangeRules = SUGGESTED_RULES,\n): Exchange {\n if (!messages || messages.length === 0) return EMPTY;\n if (messages.length > 2) return START_OVER;\n const [question, answer] = messages;\n if (question?.role !== \"USER\") return START_OVER;\n const first = { question, askedHere: isAskedHere(question, rules) };\n if (answer === undefined) {\n // The question alone. On its way: the answer is coming. Otherwise none is: the chat drops a failed answer that\n // had no text (and one a reload cut short), so under `any` the tab says the answer failed; under `suggested`, as\n // before, nothing has been answered yet.\n if (rules.inFlight) return { ...EMPTY, ...first, kind: \"asking\" };\n return rules.any ? { ...START_OVER, ...first, kind: \"failed\" } : EMPTY;\n }\n if (answer.role !== \"ASSISTANT\") return START_OVER;\n if (answer.status === \"PENDING\" || answer.status === \"RUNNING\") {\n return {\n ...EMPTY,\n ...first,\n kind: \"asking\",\n pendingAnswerId: isAvatarMessageId(answer.id) ? answer.id : null,\n };\n }\n if (rules.any && answer.status === \"FAILED\") {\n return { ...START_OVER, ...first, kind: \"failed\" };\n }\n if (\n answer.status !== \"COMPLETED\" ||\n answer.content.trim() === \"\" ||\n !isAvatarMessageId(answer.id)\n ) {\n return START_OVER;\n }\n if (rules.any && !first.askedHere) {\n return { ...START_OVER, ...first, kind: \"ask-here\" };\n }\n if (rules.any && !readable(question, answer)) {\n return { ...START_OVER, ...first, kind: \"text-only\" };\n }\n return {\n ...EMPTY,\n ...first,\n kind: \"answer\",\n answerId: answer.id,\n offerUntil: createdAtOf(answer) + ANSWER_OFFER_MS,\n };\n}\n\n/** Whether the chat has a question on its way. */\nfunction inFlight(conversation: AvatarConversation | null): boolean {\n return (\n conversation?.phase === \"sending\" || conversation?.phase === \"streaming\"\n );\n}\n\n/** What the Avatar tab's mic reads of the tab to tell whether its box takes a question now. */\ninterface AskSlot {\n /** The server reads typed questions (`questions: \"any\"`): the tab has a box of its own. */\n any: boolean;\n phase: Phase[\"name\"];\n /** The exchange as offered now. */\n kind: ExchangeKind;\n /** The box asks ordinary questions, whose answers stay text (see `textMode`). */\n textMode: boolean;\n /** Why the box's Send cannot be pressed now, or null when it can. */\n reason: string | null;\n /** The box is under a live session that reads the answers after the first (Stage D: {@link followUpBox}). */\n followUp: boolean;\n}\n\n/**\n * Whether the Avatar tab's own box takes a question right now, for the avatar: the one rule the mic is offered by (with\n * the site's opt-in and the server's offer), while the chat can take one and the box does not ask in text. Stage C: the\n * box that asks the avatar the first question of a new chat (nothing asked yet). Stage D: also the box under a live\n * session that reads the answers after the first, for the next question of its conversation.\n */\nfunction acceptsQuestion(slot: AskSlot): boolean {\n if (!slot.any || slot.textMode || slot.reason !== null) return false;\n return slot.phase === \"needs-answer\"\n ? slot.kind === \"empty\"\n : slot.phase === \"live\" && slot.followUp;\n}\n\n/**\n * Whether a live session's box asks it the next question (Stage D): the session reads the answers after the first, has\n * not read all it may, and the chat is still the conversation it reads. (While a question of the box's is on its way,\n * the box shows, and Send waits for it.)\n */\nfunction followUpBox(\n phase: Phase,\n run: FollowUpRun | null,\n token: string | null,\n): boolean {\n return (\n phase.name === \"live\" &&\n run !== null &&\n phase.session.followUp !== null &&\n !phase.session.followUp.closed &&\n token === run.token\n );\n}\n\n/** The mic's offer from an availability answer, stamped with this browser's clock; null without one. */\nfunction micOfferOf(result: AvatarAvailability): AvatarMicOffer | null {\n return result.kind === \"available\" && result.offer.stt !== undefined\n ? { ...result.offer.stt, receivedAt: Date.now() }\n : null;\n}\n\n/** Today, as UTC: the day the box's note of a used session is for. */\nfunction utcToday(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\n/** Whether this browser noted a live session today. Storage that cannot be read (a private window) is no note. */\nfunction usedTodayHere(): boolean {\n try {\n return window.localStorage.getItem(USED_ON_KEY) === utcToday();\n } catch {\n return false;\n }\n}\n\n/** Note today's live session, where this browser lets the page keep it. */\nfunction noteUsedToday(): void {\n try {\n window.localStorage.setItem(USED_ON_KEY, utcToday());\n } catch {\n // Storage blocked: the box simply does not know, and the server's limits still hold.\n }\n}\n\n/** A tenth of a second of silence, as a WAV data URI, made once, the first time a Start needs it. */\nlet silence: string | null = null;\n\nfunction silentWav(): string {\n if (silence !== null) return silence;\n // 8 kHz, 8-bit mono: 800 samples at the mid level (128) is silence.\n const rate = 8_000;\n const samples = rate / 10;\n const bytes = new Uint8Array(44 + samples);\n const view = new DataView(bytes.buffer);\n const text = (at: number, value: string) => {\n for (let i = 0; i < value.length; i += 1) {\n bytes[at + i] = value.charCodeAt(i);\n }\n };\n text(0, \"RIFF\");\n view.setUint32(4, 36 + samples, true);\n text(8, \"WAVE\");\n text(12, \"fmt \");\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true); // PCM\n view.setUint16(22, 1, true); // mono\n view.setUint32(24, rate, true);\n view.setUint32(28, rate, true); // bytes a second\n view.setUint16(32, 1, true); // bytes a frame\n view.setUint16(34, 8, true); // bits a sample\n text(36, \"data\");\n view.setUint32(40, samples, true);\n bytes.fill(128, 44);\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n silence = `data:audio/wav;base64,${btoa(binary)}`;\n return silence;\n}\n\n/**\n * Let the page play sound later: called straight from the visitor's tap on Start (browsers allow sound only from inside\n * a gesture, and Safari on iOS keeps an element locked until then), it plays a tenth of a second of silence on the\n * element the room's audio will use, and pauses it. \"Tap to turn on sound\" stays for a browser that still holds sound\n * back. An element already playing a room's audio is left alone.\n */\nfunction unlockSound(audio: HTMLAudioElement | null): void {\n if (audio === null || audio.srcObject) return;\n try {\n audio.src = silentWav();\n void Promise.resolve(audio.play()).then(\n () => audio.pause(),\n () => undefined,\n );\n } catch {\n // A browser that cannot play it now: the room's own playback, and the sound button, still work.\n }\n}\n\n/**\n * The step that offers `messageId` to the visitor: the consent card, unless this visit has already used that answer\n * (`claimed` holds every answer a session was created for, or that the server said it already has one for), in which\n * case it says so instead. The ways back to a consent card for an answer that may have been used in the meantime go\n * through here: the availability answer, and returning from a bot check.\n */\nfunction offering(\n offer: Offer,\n messageId: string,\n claimed: ReadonlySet<string>,\n): Phase {\n return claimed.has(messageId)\n ? { name: \"refused\", reason: \"answer_claimed\" }\n : { name: \"consent\", offer, messageId };\n}\n\nasync function loadModule(\n load: () => Promise<AvatarLiveModule>,\n): Promise<AvatarLiveModule> {\n const loaded: unknown = await load();\n const join =\n loaded !== null && typeof loaded === \"object\"\n ? (loaded as Partial<AvatarLiveModule>).joinReceiveOnly\n : undefined;\n if (typeof join !== \"function\") {\n throw new Error(\"The live avatar module could not be loaded.\");\n }\n return loaded as AvatarLiveModule;\n}\n\n/** `m:ss`. */\nfunction clock(seconds: number): string {\n const whole = Math.max(0, Math.ceil(seconds));\n return `${Math.floor(whole / 60)}:${String(whole % 60).padStart(2, \"0\")}`;\n}\n\nexport interface AvatarLiveViewProps {\n live: ExplorePanelAvatarLive;\n /** The Avatar view is showing: the panel is open and its Avatar tab is selected. */\n active: boolean;\n /**\n * The panel is open, whichever tab it shows. With `active` it tells the Chat tab (open, not active: the pane is only\n * hidden, and a session under way keeps playing) from the panel closing (not open: what is under way ends).\n */\n open: boolean;\n locale: ExploreLocale;\n /** The product the panel speaks for, when it is one product's own; null on the portfolio's. */\n productName: string | null;\n /** The approved still picture. */\n still: { src: string; alt: string };\n /** The Avatar tab as it was before the live avatar: shown whenever the live avatar is not offered or not reachable. */\n fallback: ReactNode;\n /**\n * Back to the Chat tab. Like the Chat tab itself, it calls off a start that has not been sent yet, and leaves a\n * session under way speaking.\n */\n onContinueInChat: () => void;\n /**\n * Told whenever the avatar's voice starts or stops being the page's: its status line while a session is being\n * created, joined or played (\"Connecting to the live avatar…\", \"The avatar is speaking.\"), and null otherwise (and\n * when the view goes). The panel holds Chat's own read-aloud and dictation meanwhile, so the page never speaks in two\n * voices and the microphone never takes down the avatar's.\n */\n onVoiceHold?: (line: string | null) => void;\n /** \"Continue in Chat\" in the panel's language: the panel's own word for it, so this chunk carries none of the panel's. */\n continueInChat: string;\n /**\n * \"New chat\" in the panel's language, the panel's own word for it: the button that starts over (the conversation's\n * `reset`, as the chat's own New chat button does, then the Chat tab) where this conversation can never be read.\n */\n newChat: string;\n /** \"Send\" and \"Try asking\" in the panel's language, for the Avatar tab's own question box. */\n send: string;\n tryAsking: string;\n /** The suggested questions the chat view shows: the box's chips. */\n prompts: readonly string[];\n /** No precise pointer: the box is not focused by itself, so the keyboard does not cover the view. */\n touchFirst: boolean;\n /** The host router's path, when it has one: a \"Start when ready\" is called off when it changes. */\n currentPath: string | undefined;\n /**\n * Nothing to ask the server about: an incomplete config, no gateway, no shared conversation to read (no provider, or a\n * read-only shared one), or a locale whose strings have not been reviewed. The tab stays as it was. Decided by\n * `ExploreAvatarLive`, which also decides whether this view is loaded at all; it can change while this view is\n * mounted (the panel's locale switching), and what is under way then ends.\n */\n off: boolean;\n /** {@link avatarApiBase} of the SDK's gateway, null when there is none to use. */\n base: string | null;\n /** Headers every request carries: the alpha gateway's access headers, and nothing on production. */\n headers: Readonly<Record<string, string>>;\n /** The panel's conversation, null when there is no provider. */\n conversation: AvatarConversation | null;\n}\n\nexport function AvatarLiveView({\n live,\n active,\n open,\n locale,\n productName,\n still,\n fallback,\n onContinueInChat,\n onVoiceHold,\n continueInChat,\n newChat,\n send,\n tryAsking,\n prompts,\n touchFirst,\n currentPath,\n off,\n base,\n headers,\n conversation,\n}: AvatarLiveViewProps) {\n const S = avatarLiveStrings(locale);\n const uid = useId();\n const consentTitleId = `${uid}-consent`;\n\n /**\n * Which first questions the server reads the answer to, as its last availability answer said (`suggested` until one\n * says `any`). Kept in a ref as well, for the steps that read it between renders.\n */\n const [questions, setQuestions] = useState<AvatarQuestions>(\"suggested\");\n const questionsRef = useRef<AvatarQuestions>(\"suggested\");\n /**\n * The question this tab asked as the first of a new chat, in this page's visit; null when none. Recorded only once the\n * chat's `send` says which message it added (see `ask`), and set and cleared through {@link setAskedHere} alone.\n */\n const askedHereRef = useRef<AskedHere | null>(null);\n /**\n * Counts every ask from the box and every clearing of {@link askedHereRef}: an ask whose send resolves after a New\n * chat, a reset, another conversation or a later ask records nothing.\n */\n const askSeqRef = useRef(0);\n /** Re-renders the view when {@link askedHereRef} changes: a ref alone would leave the card unshown. */\n const [, setAskedHereTick] = useState(0);\n const setAskedHere = useCallback((next: AskedHere | null) => {\n if (next === null) {\n askSeqRef.current += 1;\n if (askedHereRef.current === null) return;\n }\n askedHereRef.current = next;\n setAskedHereTick((tick) => tick + 1);\n }, []);\n\n // Compared, never shown: see `getConversationToken`.\n const token = conversation?.getConversationToken() ?? null;\n const exchange = firstExchange(conversation?.messages, {\n any: questions === \"any\",\n askedHere: askedHereRef.current,\n token,\n inFlight: inFlight(conversation),\n });\n // Re-rendered by the timer below at the moment the answer stops being offered: the time is read here, on each render.\n const [ageTick, setAgeTick] = useState(0);\n const shown = offeredAt(exchange, Date.now());\n const { answerId, startOver } = shown;\n /** Until when the answer is offered, while one is. */\n const offerUntil = answerId === null ? null : exchange.offerUntil;\n\n const [phase, setPhase] = useState<Phase>(IDLE);\n const [blocked, setBlocked] = useState(false);\n const [now, setNow] = useState(() => Date.now());\n /** The box's text: the view's own, never the chat's draft. */\n const [draft, setDraft] = useState(\"\");\n /**\n * The longest question the box takes: the avatar service's limit, or the chat's own (the live catalog's) where that is\n * shorter, since the chat refuses a longer one without adding it.\n */\n const chatMaxLength = conversation?.catalog.limits.maxMessageLength;\n const askMaxLength =\n chatMaxLength !== undefined &&\n Number.isFinite(chatMaxLength) &&\n chatMaxLength >= 1\n ? Math.min(ASK_MAX_LENGTH, Math.floor(chatMaxLength))\n : ASK_MAX_LENGTH;\n /** A line the view owes the visitor: a new chat was started for the avatar, or a \"Start when ready\" was called off. */\n const [note, setNote] = useState<\"new-chat\" | \"cancelled\" | null>(null);\n /** This browser noted a live session today (read once the view is on the page). */\n const [usedToday, setUsedToday] = useState(false);\n\n /**\n * The live view is on the page: the Avatar tab is selected in an open panel, and the live avatar is on. It is also\n * hidden while `off` puts the fallback in its place (the panel's locale switching to one whose strings have not been\n * reviewed, say), which unmounts the video and audio elements a room is attached to.\n */\n const showing = active && !off;\n /**\n * Hidden only because the open panel shows its Chat tab: the pane is CSS-hidden, its video and audio elements stay\n * mounted and attached, so a session under way can keep playing (see `leave`).\n */\n const behindChat = open && !active && !off;\n\n const phaseRef = useRef<Phase>(IDLE);\n /** This render's view of everything the asynchronous steps read, so they never act on a stale one. */\n const latest = useRef({\n live,\n locale,\n base,\n headers,\n off,\n currentPath,\n showing,\n });\n latest.current = { live, locale, base, headers, off, currentPath, showing };\n const conversationRef = useRef(conversation);\n conversationRef.current = conversation;\n const waitRef = useRef<WaitRun | null>(null);\n /** A question from the box is on its way to the chat: a second press sends nothing. */\n const sendingRef = useRef(false);\n /** The box asks ordinary questions, whose answers stay text (set each render; see `textBox`). */\n const textBoxRef = useRef(false);\n /** The mic's offer from the last availability answer (Stage C): null when it carried none. */\n const [micOffer, setMicOffer] = useState<AvatarMicOffer | null>(null);\n /** Ends whatever the mic has under way and releases the microphone: every way out of the view calls it. */\n const micCancelRef = useRef<() => void>(() => undefined);\n /**\n * Stage D: sends the answer waiting to be read once it may go (`sendDue`, set each render), for the timers that\n * decide when: the quiet that ends the answer before it, and the wait after a `busy`.\n */\n const sendDueRef = useRef<(handle: SessionHandle) => void>(() => undefined);\n\n const checkRef = useRef<AbortController | null>(null);\n /**\n * The locale the last availability question was asked for (or settled without asking): a later change of locale asks\n * again (see the effect on `locale`), and a view that has just asked for the new locale does not ask twice.\n */\n const askedLocale = useRef(locale);\n const startRef = useRef<StartRun | null>(null);\n const sessionRef = useRef<SessionHandle | null>(null);\n /**\n * Every answer whose session this visit has already created (or found already read): none of them is offered again.\n * A set and not the latest one: a create the visitor gave up on can answer long after they moved to another chat and\n * used its first answer, and what it reports is added to what is known, never put in its place.\n */\n const claimedRef = useRef<Set<string>>(new Set());\n\n const rootRef = useRef<HTMLDivElement>(null);\n const videoRef = useRef<HTMLVideoElement>(null);\n const audioRef = useRef<HTMLAudioElement>(null);\n const botBoxRef = useRef<HTMLDivElement>(null);\n\n const go = useCallback((next: Phase) => {\n phaseRef.current = next;\n setPhase(next);\n }, []);\n\n /**\n * Whether the visitor can see the view: it is showing, and the page is not hidden. Out of sight, a browser may hold a\n * muted video back (Chrome pauses one that is off screen or in a background tab), so its `playing` cannot be waited\n * for there (see `goLive`).\n */\n const inSight = useCallback(\n (): boolean =>\n latest.current.showing &&\n (typeof document === \"undefined\" ||\n document.visibilityState !== \"hidden\"),\n [],\n );\n\n const setMode = useCallback((next: AvatarQuestions) => {\n questionsRef.current = next;\n setQuestions(next);\n }, []);\n\n /**\n * The exchange right now, read when a step needs it rather than from the last render: the answer may have stopped\n * being offered since (it grew too old while nothing re-rendered), and the server's `questions` may have just changed.\n */\n const exchangeNow = useCallback(\n (): Exchange =>\n offeredAt(\n firstExchange(conversationRef.current?.messages, {\n any: questionsRef.current === \"any\",\n askedHere: askedHereRef.current,\n token: conversationRef.current?.getConversationToken() ?? null,\n inFlight: inFlight(conversationRef.current),\n }),\n Date.now(),\n ),\n [],\n );\n\n /** The answer offered right now (see {@link exchangeNow}). */\n const offeredNow = useCallback(\n (): string | null => exchangeNow().answerId,\n [exchangeNow],\n );\n\n /** The page the visitor is on: the host router's path, else the window's. */\n const pathNow = useCallback(\n (): string =>\n latest.current.currentPath ??\n (typeof window === \"undefined\" ? \"\" : window.location.pathname),\n [],\n );\n\n /** Back to what the offer shows for the answer offered now: its consent card, or the step without one. */\n const reoffer = useCallback(\n (offer: Offer): Phase => {\n const messageId = offeredNow();\n return messageId === null\n ? { name: \"needs-answer\", offer }\n : offering(offer, messageId, claimedRef.current);\n },\n [offeredNow],\n );\n\n /** End the session: tell the server (unless it ended it), leave the room, and show how it ended. */\n const finish = useCallback(\n (how: EndedHow, reason: AvatarEndReason | null) => {\n const handle = sessionRef.current;\n if (!handle || handle.done) return;\n handle.done = true;\n stopAttending(handle);\n sessionRef.current = null;\n if (reason !== null) {\n sendEnd({\n base: handle.base,\n headers: handle.headers,\n sessionId: handle.session.sessionId,\n secret: handle.session.endSecret,\n reason,\n });\n }\n const room = handle.joined;\n handle.joined = null;\n if (room) void room.leave().catch(() => undefined);\n setBlocked(false);\n go({ name: \"ended\", how });\n },\n [go],\n );\n\n /**\n * The avatar is on: its video plays (`playing`), or, while the view is out of sight (the Chat tab, a hidden page),\n * its video has arrived. A browser may hold a muted video back out of sight and play it only once it shows again, so\n * waiting for `playing` there would leave a session that is speaking counted as never started, and ended as failed\n * when the server closes it. Under `any`, the box notes the day's session as used (a hint for the visitor: the limits\n * are the server's).\n */\n const goLive = useCallback(() => {\n const current = phaseRef.current;\n const handle = sessionRef.current;\n if (current.name !== \"pending\" || !handle) return;\n handle.speakerArrived = true;\n if (questionsRef.current === \"any\") {\n noteUsedToday();\n setUsedToday(true);\n }\n go({ name: \"live\", session: current.session });\n }, [go]);\n\n /**\n * The attention rule, under `live.endUnattended` (without it, nothing here runs and nothing changes): a paid session\n * never outlives the visitor's attention. Out of sight (behind the Chat tab, on a hidden page) the answer under way\n * still plays to its end; past that, nothing is paid for that nobody can see or hear:\n *\n * - **Played out** (its speech ended at the source, and {@link PLAYOUT_TAIL_MS} has passed): a live session out of\n * sight ends at once, as finished. This is the lifecycle rule every later stage keeps: **an idle tail after an\n * answer runs only while the Avatar view is in sight**, and going out of sight during it ends the session then. (A\n * session still waiting for the avatar's video is the speaker wait's, {@link SPEAKER_WAIT_MS}.)\n * - **Sound held back** (`playback-blocked`'s `sound`: autoplay refused, or the room's audio context suspended), once\n * the avatar's voice has arrived: in sight, \"Tap to turn on sound\" shows and nothing ends. Out of sight nobody can\n * tap it, so after {@link UNHEARD_GRACE_MS} the session ends early: \"The live avatar stopped early.\" and \"The full\n * answer is in Chat.\". Back in sight, or the sound let through, within the grace: nothing ends.\n *\n * Both send the end with reason `user`, and once (`finish`). Run whenever what it reads changes: the view's sight, the\n * page's, the sound and the playout.\n *\n * In a session that reads the answers after the first (Stage D), an answer has played out once the worker's voice\n * has gone quiet (`heardVoice`), and a question asked from the box is no idle tail: its answer is on its way to be\n * read, out of sight as any answer under way is, and the rule applies again once that one has played out or was not\n * read.\n */\n const attend = useCallback(() => {\n const handle = sessionRef.current;\n if (!handle || handle.done || latest.current.live.endUnattended !== true) {\n return;\n }\n const shown = phaseRef.current;\n if (shown.name !== \"pending\" && shown.name !== \"live\") return;\n const current = shown.name;\n const away = !inSight();\n const followUp = shown.session.followUp;\n const asking = followUp !== null && followUp.pending !== null;\n if (away && handle.playedOut && current === \"live\" && !asking) {\n finish(\"finished\", \"user\");\n return;\n }\n if (!(away && handle.soundHeld && handle.voiceArrived)) {\n if (handle.unheard !== null) {\n clearTimeout(handle.unheard);\n handle.unheard = null;\n }\n return;\n }\n if (handle.unheard !== null) return;\n handle.unheard = setTimeout(() => {\n handle.unheard = null;\n if (\n sessionRef.current === handle &&\n !handle.done &&\n latest.current.live.endUnattended === true &&\n handle.soundHeld &&\n handle.voiceArrived &&\n !inSight()\n ) {\n finish(\"interrupted\", \"user\");\n }\n }, UNHEARD_GRACE_MS);\n }, [finish, inSight]);\n\n /**\n * Show what a session that reads the answers after the first is doing (Stage D): `next` over what its status line and\n * box show now, and the captions and excerpt flag of an answer it has accepted (`spoken`). Nothing for a session of one\n * answer, or one that has ended.\n */\n const showFollowUp = useCallback(\n (\n handle: SessionHandle,\n next: Partial<ShownFollowUp>,\n spoken?: Pick<ShownSession, \"captions\" | \"excerpt\">,\n ) => {\n const current = phaseRef.current;\n if (\n sessionRef.current !== handle ||\n handle.done ||\n (current.name !== \"pending\" && current.name !== \"live\") ||\n current.session.followUp === null\n ) {\n return;\n }\n const session: ShownSession = {\n ...current.session,\n ...spoken,\n followUp: { ...current.session.followUp, ...next },\n };\n go(\n current.name === \"live\"\n ? { name: \"live\", session }\n : { name: \"pending\", session },\n );\n },\n [go],\n );\n\n /**\n * Tell a session that reads the answers after the first what the visitor does (Stage D): a mark its idle end waits\n * for (`asking`, `listening`), or an interrupt. Sent, and not waited for: what it answers changes nothing here. A mark\n * that does not land only lets the idle end come sooner, and the session's own end bounds everything.\n */\n const tell = useCallback(\n (handle: SessionHandle, kind: \"asking\" | \"listening\" | \"interrupt\") => {\n if (handle.done || handle.followUps === null) return;\n void requestTurn({\n base: handle.base,\n headers: handle.headers,\n sessionId: handle.session.sessionId,\n secret: handle.session.endSecret,\n kind,\n });\n },\n [],\n );\n\n /**\n * The worker's voice has been quiet for `delay` (Stage D): the answer it read has played out, unless one the session\n * accepted is still to be heard, which gets {@link OWED_VOICE_WAIT_MS} more to start. Played out, the status line waits\n * for the next question, the attention rule reads the answer as played out (`attend`), and an answer waiting for this\n * one to end goes to the session (`sendDue`). The voice coming back calls the wait off (`heardVoice`).\n */\n const whenQuiet = useCallback(\n (handle: SessionHandle, delay: number) => {\n const run = handle.followUps;\n if (run === null) return;\n const wait = (ms: number) => {\n if (run.quiet !== null) clearTimeout(run.quiet);\n run.quiet = setTimeout(() => {\n run.quiet = null;\n if (sessionRef.current !== handle || handle.done || run.voice) {\n return;\n }\n if (run.owed) {\n run.owed = false;\n wait(OWED_VOICE_WAIT_MS);\n return;\n }\n handle.playedOut = true;\n showFollowUp(handle, { speaking: false });\n attend();\n sendDueRef.current(handle);\n }, ms);\n };\n wait(delay);\n },\n [attend, showFollowUp],\n );\n\n /**\n * The worker's voice heard, or gone quiet (the room's `speaking`), in a session that reads the answers after the first\n * (Stage D). Heard, an answer is being read; quiet for {@link QUIET_PLAYED_OUT_MS}, it has played out (`whenQuiet`).\n * A session of one answer reads none of this: `speech-ended` tells its end, as before.\n */\n const heardVoice = useCallback(\n (handle: SessionHandle, speaking: boolean) => {\n const run = handle.followUps;\n if (run === null) return;\n run.voice = speaking;\n if (!speaking) {\n whenQuiet(handle, QUIET_PLAYED_OUT_MS);\n return;\n }\n if (run.quiet !== null) clearTimeout(run.quiet);\n run.quiet = null;\n run.heard = true;\n run.starts += 1;\n run.owed = false;\n handle.playedOut = false;\n showFollowUp(handle, { speaking: true });\n },\n [showFollowUp, whenQuiet],\n );\n\n /**\n * Send the answer the session is asked to read (`run.due`, see `readFollowUp`), once it may go. The session reads one\n * answer at a time and refuses another (`busy`) while the one before is still played, so where this view hears the\n * worker's voice, the request waits until the answer before has played out here (`whenQuiet` sends it then); where no\n * voice is told at all, it goes at once. One request with the answer's own key, asked again with that same key when it\n * got no reply (the server then answers what it answered the first time, and never synthesizes twice), and after a\n * `busy` (a refusal that took nothing, which the server judges afresh): after its `retryAfterSeconds`, doubling up to\n * {@link BUSY_RETRY_MAX_MS}, at most {@link MAX_BUSY_RETRIES} times, never past the session's end, and, where the\n * voice is heard again, once it has played out. Accepted, its captions show while it is read; not read, the status\n * line says why in one line (this browser's own reason first), and the answer stays in Chat.\n */\n const sendDue = useCallback(\n (handle: SessionHandle) => {\n const run = handle.followUps;\n const due = run?.due ?? null;\n if (\n run === null ||\n due === null ||\n due.sending ||\n run.retry !== null ||\n handle.done ||\n sessionRef.current !== handle ||\n (run.heard && !handle.playedOut)\n ) {\n return;\n }\n due.sending = true;\n // The voice's starts as the request goes: one heard after this is the voice of this answer.\n const starts = run.starts;\n const read = () =>\n requestTurn({\n base: handle.base,\n headers: handle.headers,\n sessionId: handle.session.sessionId,\n secret: handle.session.endSecret,\n kind: \"answer\",\n messageId: due.messageId,\n idempotencyKey: due.idempotencyKey,\n });\n const notRead = (unread: FollowUpUnread, closed: boolean) => {\n run.due = null;\n showFollowUp(handle, {\n pending: null,\n unread: due.known ?? unread,\n ...(closed ? { closed } : {}),\n });\n attend();\n };\n void (async () => {\n let result = await read();\n if (result.kind === \"failed\" && result.lost && !handle.done) {\n result = await read();\n }\n due.sending = false;\n if (sessionRef.current !== handle || handle.done || run.due !== due) {\n return;\n }\n if (\n result.kind === \"refused\" &&\n result.reason === \"busy\" &&\n due.busy < MAX_BUSY_RETRIES\n ) {\n due.busy += 1;\n // The voice heard again: asked again once it has played out.\n if (run.heard && !handle.playedOut) return;\n const delay = Math.max(\n result.retryAfterSeconds === undefined\n ? BUSY_RETRY_MS\n : result.retryAfterSeconds * 1_000,\n Math.min(BUSY_RETRY_MAX_MS, BUSY_RETRY_MS * 2 ** (due.busy - 1)),\n );\n if (Date.now() + delay >= handle.endsAt) {\n // The session ends before it could be asked again: no time is left to read it.\n notRead(\"no_time\", false);\n return;\n }\n run.retry = setTimeout(() => {\n run.retry = null;\n sendDueRef.current(handle);\n }, delay);\n return;\n }\n if (result.kind !== \"accepted\") {\n notRead(\n result.kind === \"refused\" ? result.reason : \"failed\",\n result.kind === \"gone\" ||\n (result.kind === \"refused\" && result.reason === \"max_answers\"),\n );\n return;\n }\n run.due = null;\n run.answers += 1;\n // Heard since its request went, this answer's voice came before its reply: it is owed no more, and once that\n // voice has been quiet past the hold, it has already played out.\n const heardSince = run.starts !== starts;\n run.owed = !heardSince;\n const playing = !heardSince || run.voice || run.quiet !== null;\n if (playing) handle.playedOut = false;\n showFollowUp(\n handle,\n {\n speaking: playing,\n pending: null,\n unread: null,\n closed: run.answers >= run.limits.maxAnswers,\n },\n { captions: result.captions, excerpt: result.excerpt },\n );\n if (!playing) {\n attend();\n return;\n }\n // With the voice quiet (and told at all in this session), the wait for this answer to be heard starts now;\n // with it heard, once the answer before it has played out.\n if (run.owed && run.heard && !run.voice) whenQuiet(handle, 0);\n })();\n },\n [attend, showFollowUp, whenQuiet],\n );\n sendDueRef.current = sendDue;\n\n /**\n * Ask the session to read `messageId`, the answer to the question asked from the box (Stage D), and show it on its\n * way (`sendDue`). `known` is this browser's own reason when it can already tell the answer will not be read (it\n * failed, or the checks this browser makes refuse it): the session is asked all the same, because only its refusal\n * of an answer ends the wait an `asking` mark holds open and starts its idle end from now; it stays the judge, and\n * the line shown is this browser's.\n */\n const readFollowUp = useCallback(\n (\n handle: SessionHandle,\n messageId: string,\n known: FollowUpUnread | null,\n ) => {\n const run = handle.followUps;\n if (run === null) return;\n run.sent.add(messageId);\n const idempotencyKey = newIdempotencyKey();\n if (idempotencyKey === null) {\n showFollowUp(handle, { pending: null, unread: known ?? \"failed\" });\n attend();\n return;\n }\n run.due = { messageId, idempotencyKey, known, busy: 0, sending: false };\n showFollowUp(handle, { pending: \"reading\", unread: null });\n sendDue(handle);\n },\n [attend, sendDue, showFollowUp],\n );\n\n /** Give up on a Start still on its way to a session. A session it still creates is ended with `reason`. */\n const cancelStart = useCallback((reason: AvatarEndReason) => {\n const run = startRef.current;\n if (!run) return;\n startRef.current = null;\n run.cancelled = reason;\n run.turnstile?.cancel();\n }, []);\n\n /**\n * Go to the step an availability answer, asked in `locale`, leads to. A `refused` answer still says which questions the\n * server reads, for the box (a `limits` refusal under `any` keeps the box, asking in text).\n */\n const applyAvailability = useCallback(\n (result: AvatarAvailability, locale: ExploreLocale) => {\n const { live } = latest.current;\n setMicOffer(micOfferOf(result));\n if (result.kind === \"inert\") {\n setMode(\"suggested\");\n go(INERT);\n return;\n }\n if (result.kind === \"refused\") {\n setMode(result.questions);\n go({ name: \"refused\", reason: result.reason });\n return;\n }\n // A fresh answer from the server, a fresh look at this browser's note of the day's session.\n setUsedToday(usedTodayHere());\n // The copy for the version the server named, in the locale it was asked about (a later locale change asks\n // again: see the effect on `locale`).\n const copy = avatarConsentCopy(result.offer.consentVersion, locale);\n // A consent version this SDK has no reviewed copy for: no card, rather than words the server does not record. Nor\n // copy that describes another bot check than the one the server runs, or other questions than the ones it reads:\n // the visitor would agree to a notice that is wrong about it.\n if (\n copy === null ||\n copy.botCheck !== result.offer.botCheck ||\n copy.questions !== result.offer.questions\n ) {\n setMode(\"suggested\");\n go(INERT);\n return;\n }\n // A server that checks for bots, and no site key this page may use for its check: no start could pass it.\n if (\n result.offer.botCheck === \"turnstile\" &&\n turnstileSiteKeyOf(live) === null\n ) {\n setMode(\"suggested\");\n go(INERT);\n return;\n }\n setMode(result.offer.questions);\n go(reoffer({ ...result.offer, locale, copy }));\n },\n [go, reoffer, setMode],\n );\n\n const check = useCallback(() => {\n const { live, locale, base, headers, off } = latest.current;\n checkRef.current?.abort();\n checkRef.current = null;\n askedLocale.current = locale;\n if (off || base === null) {\n go(INERT);\n return;\n }\n const controller = new AbortController();\n checkRef.current = controller;\n go({ name: \"checking\" });\n void requestAvailability({\n base,\n headers,\n site: live.site,\n locale,\n signal: controller.signal,\n }).then((result) => {\n if (checkRef.current !== controller) return;\n checkRef.current = null;\n applyAvailability(result, locale);\n });\n }, [applyAvailability, go]);\n\n const begin = useCallback(\n (session: AvatarSession, context: CreateContext) => {\n const { offer } = context;\n // Count down on the server's end when this browser's clock agrees with it, else on this browser's own clock.\n const received = Date.now();\n const longest = offer.maxSessionSeconds * 1000;\n const ahead = session.endsAt - received;\n const endsAt =\n ahead > 0 && ahead <= longest + CLOCK_TOLERANCE_MS\n ? session.endsAt\n : received + longest;\n // Stage D: the answers after the first, only where the 201 offers them, the words the visitor agreed to describe\n // them, and the tab has its own box to ask them. Anything else reads its one answer, as before.\n const followUps: FollowUpRun | null =\n session.followUps !== undefined &&\n offer.copy.followUps === true &&\n offer.questions === \"any\"\n ? {\n limits: session.followUps,\n token: context.conversationToken,\n answers: 1,\n voice: false,\n heard: false,\n starts: 0,\n owed: true,\n quiet: null,\n asked: null,\n due: null,\n retry: null,\n sent: new Set([context.messageId]),\n seq: 0,\n }\n : null;\n sessionRef.current = {\n session,\n base: context.base,\n headers: context.headers,\n module: context.module,\n room: null,\n joined: null,\n endsAt,\n speakerArrived: false,\n voiceArrived: false,\n soundHeld: false,\n playedOut: false,\n unheard: null,\n tail: null,\n followUps,\n done: false,\n };\n setBlocked(false);\n setNow(received);\n go({\n name: \"pending\",\n session: {\n endsAt,\n captions: session.captions,\n excerpt: session.excerpt,\n followUp:\n followUps === null\n ? null\n : {\n speaking: true,\n pending: null,\n unread: null,\n closed: followUps.answers >= followUps.limits.maxAnswers,\n },\n },\n });\n },\n [go],\n );\n\n /**\n * Act on a create's answer. `givenUp` is why the view no longer waits for it, or null while it does: the visitor (or\n * the page) gave the start up while the request was on its way (`StartRun.cancelled`), or the answer came after the\n * create's deadline, when the view had already said the live avatar couldn't start. Given up on, an answer changes\n * nothing on the page but what it says about the answer having been used: a session it created is ended at once with\n * `givenUp`, and never joined.\n */\n const settle = useCallback(\n (\n result: AvatarCreateResult,\n givenUp: AvatarEndReason | null,\n context: CreateContext,\n ) => {\n const created =\n result.kind === \"created\"\n ? {\n sessionId: result.session.sessionId,\n secret: result.session.endSecret,\n }\n : result.kind === \"unusable\"\n ? { sessionId: result.sessionId, secret: result.endSecret }\n : null;\n // A session now exists for this answer (this create made it, or the server says an earlier one did): it is used.\n const claimed =\n created !== null ||\n (result.kind === \"refused\" && result.reason === \"answer_claimed\");\n if (claimed) claimedRef.current.add(context.messageId);\n if (givenUp !== null) {\n // Given up while the request was on its way, or answered past its deadline: a session it created is ended at\n // once.\n if (created !== null) {\n sendEnd({\n base: context.base,\n headers: context.headers,\n sessionId: created.sessionId,\n secret: created.secret,\n reason: givenUp,\n });\n }\n // The visitor may be back on the consent card for this very answer by now (they left during the create and came\n // back before it answered): it has been read, so the card gives way to saying so rather than offering it again.\n const shown = phaseRef.current;\n if (\n claimed &&\n shown.name === \"consent\" &&\n shown.messageId === context.messageId\n ) {\n go({ name: \"refused\", reason: \"answer_claimed\" });\n }\n return;\n }\n switch (result.kind) {\n case \"created\":\n begin(result.session, context);\n return;\n case \"unusable\":\n sendEnd({\n base: context.base,\n headers: context.headers,\n sessionId: result.sessionId,\n secret: result.endSecret,\n reason: \"client_error\",\n });\n go({ name: \"ended\", how: \"failed\" });\n return;\n case \"refused\":\n go({ name: \"refused\", reason: result.reason });\n return;\n case \"consent\":\n // The consent version moved on: ask again, and show the consent that is current now.\n check();\n return;\n case \"inert\":\n go(INERT);\n return;\n case \"failed\":\n go({ name: \"ended\", how: \"failed\" });\n return;\n }\n },\n [begin, check, go],\n );\n\n /**\n * From the visitor's consent to a session for `messageId`: Start on the card, or a \"Start when ready\" whose answer is\n * now ready and checked (with the room module it has been loading meanwhile, `preloaded`). One create request, never\n * sent again by itself: a failed create ends as failed, and only another tap can start again.\n */\n const launch = useCallback(\n (\n offer: Offer,\n messageId: string,\n preloaded: Promise<AvatarLiveModule> | null,\n ) => {\n const { live, base, headers } = latest.current;\n if (base === null) return;\n const exchangeAtStart = exchangeNow();\n // The answer has grown too old for the service since the card was shown (a timer that has not run yet: a throttled\n // background tab, say), or the conversation has moved on: no request the service would refuse.\n if (exchangeAtStart.answerId !== messageId) {\n go(reoffer(offer));\n return;\n }\n // Already read in this visit (a \"Start when ready\" whose answer a session elsewhere in this visit used): say so.\n if (claimedRef.current.has(messageId)) {\n go({ name: \"refused\", reason: \"answer_claimed\" });\n return;\n }\n // When the service will refuse this answer as too old: the module and a bot check can take a while, and a create\n // that starts after this is not sent.\n const refusedFrom =\n exchangeAtStart.offerUntil - ANSWER_OFFER_MS + SERVICE_MAX_AGE_MS;\n // The key for the bot check, where the server runs one; null where it runs none.\n const siteKey =\n offer.botCheck === \"turnstile\" ? turnstileSiteKeyOf(live) : null;\n // A bot check with no key this page may use, or with no WebCrypto (a page that is not a secure context) to bind it\n // to a create request: no live avatar can start here. Nothing is loaded for a start that cannot happen (no module,\n // no bot-check script), and the tab stays as it was.\n if (\n offer.botCheck === \"turnstile\" &&\n (siteKey === null || !canBindBotCheck())\n ) {\n go(INERT);\n return;\n }\n // The create request's values, read once, here. A bot check is bound to exactly these (`avatarBotBinding`, before its\n // widget is rendered), so the request that follows it carries this same body and reads nothing again.\n const conversationToken =\n conversationRef.current?.getConversationToken() ?? null;\n const idempotencyKey = newIdempotencyKey();\n if (\n conversationToken === null ||\n !isAvatarConversationToken(conversationToken) ||\n idempotencyKey === null\n ) {\n // Nothing to create a session for: no module, no bot check.\n go({ name: \"ended\", how: \"failed\" });\n return;\n }\n const body: AvatarCreateBody = {\n site: live.site,\n locale: offer.locale,\n conversationToken,\n messageId,\n consentVersion: offer.consentVersion,\n manifestVersion: live.manifestVersion,\n };\n const run: StartRun = { cancelled: null, turnstile: null };\n startRef.current = run;\n // Only now that the visitor has agreed: the live module (already loading, for a \"Start when ready\"), and the bot\n // check where the server runs one. Where it runs none, there is no Cloudflare script, no widget and no token: the\n // module loads and the request follows.\n const module = preloaded ?? loadModule(live.load);\n let turnstile: TurnstileRun | null = null;\n if (siteKey === null) {\n go({ name: \"creating\" });\n } else {\n go({ name: \"bot-check\", offer, messageId });\n turnstile = runTurnstile(\n botBoxRef.current,\n siteKey,\n \"avatar_start\",\n avatarBotBinding(body),\n );\n run.turnstile = turnstile;\n }\n void (async () => {\n let loaded: AvatarLiveModule;\n let botToken: string | undefined;\n try {\n [loaded, botToken] = await Promise.all([module, turnstile?.token]);\n } catch {\n turnstile?.cancel();\n if (run.cancelled === null) {\n startRef.current = null;\n go(INERT);\n }\n return;\n }\n // The widget has done its work.\n turnstile?.cancel();\n if (run.cancelled !== null) return;\n // The answer grew too old for the service while the module or the bot check took their time: nothing is created,\n // and the view says to start a new chat (it reads the answer as too old now).\n if (!(Date.now() < refusedFrom)) {\n startRef.current = null;\n go({ name: \"needs-answer\", offer });\n return;\n }\n if (turnstile !== null) go({ name: \"creating\" });\n const context: CreateContext = {\n module: loaded,\n offer,\n messageId,\n conversationToken,\n base,\n headers,\n };\n // Sent: from here an answer that never comes is `failed` (the server may have made the session), and the wait\n // ends by the create's deadline whatever the network does (see `requestCreate`).\n const result = await requestCreate({\n base,\n headers,\n idempotencyKey,\n botToken,\n body,\n // An answer past the deadline, after the view has said the live avatar couldn't start: a session it made is\n // ended at once with its own secret, and never joined. The reason is the visitor's own where they gave the\n // start up first, else `client_error`. It reads `run` and never writes it, so the deadline's `failed` below is\n // shown whichever of the two is handled first.\n onLate: (late) =>\n settle(late, run.cancelled ?? \"client_error\", context),\n });\n if (startRef.current === run) startRef.current = null;\n settle(result, run.cancelled, context);\n })();\n },\n [exchangeNow, go, reoffer, settle],\n );\n\n /** Start, on the consent card. Under `any`, the tap also lets the page play the avatar's sound later. */\n const start = useCallback(() => {\n const current = phaseRef.current;\n if (current.name !== \"consent\") return;\n if (current.offer.questions === \"any\") unlockSound(audioRef.current);\n launch(current.offer, current.messageId, null);\n }, [launch]);\n\n /**\n * Call off a \"Start when ready\": nothing is created, and the view goes back to the answer being written (or to what\n * the conversation now is). `told`: the visitor did not cancel it themselves, so the view says it did not start.\n */\n const cancelWaiting = useCallback(\n (told: boolean) => {\n const wait = waitRef.current;\n waitRef.current = null;\n wait?.check?.abort();\n const current = phaseRef.current;\n if (current.name !== \"waiting\") return;\n if (told) setNote(\"cancelled\");\n go({ name: \"needs-answer\", offer: current.offer });\n },\n [go],\n );\n\n /** Whether what a \"Start when ready\" was bound to still holds, for the exchange as it is now. */\n const bindingHolds = useCallback(\n (bound: WaitRun[\"bound\"], exchange: Exchange): boolean => {\n const { live, locale } = latest.current;\n return (\n conversationRef.current?.getConversationToken() === bound.token &&\n exchange.question?.id === bound.questionId &&\n live.site === bound.site &&\n locale === bound.locale &&\n pathNow() === bound.path\n );\n },\n [pathNow],\n );\n\n /**\n * \"Start when ready\", on the card shown while the answer is written: the visitor's consent for this conversation's\n * first answer, once it is ready (see {@link WaitRun}). Pressed only for a question this tab asked as the first of a\n * new chat, once the server has taken it.\n */\n const startWhenReady = useCallback(() => {\n const current = phaseRef.current;\n if (current.name !== \"needs-answer\") return;\n const { live, locale } = latest.current;\n const exchange = exchangeNow();\n const token = conversationRef.current?.getConversationToken() ?? null;\n if (\n exchange.kind !== \"asking\" ||\n !exchange.askedHere ||\n exchange.question === null ||\n exchange.pendingAnswerId === null ||\n token === null ||\n !isAvatarConversationToken(token)\n ) {\n return;\n }\n unlockSound(audioRef.current);\n const module = loadModule(live.load);\n // Read when the answer is ready; a failure then is the start's. Until then, nothing is left unhandled.\n module.catch(() => undefined);\n waitRef.current = {\n bound: {\n token,\n questionId: exchange.question.id,\n answerId: exchange.pendingAnswerId,\n site: live.site,\n locale,\n path: pathNow(),\n consentVersion: current.offer.consentVersion,\n botCheck: current.offer.botCheck,\n },\n module,\n check: null,\n };\n setNote(null);\n go({ name: \"waiting\", offer: current.offer });\n }, [exchangeNow, go, pathNow]);\n\n /**\n * The answer a \"Start when ready\" waited for is ready: ask availability again (no cache) and check the answer again,\n * and create only if nothing differs. Anything that does (another consent version or bot check, a refusal, the answer\n * or the conversation) shows what is offered now instead: the card again, or why there is none.\n */\n const confirm = useCallback(\n (offer: Offer, wait: WaitRun) => {\n const { live, locale, base, headers } = latest.current;\n if (base === null) {\n cancelWaiting(true);\n return;\n }\n const controller = new AbortController();\n wait.check = controller;\n void requestAvailability({\n base,\n headers,\n site: live.site,\n locale,\n signal: controller.signal,\n }).then((result) => {\n if (waitRef.current !== wait || phaseRef.current.name !== \"waiting\") {\n return;\n }\n waitRef.current = null;\n // (A change of locale while this was asked has already called the start off, dropping this answer: see the\n // effect on `locale`. So it is the answer for the locale the panel is in.)\n const exchange = exchangeNow();\n const same =\n result.kind === \"available\" &&\n result.offer.consentVersion === wait.bound.consentVersion &&\n result.offer.botCheck === wait.bound.botCheck &&\n result.offer.questions === \"any\" &&\n exchange.kind === \"answer\" &&\n exchange.answerId === wait.bound.answerId &&\n bindingHolds(wait.bound, exchange);\n if (!same || result.kind !== \"available\") {\n applyAvailability(result, locale);\n return;\n }\n // The offer as it is now (the same version, bot check and questions; the session's length may have moved).\n launch({ ...offer, ...result.offer }, wait.bound.answerId, wait.module);\n });\n },\n [applyAvailability, bindingHolds, cancelWaiting, exchangeNow, launch],\n );\n\n /** The visitor's Stop, at any step from Start on (and Cancel, for a \"Start when ready\"). */\n const stop = useCallback(() => {\n micCancelRef.current();\n const current = phaseRef.current;\n if (current.name === \"waiting\") {\n cancelWaiting(false);\n return;\n }\n if (current.name === \"bot-check\") {\n // Nothing was created: back to the consent card, if its answer is still offered.\n cancelStart(\"user\");\n go(reoffer(current.offer));\n return;\n }\n if (current.name === \"creating\") {\n cancelStart(\"user\");\n go({ name: \"ended\", how: \"stopped\" });\n return;\n }\n if (current.name === \"pending\" || current.name === \"live\") {\n finish(\"stopped\", \"user\");\n }\n }, [cancelStart, cancelWaiting, finish, go, reoffer]);\n\n /**\n * The view going out of the visitor's sight, by what took it away:\n *\n * - `user`: the panel closing, or the live avatar going off (the fallback takes the view's place, unmounting the\n * video and audio a room is attached to, and Stop with them). Everything under way ends, a session with `user`.\n * - `chat`: the open panel showing its Chat tab instead. Before the create is sent nothing paid exists, so it is\n * called off as `user` would (C3): a check is dropped (opening the view asks again), a \"Start when ready\" and a bot\n * check are called off with nothing created. From the create on (`creating`, `pending`, `live`) nothing ends: the\n * pane is only hidden, the room's video and audio stay attached, and the avatar speaks to its planned end.\n * - `hidden`: the page hidden (another browser tab, another app). A \"Start when ready\" is called off and a bot check\n * goes back to the consent card, so the view is as the visitor left it when they come back; a check is kept. From\n * the create on nothing ends, as for `chat`: the server ends the session at its planned end, so a hidden page adds\n * no paid time.\n * - `page_hide`: the page being left (`pagehide`). Everything ends, a session with `page_hide`; a check is kept.\n *\n * Out of sight with a session whose video has already arrived, it is counted as live (see `goLive`). What a session\n * kept out of sight may still end on is the attention rule's (`attend`), under `live.endUnattended`.\n *\n * In every case, first, the mic (Stage C) stops whatever it has under way and releases the microphone: it never\n * records out of sight.\n */\n const leave = useCallback(\n (event: \"user\" | \"chat\" | \"hidden\" | \"page_hide\") => {\n micCancelRef.current();\n const current = phaseRef.current;\n const reason: AvatarEndReason =\n event === \"user\" || event === \"chat\" ? \"user\" : \"page_hide\";\n const how: EndedHow = reason === \"user\" ? \"stopped\" : \"interrupted\";\n /** Once the create has been sent, only the panel closing, the live avatar going off and leaving the page end it. */\n const keepsSession = event === \"chat\" || event === \"hidden\";\n switch (current.name) {\n case \"checking\": {\n if (reason !== \"user\") return;\n const controller = checkRef.current;\n checkRef.current = null;\n controller?.abort();\n go(IDLE);\n return;\n }\n case \"waiting\":\n // A \"Start when ready\" is for this view as the visitor left it: called off, with nothing created.\n cancelWaiting(true);\n return;\n case \"bot-check\":\n cancelStart(reason);\n go(reason === \"user\" ? IDLE : reoffer(current.offer));\n return;\n case \"creating\":\n if (keepsSession) return;\n cancelStart(reason);\n go({ name: \"ended\", how });\n return;\n case \"pending\":\n case \"live\":\n if (keepsSession) {\n if (\n current.name === \"pending\" &&\n sessionRef.current?.speakerArrived\n ) {\n goLive();\n }\n return;\n }\n finish(how, reason);\n return;\n default:\n return;\n }\n },\n [cancelStart, cancelWaiting, finish, go, goLive, reoffer],\n );\n\n // The Avatar view showing, and hiding. Opening it asks again, except where this visit has already used the answer,\n // and except during a session, which shows as it is, counting down to its end.\n //\n // Hidden behind the Chat tab, a session under way keeps playing (`leave(\"chat\")`). Anything else that hides the view\n // (the panel closing, the live avatar going off) ends whatever is under way (`leave(\"user\")`): a bot check is called\n // off, a create in flight is ended once it answers, a session is ended and its room left. Coming back asks again.\n useEffect(() => {\n if (!showing) {\n leave(behindChat ? \"chat\" : \"user\");\n return;\n }\n const current = phaseRef.current;\n if (\n current.name === \"creating\" ||\n current.name === \"pending\" ||\n current.name === \"live\"\n ) {\n // Back during a session, after the Chat tab: nothing is asked again and nothing reset. The countdown is to the\n // session's end as `begin` set it, and is brought up to date at once rather than at its next tick.\n setNow(Date.now());\n return;\n }\n const offered = offeredNow();\n const used = offered !== null && claimedRef.current.has(offered);\n if (current.name === \"ended\" && used) return;\n if (\n current.name === \"refused\" &&\n current.reason === \"answer_claimed\" &&\n used\n ) {\n return;\n }\n if (\n current.name === \"idle\" ||\n current.name === \"inert\" ||\n current.name === \"refused\" ||\n current.name === \"needs-answer\" ||\n current.name === \"consent\" ||\n current.name === \"declined\" ||\n current.name === \"ended\" ||\n // Asking, with nothing actually asking: React's strict mode unmounts and mounts a component again with the state it\n // left, and the unmount in between dropped the question. (This view mounts already showing, the first time the\n // Avatar view opens.)\n (current.name === \"checking\" && checkRef.current === null)\n ) {\n check();\n }\n }, [showing, behindChat, check, leave, offeredNow]);\n\n // The attention rule (`attend`), each time the view comes into sight or goes out of it, once the effect above has\n // dealt with the move (the page's own sight is the visibility handler's, below).\n useEffect(() => {\n attend();\n }, [showing, attend]);\n\n // The panel's locale changing before Start: an availability answer, and the consent copy chosen for it, belong to the\n // locale they were asked about, so the view asks again (or, hidden, starts over when it next opens). A session already\n // under way keeps its own. A \"Start when ready\" is bound to its locale: it is called off, with nothing created (and\n // the availability question it may be asking again for the old locale is dropped with it), and the view asks again\n // for the new one.\n useEffect(() => {\n if (askedLocale.current === locale) return;\n askedLocale.current = locale;\n if (phaseRef.current.name === \"waiting\") cancelWaiting(true);\n const current = phaseRef.current.name;\n if (\n current !== \"checking\" &&\n current !== \"needs-answer\" &&\n current !== \"consent\" &&\n current !== \"declined\" &&\n current !== \"refused\" &&\n current !== \"inert\"\n ) {\n return;\n }\n if (active) {\n check();\n } else {\n checkRef.current?.abort();\n checkRef.current = null;\n go(IDLE);\n }\n }, [active, cancelWaiting, check, go, locale]);\n\n // The first answer arriving (it may complete while the Avatar view shows), or the conversation starting over.\n const kind = shown.kind;\n useEffect(() => {\n const current = phaseRef.current;\n if (current.name === \"needs-answer\" && answerId !== null) {\n go({ name: \"consent\", offer: current.offer, messageId: answerId });\n } else if (current.name === \"consent\" && current.messageId !== answerId) {\n go(\n answerId === null\n ? { name: \"needs-answer\", offer: current.offer }\n : { ...current, messageId: answerId },\n );\n } else if (current.name === \"declined\" && answerId === null) {\n // Not now, and then the conversation moved on (a new chat, say): nothing is declined any more.\n if (kind !== \"asking\") go({ name: \"needs-answer\", offer: current.offer });\n }\n }, [answerId, kind, go]);\n\n // A \"Start when ready\" while its answer is written: on every render, whatever changed (the conversation, its answer,\n // the page, the locale). It holds while the answer it is bound to is on its way; once that answer is ready and passes\n // the checks this browser can make, it is confirmed (`confirm`); anything else calls it off, with nothing created. A\n // failed or unreadable answer then says why itself; anything else says the start was called off.\n useEffect(() => {\n const current = phaseRef.current;\n const wait = waitRef.current;\n if (current.name !== \"waiting\" || wait === null || wait.check !== null) {\n return;\n }\n const now = exchangeNow();\n const holds = bindingHolds(wait.bound, now);\n if (\n holds &&\n now.kind === \"asking\" &&\n now.pendingAnswerId === wait.bound.answerId\n ) {\n return;\n }\n if (\n !holds ||\n now.kind !== \"answer\" ||\n now.answerId !== wait.bound.answerId\n ) {\n cancelWaiting(now.kind !== \"failed\" && now.kind !== \"text-only\");\n return;\n }\n confirm(current.offer, wait);\n });\n\n // A question asked here that Chat's Retry sent again is still the one asked here: the retry's question replaces it\n // (first the one shown while it is on its way, then the server's own, with the token the server may have just\n // minted; each names every id the question had). Declared before the two effects below, which run in the same commit\n // as the change it follows: the record moves to the new question (and its token) before they compare it.\n const resent = conversation?.resent ?? null;\n useEffect(() => {\n const asked = askedHereRef.current;\n if (\n resent === null ||\n asked === null ||\n !resent.replacedMessageIds.includes(asked.messageId)\n ) {\n return;\n }\n setAskedHere({\n messageId: resent.sent.userMessageId,\n token: resent.sent.conversationToken,\n });\n }, [resent, setAskedHere]);\n\n // The question this tab asked is the first of its chat only while that chat lasts: a conversation that empties (New\n // chat, in either tab) has no question asked here.\n const empty = (conversation?.messages.length ?? 0) === 0;\n useEffect(() => {\n if (empty) setAskedHere(null);\n }, [empty, setAskedHere]);\n // And it belongs to the conversation its send ended in, and no other: another token (a conversation opened from\n // History, say, whatever its first question says) ends it.\n useEffect(() => {\n const asked = askedHereRef.current;\n if (asked !== null && asked.token !== token) setAskedHere(null);\n }, [token, setAskedHere]);\n\n // This browser's note of a session today, read each time the view shows (never while rendering on a server), so a\n // page left open past midnight (UTC) has the new day's session.\n useEffect(() => {\n if (showing) setUsedToday(usedTodayHere());\n }, [showing]);\n\n // The answer stops being offered at `offerUntil`: one timer for that moment, set again for a new answer, and cleared\n // when the answer changes or the view goes. It re-renders the view, which then reads the answer as too old (and the\n // effect above moves a consent card to the start-over step). A timer that ran early, or a deadline past the longest\n // delay a timer keeps, is simply set again (`ageTick`).\n useEffect(() => {\n if (offerUntil === null) return;\n const timer = setTimeout(\n () => setAgeTick((tick) => tick + 1),\n Math.min(MAX_TIMER_MS, Math.max(0, offerUntil - Date.now())),\n );\n return () => clearTimeout(timer);\n }, [offerUntil, ageTick]);\n\n /** Start over: the chat's own New chat (the conversation's `reset`), then the Chat tab and its suggested questions. */\n const startNewChat = useCallback(() => {\n conversationRef.current?.reset();\n onContinueInChat();\n }, [onContinueInChat]);\n\n const onRoomEvent = useCallback(\n (handle: SessionHandle, event: ReceiveOnlyEvent) => {\n if (handle.done || sessionRef.current !== handle) return;\n const wasLive = phaseRef.current.name === \"live\";\n switch (event.type) {\n case \"speaker-track\":\n if (event.kind !== \"video\") {\n handle.voiceArrived = true;\n attend();\n return;\n }\n handle.speakerArrived = true;\n // Out of sight, the video's own `playing` may not come until the view shows again.\n if (!inSight()) goLive();\n return;\n case \"playback-blocked\":\n setBlocked(event.blocked);\n handle.soundHeld = event.sound ?? event.blocked;\n attend();\n return;\n case \"speech-ended\":\n // Under `endUnattended` only: the answer counts as played out once the worker's lag has had its time.\n if (\n latest.current.live.endUnattended !== true ||\n handle.tail !== null ||\n handle.playedOut\n ) {\n return;\n }\n handle.tail = setTimeout(() => {\n handle.tail = null;\n if (sessionRef.current !== handle || handle.done) return;\n handle.playedOut = true;\n attend();\n }, PLAYOUT_TAIL_MS);\n return;\n case \"speaking\":\n // Stage D only (a session of one answer reads nothing of it): the end of each answer.\n heardVoice(handle, event.speaking);\n return;\n case \"speaker-left\":\n finish(\n wasLive ? \"finished\" : \"failed\",\n wasLive ? null : \"client_error\",\n );\n return;\n case \"disconnected\":\n if (event.byServer) finish(wasLive ? \"finished\" : \"failed\", null);\n else finish(wasLive ? \"interrupted\" : \"failed\", \"client_error\");\n return;\n }\n },\n [attend, finish, goLive, heardVoice, inSight],\n );\n\n // A created session: join its room once the video and audio elements are on the page.\n useEffect(() => {\n if (phase.name !== \"pending\") return;\n const handle = sessionRef.current;\n if (!handle || handle.room !== null || handle.done) return;\n const video = videoRef.current;\n const audio = audioRef.current;\n if (!video || !audio) {\n finish(\"failed\", \"client_error\");\n return;\n }\n let joining: Promise<ReceiveOnlySession>;\n try {\n joining = handle.module.joinReceiveOnly({\n url: handle.session.join.livekitUrl,\n token: handle.session.join.participantToken,\n workerIdentity: handle.session.join.workerIdentity,\n video,\n audio,\n onEvent: (event) => onRoomEvent(handle, event),\n });\n } catch (error) {\n joining = Promise.reject(error);\n }\n handle.room = joining.then(\n (room) => {\n if (handle.done) {\n void room.leave().catch(() => undefined);\n return null;\n }\n handle.joined = room;\n return room;\n },\n () => {\n if (!handle.done) finish(\"failed\", \"client_error\");\n return null;\n },\n );\n }, [phase.name, finish, onRoomEvent]);\n\n // While a session lasts: give up on a speaker who never comes, and leave a room still open after the session's end.\n useEffect(() => {\n if (phase.name !== \"pending\" && phase.name !== \"live\") return;\n const handle = sessionRef.current;\n if (!handle) return;\n const timers: Array<ReturnType<typeof setTimeout>> = [];\n if (phase.name === \"pending\") {\n timers.push(\n setTimeout(() => {\n if (sessionRef.current === handle && !handle.speakerArrived) {\n finish(\"failed\", \"client_error\");\n }\n }, SPEAKER_WAIT_MS),\n );\n }\n timers.push(\n setTimeout(\n () => {\n if (sessionRef.current !== handle) return;\n finish(\n phaseRef.current.name === \"live\" ? \"finished\" : \"failed\",\n \"client_error\",\n );\n },\n Math.max(0, handle.endsAt + END_GRACE_MS - Date.now()),\n ),\n );\n return () => timers.forEach((timer) => clearTimeout(timer));\n }, [phase.name, finish]);\n\n // The countdown: once a second while a session lasts.\n const ticking = phase.name === \"pending\" || phase.name === \"live\";\n useEffect(() => {\n if (!ticking) return;\n const timer = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(timer);\n }, [ticking]);\n\n // The avatar's voice is the page's from the create until the session ends: the panel is told its status line then,\n // and null otherwise (and when the view goes), and holds Chat's own read-aloud and dictation meanwhile.\n const voiceLine =\n phase.name === \"live\"\n ? S.speaking\n : phase.name === \"creating\" || phase.name === \"pending\"\n ? S.connecting\n : null;\n const onVoiceHoldRef = useRef(onVoiceHold);\n onVoiceHoldRef.current = onVoiceHold;\n useEffect(() => {\n onVoiceHoldRef.current?.(voiceLine);\n }, [voiceLine]);\n useEffect(() => () => onVoiceHoldRef.current?.(null), []);\n\n // Leaving the page ends a session. Hiding it (another browser tab, another app) calls off only what has not been sent\n // yet: a session keeps playing to its planned end, which the server keeps either way (see `leave`), unless the\n // attention rule ends it sooner (`attend`). The page showing again brings the countdown up to date at once: a hidden\n // page's timers may have been held back.\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const onPageHide = () => leave(\"page_hide\");\n const onVisibility = () => {\n if (document.visibilityState === \"hidden\") {\n leave(\"hidden\");\n attend();\n return;\n }\n const current = phaseRef.current.name;\n if (current === \"pending\" || current === \"live\") setNow(Date.now());\n attend();\n };\n window.addEventListener(\"pagehide\", onPageHide);\n document.addEventListener(\"visibilitychange\", onVisibility);\n return () => {\n window.removeEventListener(\"pagehide\", onPageHide);\n document.removeEventListener(\"visibilitychange\", onVisibility);\n };\n }, [attend, leave]);\n\n // Unmounted with something under way: end it, as closing the panel would.\n useEffect(\n () => () => {\n const controller = checkRef.current;\n checkRef.current = null;\n controller?.abort();\n const run = startRef.current;\n startRef.current = null;\n if (run) {\n run.cancelled = \"user\";\n run.turnstile?.cancel();\n }\n const wait = waitRef.current;\n waitRef.current = null;\n wait?.check?.abort();\n const handle = sessionRef.current;\n sessionRef.current = null;\n if (handle && !handle.done) {\n handle.done = true;\n stopAttending(handle);\n sendEnd({\n base: handle.base,\n headers: handle.headers,\n sessionId: handle.session.sessionId,\n secret: handle.session.endSecret,\n reason: \"user\",\n });\n if (handle.joined) void handle.joined.leave().catch(() => undefined);\n }\n },\n [],\n );\n\n const any = questions === \"any\";\n /**\n * Under `any`, the tab asks in text: the day's session is used (this browser's note of it, which a session that\n * played and has now ended leaves too), or the server says its limit is reached. The box then sends ordinary\n * questions, without `surface`, and their answers show here as text (after a session, under how it ended).\n */\n const textMode =\n any &&\n ((usedToday &&\n (phase.name === \"needs-answer\" ||\n phase.name === \"consent\" ||\n phase.name === \"declined\" ||\n phase.name === \"ended\")) ||\n (phase.name === \"refused\" && phase.reason === \"limits\"));\n // The box asks in text exactly where the tab shows the answers as text (see `ask`).\n textBoxRef.current = textMode;\n /** Under `any`: which of the Avatar tab's states shows, on the view's root (for tests and a site's own checks). */\n const askState = !any\n ? undefined\n : textMode\n ? \"text\"\n : phase.name === \"needs-answer\"\n ? kind === \"empty\"\n ? \"ready\"\n : kind\n : phase.name;\n /** Stage D: a live session's answers after the first, as it shows them (null for any other step or session). */\n const followUp = phase.name === \"live\" ? phase.session.followUp : null;\n /** Stage D: the box asks the live session the next question (see {@link followUpBox}). */\n const followUpAsks = followUpBox(\n phase,\n sessionRef.current?.followUps ?? null,\n token,\n );\n /**\n * Why the box's Send cannot be pressed now (an answer on its way, a chat that cannot ask, or, under a live session,\n * the question asked from the box not read or refused yet), or null when it can.\n */\n const askReason =\n inFlight(conversation) || (followUp !== null && followUp.pending !== null)\n ? S.askBusy\n : conversation?.canSend\n ? null\n : S.askUnavailable;\n\n /**\n * The mic's offer again, for a press whose offer has expired or was refused (Stage C): availability asked again, its\n * new offer held. An answer without one leaves the held one as it was, and the press says the mic is not available.\n * No answer at all (the network, its deadline) rejects: the press says to try again, and the mic stays.\n */\n const refreshMicOffer =\n useCallback(async (): Promise<AvatarMicOffer | null> => {\n const { live, locale, base, headers } = latest.current;\n if (base === null) return null;\n const next = micOfferOf(\n await requestAvailabilityAnswer({\n base,\n headers,\n site: live.site,\n locale,\n }),\n );\n if (next !== null) setMicOffer(next);\n return next;\n }, []);\n\n /** A press's final text: into the box, after what the visitor typed, and the box focused to correct it and Send. */\n const onMicText = useCallback(\n (text: string) => {\n setDraft((current) => withHeardText(current, text, askMaxLength));\n if (touchFirst) return;\n rootRef.current\n ?.querySelector<HTMLTextAreaElement>(\n '[data-boff-explore=\"avatar-live-ask-input\"]',\n )\n ?.focus();\n },\n [askMaxLength, touchFirst],\n );\n\n /**\n * The mic tapped to start under a live session that reads the answers after the first (Stage D): while the avatar\n * reads an answer, the session is told to stop it first (`interrupt`). The session goes on, waiting for the question.\n */\n const onMicStart = useCallback(() => {\n const handle = sessionRef.current;\n const current = phaseRef.current;\n if (\n handle === null ||\n handle.followUps === null ||\n handle.done ||\n current.name !== \"live\" ||\n current.session.followUp?.speaking !== true\n ) {\n return;\n }\n const run = handle.followUps;\n tell(handle, \"interrupt\");\n if (run.quiet !== null) clearTimeout(run.quiet);\n run.quiet = null;\n run.owed = false;\n handle.playedOut = true;\n showFollowUp(handle, { speaking: false });\n }, [showFollowUp, tell]);\n\n // The Avatar tab's mic (Stage C): offered where the site opts in, the server's last availability answer carried an\n // offer, and the box takes a question now (Stage D: the box under a live session too).\n const mic = useAvatarMic({\n enabled:\n live.mic === true &&\n micOffer !== null &&\n !off &&\n acceptsQuestion({\n any,\n phase: phase.name,\n kind,\n textMode,\n reason: askReason,\n followUp: followUpAsks,\n }),\n locale,\n base,\n offer: micOffer,\n refreshOffer: refreshMicOffer,\n onText: onMicText,\n onStart: onMicStart,\n });\n micCancelRef.current = mic.cancel;\n\n // Stage D: while the mic records under a session that reads the answers after the first, the session is told so (a\n // `listening` mark) as the recording starts, every few seconds while it lasts, and as it stops, so its idle end waits\n // while the visitor speaks and counts from when they stopped. A recording starts once the microphone is open and its\n // stream ready (`mic.recording`), not at the tap: a permission prompt left unanswered keeps no session open.\n const micRecording = mic.recording;\n useEffect(() => {\n const handle = sessionRef.current;\n if (\n !micRecording ||\n handle === null ||\n handle.followUps === null ||\n handle.done\n ) {\n return;\n }\n tell(handle, \"listening\");\n const every = Math.min(\n LISTENING_MARK_MS,\n Math.max(1_000, (handle.followUps.limits.idleSeconds * 1_000) / 3),\n );\n const timer = setInterval(() => tell(handle, \"listening\"), every);\n return () => {\n clearInterval(timer);\n if (sessionRef.current === handle) tell(handle, \"listening\");\n };\n }, [micRecording, tell]);\n\n /**\n * Not now. Under `any` the visitor stays on the tab, told the answer is in Chat (the card is offered again when the tab\n * next opens, while the answer is fresh); otherwise, as before, back to the Chat tab.\n */\n const notNow = useCallback(() => {\n const current = phaseRef.current;\n if (\n (current.name === \"consent\" || current.name === \"needs-answer\") &&\n current.offer.questions === \"any\"\n ) {\n go({ name: \"declined\", offer: current.offer });\n return;\n }\n onContinueInChat();\n }, [go, onContinueInChat]);\n\n /**\n * Ask `question` from the box under a live session that reads the answers after the first (Stage D): the next\n * question of the same conversation, with `surface: \"AVATAR\"` as the first was, so its answer is written to be read\n * aloud. The session is told at once (`asking`: its idle end waits for the answer), and the answer goes to it to read\n * once written (see the effect on it). Only while the box asks the session ({@link followUpBox}) and no question of\n * the box's is on its way; one press at a time, as for any question from the box.\n */\n const askFollowUp = useCallback(\n (\n handle: SessionHandle,\n conversation: AvatarConversation,\n question: string,\n ) => {\n const run = handle.followUps;\n const current = phaseRef.current;\n if (\n run === null ||\n handle.done ||\n current.name !== \"live\" ||\n current.session.followUp?.pending !== null ||\n !followUpBox(current, run, conversation.getConversationToken())\n ) {\n return;\n }\n sendingRef.current = true;\n run.seq += 1;\n const seq = run.seq;\n setDraft(\"\");\n tell(handle, \"asking\");\n showFollowUp(handle, { pending: \"asking\", unread: null });\n void conversation\n .send(question, [], { surface: \"AVATAR\" })\n .then((added) => {\n // As for the first question: one the chat added nothing for goes back into the box, never silently lost.\n if (added === null) {\n setDraft((current) => (current === \"\" ? question : current));\n }\n if (sessionRef.current !== handle || handle.done || run.seq !== seq) {\n return;\n }\n if (added === null || added.conversationToken !== run.token) {\n showFollowUp(handle, { pending: null });\n attend();\n return;\n }\n run.asked = {\n messageId: added.userMessageId,\n token: added.conversationToken,\n answerId: null,\n };\n // A render for the effect on the answer, which reads the question from here (the answer may be in already).\n showFollowUp(handle, { pending: \"asking\" });\n })\n .finally(() => {\n sendingRef.current = false;\n });\n },\n [attend, showFollowUp, tell],\n );\n\n /**\n * Ask `text` from the box (or a chip). For the avatar, it is the first question of a new chat, sent with `surface:\n * \"AVATAR\"`, so its answer is the one the card offers. It is remembered as asked here only once the chat's `send` says\n * it added it, bound to the USER message it added and the conversation it ended in; a send that added nothing (too\n * long a question, another question already on its way, a disabled chat) leaves nothing remembered, so the same words\n * asked later in Chat never get the card, and puts the question back in the box. In text (see `textMode`), an\n * ordinary question, without `surface`, into the chat as it is. Under a live session that reads the answers after the\n * first, its next question (`askFollowUp`). Never resets the conversation: a chat that is not new is started over\n * only by the visitor's own \"New chat for the avatar\". One question at a time: a second press while the first is on\n * its way sends nothing.\n */\n const ask = useCallback(\n (text: string) => {\n const conversation = conversationRef.current;\n const question = text.trim();\n if (conversation === null || question === \"\" || sendingRef.current) {\n return;\n }\n const spoken = !textBoxRef.current;\n // Stage D: under a live session that reads the answers after the first, the box asks it the next question.\n const handle = sessionRef.current;\n if (spoken && handle !== null && handle.followUps !== null) {\n askFollowUp(handle, conversation, question);\n return;\n }\n if (spoken && conversation.messages.length > 0) return;\n sendingRef.current = true;\n // Whatever was remembered goes: only this ask's own send can put a question back.\n setAskedHere(null);\n const seq = askSeqRef.current;\n setNote(null);\n setDraft(\"\");\n void conversation\n .send(question, [], spoken ? { surface: \"AVATAR\" } : {})\n .then((added) => {\n // The chat added nothing (over its own length or turn limit, another question on its way, a disabled chat):\n // the question goes back into the box, unless the visitor has typed something else since, so it is never\n // silently lost.\n if (added === null) {\n setDraft((current) => (current === \"\" ? question : current));\n }\n if (\n !spoken ||\n added === null ||\n askSeqRef.current !== seq ||\n added.conversationToken !==\n (conversationRef.current?.getConversationToken() ?? null)\n ) {\n return;\n }\n setAskedHere({\n messageId: added.userMessageId,\n token: added.conversationToken,\n });\n })\n .finally(() => {\n sendingRef.current = false;\n });\n },\n [askFollowUp, setAskedHere],\n );\n\n // Stage D: the answer to the question asked from the box under a live session, once it is written. Checked on every\n // render (the chat's messages bring one), as long as the question waits: a completed answer that is the\n // conversation's latest and passes the checks this browser can make goes to the session to read, once\n // (`readFollowUp`). A failed answer, or one those checks refuse, is said in a line and stays in Chat, but the\n // session is still asked for it where there is an answer to name (the id the chat gave it while it was written, for\n // one the chat dropped): only its refusal ends the wait the question's `asking` mark holds open, so its idle end\n // counts from now. A conversation that has moved on lets the question go, with nothing sent and nothing said: its\n // answer is no longer the visitor's to hear.\n useEffect(() => {\n const handle = sessionRef.current;\n const run = handle?.followUps ?? null;\n if (handle === null || run === null || handle.done || run.asked === null) {\n return;\n }\n const asked = run.asked;\n const chat = conversationRef.current;\n const messages = chat?.messages ?? [];\n const at = messages.findIndex((message) => message.id === asked.messageId);\n const question = at === -1 ? undefined : messages[at];\n const answer = at === -1 ? undefined : messages[at + 1];\n const drop = (unread: FollowUpUnread | null) => {\n run.asked = null;\n showFollowUp(handle, { pending: null, unread });\n attend();\n };\n /** Not read for `unread`: said so, with the session asked for `id` all the same where there is one to name. */\n const unread = (id: string | null, reason: FollowUpUnread) => {\n if (id === null || run.sent.has(id) || !isAvatarMessageId(id)) {\n drop(reason);\n return;\n }\n run.asked = null;\n readFollowUp(handle, id, reason);\n };\n if (\n question === undefined ||\n (chat?.getConversationToken() ?? null) !== run.token\n ) {\n drop(null);\n return;\n }\n if (answer === undefined) {\n // The send failed before any answer came, or the chat dropped a failed answer that had no text; while it is on\n // its way, the answer is still to come.\n if (!inFlight(chat)) unread(asked.answerId, \"answer_failed\");\n return;\n }\n if (answer.status === \"PENDING\" || answer.status === \"RUNNING\") {\n if (answer.role === \"ASSISTANT\") asked.answerId = answer.id;\n return;\n }\n if (answer.role !== \"ASSISTANT\") {\n unread(asked.answerId, \"answer_failed\");\n return;\n }\n if (answer.status !== \"COMPLETED\" || answer.content.trim() === \"\") {\n unread(answer.id, \"answer_failed\");\n return;\n }\n if (run.sent.has(answer.id) || !isAvatarMessageId(answer.id)) {\n drop(\"not_eligible\");\n return;\n }\n if (at + 2 !== messages.length || !readable(question, answer)) {\n unread(answer.id, \"not_eligible\");\n return;\n }\n run.asked = null;\n readFollowUp(handle, answer.id, null);\n });\n\n /**\n * \"New chat for the avatar\": the visitor's own start over, where this conversation can no longer be read. The chat's\n * New chat (the conversation's `reset`, so the chat being left stays in History), staying on the Avatar tab, whose\n * box then asks for the avatar. A failed question goes back into the box, if the box is empty.\n */\n const newChatForAvatar = useCallback(() => {\n const conversation = conversationRef.current;\n if (conversation === null) return;\n const now = exchangeNow();\n const failedQuestion =\n now.kind === \"failed\" ? (now.question?.content ?? null) : null;\n conversation.reset();\n setAskedHere(null);\n setNote(\"new-chat\");\n if (failedQuestion !== null) {\n setDraft((current) => (current === \"\" ? failedQuestion : current));\n }\n const current = phaseRef.current;\n if (\n current.name === \"needs-answer\" ||\n current.name === \"consent\" ||\n current.name === \"declined\"\n ) {\n go({ name: \"needs-answer\", offer: current.offer });\n } else {\n // From a refusal or a session's end: ask again whether the avatar is offered, for the new chat.\n check();\n }\n }, [check, exchangeNow, go, setAskedHere]);\n\n // Each step's own control takes focus when the one the visitor was on has gone (Start, once pressed, say): focus\n // left on the page's body would also take Escape out of the panel. \"Tap to turn on sound\" is one of those controls:\n // it goes the moment playback resumes (`blocked` clears), so focus moves on to Stop rather than falling to the body.\n // So is the box under a live session (Stage D): it goes when the session reads no more answers.\n useEffect(() => {\n if (!active) return;\n const focused = document.activeElement;\n if (focused && focused !== document.body && focused.isConnected) return;\n rootRef.current?.querySelector<HTMLElement>(PRIMARY)?.focus();\n // (The card's arrival while the answer is written is a step of its own here: its Start when ready takes focus from\n // the box the question was asked from, which has gone.)\n }, [\n active,\n phase.name,\n askState,\n shown.pendingAnswerId,\n blocked,\n followUpAsks,\n ]);\n\n // The avatar's video plays: the session is live (`goLive`).\n const onPlaying = goLive;\n\n const enablePlayback = useCallback(() => {\n // Called straight from the tap: browsers allow sound only from inside the visitor's gesture.\n void sessionRef.current?.joined?.enablePlayback().catch(() => undefined);\n }, []);\n\n if (off || phase.name === \"inert\") {\n return (\n // `display: contents`: the earlier Avatar view's picture, line and button lay out in the pane exactly as before.\n <div\n ref={rootRef}\n style={{ display: \"contents\" }}\n data-boff-explore=\"avatar-live\"\n data-phase={off ? \"off\" : \"inert\"}\n >\n {fallback}\n </div>\n );\n }\n\n const primaryButton =\n \"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 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 motion-reduce:transition-none\";\n const secondaryButton =\n \"inline-flex items-center justify-center rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background motion-reduce:transition-none\";\n const stillPicture = (small: boolean) => (\n <img\n src={still.src}\n alt={still.alt}\n decoding=\"async\"\n width={small ? 64 : 128}\n height={small ? 64 : 128}\n className={cn(\n \"shrink-0 rounded-full border border-border object-cover shadow-sm\",\n small\n ? \"h-16 w-16\"\n : any\n ? \"h-[min(12rem,32dvh)] w-[min(12rem,32dvh)]\"\n : \"h-32 w-32\",\n )}\n />\n );\n const continueButton = (\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-continue\"\n className={primaryButton}\n onClick={onContinueInChat}\n >\n {continueInChat}\n </button>\n );\n /** Where this conversation can never be read: New chat first, and Continue in Chat beside it. */\n const startOverActions = (\n <div className=\"flex flex-wrap items-center justify-center gap-2\">\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-new-chat\"\n className={primaryButton}\n onClick={startNewChat}\n >\n {newChat}\n </button>\n <button\n type=\"button\"\n data-boff-explore=\"avatar-live-continue\"\n className={secondaryButton}\n onClick={onContinueInChat}\n >\n {continueInChat}\n </button>\n </div>\n );\n const stopButton = (\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-stop\"\n className={secondaryButton}\n onClick={stop}\n >\n {S.stop}\n </button>\n );\n /** Under `any`: to the Chat tab, where the answer and its sources are. */\n const readInChatButton = (primary: boolean) => (\n <button\n type=\"button\"\n data-avatar-primary={primary ? \"\" : undefined}\n data-boff-explore=\"avatar-live-read-in-chat\"\n className={primary ? primaryButton : secondaryButton}\n onClick={onContinueInChat}\n >\n {S.readInChat}\n </button>\n );\n /** The consent card: exactly its four lines and the privacy link (the notice's digest is taken over them). */\n const consentCard = (copy: AvatarConsentCopy) => (\n <section\n aria-labelledby={consentTitleId}\n data-boff-explore=\"avatar-live-consent\"\n className=\"w-full max-w-sm rounded-lg border border-border p-4 text-start\"\n >\n <h2 id={consentTitleId} className=\"text-base font-semibold\">\n {copy.title}\n </h2>\n <p className=\"mt-2 text-sm\">\n {productName === null || copy.introProduct === null\n ? copy.intro\n : fill(copy.introProduct, { product: productName })}\n </p>\n <p className=\"mt-2 text-sm text-muted-foreground\">{copy.processing}</p>\n <p className=\"mt-2 text-sm text-muted-foreground\">{copy.storage}</p>\n <a\n href={PRIVACY_HREF}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-boff-explore=\"avatar-live-privacy\"\n 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\"\n >\n {copy.privacyLink}\n <span className=\"sr-only\"> {S.opensInNewTab}</span>\n </a>\n </section>\n );\n /** The card's buttons: Start (or, while the answer is written, Start when ready) and Not now. */\n const consentActions = (whenReady: boolean) => (\n <div className=\"flex flex-wrap items-center justify-center gap-2\">\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore={\n whenReady ? \"avatar-live-start-when-ready\" : \"avatar-live-start\"\n }\n className={primaryButton}\n onClick={whenReady ? startWhenReady : start}\n >\n {whenReady ? S.startWhenReady : S.start}\n </button>\n <button\n type=\"button\"\n data-boff-explore=\"avatar-live-not-now\"\n className={secondaryButton}\n onClick={notNow}\n >\n {S.notNow}\n </button>\n </div>\n );\n const liveMedia = (playing: boolean) => (\n <div\n className={cn(\n \"relative shrink-0 overflow-hidden rounded-xl border border-border bg-muted\",\n any ? \"h-[min(12rem,32dvh)] w-[min(12rem,32dvh)]\" : \"h-48 w-48\",\n )}\n >\n <video\n ref={videoRef}\n aria-label={S.video}\n data-boff-explore=\"avatar-live-video\"\n playsInline\n autoPlay\n muted\n onPlaying={onPlaying}\n className={cn(\"h-full w-full object-cover\", !playing && \"opacity-0\")}\n />\n {playing ? null : (\n <img\n src={still.src}\n alt=\"\"\n decoding=\"async\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n )}\n {/* Under `any`, the audio element is the view's own, so that Start's tap can let it play (see `unlockSound`). */}\n {any ? null : (\n <audio ref={audioRef} data-boff-explore=\"avatar-live-audio\" />\n )}\n </div>\n );\n /**\n * The status line while the avatar speaks. Where the server speaks only the first part of the answer (Stage B), the\n * line says so, and that the full answer is in Chat, in place of \"The avatar is speaking.\": the same slot, so the\n * layout is the same whether or not a cap applies.\n */\n const speakingLine = (session: ShownSession) =>\n session.excerpt ? S.excerpt : S.speaking;\n const liveBody = (session: ShownSession) => (\n <>\n <section\n aria-label={S.captions}\n data-boff-explore=\"avatar-live-captions\"\n lang={session.captions.locale || undefined}\n dir=\"auto\"\n tabIndex={0}\n 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\"\n >\n {session.captions.text}\n </section>\n <p className=\"text-xs text-muted-foreground\">{S.answerInChat}</p>\n <p className=\"text-sm tabular-nums text-muted-foreground\">\n {S.timeLeft}{\" \"}\n <span role=\"timer\" data-boff-explore=\"avatar-live-countdown\">\n {clock(Math.max(0, (session.endsAt - now) / 1000))}\n </span>\n </p>\n </>\n );\n /** A session's buttons: the sound, where the browser holds it back, Stop, and the way back to the chat. */\n const liveActions = (back: ReactNode) => (\n <div className=\"flex flex-wrap items-center justify-center gap-2\">\n {blocked ? (\n <button\n type=\"button\"\n data-boff-explore=\"avatar-live-sound\"\n className={primaryButton}\n onClick={enablePlayback}\n >\n {S.tapForSound}\n </button>\n ) : null}\n {stopButton}\n {back}\n </div>\n );\n const badge = (\n <p\n data-boff-explore=\"avatar-live-badge\"\n className=\"rounded-full bg-muted px-3 py-1 text-xs font-medium text-foreground\"\n >\n {S.badge}\n </p>\n );\n\n if (any) {\n // The Avatar tab with its own question box: a stage that scrolls (the picture or the video, the status, the card or\n // the captions, the question) over a foot that stays (the chips, the box and the line under it).\n let status = \"\";\n let outcome = false;\n let lead: ReactNode = null;\n let top: ReactNode = null;\n let media: ReactNode = stillPicture(false);\n let body: ReactNode = null;\n let actions: ReactNode = null;\n let newChatOffer = false;\n let box: \"spoken\" | \"text\" | null = null;\n const first = exchange.question;\n const questionLine =\n first === null ? null : (\n <p\n data-boff-explore=\"avatar-live-question\"\n dir=\"auto\"\n className=\"line-clamp-2 w-full max-w-sm break-words text-sm font-medium\"\n >\n {first.content}\n </p>\n );\n const activity = conversation?.activity ?? null;\n const activityLine =\n activity === null ? null : (\n <p\n data-boff-explore=\"avatar-live-activity\"\n className=\"text-xs text-muted-foreground\"\n >\n {activity}\n </p>\n );\n\n if (textMode) {\n // The day's session is used (or the server says its limit is reached): the box asks ordinary questions, and the\n // answer shows here as text.\n const messages = conversation?.messages ?? [];\n let questionAt = messages.length - 1;\n while (questionAt >= 0 && messages[questionAt]?.role !== \"USER\") {\n questionAt -= 1;\n }\n const lastQuestion = questionAt === -1 ? undefined : messages[questionAt];\n // Only that question's own answer, the message right after it: the chat adds the question at once and its answer\n // only once the server takes it (and none when the send fails), so an earlier answer is never shown under it.\n const after = questionAt === -1 ? undefined : messages[questionAt + 1];\n const lastAnswer = after?.role === \"ASSISTANT\" ? after : undefined;\n const chatPhase = conversation?.phase;\n /** The question has no answer yet: on its way, failed (the chat's error is the send's), or neither. */\n const unanswered =\n lastQuestion === undefined || lastAnswer !== undefined\n ? null\n : chatPhase === \"sending\" || chatPhase === \"streaming\"\n ? \"waiting\"\n : chatPhase === \"error\" || chatPhase === \"limited\"\n ? \"failed\"\n : null;\n if (phase.name === \"refused\") {\n status = S[REFUSAL_TEXT[phase.reason]];\n outcome = true;\n } else if (phase.name === \"ended\") {\n // After the day's session: how it ended stays said, over the last question and its answer.\n status = S[phase.how];\n outcome = true;\n }\n body = (\n <>\n {lastQuestion === undefined ? null : (\n <p\n data-boff-explore=\"avatar-live-question\"\n dir=\"auto\"\n className=\"line-clamp-2 w-full max-w-sm break-words text-sm font-medium\"\n >\n {lastQuestion.content}\n </p>\n )}\n {lastAnswer === undefined ? (\n unanswered === \"waiting\" ? (\n <p className=\"text-xs text-muted-foreground\">\n {activity ?? S.gettingAnswer}\n </p>\n ) : unanswered === \"failed\" ? (\n <p className=\"text-sm text-muted-foreground\">{S.answerFailed}</p>\n ) : null\n ) : lastAnswer.status === \"PENDING\" ||\n lastAnswer.status === \"RUNNING\" ? (\n <p className=\"text-xs text-muted-foreground\">\n {activity ?? S.gettingAnswer}\n </p>\n ) : lastAnswer.status === \"FAILED\" ? (\n <p className=\"text-sm text-muted-foreground\">{S.answerFailed}</p>\n ) : (\n // The answer's words, not its markdown: `content` is written for the chat's renderer, and shown as it is\n // here a link reads `[label](https://…)`. In its spoken form, as the chat's read-aloud says it: a link is its\n // label (the address is in Chat, one tap away), a table its rows, and the markers of emphasis, headings,\n // quotes and list items go (`answerDisplayText`). The words are the ones the chat shows, citation markers\n // included, which the sources in Chat answer to.\n <p\n data-boff-explore=\"avatar-live-text-answer\"\n dir=\"auto\"\n className=\"line-clamp-6 w-full max-w-sm whitespace-pre-wrap break-words text-start text-sm\"\n >\n {answerDisplayText(lastAnswer.content)}\n </p>\n )}\n </>\n );\n // After a session, \"Read the answer and sources in Chat\" stays the step's own control, as it was before the box\n // asked anything (focus moves there from Stop).\n const ended = phase.name === \"ended\";\n // A send that failed before any answer came is retried in Chat, so the way there is offered for it too.\n actions =\n lastAnswer === undefined && unanswered !== \"failed\" && !ended\n ? null\n : readInChatButton(ended);\n box = \"text\";\n } else {\n switch (phase.name) {\n case \"checking\":\n status = S.checking;\n break;\n case \"needs-answer\":\n switch (shown.kind) {\n case \"empty\":\n status = note === \"new-chat\" ? S.newChatStarted : \"\";\n lead = <p className=\"text-base font-semibold\">{S.askHeadline}</p>;\n box = \"spoken\";\n break;\n case \"asking\":\n case \"answer\": {\n // The card shows while the answer is written, for a question asked here as the first of a new chat, once\n // the server has taken it.\n const card = shown.askedHere && shown.pendingAnswerId !== null;\n status =\n note === \"cancelled\" ? S.armedCancelled : S.gettingAnswer;\n if (card) media = stillPicture(true);\n body = (\n <>\n {questionLine}\n {activityLine}\n {card ? consentCard(phase.offer.copy) : null}\n </>\n );\n actions = card ? consentActions(true) : null;\n break;\n }\n case \"text-only\":\n status = S.notSpoken;\n outcome = true;\n body = questionLine;\n actions = readInChatButton(false);\n newChatOffer = true;\n break;\n case \"failed\":\n status = S.answerFailed;\n outcome = true;\n body = questionLine;\n newChatOffer = true;\n break;\n case \"ask-here\":\n status = S.askHere;\n outcome = true;\n actions = readInChatButton(false);\n newChatOffer = true;\n break;\n default:\n status = S.startNewChat;\n outcome = true;\n body = (\n <p className=\"text-sm text-muted-foreground\">\n {S.startNewChatDetailAny}\n </p>\n );\n actions = readInChatButton(false);\n newChatOffer = true;\n break;\n }\n break;\n case \"consent\":\n media = stillPicture(true);\n body = (\n <>\n {questionLine}\n {consentCard(phase.offer.copy)}\n </>\n );\n actions = consentActions(false);\n break;\n case \"declined\":\n status = S.declined;\n actions = readInChatButton(true);\n break;\n case \"waiting\":\n status = S.armed;\n body = questionLine;\n actions = (\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-cancel\"\n className={secondaryButton}\n onClick={stop}\n >\n {S.cancel}\n </button>\n );\n break;\n case \"refused\":\n outcome = true;\n if (\n phase.reason === \"not_eligible\" ||\n phase.reason === \"answer_claimed\"\n ) {\n // This chat's answer will not be read: a new chat for the avatar can be.\n status =\n phase.reason === \"not_eligible\"\n ? S.notEligibleAny\n : S.answerClaimed;\n actions = readInChatButton(false);\n newChatOffer = true;\n } else {\n status = S[REFUSAL_TEXT[phase.reason]];\n actions = continueButton;\n }\n break;\n case \"bot-check\":\n status = S.botCheck;\n actions = stopButton;\n break;\n case \"creating\":\n status = S.connecting;\n actions = stopButton;\n break;\n case \"pending\":\n case \"live\": {\n top = badge;\n media = liveMedia(phase.name === \"live\");\n body = liveBody(phase.session);\n actions = liveActions(readInChatButton(false));\n if (followUp === null) {\n status =\n phase.name === \"live\"\n ? speakingLine(phase.session)\n : S.connecting;\n break;\n }\n // Stage D: between its answers, the session says what it is doing, and the box asks it the next question.\n status = followUp.speaking\n ? speakingLine(phase.session)\n : followUp.pending !== null\n ? ((followUp.pending === \"asking\" ? activity : null) ??\n S.gettingAnswer)\n : followUp.unread !== null\n ? S[FOLLOW_UP_TEXT[followUp.unread]]\n : followUp.closed\n ? S.followUpLast\n : S.followUpIdle;\n if (\n !followUp.speaking &&\n followUp.pending === null &&\n followUp.unread !== null &&\n !followUp.closed\n ) {\n // The status line says why the last answer was not read; the session still waits for a question.\n body = (\n <>\n {body}\n <p\n data-boff-explore=\"avatar-live-idle\"\n className=\"text-xs text-muted-foreground\"\n >\n {S.followUpIdle}\n </p>\n </>\n );\n }\n if (followUpAsks) box = \"spoken\";\n break;\n }\n case \"ended\":\n status = S[phase.how];\n outcome = true;\n actions = readInChatButton(true);\n // A session that never played leaves no note of the day's: a new chat for the avatar can still be. (One that\n // played is in text mode, above.)\n newChatOffer = true;\n break;\n default:\n break;\n }\n }\n\n const reason = askReason;\n const chips =\n box !== null && shown.kind === \"empty\" && prompts.length > 0 ? (\n <div className=\"flex flex-col gap-1\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n {tryAsking}\n </p>\n <div className=\"flex max-h-28 flex-wrap gap-2 overflow-y-auto\">\n {prompts.map((prompt) => (\n <button\n key={prompt}\n type=\"button\"\n data-boff-explore=\"avatar-live-chip\"\n aria-disabled={reason !== null ? \"true\" : undefined}\n 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\"\n onClick={() => {\n if (reason === null) ask(prompt);\n }}\n >\n {prompt}\n </button>\n ))}\n </div>\n </div>\n ) : null;\n const foot =\n box === null && !newChatOffer ? null : (\n <div\n data-boff-explore=\"avatar-live-foot\"\n 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))]\"\n >\n {newChatOffer ? (\n <div className=\"flex flex-col items-center gap-1 text-center\">\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-new-chat-avatar\"\n className={cn(primaryButton, \"min-h-11\")}\n onClick={newChatForAvatar}\n >\n {S.newChatForAvatar}\n </button>\n <p className=\"text-xs text-muted-foreground\">{S.newChatNote}</p>\n </div>\n ) : null}\n {chips}\n {box !== null && usedToday && phase.name !== \"live\" ? (\n <p\n data-boff-explore=\"avatar-live-used-today\"\n className=\"text-xs text-muted-foreground\"\n >\n {S.usedToday}\n </p>\n ) : null}\n {box === \"spoken\" ? mic.notice : null}\n {box === null ? null : (\n <AskBox\n value={draft}\n maxLength={askMaxLength}\n onChange={setDraft}\n onAsk={ask}\n reason={reason}\n label={S.askLabel}\n placeholder={S.askPlaceholder}\n send={send}\n footer={S.askFooter}\n noFiles={S.askNoFiles}\n hint={box === \"spoken\" ? S.needsAnswerAny : null}\n touchFirst={touchFirst}\n mic={box === \"spoken\" ? mic.button : null}\n micLines={box === \"spoken\" ? mic.lines : null}\n />\n )}\n </div>\n );\n\n return (\n <div\n ref={rootRef}\n data-boff-explore=\"avatar-live\"\n data-phase={phase.name}\n data-ask={askState}\n className=\"absolute inset-0 flex flex-col bg-background\"\n >\n <div className=\"flex min-h-0 flex-1 flex-col items-center gap-4 overflow-y-auto p-6 text-center\">\n {top}\n {media}\n {lead}\n <p\n role=\"status\"\n data-boff-explore=\"avatar-live-status\"\n className={\n outcome\n ? \"text-base font-semibold\"\n : \"text-sm text-muted-foreground\"\n }\n >\n {status}\n </p>\n {body}\n <div ref={botBoxRef} data-boff-explore=\"avatar-live-bot-check\" />\n {actions}\n </div>\n {foot}\n <audio ref={audioRef} data-boff-explore=\"avatar-live-audio\" />\n </div>\n );\n }\n\n // The headline of each step, in the one polite status region: announced as it changes, the countdown never.\n const headline: Record<Phase[\"name\"], string> = {\n idle: \"\",\n checking: S.checking,\n inert: \"\",\n // A question asked and its answer on its way: the answer is coming (the avatar is offered once it completes).\n \"needs-answer\": startOver\n ? S.startNewChat\n : shown.kind === \"asking\"\n ? S.gettingAnswer\n : S.needsAnswer,\n consent: \"\",\n declined: S.declined,\n waiting: S.armed,\n refused: phase.name === \"refused\" ? S[REFUSAL_TEXT[phase.reason]] : \"\",\n \"bot-check\": S.botCheck,\n creating: S.connecting,\n pending: S.connecting,\n live: phase.name === \"live\" ? speakingLine(phase.session) : \"\",\n ended: phase.name === \"ended\" ? S[phase.how] : \"\",\n };\n const outcome =\n phase.name === \"needs-answer\" ||\n phase.name === \"refused\" ||\n phase.name === \"ended\";\n\n let top: ReactNode = null;\n let media: ReactNode = stillPicture(false);\n let body: ReactNode = null;\n let actions: ReactNode = null;\n\n switch (phase.name) {\n case \"needs-answer\":\n // Nothing to read yet (choose a suggested question), or never in this conversation (start a new chat).\n body = (\n <p className=\"text-sm text-muted-foreground\">\n {startOver ? S.startNewChatDetail : S.needsAnswerDetail}\n </p>\n );\n actions = startOver ? startOverActions : continueButton;\n break;\n case \"consent\":\n media = stillPicture(true);\n body = consentCard(phase.offer.copy);\n actions = consentActions(false);\n break;\n case \"refused\":\n // An answer the service will not read (not one of the suggested questions, or too old by its clock): only a new\n // chat can be.\n actions =\n phase.reason === \"not_eligible\" ? startOverActions : continueButton;\n break;\n case \"bot-check\":\n case \"creating\":\n actions = stopButton;\n break;\n case \"pending\":\n case \"live\":\n top = badge;\n media = liveMedia(phase.name === \"live\");\n body = liveBody(phase.session);\n actions = liveActions(\n <button\n type=\"button\"\n data-boff-explore=\"avatar-live-continue\"\n className={secondaryButton}\n onClick={onContinueInChat}\n >\n {continueInChat}\n </button>,\n );\n break;\n case \"ended\":\n body = <p className=\"text-sm text-muted-foreground\">{S.answerInChat}</p>;\n actions = (\n <button\n type=\"button\"\n data-avatar-primary=\"\"\n data-boff-explore=\"avatar-live-back\"\n className={primaryButton}\n onClick={onContinueInChat}\n >\n {S.backToChat}\n </button>\n );\n break;\n default:\n break;\n }\n\n // The same slots in every step, so the status region and the bot check's box stay the same elements throughout.\n return (\n <div\n ref={rootRef}\n data-boff-explore=\"avatar-live\"\n data-phase={phase.name}\n className=\"flex max-h-full w-full flex-col items-center gap-4 overflow-y-auto\"\n >\n {top}\n {media}\n <p\n role=\"status\"\n data-boff-explore=\"avatar-live-status\"\n className={\n outcome ? \"text-base font-semibold\" : \"text-sm text-muted-foreground\"\n }\n >\n {headline[phase.name]}\n </p>\n {body}\n <div ref={botBoxRef} data-boff-explore=\"avatar-live-bot-check\" />\n {actions}\n </div>\n );\n}\n\ninterface AskBoxProps {\n value: string;\n /** The longest question the box takes: {@link ASK_MAX_LENGTH}, or the chat's own limit where that is shorter. */\n maxLength: number;\n onChange: (value: string) => void;\n /** Ask `question`. Called only with text, and only while {@link AskBoxProps.reason} is null. */\n onAsk: (question: string) => void;\n /** Why Send cannot be pressed now (an answer on its way, a chat that cannot ask), or null when it can. */\n reason: string | null;\n label: string;\n placeholder: string;\n send: string;\n /** The line under the box, always shown with it. */\n footer: string;\n /** Said when a file is pasted or dropped on the box. */\n noFiles: string;\n /** What the box is for, read with it by a screen reader; null for nothing more than its name. */\n hint: string | null;\n touchFirst: boolean;\n /** The mic's button, between the box and Send (Stage C); null without a mic. */\n mic: ReactNode;\n /** The mic's status line and what it hears, under the box's row; null without a mic. */\n micLines: ReactNode;\n}\n\n/**\n * The Avatar tab's own question box. Its text is the view's (never the chat's draft); it takes text only, up to\n * {@link AskBoxProps.maxLength} characters. Send is never `disabled` (a disabled control cannot be focused or explained): it is\n * `aria-disabled`, described by why. Enter asks and Shift+Enter breaks the line; while an input method is composing,\n * Enter is the input method's, and so is Escape, which then does not reach the panel. 44 px controls.\n */\nfunction AskBox({\n value,\n maxLength,\n onChange,\n onAsk,\n reason,\n label,\n placeholder,\n send,\n footer,\n noFiles,\n hint,\n touchFirst,\n mic,\n micLines,\n}: AskBoxProps) {\n const uid = useId();\n const reasonId = `${uid}-reason`;\n const hintId = `${uid}-hint`;\n const footerId = `${uid}-footer`;\n const [refusedFiles, setRefusedFiles] = useState(false);\n const empty = value.trim() === \"\";\n\n const submit = () => {\n if (reason !== null || empty) return;\n onAsk(value);\n };\n const onKeyDown = (event: ReactKeyboardEvent<HTMLTextAreaElement>) => {\n if (event.nativeEvent.isComposing || event.keyCode === 229) {\n if (event.key === \"Escape\") event.stopPropagation();\n return;\n }\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n submit();\n }\n };\n // Files are the chat's: one pasted or dropped here is refused, with a word on where to attach it.\n const onPaste = (event: ReactClipboardEvent<HTMLTextAreaElement>) => {\n if (event.clipboardData.files.length === 0) return;\n event.preventDefault();\n setRefusedFiles(true);\n };\n const onDrop = (event: ReactDragEvent<HTMLTextAreaElement>) => {\n if (!Array.from(event.dataTransfer.types).includes(\"Files\")) return;\n event.preventDefault();\n setRefusedFiles(true);\n };\n\n return (\n <form\n data-boff-explore=\"avatar-live-ask\"\n className=\"flex w-full flex-col gap-1\"\n onSubmit={(event) => {\n event.preventDefault();\n submit();\n }}\n >\n <div className=\"flex items-end gap-2\">\n <textarea\n value={value}\n rows={1}\n maxLength={maxLength}\n aria-label={label}\n aria-describedby={hint === null ? footerId : `${hintId} ${footerId}`}\n placeholder={placeholder}\n dir=\"auto\"\n data-avatar-primary={touchFirst ? undefined : \"\"}\n data-boff-explore=\"avatar-live-ask-input\"\n 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\"\n onChange={(event) => {\n setRefusedFiles(false);\n onChange(event.target.value);\n }}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n onDrop={onDrop}\n />\n {mic}\n <button\n type=\"submit\"\n aria-disabled={reason !== null || empty ? \"true\" : undefined}\n aria-describedby={reason !== null ? reasonId : undefined}\n data-avatar-primary={touchFirst ? \"\" : undefined}\n data-boff-explore=\"avatar-live-ask-send\"\n 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\"\n >\n {send}\n </button>\n </div>\n {micLines}\n {reason === null ? null : (\n <p\n id={reasonId}\n data-boff-explore=\"avatar-live-ask-reason\"\n className=\"text-xs text-muted-foreground\"\n >\n {reason}\n </p>\n )}\n {refusedFiles ? (\n <p\n data-boff-explore=\"avatar-live-ask-files\"\n className=\"text-xs text-muted-foreground\"\n >\n {noFiles}\n </p>\n ) : null}\n {hint === null ? null : (\n <p id={hintId} className=\"sr-only\">\n {hint}\n </p>\n )}\n <p id={footerId} className=\"text-xs text-muted-foreground\">\n {footer}\n </p>\n </form>\n );\n}\n"]}
|