Skip to content

πŸ¦‹ New version release#16

Merged
brentrager merged 1 commit into
mainfrom
changeset-release/main
Jun 29, 2026
Merged

πŸ¦‹ New version release#16
brentrager merged 1 commit into
mainfrom
changeset-release/main

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

@smooai/[email protected]

Minor Changes

  • 9ea1dfc: Identity, persistence & consent client layer (ADR-048) β€” same-session resume, cross-device "restore my chats", marketing consent, and a stable browser fingerprint.

    Persisted state (Zustand). A framework-agnostic zustand/vanilla store with the persist middleware now keeps a small per-agent blob in localStorage (smoo-chat-widget:<agentId>): the session pointer, visitor identity (name/email/phone), marketing consent, a verified email, and the browser fingerprint. The transcript is never persisted β€” the smooth-operator server stays the source of truth and history is re-hydrated via get_conversation_messages. A version field drives persist.migrate so future shape changes upgrade old blobs in place; the storage adapter tolerates missing/locked-down localStorage (SSR, privacy mode) and never throws on boot.

    Browser fingerprint. Every create_conversation_session now carries a stable browserFingerprint for anonymous-visitor correlation (and server-side CRM matching). Computed once and cached in the persisted store. Rather than pull in ThumbmarkJS β€” tens of KB and async device-probing, too heavy for an embed whose whole point is staying out of the host's LCP/TBT budget β€” the fingerprint is a persisted random UUID (the exact same-browser correlator) suffixed with a small FNV hash of a few non-invasive, stable signals (UA, language, timezone, screen). No canvas/WebGL/audio probes, no network, XSS-safe. Tradeoff: weaker cross-storage matching than a full device fingerprint, deferred to the server resolver, in exchange for a tiny, transparent, privacy-light token.

    Same-session resume. On load, if a session pointer is persisted the widget calls get_session; when the session isn't ended it reuses the sessionId, replays history (get_conversation_messages, newest-first β†’ reversed to chronological), skips the pre-chat form, and continues the conversation. An ended/404 session clears only the pointer (identity & consent survive) and starts fresh.

    Returning-visitor resume by fingerprint (HTTP). When there is no persisted pointer, the widget first POSTs /internal/resume-by-fingerprint on the chat-ws wrapper with the browser fingerprint; if the wrapper resolves (and primes) a recent session it returns { resumable: true, sessionId, … } and the widget adopts that session (then get_session + get_conversation_messages to hydrate) instead of creating a new one. { resumable: false } falls through to a normal create.

    Pre-chat form: phone + marketing consent. The phone field is now shown by default (optional; rides session metadata.userPhone). Two explicit, default-unchecked consent checkboxes (email + SMS) capture marketing opt-in; ticking one stamps a consentAt ISO timestamp, and the consent record ({ emailOptIn, smsOptIn, consentSource: 'chat-widget-prechat', consentAt }) threads into the session metadata. New config flags: collectPhone, collectConsent, allowChatRestore (all default true).

    Cross-device "Restore my chats." An explicit footer affordance (not a mid-turn agent pause) runs the identity OTP flow over the chat-ws wrapper's HTTP routes β€” POST /internal/identity/request-otp β†’ verify-otp β†’ resolve β€” reusing the existing OTP UI. On a resolved list the visitor picks a conversation to replay (get_session + get_conversation_messages); the verified email is persisted.

    HTTP, not WS frames. The smooth-operator engine (1.8.0) owns the /ws dispatch and rejects unknown verbs, so the cross-device identity flow and fingerprint resume are fetch() (POST, JSON) calls to the chat-ws wrapper, with the HTTP base derived from the WS endpoint (wss://ai.smoo.ai/ws β†’ https://ai.smoo.ai). The browser sends Origin automatically (origin-allowlisted server-side) and each request carries agentId/agentName plus an optional pre-auth authContext ({ userId, signature, timestamp }) from the new authContext config option.

    All server-supplied strings (masked destinations, conversation previews, history) are rendered via textContent, keeping the 0.6.0 XSS guarantees intact, and the new UI follows the Aurora-Glass styling.

@brentrager brentrager merged commit bf09cd2 into main Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant