@burdenoff/website-sdk 2026.828.2 → 2026.828.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/client/index.d.mts +2 -2
  2. package/dist/client/index.d.ts +2 -2
  3. package/dist/client/index.js +22 -1
  4. package/dist/client/index.js.map +1 -1
  5. package/dist/client/index.mjs +22 -1
  6. package/dist/client/index.mjs.map +1 -1
  7. package/dist/components/contact.js +22 -1
  8. package/dist/components/contact.js.map +1 -1
  9. package/dist/components/contact.mjs +22 -1
  10. package/dist/components/contact.mjs.map +1 -1
  11. package/dist/components/explore.js +22 -1
  12. package/dist/components/explore.js.map +1 -1
  13. package/dist/components/explore.mjs +22 -1
  14. package/dist/components/explore.mjs.map +1 -1
  15. package/dist/components/newsletter.js +22 -1
  16. package/dist/components/newsletter.js.map +1 -1
  17. package/dist/components/newsletter.mjs +22 -1
  18. package/dist/components/newsletter.mjs.map +1 -1
  19. package/dist/components/partners.js +22 -1
  20. package/dist/components/partners.js.map +1 -1
  21. package/dist/components/partners.mjs +22 -1
  22. package/dist/components/partners.mjs.map +1 -1
  23. package/dist/components/pricing.js +22 -1
  24. package/dist/components/pricing.js.map +1 -1
  25. package/dist/components/pricing.mjs +22 -1
  26. package/dist/components/pricing.mjs.map +1 -1
  27. package/dist/components/resource-links.js +22 -1
  28. package/dist/components/resource-links.js.map +1 -1
  29. package/dist/components/resource-links.mjs +22 -1
  30. package/dist/components/resource-links.mjs.map +1 -1
  31. package/dist/components/social-links.js +22 -1
  32. package/dist/components/social-links.js.map +1 -1
  33. package/dist/components/social-links.mjs +22 -1
  34. package/dist/components/social-links.mjs.map +1 -1
  35. package/dist/components/unsubscribe.js +22 -1
  36. package/dist/components/unsubscribe.js.map +1 -1
  37. package/dist/components/unsubscribe.mjs +22 -1
  38. package/dist/components/unsubscribe.mjs.map +1 -1
  39. package/dist/components/waitlist.js +22 -1
  40. package/dist/components/waitlist.js.map +1 -1
  41. package/dist/components/waitlist.mjs +22 -1
  42. package/dist/components/waitlist.mjs.map +1 -1
  43. package/dist/content/index.d.mts +2 -2
  44. package/dist/content/index.d.ts +2 -2
  45. package/dist/content/index.js +22 -1
  46. package/dist/content/index.js.map +1 -1
  47. package/dist/content/index.mjs +22 -1
  48. package/dist/content/index.mjs.map +1 -1
  49. package/dist/{graphql-client-BXn6RYV0.d.mts → graphql-client-CI9vbgat.d.mts} +18 -0
  50. package/dist/{graphql-client-BXn6RYV0.d.ts → graphql-client-CI9vbgat.d.ts} +18 -0
  51. package/dist/hooks/index.js +22 -1
  52. package/dist/hooks/index.js.map +1 -1
  53. package/dist/hooks/index.mjs +22 -1
  54. package/dist/hooks/index.mjs.map +1 -1
  55. package/dist/{index-DYxQiEm5.d.mts → index-BMWQNZDX.d.mts} +1 -1
  56. package/dist/{index-BXg7cQLm.d.ts → index-BqHF-G-S.d.ts} +1 -1
  57. package/dist/index.d.mts +5 -5
  58. package/dist/index.d.ts +5 -5
  59. package/dist/index.js +22 -1
  60. package/dist/index.js.map +1 -1
  61. package/dist/index.mjs +22 -1
  62. package/dist/index.mjs.map +1 -1
  63. package/dist/product/index.js +22 -1
  64. package/dist/product/index.js.map +1 -1
  65. package/dist/product/index.mjs +22 -1
  66. package/dist/product/index.mjs.map +1 -1
  67. package/dist/{provider-D_uUM7_e.d.ts → provider-Dwgz4d0r.d.ts} +1 -1
  68. package/dist/{provider-CUfI8meE.d.mts → provider-MFV1NVqZ.d.mts} +1 -1
  69. package/dist/store/index.js +22 -1
  70. package/dist/store/index.js.map +1 -1
  71. package/dist/store/index.mjs +22 -1
  72. package/dist/store/index.mjs.map +1 -1
  73. package/package.json +1 -1
