π¦ New version release#16
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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/vanillastore with thepersistmiddleware 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 viaget_conversation_messages. Aversionfield drivespersist.migrateso 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_sessionnow carries a stablebrowserFingerprintfor 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'tendedit reuses thesessionId, 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-fingerprinton 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 (thenget_session+get_conversation_messagesto 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 aconsentAtISO timestamp, and the consent record ({ emailOptIn, smsOptIn, consentSource: 'chat-widget-prechat', consentAt }) threads into the session metadata. New config flags:collectPhone,collectConsent,allowChatRestore(all defaulttrue).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
/wsdispatch and rejects unknown verbs, so the cross-device identity flow and fingerprint resume arefetch()(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 sendsOriginautomatically (origin-allowlisted server-side) and each request carriesagentId/agentNameplus an optional pre-authauthContext({ userId, signature, timestamp }) from the newauthContextconfig 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.