@waniwani/sdk 0.18.0 → 0.19.1

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.
@@ -68,7 +68,7 @@ interface KbClient {
68
68
  * first-class names at runtime (the widget transport passes these through
69
69
  * verbatim instead of namespacing them as custom widget events).
70
70
  */
71
- declare const EVENT_TYPES: readonly ["session.started", "page.viewed", "tool.called", "quote.requested", "quote.succeeded", "quote.failed", "link.clicked", "purchase.completed", "widget_render", "user.identified", "price_shown", "prices_compared", "option_selected", "lead_qualified", "converted"];
71
+ declare const EVENT_TYPES: readonly ["session.started", "page.viewed", "tool.called", "link.clicked", "widget_render", "user.identified", "price_shown", "prices_compared", "option_selected", "lead_qualified", "converted"];
72
72
  type EventType = (typeof EVENT_TYPES)[number];
73
73
  /**
74
74
  * Properties for `page.viewed` — emitted once when the chat widget initializes
@@ -97,17 +97,9 @@ interface ToolCalledProperties {
97
97
  /** Retrieval traces for kb.search() calls made inside this tool handler. */
98
98
  kbSearch?: KbSearchTrace[];
99
99
  }
100
- interface QuoteSucceededProperties {
101
- amount?: number;
102
- currency?: string;
103
- }
104
100
  interface LinkClickedProperties {
105
101
  url?: string;
106
102
  }
107
- interface PurchaseCompletedProperties {
108
- amount?: number;
109
- currency?: string;
110
- }
111
103
  interface PriceShownProperties {
112
104
  amount: number;
113
105
  currency: string;
@@ -194,19 +186,9 @@ type TrackEvent = ({
194
186
  } & BaseTrackEvent) | ({
195
187
  event: "tool.called";
196
188
  properties?: ToolCalledProperties;
197
- } & BaseTrackEvent) | ({
198
- event: "quote.requested";
199
- } & BaseTrackEvent) | ({
200
- event: "quote.succeeded";
201
- properties?: QuoteSucceededProperties;
202
- } & BaseTrackEvent) | ({
203
- event: "quote.failed";
204
189
  } & BaseTrackEvent) | ({
205
190
  event: "link.clicked";
206
191
  properties?: LinkClickedProperties;
207
- } & BaseTrackEvent) | ({
208
- event: "purchase.completed";
209
- properties?: PurchaseCompletedProperties;
210
192
  } & BaseTrackEvent) | ({
211
193
  event: "user.identified";
212
194
  } & BaseTrackEvent) | ({
@@ -235,11 +217,7 @@ interface LegacyTrackEvent extends TrackingContext {
235
217
  properties?: Record<string, unknown>;
236
218
  toolName?: string;
237
219
  toolType?: ToolCalledProperties["type"];
238
- quoteAmount?: number;
239
- quoteCurrency?: string;
240
220
  linkUrl?: string;
241
- purchaseAmount?: number;
242
- purchaseCurrency?: string;
243
221
  }
244
222
  /**
245
223
  * Public track input accepted by `client.track()`.
@@ -22,7 +22,7 @@ interface KbSearchTrace {
22
22
  * first-class names at runtime (the widget transport passes these through
23
23
  * verbatim instead of namespacing them as custom widget events).
24
24
  */
25
- declare const EVENT_TYPES: readonly ["session.started", "page.viewed", "tool.called", "quote.requested", "quote.succeeded", "quote.failed", "link.clicked", "purchase.completed", "widget_render", "user.identified", "price_shown", "prices_compared", "option_selected", "lead_qualified", "converted"];
25
+ declare const EVENT_TYPES: readonly ["session.started", "page.viewed", "tool.called", "link.clicked", "widget_render", "user.identified", "price_shown", "prices_compared", "option_selected", "lead_qualified", "converted"];
26
26
  type EventType = (typeof EVENT_TYPES)[number];
27
27
  /**
28
28
  * Properties for `page.viewed` — emitted once when the chat widget initializes
@@ -51,17 +51,9 @@ interface ToolCalledProperties {
51
51
  /** Retrieval traces for kb.search() calls made inside this tool handler. */
52
52
  kbSearch?: KbSearchTrace[];
53
53
  }
54
- interface QuoteSucceededProperties {
55
- amount?: number;
56
- currency?: string;
57
- }
58
54
  interface LinkClickedProperties {
59
55
  url?: string;
60
56
  }
61
- interface PurchaseCompletedProperties {
62
- amount?: number;
63
- currency?: string;
64
- }
65
57
  interface PriceShownProperties {
66
58
  amount: number;
67
59
  currency: string;
@@ -148,19 +140,9 @@ type TrackEvent = ({
148
140
  } & BaseTrackEvent) | ({
149
141
  event: "tool.called";
150
142
  properties?: ToolCalledProperties;
151
- } & BaseTrackEvent) | ({
152
- event: "quote.requested";
153
- } & BaseTrackEvent) | ({
154
- event: "quote.succeeded";
155
- properties?: QuoteSucceededProperties;
156
- } & BaseTrackEvent) | ({
157
- event: "quote.failed";
158
143
  } & BaseTrackEvent) | ({
159
144
  event: "link.clicked";
160
145
  properties?: LinkClickedProperties;
161
- } & BaseTrackEvent) | ({
162
- event: "purchase.completed";
163
- properties?: PurchaseCompletedProperties;
164
146
  } & BaseTrackEvent) | ({
165
147
  event: "user.identified";
166
148
  } & BaseTrackEvent) | ({
@@ -189,11 +171,7 @@ interface LegacyTrackEvent extends TrackingContext {
189
171
  properties?: Record<string, unknown>;
190
172
  toolName?: string;
191
173
  toolType?: ToolCalledProperties["type"];
192
- quoteAmount?: number;
193
- quoteCurrency?: string;
194
174
  linkUrl?: string;
195
- purchaseAmount?: number;
196
- purchaseCurrency?: string;
197
175
  }
198
176
  /**
199
177
  * Public track input accepted by `client.track()`.
@@ -336,6 +314,66 @@ type DeepPartial<T> = T extends (...args: never[]) => unknown ? T : T extends ob
336
314
  } : T;
337
315
  type MessageOverrides = DeepPartial<Messages>;
338
316
 
317
+ /**
318
+ * A visitor id to apply, or a resolver that produces one. The resolver may be
319
+ * sync (`() => posthog.get_distinct_id()`) or async
320
+ * (`async () => (await sdk.ready()).id`), for analytics SDKs whose id is only
321
+ * available after they bootstrap.
322
+ */
323
+ type VisitorIdInput = string | (() => string | undefined | null | Promise<string | undefined | null>);
324
+
325
+ /** Surface the widget is mounted on. */
326
+ type WidgetMode = "inline" | "floating";
327
+ interface WidgetEventBase {
328
+ /** Surface the widget is mounted on. */
329
+ mode: WidgetMode;
330
+ /**
331
+ * Conversation session id, when one exists. Assigned on the first
332
+ * exchange, so it is `undefined` for events that precede it.
333
+ */
334
+ sessionId?: string;
335
+ /** Epoch milliseconds at emit time. */
336
+ timestamp: number;
337
+ }
338
+ /**
339
+ * Per-event discriminant and extra properties. Events in the first branch
340
+ * carry no `properties` object.
341
+ */
342
+ type WidgetEventDetail = {
343
+ name: "chat.ready" | "chat.opened" | "chat.closed" | "message.sent" | "message.received";
344
+ } | {
345
+ name: "session.started";
346
+ properties: {
347
+ sessionId: string;
348
+ };
349
+ } | {
350
+ name: "thread.changed";
351
+ properties: {
352
+ threadId: string;
353
+ };
354
+ } | {
355
+ name: "chat.error";
356
+ properties: {
357
+ message: string;
358
+ };
359
+ } | {
360
+ name: "suggestion.clicked";
361
+ properties: {
362
+ text: string;
363
+ index: number;
364
+ /** Which provider supplied the clicked pill: `"channel"` (starter prompts), `"page"` (per-URL starter prompts), `"flow"` (an MCP flow's `interrupt({ suggestions })`), or `"followup"` (generated from the conversation). */
365
+ origin: SuggestionOrigin;
366
+ };
367
+ } | {
368
+ name: "link.clicked";
369
+ properties: {
370
+ url: string;
371
+ };
372
+ };
373
+ /** Payload handed to `onEvent` subscribers. Discriminated on `name`. */
374
+ type WidgetEvent = WidgetEventBase & WidgetEventDetail;
375
+ type WidgetEventName = WidgetEventDetail["name"];
376
+
339
377
  /**
340
378
  * Built-in theme presets. `auto` follows the host's `prefers-color-scheme`
341
379
  * and switches at runtime without re-rendering.
@@ -438,6 +476,15 @@ interface WelcomeConfig {
438
476
  /** Suggestion cards shown in the welcome screen. Disappear after the first message. */
439
477
  suggestions?: string[];
440
478
  }
479
+ /** Where a suggestion pill came from. */
480
+ /**
481
+ * Every place a suggestion pill can come from. The single source of truth:
482
+ * {@link SuggestionOrigin} derives from it, and runtime validation reads it,
483
+ * so adding an origin is a one-line change.
484
+ */
485
+ declare const SUGGESTION_ORIGINS: readonly ["channel", "page", "flow", "followup"];
486
+ /** Where a suggestion pill came from. */
487
+ type SuggestionOrigin = (typeof SUGGESTION_ORIGINS)[number];
441
488
  interface SuggestionsConfig {
442
489
  /**
443
490
  * Initial suggestions to show before the user sends their first message.
@@ -445,8 +492,14 @@ interface SuggestionsConfig {
445
492
  */
446
493
  initial?: string[];
447
494
  /**
448
- * Enable AI-generated suggestions after each response.
449
- * Defaults to `true` when suggestions config is provided.
495
+ * Which providers may fill the pill row. Omitted, this defaults to
496
+ * `["channel", "page", "followup"]`: starter prompts and generated
497
+ * follow-ups render, flow-driven pills stay opt-in.
498
+ */
499
+ origins?: SuggestionOrigin[];
500
+ /**
501
+ * @deprecated Use `origins`. `true` maps to every origin, `false` to none.
502
+ * Will be removed in a future minor release.
450
503
  */
451
504
  dynamic?: boolean;
452
505
  }
@@ -494,6 +547,21 @@ interface ChatBaseProps {
494
547
  appearance?: ChatAppearance;
495
548
  /** Per-slot class name overrides. See {@link ChatClassNames}. */
496
549
  classNames?: ChatClassNames;
550
+ /**
551
+ * Override the anonymous visitor id the widget generates with one you
552
+ * already track (a PostHog / Amplitude / Segment distinct id, your own
553
+ * cookie, etc.). The chat sends it on every request, so Waniwani sessions
554
+ * and events correlate to the same visitor, and server-side MCP tools and
555
+ * flows read it back as `context.waniwani.visitorId`.
556
+ *
557
+ * A string, or a resolver that returns one — sync
558
+ * (`() => posthog.get_distinct_id()`) or async
559
+ * (`async () => (await sdk.ready()).id`), for analytics SDKs whose id is
560
+ * only ready after they bootstrap. A blank / failed result is ignored, so
561
+ * the auto-generated, `localStorage`-persisted id is kept. Leave unset to
562
+ * always use the auto id.
563
+ */
564
+ visitorId?: VisitorIdInput;
497
565
  /** Additional headers to send with chat API requests */
498
566
  headers?: Record<string, string>;
499
567
  /** Additional body fields to send with each chat request */
@@ -513,8 +581,11 @@ interface ChatBaseProps {
513
581
  /** Callback fired when a response is received */
514
582
  onResponseReceived?: () => void;
515
583
  /**
516
- * Enable AI-generated suggestions after each response.
517
- * `true` enables with defaults (3 suggestions), object allows config, `false`/undefined disables.
584
+ * Suggestion pill configuration. Unset: no suggestions. An object sets
585
+ * starter prompts (`initial`) and which origins may fill the per-turn
586
+ * pill row (`origins`); `origins: ["flow"]` (or any list including
587
+ * `"flow"`) opts into flow-driven pills. `true` enables every origin with
588
+ * defaults; `false` hides the pill row entirely.
518
589
  */
519
590
  suggestions?: boolean | SuggestionsConfig;
520
591
  /**
@@ -852,6 +923,15 @@ interface WaniwaniChatOverrides {
852
923
  placeholder?: string;
853
924
  /** Initial suggestion chips. */
854
925
  suggestions?: string[];
926
+ /**
927
+ * Which providers may fill the per-turn pill row. Defaults to
928
+ * `["channel", "page", "followup"]` when unset: starter prompts and
929
+ * generated follow-ups render, flow-driven pills stay opt-in — include
930
+ * `"flow"` to render the pills a flow drives via
931
+ * `interrupt({ suggestions })`. Starter prompts (`suggestions`) are
932
+ * unaffected by this field and show either way.
933
+ */
934
+ suggestionOrigins?: SuggestionOrigin[];
855
935
  /** Persist conversations across reloads in IndexedDB. */
856
936
  enableThreadHistory?: boolean;
857
937
  /**
@@ -945,6 +1025,22 @@ interface WaniwaniChatProps {
945
1025
  token: string;
946
1026
  /** Agent channel ID — routes the conversation to the right agent. */
947
1027
  channelId?: string;
1028
+ /**
1029
+ * Override the anonymous visitor id the widget generates with one you
1030
+ * already track (a PostHog / Amplitude / Segment distinct id, your own
1031
+ * cookie, etc.). The chat sends it on every request, so Waniwani sessions
1032
+ * and events correlate to the same visitor, and server-side MCP tools and
1033
+ * flows read it back as `context.waniwani.visitorId`.
1034
+ *
1035
+ * A string, or a resolver that returns one — sync
1036
+ * (`() => posthog.get_distinct_id()`) or async
1037
+ * (`async () => (await sdk.ready()).id`), for analytics SDKs whose id is only
1038
+ * ready after they bootstrap. Read live on each request, so updating it
1039
+ * applies to the next message. A blank / failed result is ignored, keeping
1040
+ * the auto-generated, `localStorage`-persisted id. Leave unset to always use
1041
+ * the auto id.
1042
+ */
1043
+ visitorId?: VisitorIdInput;
948
1044
  /** Additional class names applied to the root element. */
949
1045
  className?: string;
950
1046
  /**
@@ -954,6 +1050,16 @@ interface WaniwaniChatProps {
954
1050
  * can't be serialized to the dashboard).
955
1051
  */
956
1052
  overrides?: WaniwaniChatOverrides;
1053
+ /**
1054
+ * Callback fired on chat lifecycle events (`chat.ready`, `message.sent`,
1055
+ * `message.received`, `session.started`, `thread.changed`, `chat.error`,
1056
+ * `suggestion.clicked`, `link.clicked`; `chat.opened`/`chat.closed` are
1057
+ * floating-embed-only and never fire here). Message events never include
1058
+ * the message text. Use it to mirror widget activity into the host page's
1059
+ * analytics. Exceptions thrown by the callback are swallowed and never
1060
+ * break the chat.
1061
+ */
1062
+ onEvent?: (event: WidgetEvent) => void;
957
1063
  }
958
1064
  declare const WaniwaniChat: react.ForwardRefExoticComponent<WaniwaniChatProps & react.RefAttributes<ChatHandle>>;
959
1065
 
@@ -969,4 +1075,4 @@ declare function mergeTheme(userTheme?: ChatTheme): Required<ChatTheme>;
969
1075
  */
970
1076
  declare function themeToCSSProperties(theme: ChatTheme): Record<string, string>;
971
1077
 
972
- export { type ChatAppearance, type ChatBaseProps, ChatCard, type ChatCardProps, ChatEmbed, type ChatEmbedMcpConfig, type ChatEmbedProps, type ChatHandle, type ChatTheme, DARK_THEME, DEFAULT_THEME, type McpAppDisplayMode, McpAppFrame, type McpAppFrameProps, type ShowToolCalls, type SuggestionsConfig, type ThemePreset, WaniwaniChat, type WaniwaniChatOverrides, type WaniwaniChatProps, type WelcomeConfig, mergeTheme, themeToCSSProperties };
1078
+ export { type ChatAppearance, type ChatBaseProps, ChatCard, type ChatCardProps, ChatEmbed, type ChatEmbedMcpConfig, type ChatEmbedProps, type ChatHandle, type ChatTheme, DARK_THEME, DEFAULT_THEME, type McpAppDisplayMode, McpAppFrame, type McpAppFrameProps, type ShowToolCalls, type SuggestionsConfig, type ThemePreset, WaniwaniChat, type WaniwaniChatOverrides, type WaniwaniChatProps, type WelcomeConfig, type WidgetEvent, type WidgetEventName, type WidgetMode, mergeTheme, themeToCSSProperties };