@@ -16,6 +16,24 @@ interface WebSDKClientConfig {
16
16
  rybbitSiteId?: string;
17
17
  /** Custom headers to include in all requests */
18
18
  headers?: Record<string, string>;
19
+ /**
20
+ * Cloudflare Access service token, for the ALPHA gateway hosts only.
21
+ *
22
+ * `alphagraphql.burdenoff.com` sits behind a Cloudflare Access application, so an
23
+ * unauthenticated browser XHR is answered with a 302 to the Access login on a different
24
+ * origin — which the browser reports as an opaque CORS failure rather than a 401. Attaching
25
+ * the service-token headers is how every app shell already passes that gate (fe-libs
26
+ * `installGatewayFetchRewrite`); the website SDK previously had no equivalent, so contact,
27
+ * newsletter, waitlist and explore all failed on alpha.
28
+ *
29
+ * Vite only inlines `VITE_*` into APP source, never into a bundled library, so the host app
30
+ * must read `import.meta.env` and pass the values in. Production gateways are not gated and
31
+ * receive no headers.
32
+ */
33
+ cfAccess?: {
34
+ clientId?: string;
35
+ clientSecret?: string;
36
+ };
19
37
  /**
20
38
  * Per-request timeout in ms. Kept below the gateway's operation timeout so a
21
39
  * stalled request surfaces as an error the UI can render, instead of leaving
@@ -16,6 +16,24 @@ interface WebSDKClientConfig {
16
16
  rybbitSiteId?: string;
17
17
  /** Custom headers to include in all requests */
18
18
  headers?: Record<string, string>;
19
+ /**
20
+ * Cloudflare Access service token, for the ALPHA gateway hosts only.
21
+ *
22
+ * `alphagraphql.burdenoff.com` sits behind a Cloudflare Access application, so an
23
+ * unauthenticated browser XHR is answered with a 302 to the Access login on a different
24
+ * origin — which the browser reports as an opaque CORS failure rather than a 401. Attaching
25
+ * the service-token headers is how every app shell already passes that gate (fe-libs
26
+ * `installGatewayFetchRewrite`); the website SDK previously had no equivalent, so contact,
27
+ * newsletter, waitlist and explore all failed on alpha.
28
+ *
29
+ * Vite only inlines `VITE_*` into APP source, never into a bundled library, so the host app
30
+ * must read `import.meta.env` and pass the values in. Production gateways are not gated and
31
+ * receive no headers.
32
+ */
33
+ cfAccess?: {
34
+ clientId?: string;
35
+ clientSecret?: string;
36
+ };
19
37
  /**
20
38
  * Per-request timeout in ms. Kept below the gateway's operation timeout so a
21
39
  * stalled request surfaces as an error the UI can render, instead of leaving
@@ -42,6 +42,26 @@ function sanitizeHeaders(headers) {
42
42
  )
43
43
  );
44
44
  }
45
+ var CF_ACCESS_GATED_HOSTS = /* @__PURE__ */ new Set([
46
+ "alphagraphql.burdenoff.com",
47
+ "alphagraphqlworkspaces.burdenoff.com"
48
+ ]);
49
+ function cfAccessHeaders(gatewayUrl, cfAccess) {
50
+ const clientId = cfAccess?.clientId?.trim();
51
+ const clientSecret = cfAccess?.clientSecret?.trim();
52
+ if (!clientId || !clientSecret) return {};
53
+ let host;
54
+ try {
55
+ host = new URL(gatewayUrl).hostname.toLowerCase();
56
+ } catch {
57
+ return {};
58
+ }
59
+ if (!CF_ACCESS_GATED_HOSTS.has(host)) return {};
60
+ return {
61
+ "CF-Access-Client-Id": clientId,
62
+ "CF-Access-Client-Secret": clientSecret
63
+ };
64
+ }
45
65
 
46
66
  // src/client/graphql-client.ts
47
67
  var _WebSDKClient = class _WebSDKClient {
@@ -124,7 +144,8 @@ var _WebSDKClient = class _WebSDKClient {
124
144
  headers: {
125
145
  "Content-Type": "application/json",
126
146
  "x-product-id": this.config.productId,
127
- ...this.config.headers
147
+ ...this.config.headers,
148
+ ...cfAccessHeaders(this.config.gatewayUrl, this.config.cfAccess)
128
149
  },
129
150
  body: JSON.stringify({ query, variables }),
130
151
  signal: controller.signal
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/security.ts","../../src/client/graphql-client.ts","../../src/client/provider.tsx","../../src/components/explore-types.ts","../../src/data/products.ts","../../src/utils/recaptcha-v3.ts","../../src/hooks/use-explore-chat.ts"],"names":["createContext","useContext","useMemo","useState","useRef","useCallback","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["const LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\nconst RESERVED_HEADERS = new Set([\n \"authorization\",\n \"cookie\",\n \"x-actor-id\",\n \"x-actor-type\",\n \"x-consent-granted-by\",\n \"x-consent-scope\",\n \"x-consent-granted-at\",\n \"x-consent-expires-at\",\n]);\n\nexport function validateGatewayUrl(value: string): string {\n let url: URL;\n\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"Gateway URL must be a valid absolute URL\");\n }\n\n if (url.protocol === \"https:\") {\n return url.toString();\n }\n\n if (\n url.protocol === \"http:\" &&\n LOOPBACK_HOSTS.has(url.hostname.toLowerCase())\n ) {\n return url.toString();\n }\n\n throw new Error(\"Gateway URL must use HTTPS unless it targets localhost\");\n}\n\nexport function sanitizeHeaders(\n headers?: Record<string, string>,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n\n return Object.fromEntries(\n Object.entries(headers).filter(\n ([key]) => !RESERVED_HEADERS.has(key.toLowerCase()),\n ),\n );\n}\n","/**\n * Lightweight GraphQL client for the Burdenoff Web SDK.\n * Uses native fetch - zero external dependencies.\n * All calls are unauthenticated (public gateway operations only).\n */\n\nimport { sanitizeHeaders, validateGatewayUrl } from \"./security\";\n\nexport interface WebSDKClientConfig {\n /** Global public gateway URL (e.g. \"https://api.burdenoff.com/global/graphql\") */\n gatewayUrl: string;\n /** Platform product ID for scoping operations */\n productId: string;\n /** Product slug (used for public product queries) */\n productSlug?: string;\n /** reCAPTCHA site key (if not fetched from product config) */\n recaptchaSiteKey?: string;\n /** Rybbit analytics site ID */\n rybbitSiteId?: string;\n /** Custom headers to include in all requests */\n headers?: Record<string, string>;\n /**\n * Per-request timeout in ms. Kept below the gateway's operation timeout so a\n * stalled request surfaces as an error the UI can render, instead of leaving\n * a page stuck on loading skeletons forever. Default 12000.\n */\n timeoutMs?: number;\n /**\n * Extra attempts for transient failures (timeout / network / 5xx / 429) on\n * QUERIES ONLY. Mutations are never retried — a retried contact-form or\n * waitlist submit would double-submit. Default 1 (2 attempts total).\n */\n maxRetries?: number;\n}\n\n/**\n * Per-call overrides for {@link WebSDKClient.query}.\n *\n * The defaults (5-minute response cache + in-flight deduplication) are right\n * for the read-once content queries most SDK components make, and wrong for a\n * poll loop: the second poll of the same `(query, variables)` pair would be\n * served straight from the cache and the UI would freeze on the first\n * response forever. Pass `{ cache: false }` for anything polled.\n */\nexport interface WebSDKQueryOptions {\n /**\n * Use the response cache and in-flight deduplication. Default `true`.\n * `false` skips the cache read, the dedupe map AND the cache write, so the\n * call always hits the network and never poisons a later cached read.\n */\n cache?: boolean;\n /** Override the client-wide request timeout for this call only. */\n timeoutMs?: number;\n}\n\n/** Per-call overrides for {@link WebSDKClient.mutate}. */\nexport interface WebSDKMutateOptions {\n /** Override the client-wide request timeout for this call only. */\n timeoutMs?: number;\n}\n\nexport interface GraphQLResponse<T = Record<string, unknown>> {\n data?: T;\n errors?: Array<{\n message: string;\n locations?: Array<{ line: number; column: number }>;\n path?: Array<string | number>;\n extensions?: Record<string, unknown>;\n }>;\n}\n\nexport class WebSDKClient {\n private config: WebSDKClientConfig;\n private queryCache = new Map<\n string,\n { data: GraphQLResponse<unknown>; ts: number }\n >();\n private inflight = new Map<string, Promise<GraphQLResponse<unknown>>>();\n private static CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n private static MAX_CACHE_ENTRIES = 100;\n private static DEFAULT_TIMEOUT_MS = 12_000;\n private static DEFAULT_MAX_RETRIES = 1;\n private static RETRY_BASE_DELAY_MS = 400;\n\n constructor(config: WebSDKClientConfig) {\n this.config = {\n ...config,\n gatewayUrl: validateGatewayUrl(config.gatewayUrl),\n headers: sanitizeHeaders(config.headers),\n };\n }\n\n getConfig(): WebSDKClientConfig {\n return this.config;\n }\n\n /**\n * Execute a GraphQL query (with deduplication and caching).\n *\n * Pass `{ cache: false }` to bypass the cache entirely — required for poll\n * loops, where every tick must reach the network.\n */\n async query<T = Record<string, unknown>>(\n query: string,\n variables?: Record<string, unknown>,\n options?: WebSDKQueryOptions,\n ): Promise<GraphQLResponse<T>> {\n // Uncached path: no cache read, no in-flight dedupe, no cache write.\n // Deliberately bypasses the dedupe map too — two identical polls issued a\n // few hundred ms apart must both hit the network, otherwise the second one\n // resolves with the first one's (already stale) snapshot.\n if (options?.cache === false) {\n return this.request<T>(query, variables, true, options.timeoutMs);\n }\n\n const cacheKey = JSON.stringify({ query, variables });\n\n // Return cached response if still valid, evict if expired\n const cached = this.queryCache.get(cacheKey);\n if (cached) {\n if (Date.now() - cached.ts < WebSDKClient.CACHE_TTL) {\n return cached.data as GraphQLResponse<T>;\n }\n this.queryCache.delete(cacheKey);\n }\n\n // Deduplicate: if same query is already in-flight, reuse the promise\n const existing = this.inflight.get(cacheKey);\n if (existing) {\n return existing as Promise<GraphQLResponse<T>>;\n }\n\n const promise = this.request<T>(query, variables, true, options?.timeoutMs)\n .then((result) => {\n // Cache successful responses only\n if (result.data && !result.errors?.length) {\n if (this.queryCache.size >= WebSDKClient.MAX_CACHE_ENTRIES) {\n const oldestEntry = this.queryCache.keys().next().value;\n if (oldestEntry) {\n this.queryCache.delete(oldestEntry);\n }\n }\n this.queryCache.set(cacheKey, { data: result, ts: Date.now() });\n }\n return result;\n })\n .finally(() => {\n this.inflight.delete(cacheKey);\n });\n\n this.inflight.set(cacheKey, promise);\n return promise;\n }\n\n /**\n * Execute a GraphQL mutation\n */\n async mutate<T = Record<string, unknown>>(\n mutation: string,\n variables?: Record<string, unknown>,\n options?: WebSDKMutateOptions,\n ): Promise<GraphQLResponse<T>> {\n // retry=false: a retried mutation could double-submit (contact form,\n // waitlist signup, order). Only the timeout applies here.\n return this.request<T>(mutation, variables, false, options?.timeoutMs);\n }\n\n /** HTTP statuses worth another attempt — transient server/edge conditions. */\n private static isRetriableStatus(status: number): boolean {\n return status === 429 || status === 408 || (status >= 500 && status < 600);\n }\n\n private static sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Perform the HTTP call with a hard timeout. Every outcome resolves to a\n * GraphQLResponse — callers never hang, so a UI's `loading` state always\n * settles into data or a renderable error.\n */\n private async attempt<T>(\n query: string,\n variables: Record<string, unknown> | undefined,\n timeoutMs: number,\n ): Promise<{ res: GraphQLResponse<T>; retriable: boolean }> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(this.config.gatewayUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-product-id\": this.config.productId,\n ...this.config.headers,\n },\n body: JSON.stringify({ query, variables }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n console.error(\n \"[WebSDK] GraphQL request failed\",\n response.status,\n response.statusText,\n );\n return {\n res: {\n errors: [\n {\n message: `HTTP ${response.status}: ${response.statusText}`,\n extensions: { code: `HTTP_${response.status}` },\n },\n ],\n },\n retriable: WebSDKClient.isRetriableStatus(response.status),\n };\n }\n\n return {\n res: (await response.json()) as GraphQLResponse<T>,\n retriable: false,\n };\n } catch (error) {\n const aborted =\n error instanceof Error &&\n (error.name === \"AbortError\" || controller.signal.aborted);\n const message = aborted\n ? `Request timed out after ${timeoutMs}ms`\n : error instanceof Error\n ? error.message\n : \"Network error\";\n console.error(\"[WebSDK] Network error\", message);\n return {\n res: {\n errors: [\n {\n message,\n extensions: { code: aborted ? \"TIMEOUT\" : \"NETWORK_ERROR\" },\n },\n ],\n },\n // Transport-level failures are worth one more try; a genuine outage\n // just fails twice quickly and still renders an error state.\n retriable: true,\n };\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async request<T>(\n query: string,\n variables?: Record<string, unknown>,\n retry = true,\n timeoutOverrideMs?: number,\n ): Promise<GraphQLResponse<T>> {\n const timeoutMs =\n timeoutOverrideMs ??\n this.config.timeoutMs ??\n WebSDKClient.DEFAULT_TIMEOUT_MS;\n const maxRetries = retry\n ? (this.config.maxRetries ?? WebSDKClient.DEFAULT_MAX_RETRIES)\n : 0;\n\n let last: GraphQLResponse<T> | undefined;\n for (let i = 0; i <= maxRetries; i++) {\n const { res, retriable } = await this.attempt<T>(\n query,\n variables,\n timeoutMs,\n );\n if (!retriable || i === maxRetries) return res;\n last = res;\n // Small backoff with jitter so a burst of clients doesn't retry in lockstep.\n await WebSDKClient.sleep(\n WebSDKClient.RETRY_BASE_DELAY_MS * (i + 1) + Math.random() * 200,\n );\n }\n return last as GraphQLResponse<T>;\n }\n}\n","/**\n * React context provider for the Web SDK client.\n * Wraps the application with WebSDKClient configuration.\n */\n\"use client\";\n\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { resolveGatewayUrl } from \"./gateway-resolver\";\nimport { WebSDKClient, type WebSDKClientConfig } from \"./graphql-client\";\n\nconst WebSDKContext = createContext<WebSDKClient | null>(null);\n\nexport interface WebSDKProviderProps {\n /** SDK client configuration */\n config: WebSDKClientConfig;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Provider component that makes the WebSDKClient available to all child components.\n *\n * @example\n * ```tsx\n * <WebSDKProvider config={{\n * gatewayUrl: \"https://api.burdenoff.com/global/graphql\",\n * productId: \"your-product-id\",\n * productSlug: \"your-product\",\n * }}>\n * <App />\n * </WebSDKProvider>\n * ```\n */\nexport function WebSDKProvider({ config, children }: WebSDKProviderProps) {\n const client = useMemo(() => {\n const resolvedConfig = {\n ...config,\n gatewayUrl: resolveGatewayUrl(config.gatewayUrl),\n };\n return new WebSDKClient(resolvedConfig);\n }, [config]);\n\n return (\n <WebSDKContext.Provider value={client}>{children}</WebSDKContext.Provider>\n );\n}\n\n/**\n * Hook to access the WebSDKClient instance.\n * Must be used within a WebSDKProvider.\n */\nexport function useWebSDK(): WebSDKClient {\n const client = useContext(WebSDKContext);\n if (!client) {\n throw new Error(\"useWebSDK must be used within a WebSDKProvider\");\n }\n return client;\n}\n\n/**\n * Hook to access the SDK configuration.\n * Useful for components that need config values like productId, recaptchaSiteKey, etc.\n */\nexport function useWebSDKConfig(): WebSDKClientConfig {\n const client = useWebSDK();\n return client.getConfig();\n}\n","/**\n * Explore chat — TypeScript mirror of the public `/explore` GraphQL contract.\n *\n * Canonical source: `~/products/dev/platform/context/explore/CONTRACT.md` §1\n * (global-support-svc, served through the global PUBLIC gateway with\n * `@rbac(public: true, scopeType: \"global\")`).\n *\n * Nothing in this file may drift from that document. If a shape here looks\n * wrong, fix CONTRACT.md first and tell the backend workstreams — never patch\n * it locally.\n *\n * Nullability note: the contract marks `title`, `description`, `product`,\n * `imageUrl`, `partialContent`, `errorCode`, `completedAt`, `productSlug`,\n * `recaptchaSiteKey` and `remainingToday` as nullable, so every one of them is\n * `?: T | null` here — a GraphQL `null` and an omitted selection both have to\n * be representable.\n */\n\n// ============================================================================\n// Enums (string unions — the wire format is the enum name)\n// ============================================================================\n\nexport type ExploreMessageRole = \"USER\" | \"ASSISTANT\";\n\nexport type ExploreMessageStatus =\n \"PENDING\" | \"RUNNING\" | \"COMPLETED\" | \"FAILED\";\n\n/**\n * The `ExploreCta.kind` values enumerated in CONTRACT.md §1.\n *\n * `ExploreCtaLink.kind` is deliberately typed `string`, not this union: the\n * field is `String!` on the wire, and a kind added server-side must render\n * (falling back to the neutral CTA style) rather than break the build of 38\n * websites. Use this union when you are *producing* a kind.\n */\nexport type ExploreCtaKind =\n | \"CONTACT\"\n | \"PARTNERS\"\n | \"PRICING\"\n | \"SERVICES\"\n | \"WAITLIST\"\n | \"STORE\"\n | \"APP\"\n | \"DOCS\"\n | \"OTHER\";\n\n/**\n * Error codes surfaced through `extensions.code`. `HTTP_429` is what the\n * gateway emits when it rate-limits at the edge; the SDK client also produces\n * `TIMEOUT` / `NETWORK_ERROR` for transport failures.\n */\nexport type ExploreErrorCode =\n | \"EXPLORE_DISABLED\"\n | \"RATE_LIMITED\"\n | \"EXPLORE_GLOBAL_LIMIT\"\n | \"CAPTCHA_REQUIRED\"\n | \"CAPTCHA_FAILED\"\n | \"MESSAGE_TOO_LONG\"\n | \"MESSAGE_EMPTY\"\n | \"CONVERSATION_LIMIT\"\n | \"CONVERSATION_BUSY\"\n | \"UPSTREAM_UNAVAILABLE\"\n | \"NOT_FOUND\"\n | \"HTTP_429\"\n | \"TIMEOUT\"\n | \"NETWORK_ERROR\";\n\n// ============================================================================\n// Object types\n// ============================================================================\n\n/** `type ExploreReference` — a cited source page for an answer. */\nexport interface ExploreReference {\n url: string;\n title?: string | null;\n description?: string | null;\n product?: string | null;\n imageUrl?: string | null;\n}\n\n/**\n * `type ExploreCta` — a suggested next step attached to an answer.\n *\n * Named `ExploreCtaLink` in the SDK because `ExploreCta` is taken by the\n * exported nav component (`<ExploreCta variant=\"header\" />`). Same shape,\n * different name; the GraphQL type is unchanged.\n */\nexport interface ExploreCtaLink {\n /** One of {@link ExploreCtaKind}; unknown values render with the neutral style. */\n kind: string;\n label: string;\n url: string;\n product?: string | null;\n}\n\n/** `type ExploreMessage`. `content` is `\"\"` while the turn is PENDING. */\nexport interface ExploreMessage {\n id: string;\n conversationId: string;\n role: ExploreMessageRole;\n status: ExploreMessageStatus;\n /** Final answer, markdown. Empty string until the turn completes. */\n content: string;\n /** Streaming preview while PENDING/RUNNING. */\n partialContent?: string | null;\n /** Human-readable progress lines, e.g. \"Searching vibecontrols…\". */\n activity: string[];\n references: ExploreReference[];\n ctas: ExploreCtaLink[];\n errorCode?: string | null;\n createdAt: string;\n completedAt?: string | null;\n}\n\n/** `type ExploreConversation`. `token` is the client's only handle. */\nexport interface ExploreConversation {\n id: string;\n token: string;\n productSlug?: string | null;\n turnCount: number;\n createdAt: string;\n}\n\n/** `type ExploreProduct` — one product the harness can answer about. */\nexport interface ExploreProduct {\n slug: string;\n name: string;\n tagline?: string | null;\n website: string;\n}\n\n/** `type ExploreLimits` — server-owned caps the composer enforces locally. */\nexport interface ExploreLimits {\n maxMessageLength: number;\n maxTurnsPerConversation: number;\n messagesPerDay: number;\n historyTurns: number;\n}\n\n/**\n * `type ExploreCatalog` — everything the page needs before the first message.\n *\n * `captchaRequired` + `recaptchaSiteKey` are what turn reCAPTCHA v3 on: it is\n * a backend secret change, and no website redeploy is involved.\n */\nexport interface ExploreCatalog {\n enabled: boolean;\n products: ExploreProduct[];\n examplePrompts: string[];\n welcomeTitle: string;\n welcomeBody: string;\n limits: ExploreLimits;\n captchaRequired: boolean;\n recaptchaSiteKey?: string | null;\n}\n\n/** `input SendExploreMessageInput`. */\nexport interface SendExploreMessageInput {\n /** Omit to start a new conversation. */\n conversationToken?: string;\n /** The site the visitor is on — a soft hint, not a hard filter. */\n productSlug?: string;\n message: string;\n /** Only sent when `catalog.captchaRequired`. */\n recaptchaToken?: string;\n locale?: string;\n pageUrl?: string;\n}\n\n/**\n * `type SendExploreMessageResult`.\n *\n * **`assistantMessage.id` is the id to poll** — it comes back `PENDING`.\n */\nexport interface SendExploreMessageResult {\n conversation: ExploreConversation;\n userMessage: ExploreMessage;\n assistantMessage: ExploreMessage;\n remainingToday?: number | null;\n}\n\n// ============================================================================\n// GraphQL documents\n//\n// Only the fields the UI actually renders are requested — a narrower selection\n// set is cheaper to poll (this runs once every ~1.5s per active visitor) and\n// keeps the contract surface the websites depend on small.\n// ============================================================================\n\n/**\n * Shared selection set for every `ExploreMessage` in this file. Inlined as a\n * template string rather than a GraphQL `fragment` so each document stays a\n * single self-contained operation (the SDK client posts raw strings and has no\n * fragment registry).\n */\nconst EXPLORE_MESSAGE_FIELDS = /* GraphQL */ `\n id\n conversationId\n role\n status\n content\n partialContent\n activity\n references {\n url\n title\n description\n product\n imageUrl\n }\n ctas {\n kind\n label\n url\n product\n }\n errorCode\n createdAt\n completedAt\n`;\n\n/** Loaded once per page. Safe to serve from the SDK's 5-minute query cache. */\nexport const EXPLORE_CATALOG_QUERY = /* GraphQL */ `\n query ExploreCatalog($productSlug: String) {\n exploreCatalog(productSlug: $productSlug) {\n enabled\n products {\n slug\n name\n tagline\n website\n }\n examplePrompts\n welcomeTitle\n welcomeBody\n limits {\n maxMessageLength\n maxTurnsPerConversation\n messagesPerDay\n historyTurns\n }\n captchaRequired\n recaptchaSiteKey\n }\n }\n`;\n\n/**\n * The poll. MUST be issued with `client.query(..., { cache: false })` — the\n * default 5-minute cache would return the first PENDING snapshot forever and\n * the answer would never appear.\n */\nexport const EXPLORE_MESSAGE_QUERY = /* GraphQL */ `\n query ExploreMessage($conversationToken: String!, $id: ID!) {\n exploreMessage(conversationToken: $conversationToken, id: $id) {\n ${EXPLORE_MESSAGE_FIELDS}\n }\n }\n`;\n\n/** Submit half of the submit + poll pair. */\nexport const SEND_EXPLORE_MESSAGE_MUTATION = /* GraphQL */ `\n mutation SendExploreMessage($input: SendExploreMessageInput!) {\n sendExploreMessage(input: $input) {\n conversation {\n id\n token\n productSlug\n turnCount\n createdAt\n }\n userMessage {\n ${EXPLORE_MESSAGE_FIELDS}\n }\n assistantMessage {\n ${EXPLORE_MESSAGE_FIELDS}\n }\n remainingToday\n }\n }\n`;\n\n// ============================================================================\n// Response envelopes (what `client.query`/`client.mutate` resolve `data` to)\n// ============================================================================\n\nexport interface ExploreCatalogQueryData {\n exploreCatalog: ExploreCatalog;\n}\n\nexport interface ExploreMessageQueryData {\n exploreMessage: ExploreMessage | null;\n}\n\nexport interface SendExploreMessageMutationData {\n sendExploreMessage: SendExploreMessageResult;\n}\n","import type { WebsiteSwitcherProduct } from \"../components/website-switcher\";\n\n/**\n * Canonical Burdenoff ecosystem product list used by WebsiteSwitcher.\n *\n * Sourced from `~/products/websites/burdenoff-website/src/data/products.ts`.\n * Keep this in sync when products are added, renamed, or moved.\n */\nexport const ECOSYSTEM_PRODUCTS: WebsiteSwitcherProduct[] = [\n {\n slug: \"workspaces\",\n name: \"Workspaces\",\n websiteUrl: \"https://burdenoff.com\",\n },\n {\n slug: \"vibecontrols\",\n name: \"VibeControls\",\n websiteUrl: \"https://vibecontrols.com\",\n },\n {\n slug: \"fluidgrids\",\n name: \"FluidGrids\",\n websiteUrl: \"https://fluidgrids.com\",\n },\n // Botlit ships on botlit.ai — botlit.com does not resolve.\n { slug: \"botlit\", name: \"Botlit\", websiteUrl: \"https://www.botlit.ai\" },\n {\n slug: \"bigconsole\",\n name: \"BigConsole\",\n websiteUrl: \"https://bigconsole.com\",\n },\n {\n slug: \"semanticfed\",\n name: \"SemanticFed\",\n websiteUrl: \"https://semanticfed.com\",\n },\n {\n slug: \"intelwatchtower\",\n name: \"IntelWatchtower\",\n websiteUrl: \"https://intelwatchtower.com\",\n },\n { slug: \"buildmyiq\", name: \"BuildMyIQ\", websiteUrl: \"https://buildmyiq.com\" },\n {\n slug: \"assethandler\",\n name: \"AssetHandler\",\n websiteUrl: \"https://assethandler.com\",\n },\n {\n slug: \"crewfoundry\",\n name: \"CrewFoundry\",\n websiteUrl: \"https://crewfoundry.com\",\n },\n {\n slug: \"planmagnet\",\n name: \"PlanMagnet\",\n websiteUrl: \"https://planmagnet.com\",\n },\n {\n slug: \"eventfullymanaged\",\n name: \"EventfullyManaged\",\n websiteUrl: \"https://eventfullymanaged.com\",\n },\n {\n slug: \"headshotmarketing\",\n name: \"HeadshotMarketing\",\n websiteUrl: \"https://headshotmarketing.com\",\n },\n {\n slug: \"technospam\",\n name: \"TechnoSpam\",\n websiteUrl: \"https://technospam.com\",\n },\n { slug: \"kadaikodi\", name: \"Kadaikodi\", websiteUrl: \"https://kadaikodi.com\" },\n {\n slug: \"movethewheels\",\n name: \"MoveTheWheels\",\n websiteUrl: \"https://movethewheels.com\",\n },\n {\n slug: \"healthybowl\",\n name: \"Healthy Bowl\",\n websiteUrl: \"https://gethealthybowl.com\",\n },\n { slug: \"ggnomad\", name: \"GGNomad\", websiteUrl: \"https://ggnomad.com\" },\n {\n slug: \"timecampus\",\n name: \"TimeCampus\",\n websiteUrl: \"https://timecampus.com\",\n },\n {\n slug: \"manufacturedops\",\n name: \"ManufacturedOps\",\n websiteUrl: \"https://manufacturedops.com\",\n },\n {\n slug: \"theglobalfuel\",\n name: \"TheGlobalFuel\",\n websiteUrl: \"https://theglobalfuel.com\",\n },\n {\n slug: \"housingvista\",\n name: \"HousingVista\",\n websiteUrl: \"https://housingvista.com\",\n },\n {\n slug: \"proserviceworld\",\n name: \"ProServiceWorld\",\n websiteUrl: \"https://proserviceworld.com\",\n },\n {\n slug: \"mybodyshield\",\n name: \"MyBodyShield\",\n websiteUrl: \"https://mybodyshield.com\",\n },\n {\n slug: \"artistrybase\",\n name: \"ArtistryBase\",\n websiteUrl: \"https://artistrybase.com\",\n },\n {\n slug: \"theculturepost\",\n name: \"TheCulturePost\",\n websiteUrl: \"https://theculturepost.com\",\n },\n { slug: \"collabkin\", name: \"CollabKin\", websiteUrl: \"https://collabkin.com\" },\n {\n slug: \"comradecircle\",\n name: \"ComradeCircle\",\n websiteUrl: \"https://comradecircle.com\",\n },\n {\n slug: \"brainyrich\",\n name: \"BrainyRich\",\n websiteUrl: \"https://brainyrich.com\",\n },\n {\n slug: \"cosmicintersection\",\n name: \"CosmicIntersection\",\n websiteUrl: \"https://cosmicintersection.com\",\n },\n {\n slug: \"govcitizenhub\",\n name: \"GovCitizenHub\",\n websiteUrl: \"https://govcitizenhub.com\",\n },\n {\n slug: \"adaptercloud\",\n name: \"AdapterCloud\",\n websiteUrl: \"https://adaptercloud.com\",\n },\n {\n slug: \"subscriberbot\",\n name: \"Subscriber Bot\",\n websiteUrl: \"https://subscriberbot.com\",\n },\n {\n slug: \"hookmovies\",\n name: \"HookMovies\",\n websiteUrl: \"https://hookmovies.com\",\n },\n {\n slug: \"coolandlovely\",\n name: \"CoolAndLovely\",\n websiteUrl: \"https://coolandlovely.com\",\n },\n {\n slug: \"atheletebridge\",\n name: \"AthleteBridge\",\n websiteUrl: \"https://atheletebridge.com\",\n },\n {\n slug: \"labsofscience\",\n name: \"LabsOfScience\",\n websiteUrl: \"https://labsofscience.com\",\n },\n {\n slug: \"ecoimpacthub\",\n name: \"EcoImpactHub\",\n websiteUrl: \"https://ecoimpacthub.com\",\n },\n];\n","/**\n * reCAPTCHA v3 (invisible, score-based) loader and token minter.\n *\n * Deliberately dependency-free: the SDK already ships the `react-google-recaptcha`\n * peer for the **v2 checkbox** used by `ContactPage`, and the two widgets cannot\n * share a script tag — v3 needs `?render=<siteKey>` on the URL, v2 must not have\n * it. This module injects its own v3 script and leaves the v2 integration alone.\n *\n * The Explore chat turns v3 on purely from the backend catalog\n * (`exploreCatalog.captchaRequired && recaptchaSiteKey`), so nothing is loaded\n * and no third-party request is made on sites where captcha is off.\n */\n\n/** The slice of the `grecaptcha` global this module uses. */\nexport interface RecaptchaV3 {\n /** Runs the callback once the API is fully initialised. */\n ready(callback: () => void): void;\n /** Mints a single-use token for `action`. */\n execute(siteKey: string, options: { action: string }): Promise<string>;\n}\n\ndeclare global {\n interface Window {\n grecaptcha?: RecaptchaV3;\n }\n}\n\nconst SCRIPT_ID = \"boff-recaptcha-v3\";\nconst SCRIPT_SRC = \"https://www.google.com/recaptcha/api.js?render=\";\n\n/** Default action name reported to reCAPTCHA for Explore chat submissions. */\nexport const EXPLORE_RECAPTCHA_ACTION = \"explore_chat\";\n\n/**\n * One in-flight/settled promise per site key. Guarantees the script tag is\n * injected at most once even when several components mount at the same time,\n * and lets later callers await the same load instead of racing it.\n */\nconst loaders = new Map<string, Promise<RecaptchaV3>>();\n\nfunction isBrowser(): boolean {\n return typeof window !== \"undefined\" && typeof document !== \"undefined\";\n}\n\n/**\n * Load the reCAPTCHA v3 script for `siteKey` and resolve once `grecaptcha` is\n * ready to mint tokens.\n *\n * - Injects the script at most once per site key (subsequent calls reuse the\n * same promise).\n * - Adopts an already-present script tag (e.g. injected by the host site)\n * rather than adding a second one.\n * - Rejects rather than hanging when the script fails to load, so the caller\n * can decide whether to submit without a token or surface an error.\n */\nexport function loadRecaptchaV3(siteKey: string): Promise<RecaptchaV3> {\n if (!siteKey) {\n return Promise.reject(new Error(\"reCAPTCHA site key is required\"));\n }\n if (!isBrowser()) {\n return Promise.reject(\n new Error(\"reCAPTCHA v3 can only be loaded in a browser\"),\n );\n }\n\n const existing = loaders.get(siteKey);\n if (existing) return existing;\n\n const promise = new Promise<RecaptchaV3>((resolve, reject) => {\n const ready = () => {\n const api = window.grecaptcha;\n if (!api) {\n reject(new Error(\"reCAPTCHA loaded but grecaptcha is unavailable\"));\n return;\n }\n // `ready` queues until the API has finished initialising internally;\n // calling `execute` before that throws.\n api.ready(() => resolve(api));\n };\n\n // Already loaded by this module, another SDK instance, or the host site.\n if (window.grecaptcha) {\n ready();\n return;\n }\n\n const scriptId = `${SCRIPT_ID}-${siteKey}`;\n const found = document.getElementById(scriptId);\n if (found) {\n found.addEventListener(\"load\", ready, { once: true });\n found.addEventListener(\n \"error\",\n () => reject(new Error(\"Failed to load reCAPTCHA v3\")),\n { once: true },\n );\n return;\n }\n\n const script = document.createElement(\"script\");\n script.id = scriptId;\n script.src = `${SCRIPT_SRC}${encodeURIComponent(siteKey)}`;\n script.async = true;\n script.defer = true;\n script.addEventListener(\"load\", ready, { once: true });\n script.addEventListener(\n \"error\",\n () => {\n // Drop the memo so a later attempt can retry a transient CDN failure\n // instead of being stuck with a permanently rejected promise.\n loaders.delete(siteKey);\n reject(new Error(\"Failed to load reCAPTCHA v3\"));\n },\n { once: true },\n );\n document.head.appendChild(script);\n });\n\n loaders.set(siteKey, promise);\n return promise;\n}\n\n/**\n * Mint a single-use reCAPTCHA v3 token, loading the script on first use.\n *\n * Tokens are valid for ~2 minutes and are consumed by one verification, so\n * this must be called per submission — never cached.\n */\nexport async function getRecaptchaV3Token(\n siteKey: string,\n action: string = EXPLORE_RECAPTCHA_ACTION,\n): Promise<string> {\n const api = await loadRecaptchaV3(siteKey);\n return api.execute(siteKey, { action });\n}\n","/**\n * useExploreChat — the `/explore` conversation state machine.\n *\n * Implements the client half of CONTRACT.md §1: a **submit + poll** exchange.\n * `sendExploreMessage` returns immediately with a PENDING assistant message;\n * the answer arrives by polling `exploreMessage(conversationToken, id)` roughly\n * every 1.5s until it reports COMPLETED or FAILED. Both gateway hops cap a\n * subgraph call at 20s while a turn takes 5-60s, which is why there is no\n * request that simply waits for the answer.\n *\n * Design rules this hook exists to enforce:\n *\n * 1. **The catalog never gates the first paint.** `catalog` is populated with a\n * static fallback synchronously, so `ExplorePage` can render its `<h1>` on\n * the very first render. The websites' prerender waits for an `h1`; if that\n * heading depended on a network round-trip, 38 static builds would capture a\n * blank page.\n * 2. **Polls bypass the query cache.** `client.query(..., { cache: false })` —\n * the default 5-minute cache would hand every later poll the first PENDING\n * snapshot and the answer would never appear.\n * 3. **Nothing outlives the component.** Unmount and `stop()` both cancel the\n * poll chain through a generation counter, so a late response can never\n * write into an unmounted tree.\n */\n\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { useWebSDK } from \"../client/provider\";\nimport {\n EXPLORE_CATALOG_QUERY,\n EXPLORE_MESSAGE_QUERY,\n SEND_EXPLORE_MESSAGE_MUTATION,\n} from \"../components/explore-types\";\nimport { ECOSYSTEM_PRODUCTS } from \"../data/products\";\nimport { getRecaptchaV3Token } from \"../utils/recaptcha-v3\";\n\nimport type {\n ExploreCatalog,\n ExploreCatalogQueryData,\n ExploreLimits,\n ExploreMessage,\n ExploreMessageQueryData,\n SendExploreMessageInput,\n SendExploreMessageMutationData,\n} from \"../components/explore-types\";\n\n// ============================================================================\n// Public types\n// ============================================================================\n\n/**\n * Where the conversation is right now.\n *\n * - `loading` — catalog request in flight (the fallback catalog is already\n * rendered, so this is a refinement, not a blank screen).\n * - `ready` — idle; the composer accepts input.\n * - `sending` — `sendExploreMessage` in flight.\n * - `streaming` — polling the assistant turn; `activity` is live.\n * - `error` — the last turn failed; `retry()` is meaningful and the\n * composer stays usable.\n * - `limited` — rate limited; the composer is disabled.\n * - `disabled` — `exploreCatalog.enabled === false`.\n */\nexport type ExploreChatPhase =\n | \"loading\"\n | \"ready\"\n | \"sending\"\n | \"streaming\"\n | \"error\"\n | \"limited\"\n | \"disabled\";\n\n/** Coarse bucket the UI switches its banner copy and affordances on. */\nexport type ExploreChatErrorKind =\n | \"rate-limit\"\n | \"captcha\"\n | \"timeout\"\n | \"network\"\n | \"disabled\"\n | \"validation\"\n | \"unknown\";\n\nexport interface ExploreChatError {\n /** UI bucket. */\n kind: ExploreChatErrorKind;\n /** Raw `extensions.code` (or a client-side code such as `TIMEOUT`). */\n code: string;\n /** Human-readable, safe to render. */\n message: string;\n /** Whether re-sending the same message could plausibly succeed. */\n retryable: boolean;\n}\n\nexport interface UseExploreChatOptions {\n /** Slug of the product site this page is on — a soft hint to the harness. */\n productSlug?: string;\n /** Full URL of the page, forwarded as `pageUrl`. */\n pageUrl?: string;\n /** BCP-47 locale, forwarded as `locale`. */\n locale?: string;\n /** Poll cadence in ms. Default 1500 (CONTRACT.md §1). */\n pollIntervalMs?: number;\n /** Give up on a turn after this long. Default 90000 (the edge poll timeout). */\n pollTimeoutMs?: number;\n /**\n * Prompts to offer when `exploreCatalog` supplies none. Resolution order is\n * catalog → this option → {@link DEFAULT_EXPLORE_EXAMPLE_PROMPTS}, so a site\n * can ship product-specific prompts without waiting on the backend and still\n * be overridden centrally once the catalog carries them.\n */\n examplePrompts?: string[];\n /** sessionStorage key. Default `boff.explore.v1`. */\n storageKey?: string;\n /** Persist the conversation across reloads within the tab. Default true. */\n persist?: boolean;\n /** Called with the message text each time a send is accepted locally. */\n onSend?: (message: string) => void;\n}\n\nexport interface UseExploreChatResult {\n phase: ExploreChatPhase;\n /** Never null — starts as the static fallback, upgraded by the server. */\n catalog: ExploreCatalog;\n messages: ExploreMessage[];\n /** Latest progress line of the in-flight turn, or null when idle. */\n activity: string | null;\n /** Messages left today for this visitor, when the server reports it. */\n remainingToday: number | null;\n error: ExploreChatError | null;\n /** Product the visitor pinned the conversation to, or null for \"all\". */\n focusProduct: string | null;\n setFocusProduct: (slug: string | null) => void;\n send: (message: string) => Promise<void>;\n /** Stop polling and keep whatever text has streamed so far. */\n stop: () => void;\n /** Re-send the last message after a failed turn. */\n retry: () => void;\n /** Clear the conversation and the persisted session. */\n reset: () => void;\n canSend: boolean;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_STORAGE_KEY = \"boff.explore.v1\";\nconst DEFAULT_POLL_INTERVAL_MS = 1_500;\n/** Matches `EXPLORE_AGENT_TIMEOUT_MS` (CONTRACT.md §3) — the edge gives up too. */\nconst DEFAULT_POLL_TIMEOUT_MS = 90_000;\n/** Per-poll HTTP timeout. Short: a stuck poll must not stall the chain. */\nconst POLL_REQUEST_TIMEOUT_MS = 10_000;\n/** The submit hop enqueues a job; generous but well under the gateway's 20s. */\nconst SEND_REQUEST_TIMEOUT_MS = 18_000;\n/** Transient poll failures tolerated before the turn is declared dead. */\nconst MAX_CONSECUTIVE_POLL_FAILURES = 4;\n/** Cap on what goes into sessionStorage — a session must not grow unbounded. */\nconst MAX_PERSISTED_MESSAGES = 40;\n\n/** Fallback limits, mirroring the server defaults in CONTRACT.md §3. */\nexport const FALLBACK_EXPLORE_LIMITS: ExploreLimits = {\n maxMessageLength: 2000,\n maxTurnsPerConversation: 20,\n messagesPerDay: 100,\n historyTurns: 6,\n};\n\n/**\n * Prompts shown when neither the catalog nor the consumer supplies any.\n * Deliberately product-agnostic — this SDK renders on 38 different sites.\n */\nexport const DEFAULT_EXPLORE_EXAMPLE_PROMPTS: string[] = [\n \"What does this product actually do?\",\n \"Which Burdenoff product fits my team?\",\n \"How do I get started, step by step?\",\n \"What does it integrate with?\",\n];\n\nconst FALLBACK_WELCOME_TITLE = \"Ask anything about our products\";\nconst FALLBACK_WELCOME_BODY =\n \"Get straight answers drawn from our product documentation and public pages — with links back to the exact page each answer came from.\";\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction buildFallbackCatalog(examplePrompts?: string[]): ExploreCatalog {\n return {\n enabled: true,\n products: ECOSYSTEM_PRODUCTS.map((p) => ({\n slug: p.slug,\n name: p.name,\n tagline: null,\n website: p.websiteUrl,\n })),\n examplePrompts: examplePrompts?.length\n ? examplePrompts\n : DEFAULT_EXPLORE_EXAMPLE_PROMPTS,\n welcomeTitle: FALLBACK_WELCOME_TITLE,\n welcomeBody: FALLBACK_WELCOME_BODY,\n limits: FALLBACK_EXPLORE_LIMITS,\n captchaRequired: false,\n recaptchaSiteKey: null,\n };\n}\n\n/**\n * Harden a server catalog against partial/degraded responses so a missing\n * field can never blank the page or produce `maxMessageLength: 0` (which would\n * silently disable the composer).\n */\nfunction normalizeCatalog(\n raw: ExploreCatalog,\n fallback: ExploreCatalog,\n): ExploreCatalog {\n return {\n enabled: raw.enabled !== false,\n products: raw.products?.length ? raw.products : fallback.products,\n examplePrompts: raw.examplePrompts?.length\n ? raw.examplePrompts\n : fallback.examplePrompts,\n welcomeTitle: raw.welcomeTitle || fallback.welcomeTitle,\n welcomeBody: raw.welcomeBody || fallback.welcomeBody,\n limits: {\n maxMessageLength:\n raw.limits?.maxMessageLength || fallback.limits.maxMessageLength,\n maxTurnsPerConversation:\n raw.limits?.maxTurnsPerConversation ||\n fallback.limits.maxTurnsPerConversation,\n messagesPerDay:\n raw.limits?.messagesPerDay || fallback.limits.messagesPerDay,\n historyTurns: raw.limits?.historyTurns || fallback.limits.historyTurns,\n },\n captchaRequired: raw.captchaRequired === true,\n recaptchaSiteKey: raw.recaptchaSiteKey ?? null,\n };\n}\n\nconst RATE_LIMIT_CODES = new Set([\n \"RATE_LIMITED\",\n \"HTTP_429\",\n \"EXPLORE_GLOBAL_LIMIT\",\n]);\nconst CAPTCHA_CODES = new Set([\"CAPTCHA_FAILED\", \"CAPTCHA_REQUIRED\"]);\nconst NETWORK_CODES = new Set([\n \"NETWORK_ERROR\",\n \"UPSTREAM_UNAVAILABLE\",\n \"CONVERSATION_BUSY\",\n \"PROVIDER_ERROR\",\n \"QUEUE_FULL\",\n]);\nconst VALIDATION_CODES = new Set([\n \"MESSAGE_TOO_LONG\",\n \"MESSAGE_EMPTY\",\n \"CONVERSATION_LIMIT\",\n \"INVALID_INPUT\",\n]);\n\n/**\n * Map a `extensions.code` (or a client-side transport code) onto the bucket the\n * UI renders. Unknown codes are treated as retryable — a transient backend\n * condition we have not enumerated is far more likely than a permanent one.\n */\nexport function classifyExploreError(\n code: string | null | undefined,\n serverMessage?: string | null,\n): ExploreChatError {\n const c = code ?? \"UNKNOWN\";\n if (RATE_LIMIT_CODES.has(c)) {\n return {\n kind: \"rate-limit\",\n code: c,\n message:\n \"You've reached the message limit for now. Please try again later.\",\n retryable: false,\n };\n }\n if (CAPTCHA_CODES.has(c)) {\n return {\n kind: \"captcha\",\n code: c,\n message:\n \"We couldn't verify that you're human. Please try sending that again.\",\n retryable: true,\n };\n }\n if (c === \"TIMEOUT\" || c === \"TOOL_BUDGET\") {\n return {\n kind: \"timeout\",\n code: c,\n message: \"That answer took too long to come back. Try asking again.\",\n retryable: true,\n };\n }\n if (NETWORK_CODES.has(c)) {\n return {\n kind: \"network\",\n code: c,\n message:\n \"We couldn't reach the assistant just now. Check your connection and try again.\",\n retryable: true,\n };\n }\n if (c === \"EXPLORE_DISABLED\") {\n return {\n kind: \"disabled\",\n code: c,\n message: \"Explore is unavailable at the moment. Please check back soon.\",\n retryable: false,\n };\n }\n if (VALIDATION_CODES.has(c)) {\n return {\n kind: \"validation\",\n code: c,\n message: serverMessage || \"That message couldn't be sent.\",\n retryable: false,\n };\n }\n if (c === \"EMPTY_ANSWER\") {\n return {\n kind: \"unknown\",\n code: c,\n message:\n \"No answer came back for that one. Try rephrasing, or ask something more specific.\",\n retryable: true,\n };\n }\n return {\n kind: \"unknown\",\n code: c,\n message: serverMessage || \"Something went wrong. Please try again.\",\n retryable: true,\n };\n}\n\ninterface PersistedExploreState {\n conversationToken: string | null;\n messages: ExploreMessage[];\n focusProduct: string | null;\n}\n\nfunction readPersisted(key: string): PersistedExploreState | null {\n // SSR / prerender: there is no sessionStorage, and reading one during the\n // first client render would desync hydration anyway.\n if (typeof window === \"undefined\") return null;\n try {\n const raw = window.sessionStorage.getItem(key);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n if (!parsed || typeof parsed !== \"object\") return null;\n const record = parsed as Partial<PersistedExploreState>;\n return {\n conversationToken:\n typeof record.conversationToken === \"string\"\n ? record.conversationToken\n : null,\n messages: Array.isArray(record.messages)\n ? record.messages.slice(-MAX_PERSISTED_MESSAGES)\n : [],\n focusProduct:\n typeof record.focusProduct === \"string\" ? record.focusProduct : null,\n };\n } catch {\n /* corrupt or unavailable storage — start a fresh conversation */\n return null;\n }\n}\n\n/**\n * A turn that never produced any text is worth dropping rather than rendering\n * as an empty bubble — used by `stop()` and by the failure paths.\n */\nfunction visibleText(message: ExploreMessage): string {\n return message.content || message.partialContent || \"\";\n}\n\nfunction countUserTurns(messages: ExploreMessage[]): number {\n return messages.filter((m) => m.role === \"USER\").length;\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useExploreChat(\n options: UseExploreChatOptions = {},\n): UseExploreChatResult {\n const {\n productSlug,\n pageUrl,\n locale,\n examplePrompts,\n pollIntervalMs = DEFAULT_POLL_INTERVAL_MS,\n pollTimeoutMs = DEFAULT_POLL_TIMEOUT_MS,\n storageKey = DEFAULT_STORAGE_KEY,\n persist = true,\n onSend,\n } = options;\n\n const client = useWebSDK();\n\n // The fallback catalog is the initial value AND the merge base for the\n // server response. Keyed on the prompt CONTENT, not the array identity —\n // a consumer passing an inline `examplePrompts={[...]}` literal would\n // otherwise rebuild it every render and re-fire the catalog effect.\n const promptKey = JSON.stringify(examplePrompts ?? []);\n const fallbackCatalog = useMemo(\n () => buildFallbackCatalog(JSON.parse(promptKey) as string[]),\n [promptKey],\n );\n\n const [catalog, setCatalog] = useState<ExploreCatalog>(fallbackCatalog);\n const [messages, setMessages] = useState<ExploreMessage[]>([]);\n const [phase, setPhase] = useState<ExploreChatPhase>(\"loading\");\n const [error, setError] = useState<ExploreChatError | null>(null);\n const [remainingToday, setRemainingToday] = useState<number | null>(null);\n const [focusProduct, setFocusProductState] = useState<string | null>(null);\n const [turnCount, setTurnCount] = useState(0);\n const [hydrated, setHydrated] = useState(false);\n\n // Refs mirror the state that async callbacks read, so `send`/`poll` never\n // close over a stale value and never need to be re-created mid-flight.\n const mountedRef = useRef(true);\n const pollGenerationRef = useRef(0);\n const pollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const conversationTokenRef = useRef<string | null>(null);\n const catalogRef = useRef<ExploreCatalog>(fallbackCatalog);\n const turnCountRef = useRef(0);\n const focusProductRef = useRef<string | null>(null);\n const lastSentTextRef = useRef<string | null>(null);\n const inFlightRef = useRef(false);\n\n catalogRef.current = catalog;\n\n const clearPollTimer = useCallback(() => {\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n }, []);\n\n /** Invalidate any running poll chain. Late responses become no-ops. */\n const cancelPolling = useCallback(() => {\n pollGenerationRef.current += 1;\n clearPollTimer();\n }, [clearPollTimer]);\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n pollGenerationRef.current += 1;\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n };\n }, []);\n\n // --------------------------------------------------------------------------\n // Hydrate from sessionStorage (effect, not lazy state, so the FIRST client\n // render matches the prerendered HTML and hydration stays clean).\n // --------------------------------------------------------------------------\n useEffect(() => {\n if (!persist) {\n setHydrated(true);\n return;\n }\n const stored = readPersisted(storageKey);\n if (stored) {\n conversationTokenRef.current = stored.conversationToken;\n focusProductRef.current = stored.focusProduct;\n // A turn that was still streaming when the tab was closed can never be\n // resumed from here — the poll chain is gone. Land it as-is.\n const settled = stored.messages.flatMap<ExploreMessage>((m) => {\n if (m.role !== \"ASSISTANT\") return [m];\n if (m.status !== \"PENDING\" && m.status !== \"RUNNING\") return [m];\n const text = visibleText(m);\n if (!text) return [];\n return [{ ...m, status: \"COMPLETED\", content: text }];\n });\n setMessages(settled);\n setFocusProductState(stored.focusProduct);\n const turns = countUserTurns(settled);\n turnCountRef.current = turns;\n setTurnCount(turns);\n }\n setHydrated(true);\n }, [persist, storageKey]);\n\n // --------------------------------------------------------------------------\n // Persist (after hydration, so the initial empty state never wipes storage).\n // --------------------------------------------------------------------------\n useEffect(() => {\n if (!persist || !hydrated || typeof window === \"undefined\") return;\n try {\n const payload: PersistedExploreState = {\n conversationToken: conversationTokenRef.current,\n messages: messages.slice(-MAX_PERSISTED_MESSAGES),\n focusProduct,\n };\n // Nothing worth restoring (fresh page, or just after reset()): drop the\n // key entirely rather than leaving an empty husk behind.\n if (\n !payload.conversationToken &&\n payload.messages.length === 0 &&\n !payload.focusProduct\n ) {\n window.sessionStorage.removeItem(storageKey);\n return;\n }\n window.sessionStorage.setItem(storageKey, JSON.stringify(payload));\n } catch {\n /* private mode / quota exceeded — persistence is a nicety, not a feature */\n }\n }, [persist, hydrated, storageKey, messages, focusProduct]);\n\n // --------------------------------------------------------------------------\n // Catalog. Cached (the default) — it is per-page-load configuration, not a\n // poll. A failure keeps the fallback so the page NEVER renders blank.\n // --------------------------------------------------------------------------\n useEffect(() => {\n let cancelled = false;\n const load = async () => {\n const res = await client.query<ExploreCatalogQueryData>(\n EXPLORE_CATALOG_QUERY,\n { productSlug: productSlug ?? null },\n );\n if (cancelled || !mountedRef.current) return;\n\n const raw = res.data?.exploreCatalog;\n if (res.errors?.length || !raw) {\n console.warn(\n \"[WebSDK] exploreCatalog unavailable — using the built-in fallback catalog\",\n res.errors?.[0]?.message,\n );\n setPhase((prev) => (prev === \"loading\" ? \"ready\" : prev));\n return;\n }\n\n const next = normalizeCatalog(raw, fallbackCatalog);\n setCatalog(next);\n catalogRef.current = next;\n setPhase((prev) => {\n if (!next.enabled) return \"disabled\";\n return prev === \"loading\" ? \"ready\" : prev;\n });\n };\n void load();\n return () => {\n cancelled = true;\n };\n }, [client, productSlug, fallbackCatalog]);\n\n // --------------------------------------------------------------------------\n // Poll chain\n // --------------------------------------------------------------------------\n const startPolling = useCallback(\n (conversationToken: string, messageId: string) => {\n pollGenerationRef.current += 1;\n const generation = pollGenerationRef.current;\n const startedAt = Date.now();\n let consecutiveFailures = 0;\n\n const isStale = () =>\n !mountedRef.current || generation !== pollGenerationRef.current;\n\n const finishWithError = (chatError: ExploreChatError) => {\n inFlightRef.current = false;\n setMessages((prev) =>\n prev.flatMap<ExploreMessage>((m) => {\n if (m.id !== messageId) return [m];\n const text = visibleText(m);\n if (!text) return [];\n return [{ ...m, status: \"FAILED\", content: text }];\n }),\n );\n setError(chatError);\n setPhase(chatError.kind === \"rate-limit\" ? \"limited\" : \"error\");\n };\n\n const tick = async () => {\n if (isStale()) return;\n\n if (Date.now() - startedAt > pollTimeoutMs) {\n finishWithError(classifyExploreError(\"TIMEOUT\"));\n return;\n }\n\n // `cache: false` is load-bearing — see CONTRACT.md §4.\n const res = await client.query<ExploreMessageQueryData>(\n EXPLORE_MESSAGE_QUERY,\n { conversationToken, id: messageId },\n { cache: false, timeoutMs: POLL_REQUEST_TIMEOUT_MS },\n );\n if (isStale()) return;\n\n const first = res.errors?.[0];\n if (first) {\n const code =\n typeof first.extensions?.code === \"string\"\n ? first.extensions.code\n : undefined;\n const classified = classifyExploreError(code, first.message);\n // Hard stops: retrying a rate limit or a disabled feature is pointless.\n if (!classified.retryable) {\n finishWithError(classified);\n return;\n }\n consecutiveFailures += 1;\n if (consecutiveFailures >= MAX_CONSECUTIVE_POLL_FAILURES) {\n finishWithError(classified);\n return;\n }\n pollTimerRef.current = setTimeout(() => void tick(), pollIntervalMs);\n return;\n }\n\n const message = res.data?.exploreMessage;\n if (!message) {\n // Can happen briefly right after submit; tolerate a few misses.\n consecutiveFailures += 1;\n if (consecutiveFailures >= MAX_CONSECUTIVE_POLL_FAILURES) {\n finishWithError(classifyExploreError(\"NOT_FOUND\"));\n return;\n }\n pollTimerRef.current = setTimeout(() => void tick(), pollIntervalMs);\n return;\n }\n\n consecutiveFailures = 0;\n // Replace in place so `partialContent` renders as it streams.\n setMessages((prev) =>\n prev.map((m) => (m.id === messageId ? message : m)),\n );\n\n if (message.status === \"COMPLETED\") {\n inFlightRef.current = false;\n setError(null);\n setPhase(\"ready\");\n return;\n }\n if (message.status === \"FAILED\") {\n finishWithError(\n classifyExploreError(message.errorCode ?? \"UPSTREAM_UNAVAILABLE\"),\n );\n return;\n }\n\n setPhase(\"streaming\");\n pollTimerRef.current = setTimeout(() => void tick(), pollIntervalMs);\n };\n\n // First poll after one interval — the turn cannot possibly be done sooner.\n pollTimerRef.current = setTimeout(() => void tick(), pollIntervalMs);\n },\n [client, pollIntervalMs, pollTimeoutMs],\n );\n\n // --------------------------------------------------------------------------\n // send\n // --------------------------------------------------------------------------\n const submit = useCallback(\n async (\n text: string,\n optimisticId: string,\n captchaAttempt: number,\n ): Promise<void> => {\n const activeCatalog = catalogRef.current;\n\n let recaptchaToken: string | undefined;\n if (activeCatalog.captchaRequired && activeCatalog.recaptchaSiteKey) {\n try {\n recaptchaToken = await getRecaptchaV3Token(\n activeCatalog.recaptchaSiteKey,\n );\n } catch (err) {\n console.warn(\"[WebSDK] reCAPTCHA v3 token could not be minted\", err);\n // Send without a token and let the backend decide — it owns the\n // policy, and a blocked third-party script must not silently kill\n // the whole feature.\n }\n }\n\n const input: SendExploreMessageInput = {\n message: text,\n ...(conversationTokenRef.current\n ? { conversationToken: conversationTokenRef.current }\n : {}),\n ...(focusProductRef.current || productSlug\n ? { productSlug: focusProductRef.current ?? productSlug }\n : {}),\n ...(recaptchaToken ? { recaptchaToken } : {}),\n ...(locale ? { locale } : {}),\n ...(pageUrl ? { pageUrl } : {}),\n };\n\n const res = await client.mutate<SendExploreMessageMutationData>(\n SEND_EXPLORE_MESSAGE_MUTATION,\n { input },\n { timeoutMs: SEND_REQUEST_TIMEOUT_MS },\n );\n if (!mountedRef.current) return;\n\n const first = res.errors?.[0];\n const result = res.data?.sendExploreMessage;\n\n if (first || !result) {\n const code =\n typeof first?.extensions?.code === \"string\"\n ? first.extensions.code\n : undefined;\n const classified = classifyExploreError(code, first?.message);\n\n // CAPTCHA_FAILED: one silent re-mint + re-send before bothering the\n // visitor. v3 tokens expire in ~2 minutes and are single-use, so a\n // stale one is a routine, self-healing failure.\n if (classified.kind === \"captcha\" && captchaAttempt === 0) {\n await submit(text, optimisticId, 1);\n return;\n }\n\n inFlightRef.current = false;\n setError(classified);\n setPhase(classified.kind === \"rate-limit\" ? \"limited\" : \"error\");\n return;\n }\n\n conversationTokenRef.current = result.conversation.token;\n turnCountRef.current = result.conversation.turnCount;\n setTurnCount(result.conversation.turnCount);\n setRemainingToday(result.remainingToday ?? null);\n\n const userMessage = result.userMessage;\n const assistantMessage = result.assistantMessage;\n\n // Swap the optimistic user bubble for the server's, then append the\n // PENDING assistant turn that the poll chain will fill in. The `some`\n // guard keeps the visitor's words on screen even in the impossible case\n // where the optimistic bubble is already gone.\n setMessages((prev) => {\n const replaced = prev.some((m) => m.id === optimisticId)\n ? prev.map((m) => (m.id === optimisticId ? userMessage : m))\n : [...prev, userMessage];\n return [...replaced, assistantMessage];\n });\n\n if (\n assistantMessage.status === \"COMPLETED\" ||\n assistantMessage.status === \"FAILED\"\n ) {\n inFlightRef.current = false;\n if (assistantMessage.status === \"FAILED\") {\n const classified = classifyExploreError(\n assistantMessage.errorCode ?? \"UPSTREAM_UNAVAILABLE\",\n );\n setError(classified);\n setPhase(\"error\");\n } else {\n setPhase(\"ready\");\n }\n return;\n }\n\n setPhase(\"streaming\");\n startPolling(result.conversation.token, assistantMessage.id);\n },\n [client, locale, pageUrl, productSlug, startPolling],\n );\n\n const send = useCallback(\n async (message: string): Promise<void> => {\n const text = message.trim();\n if (!text) return;\n if (inFlightRef.current) return;\n\n const activeCatalog = catalogRef.current;\n if (!activeCatalog.enabled) {\n setError(classifyExploreError(\"EXPLORE_DISABLED\"));\n setPhase(\"disabled\");\n return;\n }\n if (text.length > activeCatalog.limits.maxMessageLength) {\n setError({\n kind: \"validation\",\n code: \"MESSAGE_TOO_LONG\",\n message: `That message is ${text.length} characters — the limit is ${activeCatalog.limits.maxMessageLength}.`,\n retryable: false,\n });\n return;\n }\n if (\n turnCountRef.current >= activeCatalog.limits.maxTurnsPerConversation\n ) {\n setError({\n kind: \"validation\",\n code: \"CONVERSATION_LIMIT\",\n message: `This conversation has reached its ${activeCatalog.limits.maxTurnsPerConversation}-message limit. Start a new chat to keep going.`,\n retryable: false,\n });\n return;\n }\n\n inFlightRef.current = true;\n lastSentTextRef.current = text;\n setError(null);\n setPhase(\"sending\");\n cancelPolling();\n\n // Optimistic user bubble — the composer clears instantly instead of\n // waiting a network round-trip for the visitor's own words.\n const optimistic: ExploreMessage = {\n id: makeOptimisticId(),\n conversationId: conversationTokenRef.current ?? \"pending\",\n role: \"USER\",\n status: \"COMPLETED\",\n content: text,\n partialContent: null,\n activity: [],\n references: [],\n ctas: [],\n errorCode: null,\n createdAt: new Date().toISOString(),\n completedAt: new Date().toISOString(),\n };\n setMessages((prev) => [...prev, optimistic]);\n turnCountRef.current += 1;\n setTurnCount(turnCountRef.current);\n onSend?.(text);\n\n try {\n await submit(text, optimistic.id, 0);\n } catch (err) {\n if (!mountedRef.current) return;\n console.error(\"[WebSDK] Explore send failed\", err);\n inFlightRef.current = false;\n setError(classifyExploreError(\"NETWORK_ERROR\"));\n setPhase(\"error\");\n }\n },\n [cancelPolling, onSend, submit],\n );\n\n const stop = useCallback(() => {\n cancelPolling();\n inFlightRef.current = false;\n setMessages((prev) =>\n prev.flatMap<ExploreMessage>((m) => {\n if (m.role !== \"ASSISTANT\") return [m];\n if (m.status !== \"PENDING\" && m.status !== \"RUNNING\") return [m];\n const text = visibleText(m);\n // Nothing streamed yet — drop the placeholder instead of leaving an\n // empty bubble behind.\n if (!text) return [];\n return [\n {\n ...m,\n status: \"COMPLETED\",\n content: text,\n completedAt: new Date().toISOString(),\n },\n ];\n }),\n );\n setPhase((prev) =>\n prev === \"sending\" || prev === \"streaming\" ? \"ready\" : prev,\n );\n }, [cancelPolling]);\n\n const retry = useCallback(() => {\n const text = lastSentTextRef.current;\n if (!text) return;\n cancelPolling();\n inFlightRef.current = false;\n // Drop the failed turn (and the user bubble that produced it) so the retry\n // does not stack a duplicate pair into the transcript.\n setMessages((prev) => {\n const next = [...prev];\n const last = next[next.length - 1];\n if (last?.role === \"ASSISTANT\" && last.status === \"FAILED\") next.pop();\n const prior = next[next.length - 1];\n if (prior?.role === \"USER\" && prior.content === text) next.pop();\n return next;\n });\n turnCountRef.current = Math.max(0, turnCountRef.current - 1);\n setTurnCount(turnCountRef.current);\n void send(text);\n }, [cancelPolling, send]);\n\n const reset = useCallback(() => {\n cancelPolling();\n inFlightRef.current = false;\n conversationTokenRef.current = null;\n lastSentTextRef.current = null;\n turnCountRef.current = 0;\n setTurnCount(0);\n setMessages([]);\n setError(null);\n setRemainingToday(null);\n setPhase(catalogRef.current.enabled ? \"ready\" : \"disabled\");\n if (typeof window !== \"undefined\") {\n try {\n window.sessionStorage.removeItem(storageKey);\n } catch {\n /* storage unavailable — nothing to clear */\n }\n }\n }, [cancelPolling, storageKey]);\n\n const setFocusProduct = useCallback((slug: string | null) => {\n focusProductRef.current = slug;\n setFocusProductState(slug);\n }, []);\n\n const activity = useMemo<string | null>(() => {\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const m = messages[i];\n if (!m || m.role !== \"ASSISTANT\") continue;\n if (m.status !== \"PENDING\" && m.status !== \"RUNNING\") return null;\n const lines = m.activity ?? [];\n return lines.length ? (lines[lines.length - 1] ?? null) : null;\n }\n return null;\n }, [messages]);\n\n const canSend =\n (phase === \"ready\" || phase === \"error\") &&\n catalog.enabled &&\n turnCount < catalog.limits.maxTurnsPerConversation;\n\n return {\n phase,\n catalog,\n messages,\n activity,\n remainingToday,\n error,\n focusProduct,\n setFocusProduct,\n send,\n stop,\n retry,\n reset,\n canSend,\n };\n}\n\n/**\n * Client-only id for the optimistic user bubble, swapped for the server's\n * `userMessage.id` as soon as the mutation resolves. The counter only has to\n * make ids unique within a tab, never across one.\n */\nlet optimisticCounter = 0;\n\nfunction makeOptimisticId(): string {\n optimisticCounter += 1;\n return `boff-explore-local-${Date.now()}-${optimisticCounter}`;\n}\n"]}
1
+ {"version":3,"sources":["../../src/client/security.ts","../../src/client/graphql-client.ts","../../src/client/provider.tsx","../../src/components/explore-types.ts","../../src/data/products.ts","../../src/utils/recaptcha-v3.ts","../../src/hooks/use-explore-chat.ts"],"names":["createContext","useContext","useMemo","useState","useRef","useCallback","useEffect"],"mappings":";;;;;;;;;;AAAA,IAAM,iCAAiB,IAAI,GAAA,CAAI,CAAC,WAAA,EAAa,WAAA,EAAa,KAAK,CAAC,CAAA;AAChE,IAAM,gBAAA,uBAAuB,GAAA,CAAI;AAAA,EAC/B,eAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,sBAAA;AAAA,EACA,iBAAA;AAAA,EACA,sBAAA;AAAA,EACA;AACF,CAAC,CAAA;AAEM,SAAS,mBAAmB,KAAA,EAAuB;AACxD,EAAA,IAAI,GAAA;AAEJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,IAAI,IAAI,KAAK,CAAA;AAAA,EACrB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,EAC5D;AAEA,EAAA,IAAI,GAAA,CAAI,aAAa,QAAA,EAAU;AAC7B,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB;AAEA,EAAA,IACE,GAAA,CAAI,aAAa,OAAA,IACjB,cAAA,CAAe,IAAI,GAAA,CAAI,QAAA,CAAS,WAAA,EAAa,CAAA,EAC7C;AACA,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB;AAEA,EAAA,MAAM,IAAI,MAAM,wDAAwD,CAAA;AAC1E;AAEO,SAAS,gBACd,OAAA,EACoC;AACpC,EAAA,IAAI,CAAC,SAAS,OAAO,MAAA;AAErB,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CAAE,MAAA;AAAA,MACtB,CAAC,CAAC,GAAG,CAAA,KAAM,CAAC,gBAAA,CAAiB,GAAA,CAAI,GAAA,CAAI,WAAA,EAAa;AAAA;AACpD,GACF;AACF;AAQA,IAAM,qBAAA,uBAA4B,GAAA,CAAI;AAAA,EACpC,4BAAA;AAAA,EACA;AACF,CAAC,CAAA;AAQM,SAAS,eAAA,CACd,YACA,QAAA,EACwB;AACxB,EAAA,MAAM,QAAA,GAAW,QAAA,EAAU,QAAA,EAAU,IAAA,EAAK;AAC1C,EAAA,MAAM,YAAA,GAAe,QAAA,EAAU,YAAA,EAAc,IAAA,EAAK;AAClD,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,YAAA,SAAqB,EAAC;AAExC,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI;AACF,IAAA,IAAA,GAAO,IAAI,GAAA,CAAI,UAAU,CAAA,CAAE,SAAS,WAAA,EAAY;AAAA,EAClD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,IAAI,CAAC,qBAAA,CAAsB,GAAA,CAAI,IAAI,CAAA,SAAU,EAAC;AAE9C,EAAA,OAAO;AAAA,IACL,qBAAA,EAAuB,QAAA;AAAA,IACvB,yBAAA,EAA2B;AAAA,GAC7B;AACF;;;ACMO,IAAM,aAAA,GAAN,MAAM,aAAA,CAAa;AAAA,EAaxB,YAAY,MAAA,EAA4B;AAZxC,IAAA,aAAA,CAAA,IAAA,EAAQ,QAAA,CAAA;AACR,IAAA,aAAA,CAAA,IAAA,EAAQ,YAAA,sBAAiB,GAAA,EAGvB,CAAA;AACF,IAAA,aAAA,CAAA,IAAA,EAAQ,UAAA,sBAAe,GAAA,EAA+C,CAAA;AAQpE,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,GAAG,MAAA;AAAA,MACH,UAAA,EAAY,kBAAA,CAAmB,MAAA,CAAO,UAAU,CAAA;AAAA,MAChD,OAAA,EAAS,eAAA,CAAgB,MAAA,CAAO,OAAO;AAAA,KACzC;AAAA,EACF;AAAA,EAEA,SAAA,GAAgC;AAC9B,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAA,CACJ,KAAA,EACA,SAAA,EACA,OAAA,EAC6B;AAK7B,IAAA,IAAI,OAAA,EAAS,UAAU,KAAA,EAAO;AAC5B,MAAA,OAAO,KAAK,OAAA,CAAW,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,QAAQ,SAAS,CAAA;AAAA,IAClE;AAEA,IAAA,MAAM,WAAW,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,WAAW,CAAA;AAGpD,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AAC3C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAI,KAAK,GAAA,EAAI,GAAI,MAAA,CAAO,EAAA,GAAK,cAAa,SAAA,EAAW;AACnD,QAAA,OAAO,MAAA,CAAO,IAAA;AAAA,MAChB;AACA,MAAA,IAAA,CAAK,UAAA,CAAW,OAAO,QAAQ,CAAA;AAAA,IACjC;AAGA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,QAAQ,CAAA;AAC3C,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAO,QAAA;AAAA,IACT;AAEA,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,CAAW,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,OAAA,EAAS,SAAS,CAAA,CACvE,IAAA,CAAK,CAAC,MAAA,KAAW;AAEhB,MAAA,IAAI,MAAA,CAAO,IAAA,IAAQ,CAAC,MAAA,CAAO,QAAQ,MAAA,EAAQ;AACzC,QAAA,IAAI,IAAA,CAAK,UAAA,CAAW,IAAA,IAAQ,aAAA,CAAa,iBAAA,EAAmB;AAC1D,UAAA,MAAM,cAAc,IAAA,CAAK,UAAA,CAAW,IAAA,EAAK,CAAE,MAAK,CAAE,KAAA;AAClD,UAAA,IAAI,WAAA,EAAa;AACf,YAAA,IAAA,CAAK,UAAA,CAAW,OAAO,WAAW,CAAA;AAAA,UACpC;AAAA,QACF;AACA,QAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,QAAA,EAAU,EAAE,IAAA,EAAM,QAAQ,EAAA,EAAI,IAAA,CAAK,GAAA,EAAI,EAAG,CAAA;AAAA,MAChE;AACA,MAAA,OAAO,MAAA;AAAA,IACT,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACb,MAAA,IAAA,CAAK,QAAA,CAAS,OAAO,QAAQ,CAAA;AAAA,IAC/B,CAAC,CAAA;AAEH,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,QAAA,EAAU,OAAO,CAAA;AACnC,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,CACJ,QAAA,EACA,SAAA,EACA,OAAA,EAC6B;AAG7B,IAAA,OAAO,KAAK,OAAA,CAAW,QAAA,EAAU,SAAA,EAAW,KAAA,EAAO,SAAS,SAAS,CAAA;AAAA,EACvE;AAAA;AAAA,EAGA,OAAe,kBAAkB,MAAA,EAAyB;AACxD,IAAA,OAAO,WAAW,GAAA,IAAO,MAAA,KAAW,GAAA,IAAQ,MAAA,IAAU,OAAO,MAAA,GAAS,GAAA;AAAA,EACxE;AAAA,EAEA,OAAe,MAAM,EAAA,EAA2B;AAC9C,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,OAAA,CACZ,KAAA,EACA,SAAA,EACA,SAAA,EAC0D;AAC1D,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,SAAS,CAAA;AAC5D,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,IAAA,CAAK,OAAO,UAAA,EAAY;AAAA,QACnD,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,kBAAA;AAAA,UAChB,cAAA,EAAgB,KAAK,MAAA,CAAO,SAAA;AAAA,UAC5B,GAAG,KAAK,MAAA,CAAO,OAAA;AAAA,UACf,GAAG,eAAA,CAAgB,IAAA,CAAK,OAAO,UAAA,EAAY,IAAA,CAAK,OAAO,QAAQ;AAAA,SACjE;AAAA,QACA,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,WAAW,CAAA;AAAA,QACzC,QAAQ,UAAA,CAAW;AAAA,OACpB,CAAA;AAED,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,OAAA,CAAQ,KAAA;AAAA,UACN,iCAAA;AAAA,UACA,QAAA,CAAS,MAAA;AAAA,UACT,QAAA,CAAS;AAAA,SACX;AACA,QAAA,OAAO;AAAA,UACL,GAAA,EAAK;AAAA,YACH,MAAA,EAAQ;AAAA,cACN;AAAA,gBACE,SAAS,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA,CAAA;AAAA,gBACxD,YAAY,EAAE,IAAA,EAAM,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAA;AAAG;AAChD;AACF,WACF;AAAA,UACA,SAAA,EAAW,aAAA,CAAa,iBAAA,CAAkB,QAAA,CAAS,MAAM;AAAA,SAC3D;AAAA,MACF;AAEA,MAAA,OAAO;AAAA,QACL,GAAA,EAAM,MAAM,QAAA,CAAS,IAAA,EAAK;AAAA,QAC1B,SAAA,EAAW;AAAA,OACb;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,UACJ,KAAA,YAAiB,KAAA,KAChB,MAAM,IAAA,KAAS,YAAA,IAAgB,WAAW,MAAA,CAAO,OAAA,CAAA;AACpD,MAAA,MAAM,OAAA,GAAU,UACZ,CAAA,wBAAA,EAA2B,SAAS,OACpC,KAAA,YAAiB,KAAA,GACf,MAAM,OAAA,GACN,eAAA;AACN,MAAA,OAAA,CAAQ,KAAA,CAAM,0BAA0B,OAAO,CAAA;AAC/C,MAAA,OAAO;AAAA,QACL,GAAA,EAAK;AAAA,UACH,MAAA,EAAQ;AAAA,YACN;AAAA,cACE,OAAA;AAAA,cACA,UAAA,EAAY,EAAE,IAAA,EAAM,OAAA,GAAU,YAAY,eAAA;AAAgB;AAC5D;AACF,SACF;AAAA;AAAA;AAAA,QAGA,SAAA,EAAW;AAAA,OACb;AAAA,IACF,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAc,OAAA,CACZ,KAAA,EACA,SAAA,EACA,KAAA,GAAQ,MACR,iBAAA,EAC6B;AAC7B,IAAA,MAAM,SAAA,GACJ,iBAAA,IACA,IAAA,CAAK,MAAA,CAAO,aACZ,aAAA,CAAa,kBAAA;AACf,IAAA,MAAM,aAAa,KAAA,GACd,IAAA,CAAK,MAAA,CAAO,UAAA,IAAc,cAAa,mBAAA,GACxC,CAAA;AAEJ,IAAA,IAAI,IAAA;AACJ,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,IAAK,UAAA,EAAY,CAAA,EAAA,EAAK;AACpC,MAAA,MAAM,EAAE,GAAA,EAAK,SAAA,EAAU,GAAI,MAAM,IAAA,CAAK,OAAA;AAAA,QACpC,KAAA;AAAA,QACA,SAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,IAAI,CAAC,SAAA,IAAa,CAAA,KAAM,UAAA,EAAY,OAAO,GAAA;AAC3C,MAAA,IAAA,GAAO,GAAA;AAEP,MAAA,MAAM,aAAA,CAAa,KAAA;AAAA,QACjB,cAAa,mBAAA,IAAuB,CAAA,GAAI,CAAA,CAAA,GAAK,IAAA,CAAK,QAAO,GAAI;AAAA,OAC/D;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF,CAAA;AA5ME,aAAA,CAPW,aAAA,EAOI,WAAA,EAAY,CAAA,GAAI,EAAA,GAAK,GAAA,CAAA;AAAA;AACpC,aAAA,CARW,eAQI,mBAAA,EAAoB,GAAA,CAAA;AACnC,aAAA,CATW,eASI,oBAAA,EAAqB,IAAA,CAAA;AACpC,aAAA,CAVW,eAUI,qBAAA,EAAsB,CAAA,CAAA;AACrC,aAAA,CAXW,eAWI,qBAAA,EAAsB,GAAA,CAAA;ACzFvC,IAAM,aAAA,GAAgBA,oBAAmC,IAAI,CAAA;AAyCtD,SAAS,SAAA,GAA0B;AACxC,EAAA,MAAM,MAAA,GAASC,iBAAW,aAAa,CAAA;AACvC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,EAClE;AACA,EAAA,OAAO,MAAA;AACT;;;ACwIA,IAAM,sBAAA;AAAA;AAAA,EAAuC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA2BtC,IAAM,qBAAA;AAAA;AAAA,EAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA8B5C,IAAM,qBAAA;AAAA;AAAA,EAAsC;AAAA;AAAA;AAAA,MAAA,EAG3C,sBAAsB;AAAA;AAAA;AAAA;AAAA,CAAA;AAMvB,IAAM,6BAAA;AAAA;AAAA,EAA8C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,EAWjD,sBAAsB;AAAA;AAAA;AAAA,QAAA,EAGtB,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;;;AC3QzB,IAAM,kBAAA,GAA+C;AAAA,EAC1D;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,cAAA;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA;AAAA,EAEA,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,QAAA,EAAU,YAAY,uBAAA,EAAwB;AAAA,EACtE;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,IAAA,EAAM,aAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,iBAAA;AAAA,IACN,IAAA,EAAM,iBAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,WAAA,EAAa,YAAY,uBAAA,EAAwB;AAAA,EAC5E;AAAA,IACE,IAAA,EAAM,cAAA;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,IAAA,EAAM,aAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,mBAAA;AAAA,IACN,IAAA,EAAM,mBAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,mBAAA;AAAA,IACN,IAAA,EAAM,mBAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,WAAA,EAAa,YAAY,uBAAA,EAAwB;AAAA,EAC5E;AAAA,IACE,IAAA,EAAM,eAAA;AAAA,IACN,IAAA,EAAM,eAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,SAAA,EAAW,YAAY,qBAAA,EAAsB;AAAA,EACtE;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,iBAAA;AAAA,IACN,IAAA,EAAM,iBAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,eAAA;AAAA,IACN,IAAA,EAAM,eAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,cAAA;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,iBAAA;AAAA,IACN,IAAA,EAAM,iBAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,cAAA;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,cAAA;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,gBAAA;AAAA,IACN,IAAA,EAAM,gBAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,WAAA,EAAa,YAAY,uBAAA,EAAwB;AAAA,EAC5E;AAAA,IACE,IAAA,EAAM,eAAA;AAAA,IACN,IAAA,EAAM,eAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,oBAAA;AAAA,IACN,IAAA,EAAM,oBAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,eAAA;AAAA,IACN,IAAA,EAAM,eAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,cAAA;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,eAAA;AAAA,IACN,IAAA,EAAM,gBAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,eAAA;AAAA,IACN,IAAA,EAAM,eAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,gBAAA;AAAA,IACN,IAAA,EAAM,eAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,eAAA;AAAA,IACN,IAAA,EAAM,eAAA;AAAA,IACN,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,IAAA,EAAM,cAAA;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,UAAA,EAAY;AAAA;AAEhB,CAAA;;;ACzJA,IAAM,SAAA,GAAY,mBAAA;AAClB,IAAM,UAAA,GAAa,iDAAA;AAGZ,IAAM,wBAAA,GAA2B,cAAA;AAOxC,IAAM,OAAA,uBAAc,GAAA,EAAkC;AAEtD,SAAS,SAAA,GAAqB;AAC5B,EAAA,OAAO,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,QAAA,KAAa,WAAA;AAC9D;AAaO,SAAS,gBAAgB,OAAA,EAAuC;AACrE,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,IAAI,KAAA,CAAM,gCAAgC,CAAC,CAAA;AAAA,EACnE;AACA,EAAA,IAAI,CAAC,WAAU,EAAG;AAChB,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,MACb,IAAI,MAAM,8CAA8C;AAAA,KAC1D;AAAA,EACF;AAEA,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,OAAO,CAAA;AACpC,EAAA,IAAI,UAAU,OAAO,QAAA;AAErB,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAqB,CAAC,SAAS,MAAA,KAAW;AAC5D,IAAA,MAAM,QAAQ,MAAM;AAClB,MAAA,MAAM,MAAM,MAAA,CAAO,UAAA;AACnB,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,MAAA,CAAO,IAAI,KAAA,CAAM,gDAAgD,CAAC,CAAA;AAClE,QAAA;AAAA,MACF;AAGA,MAAA,GAAA,CAAI,KAAA,CAAM,MAAM,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,IAC9B,CAAA;AAGA,IAAA,IAAI,OAAO,UAAA,EAAY;AACrB,MAAA,KAAA,EAAM;AACN,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AACxC,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,cAAA,CAAe,QAAQ,CAAA;AAC9C,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,KAAA,CAAM,iBAAiB,MAAA,EAAQ,KAAA,EAAO,EAAE,IAAA,EAAM,MAAM,CAAA;AACpD,MAAA,KAAA,CAAM,gBAAA;AAAA,QACJ,OAAA;AAAA,QACA,MAAM,MAAA,CAAO,IAAI,KAAA,CAAM,6BAA6B,CAAC,CAAA;AAAA,QACrD,EAAE,MAAM,IAAA;AAAK,OACf;AACA,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,MAAA,CAAO,EAAA,GAAK,QAAA;AACZ,IAAA,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,CAAA,EAAG,kBAAA,CAAmB,OAAO,CAAC,CAAA,CAAA;AACxD,IAAA,MAAA,CAAO,KAAA,GAAQ,IAAA;AACf,IAAA,MAAA,CAAO,KAAA,GAAQ,IAAA;AACf,IAAA,MAAA,CAAO,iBAAiB,MAAA,EAAQ,KAAA,EAAO,EAAE,IAAA,EAAM,MAAM,CAAA;AACrD,IAAA,MAAA,CAAO,gBAAA;AAAA,MACL,OAAA;AAAA,MACA,MAAM;AAGJ,QAAA,OAAA,CAAQ,OAAO,OAAO,CAAA;AACtB,QAAA,MAAA,CAAO,IAAI,KAAA,CAAM,6BAA6B,CAAC,CAAA;AAAA,MACjD,CAAA;AAAA,MACA,EAAE,MAAM,IAAA;AAAK,KACf;AACA,IAAA,QAAA,CAAS,IAAA,CAAK,YAAY,MAAM,CAAA;AAAA,EAClC,CAAC,CAAA;AAED,EAAA,OAAA,CAAQ,GAAA,CAAI,SAAS,OAAO,CAAA;AAC5B,EAAA,OAAO,OAAA;AACT;AAQA,eAAsB,mBAAA,CACpB,OAAA,EACA,MAAA,GAAiB,wBAAA,EACA;AACjB,EAAA,MAAM,GAAA,GAAM,MAAM,eAAA,CAAgB,OAAO,CAAA;AACzC,EAAA,OAAO,GAAA,CAAI,OAAA,CAAQ,OAAA,EAAS,EAAE,QAAQ,CAAA;AACxC;;;ACcA,IAAM,mBAAA,GAAsB,iBAAA;AAC5B,IAAM,wBAAA,GAA2B,IAAA;AAEjC,IAAM,uBAAA,GAA0B,GAAA;AAEhC,IAAM,uBAAA,GAA0B,GAAA;AAEhC,IAAM,uBAAA,GAA0B,IAAA;AAEhC,IAAM,6BAAA,GAAgC,CAAA;AAEtC,IAAM,sBAAA,GAAyB,EAAA;AAGxB,IAAM,uBAAA,GAAyC;AAAA,EACpD,gBAAA,EAAkB,GAAA;AAAA,EAClB,uBAAA,EAAyB,EAAA;AAAA,EACzB,cAAA,EAAgB,GAAA;AAAA,EAChB,YAAA,EAAc;AAChB;AAMO,IAAM,+BAAA,GAA4C;AAAA,EACvD,qCAAA;AAAA,EACA,uCAAA;AAAA,EACA,qCAAA;AAAA,EACA;AACF;AAEA,IAAM,sBAAA,GAAyB,iCAAA;AAC/B,IAAM,qBAAA,GACJ,4IAAA;AAMF,SAAS,qBAAqB,cAAA,EAA2C;AACvE,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,IAAA;AAAA,IACT,QAAA,EAAU,kBAAA,CAAmB,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACvC,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,OAAA,EAAS,IAAA;AAAA,MACT,SAAS,CAAA,CAAE;AAAA,KACb,CAAE,CAAA;AAAA,IACF,cAAA,EAAgB,cAAA,EAAgB,MAAA,GAC5B,cAAA,GACA,+BAAA;AAAA,IACJ,YAAA,EAAc,sBAAA;AAAA,IACd,WAAA,EAAa,qBAAA;AAAA,IACb,MAAA,EAAQ,uBAAA;AAAA,IACR,eAAA,EAAiB,KAAA;AAAA,IACjB,gBAAA,EAAkB;AAAA,GACpB;AACF;AAOA,SAAS,gBAAA,CACP,KACA,QAAA,EACgB;AAChB,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,IAAI,OAAA,KAAY,KAAA;AAAA,IACzB,UAAU,GAAA,CAAI,QAAA,EAAU,MAAA,GAAS,GAAA,CAAI,WAAW,QAAA,CAAS,QAAA;AAAA,IACzD,gBAAgB,GAAA,CAAI,cAAA,EAAgB,MAAA,GAChC,GAAA,CAAI,iBACJ,QAAA,CAAS,cAAA;AAAA,IACb,YAAA,EAAc,GAAA,CAAI,YAAA,IAAgB,QAAA,CAAS,YAAA;AAAA,IAC3C,WAAA,EAAa,GAAA,CAAI,WAAA,IAAe,QAAA,CAAS,WAAA;AAAA,IACzC,MAAA,EAAQ;AAAA,MACN,gBAAA,EACE,GAAA,CAAI,MAAA,EAAQ,gBAAA,IAAoB,SAAS,MAAA,CAAO,gBAAA;AAAA,MAClD,uBAAA,EACE,GAAA,CAAI,MAAA,EAAQ,uBAAA,IACZ,SAAS,MAAA,CAAO,uBAAA;AAAA,MAClB,cAAA,EACE,GAAA,CAAI,MAAA,EAAQ,cAAA,IAAkB,SAAS,MAAA,CAAO,cAAA;AAAA,MAChD,YAAA,EAAc,GAAA,CAAI,MAAA,EAAQ,YAAA,IAAgB,SAAS,MAAA,CAAO;AAAA,KAC5D;AAAA,IACA,eAAA,EAAiB,IAAI,eAAA,KAAoB,IAAA;AAAA,IACzC,gBAAA,EAAkB,IAAI,gBAAA,IAAoB;AAAA,GAC5C;AACF;AAEA,IAAM,gBAAA,uBAAuB,GAAA,CAAI;AAAA,EAC/B,cAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAC,CAAA;AACD,IAAM,gCAAgB,IAAI,GAAA,CAAI,CAAC,gBAAA,EAAkB,kBAAkB,CAAC,CAAA;AACpE,IAAM,aAAA,uBAAoB,GAAA,CAAI;AAAA,EAC5B,eAAA;AAAA,EACA,sBAAA;AAAA,EACA,mBAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF,CAAC,CAAA;AACD,IAAM,gBAAA,uBAAuB,GAAA,CAAI;AAAA,EAC/B,kBAAA;AAAA,EACA,eAAA;AAAA,EACA,oBAAA;AAAA,EACA;AACF,CAAC,CAAA;AAOM,SAAS,oBAAA,CACd,MACA,aAAA,EACkB;AAClB,EAAA,MAAM,IAAI,IAAA,IAAQ,SAAA;AAClB,EAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,CAAC,CAAA,EAAG;AAC3B,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,YAAA;AAAA,MACN,IAAA,EAAM,CAAA;AAAA,MACN,OAAA,EACE,mEAAA;AAAA,MACF,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AACA,EAAA,IAAI,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,EAAG;AACxB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,SAAA;AAAA,MACN,IAAA,EAAM,CAAA;AAAA,MACN,OAAA,EACE,sEAAA;AAAA,MACF,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AACA,EAAA,IAAI,CAAA,KAAM,SAAA,IAAa,CAAA,KAAM,aAAA,EAAe;AAC1C,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,SAAA;AAAA,MACN,IAAA,EAAM,CAAA;AAAA,MACN,OAAA,EAAS,2DAAA;AAAA,MACT,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AACA,EAAA,IAAI,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,EAAG;AACxB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,SAAA;AAAA,MACN,IAAA,EAAM,CAAA;AAAA,MACN,OAAA,EACE,gFAAA;AAAA,MACF,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AACA,EAAA,IAAI,MAAM,kBAAA,EAAoB;AAC5B,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,UAAA;AAAA,MACN,IAAA,EAAM,CAAA;AAAA,MACN,OAAA,EAAS,+DAAA;AAAA,MACT,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AACA,EAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,CAAC,CAAA,EAAG;AAC3B,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,YAAA;AAAA,MACN,IAAA,EAAM,CAAA;AAAA,MACN,SAAS,aAAA,IAAiB,gCAAA;AAAA,MAC1B,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AACA,EAAA,IAAI,MAAM,cAAA,EAAgB;AACxB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,SAAA;AAAA,MACN,IAAA,EAAM,CAAA;AAAA,MACN,OAAA,EACE,mFAAA;AAAA,MACF,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,IAAA,EAAM,CAAA;AAAA,IACN,SAAS,aAAA,IAAiB,yCAAA;AAAA,IAC1B,SAAA,EAAW;AAAA,GACb;AACF;AAQA,SAAS,cAAc,GAAA,EAA2C;AAGhE,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,IAAA;AAC1C,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,cAAA,CAAe,OAAA,CAAQ,GAAG,CAAA;AAC7C,IAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AACjB,IAAA,MAAM,MAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AACtC,IAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,UAAU,OAAO,IAAA;AAClD,IAAA,MAAM,MAAA,GAAS,MAAA;AACf,IAAA,OAAO;AAAA,MACL,mBACE,OAAO,MAAA,CAAO,iBAAA,KAAsB,QAAA,GAChC,OAAO,iBAAA,GACP,IAAA;AAAA,MACN,QAAA,EAAU,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA,GACnC,MAAA,CAAO,QAAA,CAAS,KAAA,CAAM,CAAC,sBAAsB,CAAA,GAC7C,EAAC;AAAA,MACL,cACE,OAAO,MAAA,CAAO,YAAA,KAAiB,QAAA,GAAW,OAAO,YAAA,GAAe;AAAA,KACpE;AAAA,EACF,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAMA,SAAS,YAAY,OAAA,EAAiC;AACpD,EAAA,OAAO,OAAA,CAAQ,OAAA,IAAW,OAAA,CAAQ,cAAA,IAAkB,EAAA;AACtD;AAEA,SAAS,eAAe,QAAA,EAAoC;AAC1D,EAAA,OAAO,SAAS,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,MAAM,CAAA,CAAE,MAAA;AACnD;AAMO,SAAS,cAAA,CACd,OAAA,GAAiC,EAAC,EACZ;AACtB,EAAA,MAAM;AAAA,IACJ,WAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA,GAAiB,wBAAA;AAAA,IACjB,aAAA,GAAgB,uBAAA;AAAA,IAChB,UAAA,GAAa,mBAAA;AAAA,IACb,OAAA,GAAU,IAAA;AAAA,IACV;AAAA,GACF,GAAI,OAAA;AAEJ,EAAA,MAAM,SAAS,SAAA,EAAU;AAMzB,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,SAAA,CAAU,cAAA,IAAkB,EAAE,CAAA;AACrD,EAAA,MAAM,eAAA,GAAkBC,aAAAA;AAAA,IACtB,MAAM,oBAAA,CAAqB,IAAA,CAAK,KAAA,CAAM,SAAS,CAAa,CAAA;AAAA,IAC5D,CAAC,SAAS;AAAA,GACZ;AAEA,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIC,eAAyB,eAAe,CAAA;AACtE,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,cAAA,CAA2B,EAAE,CAAA;AAC7D,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAA2B,SAAS,CAAA;AAC9D,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAkC,IAAI,CAAA;AAChE,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIA,eAAwB,IAAI,CAAA;AACxE,EAAA,MAAM,CAAC,YAAA,EAAc,oBAAoB,CAAA,GAAIA,eAAwB,IAAI,CAAA;AACzE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,eAAS,CAAC,CAAA;AAC5C,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,eAAS,KAAK,CAAA;AAI9C,EAAA,MAAM,UAAA,GAAaC,aAAO,IAAI,CAAA;AAC9B,EAAA,MAAM,iBAAA,GAAoBA,aAAO,CAAC,CAAA;AAClC,EAAA,MAAM,YAAA,GAAeA,aAA6C,IAAI,CAAA;AACtE,EAAA,MAAM,oBAAA,GAAuBA,aAAsB,IAAI,CAAA;AACvD,EAAA,MAAM,UAAA,GAAaA,aAAuB,eAAe,CAAA;AACzD,EAAA,MAAM,YAAA,GAAeA,aAAO,CAAC,CAAA;AAC7B,EAAA,MAAM,eAAA,GAAkBA,aAAsB,IAAI,CAAA;AAClD,EAAA,MAAM,eAAA,GAAkBA,aAAsB,IAAI,CAAA;AAClD,EAAA,MAAM,WAAA,GAAcA,aAAO,KAAK,CAAA;AAEhC,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AAErB,EAAA,MAAM,cAAA,GAAiBC,kBAAY,MAAM;AACvC,IAAA,IAAI,YAAA,CAAa,YAAY,IAAA,EAAM;AACjC,MAAA,YAAA,CAAa,aAAa,OAAO,CAAA;AACjC,MAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AAAA,IACzB;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,aAAA,GAAgBA,kBAAY,MAAM;AACtC,IAAA,iBAAA,CAAkB,OAAA,IAAW,CAAA;AAC7B,IAAA,cAAA,EAAe;AAAA,EACjB,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,IAAA,OAAO,MAAM;AACX,MAAA,UAAA,CAAW,OAAA,GAAU,KAAA;AACrB,MAAA,iBAAA,CAAkB,OAAA,IAAW,CAAA;AAC7B,MAAA,IAAI,YAAA,CAAa,YAAY,IAAA,EAAM;AACjC,QAAA,YAAA,CAAa,aAAa,OAAO,CAAA;AACjC,QAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AAAA,MACzB;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAML,EAAAA,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,WAAA,CAAY,IAAI,CAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAAS,cAAc,UAAU,CAAA;AACvC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,oBAAA,CAAqB,UAAU,MAAA,CAAO,iBAAA;AACtC,MAAA,eAAA,CAAgB,UAAU,MAAA,CAAO,YAAA;AAGjC,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,QAAA,CAAS,OAAA,CAAwB,CAAC,CAAA,KAAM;AAC7D,QAAA,IAAI,CAAA,CAAE,IAAA,KAAS,WAAA,EAAa,OAAO,CAAC,CAAC,CAAA;AACrC,QAAA,IAAI,CAAA,CAAE,WAAW,SAAA,IAAa,CAAA,CAAE,WAAW,SAAA,EAAW,OAAO,CAAC,CAAC,CAAA;AAC/D,QAAA,MAAM,IAAA,GAAO,YAAY,CAAC,CAAA;AAC1B,QAAA,IAAI,CAAC,IAAA,EAAM,OAAO,EAAC;AACnB,QAAA,OAAO,CAAC,EAAE,GAAG,CAAA,EAAG,QAAQ,WAAA,EAAa,OAAA,EAAS,MAAM,CAAA;AAAA,MACtD,CAAC,CAAA;AACD,MAAA,WAAA,CAAY,OAAO,CAAA;AACnB,MAAA,oBAAA,CAAqB,OAAO,YAAY,CAAA;AACxC,MAAA,MAAM,KAAA,GAAQ,eAAe,OAAO,CAAA;AACpC,MAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AACvB,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AACA,IAAA,WAAA,CAAY,IAAI,CAAA;AAAA,EAClB,CAAA,EAAG,CAAC,OAAA,EAAS,UAAU,CAAC,CAAA;AAKxB,EAAAA,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,QAAA,IAAY,OAAO,WAAW,WAAA,EAAa;AAC5D,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAiC;AAAA,QACrC,mBAAmB,oBAAA,CAAqB,OAAA;AAAA,QACxC,QAAA,EAAU,QAAA,CAAS,KAAA,CAAM,CAAC,sBAAsB,CAAA;AAAA,QAChD;AAAA,OACF;AAGA,MAAA,IACE,CAAC,QAAQ,iBAAA,IACT,OAAA,CAAQ,SAAS,MAAA,KAAW,CAAA,IAC5B,CAAC,OAAA,CAAQ,YAAA,EACT;AACA,QAAA,MAAA,CAAO,cAAA,CAAe,WAAW,UAAU,CAAA;AAC3C,QAAA;AAAA,MACF;AACA,MAAA,MAAA,CAAO,eAAe,OAAA,CAAQ,UAAA,EAAY,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,IACnE,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,OAAA,EAAS,UAAU,UAAA,EAAY,QAAA,EAAU,YAAY,CAAC,CAAA;AAM1D,EAAAA,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,MAAM,OAAO,YAAY;AACvB,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,KAAA;AAAA,QACvB,qBAAA;AAAA,QACA,EAAE,WAAA,EAAa,WAAA,IAAe,IAAA;AAAK,OACrC;AACA,MAAA,IAAI,SAAA,IAAa,CAAC,UAAA,CAAW,OAAA,EAAS;AAEtC,MAAA,MAAM,GAAA,GAAM,IAAI,IAAA,EAAM,cAAA;AACtB,MAAA,IAAI,GAAA,CAAI,MAAA,EAAQ,MAAA,IAAU,CAAC,GAAA,EAAK;AAC9B,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,gFAAA;AAAA,UACA,GAAA,CAAI,MAAA,GAAS,CAAC,CAAA,EAAG;AAAA,SACnB;AACA,QAAA,QAAA,CAAS,CAAC,IAAA,KAAU,IAAA,KAAS,SAAA,GAAY,UAAU,IAAK,CAAA;AACxD,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,GAAA,EAAK,eAAe,CAAA;AAClD,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,MAAA,QAAA,CAAS,CAAC,IAAA,KAAS;AACjB,QAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,OAAO,UAAA;AAC1B,QAAA,OAAO,IAAA,KAAS,YAAY,OAAA,GAAU,IAAA;AAAA,MACxC,CAAC,CAAA;AAAA,IACH,CAAA;AACA,IAAA,KAAK,IAAA,EAAK;AACV,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,WAAA,EAAa,eAAe,CAAC,CAAA;AAKzC,EAAA,MAAM,YAAA,GAAeD,iBAAA;AAAA,IACnB,CAAC,mBAA2B,SAAA,KAAsB;AAChD,MAAA,iBAAA,CAAkB,OAAA,IAAW,CAAA;AAC7B,MAAA,MAAM,aAAa,iBAAA,CAAkB,OAAA;AACrC,MAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,MAAA,IAAI,mBAAA,GAAsB,CAAA;AAE1B,MAAA,MAAM,UAAU,MACd,CAAC,UAAA,CAAW,OAAA,IAAW,eAAe,iBAAA,CAAkB,OAAA;AAE1D,MAAA,MAAM,eAAA,GAAkB,CAAC,SAAA,KAAgC;AACvD,QAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,QAAA,WAAA;AAAA,UAAY,CAAC,IAAA,KACX,IAAA,CAAK,OAAA,CAAwB,CAAC,CAAA,KAAM;AAClC,YAAA,IAAI,CAAA,CAAE,EAAA,KAAO,SAAA,EAAW,OAAO,CAAC,CAAC,CAAA;AACjC,YAAA,MAAM,IAAA,GAAO,YAAY,CAAC,CAAA;AAC1B,YAAA,IAAI,CAAC,IAAA,EAAM,OAAO,EAAC;AACnB,YAAA,OAAO,CAAC,EAAE,GAAG,CAAA,EAAG,QAAQ,QAAA,EAAU,OAAA,EAAS,MAAM,CAAA;AAAA,UACnD,CAAC;AAAA,SACH;AACA,QAAA,QAAA,CAAS,SAAS,CAAA;AAClB,QAAA,QAAA,CAAS,SAAA,CAAU,IAAA,KAAS,YAAA,GAAe,SAAA,GAAY,OAAO,CAAA;AAAA,MAChE,CAAA;AAEA,MAAA,MAAM,OAAO,YAAY;AACvB,QAAA,IAAI,SAAQ,EAAG;AAEf,QAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA,GAAY,aAAA,EAAe;AAC1C,UAAA,eAAA,CAAgB,oBAAA,CAAqB,SAAS,CAAC,CAAA;AAC/C,UAAA;AAAA,QACF;AAGA,QAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,KAAA;AAAA,UACvB,qBAAA;AAAA,UACA,EAAE,iBAAA,EAAmB,EAAA,EAAI,SAAA,EAAU;AAAA,UACnC,EAAE,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,uBAAA;AAAwB,SACrD;AACA,QAAA,IAAI,SAAQ,EAAG;AAEf,QAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,MAAA,GAAS,CAAC,CAAA;AAC5B,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,MAAM,IAAA,GACJ,OAAO,KAAA,CAAM,UAAA,EAAY,SAAS,QAAA,GAC9B,KAAA,CAAM,WAAW,IAAA,GACjB,MAAA;AACN,UAAA,MAAM,UAAA,GAAa,oBAAA,CAAqB,IAAA,EAAM,KAAA,CAAM,OAAO,CAAA;AAE3D,UAAA,IAAI,CAAC,WAAW,SAAA,EAAW;AACzB,YAAA,eAAA,CAAgB,UAAU,CAAA;AAC1B,YAAA;AAAA,UACF;AACA,UAAA,mBAAA,IAAuB,CAAA;AACvB,UAAA,IAAI,uBAAuB,6BAAA,EAA+B;AACxD,YAAA,eAAA,CAAgB,UAAU,CAAA;AAC1B,YAAA;AAAA,UACF;AACA,UAAA,YAAA,CAAa,UAAU,UAAA,CAAW,MAAM,KAAK,IAAA,IAAQ,cAAc,CAAA;AACnE,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,OAAA,GAAU,IAAI,IAAA,EAAM,cAAA;AAC1B,QAAA,IAAI,CAAC,OAAA,EAAS;AAEZ,UAAA,mBAAA,IAAuB,CAAA;AACvB,UAAA,IAAI,uBAAuB,6BAAA,EAA+B;AACxD,YAAA,eAAA,CAAgB,oBAAA,CAAqB,WAAW,CAAC,CAAA;AACjD,YAAA;AAAA,UACF;AACA,UAAA,YAAA,CAAa,UAAU,UAAA,CAAW,MAAM,KAAK,IAAA,IAAQ,cAAc,CAAA;AACnE,UAAA;AAAA,QACF;AAEA,QAAA,mBAAA,GAAsB,CAAA;AAEtB,QAAA,WAAA;AAAA,UAAY,CAAC,IAAA,KACX,IAAA,CAAK,GAAA,CAAI,CAAC,MAAO,CAAA,CAAE,EAAA,KAAO,SAAA,GAAY,OAAA,GAAU,CAAE;AAAA,SACpD;AAEA,QAAA,IAAI,OAAA,CAAQ,WAAW,WAAA,EAAa;AAClC,UAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,UAAA,QAAA,CAAS,IAAI,CAAA;AACb,UAAA,QAAA,CAAS,OAAO,CAAA;AAChB,UAAA;AAAA,QACF;AACA,QAAA,IAAI,OAAA,CAAQ,WAAW,QAAA,EAAU;AAC/B,UAAA,eAAA;AAAA,YACE,oBAAA,CAAqB,OAAA,CAAQ,SAAA,IAAa,sBAAsB;AAAA,WAClE;AACA,UAAA;AAAA,QACF;AAEA,QAAA,QAAA,CAAS,WAAW,CAAA;AACpB,QAAA,YAAA,CAAa,UAAU,UAAA,CAAW,MAAM,KAAK,IAAA,IAAQ,cAAc,CAAA;AAAA,MACrE,CAAA;AAGA,MAAA,YAAA,CAAa,UAAU,UAAA,CAAW,MAAM,KAAK,IAAA,IAAQ,cAAc,CAAA;AAAA,IACrE,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,cAAA,EAAgB,aAAa;AAAA,GACxC;AAKA,EAAA,MAAM,MAAA,GAASA,iBAAA;AAAA,IACb,OACE,IAAA,EACA,YAAA,EACA,cAAA,KACkB;AAClB,MAAA,MAAM,gBAAgB,UAAA,CAAW,OAAA;AAEjC,MAAA,IAAI,cAAA;AACJ,MAAA,IAAI,aAAA,CAAc,eAAA,IAAmB,aAAA,CAAc,gBAAA,EAAkB;AACnE,QAAA,IAAI;AACF,UAAA,cAAA,GAAiB,MAAM,mBAAA;AAAA,YACrB,aAAA,CAAc;AAAA,WAChB;AAAA,QACF,SAAS,GAAA,EAAK;AACZ,UAAA,OAAA,CAAQ,IAAA,CAAK,mDAAmD,GAAG,CAAA;AAAA,QAIrE;AAAA,MACF;AAEA,MAAA,MAAM,KAAA,GAAiC;AAAA,QACrC,OAAA,EAAS,IAAA;AAAA,QACT,GAAI,qBAAqB,OAAA,GACrB,EAAE,mBAAmB,oBAAA,CAAqB,OAAA,KAC1C,EAAC;AAAA,QACL,GAAI,eAAA,CAAgB,OAAA,IAAW,WAAA,GAC3B,EAAE,aAAa,eAAA,CAAgB,OAAA,IAAW,WAAA,EAAY,GACtD,EAAC;AAAA,QACL,GAAI,cAAA,GAAiB,EAAE,cAAA,KAAmB,EAAC;AAAA,QAC3C,GAAI,MAAA,GAAS,EAAE,MAAA,KAAW,EAAC;AAAA,QAC3B,GAAI,OAAA,GAAU,EAAE,OAAA,KAAY;AAAC,OAC/B;AAEA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,MAAA;AAAA,QACvB,6BAAA;AAAA,QACA,EAAE,KAAA,EAAM;AAAA,QACR,EAAE,WAAW,uBAAA;AAAwB,OACvC;AACA,MAAA,IAAI,CAAC,WAAW,OAAA,EAAS;AAEzB,MAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,MAAA,GAAS,CAAC,CAAA;AAC5B,MAAA,MAAM,MAAA,GAAS,IAAI,IAAA,EAAM,kBAAA;AAEzB,MAAA,IAAI,KAAA,IAAS,CAAC,MAAA,EAAQ;AACpB,QAAA,MAAM,IAAA,GACJ,OAAO,KAAA,EAAO,UAAA,EAAY,SAAS,QAAA,GAC/B,KAAA,CAAM,WAAW,IAAA,GACjB,MAAA;AACN,QAAA,MAAM,UAAA,GAAa,oBAAA,CAAqB,IAAA,EAAM,KAAA,EAAO,OAAO,CAAA;AAK5D,QAAA,IAAI,UAAA,CAAW,IAAA,KAAS,SAAA,IAAa,cAAA,KAAmB,CAAA,EAAG;AACzD,UAAA,MAAM,MAAA,CAAO,IAAA,EAAM,YAAA,EAAc,CAAC,CAAA;AAClC,UAAA;AAAA,QACF;AAEA,QAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,QAAA,QAAA,CAAS,UAAU,CAAA;AACnB,QAAA,QAAA,CAAS,UAAA,CAAW,IAAA,KAAS,YAAA,GAAe,SAAA,GAAY,OAAO,CAAA;AAC/D,QAAA;AAAA,MACF;AAEA,MAAA,oBAAA,CAAqB,OAAA,GAAU,OAAO,YAAA,CAAa,KAAA;AACnD,MAAA,YAAA,CAAa,OAAA,GAAU,OAAO,YAAA,CAAa,SAAA;AAC3C,MAAA,YAAA,CAAa,MAAA,CAAO,aAAa,SAAS,CAAA;AAC1C,MAAA,iBAAA,CAAkB,MAAA,CAAO,kBAAkB,IAAI,CAAA;AAE/C,MAAA,MAAM,cAAc,MAAA,CAAO,WAAA;AAC3B,MAAA,MAAM,mBAAmB,MAAA,CAAO,gBAAA;AAMhC,MAAA,WAAA,CAAY,CAAC,IAAA,KAAS;AACpB,QAAA,MAAM,QAAA,GAAW,KAAK,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,EAAA,KAAO,YAAY,CAAA,GACnD,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAO,CAAA,CAAE,OAAO,YAAA,GAAe,WAAA,GAAc,CAAE,CAAA,GACzD,CAAC,GAAG,IAAA,EAAM,WAAW,CAAA;AACzB,QAAA,OAAO,CAAC,GAAG,QAAA,EAAU,gBAAgB,CAAA;AAAA,MACvC,CAAC,CAAA;AAED,MAAA,IACE,gBAAA,CAAiB,MAAA,KAAW,WAAA,IAC5B,gBAAA,CAAiB,WAAW,QAAA,EAC5B;AACA,QAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,QAAA,IAAI,gBAAA,CAAiB,WAAW,QAAA,EAAU;AACxC,UAAA,MAAM,UAAA,GAAa,oBAAA;AAAA,YACjB,iBAAiB,SAAA,IAAa;AAAA,WAChC;AACA,UAAA,QAAA,CAAS,UAAU,CAAA;AACnB,UAAA,QAAA,CAAS,OAAO,CAAA;AAAA,QAClB,CAAA,MAAO;AACL,UAAA,QAAA,CAAS,OAAO,CAAA;AAAA,QAClB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,QAAA,CAAS,WAAW,CAAA;AACpB,MAAA,YAAA,CAAa,MAAA,CAAO,YAAA,CAAa,KAAA,EAAO,gBAAA,CAAiB,EAAE,CAAA;AAAA,IAC7D,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,aAAa,YAAY;AAAA,GACrD;AAEA,EAAA,MAAM,IAAA,GAAOA,iBAAA;AAAA,IACX,OAAO,OAAA,KAAmC;AACxC,MAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,EAAK;AAC1B,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,IAAI,YAAY,OAAA,EAAS;AAEzB,MAAA,MAAM,gBAAgB,UAAA,CAAW,OAAA;AACjC,MAAA,IAAI,CAAC,cAAc,OAAA,EAAS;AAC1B,QAAA,QAAA,CAAS,oBAAA,CAAqB,kBAAkB,CAAC,CAAA;AACjD,QAAA,QAAA,CAAS,UAAU,CAAA;AACnB,QAAA;AAAA,MACF;AACA,MAAA,IAAI,IAAA,CAAK,MAAA,GAAS,aAAA,CAAc,MAAA,CAAO,gBAAA,EAAkB;AACvD,QAAA,QAAA,CAAS;AAAA,UACP,IAAA,EAAM,YAAA;AAAA,UACN,IAAA,EAAM,kBAAA;AAAA,UACN,SAAS,CAAA,gBAAA,EAAmB,IAAA,CAAK,MAAM,CAAA,gCAAA,EAA8B,aAAA,CAAc,OAAO,gBAAgB,CAAA,CAAA,CAAA;AAAA,UAC1G,SAAA,EAAW;AAAA,SACZ,CAAA;AACD,QAAA;AAAA,MACF;AACA,MAAA,IACE,YAAA,CAAa,OAAA,IAAW,aAAA,CAAc,MAAA,CAAO,uBAAA,EAC7C;AACA,QAAA,QAAA,CAAS;AAAA,UACP,IAAA,EAAM,YAAA;AAAA,UACN,IAAA,EAAM,oBAAA;AAAA,UACN,OAAA,EAAS,CAAA,kCAAA,EAAqC,aAAA,CAAc,MAAA,CAAO,uBAAuB,CAAA,+CAAA,CAAA;AAAA,UAC1F,SAAA,EAAW;AAAA,SACZ,CAAA;AACD,QAAA;AAAA,MACF;AAEA,MAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,MAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAC1B,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,QAAA,CAAS,SAAS,CAAA;AAClB,MAAA,aAAA,EAAc;AAId,MAAA,MAAM,UAAA,GAA6B;AAAA,QACjC,IAAI,gBAAA,EAAiB;AAAA,QACrB,cAAA,EAAgB,qBAAqB,OAAA,IAAW,SAAA;AAAA,QAChD,IAAA,EAAM,MAAA;AAAA,QACN,MAAA,EAAQ,WAAA;AAAA,QACR,OAAA,EAAS,IAAA;AAAA,QACT,cAAA,EAAgB,IAAA;AAAA,QAChB,UAAU,EAAC;AAAA,QACX,YAAY,EAAC;AAAA,QACb,MAAM,EAAC;AAAA,QACP,SAAA,EAAW,IAAA;AAAA,QACX,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAClC,WAAA,EAAA,iBAAa,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,OACtC;AACA,MAAA,WAAA,CAAY,CAAC,IAAA,KAAS,CAAC,GAAG,IAAA,EAAM,UAAU,CAAC,CAAA;AAC3C,MAAA,YAAA,CAAa,OAAA,IAAW,CAAA;AACxB,MAAA,YAAA,CAAa,aAAa,OAAO,CAAA;AACjC,MAAA,MAAA,GAAS,IAAI,CAAA;AAEb,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,CAAO,IAAA,EAAM,UAAA,CAAW,EAAA,EAAI,CAAC,CAAA;AAAA,MACrC,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,CAAC,WAAW,OAAA,EAAS;AACzB,QAAA,OAAA,CAAQ,KAAA,CAAM,gCAAgC,GAAG,CAAA;AACjD,QAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,QAAA,QAAA,CAAS,oBAAA,CAAqB,eAAe,CAAC,CAAA;AAC9C,QAAA,QAAA,CAAS,OAAO,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,aAAA,EAAe,MAAA,EAAQ,MAAM;AAAA,GAChC;AAEA,EAAA,MAAM,IAAA,GAAOA,kBAAY,MAAM;AAC7B,IAAA,aAAA,EAAc;AACd,IAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,IAAA,WAAA;AAAA,MAAY,CAAC,IAAA,KACX,IAAA,CAAK,OAAA,CAAwB,CAAC,CAAA,KAAM;AAClC,QAAA,IAAI,CAAA,CAAE,IAAA,KAAS,WAAA,EAAa,OAAO,CAAC,CAAC,CAAA;AACrC,QAAA,IAAI,CAAA,CAAE,WAAW,SAAA,IAAa,CAAA,CAAE,WAAW,SAAA,EAAW,OAAO,CAAC,CAAC,CAAA;AAC/D,QAAA,MAAM,IAAA,GAAO,YAAY,CAAC,CAAA;AAG1B,QAAA,IAAI,CAAC,IAAA,EAAM,OAAO,EAAC;AACnB,QAAA,OAAO;AAAA,UACL;AAAA,YACE,GAAG,CAAA;AAAA,YACH,MAAA,EAAQ,WAAA;AAAA,YACR,OAAA,EAAS,IAAA;AAAA,YACT,WAAA,EAAA,iBAAa,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY;AACtC,SACF;AAAA,MACF,CAAC;AAAA,KACH;AACA,IAAA,QAAA;AAAA,MAAS,CAAC,IAAA,KACR,IAAA,KAAS,SAAA,IAAa,IAAA,KAAS,cAAc,OAAA,GAAU;AAAA,KACzD;AAAA,EACF,CAAA,EAAG,CAAC,aAAa,CAAC,CAAA;AAElB,EAAA,MAAM,KAAA,GAAQA,kBAAY,MAAM;AAC9B,IAAA,MAAM,OAAO,eAAA,CAAgB,OAAA;AAC7B,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,aAAA,EAAc;AACd,IAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AAGtB,IAAA,WAAA,CAAY,CAAC,IAAA,KAAS;AACpB,MAAA,MAAM,IAAA,GAAO,CAAC,GAAG,IAAI,CAAA;AACrB,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AACjC,MAAA,IAAI,MAAM,IAAA,KAAS,WAAA,IAAe,KAAK,MAAA,KAAW,QAAA,OAAe,GAAA,EAAI;AACrE,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAClC,MAAA,IAAI,OAAO,IAAA,KAAS,MAAA,IAAU,MAAM,OAAA,KAAY,IAAA,OAAW,GAAA,EAAI;AAC/D,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AACD,IAAA,YAAA,CAAa,UAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,YAAA,CAAa,UAAU,CAAC,CAAA;AAC3D,IAAA,YAAA,CAAa,aAAa,OAAO,CAAA;AACjC,IAAA,KAAK,KAAK,IAAI,CAAA;AAAA,EAChB,CAAA,EAAG,CAAC,aAAA,EAAe,IAAI,CAAC,CAAA;AAExB,EAAA,MAAM,KAAA,GAAQA,kBAAY,MAAM;AAC9B,IAAA,aAAA,EAAc;AACd,IAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,IAAA,oBAAA,CAAqB,OAAA,GAAU,IAAA;AAC/B,IAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAC1B,IAAA,YAAA,CAAa,OAAA,GAAU,CAAA;AACvB,IAAA,YAAA,CAAa,CAAC,CAAA;AACd,IAAA,WAAA,CAAY,EAAE,CAAA;AACd,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,IAAA,QAAA,CAAS,UAAA,CAAW,OAAA,CAAQ,OAAA,GAAU,OAAA,GAAU,UAAU,CAAA;AAC1D,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,MAAA,IAAI;AACF,QAAA,MAAA,CAAO,cAAA,CAAe,WAAW,UAAU,CAAA;AAAA,MAC7C,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,aAAA,EAAe,UAAU,CAAC,CAAA;AAE9B,EAAA,MAAM,eAAA,GAAkBA,iBAAA,CAAY,CAAC,IAAA,KAAwB;AAC3D,IAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAC1B,IAAA,oBAAA,CAAqB,IAAI,CAAA;AAAA,EAC3B,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,QAAA,GAAWH,cAAuB,MAAM;AAC5C,IAAA,KAAA,IAAS,IAAI,QAAA,CAAS,MAAA,GAAS,GAAG,CAAA,IAAK,CAAA,EAAG,KAAK,CAAA,EAAG;AAChD,MAAA,MAAM,CAAA,GAAI,SAAS,CAAC,CAAA;AACpB,MAAA,IAAI,CAAC,CAAA,IAAK,CAAA,CAAE,IAAA,KAAS,WAAA,EAAa;AAClC,MAAA,IAAI,EAAE,MAAA,KAAW,SAAA,IAAa,CAAA,CAAE,MAAA,KAAW,WAAW,OAAO,IAAA;AAC7D,MAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,QAAA,IAAY,EAAC;AAC7B,MAAA,OAAO,MAAM,MAAA,GAAU,KAAA,CAAM,MAAM,MAAA,GAAS,CAAC,KAAK,IAAA,GAAQ,IAAA;AAAA,IAC5D;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,MAAM,OAAA,GAAA,CACH,UAAU,OAAA,IAAW,KAAA,KAAU,YAChC,OAAA,CAAQ,OAAA,IACR,SAAA,GAAY,OAAA,CAAQ,MAAA,CAAO,uBAAA;AAE7B,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA;AAAA,IACA,cAAA;AAAA,IACA,KAAA;AAAA,IACA,YAAA;AAAA,IACA,eAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACF;AACF;AAOA,IAAI,iBAAA,GAAoB,CAAA;AAExB,SAAS,gBAAA,GAA2B;AAClC,EAAA,iBAAA,IAAqB,CAAA;AACrB,EAAA,OAAO,CAAA,mBAAA,EAAsB,IAAA,CAAK,GAAA,EAAK,IAAI,iBAAiB,CAAA,CAAA;AAC9D","file":"index.js","sourcesContent":["const LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\nconst RESERVED_HEADERS = new Set([\n \"authorization\",\n \"cookie\",\n \"x-actor-id\",\n \"x-actor-type\",\n \"x-consent-granted-by\",\n \"x-consent-scope\",\n \"x-consent-granted-at\",\n \"x-consent-expires-at\",\n]);\n\nexport function validateGatewayUrl(value: string): string {\n let url: URL;\n\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"Gateway URL must be a valid absolute URL\");\n }\n\n if (url.protocol === \"https:\") {\n return url.toString();\n }\n\n if (\n url.protocol === \"http:\" &&\n LOOPBACK_HOSTS.has(url.hostname.toLowerCase())\n ) {\n return url.toString();\n }\n\n throw new Error(\"Gateway URL must use HTTPS unless it targets localhost\");\n}\n\nexport function sanitizeHeaders(\n headers?: Record<string, string>,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n\n return Object.fromEntries(\n Object.entries(headers).filter(\n ([key]) => !RESERVED_HEADERS.has(key.toLowerCase()),\n ),\n );\n}\n\n/**\n * Hostnames whose Cloudflare Access application gates the GraphQL gateway.\n *\n * Only the alpha gateways are gated; the production gateways are public, so a token is never\n * attached there even if one is configured.\n */\nconst CF_ACCESS_GATED_HOSTS = new Set([\n \"alphagraphql.burdenoff.com\",\n \"alphagraphqlworkspaces.burdenoff.com\",\n]);\n\n/**\n * Service-token headers for a gated gateway, or nothing.\n *\n * Returns an empty object unless the target really is a gated host AND both halves of the token\n * are present — a half-configured token would send a malformed credential to every request.\n */\nexport function cfAccessHeaders(\n gatewayUrl: string,\n cfAccess?: { clientId?: string; clientSecret?: string },\n): Record<string, string> {\n const clientId = cfAccess?.clientId?.trim();\n const clientSecret = cfAccess?.clientSecret?.trim();\n if (!clientId || !clientSecret) return {};\n\n let host: string;\n try {\n host = new URL(gatewayUrl).hostname.toLowerCase();\n } catch {\n return {};\n }\n if (!CF_ACCESS_GATED_HOSTS.has(host)) return {};\n\n return {\n \"CF-Access-Client-Id\": clientId,\n \"CF-Access-Client-Secret\": clientSecret,\n };\n}\n","/**\n * Lightweight GraphQL client for the Burdenoff Web SDK.\n * Uses native fetch - zero external dependencies.\n * All calls are unauthenticated (public gateway operations only).\n */\n\nimport {\n cfAccessHeaders,\n sanitizeHeaders,\n validateGatewayUrl,\n} from \"./security\";\n\nexport interface WebSDKClientConfig {\n /** Global public gateway URL (e.g. \"https://api.burdenoff.com/global/graphql\") */\n gatewayUrl: string;\n /** Platform product ID for scoping operations */\n productId: string;\n /** Product slug (used for public product queries) */\n productSlug?: string;\n /** reCAPTCHA site key (if not fetched from product config) */\n recaptchaSiteKey?: string;\n /** Rybbit analytics site ID */\n rybbitSiteId?: string;\n /** Custom headers to include in all requests */\n headers?: Record<string, string>;\n /**\n * Cloudflare Access service token, for the ALPHA gateway hosts only.\n *\n * `alphagraphql.burdenoff.com` sits behind a Cloudflare Access application, so an\n * unauthenticated browser XHR is answered with a 302 to the Access login on a different\n * origin — which the browser reports as an opaque CORS failure rather than a 401. Attaching\n * the service-token headers is how every app shell already passes that gate (fe-libs\n * `installGatewayFetchRewrite`); the website SDK previously had no equivalent, so contact,\n * newsletter, waitlist and explore all failed on alpha.\n *\n * Vite only inlines `VITE_*` into APP source, never into a bundled library, so the host app\n * must read `import.meta.env` and pass the values in. Production gateways are not gated and\n * receive no headers.\n */\n cfAccess?: { clientId?: string; clientSecret?: string };\n /**\n * Per-request timeout in ms. Kept below the gateway's operation timeout so a\n * stalled request surfaces as an error the UI can render, instead of leaving\n * a page stuck on loading skeletons forever. Default 12000.\n */\n timeoutMs?: number;\n /**\n * Extra attempts for transient failures (timeout / network / 5xx / 429) on\n * QUERIES ONLY. Mutations are never retried — a retried contact-form or\n * waitlist submit would double-submit. Default 1 (2 attempts total).\n */\n maxRetries?: number;\n}\n\n/**\n * Per-call overrides for {@link WebSDKClient.query}.\n *\n * The defaults (5-minute response cache + in-flight deduplication) are right\n * for the read-once content queries most SDK components make, and wrong for a\n * poll loop: the second poll of the same `(query, variables)` pair would be\n * served straight from the cache and the UI would freeze on the first\n * response forever. Pass `{ cache: false }` for anything polled.\n */\nexport interface WebSDKQueryOptions {\n /**\n * Use the response cache and in-flight deduplication. Default `true`.\n * `false` skips the cache read, the dedupe map AND the cache write, so the\n * call always hits the network and never poisons a later cached read.\n */\n cache?: boolean;\n /** Override the client-wide request timeout for this call only. */\n timeoutMs?: number;\n}\n\n/** Per-call overrides for {@link WebSDKClient.mutate}. */\nexport interface WebSDKMutateOptions {\n /** Override the client-wide request timeout for this call only. */\n timeoutMs?: number;\n}\n\nexport interface GraphQLResponse<T = Record<string, unknown>> {\n data?: T;\n errors?: Array<{\n message: string;\n locations?: Array<{ line: number; column: number }>;\n path?: Array<string | number>;\n extensions?: Record<string, unknown>;\n }>;\n}\n\nexport class WebSDKClient {\n private config: WebSDKClientConfig;\n private queryCache = new Map<\n string,\n { data: GraphQLResponse<unknown>; ts: number }\n >();\n private inflight = new Map<string, Promise<GraphQLResponse<unknown>>>();\n private static CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n private static MAX_CACHE_ENTRIES = 100;\n private static DEFAULT_TIMEOUT_MS = 12_000;\n private static DEFAULT_MAX_RETRIES = 1;\n private static RETRY_BASE_DELAY_MS = 400;\n\n constructor(config: WebSDKClientConfig) {\n this.config = {\n ...config,\n gatewayUrl: validateGatewayUrl(config.gatewayUrl),\n headers: sanitizeHeaders(config.headers),\n };\n }\n\n getConfig(): WebSDKClientConfig {\n return this.config;\n }\n\n /**\n * Execute a GraphQL query (with deduplication and caching).\n *\n * Pass `{ cache: false }` to bypass the cache entirely — required for poll\n * loops, where every tick must reach the network.\n */\n async query<T = Record<string, unknown>>(\n query: string,\n variables?: Record<string, unknown>,\n options?: WebSDKQueryOptions,\n ): Promise<GraphQLResponse<T>> {\n // Uncached path: no cache read, no in-flight dedupe, no cache write.\n // Deliberately bypasses the dedupe map too — two identical polls issued a\n // few hundred ms apart must both hit the network, otherwise the second one\n // resolves with the first one's (already stale) snapshot.\n if (options?.cache === false) {\n return this.request<T>(query, variables, true, options.timeoutMs);\n }\n\n const cacheKey = JSON.stringify({ query, variables });\n\n // Return cached response if still valid, evict if expired\n const cached = this.queryCache.get(cacheKey);\n if (cached) {\n if (Date.now() - cached.ts < WebSDKClient.CACHE_TTL) {\n return cached.data as GraphQLResponse<T>;\n }\n this.queryCache.delete(cacheKey);\n }\n\n // Deduplicate: if same query is already in-flight, reuse the promise\n const existing = this.inflight.get(cacheKey);\n if (existing) {\n return existing as Promise<GraphQLResponse<T>>;\n }\n\n const promise = this.request<T>(query, variables, true, options?.timeoutMs)\n .then((result) => {\n // Cache successful responses only\n if (result.data && !result.errors?.length) {\n if (this.queryCache.size >= WebSDKClient.MAX_CACHE_ENTRIES) {\n const oldestEntry = this.queryCache.keys().next().value;\n if (oldestEntry) {\n this.queryCache.delete(oldestEntry);\n }\n }\n this.queryCache.set(cacheKey, { data: result, ts: Date.now() });\n }\n return result;\n })\n .finally(() => {\n this.inflight.delete(cacheKey);\n });\n\n this.inflight.set(cacheKey, promise);\n return promise;\n }\n\n /**\n * Execute a GraphQL mutation\n */\n async mutate<T = Record<string, unknown>>(\n mutation: string,\n variables?: Record<string, unknown>,\n options?: WebSDKMutateOptions,\n ): Promise<GraphQLResponse<T>> {\n // retry=false: a retried mutation could double-submit (contact form,\n // waitlist signup, order). Only the timeout applies here.\n return this.request<T>(mutation, variables, false, options?.timeoutMs);\n }\n\n /** HTTP statuses worth another attempt — transient server/edge conditions. */\n private static isRetriableStatus(status: number): boolean {\n return status === 429 || status === 408 || (status >= 500 && status < 600);\n }\n\n private static sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Perform the HTTP call with a hard timeout. Every outcome resolves to a\n * GraphQLResponse — callers never hang, so a UI's `loading` state always\n * settles into data or a renderable error.\n */\n private async attempt<T>(\n query: string,\n variables: Record<string, unknown> | undefined,\n timeoutMs: number,\n ): Promise<{ res: GraphQLResponse<T>; retriable: boolean }> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(this.config.gatewayUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-product-id\": this.config.productId,\n ...this.config.headers,\n ...cfAccessHeaders(this.config.gatewayUrl, this.config.cfAccess),\n },\n body: JSON.stringify({ query, variables }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n console.error(\n \"[WebSDK] GraphQL request failed\",\n response.status,\n response.statusText,\n );\n return {\n res: {\n errors: [\n {\n message: `HTTP ${response.status}: ${response.statusText}`,\n extensions: { code: `HTTP_${response.status}` },\n },\n ],\n },\n retriable: WebSDKClient.isRetriableStatus(response.status),\n };\n }\n\n return {\n res: (await response.json()) as GraphQLResponse<T>,\n retriable: false,\n };\n } catch (error) {\n const aborted =\n error instanceof Error &&\n (error.name === \"AbortError\" || controller.signal.aborted);\n const message = aborted\n ? `Request timed out after ${timeoutMs}ms`\n : error instanceof Error\n ? error.message\n : \"Network error\";\n console.error(\"[WebSDK] Network error\", message);\n return {\n res: {\n errors: [\n {\n message,\n extensions: { code: aborted ? \"TIMEOUT\" : \"NETWORK_ERROR\" },\n },\n ],\n },\n // Transport-level failures are worth one more try; a genuine outage\n // just fails twice quickly and still renders an error state.\n retriable: true,\n };\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async request<T>(\n query: string,\n variables?: Record<string, unknown>,\n retry = true,\n timeoutOverrideMs?: number,\n ): Promise<GraphQLResponse<T>> {\n const timeoutMs =\n timeoutOverrideMs ??\n this.config.timeoutMs ??\n WebSDKClient.DEFAULT_TIMEOUT_MS;\n const maxRetries = retry\n ? (this.config.maxRetries ?? WebSDKClient.DEFAULT_MAX_RETRIES)\n : 0;\n\n let last: GraphQLResponse<T> | undefined;\n for (let i = 0; i <= maxRetries; i++) {\n const { res, retriable } = await this.attempt<T>(\n query,\n variables,\n timeoutMs,\n );\n if (!retriable || i === maxRetries) return res;\n last = res;\n // Small backoff with jitter so a burst of clients doesn't retry in lockstep.\n await WebSDKClient.sleep(\n WebSDKClient.RETRY_BASE_DELAY_MS * (i + 1) + Math.random() * 200,\n );\n }\n return last as GraphQLResponse<T>;\n }\n}\n","/**\n * React context provider for the Web SDK client.\n * Wraps the application with WebSDKClient configuration.\n */\n\"use client\";\n\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { resolveGatewayUrl } from \"./gateway-resolver\";\nimport { WebSDKClient, type WebSDKClientConfig } from \"./graphql-client\";\n\nconst WebSDKContext = createContext<WebSDKClient | null>(null);\n\nexport interface WebSDKProviderProps {\n /** SDK client configuration */\n config: WebSDKClientConfig;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Provider component that makes the WebSDKClient available to all child components.\n *\n * @example\n * ```tsx\n * <WebSDKProvider config={{\n * gatewayUrl: \"https://api.burdenoff.com/global/graphql\",\n * productId: \"your-product-id\",\n * productSlug: \"your-product\",\n * }}>\n * <App />\n * </WebSDKProvider>\n * ```\n */\nexport function WebSDKProvider({ config, children }: WebSDKProviderProps) {\n const client = useMemo(() => {\n const resolvedConfig = {\n ...config,\n gatewayUrl: resolveGatewayUrl(config.gatewayUrl),\n };\n return new WebSDKClient(resolvedConfig);\n }, [config]);\n\n return (\n <WebSDKContext.Provider value={client}>{children}</WebSDKContext.Provider>\n );\n}\n\n/**\n * Hook to access the WebSDKClient instance.\n * Must be used within a WebSDKProvider.\n */\nexport function useWebSDK(): WebSDKClient {\n const client = useContext(WebSDKContext);\n if (!client) {\n throw new Error(\"useWebSDK must be used within a WebSDKProvider\");\n }\n return client;\n}\n\n/**\n * Hook to access the SDK configuration.\n * Useful for components that need config values like productId, recaptchaSiteKey, etc.\n */\nexport function useWebSDKConfig(): WebSDKClientConfig {\n const client = useWebSDK();\n return client.getConfig();\n}\n","/**\n * Explore chat — TypeScript mirror of the public `/explore` GraphQL contract.\n *\n * Canonical source: `~/products/dev/platform/context/explore/CONTRACT.md` §1\n * (global-support-svc, served through the global PUBLIC gateway with\n * `@rbac(public: true, scopeType: \"global\")`).\n *\n * Nothing in this file may drift from that document. If a shape here looks\n * wrong, fix CONTRACT.md first and tell the backend workstreams — never patch\n * it locally.\n *\n * Nullability note: the contract marks `title`, `description`, `product`,\n * `imageUrl`, `partialContent`, `errorCode`, `completedAt`, `productSlug`,\n * `recaptchaSiteKey` and `remainingToday` as nullable, so every one of them is\n * `?: T | null` here — a GraphQL `null` and an omitted selection both have to\n * be representable.\n */\n\n// ============================================================================\n// Enums (string unions — the wire format is the enum name)\n// ============================================================================\n\nexport type ExploreMessageRole = \"USER\" | \"ASSISTANT\";\n\nexport type ExploreMessageStatus =\n \"PENDING\" | \"RUNNING\" | \"COMPLETED\" | \"FAILED\";\n\n/**\n * The `ExploreCta.kind` values enumerated in CONTRACT.md §1.\n *\n * `ExploreCtaLink.kind` is deliberately typed `string`, not this union: the\n * field is `String!` on the wire, and a kind added server-side must render\n * (falling back to the neutral CTA style) rather than break the build of 38\n * websites. Use this union when you are *producing* a kind.\n */\nexport type ExploreCtaKind =\n | \"CONTACT\"\n | \"PARTNERS\"\n | \"PRICING\"\n | \"SERVICES\"\n | \"WAITLIST\"\n | \"STORE\"\n | \"APP\"\n | \"DOCS\"\n | \"OTHER\";\n\n/**\n * Error codes surfaced through `extensions.code`. `HTTP_429` is what the\n * gateway emits when it rate-limits at the edge; the SDK client also produces\n * `TIMEOUT` / `NETWORK_ERROR` for transport failures.\n */\nexport type ExploreErrorCode =\n | \"EXPLORE_DISABLED\"\n | \"RATE_LIMITED\"\n | \"EXPLORE_GLOBAL_LIMIT\"\n | \"CAPTCHA_REQUIRED\"\n | \"CAPTCHA_FAILED\"\n | \"MESSAGE_TOO_LONG\"\n | \"MESSAGE_EMPTY\"\n | \"CONVERSATION_LIMIT\"\n | \"CONVERSATION_BUSY\"\n | \"UPSTREAM_UNAVAILABLE\"\n | \"NOT_FOUND\"\n | \"HTTP_429\"\n | \"TIMEOUT\"\n | \"NETWORK_ERROR\";\n\n// ============================================================================\n// Object types\n// ============================================================================\n\n/** `type ExploreReference` — a cited source page for an answer. */\nexport interface ExploreReference {\n url: string;\n title?: string | null;\n description?: string | null;\n product?: string | null;\n imageUrl?: string | null;\n}\n\n/**\n * `type ExploreCta` — a suggested next step attached to an answer.\n *\n * Named `ExploreCtaLink` in the SDK because `ExploreCta` is taken by the\n * exported nav component (`<ExploreCta variant=\"header\" />`). Same shape,\n * different name; the GraphQL type is unchanged.\n */\nexport interface ExploreCtaLink {\n /** One of {@link ExploreCtaKind}; unknown values render with the neutral style. */\n kind: string;\n label: string;\n url: string;\n product?: string | null;\n}\n\n/** `type ExploreMessage`. `content` is `\"\"` while the turn is PENDING. */\nexport interface ExploreMessage {\n id: string;\n conversationId: string;\n role: ExploreMessageRole;\n status: ExploreMessageStatus;\n /** Final answer, markdown. Empty string until the turn completes. */\n content: string;\n /** Streaming preview while PENDING/RUNNING. */\n partialContent?: string | null;\n /** Human-readable progress lines, e.g. \"Searching vibecontrols…\". */\n activity: string[];\n references: ExploreReference[];\n ctas: ExploreCtaLink[];\n errorCode?: string | null;\n createdAt: string;\n completedAt?: string | null;\n}\n\n/** `type ExploreConversation`. `token` is the client's only handle. */\nexport interface ExploreConversation {\n id: string;\n token: string;\n productSlug?: string | null;\n turnCount: number;\n createdAt: string;\n}\n\n/** `type ExploreProduct` — one product the harness can answer about. */\nexport interface ExploreProduct {\n slug: string;\n name: string;\n tagline?: string | null;\n website: string;\n}\n\n/** `type ExploreLimits` — server-owned caps the composer enforces locally. */\nexport interface ExploreLimits {\n maxMessageLength: number;\n maxTurnsPerConversation: number;\n messagesPerDay: number;\n historyTurns: number;\n}\n\n/**\n * `type ExploreCatalog` — everything the page needs before the first message.\n *\n * `captchaRequired` + `recaptchaSiteKey` are what turn reCAPTCHA v3 on: it is\n * a backend secret change, and no website redeploy is involved.\n */\nexport interface ExploreCatalog {\n enabled: boolean;\n products: ExploreProduct[];\n examplePrompts: string[];\n welcomeTitle: string;\n welcomeBody: string;\n limits: ExploreLimits;\n captchaRequired: boolean;\n recaptchaSiteKey?: string | null;\n}\n\n/** `input SendExploreMessageInput`. */\nexport interface SendExploreMessageInput {\n /** Omit to start a new conversation. */\n conversationToken?: string;\n /** The site the visitor is on — a soft hint, not a hard filter. */\n productSlug?: string;\n message: string;\n /** Only sent when `catalog.captchaRequired`. */\n recaptchaToken?: string;\n locale?: string;\n pageUrl?: string;\n}\n\n/**\n * `type SendExploreMessageResult`.\n *\n * **`assistantMessage.id` is the id to poll** — it comes back `PENDING`.\n */\nexport interface SendExploreMessageResult {\n conversation: ExploreConversation;\n userMessage: ExploreMessage;\n assistantMessage: ExploreMessage;\n remainingToday?: number | null;\n}\n\n// ============================================================================\n// GraphQL documents\n//\n// Only the fields the UI actually renders are requested — a narrower selection\n// set is cheaper to poll (this runs once every ~1.5s per active visitor) and\n// keeps the contract surface the websites depend on small.\n// ============================================================================\n\n/**\n * Shared selection set for every `ExploreMessage` in this file. Inlined as a\n * template string rather than a GraphQL `fragment` so each document stays a\n * single self-contained operation (the SDK client posts raw strings and has no\n * fragment registry).\n */\nconst EXPLORE_MESSAGE_FIELDS = /* GraphQL */ `\n id\n conversationId\n role\n status\n content\n partialContent\n activity\n references {\n url\n title\n description\n product\n imageUrl\n }\n ctas {\n kind\n label\n url\n product\n }\n errorCode\n createdAt\n completedAt\n`;\n\n/** Loaded once per page. Safe to serve from the SDK's 5-minute query cache. */\nexport const EXPLORE_CATALOG_QUERY = /* GraphQL */ `\n query ExploreCatalog($productSlug: String) {\n exploreCatalog(productSlug: $productSlug) {\n enabled\n products {\n slug\n name\n tagline\n website\n }\n examplePrompts\n welcomeTitle\n welcomeBody\n limits {\n maxMessageLength\n maxTurnsPerConversation\n messagesPerDay\n historyTurns\n }\n captchaRequired\n recaptchaSiteKey\n }\n }\n`;\n\n/**\n * The poll. MUST be issued with `client.query(..., { cache: false })` — the\n * default 5-minute cache would return the first PENDING snapshot forever and\n * the answer would never appear.\n */\nexport const EXPLORE_MESSAGE_QUERY = /* GraphQL */ `\n query ExploreMessage($conversationToken: String!, $id: ID!) {\n exploreMessage(conversationToken: $conversationToken, id: $id) {\n ${EXPLORE_MESSAGE_FIELDS}\n }\n }\n`;\n\n/** Submit half of the submit + poll pair. */\nexport const SEND_EXPLORE_MESSAGE_MUTATION = /* GraphQL */ `\n mutation SendExploreMessage($input: SendExploreMessageInput!) {\n sendExploreMessage(input: $input) {\n conversation {\n id\n token\n productSlug\n turnCount\n createdAt\n }\n userMessage {\n ${EXPLORE_MESSAGE_FIELDS}\n }\n assistantMessage {\n ${EXPLORE_MESSAGE_FIELDS}\n }\n remainingToday\n }\n }\n`;\n\n// ============================================================================\n// Response envelopes (what `client.query`/`client.mutate` resolve `data` to)\n// ============================================================================\n\nexport interface ExploreCatalogQueryData {\n exploreCatalog: ExploreCatalog;\n}\n\nexport interface ExploreMessageQueryData {\n exploreMessage: ExploreMessage | null;\n}\n\nexport interface SendExploreMessageMutationData {\n sendExploreMessage: SendExploreMessageResult;\n}\n","import type { WebsiteSwitcherProduct } from \"../components/website-switcher\";\n\n/**\n * Canonical Burdenoff ecosystem product list used by WebsiteSwitcher.\n *\n * Sourced from `~/products/websites/burdenoff-website/src/data/products.ts`.\n * Keep this in sync when products are added, renamed, or moved.\n */\nexport const ECOSYSTEM_PRODUCTS: WebsiteSwitcherProduct[] = [\n {\n slug: \"workspaces\",\n name: \"Workspaces\",\n websiteUrl: \"https://burdenoff.com\",\n },\n {\n slug: \"vibecontrols\",\n name: \"VibeControls\",\n websiteUrl: \"https://vibecontrols.com\",\n },\n {\n slug: \"fluidgrids\",\n name: \"FluidGrids\",\n websiteUrl: \"https://fluidgrids.com\",\n },\n // Botlit ships on botlit.ai — botlit.com does not resolve.\n { slug: \"botlit\", name: \"Botlit\", websiteUrl: \"https://www.botlit.ai\" },\n {\n slug: \"bigconsole\",\n name: \"BigConsole\",\n websiteUrl: \"https://bigconsole.com\",\n },\n {\n slug: \"semanticfed\",\n name: \"SemanticFed\",\n websiteUrl: \"https://semanticfed.com\",\n },\n {\n slug: \"intelwatchtower\",\n name: \"IntelWatchtower\",\n websiteUrl: \"https://intelwatchtower.com\",\n },\n { slug: \"buildmyiq\", name: \"BuildMyIQ\", websiteUrl: \"https://buildmyiq.com\" },\n {\n slug: \"assethandler\",\n name: \"AssetHandler\",\n websiteUrl: \"https://assethandler.com\",\n },\n {\n slug: \"crewfoundry\",\n name: \"CrewFoundry\",\n websiteUrl: \"https://crewfoundry.com\",\n },\n {\n slug: \"planmagnet\",\n name: \"PlanMagnet\",\n websiteUrl: \"https://planmagnet.com\",\n },\n {\n slug: \"eventfullymanaged\",\n name: \"EventfullyManaged\",\n websiteUrl: \"https://eventfullymanaged.com\",\n },\n {\n slug: \"headshotmarketing\",\n name: \"HeadshotMarketing\",\n websiteUrl: \"https://headshotmarketing.com\",\n },\n {\n slug: \"technospam\",\n name: \"TechnoSpam\",\n websiteUrl: \"https://technospam.com\",\n },\n { slug: \"kadaikodi\", name: \"Kadaikodi\", websiteUrl: \"https://kadaikodi.com\" },\n {\n slug: \"movethewheels\",\n name: \"MoveTheWheels\",\n websiteUrl: \"https://movethewheels.com\",\n },\n {\n slug: \"healthybowl\",\n name: \"Healthy Bowl\",\n websiteUrl: \"https://gethealthybowl.com\",\n },\n { slug: \"ggnomad\", name: \"GGNomad\", websiteUrl: \"https://ggnomad.com\" },\n {\n slug: \"timecampus\",\n name: \"TimeCampus\",\n websiteUrl: \"https://timecampus.com\",\n },\n {\n slug: \"manufacturedops\",\n name: \"ManufacturedOps\",\n websiteUrl: \"https://manufacturedops.com\",\n },\n {\n slug: \"theglobalfuel\",\n name: \"TheGlobalFuel\",\n websiteUrl: \"https://theglobalfuel.com\",\n },\n {\n slug: \"housingvista\",\n name: \"HousingVista\",\n websiteUrl: \"https://housingvista.com\",\n },\n {\n slug: \"proserviceworld\",\n name: \"ProServiceWorld\",\n websiteUrl: \"https://proserviceworld.com\",\n },\n {\n slug: \"mybodyshield\",\n name: \"MyBodyShield\",\n websiteUrl: \"https://mybodyshield.com\",\n },\n {\n slug: \"artistrybase\",\n name: \"ArtistryBase\",\n websiteUrl: \"https://artistrybase.com\",\n },\n {\n slug: \"theculturepost\",\n name: \"TheCulturePost\",\n websiteUrl: \"https://theculturepost.com\",\n },\n { slug: \"collabkin\", name: \"CollabKin\", websiteUrl: \"https://collabkin.com\" },\n {\n slug: \"comradecircle\",\n name: \"ComradeCircle\",\n websiteUrl: \"https://comradecircle.com\",\n },\n {\n slug: \"brainyrich\",\n name: \"BrainyRich\",\n websiteUrl: \"https://brainyrich.com\",\n },\n {\n slug: \"cosmicintersection\",\n name: \"CosmicIntersection\",\n websiteUrl: \"https://cosmicintersection.com\",\n },\n {\n slug: \"govcitizenhub\",\n name: \"GovCitizenHub\",\n websiteUrl: \"https://govcitizenhub.com\",\n },\n {\n slug: \"adaptercloud\",\n name: \"AdapterCloud\",\n websiteUrl: \"https://adaptercloud.com\",\n },\n {\n slug: \"subscriberbot\",\n name: \"Subscriber Bot\",\n websiteUrl: \"https://subscriberbot.com\",\n },\n {\n slug: \"hookmovies\",\n name: \"HookMovies\",\n websiteUrl: \"https://hookmovies.com\",\n },\n {\n slug: \"coolandlovely\",\n name: \"CoolAndLovely\",\n websiteUrl: \"https://coolandlovely.com\",\n },\n {\n slug: \"atheletebridge\",\n name: \"AthleteBridge\",\n websiteUrl: \"https://atheletebridge.com\",\n },\n {\n slug: \"labsofscience\",\n name: \"LabsOfScience\",\n websiteUrl: \"https://labsofscience.com\",\n },\n {\n slug: \"ecoimpacthub\",\n name: \"EcoImpactHub\",\n websiteUrl: \"https://ecoimpacthub.com\",\n },\n];\n","/**\n * reCAPTCHA v3 (invisible, score-based) loader and token minter.\n *\n * Deliberately dependency-free: the SDK already ships the `react-google-recaptcha`\n * peer for the **v2 checkbox** used by `ContactPage`, and the two widgets cannot\n * share a script tag — v3 needs `?render=<siteKey>` on the URL, v2 must not have\n * it. This module injects its own v3 script and leaves the v2 integration alone.\n *\n * The Explore chat turns v3 on purely from the backend catalog\n * (`exploreCatalog.captchaRequired && recaptchaSiteKey`), so nothing is loaded\n * and no third-party request is made on sites where captcha is off.\n */\n\n/** The slice of the `grecaptcha` global this module uses. */\nexport interface RecaptchaV3 {\n /** Runs the callback once the API is fully initialised. */\n ready(callback: () => void): void;\n /** Mints a single-use token for `action`. */\n execute(siteKey: string, options: { action: string }): Promise<string>;\n}\n\ndeclare global {\n interface Window {\n grecaptcha?: RecaptchaV3;\n }\n}\n\nconst SCRIPT_ID = \"boff-recaptcha-v3\";\nconst SCRIPT_SRC = \"https://www.google.com/recaptcha/api.js?render=\";\n\n/** Default action name reported to reCAPTCHA for Explore chat submissions. */\nexport const EXPLORE_RECAPTCHA_ACTION = \"explore_chat\";\n\n/**\n * One in-flight/settled promise per site key. Guarantees the script tag is\n * injected at most once even when several components mount at the same time,\n * and lets later callers await the same load instead of racing it.\n */\nconst loaders = new Map<string, Promise<RecaptchaV3>>();\n\nfunction isBrowser(): boolean {\n return typeof window !== \"undefined\" && typeof document !== \"undefined\";\n}\n\n/**\n * Load the reCAPTCHA v3 script for `siteKey` and resolve once `grecaptcha` is\n * ready to mint tokens.\n *\n * - Injects the script at most once per site key (subsequent calls reuse the\n * same promise).\n * - Adopts an already-present script tag (e.g. injected by the host site)\n * rather than adding a second one.\n * - Rejects rather than hanging when the script fails to load, so the caller\n * can decide whether to submit without a token or surface an error.\n */\nexport function loadRecaptchaV3(siteKey: string): Promise<RecaptchaV3> {\n if (!siteKey) {\n return Promise.reject(new Error(\"reCAPTCHA site key is required\"));\n }\n if (!isBrowser()) {\n return Promise.reject(\n new Error(\"reCAPTCHA v3 can only be loaded in a browser\"),\n );\n }\n\n const existing = loaders.get(siteKey);\n if (existing) return existing;\n\n const promise = new Promise<RecaptchaV3>((resolve, reject) => {\n const ready = () => {\n const api = window.grecaptcha;\n if (!api) {\n reject(new Error(\"reCAPTCHA loaded but grecaptcha is unavailable\"));\n return;\n }\n // `ready` queues until the API has finished initialising internally;\n // calling `execute` before that throws.\n api.ready(() => resolve(api));\n };\n\n // Already loaded by this module, another SDK instance, or the host site.\n if (window.grecaptcha) {\n ready();\n return;\n }\n\n const scriptId = `${SCRIPT_ID}-${siteKey}`;\n const found = document.getElementById(scriptId);\n if (found) {\n found.addEventListener(\"load\", ready, { once: true });\n found.addEventListener(\n \"error\",\n () => reject(new Error(\"Failed to load reCAPTCHA v3\")),\n { once: true },\n );\n return;\n }\n\n const script = document.createElement(\"script\");\n script.id = scriptId;\n script.src = `${SCRIPT_SRC}${encodeURIComponent(siteKey)}`;\n script.async = true;\n script.defer = true;\n script.addEventListener(\"load\", ready, { once: true });\n script.addEventListener(\n \"error\",\n () => {\n // Drop the memo so a later attempt can retry a transient CDN failure\n // instead of being stuck with a permanently rejected promise.\n loaders.delete(siteKey);\n reject(new Error(\"Failed to load reCAPTCHA v3\"));\n },\n { once: true },\n );\n document.head.appendChild(script);\n });\n\n loaders.set(siteKey, promise);\n return promise;\n}\n\n/**\n * Mint a single-use reCAPTCHA v3 token, loading the script on first use.\n *\n * Tokens are valid for ~2 minutes and are consumed by one verification, so\n * this must be called per submission — never cached.\n */\nexport async function getRecaptchaV3Token(\n siteKey: string,\n action: string = EXPLORE_RECAPTCHA_ACTION,\n): Promise<string> {\n const api = await loadRecaptchaV3(siteKey);\n return api.execute(siteKey, { action });\n}\n","/**\n * useExploreChat — the `/explore` conversation state machine.\n *\n * Implements the client half of CONTRACT.md §1: a **submit + poll** exchange.\n * `sendExploreMessage` returns immediately with a PENDING assistant message;\n * the answer arrives by polling `exploreMessage(conversationToken, id)` roughly\n * every 1.5s until it reports COMPLETED or FAILED. Both gateway hops cap a\n * subgraph call at 20s while a turn takes 5-60s, which is why there is no\n * request that simply waits for the answer.\n *\n * Design rules this hook exists to enforce:\n *\n * 1. **The catalog never gates the first paint.** `catalog` is populated with a\n * static fallback synchronously, so `ExplorePage` can render its `<h1>` on\n * the very first render. The websites' prerender waits for an `h1`; if that\n * heading depended on a network round-trip, 38 static builds would capture a\n * blank page.\n * 2. **Polls bypass the query cache.** `client.query(..., { cache: false })` —\n * the default 5-minute cache would hand every later poll the first PENDING\n * snapshot and the answer would never appear.\n * 3. **Nothing outlives the component.** Unmount and `stop()` both cancel the\n * poll chain through a generation counter, so a late response can never\n * write into an unmounted tree.\n */\n\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { useWebSDK } from \"../client/provider\";\nimport {\n EXPLORE_CATALOG_QUERY,\n EXPLORE_MESSAGE_QUERY,\n SEND_EXPLORE_MESSAGE_MUTATION,\n} from \"../components/explore-types\";\nimport { ECOSYSTEM_PRODUCTS } from \"../data/products\";\nimport { getRecaptchaV3Token } from \"../utils/recaptcha-v3\";\n\nimport type {\n ExploreCatalog,\n ExploreCatalogQueryData,\n ExploreLimits,\n ExploreMessage,\n ExploreMessageQueryData,\n SendExploreMessageInput,\n SendExploreMessageMutationData,\n} from \"../components/explore-types\";\n\n// ============================================================================\n// Public types\n// ============================================================================\n\n/**\n * Where the conversation is right now.\n *\n * - `loading` — catalog request in flight (the fallback catalog is already\n * rendered, so this is a refinement, not a blank screen).\n * - `ready` — idle; the composer accepts input.\n * - `sending` — `sendExploreMessage` in flight.\n * - `streaming` — polling the assistant turn; `activity` is live.\n * - `error` — the last turn failed; `retry()` is meaningful and the\n * composer stays usable.\n * - `limited` — rate limited; the composer is disabled.\n * - `disabled` — `exploreCatalog.enabled === false`.\n */\nexport type ExploreChatPhase =\n | \"loading\"\n | \"ready\"\n | \"sending\"\n | \"streaming\"\n | \"error\"\n | \"limited\"\n | \"disabled\";\n\n/** Coarse bucket the UI switches its banner copy and affordances on. */\nexport type ExploreChatErrorKind =\n | \"rate-limit\"\n | \"captcha\"\n | \"timeout\"\n | \"network\"\n | \"disabled\"\n | \"validation\"\n | \"unknown\";\n\nexport interface ExploreChatError {\n /** UI bucket. */\n kind: ExploreChatErrorKind;\n /** Raw `extensions.code` (or a client-side code such as `TIMEOUT`). */\n code: string;\n /** Human-readable, safe to render. */\n message: string;\n /** Whether re-sending the same message could plausibly succeed. */\n retryable: boolean;\n}\n\nexport interface UseExploreChatOptions {\n /** Slug of the product site this page is on — a soft hint to the harness. */\n productSlug?: string;\n /** Full URL of the page, forwarded as `pageUrl`. */\n pageUrl?: string;\n /** BCP-47 locale, forwarded as `locale`. */\n locale?: string;\n /** Poll cadence in ms. Default 1500 (CONTRACT.md §1). */\n pollIntervalMs?: number;\n /** Give up on a turn after this long. Default 90000 (the edge poll timeout). */\n pollTimeoutMs?: number;\n /**\n * Prompts to offer when `exploreCatalog` supplies none. Resolution order is\n * catalog → this option → {@link DEFAULT_EXPLORE_EXAMPLE_PROMPTS}, so a site\n * can ship product-specific prompts without waiting on the backend and still\n * be overridden centrally once the catalog carries them.\n */\n examplePrompts?: string[];\n /** sessionStorage key. Default `boff.explore.v1`. */\n storageKey?: string;\n /** Persist the conversation across reloads within the tab. Default true. */\n persist?: boolean;\n /** Called with the message text each time a send is accepted locally. */\n onSend?: (message: string) => void;\n}\n\nexport interface UseExploreChatResult {\n phase: ExploreChatPhase;\n /** Never null — starts as the static fallback, upgraded by the server. */\n catalog: ExploreCatalog;\n messages: ExploreMessage[];\n /** Latest progress line of the in-flight turn, or null when idle. */\n activity: string | null;\n /** Messages left today for this visitor, when the server reports it. */\n remainingToday: number | null;\n error: ExploreChatError | null;\n /** Product the visitor pinned the conversation to, or null for \"all\". */\n focusProduct: string | null;\n setFocusProduct: (slug: string | null) => void;\n send: (message: string) => Promise<void>;\n /** Stop polling and keep whatever text has streamed so far. */\n stop: () => void;\n /** Re-send the last message after a failed turn. */\n retry: () => void;\n /** Clear the conversation and the persisted session. */\n reset: () => void;\n canSend: boolean;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_STORAGE_KEY = \"boff.explore.v1\";\nconst DEFAULT_POLL_INTERVAL_MS = 1_500;\n/** Matches `EXPLORE_AGENT_TIMEOUT_MS` (CONTRACT.md §3) — the edge gives up too. */\nconst DEFAULT_POLL_TIMEOUT_MS = 90_000;\n/** Per-poll HTTP timeout. Short: a stuck poll must not stall the chain. */\nconst POLL_REQUEST_TIMEOUT_MS = 10_000;\n/** The submit hop enqueues a job; generous but well under the gateway's 20s. */\nconst SEND_REQUEST_TIMEOUT_MS = 18_000;\n/** Transient poll failures tolerated before the turn is declared dead. */\nconst MAX_CONSECUTIVE_POLL_FAILURES = 4;\n/** Cap on what goes into sessionStorage — a session must not grow unbounded. */\nconst MAX_PERSISTED_MESSAGES = 40;\n\n/** Fallback limits, mirroring the server defaults in CONTRACT.md §3. */\nexport const FALLBACK_EXPLORE_LIMITS: ExploreLimits = {\n maxMessageLength: 2000,\n maxTurnsPerConversation: 20,\n messagesPerDay: 100,\n historyTurns: 6,\n};\n\n/**\n * Prompts shown when neither the catalog nor the consumer supplies any.\n * Deliberately product-agnostic — this SDK renders on 38 different sites.\n */\nexport const DEFAULT_EXPLORE_EXAMPLE_PROMPTS: string[] = [\n \"What does this product actually do?\",\n \"Which Burdenoff product fits my team?\",\n \"How do I get started, step by step?\",\n \"What does it integrate with?\",\n];\n\nconst FALLBACK_WELCOME_TITLE = \"Ask anything about our products\";\nconst FALLBACK_WELCOME_BODY =\n \"Get straight answers drawn from our product documentation and public pages — with links back to the exact page each answer came from.\";\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction buildFallbackCatalog(examplePrompts?: string[]): ExploreCatalog {\n return {\n enabled: true,\n products: ECOSYSTEM_PRODUCTS.map((p) => ({\n slug: p.slug,\n name: p.name,\n tagline: null,\n website: p.websiteUrl,\n })),\n examplePrompts: examplePrompts?.length\n ? examplePrompts\n : DEFAULT_EXPLORE_EXAMPLE_PROMPTS,\n welcomeTitle: FALLBACK_WELCOME_TITLE,\n welcomeBody: FALLBACK_WELCOME_BODY,\n limits: FALLBACK_EXPLORE_LIMITS,\n captchaRequired: false,\n recaptchaSiteKey: null,\n };\n}\n\n/**\n * Harden a server catalog against partial/degraded responses so a missing\n * field can never blank the page or produce `maxMessageLength: 0` (which would\n * silently disable the composer).\n */\nfunction normalizeCatalog(\n raw: ExploreCatalog,\n fallback: ExploreCatalog,\n): ExploreCatalog {\n return {\n enabled: raw.enabled !== false,\n products: raw.products?.length ? raw.products : fallback.products,\n examplePrompts: raw.examplePrompts?.length\n ? raw.examplePrompts\n : fallback.examplePrompts,\n welcomeTitle: raw.welcomeTitle || fallback.welcomeTitle,\n welcomeBody: raw.welcomeBody || fallback.welcomeBody,\n limits: {\n maxMessageLength:\n raw.limits?.maxMessageLength || fallback.limits.maxMessageLength,\n maxTurnsPerConversation:\n raw.limits?.maxTurnsPerConversation ||\n fallback.limits.maxTurnsPerConversation,\n messagesPerDay:\n raw.limits?.messagesPerDay || fallback.limits.messagesPerDay,\n historyTurns: raw.limits?.historyTurns || fallback.limits.historyTurns,\n },\n captchaRequired: raw.captchaRequired === true,\n recaptchaSiteKey: raw.recaptchaSiteKey ?? null,\n };\n}\n\nconst RATE_LIMIT_CODES = new Set([\n \"RATE_LIMITED\",\n \"HTTP_429\",\n \"EXPLORE_GLOBAL_LIMIT\",\n]);\nconst CAPTCHA_CODES = new Set([\"CAPTCHA_FAILED\", \"CAPTCHA_REQUIRED\"]);\nconst NETWORK_CODES = new Set([\n \"NETWORK_ERROR\",\n \"UPSTREAM_UNAVAILABLE\",\n \"CONVERSATION_BUSY\",\n \"PROVIDER_ERROR\",\n \"QUEUE_FULL\",\n]);\nconst VALIDATION_CODES = new Set([\n \"MESSAGE_TOO_LONG\",\n \"MESSAGE_EMPTY\",\n \"CONVERSATION_LIMIT\",\n \"INVALID_INPUT\",\n]);\n\n/**\n * Map a `extensions.code` (or a client-side transport code) onto the bucket the\n * UI renders. Unknown codes are treated as retryable — a transient backend\n * condition we have not enumerated is far more likely than a permanent one.\n */\nexport function classifyExploreError(\n code: string | null | undefined,\n serverMessage?: string | null,\n): ExploreChatError {\n const c = code ?? \"UNKNOWN\";\n if (RATE_LIMIT_CODES.has(c)) {\n return {\n kind: \"rate-limit\",\n code: c,\n message:\n \"You've reached the message limit for now. Please try again later.\",\n retryable: false,\n };\n }\n if (CAPTCHA_CODES.has(c)) {\n return {\n kind: \"captcha\",\n code: c,\n message:\n \"We couldn't verify that you're human. Please try sending that again.\",\n retryable: true,\n };\n }\n if (c === \"TIMEOUT\" || c === \"TOOL_BUDGET\") {\n return {\n kind: \"timeout\",\n code: c,\n message: \"That answer took too long to come back. Try asking again.\",\n retryable: true,\n };\n }\n if (NETWORK_CODES.has(c)) {\n return {\n kind: \"network\",\n code: c,\n message:\n \"We couldn't reach the assistant just now. Check your connection and try again.\",\n retryable: true,\n };\n }\n if (c === \"EXPLORE_DISABLED\") {\n return {\n kind: \"disabled\",\n code: c,\n message: \"Explore is unavailable at the moment. Please check back soon.\",\n retryable: false,\n };\n }\n if (VALIDATION_CODES.has(c)) {\n return {\n kind: \"validation\",\n code: c,\n message: serverMessage || \"That message couldn't be sent.\",\n retryable: false,\n };\n }\n if (c === \"EMPTY_ANSWER\") {\n return {\n kind: \"unknown\",\n code: c,\n message:\n \"No answer came back for that one. Try rephrasing, or ask something more specific.\",\n retryable: true,\n };\n }\n return {\n kind: \"unknown\",\n code: c,\n message: serverMessage || \"Something went wrong. Please try again.\",\n retryable: true,\n };\n}\n\ninterface PersistedExploreState {\n conversationToken: string | null;\n messages: ExploreMessage[];\n focusProduct: string | null;\n}\n\nfunction readPersisted(key: string): PersistedExploreState | null {\n // SSR / prerender: there is no sessionStorage, and reading one during the\n // first client render would desync hydration anyway.\n if (typeof window === \"undefined\") return null;\n try {\n const raw = window.sessionStorage.getItem(key);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n if (!parsed || typeof parsed !== \"object\") return null;\n const record = parsed as Partial<PersistedExploreState>;\n return {\n conversationToken:\n typeof record.conversationToken === \"string\"\n ? record.conversationToken\n : null,\n messages: Array.isArray(record.messages)\n ? record.messages.slice(-MAX_PERSISTED_MESSAGES)\n : [],\n focusProduct:\n typeof record.focusProduct === \"string\" ? record.focusProduct : null,\n };\n } catch {\n /* corrupt or unavailable storage — start a fresh conversation */\n return null;\n }\n}\n\n/**\n * A turn that never produced any text is worth dropping rather than rendering\n * as an empty bubble — used by `stop()` and by the failure paths.\n */\nfunction visibleText(message: ExploreMessage): string {\n return message.content || message.partialContent || \"\";\n}\n\nfunction countUserTurns(messages: ExploreMessage[]): number {\n return messages.filter((m) => m.role === \"USER\").length;\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useExploreChat(\n options: UseExploreChatOptions = {},\n): UseExploreChatResult {\n const {\n productSlug,\n pageUrl,\n locale,\n examplePrompts,\n pollIntervalMs = DEFAULT_POLL_INTERVAL_MS,\n pollTimeoutMs = DEFAULT_POLL_TIMEOUT_MS,\n storageKey = DEFAULT_STORAGE_KEY,\n persist = true,\n onSend,\n } = options;\n\n const client = useWebSDK();\n\n // The fallback catalog is the initial value AND the merge base for the\n // server response. Keyed on the prompt CONTENT, not the array identity —\n // a consumer passing an inline `examplePrompts={[...]}` literal would\n // otherwise rebuild it every render and re-fire the catalog effect.\n const promptKey = JSON.stringify(examplePrompts ?? []);\n const fallbackCatalog = useMemo(\n () => buildFallbackCatalog(JSON.parse(promptKey) as string[]),\n [promptKey],\n );\n\n const [catalog, setCatalog] = useState<ExploreCatalog>(fallbackCatalog);\n const [messages, setMessages] = useState<ExploreMessage[]>([]);\n const [phase, setPhase] = useState<ExploreChatPhase>(\"loading\");\n const [error, setError] = useState<ExploreChatError | null>(null);\n const [remainingToday, setRemainingToday] = useState<number | null>(null);\n const [focusProduct, setFocusProductState] = useState<string | null>(null);\n const [turnCount, setTurnCount] = useState(0);\n const [hydrated, setHydrated] = useState(false);\n\n // Refs mirror the state that async callbacks read, so `send`/`poll` never\n // close over a stale value and never need to be re-created mid-flight.\n const mountedRef = useRef(true);\n const pollGenerationRef = useRef(0);\n const pollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const conversationTokenRef = useRef<string | null>(null);\n const catalogRef = useRef<ExploreCatalog>(fallbackCatalog);\n const turnCountRef = useRef(0);\n const focusProductRef = useRef<string | null>(null);\n const lastSentTextRef = useRef<string | null>(null);\n const inFlightRef = useRef(false);\n\n catalogRef.current = catalog;\n\n const clearPollTimer = useCallback(() => {\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n }, []);\n\n /** Invalidate any running poll chain. Late responses become no-ops. */\n const cancelPolling = useCallback(() => {\n pollGenerationRef.current += 1;\n clearPollTimer();\n }, [clearPollTimer]);\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n pollGenerationRef.current += 1;\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n };\n }, []);\n\n // --------------------------------------------------------------------------\n // Hydrate from sessionStorage (effect, not lazy state, so the FIRST client\n // render matches the prerendered HTML and hydration stays clean).\n // --------------------------------------------------------------------------\n useEffect(() => {\n if (!persist) {\n setHydrated(true);\n return;\n }\n const stored = readPersisted(storageKey);\n if (stored) {\n conversationTokenRef.current = stored.conversationToken;\n focusProductRef.current = stored.focusProduct;\n // A turn that was still streaming when the tab was closed can never be\n // resumed from here — the poll chain is gone. Land it as-is.\n const settled = stored.messages.flatMap<ExploreMessage>((m) => {\n if (m.role !== \"ASSISTANT\") return [m];\n if (m.status !== \"PENDING\" && m.status !== \"RUNNING\") return [m];\n const text = visibleText(m);\n if (!text) return [];\n return [{ ...m, status: \"COMPLETED\", content: text }];\n });\n setMessages(settled);\n setFocusProductState(stored.focusProduct);\n const turns = countUserTurns(settled);\n turnCountRef.current = turns;\n setTurnCount(turns);\n }\n setHydrated(true);\n }, [persist, storageKey]);\n\n // --------------------------------------------------------------------------\n // Persist (after hydration, so the initial empty state never wipes storage).\n // --------------------------------------------------------------------------\n useEffect(() => {\n if (!persist || !hydrated || typeof window === \"undefined\") return;\n try {\n const payload: PersistedExploreState = {\n conversationToken: conversationTokenRef.current,\n messages: messages.slice(-MAX_PERSISTED_MESSAGES),\n focusProduct,\n };\n // Nothing worth restoring (fresh page, or just after reset()): drop the\n // key entirely rather than leaving an empty husk behind.\n if (\n !payload.conversationToken &&\n payload.messages.length === 0 &&\n !payload.focusProduct\n ) {\n window.sessionStorage.removeItem(storageKey);\n return;\n }\n window.sessionStorage.setItem(storageKey, JSON.stringify(payload));\n } catch {\n /* private mode / quota exceeded — persistence is a nicety, not a feature */\n }\n }, [persist, hydrated, storageKey, messages, focusProduct]);\n\n // --------------------------------------------------------------------------\n // Catalog. Cached (the default) — it is per-page-load configuration, not a\n // poll. A failure keeps the fallback so the page NEVER renders blank.\n // --------------------------------------------------------------------------\n useEffect(() => {\n let cancelled = false;\n const load = async () => {\n const res = await client.query<ExploreCatalogQueryData>(\n EXPLORE_CATALOG_QUERY,\n { productSlug: productSlug ?? null },\n );\n if (cancelled || !mountedRef.current) return;\n\n const raw = res.data?.exploreCatalog;\n if (res.errors?.length || !raw) {\n console.warn(\n \"[WebSDK] exploreCatalog unavailable — using the built-in fallback catalog\",\n res.errors?.[0]?.message,\n );\n setPhase((prev) => (prev === \"loading\" ? \"ready\" : prev));\n return;\n }\n\n const next = normalizeCatalog(raw, fallbackCatalog);\n setCatalog(next);\n catalogRef.current = next;\n setPhase((prev) => {\n if (!next.enabled) return \"disabled\";\n return prev === \"loading\" ? \"ready\" : prev;\n });\n };\n void load();\n return () => {\n cancelled = true;\n };\n }, [client, productSlug, fallbackCatalog]);\n\n // --------------------------------------------------------------------------\n // Poll chain\n // --------------------------------------------------------------------------\n const startPolling = useCallback(\n (conversationToken: string, messageId: string) => {\n pollGenerationRef.current += 1;\n const generation = pollGenerationRef.current;\n const startedAt = Date.now();\n let consecutiveFailures = 0;\n\n const isStale = () =>\n !mountedRef.current || generation !== pollGenerationRef.current;\n\n const finishWithError = (chatError: ExploreChatError) => {\n inFlightRef.current = false;\n setMessages((prev) =>\n prev.flatMap<ExploreMessage>((m) => {\n if (m.id !== messageId) return [m];\n const text = visibleText(m);\n if (!text) return [];\n return [{ ...m, status: \"FAILED\", content: text }];\n }),\n );\n setError(chatError);\n setPhase(chatError.kind === \"rate-limit\" ? \"limited\" : \"error\");\n };\n\n const tick = async () => {\n if (isStale()) return;\n\n if (Date.now() - startedAt > pollTimeoutMs) {\n finishWithError(classifyExploreError(\"TIMEOUT\"));\n return;\n }\n\n // `cache: false` is load-bearing — see CONTRACT.md §4.\n const res = await client.query<ExploreMessageQueryData>(\n EXPLORE_MESSAGE_QUERY,\n { conversationToken, id: messageId },\n { cache: false, timeoutMs: POLL_REQUEST_TIMEOUT_MS },\n );\n if (isStale()) return;\n\n const first = res.errors?.[0];\n if (first) {\n const code =\n typeof first.extensions?.code === \"string\"\n ? first.extensions.code\n : undefined;\n const classified = classifyExploreError(code, first.message);\n // Hard stops: retrying a rate limit or a disabled feature is pointless.\n if (!classified.retryable) {\n finishWithError(classified);\n return;\n }\n consecutiveFailures += 1;\n if (consecutiveFailures >= MAX_CONSECUTIVE_POLL_FAILURES) {\n finishWithError(classified);\n return;\n }\n pollTimerRef.current = setTimeout(() => void tick(), pollIntervalMs);\n return;\n }\n\n const message = res.data?.exploreMessage;\n if (!message) {\n // Can happen briefly right after submit; tolerate a few misses.\n consecutiveFailures += 1;\n if (consecutiveFailures >= MAX_CONSECUTIVE_POLL_FAILURES) {\n finishWithError(classifyExploreError(\"NOT_FOUND\"));\n return;\n }\n pollTimerRef.current = setTimeout(() => void tick(), pollIntervalMs);\n return;\n }\n\n consecutiveFailures = 0;\n // Replace in place so `partialContent` renders as it streams.\n setMessages((prev) =>\n prev.map((m) => (m.id === messageId ? message : m)),\n );\n\n if (message.status === \"COMPLETED\") {\n inFlightRef.current = false;\n setError(null);\n setPhase(\"ready\");\n return;\n }\n if (message.status === \"FAILED\") {\n finishWithError(\n classifyExploreError(message.errorCode ?? \"UPSTREAM_UNAVAILABLE\"),\n );\n return;\n }\n\n setPhase(\"streaming\");\n pollTimerRef.current = setTimeout(() => void tick(), pollIntervalMs);\n };\n\n // First poll after one interval — the turn cannot possibly be done sooner.\n pollTimerRef.current = setTimeout(() => void tick(), pollIntervalMs);\n },\n [client, pollIntervalMs, pollTimeoutMs],\n );\n\n // --------------------------------------------------------------------------\n // send\n // --------------------------------------------------------------------------\n const submit = useCallback(\n async (\n text: string,\n optimisticId: string,\n captchaAttempt: number,\n ): Promise<void> => {\n const activeCatalog = catalogRef.current;\n\n let recaptchaToken: string | undefined;\n if (activeCatalog.captchaRequired && activeCatalog.recaptchaSiteKey) {\n try {\n recaptchaToken = await getRecaptchaV3Token(\n activeCatalog.recaptchaSiteKey,\n );\n } catch (err) {\n console.warn(\"[WebSDK] reCAPTCHA v3 token could not be minted\", err);\n // Send without a token and let the backend decide — it owns the\n // policy, and a blocked third-party script must not silently kill\n // the whole feature.\n }\n }\n\n const input: SendExploreMessageInput = {\n message: text,\n ...(conversationTokenRef.current\n ? { conversationToken: conversationTokenRef.current }\n : {}),\n ...(focusProductRef.current || productSlug\n ? { productSlug: focusProductRef.current ?? productSlug }\n : {}),\n ...(recaptchaToken ? { recaptchaToken } : {}),\n ...(locale ? { locale } : {}),\n ...(pageUrl ? { pageUrl } : {}),\n };\n\n const res = await client.mutate<SendExploreMessageMutationData>(\n SEND_EXPLORE_MESSAGE_MUTATION,\n { input },\n { timeoutMs: SEND_REQUEST_TIMEOUT_MS },\n );\n if (!mountedRef.current) return;\n\n const first = res.errors?.[0];\n const result = res.data?.sendExploreMessage;\n\n if (first || !result) {\n const code =\n typeof first?.extensions?.code === \"string\"\n ? first.extensions.code\n : undefined;\n const classified = classifyExploreError(code, first?.message);\n\n // CAPTCHA_FAILED: one silent re-mint + re-send before bothering the\n // visitor. v3 tokens expire in ~2 minutes and are single-use, so a\n // stale one is a routine, self-healing failure.\n if (classified.kind === \"captcha\" && captchaAttempt === 0) {\n await submit(text, optimisticId, 1);\n return;\n }\n\n inFlightRef.current = false;\n setError(classified);\n setPhase(classified.kind === \"rate-limit\" ? \"limited\" : \"error\");\n return;\n }\n\n conversationTokenRef.current = result.conversation.token;\n turnCountRef.current = result.conversation.turnCount;\n setTurnCount(result.conversation.turnCount);\n setRemainingToday(result.remainingToday ?? null);\n\n const userMessage = result.userMessage;\n const assistantMessage = result.assistantMessage;\n\n // Swap the optimistic user bubble for the server's, then append the\n // PENDING assistant turn that the poll chain will fill in. The `some`\n // guard keeps the visitor's words on screen even in the impossible case\n // where the optimistic bubble is already gone.\n setMessages((prev) => {\n const replaced = prev.some((m) => m.id === optimisticId)\n ? prev.map((m) => (m.id === optimisticId ? userMessage : m))\n : [...prev, userMessage];\n return [...replaced, assistantMessage];\n });\n\n if (\n assistantMessage.status === \"COMPLETED\" ||\n assistantMessage.status === \"FAILED\"\n ) {\n inFlightRef.current = false;\n if (assistantMessage.status === \"FAILED\") {\n const classified = classifyExploreError(\n assistantMessage.errorCode ?? \"UPSTREAM_UNAVAILABLE\",\n );\n setError(classified);\n setPhase(\"error\");\n } else {\n setPhase(\"ready\");\n }\n return;\n }\n\n setPhase(\"streaming\");\n startPolling(result.conversation.token, assistantMessage.id);\n },\n [client, locale, pageUrl, productSlug, startPolling],\n );\n\n const send = useCallback(\n async (message: string): Promise<void> => {\n const text = message.trim();\n if (!text) return;\n if (inFlightRef.current) return;\n\n const activeCatalog = catalogRef.current;\n if (!activeCatalog.enabled) {\n setError(classifyExploreError(\"EXPLORE_DISABLED\"));\n setPhase(\"disabled\");\n return;\n }\n if (text.length > activeCatalog.limits.maxMessageLength) {\n setError({\n kind: \"validation\",\n code: \"MESSAGE_TOO_LONG\",\n message: `That message is ${text.length} characters — the limit is ${activeCatalog.limits.maxMessageLength}.`,\n retryable: false,\n });\n return;\n }\n if (\n turnCountRef.current >= activeCatalog.limits.maxTurnsPerConversation\n ) {\n setError({\n kind: \"validation\",\n code: \"CONVERSATION_LIMIT\",\n message: `This conversation has reached its ${activeCatalog.limits.maxTurnsPerConversation}-message limit. Start a new chat to keep going.`,\n retryable: false,\n });\n return;\n }\n\n inFlightRef.current = true;\n lastSentTextRef.current = text;\n setError(null);\n setPhase(\"sending\");\n cancelPolling();\n\n // Optimistic user bubble — the composer clears instantly instead of\n // waiting a network round-trip for the visitor's own words.\n const optimistic: ExploreMessage = {\n id: makeOptimisticId(),\n conversationId: conversationTokenRef.current ?? \"pending\",\n role: \"USER\",\n status: \"COMPLETED\",\n content: text,\n partialContent: null,\n activity: [],\n references: [],\n ctas: [],\n errorCode: null,\n createdAt: new Date().toISOString(),\n completedAt: new Date().toISOString(),\n };\n setMessages((prev) => [...prev, optimistic]);\n turnCountRef.current += 1;\n setTurnCount(turnCountRef.current);\n onSend?.(text);\n\n try {\n await submit(text, optimistic.id, 0);\n } catch (err) {\n if (!mountedRef.current) return;\n console.error(\"[WebSDK] Explore send failed\", err);\n inFlightRef.current = false;\n setError(classifyExploreError(\"NETWORK_ERROR\"));\n setPhase(\"error\");\n }\n },\n [cancelPolling, onSend, submit],\n );\n\n const stop = useCallback(() => {\n cancelPolling();\n inFlightRef.current = false;\n setMessages((prev) =>\n prev.flatMap<ExploreMessage>((m) => {\n if (m.role !== \"ASSISTANT\") return [m];\n if (m.status !== \"PENDING\" && m.status !== \"RUNNING\") return [m];\n const text = visibleText(m);\n // Nothing streamed yet — drop the placeholder instead of leaving an\n // empty bubble behind.\n if (!text) return [];\n return [\n {\n ...m,\n status: \"COMPLETED\",\n content: text,\n completedAt: new Date().toISOString(),\n },\n ];\n }),\n );\n setPhase((prev) =>\n prev === \"sending\" || prev === \"streaming\" ? \"ready\" : prev,\n );\n }, [cancelPolling]);\n\n const retry = useCallback(() => {\n const text = lastSentTextRef.current;\n if (!text) return;\n cancelPolling();\n inFlightRef.current = false;\n // Drop the failed turn (and the user bubble that produced it) so the retry\n // does not stack a duplicate pair into the transcript.\n setMessages((prev) => {\n const next = [...prev];\n const last = next[next.length - 1];\n if (last?.role === \"ASSISTANT\" && last.status === \"FAILED\") next.pop();\n const prior = next[next.length - 1];\n if (prior?.role === \"USER\" && prior.content === text) next.pop();\n return next;\n });\n turnCountRef.current = Math.max(0, turnCountRef.current - 1);\n setTurnCount(turnCountRef.current);\n void send(text);\n }, [cancelPolling, send]);\n\n const reset = useCallback(() => {\n cancelPolling();\n inFlightRef.current = false;\n conversationTokenRef.current = null;\n lastSentTextRef.current = null;\n turnCountRef.current = 0;\n setTurnCount(0);\n setMessages([]);\n setError(null);\n setRemainingToday(null);\n setPhase(catalogRef.current.enabled ? \"ready\" : \"disabled\");\n if (typeof window !== \"undefined\") {\n try {\n window.sessionStorage.removeItem(storageKey);\n } catch {\n /* storage unavailable — nothing to clear */\n }\n }\n }, [cancelPolling, storageKey]);\n\n const setFocusProduct = useCallback((slug: string | null) => {\n focusProductRef.current = slug;\n setFocusProductState(slug);\n }, []);\n\n const activity = useMemo<string | null>(() => {\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const m = messages[i];\n if (!m || m.role !== \"ASSISTANT\") continue;\n if (m.status !== \"PENDING\" && m.status !== \"RUNNING\") return null;\n const lines = m.activity ?? [];\n return lines.length ? (lines[lines.length - 1] ?? null) : null;\n }\n return null;\n }, [messages]);\n\n const canSend =\n (phase === \"ready\" || phase === \"error\") &&\n catalog.enabled &&\n turnCount < catalog.limits.maxTurnsPerConversation;\n\n return {\n phase,\n catalog,\n messages,\n activity,\n remainingToday,\n error,\n focusProduct,\n setFocusProduct,\n send,\n stop,\n retry,\n reset,\n canSend,\n };\n}\n\n/**\n * Client-only id for the optimistic user bubble, swapped for the server's\n * `userMessage.id` as soon as the mutation resolves. The counter only has to\n * make ids unique within a tab, never across one.\n */\nlet optimisticCounter = 0;\n\nfunction makeOptimisticId(): string {\n optimisticCounter += 1;\n return `boff-explore-local-${Date.now()}-${optimisticCounter}`;\n}\n"]}