@smooai/chat-widget 0.5.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Citation } from "@smooai/smooth-operator";
2
+ import { StoreApi } from "zustand/vanilla";
2
3
 
3
4
  //#region src/config.d.ts
4
5
  /**
@@ -68,6 +69,17 @@ interface ChatWidgetConfig {
68
69
  userEmail?: string;
69
70
  /** Optional phone number for the user participant (passed via session metadata). */
70
71
  userPhone?: string;
72
+ /**
73
+ * Optional pre-auth HMAC context. When the host page has a shared secret with
74
+ * the agent, it can sign `{ userId, signature, timestamp }` so the chat-ws
75
+ * wrapper's `/internal/*` identity routes (and the WS create path) verify the
76
+ * caller without an OTP round-trip (ADR-046/ADR-048). Passed through verbatim.
77
+ */
78
+ authContext?: {
79
+ userId: string;
80
+ signature: string;
81
+ timestamp: number;
82
+ };
71
83
  /** Placeholder text for the message input. */
72
84
  placeholder?: string;
73
85
  /** Greeting rendered when the conversation opens (before any messages). */
@@ -87,6 +99,24 @@ interface ChatWidgetConfig {
87
99
  requireEmail?: boolean;
88
100
  /** Require the visitor's phone before chatting. */
89
101
  requirePhone?: boolean;
102
+ /**
103
+ * Show the phone field on the pre-chat form (optional unless {@link requirePhone}).
104
+ * Defaults to `true` for this widget — phone rides the session metadata as
105
+ * `userPhone` so the agent can follow up by SMS. Set `false` to hide it.
106
+ */
107
+ collectPhone?: boolean;
108
+ /**
109
+ * Show the email + SMS marketing-consent checkboxes on the pre-chat form.
110
+ * Explicit opt-in, default UNCHECKED; a `consentAt` timestamp is stamped when
111
+ * a box is ticked. Defaults to `true`. The consent record is threaded into the
112
+ * session metadata (ADR-048).
113
+ */
114
+ collectConsent?: boolean;
115
+ /**
116
+ * Offer the cross-device "Restore my chats" affordance — an explicit link that
117
+ * runs the identity-OTP → resolve → replay flow. Defaults to `true`.
118
+ */
119
+ allowChatRestore?: boolean;
90
120
  /**
91
121
  * Let visitors chat without providing any identity. When `true`, the
92
122
  * `require*` flags are ignored and the pre-chat form is skipped.
@@ -113,9 +143,17 @@ declare class SmoothAgentChatElement extends HTMLElement {
113
143
  private hasSent;
114
144
  /** Starter prompts shown as chips in the empty state. */
115
145
  private examplePrompts;
146
+ /** Resolved greeting text, cached so async (rAF) renders can reuse it. */
147
+ private greeting;
116
148
  /** Current mid-turn interrupt (OTP / tool-confirmation), or null. */
117
149
  private interrupt;
118
150
  private interruptEl;
151
+ /** Cross-device "restore my chats" flow state (ADR-048 §c). */
152
+ private identityRestore;
153
+ /** Whether the cross-device restore affordance is offered (config). */
154
+ private allowChatRestore;
155
+ /** True while the pre-chat identity gate is showing (blocks premature connect). */
156
+ private gating;
119
157
  private panelEl;
120
158
  private launcherEl;
121
159
  private messagesEl;
@@ -123,6 +161,15 @@ declare class SmoothAgentChatElement extends HTMLElement {
123
161
  private dotEl;
124
162
  private inputEl;
125
163
  private sendBtn;
164
+ /** The live streaming assistant bubble whose textContent the rAF loop drives. */
165
+ private streamBubbleEl;
166
+ /** Message id the reveal is bound to (guards against stale frames after rebuilds). */
167
+ private streamMsgId;
168
+ /** Full buffered target text for the streaming message (grows as tokens arrive). */
169
+ private streamTarget;
170
+ /** How many chars of {@link streamTarget} are currently shown. */
171
+ private displayedLength;
172
+ private rafId;
126
173
  constructor();
127
174
  connectedCallback(): void;
128
175
  disconnectedCallback(): void;
@@ -144,14 +191,63 @@ declare class SmoothAgentChatElement extends HTMLElement {
144
191
  * set via `textContent` (never innerHTML); only static icons use innerHTML.
145
192
  */
146
193
  private renderInterrupt;
147
- /** Collect identity from the pre-chat form, then drop into the chat view. */
194
+ /**
195
+ * Build the cross-device "Restore my chats" card (ADR-048 §c). Reuses the
196
+ * same overlay slot + visual language as the OTP interrupt. All server-supplied
197
+ * strings (masked destination, conversation previews) are set via `textContent`
198
+ * — never innerHTML — so they can't inject markup; only the static lock icon
199
+ * uses innerHTML.
200
+ */
201
+ private buildRestoreCard;
202
+ /** Format an ISO timestamp as a short, locale-aware label (best-effort). */
203
+ private formatWhen;
204
+ /** Collect identity + consent from the pre-chat form, then drop into the chat view. */
148
205
  private handlePrechatSubmit;
149
206
  /** Send a starter prompt (from a chip click). */
150
207
  private submitPrompt;
151
208
  private syncOpenState;
152
209
  /** Grow the textarea with its content, up to the CSS max-height. */
153
210
  private autosize;
211
+ /**
212
+ * Receive a new message snapshot from the controller and update the view.
213
+ *
214
+ * `onMessages` fires on *every* `stream_token` delta. Rebuilding the whole
215
+ * list each frame is wasteful and fights the smooth reveal, so we take the
216
+ * cheap path when the only change is the trailing streaming assistant message
217
+ * growing: just bump the reveal *target* (the rAF loop drains it). Any
218
+ * structural change (new message, finalize, citations) triggers a full
219
+ * rebuild via {@link renderMessages}.
220
+ */
221
+ private handleMessages;
154
222
  private renderMessages;
223
+ /** True when the host/user prefers reduced motion (snap, no typewriter). */
224
+ private prefersReducedMotion;
225
+ /**
226
+ * Bind the rAF typewriter to a freshly built streaming bubble. Preserves the
227
+ * already-revealed prefix across rebuilds (so a structural rebuild mid-stream
228
+ * doesn't restart the reveal from zero), then resumes the loop.
229
+ */
230
+ private bindReveal;
231
+ /** Start the rAF loop if it isn't already running. */
232
+ private ensureRevealLoop;
233
+ /**
234
+ * One animation frame of the reveal. Advances `displayedLength` toward the
235
+ * buffered target at an ADAPTIVE rate — the deeper the backlog, the more
236
+ * chars per frame — so the reveal stays smooth yet never falls behind the
237
+ * network. Updates ONLY the bound bubble's textContent (no list rebuild).
238
+ */
239
+ private tickReveal;
240
+ /** Snap the bound bubble to the full buffered text immediately (reduced-motion / no-rAF). */
241
+ private snapReveal;
242
+ /** Cancel any in-flight reveal loop and clear its state (called on full rebuild). */
243
+ private resetReveal;
244
+ /**
245
+ * Auto-scroll the message list to the bottom — but don't fight a visitor who
246
+ * has scrolled up to read history. When `force` (a structural rebuild) we
247
+ * always pin to bottom; during the streaming reveal we only follow if the
248
+ * viewport is already near the bottom.
249
+ */
250
+ private scrollToBottom;
155
251
  /** Wrap a bubble in a `.row`, prefixing assistant rows with a mini avatar. */
156
252
  private buildRow;
157
253
  private greetingBubble;
@@ -229,7 +325,86 @@ declare function mountFullPageChat(config: Omit<ChatWidgetConfig, 'mode'>, targe
229
325
  */
230
326
  declare function initChatWidgetLoader(): void;
231
327
  //#endregion
328
+ //#region src/persistence.d.ts
329
+ /** Current persisted-shape version. Bump when the shape below changes incompatibly. */
330
+ declare const PERSIST_VERSION: 1;
331
+ /** Marketing-consent record captured at the pre-chat form. */
332
+ interface ConsentState {
333
+ emailOptIn: boolean;
334
+ smsOptIn: boolean;
335
+ /** Where the consent was captured. The widget always stamps `chat-widget-prechat`. */
336
+ consentSource?: string;
337
+ /** ISO 8601 timestamp stamped when the visitor ticked a consent box. */
338
+ consentAt?: string;
339
+ }
340
+ /** Visitor identity collected from config or the pre-chat form. */
341
+ interface IdentityState {
342
+ name?: string;
343
+ email?: string;
344
+ phone?: string;
345
+ }
346
+ /**
347
+ * The exact persisted shape (ADR-048 §d). Only the pointer + identity + consent
348
+ * persist — never the transcript.
349
+ */
350
+ interface PersistedWidgetState {
351
+ version: typeof PERSIST_VERSION;
352
+ /** Pointer to the active conversation session; cleared on ended/404. */
353
+ sessionId: string | null;
354
+ identity: IdentityState;
355
+ consent: ConsentState;
356
+ /**
357
+ * Email proven via OTP for the CURRENT session. Session-scoped: cleared on
358
+ * `clearSession()` so it can't leak across visitors on a shared browser, and
359
+ * only threaded into session metadata when {@link verifiedEmailSessionId}
360
+ * matches the live session (i.e. on resume of the verified session) — never
361
+ * auto-stamped onto a brand-new session.
362
+ */
363
+ verifiedEmail: string | null;
364
+ /** The sessionId the {@link verifiedEmail} was proven against (binds the proof to one session). */
365
+ verifiedEmailSessionId: string | null;
366
+ /** Stable per-browser correlation token (see fingerprint.ts). */
367
+ browserFingerprint: string | null;
368
+ }
369
+ /** Store actions layered on top of the persisted state. */
370
+ interface WidgetStoreActions {
371
+ setSessionId: (sessionId: string | null) => void;
372
+ /** Merge identity fields (undefined values don't clobber existing ones). */
373
+ mergeIdentity: (identity: IdentityState) => void;
374
+ /** Replace consent wholesale (the pre-chat form computes the full record). */
375
+ setConsent: (consent: ConsentState) => void;
376
+ /** Record an OTP-proven email bound to a specific session. */
377
+ setVerifiedEmail: (email: string | null, sessionId?: string | null) => void;
378
+ setBrowserFingerprint: (fp: string) => void;
379
+ /**
380
+ * Clear the session pointer (and the session-scoped `verifiedEmail` proof) but
381
+ * KEEP identity / consent / fingerprint — used when a persisted session has
382
+ * ended or 404s so the next turn starts a fresh session for a known visitor.
383
+ * `verifiedEmail` is deliberately cleared here: it is a per-session OTP proof,
384
+ * not a durable identity, so it must NOT survive onto a new session (which on a
385
+ * shared browser could be a different visitor).
386
+ */
387
+ clearSession: () => void;
388
+ }
389
+ type WidgetStore = PersistedWidgetState & WidgetStoreActions;
390
+ /** localStorage key for an agent's persisted widget state. */
391
+ declare function storageKey(agentId: string): string;
392
+ /**
393
+ * Create the per-agent persisted Zustand store. The `partialize` step ensures
394
+ * only the persisted shape (never any future transient action/UI state) is
395
+ * written to localStorage.
396
+ */
397
+ declare function createWidgetStore(agentId: string): StoreApi<WidgetStore>;
398
+ //#endregion
232
399
  //#region src/conversation.d.ts
400
+ /**
401
+ * Derive the HTTP base for the chat-ws wrapper's `/internal/*` REST routes from
402
+ * the WS endpoint: `wss://ai.smoo.ai/ws` → `https://ai.smoo.ai`. The engine
403
+ * (smooth-operator 1.8.0) owns the `/ws` dispatch and REJECTS unknown verbs, so
404
+ * the cross-device identity flow + fingerprint resume are HTTP POST routes on the
405
+ * wrapper (origin-allowlisted + authContext, per ADR-046/ADR-048) — NOT WS frames.
406
+ */
407
+ declare function httpBaseFromWsEndpoint(endpoint: string): string | null;
233
408
  type Role = 'user' | 'assistant';
234
409
  interface ChatMessage {
235
410
  id: string;
@@ -275,7 +450,56 @@ interface UserInfo {
275
450
  name?: string;
276
451
  email?: string;
277
452
  phone?: string;
453
+ /** Marketing-consent opt-ins captured at the pre-chat form (ADR-048). */
454
+ consent?: {
455
+ emailOptIn: boolean;
456
+ smsOptIn: boolean;
457
+ };
458
+ }
459
+ /** One conversation surfaced by `resolve_identity` for the cross-device picker. */
460
+ interface RestorableConversation {
461
+ conversationId: string;
462
+ sessionId: string;
463
+ lastActivityAt?: string;
464
+ preview?: string;
278
465
  }
466
+ /**
467
+ * State machine for the cross-device "restore my chats" flow. Driven by the three
468
+ * HTTP POST routes on the chat-ws wrapper — `/internal/identity/request-otp` →
469
+ * `/internal/identity/verify-otp` → `/internal/identity/resolve` (ADR-048 §c).
470
+ * The view renders a panel off this.
471
+ */
472
+ type IdentityRestore = {
473
+ phase: 'idle';
474
+ } /** UI-local: the email-entry step before any request is sent. */ | {
475
+ phase: 'awaiting_email';
476
+ error?: string;
477
+ } | {
478
+ phase: 'requesting';
479
+ email: string;
480
+ channel: 'email' | 'sms';
481
+ } | {
482
+ phase: 'awaiting_code';
483
+ email: string;
484
+ channel: 'email' | 'sms';
485
+ maskedDestination?: string;
486
+ error?: string;
487
+ attemptsRemaining?: number;
488
+ } | {
489
+ phase: 'verifying';
490
+ email: string;
491
+ channel: 'email' | 'sms';
492
+ } | {
493
+ phase: 'resolving';
494
+ email: string;
495
+ } | {
496
+ phase: 'resolved';
497
+ email: string;
498
+ conversations: RestorableConversation[];
499
+ } | {
500
+ phase: 'error';
501
+ message: string;
502
+ };
279
503
  interface ConversationEvents {
280
504
  /** Fired whenever the message list changes (append, token delta, finalize). */
281
505
  onMessages: (messages: ChatMessage[]) => void;
@@ -283,25 +507,51 @@ interface ConversationEvents {
283
507
  onStatus: (status: ConnectionStatus, detail?: string) => void;
284
508
  /** Fired when a turn pauses for OTP / tool-confirmation, and `null` when it clears. */
285
509
  onInterrupt?: (interrupt: Interrupt | null) => void;
510
+ /** Fired on cross-device identity-restore state transitions. */
511
+ onIdentityRestore?: (state: IdentityRestore) => void;
286
512
  }
287
513
  declare class ConversationController {
288
514
  private readonly config;
289
515
  private readonly events;
516
+ private readonly store;
290
517
  private client;
291
518
  private sessionId;
292
519
  private readonly messages;
293
520
  private status;
294
521
  private seq;
295
- /** Visitor identity, seeded from config and updated by the pre-chat form. */
296
- private identity;
297
522
  /** requestId of the in-flight turn — used to resume OTP / tool confirmations. */
298
523
  private activeRequestId;
299
524
  private interrupt;
300
- constructor(config: ChatWidgetConfig, events: ConversationEvents);
525
+ private identityRestore;
526
+ /**
527
+ * True once the resume probe (persisted-pointer get_session OR the
528
+ * `/internal/resume-by-fingerprint` POST) has run for this controller. Makes
529
+ * `connect()` idempotent: re-entering after a transient `error` status (e.g. a
530
+ * retried `send()`) creates a fresh session rather than re-running the resume
531
+ * probe — which would fire another `resumeByFingerprint` POST and could adopt a
532
+ * session we already decided not to resume.
533
+ */
534
+ private resumeAttempted;
535
+ /**
536
+ * HTTP base for the chat-ws wrapper's `/internal/*` REST routes. `null` when
537
+ * the configured WS endpoint could not be parsed into an absolute origin — in
538
+ * that case the `/internal/*` routes are refused (rather than mis-targeted at
539
+ * the host page origin). See {@link httpBaseFromWsEndpoint}.
540
+ */
541
+ private readonly httpBase;
542
+ constructor(config: ChatWidgetConfig, events: ConversationEvents, store?: StoreApi<WidgetStore>);
301
543
  get connectionStatus(): ConnectionStatus;
302
- /** Merge in visitor identity (from the pre-chat form). Applied on next connect. */
544
+ /** The persisted store, exposed so the view can read identity for the pre-chat gate. */
545
+ getStore(): StoreApi<WidgetStore>;
546
+ /** True when a persisted session pointer exists (drives the resume path). */
547
+ hasPersistedSession(): boolean;
548
+ /** True when persisted identity exists (lets the view skip the pre-chat form). */
549
+ hasPersistedIdentity(): boolean;
550
+ /** Merge in visitor identity + consent (from the pre-chat form). Applied on next connect. */
303
551
  setUserInfo(info: UserInfo): void;
304
552
  private setInterrupt;
553
+ private setIdentityRestore;
554
+ get currentIdentityRestore(): IdentityRestore;
305
555
  /** Submit an OTP code to resume the paused turn. No-op if not awaiting OTP. */
306
556
  verifyOtp(code: string): void;
307
557
  /** Approve or reject a pending tool write to resume the paused turn. */
@@ -309,8 +559,68 @@ declare class ConversationController {
309
559
  private nextId;
310
560
  private setStatus;
311
561
  private emitMessages;
312
- /** Open the transport and create a conversation session. Idempotent. */
562
+ /** Compute (once) + return the persisted browser fingerprint. */
563
+ private fingerprint;
564
+ /**
565
+ * Build the `metadata` payload threaded into `create_conversation_session`:
566
+ * phone (no first-class engine field) and consent.
567
+ *
568
+ * NOTE: `verifiedEmail` is deliberately NOT stamped here. It is a per-session
569
+ * OTP proof bound to the session it was verified against
570
+ * (`verifiedEmailSessionId`), and the server only treats an actual OTP `verify`
571
+ * as proof — metadata `verifiedEmail` is just a hint. Auto-stamping it onto
572
+ * every brand-new `create_conversation_session` would mislabel a fresh
573
+ * visitor's session with a prior (possibly different) visitor's email on a
574
+ * shared browser. The verified email is only used when RESUMING the exact
575
+ * session it was proven for — see {@link verifiedEmailForSession}.
576
+ */
577
+ private sessionMetadata;
578
+ /**
579
+ * The verified-email hint, but ONLY when the OTP proof is bound to the session
580
+ * being resumed (`verifiedEmailSessionId === sessionId`). Returns null
581
+ * otherwise so a stale/cross-visitor proof is never threaded onto a session it
582
+ * wasn't proven for.
583
+ */
584
+ private verifiedEmailForSession;
585
+ /** Lazily open the WS client (default transport). Idempotent within a connect. */
586
+ private ensureClient;
587
+ /**
588
+ * Open the connection and either RESUME or create a session.
589
+ *
590
+ * 1. Persisted pointer (ADR-048 §b): `get_session` → if not `ended`, reuse +
591
+ * hydrate from `get_messages` (newest-first, reversed). On ended/404 clear
592
+ * ONLY the pointer (identity/consent survive).
593
+ * 2. No persisted pointer: POST `/internal/resume-by-fingerprint` FIRST; if
594
+ * `resumable`, adopt the returned session (the wrapper has primed the
595
+ * operator registry), reuse the sessionId, and hydrate via get_session/
596
+ * get_messages — rather than relying on createConversationSession to resume.
597
+ * 3. Otherwise create a fresh session.
598
+ */
313
599
  connect(): Promise<void>;
600
+ /**
601
+ * Build the auth fields every `/internal/*` route shares: `agentId` (required
602
+ * for the agent-policy lookup), `agentName` (used as the OTP email sender), and
603
+ * the optional pre-auth `authContext` the host page may have configured. The
604
+ * `Origin` header is sent automatically by the browser and checked server-side.
605
+ */
606
+ private authBody;
607
+ /** POST JSON to a `/internal/*` route; returns the parsed body (or throws). */
608
+ private postInternal;
609
+ /**
610
+ * POST `/internal/resume-by-fingerprint`. Returns the resumable sessionId when
611
+ * the wrapper found (and primed) a recent session for this fingerprint, else
612
+ * null. Network/route failures are swallowed → null (fall through to create).
613
+ */
614
+ private resumeByFingerprint;
615
+ /** `create_conversation_session` with fingerprint + identity + consent metadata. */
616
+ private createSession;
617
+ /**
618
+ * Attempt to resume `sessionId`: returns true and hydrates the transcript when
619
+ * the session is live, false when it has ended / can't be fetched.
620
+ */
621
+ private tryResume;
622
+ /** Page recent history (newest-first), reverse to chronological, and render. */
623
+ private hydrateHistory;
314
624
  /**
315
625
  * Submit a user message. Appends the user bubble immediately, then streams the
316
626
  * assistant reply token-by-token, finalizing on `eventual_response`.
@@ -318,9 +628,73 @@ declare class ConversationController {
318
628
  send(text: string): Promise<void>;
319
629
  /** Map a non-token turn event (OTP / tool-confirmation lifecycle) to interrupt state. */
320
630
  private handleTurnEvent;
631
+ /**
632
+ * Begin the cross-device restore: POST `/internal/identity/request-otp` for
633
+ * `email` over `channel`. The view collects the email via an explicit affordance.
634
+ */
635
+ requestIdentityOtp(email: string, channel?: 'email' | 'sms'): Promise<void>;
636
+ /** Submit the code: POST `/internal/identity/verify-otp`, then resolve on success. */
637
+ verifyIdentityOtp(code: string): Promise<void>;
638
+ /** Resolve the verified identity → restorable conversations via POST `/internal/identity/resolve`. */
639
+ private resolveIdentity;
640
+ /**
641
+ * Replay a chosen restorable conversation: point the live session at its
642
+ * sessionId, hydrate its transcript (get_session + get_messages), and persist
643
+ * the new pointer so the next `sendMessage` continues it.
644
+ */
645
+ restoreConversation(sessionId: string): Promise<void>;
646
+ /** Dismiss the cross-device restore panel. */
647
+ cancelIdentityRestore(): void;
321
648
  /** Tear down the underlying client. */
322
649
  disconnect(): void;
323
650
  }
324
651
  //#endregion
325
- export { type ChatMessage, type ChatWidgetConfig, type ChatWidgetMode, type ChatWidgetTheme, type Citation, type ConnectionStatus, ConversationController, type ConversationEvents, ELEMENT_TAG, type Role, SmoothAgentChatElement, defineChatWidget, initChatWidgetLoader, mountChatWidget, mountFullPageChat };
652
+ //#region src/fingerprint.d.ts
653
+ /**
654
+ * Browser fingerprint — a stable, privacy-light identifier used by the
655
+ * smooth-operator server to correlate an anonymous visitor's sessions across
656
+ * page loads (and, server-side, to match an anonymous fingerprint to a known
657
+ * CRM contact). It rides every `create_conversation_session` as
658
+ * `browserFingerprint` (see ADR-048).
659
+ *
660
+ * ## Why not ThumbmarkJS
661
+ *
662
+ * The ADR floats ThumbmarkJS as the reference implementation. For an *embed*
663
+ * that is injected onto arbitrary host pages, ThumbmarkJS is too heavy: its
664
+ * full build pulls in extensive device-detection tables and async
665
+ * component collection, adding tens of kilobytes (and async surface) to a
666
+ * bundle whose whole selling point is staying out of the host page's
667
+ * LCP/TBT budget. The fingerprint here is a few hundred bytes.
668
+ *
669
+ * ## What this is (and the tradeoff)
670
+ *
671
+ * The correlation that actually matters — "is this the same browser as last
672
+ * time?" — is carried by a **persisted random UUID** (the `browserFingerprint`
673
+ * field in the persisted store). That UUID is generated once and reused for
674
+ * the life of the localStorage entry, so same-browser resume is exact and
675
+ * deterministic. The signal hash below is a best-effort entropy *supplement*
676
+ * mixed into that UUID's derivation seed on first generation — it gives the
677
+ * server-side resolver a soft signal for the (rare) cross-storage case where
678
+ * the UUID was cleared but the device is unchanged. It is intentionally NOT a
679
+ * high-entropy device fingerprint: no canvas/WebGL/audio probes, no font
680
+ * enumeration, nothing that reads as invasive tracking. The tradeoff is weaker
681
+ * cross-storage matching in exchange for a tiny, transparent, no-network,
682
+ * XSS-safe implementation. The server's resolver (SMOODEV-2129d) is the source
683
+ * of truth for any fuzzy matching; the client just supplies a stable token.
684
+ */
685
+ /**
686
+ * Compute a fresh fingerprint token: a stable random UUID, suffixed with the
687
+ * FNV hash of the device signals so the server can recover a soft device
688
+ * signal even if it only has the token. Called ONCE per browser (the result is
689
+ * persisted and reused) — see {@link getOrCreateFingerprint}.
690
+ */
691
+ declare function computeFingerprint(): string;
692
+ /**
693
+ * Return the cached fingerprint if one was already computed for this browser,
694
+ * otherwise compute + persist a new one via the provided accessors. The
695
+ * persistence layer owns storage; this function owns the "compute once" policy.
696
+ */
697
+ declare function getOrCreateFingerprint(get: () => string | null, set: (fp: string) => void): string;
698
+ //#endregion
699
+ export { type ChatMessage, type ChatWidgetConfig, type ChatWidgetMode, type ChatWidgetTheme, type Citation, type ConnectionStatus, type ConsentState, ConversationController, type ConversationEvents, ELEMENT_TAG, type IdentityRestore, type IdentityState, PERSIST_VERSION, type PersistedWidgetState, type RestorableConversation, type Role, SmoothAgentChatElement, type UserInfo, type WidgetStore, computeFingerprint, createWidgetStore, defineChatWidget, getOrCreateFingerprint, httpBaseFromWsEndpoint, initChatWidgetLoader, mountChatWidget, mountFullPageChat, storageKey };
326
700
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/config.ts","../src/element.ts","../src/loader-core.ts","../src/conversation.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/config.ts","../src/element.ts","../src/loader-core.ts","../src/persistence.ts","../src/conversation.ts","../src/fingerprint.ts"],"mappings":"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"}