@smooai/chat-widget 0.6.0 → 0.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smooai/chat-widget",
3
- "version": "0.6.0",
3
+ "version": "0.9.0",
4
4
  "description": "Embeddable AI chat as a framework-light web component — the Aurora Glass design, streaming replies, grounded sources, and per-brand theming. Speaks the smooth-operator WebSocket protocol.",
5
5
  "license": "MIT",
6
6
  "author": "SmooAI",
@@ -58,7 +58,9 @@
58
58
  "access": "public"
59
59
  },
60
60
  "dependencies": {
61
- "@smooai/smooth-operator": "^1.8.0"
61
+ "@smooai/smooth-operator": "^1.8.0",
62
+ "libphonenumber-js": "^1.13.7",
63
+ "zustand": "^5.0.14"
62
64
  },
63
65
  "devDependencies": {
64
66
  "@changesets/cli": "^2.28.1",
package/src/config.ts CHANGED
@@ -71,6 +71,13 @@ export interface ChatWidgetConfig {
71
71
  userEmail?: string;
72
72
  /** Optional phone number for the user participant (passed via session metadata). */
73
73
  userPhone?: string;
74
+ /**
75
+ * Optional pre-auth HMAC context. When the host page has a shared secret with
76
+ * the agent, it can sign `{ userId, signature, timestamp }` so the chat-ws
77
+ * wrapper's `/internal/*` identity routes (and the WS create path) verify the
78
+ * caller without an OTP round-trip (ADR-046/ADR-048). Passed through verbatim.
79
+ */
80
+ authContext?: { userId: string; signature: string; timestamp: number };
74
81
  /** Placeholder text for the message input. */
75
82
  placeholder?: string;
76
83
  /** Greeting rendered when the conversation opens (before any messages). */
@@ -90,6 +97,24 @@ export interface ChatWidgetConfig {
90
97
  requireEmail?: boolean;
91
98
  /** Require the visitor's phone before chatting. */
92
99
  requirePhone?: boolean;
100
+ /**
101
+ * Show the phone field on the pre-chat form (optional unless {@link requirePhone}).
102
+ * Defaults to `true` for this widget — phone rides the session metadata as
103
+ * `userPhone` so the agent can follow up by SMS. Set `false` to hide it.
104
+ */
105
+ collectPhone?: boolean;
106
+ /**
107
+ * Show the email + SMS marketing-consent checkboxes on the pre-chat form.
108
+ * Explicit opt-in, default UNCHECKED; a `consentAt` timestamp is stamped when
109
+ * a box is ticked. Defaults to `true`. The consent record is threaded into the
110
+ * session metadata (ADR-048).
111
+ */
112
+ collectConsent?: boolean;
113
+ /**
114
+ * Offer the cross-device "Restore my chats" affordance — an explicit link that
115
+ * runs the identity-OTP → resolve → replay flow. Defaults to `true`.
116
+ */
117
+ allowChatRestore?: boolean;
93
118
  /**
94
119
  * Let visitors chat without providing any identity. When `true`, the
95
120
  * `require*` flags are ignored and the pre-chat form is skipped.
@@ -102,11 +127,12 @@ export interface ChatWidgetConfig {
102
127
  /** The fully-resolved theme (canonical keys only — aliases are folded in). */
103
128
  export type ResolvedTheme = Required<Omit<ChatWidgetTheme, 'chatBubbleInbound' | 'chatBubbleInboundText' | 'chatBubbleOutbound' | 'chatBubbleOutboundText'>>;
104
129
 
105
- export type ResolvedConfig = Required<Omit<ChatWidgetConfig, 'theme' | 'userName' | 'userEmail' | 'userPhone'>> & {
130
+ export type ResolvedConfig = Required<Omit<ChatWidgetConfig, 'theme' | 'userName' | 'userEmail' | 'userPhone' | 'authContext'>> & {
106
131
  theme: ResolvedTheme;
107
132
  userName?: string;
108
133
  userEmail?: string;
109
134
  userPhone?: string;
135
+ authContext?: { userId: string; signature: string; timestamp: number };
110
136
  };
111
137
 
112
138
  /** Resolve a partial config against the built-in defaults. */
@@ -127,6 +153,7 @@ export function resolveConfig(config: ChatWidgetConfig): ResolvedConfig {
127
153
  userName: config.userName,
128
154
  userEmail: config.userEmail,
129
155
  userPhone: config.userPhone,
156
+ authContext: config.authContext,
130
157
  placeholder: config.placeholder ?? 'Type a message…',
131
158
  greeting: config.greeting ?? 'Hi! How can I help you today?',
132
159
  connectionErrorMessage: config.connectionErrorMessage ?? "We couldn't reach the chat. Please try again in a moment.",
@@ -135,6 +162,9 @@ export function resolveConfig(config: ChatWidgetConfig): ResolvedConfig {
135
162
  requireName: config.requireName ?? false,
136
163
  requireEmail: config.requireEmail ?? false,
137
164
  requirePhone: config.requirePhone ?? false,
165
+ collectPhone: config.collectPhone ?? true,
166
+ collectConsent: config.collectConsent ?? true,
167
+ allowChatRestore: config.allowChatRestore ?? true,
138
168
  allowAnonymous: config.allowAnonymous ?? false,
139
169
  theme: {
140
170
  text: theme.text ?? '#f8fafc',