posthog-js 1.347.2 → 1.348.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.
Files changed (74) hide show
  1. package/dist/array.full.es5.js +1 -1
  2. package/dist/array.full.js +1 -1
  3. package/dist/array.full.no-external.js +1 -1
  4. package/dist/array.js +1 -1
  5. package/dist/array.no-external.js +1 -1
  6. package/dist/conversations.js +1 -1
  7. package/dist/conversations.js.map +1 -1
  8. package/dist/customizations.full.js +1 -1
  9. package/dist/lazy-recorder.js +1 -1
  10. package/dist/main.js +1 -1
  11. package/dist/main.js.map +1 -1
  12. package/dist/module.d.ts +43 -1
  13. package/dist/module.full.d.ts +43 -1
  14. package/dist/module.full.js +1 -1
  15. package/dist/module.full.js.map +1 -1
  16. package/dist/module.full.no-external.d.ts +43 -1
  17. package/dist/module.full.no-external.js +1 -1
  18. package/dist/module.full.no-external.js.map +1 -1
  19. package/dist/module.js +1 -1
  20. package/dist/module.js.map +1 -1
  21. package/dist/module.no-external.d.ts +43 -1
  22. package/dist/module.no-external.js +1 -1
  23. package/dist/module.no-external.js.map +1 -1
  24. package/dist/posthog-recorder.js +1 -1
  25. package/dist/product-tours-preview.d.ts +2 -0
  26. package/dist/product-tours-preview.js +1 -1
  27. package/dist/product-tours-preview.js.map +1 -1
  28. package/dist/product-tours.js +1 -1
  29. package/dist/product-tours.js.map +1 -1
  30. package/dist/src/extensions/conversations/external/components/ConversationsWidget.d.ts +43 -2
  31. package/dist/src/extensions/conversations/external/components/TicketListItem.d.ts +13 -0
  32. package/dist/src/extensions/conversations/external/components/TicketListView.d.ts +15 -0
  33. package/dist/src/extensions/conversations/external/components/styles.d.ts +184 -0
  34. package/dist/src/extensions/conversations/external/components/utils.d.ts +8 -0
  35. package/dist/src/extensions/conversations/external/index.d.ts +39 -1
  36. package/dist/src/extensions/product-tours/product-tours.d.ts +2 -0
  37. package/dist/src/posthog-product-tours-types.d.ts +42 -0
  38. package/dist/surveys-preview.d.ts +2 -0
  39. package/lib/package.json +1 -1
  40. package/lib/src/extensions/conversations/external/components/ConversationsWidget.d.ts +43 -2
  41. package/lib/src/extensions/conversations/external/components/ConversationsWidget.js +96 -28
  42. package/lib/src/extensions/conversations/external/components/ConversationsWidget.js.map +1 -1
  43. package/lib/src/extensions/conversations/external/components/TicketListItem.d.ts +13 -0
  44. package/lib/src/extensions/conversations/external/components/TicketListItem.js +47 -0
  45. package/lib/src/extensions/conversations/external/components/TicketListItem.js.map +1 -0
  46. package/lib/src/extensions/conversations/external/components/TicketListView.d.ts +15 -0
  47. package/lib/src/extensions/conversations/external/components/TicketListView.js +75 -0
  48. package/lib/src/extensions/conversations/external/components/TicketListView.js.map +1 -0
  49. package/lib/src/extensions/conversations/external/components/styles.d.ts +184 -0
  50. package/lib/src/extensions/conversations/external/components/styles.js +189 -0
  51. package/lib/src/extensions/conversations/external/components/styles.js.map +1 -1
  52. package/lib/src/extensions/conversations/external/components/utils.d.ts +8 -0
  53. package/lib/src/extensions/conversations/external/components/utils.js +49 -0
  54. package/lib/src/extensions/conversations/external/components/utils.js.map +1 -0
  55. package/lib/src/extensions/conversations/external/index.d.ts +39 -1
  56. package/lib/src/extensions/conversations/external/index.js +253 -31
  57. package/lib/src/extensions/conversations/external/index.js.map +1 -1
  58. package/lib/src/extensions/product-tours/components/ProductTourSurveyStepInner.js +1 -1
  59. package/lib/src/extensions/product-tours/components/ProductTourSurveyStepInner.js.map +1 -1
  60. package/lib/src/extensions/product-tours/product-tours.d.ts +2 -0
  61. package/lib/src/extensions/product-tours/product-tours.js +78 -71
  62. package/lib/src/extensions/product-tours/product-tours.js.map +1 -1
  63. package/lib/src/posthog-product-tours-types.d.ts +42 -0
  64. package/lib/src/posthog-product-tours-types.js +43 -1
  65. package/lib/src/posthog-product-tours-types.js.map +1 -1
  66. package/lib/src/utils/product-tour-event-receiver.js +2 -1
  67. package/lib/src/utils/product-tour-event-receiver.js.map +1 -1
  68. package/lib/tsconfig.tsbuildinfo +1 -1
  69. package/package.json +3 -3
  70. package/react/dist/esm/index.js +25 -1
  71. package/react/dist/esm/index.js.map +1 -1
  72. package/react/dist/types/index.d.ts +4 -2
  73. package/react/dist/umd/index.js +25 -0
  74. package/react/dist/umd/index.js.map +1 -1
@@ -104,6 +104,11 @@ var ConversationsManager = /** @class */ (function () {
104
104
  this._unsubscribeIdentifyListener = null;
105
105
  this._unreadCount = 0;
106
106
  this._isWidgetRendered = false;
107
+ this._initializeWidgetPromise = null;
108
+ // View state management for ticket list vs message view
109
+ this._currentView = 'messages';
110
+ this._tickets = [];
111
+ this._hasMultipleTickets = false;
107
112
  /**
108
113
  * Handle user identification from the widget form
109
114
  */
@@ -152,17 +157,18 @@ var ConversationsManager = /** @class */ (function () {
152
157
  * Handle widget state changes
153
158
  */
154
159
  this._handleStateChange = function (state) {
155
- logger.info('Widget state changed', { state: state });
160
+ logger.info('Widget state changed', { state: state, view: _this._currentView });
156
161
  // Track state changes
157
162
  _this._posthog.capture('$conversations_widget_state_changed', {
158
163
  state: state,
164
+ view: _this._currentView,
159
165
  ticketId: _this._currentTicketId,
160
166
  });
161
167
  // Save state to localStorage
162
168
  _this._persistence.saveWidgetState(state);
163
- // Mark messages as read when widget opens
169
+ // Mark messages as read when widget opens (only if in message view with a ticket)
164
170
  if (state === 'open') {
165
- if (_this._unreadCount > 0 && _this._currentTicketId) {
171
+ if (_this._currentView === 'messages' && _this._unreadCount > 0 && _this._currentTicketId) {
166
172
  _this._markMessagesAsRead();
167
173
  }
168
174
  }
@@ -192,6 +198,131 @@ var ConversationsManager = /** @class */ (function () {
192
198
  }
193
199
  });
194
200
  }); };
201
+ /**
202
+ * Poll for tickets list
203
+ */
204
+ this._pollTickets = function () { return __awaiter(_this, void 0, void 0, function () {
205
+ return __generator(this, function (_a) {
206
+ switch (_a.label) {
207
+ case 0:
208
+ if (this._isPolling) {
209
+ return [2 /*return*/];
210
+ }
211
+ this._isPolling = true;
212
+ _a.label = 1;
213
+ case 1:
214
+ _a.trys.push([1, , 3, 4]);
215
+ return [4 /*yield*/, this._loadTickets()];
216
+ case 2:
217
+ _a.sent();
218
+ return [3 /*break*/, 4];
219
+ case 3:
220
+ this._isPolling = false;
221
+ return [7 /*endfinally*/];
222
+ case 4: return [2 /*return*/];
223
+ }
224
+ });
225
+ }); };
226
+ /**
227
+ * Main poll function that polls based on current view
228
+ */
229
+ this._poll = function () { return __awaiter(_this, void 0, void 0, function () {
230
+ return __generator(this, function (_a) {
231
+ switch (_a.label) {
232
+ case 0:
233
+ if (!(this._currentView === 'tickets')) return [3 /*break*/, 2];
234
+ return [4 /*yield*/, this._pollTickets()];
235
+ case 1:
236
+ _a.sent();
237
+ return [3 /*break*/, 4];
238
+ case 2: return [4 /*yield*/, this._pollMessages()];
239
+ case 3:
240
+ _a.sent();
241
+ _a.label = 4;
242
+ case 4: return [2 /*return*/];
243
+ }
244
+ });
245
+ }); };
246
+ /**
247
+ * Handle view changes from the widget
248
+ */
249
+ this._handleViewChange = function (view) {
250
+ logger.info('View changed', { from: _this._currentView, to: view });
251
+ _this._currentView = view;
252
+ };
253
+ /**
254
+ * Handle ticket selection from the list
255
+ */
256
+ this._handleSelectTicket = function (ticketId) { return __awaiter(_this, void 0, void 0, function () {
257
+ var _a, _b;
258
+ return __generator(this, function (_c) {
259
+ switch (_c.label) {
260
+ case 0:
261
+ // Switch to this ticket
262
+ this._switchToTicketIfNeeded(ticketId);
263
+ // Clear messages and reset timestamp
264
+ this._lastMessageTimestamp = null;
265
+ (_a = this._widgetRef) === null || _a === void 0 ? void 0 : _a.clearMessages();
266
+ // Switch view to messages
267
+ this._currentView = 'messages';
268
+ (_b = this._widgetRef) === null || _b === void 0 ? void 0 : _b.setView('messages');
269
+ // Load messages for the selected ticket
270
+ return [4 /*yield*/, this._loadMessages()
271
+ // Mark as read if widget is open
272
+ ];
273
+ case 1:
274
+ // Load messages for the selected ticket
275
+ _c.sent();
276
+ // Mark as read if widget is open
277
+ if (this._isWidgetOpen() && this._unreadCount > 0) {
278
+ this._markMessagesAsRead();
279
+ }
280
+ return [2 /*return*/];
281
+ }
282
+ });
283
+ }); };
284
+ /**
285
+ * Handle new conversation request
286
+ */
287
+ this._handleNewConversation = function () {
288
+ var _a, _b;
289
+ logger.info('New conversation requested');
290
+ // Clear current ticket
291
+ _this._currentTicketId = null;
292
+ _this._persistence.clearTicketId();
293
+ // Reset timestamp
294
+ _this._lastMessageTimestamp = null;
295
+ // Switch view to messages
296
+ _this._currentView = 'messages';
297
+ (_a = _this._widgetRef) === null || _a === void 0 ? void 0 : _a.setView('messages');
298
+ // Clear messages and add greeting
299
+ (_b = _this._widgetRef) === null || _b === void 0 ? void 0 : _b.clearMessages(true);
300
+ };
301
+ /**
302
+ * Handle back to tickets request
303
+ */
304
+ this._handleBackToTickets = function () { return __awaiter(_this, void 0, void 0, function () {
305
+ var _a, _b;
306
+ return __generator(this, function (_c) {
307
+ switch (_c.label) {
308
+ case 0:
309
+ logger.info('Back to tickets requested');
310
+ // Switch view to tickets
311
+ this._currentView = 'tickets';
312
+ (_a = this._widgetRef) === null || _a === void 0 ? void 0 : _a.setView('tickets');
313
+ // Load tickets
314
+ (_b = this._widgetRef) === null || _b === void 0 ? void 0 : _b.setTicketsLoading(true);
315
+ return [4 /*yield*/, this._loadTickets()
316
+ // Track back to tickets
317
+ ];
318
+ case 1:
319
+ _c.sent();
320
+ // Track back to tickets
321
+ this._posthog.capture('$conversations_back_to_tickets');
322
+ return [2 /*return*/];
323
+ }
324
+ });
325
+ }); };
195
326
  this._config = config;
196
327
  this._persistence = new persistence_1.ConversationsPersistence(_posthog);
197
328
  // Get or create widget_session_id - this stays the same even when user identifies
@@ -467,34 +598,55 @@ var ConversationsManager = /** @class */ (function () {
467
598
  };
468
599
  /**
469
600
  * Initialize and render the widget UI
601
+ * Uses a promise guard to prevent race conditions from concurrent calls
470
602
  */
471
603
  ConversationsManager.prototype._initializeWidget = function () {
472
604
  if (this._isWidgetRendered) {
473
- return; // Already rendered
605
+ return Promise.resolve();
474
606
  }
475
- var savedState = this._persistence.loadWidgetState();
476
- var initialState = 'closed';
477
- if (savedState === 'open') {
478
- initialState = 'open';
607
+ if (this._initializeWidgetPromise) {
608
+ return this._initializeWidgetPromise;
479
609
  }
480
- // Get initial user traits (from PostHog person properties or saved)
481
- var initialUserTraits = this._getInitialUserTraits();
482
- // Render the widget
483
- this._renderWidget(initialState, initialUserTraits);
484
- this._isWidgetRendered = true;
485
- // Track widget initialization
486
- this._posthog.capture('$conversations_widget_loaded', {
487
- hasExistingTicket: !!this._currentTicketId,
488
- initialState: initialState,
489
- hasUserTraits: !!initialUserTraits,
610
+ this._initializeWidgetPromise = this._doInitializeWidget();
611
+ return this._initializeWidgetPromise;
612
+ };
613
+ ConversationsManager.prototype._doInitializeWidget = function () {
614
+ return __awaiter(this, void 0, void 0, function () {
615
+ var savedState, initialState, initialUserTraits, _a, initialView, tickets;
616
+ return __generator(this, function (_b) {
617
+ switch (_b.label) {
618
+ case 0:
619
+ savedState = this._persistence.loadWidgetState();
620
+ initialState = 'closed';
621
+ if (savedState === 'open') {
622
+ initialState = 'open';
623
+ }
624
+ initialUserTraits = this._getInitialUserTraits();
625
+ return [4 /*yield*/, this._determineInitialView()];
626
+ case 1:
627
+ _a = _b.sent(), initialView = _a.view, tickets = _a.tickets;
628
+ this._currentView = initialView;
629
+ // Render the widget with initial view
630
+ this._renderWidget(initialState, initialUserTraits, initialView, tickets);
631
+ this._isWidgetRendered = true;
632
+ // Track widget initialization
633
+ this._posthog.capture('$conversations_widget_loaded', {
634
+ hasExistingTicket: !!this._currentTicketId,
635
+ initialState: initialState,
636
+ initialView: initialView,
637
+ ticketCount: tickets.length,
638
+ hasUserTraits: !!initialUserTraits,
639
+ });
640
+ // Load messages if in message view and have a ticket
641
+ if (initialView === 'messages' && this._currentTicketId) {
642
+ this._loadMessages();
643
+ }
644
+ // Start polling based on current view
645
+ this._startPolling();
646
+ return [2 /*return*/];
647
+ }
648
+ });
490
649
  });
491
- // Set up polling and load messages only when widget is rendered
492
- // If we have a ticket, load its messages
493
- if (this._currentTicketId) {
494
- this._loadMessages();
495
- }
496
- // Start polling for messages to keep widget UI updated
497
- this._startPolling();
498
650
  };
499
651
  /**
500
652
  * Get initial user traits from PostHog or localStorage
@@ -604,7 +756,74 @@ var ConversationsManager = /** @class */ (function () {
604
756
  return this._persistence.loadWidgetState() === 'open';
605
757
  };
606
758
  /**
607
- * Start polling for new messages
759
+ * Load tickets list from API
760
+ */
761
+ ConversationsManager.prototype._loadTickets = function () {
762
+ return __awaiter(this, void 0, void 0, function () {
763
+ var response, totalUnread, error_4;
764
+ var _a, _b;
765
+ return __generator(this, function (_c) {
766
+ switch (_c.label) {
767
+ case 0:
768
+ _c.trys.push([0, 2, , 3]);
769
+ return [4 /*yield*/, this.getTickets()];
770
+ case 1:
771
+ response = _c.sent();
772
+ this._tickets = response.results;
773
+ this._hasMultipleTickets = response.results.length > 1;
774
+ (_a = this._widgetRef) === null || _a === void 0 ? void 0 : _a.updateTickets(response.results);
775
+ totalUnread = response.results.reduce(function (sum, t) { return sum + (t.unread_count || 0); }, 0);
776
+ this._unreadCount = totalUnread;
777
+ (_b = this._widgetRef) === null || _b === void 0 ? void 0 : _b.setUnreadCount(totalUnread);
778
+ logger.info('Tickets loaded', { count: response.results.length, totalUnread: totalUnread });
779
+ return [3 /*break*/, 3];
780
+ case 2:
781
+ error_4 = _c.sent();
782
+ logger.error('Failed to load tickets', error_4);
783
+ return [3 /*break*/, 3];
784
+ case 3: return [2 /*return*/];
785
+ }
786
+ });
787
+ });
788
+ };
789
+ /**
790
+ * Determine initial view based on ticket count
791
+ */
792
+ ConversationsManager.prototype._determineInitialView = function () {
793
+ return __awaiter(this, void 0, void 0, function () {
794
+ var response, totalUnread, error_5;
795
+ return __generator(this, function (_a) {
796
+ switch (_a.label) {
797
+ case 0:
798
+ _a.trys.push([0, 2, , 3]);
799
+ return [4 /*yield*/, this.getTickets()];
800
+ case 1:
801
+ response = _a.sent();
802
+ this._tickets = response.results;
803
+ this._hasMultipleTickets = response.results.length > 1;
804
+ totalUnread = response.results.reduce(function (sum, t) { return sum + (t.unread_count || 0); }, 0);
805
+ this._unreadCount = totalUnread;
806
+ // If 2+ tickets, show ticket list; otherwise show messages
807
+ if (response.results.length >= 2) {
808
+ return [2 /*return*/, { view: 'tickets', tickets: response.results }];
809
+ }
810
+ // If exactly 1 ticket, set it as current
811
+ if (response.results.length === 1) {
812
+ this._currentTicketId = response.results[0].id;
813
+ this._persistence.saveTicketId(response.results[0].id);
814
+ }
815
+ return [2 /*return*/, { view: 'messages', tickets: response.results }];
816
+ case 2:
817
+ error_5 = _a.sent();
818
+ logger.error('Failed to determine initial view', error_5);
819
+ return [2 /*return*/, { view: 'messages', tickets: [] }];
820
+ case 3: return [2 /*return*/];
821
+ }
822
+ });
823
+ });
824
+ };
825
+ /**
826
+ * Start polling based on current view
608
827
  */
609
828
  ConversationsManager.prototype._startPolling = function () {
610
829
  var _this = this;
@@ -612,12 +831,12 @@ var ConversationsManager = /** @class */ (function () {
612
831
  return; // Already polling
613
832
  }
614
833
  // Poll immediately
615
- this._pollMessages();
834
+ this._poll();
616
835
  // Set up interval
617
836
  this._pollIntervalId = globals_1.window === null || globals_1.window === void 0 ? void 0 : globals_1.window.setInterval(function () {
618
- _this._pollMessages();
837
+ _this._poll();
619
838
  }, POLL_INTERVAL_MS);
620
- logger.info('Started polling for messages');
839
+ logger.info('Started polling', { view: this._currentView });
621
840
  };
622
841
  /**
623
842
  * Stop polling for new messages
@@ -674,6 +893,7 @@ var ConversationsManager = /** @class */ (function () {
674
893
  }
675
894
  this._widgetRef = null;
676
895
  this._isWidgetRendered = false;
896
+ this._initializeWidgetPromise = null;
677
897
  // Reset timestamp so show() will re-fetch all messages
678
898
  this._lastMessageTimestamp = null;
679
899
  };
@@ -781,8 +1001,10 @@ var ConversationsManager = /** @class */ (function () {
781
1001
  /**
782
1002
  * Render the widget to the DOM
783
1003
  */
784
- ConversationsManager.prototype._renderWidget = function (initialState, initialUserTraits) {
1004
+ ConversationsManager.prototype._renderWidget = function (initialState, initialUserTraits, initialView, initialTickets) {
785
1005
  var _this = this;
1006
+ if (initialView === void 0) { initialView = 'messages'; }
1007
+ if (initialTickets === void 0) { initialTickets = []; }
786
1008
  if (!globals_1.document) {
787
1009
  logger.info('Conversations widget not rendered: Document not available');
788
1010
  return;
@@ -802,7 +1024,7 @@ var ConversationsManager = /** @class */ (function () {
802
1024
  // Render widget with ref
803
1025
  (0, preact_1.render)((0, jsx_runtime_1.jsx)(ConversationsWidget_1.ConversationsWidget, { ref: function (ref) {
804
1026
  _this._widgetRef = ref;
805
- }, config: this._config, initialState: initialState, initialUserTraits: initialUserTraits, isUserIdentified: this._posthog._isIdentified(), onSendMessage: this._handleSendMessage, onStateChange: this._handleStateChange, onIdentify: this._handleIdentify }), container);
1027
+ }, config: this._config, initialState: initialState, initialUserTraits: initialUserTraits, isUserIdentified: this._posthog._isIdentified(), initialView: initialView, initialTickets: initialTickets, hasMultipleTickets: this._hasMultipleTickets, onSendMessage: this._handleSendMessage, onStateChange: this._handleStateChange, onIdentify: this._handleIdentify, onSelectTicket: this._handleSelectTicket, onNewConversation: this._handleNewConversation, onBackToTickets: this._handleBackToTickets, onViewChange: this._handleViewChange }), container);
806
1028
  };
807
1029
  return ConversationsManager;
808
1030
  }());
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/extensions/conversations/external/index.tsx"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { render, h } from 'preact'\nimport { isNumber } from '@posthog/core'\nimport {\n ConversationsRemoteConfig,\n ConversationsWidgetState,\n UserProvidedTraits,\n SendMessageResponse,\n SendMessagePayload,\n GetMessagesResponse,\n MarkAsReadResponse,\n GetTicketsOptions,\n GetTicketsResponse,\n} from '../../../posthog-conversations-types'\nimport { PostHog } from '../../../posthog-core'\nimport { ConversationsManager as ConversationsManagerInterface } from '../posthog-conversations'\nimport { ConversationsPersistence } from './persistence'\nimport { ConversationsWidget } from './components/ConversationsWidget'\nimport { createLogger } from '../../../utils/logger'\nimport { document, window } from '../../../utils/globals'\nimport { formDataToQuery } from '../../../utils/request-utils'\n\nconst logger = createLogger('[ConversationsManager]')\n\nconst WIDGET_CONTAINER_ID = 'ph-conversations-widget-container'\nconst POLL_INTERVAL_MS = 5000 // 5 seconds\n\n/**\n * Extract hostname from a domain string (handles URLs and plain hostnames)\n */\nfunction extractHostname(domain: string): string | null {\n // Remove protocol if present\n let hostname = domain.replace(/^https?:\\/\\//, '')\n // Remove path, query, port if present\n hostname = hostname.split('/')[0].split('?')[0].split(':')[0]\n return hostname || null\n}\n\n/**\n * Check if the current domain matches the allowed domains list.\n * Returns true if:\n * - domains is empty or not present (no restriction)\n * - current hostname matches any allowed domain\n */\nfunction isCurrentDomainAllowed(domains: string[] | undefined): boolean {\n // No domain restriction - allow all\n if (!domains || domains.length === 0) {\n return true\n }\n\n const currentHostname = window?.location?.hostname\n if (!currentHostname) {\n // Can't determine hostname (SSR, etc.) - allow by default\n return true\n }\n\n return domains.some((domain) => {\n const allowedHostname = extractHostname(domain)\n if (!allowedHostname) {\n return false\n }\n\n if (allowedHostname.startsWith('*.')) {\n // Wildcard match: *.example.com matches foo.example.com and example.com\n const pattern = allowedHostname.slice(2) // Remove \"*.\"\n return currentHostname.endsWith(`.${pattern}`) || currentHostname === pattern\n }\n\n // Exact match\n return currentHostname === allowedHostname\n })\n}\n\nexport class ConversationsManager implements ConversationsManagerInterface {\n private _config: ConversationsRemoteConfig\n private _persistence: ConversationsPersistence\n private _widgetRef: ConversationsWidget | null = null\n private _containerElement: HTMLDivElement | null = null\n private _currentTicketId: string | null = null\n private _pollIntervalId: number | null = null\n private _lastMessageTimestamp: string | null = null\n private _isPolling: boolean = false\n private _unsubscribeIdentifyListener: (() => void) | null = null\n private _unreadCount: number = 0\n // SECURITY: widget_session_id is the key for access control\n // This is a random UUID that only this browser knows\n private _widgetSessionId: string\n private _isWidgetEnabled: boolean\n private _isDomainAllowed: boolean\n private _isWidgetRendered: boolean = false\n\n constructor(\n config: ConversationsRemoteConfig,\n private readonly _posthog: PostHog\n ) {\n this._config = config\n this._persistence = new ConversationsPersistence(_posthog)\n // Get or create widget_session_id - this stays the same even when user identifies\n this._widgetSessionId = this._persistence.getOrCreateWidgetSessionId()\n\n // Determine if widget should be shown based on config and domain\n this._isWidgetEnabled = config.widgetEnabled === true\n this._isDomainAllowed = isCurrentDomainAllowed(config.domains)\n\n logger.info('ConversationsManager initialized', {\n config,\n widgetSessionId: this._widgetSessionId,\n isWidgetEnabled: this._isWidgetEnabled,\n isDomainAllowed: this._isDomainAllowed,\n })\n\n this._initialize()\n }\n\n /**\n * Send a message programmatically via the API\n * Creates a new ticket if none exists or if newTicket is true\n *\n * @param message - The message text to send\n * @param userTraits - Optional user identification data (name, email)\n * @param newTicket - If true, forces creation of a new ticket (ignores current ticket)\n * @returns Promise with the response including ticket_id and message_id\n */\n async sendMessage(\n message: string,\n userTraits?: UserProvidedTraits,\n newTicket?: boolean\n ): Promise<SendMessageResponse> {\n // Determine which ticket to use\n // If newTicket is true, force creation of new ticket by sending null\n // Otherwise use current ticket ID (which may be null if no ticket exists yet)\n const ticketId = newTicket ? null : this._currentTicketId\n\n // Track if this is creating a new ticket\n const isNewTicket = !ticketId\n\n const token = this._config.token\n\n // eslint-disable-next-line compat/compat\n return new Promise((resolve, reject) => {\n const distinctId = this._posthog.get_distinct_id()\n const personProperties = this._posthog.persistence?.props || {}\n\n // Priority for traits:\n // 1. User-provided traits from the widget form\n // 2. PostHog person properties\n const name = userTraits?.name || personProperties.$name || personProperties.name || null\n const email = userTraits?.email || personProperties.$email || personProperties.email || null\n\n const payload: Partial<SendMessagePayload> = {\n widget_session_id: this._widgetSessionId,\n // distinct_id is only used for Person linking, not access control\n distinct_id: distinctId,\n message: message.trim(),\n traits: {\n name,\n email,\n },\n ticket_id: ticketId,\n }\n\n try {\n // Capture session ID - sent with every message\n const capturedSessionId = this._posthog.get_session_id()\n if (capturedSessionId) {\n payload.session_id = capturedSessionId\n }\n\n // Capture session replay URL with timestamp - sent with every message\n const replayUrl = this._posthog.get_session_replay_url({\n withTimestamp: true,\n timestampLookBack: 30,\n })\n\n // Capture current URL - only for new tickets to record where user started\n const currentUrl = isNewTicket ? window?.location?.href : undefined\n\n if (replayUrl || currentUrl) {\n payload.session_context = {\n session_replay_url: replayUrl || undefined,\n current_url: currentUrl || undefined,\n }\n }\n } catch (error) {\n // Log error but don't fail message sending\n logger.warn('Failed to capture session context', error)\n }\n\n this._posthog._send_request({\n url: this._posthog.requestRouter.endpointFor('api', '/api/conversations/v1/widget/message'),\n method: 'POST',\n data: payload,\n headers: {\n 'X-Conversations-Token': token,\n },\n callback: (response) => {\n if (response.statusCode === 429) {\n reject(new Error('Too many requests. Please wait before trying again.'))\n return\n }\n\n if (response.statusCode !== 200 && response.statusCode !== 201) {\n const errorMsg = response.json?.detail || response.json?.message || 'Failed to send message'\n logger.error('Failed to send message', { status: response.statusCode })\n reject(new Error(errorMsg))\n return\n }\n\n if (!response.json) {\n reject(new Error('Invalid response from server'))\n return\n }\n\n const data = response.json as SendMessageResponse\n\n // Update current ticket ID if this was a new ticket\n // This happens when: 1) No ticket existed, or 2) User forced new ticket creation\n if (isNewTicket && data.ticket_id) {\n this._currentTicketId = data.ticket_id\n this._persistence.saveTicketId(data.ticket_id)\n logger.info('New ticket created', {\n ticketId: data.ticket_id,\n forced: newTicket === true,\n })\n }\n\n // Track message sent\n this._posthog.capture('$conversations_message_sent', {\n ticketId: data.ticket_id,\n isNewTicket: isNewTicket,\n messageLength: message.length,\n })\n\n // Update last message timestamp\n this._lastMessageTimestamp = data.created_at\n\n resolve(data)\n },\n })\n })\n }\n\n /**\n * Switch to a different ticket if an explicit ticketId is provided\n * This ensures subsequent operations (sendMessage, etc.) use the correct ticket\n */\n private _switchToTicketIfNeeded(ticketId: string | undefined): void {\n if (ticketId && ticketId !== this._currentTicketId) {\n this._currentTicketId = ticketId\n this._persistence.saveTicketId(ticketId)\n // Reset last message timestamp when switching tickets\n this._lastMessageTimestamp = null\n }\n }\n\n /** Fetch messages via the API */\n async getMessages(ticketId?: string, after?: string): Promise<GetMessagesResponse> {\n // Use provided ticketId or fall back to current ticket\n const targetTicketId = ticketId || this._currentTicketId\n\n if (!targetTicketId) {\n throw new Error('No ticket ID provided and no active conversation')\n }\n\n // Switch to this ticket if explicitly provided\n this._switchToTicketIfNeeded(ticketId)\n\n const token = this._config.token\n\n // eslint-disable-next-line compat/compat\n return new Promise((resolve, reject) => {\n // SECURITY: widget_session_id is required for access control\n // distinct_id is NOT sent for getMessages - access is controlled by widget_session_id only\n const queryParams: Record<string, string> = {\n widget_session_id: this._widgetSessionId,\n limit: '50',\n }\n\n if (after) {\n queryParams.after = after\n }\n\n this._posthog._send_request({\n url: this._posthog.requestRouter.endpointFor(\n 'api',\n `/api/conversations/v1/widget/messages/${targetTicketId}?${formDataToQuery(queryParams)}`\n ),\n method: 'GET',\n headers: {\n 'X-Conversations-Token': token,\n },\n callback: (response) => {\n if (response.statusCode === 429) {\n reject(new Error('Too many requests. Please wait before trying again.'))\n return\n }\n\n if (response.statusCode !== 200) {\n const errorMsg = response.json?.detail || response.json?.message || 'Failed to fetch messages'\n logger.error('Failed to fetch messages', { status: response.statusCode })\n reject(new Error(errorMsg))\n return\n }\n\n if (!response.json) {\n reject(new Error('Invalid response from server'))\n return\n }\n\n const data = response.json as GetMessagesResponse\n resolve(data)\n },\n })\n })\n }\n\n /** Mark messages as read via the API */\n async markAsRead(ticketId?: string): Promise<MarkAsReadResponse> {\n // Use provided ticketId or fall back to current ticket\n const targetTicketId = ticketId || this._currentTicketId\n\n if (!targetTicketId) {\n throw new Error('No ticket ID provided and no active conversation')\n }\n\n // Switch to this ticket if explicitly provided\n this._switchToTicketIfNeeded(ticketId)\n\n const token = this._config.token\n\n logger.info('Marking messages as read', { ticketId: targetTicketId })\n\n // eslint-disable-next-line compat/compat\n return new Promise((resolve, reject) => {\n this._posthog._send_request({\n url: this._posthog.requestRouter.endpointFor(\n 'api',\n `/api/conversations/v1/widget/messages/${targetTicketId}/read`\n ),\n method: 'POST',\n data: {\n widget_session_id: this._widgetSessionId,\n },\n headers: {\n 'X-Conversations-Token': token,\n },\n callback: (response) => {\n if (response.statusCode === 429) {\n reject(new Error('Too many requests. Please wait before trying again.'))\n return\n }\n\n if (response.statusCode !== 200) {\n const errorMsg =\n response.json?.detail || response.json?.message || 'Failed to mark messages as read'\n logger.error('Failed to mark messages as read', { status: response.statusCode })\n reject(new Error(errorMsg))\n return\n }\n\n if (!response.json) {\n reject(new Error('Invalid response from server'))\n return\n }\n\n const data = response.json as MarkAsReadResponse\n resolve(data)\n },\n })\n })\n }\n\n /**\n * Initialize the conversations manager.\n * Always initializes persistence and event listeners for API usage.\n * Only renders the widget if widgetEnabled is true AND domain is allowed.\n */\n private _initialize(): void {\n if (!document || !window) {\n logger.info('Conversations not available: Document or window not available')\n return\n }\n\n // Load any existing ticket ID from localStorage\n this._currentTicketId = this._persistence.loadTicketId()\n logger.info('Loaded ticket ID from storage', { ticketId: this._currentTicketId })\n\n // Track conversations API loaded (separate from widget loaded)\n this._posthog.capture('$conversations_loaded', {\n hasExistingTicket: !!this._currentTicketId,\n widgetEnabled: this._isWidgetEnabled,\n domainAllowed: this._isDomainAllowed,\n })\n\n // Only render widget if both widgetEnabled and domain is allowed\n if (this._isWidgetEnabled && this._isDomainAllowed) {\n this._initializeWidget()\n } else {\n logger.info('Widget not rendered', {\n widgetEnabled: this._isWidgetEnabled,\n domainAllowed: this._isDomainAllowed,\n })\n }\n\n // Listen for identify events to hide identification form when user identifies\n this._setupIdentifyListener()\n }\n\n /**\n * Initialize and render the widget UI\n */\n private _initializeWidget(): void {\n if (this._isWidgetRendered) {\n return // Already rendered\n }\n\n const savedState = this._persistence.loadWidgetState()\n let initialState: ConversationsWidgetState = 'closed'\n if (savedState === 'open') {\n initialState = 'open'\n }\n\n // Get initial user traits (from PostHog person properties or saved)\n const initialUserTraits = this._getInitialUserTraits()\n\n // Render the widget\n this._renderWidget(initialState, initialUserTraits)\n this._isWidgetRendered = true\n\n // Track widget initialization\n this._posthog.capture('$conversations_widget_loaded', {\n hasExistingTicket: !!this._currentTicketId,\n initialState: initialState,\n hasUserTraits: !!initialUserTraits,\n })\n\n // Set up polling and load messages only when widget is rendered\n // If we have a ticket, load its messages\n if (this._currentTicketId) {\n this._loadMessages()\n }\n\n // Start polling for messages to keep widget UI updated\n this._startPolling()\n }\n\n /**\n * Get initial user traits from PostHog or localStorage\n */\n private _getInitialUserTraits(): UserProvidedTraits | null {\n // First, check PostHog's person properties\n const personProperties = this._posthog.persistence?.props || {}\n const posthogName = personProperties.$name || personProperties.name\n const posthogEmail = personProperties.$email || personProperties.email\n\n // If we have traits from PostHog, use those\n if (posthogName || posthogEmail) {\n return {\n name: posthogName || undefined,\n email: posthogEmail || undefined,\n }\n }\n\n // Otherwise, check localStorage for previously saved traits\n const savedTraits = this._persistence.loadUserTraits()\n if (savedTraits && (savedTraits.name || savedTraits.email)) {\n return savedTraits\n }\n\n return null\n }\n\n /**\n * Handle user identification from the widget form\n */\n private _handleIdentify = (traits: UserProvidedTraits): void => {\n // Save traits to localStorage\n this._persistence.saveUserTraits(traits)\n\n // Track identification\n this._posthog.capture('$conversations_user_identified', {\n hasName: !!traits.name,\n hasEmail: !!traits.email,\n })\n }\n\n /**\n * Handle sending a message from the widget\n */\n private _handleSendMessage = async (message: string): Promise<void> => {\n // Get user traits from the widget\n const userTraits = this._widgetRef?.getUserTraits() || undefined\n\n try {\n // Call the public API method (which handles tracking and state updates)\n await this.sendMessage(message, userTraits)\n\n // Poll for response immediately\n setTimeout(() => this._pollMessages(), 1000)\n } catch (error) {\n logger.error('Failed to send message', error)\n throw error\n }\n }\n\n /**\n * Handle widget state changes\n */\n private _handleStateChange = (state: ConversationsWidgetState): void => {\n logger.info('Widget state changed', { state })\n\n // Track state changes\n this._posthog.capture('$conversations_widget_state_changed', {\n state: state,\n ticketId: this._currentTicketId,\n })\n\n // Save state to localStorage\n this._persistence.saveWidgetState(state)\n\n // Mark messages as read when widget opens\n if (state === 'open') {\n if (this._unreadCount > 0 && this._currentTicketId) {\n this._markMessagesAsRead()\n }\n }\n }\n\n /**\n * Mark messages as read\n */\n private async _markMessagesAsRead(): Promise<void> {\n if (!this._currentTicketId) {\n return\n }\n\n try {\n const response = await this.markAsRead(this._currentTicketId || undefined)\n this._unreadCount = response.unread_count\n // Update the widget to reflect the new unread count\n this._widgetRef?.setUnreadCount(0)\n logger.info('Messages marked as read', { unreadCount: response.unread_count })\n } catch (error) {\n logger.error('Failed to mark messages as read', error)\n }\n }\n\n /**\n * Load messages for the current ticket\n */\n private async _loadMessages(): Promise<void> {\n if (!this._currentTicketId) {\n return\n }\n\n try {\n const response = await this.getMessages(\n this._currentTicketId || undefined,\n this._lastMessageTimestamp || undefined\n )\n\n // Update unread count from response\n if (isNumber(response.unread_count)) {\n this._unreadCount = response.unread_count\n this._widgetRef?.setUnreadCount(response.unread_count)\n\n // If widget is open and there are unread messages, mark them as read\n if (response.unread_count > 0 && this._isWidgetOpen()) {\n this._markMessagesAsRead()\n }\n }\n\n if (response.messages.length > 0) {\n this._widgetRef?.addMessages(response.messages)\n // Update last message timestamp\n const lastMessage = response.messages[response.messages.length - 1]\n this._lastMessageTimestamp = lastMessage.created_at\n }\n } catch (error) {\n logger.error('Failed to load messages', error)\n }\n }\n\n /**\n * Check if the widget is currently open\n */\n private _isWidgetOpen(): boolean {\n return this._persistence.loadWidgetState() === 'open'\n }\n\n /**\n * Poll for new messages\n */\n private _pollMessages = async (): Promise<void> => {\n if (this._isPolling || !this._currentTicketId) {\n return\n }\n\n this._isPolling = true\n try {\n await this._loadMessages()\n } finally {\n this._isPolling = false\n }\n }\n\n /**\n * Start polling for new messages\n */\n private _startPolling(): void {\n if (this._pollIntervalId) {\n return // Already polling\n }\n\n // Poll immediately\n this._pollMessages()\n\n // Set up interval\n this._pollIntervalId = window?.setInterval(() => {\n this._pollMessages()\n }, POLL_INTERVAL_MS) as unknown as number\n\n logger.info('Started polling for messages')\n }\n\n /**\n * Stop polling for new messages\n */\n private _stopPolling(): void {\n if (this._pollIntervalId) {\n window?.clearInterval(this._pollIntervalId)\n this._pollIntervalId = null\n logger.info('Stopped polling for messages')\n }\n }\n\n /**\n * Setup listener for identify events.\n * When user calls posthog.identify(), hide the identification form\n * since we now know who they are.\n */\n private _setupIdentifyListener(): void {\n this._unsubscribeIdentifyListener = this._posthog.on('eventCaptured', (event: any) => {\n if (event.event === '$identify') {\n // User just identified - hide the identification form if it's showing\n this._widgetRef?.setUserIdentified()\n }\n })\n }\n\n /**\n * Show the widget (render it to DOM).\n * The widget respects its saved state (open/closed).\n * Note: Domain restrictions still apply - widget won't render on disallowed domains.\n */\n show(): void {\n // Check domain restrictions - don't render on disallowed domains\n if (!this._isDomainAllowed) {\n logger.warn('Cannot show widget: current domain is not allowed')\n return\n }\n\n // If widget isn't rendered yet, render it now\n if (!this._isWidgetRendered) {\n this._initializeWidget()\n }\n }\n\n /**\n * Hide and remove the widget from the DOM.\n * Conversation data is preserved - call show() to re-render.\n */\n hide(): void {\n // Stop polling when widget is hidden (save resources)\n this._stopPolling()\n\n if (this._containerElement) {\n render(null, this._containerElement)\n this._containerElement.remove()\n this._containerElement = null\n }\n this._widgetRef = null\n this._isWidgetRendered = false\n\n // Reset timestamp so show() will re-fetch all messages\n this._lastMessageTimestamp = null\n }\n\n /**\n * Check if the widget is currently visible (rendered in DOM)\n */\n isVisible(): boolean {\n return this._isWidgetRendered\n }\n\n /** Get tickets list for the current widget session */\n async getTickets(options?: GetTicketsOptions): Promise<GetTicketsResponse> {\n const token = this._config.token\n\n const queryParams: Record<string, string> = {\n widget_session_id: this._widgetSessionId,\n limit: String(options?.limit ?? 20),\n offset: String(options?.offset ?? 0),\n }\n\n if (options?.status) {\n queryParams.status = options.status\n }\n\n // eslint-disable-next-line compat/compat\n return new Promise((resolve, reject) => {\n this._posthog._send_request({\n url: this._posthog.requestRouter.endpointFor(\n 'api',\n `/api/conversations/v1/widget/tickets?${formDataToQuery(queryParams)}`\n ),\n method: 'GET',\n headers: {\n 'X-Conversations-Token': token,\n },\n callback: (response) => {\n if (response.statusCode === 429) {\n reject(new Error('Too many requests. Please wait before trying again.'))\n return\n }\n\n if (response.statusCode !== 200) {\n const errorMsg = response.json?.detail || response.json?.message || 'Failed to fetch tickets'\n logger.error('Failed to fetch tickets', { status: response.statusCode })\n reject(new Error(errorMsg))\n return\n }\n\n if (!response.json) {\n reject(new Error('Invalid response from server'))\n return\n }\n\n const data = response.json as GetTicketsResponse\n resolve(data)\n },\n })\n })\n }\n\n /**\n * Get the current active ticket ID\n * Returns null if no conversation has been started yet\n */\n getCurrentTicketId(): string | null {\n return this._currentTicketId\n }\n\n /**\n * Get the widget session ID (persistent browser identifier)\n * This ID is used for access control and stays the same across page loads\n */\n getWidgetSessionId(): string {\n return this._widgetSessionId\n }\n\n /**\n * Clean up the widget\n */\n destroy(): void {\n this._stopPolling()\n\n // Unsubscribe from identify events\n if (this._unsubscribeIdentifyListener) {\n this._unsubscribeIdentifyListener()\n this._unsubscribeIdentifyListener = null\n }\n\n if (this._containerElement) {\n render(null, this._containerElement)\n this._containerElement.remove()\n this._containerElement = null\n }\n\n this._widgetRef = null\n logger.info('Widget destroyed')\n }\n\n /**\n * Reset all conversation data and destroy the widget.\n * Called on posthog.reset() to start fresh.\n */\n reset(): void {\n // Clear all persisted conversation data\n this._persistence.clearAll()\n\n // Reset local state\n this._currentTicketId = null\n this._lastMessageTimestamp = null\n this._unreadCount = 0\n\n // Destroy the widget\n this.destroy()\n\n logger.info('Conversations reset')\n }\n\n /**\n * Render the widget to the DOM\n */\n private _renderWidget(initialState: ConversationsWidgetState, initialUserTraits: UserProvidedTraits | null): void {\n if (!document) {\n logger.info('Conversations widget not rendered: Document not available')\n return\n }\n\n // Create container if it doesn't exist\n let container = document.getElementById(WIDGET_CONTAINER_ID) as HTMLDivElement\n if (!container) {\n if (!document.body) {\n logger.info('Conversations widget not rendered: Document body not available yet')\n return\n }\n container = document.createElement('div')\n container.id = WIDGET_CONTAINER_ID\n document.body.appendChild(container)\n }\n this._containerElement = container\n\n // Render widget with ref\n render(\n <ConversationsWidget\n ref={(ref: ConversationsWidget | null) => {\n this._widgetRef = ref\n }}\n config={this._config}\n initialState={initialState}\n initialUserTraits={initialUserTraits}\n isUserIdentified={this._posthog._isIdentified()}\n onSendMessage={this._handleSendMessage}\n onStateChange={this._handleStateChange}\n onIdentify={this._handleIdentify}\n />,\n container\n )\n }\n}\n\n/**\n * Initialize the conversations widget\n * This is the entry point called from the lazy-loaded bundle\n */\nexport function initConversations(config: ConversationsRemoteConfig, posthog: PostHog): ConversationsManager {\n logger.info('initConversations called', { hasConfig: !!config, hasPosthog: !!posthog })\n return new ConversationsManager(config, posthog)\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/extensions/conversations/external/index.tsx"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { render, h } from 'preact'\nimport { isNumber } from '@posthog/core'\nimport {\n ConversationsRemoteConfig,\n ConversationsWidgetState,\n UserProvidedTraits,\n SendMessageResponse,\n SendMessagePayload,\n GetMessagesResponse,\n MarkAsReadResponse,\n GetTicketsOptions,\n GetTicketsResponse,\n Ticket,\n} from '../../../posthog-conversations-types'\nimport { PostHog } from '../../../posthog-core'\nimport { ConversationsManager as ConversationsManagerInterface } from '../posthog-conversations'\nimport { ConversationsPersistence } from './persistence'\nimport { ConversationsWidget, WidgetView } from './components/ConversationsWidget'\nimport { createLogger } from '../../../utils/logger'\nimport { document, window } from '../../../utils/globals'\nimport { formDataToQuery } from '../../../utils/request-utils'\n\nconst logger = createLogger('[ConversationsManager]')\n\nconst WIDGET_CONTAINER_ID = 'ph-conversations-widget-container'\nconst POLL_INTERVAL_MS = 5000 // 5 seconds\n\n/**\n * Extract hostname from a domain string (handles URLs and plain hostnames)\n */\nfunction extractHostname(domain: string): string | null {\n // Remove protocol if present\n let hostname = domain.replace(/^https?:\\/\\//, '')\n // Remove path, query, port if present\n hostname = hostname.split('/')[0].split('?')[0].split(':')[0]\n return hostname || null\n}\n\n/**\n * Check if the current domain matches the allowed domains list.\n * Returns true if:\n * - domains is empty or not present (no restriction)\n * - current hostname matches any allowed domain\n */\nfunction isCurrentDomainAllowed(domains: string[] | undefined): boolean {\n // No domain restriction - allow all\n if (!domains || domains.length === 0) {\n return true\n }\n\n const currentHostname = window?.location?.hostname\n if (!currentHostname) {\n // Can't determine hostname (SSR, etc.) - allow by default\n return true\n }\n\n return domains.some((domain) => {\n const allowedHostname = extractHostname(domain)\n if (!allowedHostname) {\n return false\n }\n\n if (allowedHostname.startsWith('*.')) {\n // Wildcard match: *.example.com matches foo.example.com and example.com\n const pattern = allowedHostname.slice(2) // Remove \"*.\"\n return currentHostname.endsWith(`.${pattern}`) || currentHostname === pattern\n }\n\n // Exact match\n return currentHostname === allowedHostname\n })\n}\n\nexport class ConversationsManager implements ConversationsManagerInterface {\n private _config: ConversationsRemoteConfig\n private _persistence: ConversationsPersistence\n private _widgetRef: ConversationsWidget | null = null\n private _containerElement: HTMLDivElement | null = null\n private _currentTicketId: string | null = null\n private _pollIntervalId: number | null = null\n private _lastMessageTimestamp: string | null = null\n private _isPolling: boolean = false\n private _unsubscribeIdentifyListener: (() => void) | null = null\n private _unreadCount: number = 0\n // SECURITY: widget_session_id is the key for access control\n // This is a random UUID that only this browser knows\n private _widgetSessionId: string\n private _isWidgetEnabled: boolean\n private _isDomainAllowed: boolean\n private _isWidgetRendered: boolean = false\n private _initializeWidgetPromise: Promise<void> | null = null\n // View state management for ticket list vs message view\n private _currentView: WidgetView = 'messages'\n private _tickets: Ticket[] = []\n private _hasMultipleTickets: boolean = false\n\n constructor(\n config: ConversationsRemoteConfig,\n private readonly _posthog: PostHog\n ) {\n this._config = config\n this._persistence = new ConversationsPersistence(_posthog)\n // Get or create widget_session_id - this stays the same even when user identifies\n this._widgetSessionId = this._persistence.getOrCreateWidgetSessionId()\n\n // Determine if widget should be shown based on config and domain\n this._isWidgetEnabled = config.widgetEnabled === true\n this._isDomainAllowed = isCurrentDomainAllowed(config.domains)\n\n logger.info('ConversationsManager initialized', {\n config,\n widgetSessionId: this._widgetSessionId,\n isWidgetEnabled: this._isWidgetEnabled,\n isDomainAllowed: this._isDomainAllowed,\n })\n\n this._initialize()\n }\n\n /**\n * Send a message programmatically via the API\n * Creates a new ticket if none exists or if newTicket is true\n *\n * @param message - The message text to send\n * @param userTraits - Optional user identification data (name, email)\n * @param newTicket - If true, forces creation of a new ticket (ignores current ticket)\n * @returns Promise with the response including ticket_id and message_id\n */\n async sendMessage(\n message: string,\n userTraits?: UserProvidedTraits,\n newTicket?: boolean\n ): Promise<SendMessageResponse> {\n // Determine which ticket to use\n // If newTicket is true, force creation of new ticket by sending null\n // Otherwise use current ticket ID (which may be null if no ticket exists yet)\n const ticketId = newTicket ? null : this._currentTicketId\n\n // Track if this is creating a new ticket\n const isNewTicket = !ticketId\n\n const token = this._config.token\n\n // eslint-disable-next-line compat/compat\n return new Promise((resolve, reject) => {\n const distinctId = this._posthog.get_distinct_id()\n const personProperties = this._posthog.persistence?.props || {}\n\n // Priority for traits:\n // 1. User-provided traits from the widget form\n // 2. PostHog person properties\n const name = userTraits?.name || personProperties.$name || personProperties.name || null\n const email = userTraits?.email || personProperties.$email || personProperties.email || null\n\n const payload: Partial<SendMessagePayload> = {\n widget_session_id: this._widgetSessionId,\n // distinct_id is only used for Person linking, not access control\n distinct_id: distinctId,\n message: message.trim(),\n traits: {\n name,\n email,\n },\n ticket_id: ticketId,\n }\n\n try {\n // Capture session ID - sent with every message\n const capturedSessionId = this._posthog.get_session_id()\n if (capturedSessionId) {\n payload.session_id = capturedSessionId\n }\n\n // Capture session replay URL with timestamp - sent with every message\n const replayUrl = this._posthog.get_session_replay_url({\n withTimestamp: true,\n timestampLookBack: 30,\n })\n\n // Capture current URL - only for new tickets to record where user started\n const currentUrl = isNewTicket ? window?.location?.href : undefined\n\n if (replayUrl || currentUrl) {\n payload.session_context = {\n session_replay_url: replayUrl || undefined,\n current_url: currentUrl || undefined,\n }\n }\n } catch (error) {\n // Log error but don't fail message sending\n logger.warn('Failed to capture session context', error)\n }\n\n this._posthog._send_request({\n url: this._posthog.requestRouter.endpointFor('api', '/api/conversations/v1/widget/message'),\n method: 'POST',\n data: payload,\n headers: {\n 'X-Conversations-Token': token,\n },\n callback: (response) => {\n if (response.statusCode === 429) {\n reject(new Error('Too many requests. Please wait before trying again.'))\n return\n }\n\n if (response.statusCode !== 200 && response.statusCode !== 201) {\n const errorMsg = response.json?.detail || response.json?.message || 'Failed to send message'\n logger.error('Failed to send message', { status: response.statusCode })\n reject(new Error(errorMsg))\n return\n }\n\n if (!response.json) {\n reject(new Error('Invalid response from server'))\n return\n }\n\n const data = response.json as SendMessageResponse\n\n // Update current ticket ID if this was a new ticket\n // This happens when: 1) No ticket existed, or 2) User forced new ticket creation\n if (isNewTicket && data.ticket_id) {\n this._currentTicketId = data.ticket_id\n this._persistence.saveTicketId(data.ticket_id)\n logger.info('New ticket created', {\n ticketId: data.ticket_id,\n forced: newTicket === true,\n })\n }\n\n // Track message sent\n this._posthog.capture('$conversations_message_sent', {\n ticketId: data.ticket_id,\n isNewTicket: isNewTicket,\n messageLength: message.length,\n })\n\n // Update last message timestamp\n this._lastMessageTimestamp = data.created_at\n\n resolve(data)\n },\n })\n })\n }\n\n /**\n * Switch to a different ticket if an explicit ticketId is provided\n * This ensures subsequent operations (sendMessage, etc.) use the correct ticket\n */\n private _switchToTicketIfNeeded(ticketId: string | undefined): void {\n if (ticketId && ticketId !== this._currentTicketId) {\n this._currentTicketId = ticketId\n this._persistence.saveTicketId(ticketId)\n // Reset last message timestamp when switching tickets\n this._lastMessageTimestamp = null\n }\n }\n\n /** Fetch messages via the API */\n async getMessages(ticketId?: string, after?: string): Promise<GetMessagesResponse> {\n // Use provided ticketId or fall back to current ticket\n const targetTicketId = ticketId || this._currentTicketId\n\n if (!targetTicketId) {\n throw new Error('No ticket ID provided and no active conversation')\n }\n\n // Switch to this ticket if explicitly provided\n this._switchToTicketIfNeeded(ticketId)\n\n const token = this._config.token\n\n // eslint-disable-next-line compat/compat\n return new Promise((resolve, reject) => {\n // SECURITY: widget_session_id is required for access control\n // distinct_id is NOT sent for getMessages - access is controlled by widget_session_id only\n const queryParams: Record<string, string> = {\n widget_session_id: this._widgetSessionId,\n limit: '50',\n }\n\n if (after) {\n queryParams.after = after\n }\n\n this._posthog._send_request({\n url: this._posthog.requestRouter.endpointFor(\n 'api',\n `/api/conversations/v1/widget/messages/${targetTicketId}?${formDataToQuery(queryParams)}`\n ),\n method: 'GET',\n headers: {\n 'X-Conversations-Token': token,\n },\n callback: (response) => {\n if (response.statusCode === 429) {\n reject(new Error('Too many requests. Please wait before trying again.'))\n return\n }\n\n if (response.statusCode !== 200) {\n const errorMsg = response.json?.detail || response.json?.message || 'Failed to fetch messages'\n logger.error('Failed to fetch messages', { status: response.statusCode })\n reject(new Error(errorMsg))\n return\n }\n\n if (!response.json) {\n reject(new Error('Invalid response from server'))\n return\n }\n\n const data = response.json as GetMessagesResponse\n resolve(data)\n },\n })\n })\n }\n\n /** Mark messages as read via the API */\n async markAsRead(ticketId?: string): Promise<MarkAsReadResponse> {\n // Use provided ticketId or fall back to current ticket\n const targetTicketId = ticketId || this._currentTicketId\n\n if (!targetTicketId) {\n throw new Error('No ticket ID provided and no active conversation')\n }\n\n // Switch to this ticket if explicitly provided\n this._switchToTicketIfNeeded(ticketId)\n\n const token = this._config.token\n\n logger.info('Marking messages as read', { ticketId: targetTicketId })\n\n // eslint-disable-next-line compat/compat\n return new Promise((resolve, reject) => {\n this._posthog._send_request({\n url: this._posthog.requestRouter.endpointFor(\n 'api',\n `/api/conversations/v1/widget/messages/${targetTicketId}/read`\n ),\n method: 'POST',\n data: {\n widget_session_id: this._widgetSessionId,\n },\n headers: {\n 'X-Conversations-Token': token,\n },\n callback: (response) => {\n if (response.statusCode === 429) {\n reject(new Error('Too many requests. Please wait before trying again.'))\n return\n }\n\n if (response.statusCode !== 200) {\n const errorMsg =\n response.json?.detail || response.json?.message || 'Failed to mark messages as read'\n logger.error('Failed to mark messages as read', { status: response.statusCode })\n reject(new Error(errorMsg))\n return\n }\n\n if (!response.json) {\n reject(new Error('Invalid response from server'))\n return\n }\n\n const data = response.json as MarkAsReadResponse\n resolve(data)\n },\n })\n })\n }\n\n /**\n * Initialize the conversations manager.\n * Always initializes persistence and event listeners for API usage.\n * Only renders the widget if widgetEnabled is true AND domain is allowed.\n */\n private _initialize(): void {\n if (!document || !window) {\n logger.info('Conversations not available: Document or window not available')\n return\n }\n\n // Load any existing ticket ID from localStorage\n this._currentTicketId = this._persistence.loadTicketId()\n logger.info('Loaded ticket ID from storage', { ticketId: this._currentTicketId })\n\n // Track conversations API loaded (separate from widget loaded)\n this._posthog.capture('$conversations_loaded', {\n hasExistingTicket: !!this._currentTicketId,\n widgetEnabled: this._isWidgetEnabled,\n domainAllowed: this._isDomainAllowed,\n })\n\n // Only render widget if both widgetEnabled and domain is allowed\n if (this._isWidgetEnabled && this._isDomainAllowed) {\n this._initializeWidget()\n } else {\n logger.info('Widget not rendered', {\n widgetEnabled: this._isWidgetEnabled,\n domainAllowed: this._isDomainAllowed,\n })\n }\n\n // Listen for identify events to hide identification form when user identifies\n this._setupIdentifyListener()\n }\n\n /**\n * Initialize and render the widget UI\n * Uses a promise guard to prevent race conditions from concurrent calls\n */\n private _initializeWidget(): Promise<void> {\n if (this._isWidgetRendered) {\n return Promise.resolve()\n }\n if (this._initializeWidgetPromise) {\n return this._initializeWidgetPromise\n }\n this._initializeWidgetPromise = this._doInitializeWidget()\n return this._initializeWidgetPromise\n }\n\n private async _doInitializeWidget(): Promise<void> {\n const savedState = this._persistence.loadWidgetState()\n let initialState: ConversationsWidgetState = 'closed'\n if (savedState === 'open') {\n initialState = 'open'\n }\n\n // Get initial user traits (from PostHog person properties or saved)\n const initialUserTraits = this._getInitialUserTraits()\n\n // Determine initial view based on ticket count\n const { view: initialView, tickets } = await this._determineInitialView()\n this._currentView = initialView\n\n // Render the widget with initial view\n this._renderWidget(initialState, initialUserTraits, initialView, tickets)\n this._isWidgetRendered = true\n\n // Track widget initialization\n this._posthog.capture('$conversations_widget_loaded', {\n hasExistingTicket: !!this._currentTicketId,\n initialState: initialState,\n initialView: initialView,\n ticketCount: tickets.length,\n hasUserTraits: !!initialUserTraits,\n })\n\n // Load messages if in message view and have a ticket\n if (initialView === 'messages' && this._currentTicketId) {\n this._loadMessages()\n }\n\n // Start polling based on current view\n this._startPolling()\n }\n\n /**\n * Get initial user traits from PostHog or localStorage\n */\n private _getInitialUserTraits(): UserProvidedTraits | null {\n // First, check PostHog's person properties\n const personProperties = this._posthog.persistence?.props || {}\n const posthogName = personProperties.$name || personProperties.name\n const posthogEmail = personProperties.$email || personProperties.email\n\n // If we have traits from PostHog, use those\n if (posthogName || posthogEmail) {\n return {\n name: posthogName || undefined,\n email: posthogEmail || undefined,\n }\n }\n\n // Otherwise, check localStorage for previously saved traits\n const savedTraits = this._persistence.loadUserTraits()\n if (savedTraits && (savedTraits.name || savedTraits.email)) {\n return savedTraits\n }\n\n return null\n }\n\n /**\n * Handle user identification from the widget form\n */\n private _handleIdentify = (traits: UserProvidedTraits): void => {\n // Save traits to localStorage\n this._persistence.saveUserTraits(traits)\n\n // Track identification\n this._posthog.capture('$conversations_user_identified', {\n hasName: !!traits.name,\n hasEmail: !!traits.email,\n })\n }\n\n /**\n * Handle sending a message from the widget\n */\n private _handleSendMessage = async (message: string): Promise<void> => {\n // Get user traits from the widget\n const userTraits = this._widgetRef?.getUserTraits() || undefined\n\n try {\n // Call the public API method (which handles tracking and state updates)\n await this.sendMessage(message, userTraits)\n\n // Poll for response immediately\n setTimeout(() => this._pollMessages(), 1000)\n } catch (error) {\n logger.error('Failed to send message', error)\n throw error\n }\n }\n\n /**\n * Handle widget state changes\n */\n private _handleStateChange = (state: ConversationsWidgetState): void => {\n logger.info('Widget state changed', { state, view: this._currentView })\n\n // Track state changes\n this._posthog.capture('$conversations_widget_state_changed', {\n state: state,\n view: this._currentView,\n ticketId: this._currentTicketId,\n })\n\n // Save state to localStorage\n this._persistence.saveWidgetState(state)\n\n // Mark messages as read when widget opens (only if in message view with a ticket)\n if (state === 'open') {\n if (this._currentView === 'messages' && this._unreadCount > 0 && this._currentTicketId) {\n this._markMessagesAsRead()\n }\n }\n }\n\n /**\n * Mark messages as read\n */\n private async _markMessagesAsRead(): Promise<void> {\n if (!this._currentTicketId) {\n return\n }\n\n try {\n const response = await this.markAsRead(this._currentTicketId || undefined)\n this._unreadCount = response.unread_count\n // Update the widget to reflect the new unread count\n this._widgetRef?.setUnreadCount(0)\n logger.info('Messages marked as read', { unreadCount: response.unread_count })\n } catch (error) {\n logger.error('Failed to mark messages as read', error)\n }\n }\n\n /**\n * Load messages for the current ticket\n */\n private async _loadMessages(): Promise<void> {\n if (!this._currentTicketId) {\n return\n }\n\n try {\n const response = await this.getMessages(\n this._currentTicketId || undefined,\n this._lastMessageTimestamp || undefined\n )\n\n // Update unread count from response\n if (isNumber(response.unread_count)) {\n this._unreadCount = response.unread_count\n this._widgetRef?.setUnreadCount(response.unread_count)\n\n // If widget is open and there are unread messages, mark them as read\n if (response.unread_count > 0 && this._isWidgetOpen()) {\n this._markMessagesAsRead()\n }\n }\n\n if (response.messages.length > 0) {\n this._widgetRef?.addMessages(response.messages)\n // Update last message timestamp\n const lastMessage = response.messages[response.messages.length - 1]\n this._lastMessageTimestamp = lastMessage.created_at\n }\n } catch (error) {\n logger.error('Failed to load messages', error)\n }\n }\n\n /**\n * Check if the widget is currently open\n */\n private _isWidgetOpen(): boolean {\n return this._persistence.loadWidgetState() === 'open'\n }\n\n /**\n * Poll for new messages\n */\n private _pollMessages = async (): Promise<void> => {\n if (this._isPolling || !this._currentTicketId) {\n return\n }\n\n this._isPolling = true\n try {\n await this._loadMessages()\n } finally {\n this._isPolling = false\n }\n }\n\n /**\n * Poll for tickets list\n */\n private _pollTickets = async (): Promise<void> => {\n if (this._isPolling) {\n return\n }\n\n this._isPolling = true\n try {\n await this._loadTickets()\n } finally {\n this._isPolling = false\n }\n }\n\n /**\n * Load tickets list from API\n */\n private async _loadTickets(): Promise<void> {\n try {\n const response = await this.getTickets()\n this._tickets = response.results\n this._hasMultipleTickets = response.results.length > 1\n this._widgetRef?.updateTickets(response.results)\n\n // Calculate total unread across all tickets\n const totalUnread = response.results.reduce((sum, t) => sum + (t.unread_count || 0), 0)\n this._unreadCount = totalUnread\n this._widgetRef?.setUnreadCount(totalUnread)\n\n logger.info('Tickets loaded', { count: response.results.length, totalUnread })\n } catch (error) {\n logger.error('Failed to load tickets', error)\n }\n }\n\n /**\n * Main poll function that polls based on current view\n */\n private _poll = async (): Promise<void> => {\n if (this._currentView === 'tickets') {\n await this._pollTickets()\n } else {\n await this._pollMessages()\n }\n }\n\n /**\n * Handle view changes from the widget\n */\n private _handleViewChange = (view: WidgetView): void => {\n logger.info('View changed', { from: this._currentView, to: view })\n this._currentView = view\n }\n\n /**\n * Handle ticket selection from the list\n */\n private _handleSelectTicket = async (ticketId: string): Promise<void> => {\n // Switch to this ticket\n this._switchToTicketIfNeeded(ticketId)\n\n // Clear messages and reset timestamp\n this._lastMessageTimestamp = null\n this._widgetRef?.clearMessages()\n\n // Switch view to messages\n this._currentView = 'messages'\n this._widgetRef?.setView('messages')\n\n // Load messages for the selected ticket\n await this._loadMessages()\n\n // Mark as read if widget is open\n if (this._isWidgetOpen() && this._unreadCount > 0) {\n this._markMessagesAsRead()\n }\n }\n\n /**\n * Handle new conversation request\n */\n private _handleNewConversation = (): void => {\n logger.info('New conversation requested')\n\n // Clear current ticket\n this._currentTicketId = null\n this._persistence.clearTicketId()\n\n // Reset timestamp\n this._lastMessageTimestamp = null\n\n // Switch view to messages\n this._currentView = 'messages'\n this._widgetRef?.setView('messages')\n\n // Clear messages and add greeting\n this._widgetRef?.clearMessages(true)\n }\n\n /**\n * Handle back to tickets request\n */\n private _handleBackToTickets = async (): Promise<void> => {\n logger.info('Back to tickets requested')\n\n // Switch view to tickets\n this._currentView = 'tickets'\n this._widgetRef?.setView('tickets')\n\n // Load tickets\n this._widgetRef?.setTicketsLoading(true)\n await this._loadTickets()\n\n // Track back to tickets\n this._posthog.capture('$conversations_back_to_tickets')\n }\n\n /**\n * Determine initial view based on ticket count\n */\n private async _determineInitialView(): Promise<{ view: WidgetView; tickets: Ticket[] }> {\n try {\n const response = await this.getTickets()\n this._tickets = response.results\n this._hasMultipleTickets = response.results.length > 1\n\n // Calculate total unread\n const totalUnread = response.results.reduce((sum, t) => sum + (t.unread_count || 0), 0)\n this._unreadCount = totalUnread\n\n // If 2+ tickets, show ticket list; otherwise show messages\n if (response.results.length >= 2) {\n return { view: 'tickets', tickets: response.results }\n }\n\n // If exactly 1 ticket, set it as current\n if (response.results.length === 1) {\n this._currentTicketId = response.results[0].id\n this._persistence.saveTicketId(response.results[0].id)\n }\n\n return { view: 'messages', tickets: response.results }\n } catch (error) {\n logger.error('Failed to determine initial view', error)\n return { view: 'messages', tickets: [] }\n }\n }\n\n /**\n * Start polling based on current view\n */\n private _startPolling(): void {\n if (this._pollIntervalId) {\n return // Already polling\n }\n\n // Poll immediately\n this._poll()\n\n // Set up interval\n this._pollIntervalId = window?.setInterval(() => {\n this._poll()\n }, POLL_INTERVAL_MS) as unknown as number\n\n logger.info('Started polling', { view: this._currentView })\n }\n\n /**\n * Stop polling for new messages\n */\n private _stopPolling(): void {\n if (this._pollIntervalId) {\n window?.clearInterval(this._pollIntervalId)\n this._pollIntervalId = null\n logger.info('Stopped polling for messages')\n }\n }\n\n /**\n * Setup listener for identify events.\n * When user calls posthog.identify(), hide the identification form\n * since we now know who they are.\n */\n private _setupIdentifyListener(): void {\n this._unsubscribeIdentifyListener = this._posthog.on('eventCaptured', (event: any) => {\n if (event.event === '$identify') {\n // User just identified - hide the identification form if it's showing\n this._widgetRef?.setUserIdentified()\n }\n })\n }\n\n /**\n * Show the widget (render it to DOM).\n * The widget respects its saved state (open/closed).\n * Note: Domain restrictions still apply - widget won't render on disallowed domains.\n */\n show(): void {\n // Check domain restrictions - don't render on disallowed domains\n if (!this._isDomainAllowed) {\n logger.warn('Cannot show widget: current domain is not allowed')\n return\n }\n\n // If widget isn't rendered yet, render it now\n if (!this._isWidgetRendered) {\n this._initializeWidget()\n }\n }\n\n /**\n * Hide and remove the widget from the DOM.\n * Conversation data is preserved - call show() to re-render.\n */\n hide(): void {\n // Stop polling when widget is hidden (save resources)\n this._stopPolling()\n\n if (this._containerElement) {\n render(null, this._containerElement)\n this._containerElement.remove()\n this._containerElement = null\n }\n this._widgetRef = null\n this._isWidgetRendered = false\n this._initializeWidgetPromise = null\n\n // Reset timestamp so show() will re-fetch all messages\n this._lastMessageTimestamp = null\n }\n\n /**\n * Check if the widget is currently visible (rendered in DOM)\n */\n isVisible(): boolean {\n return this._isWidgetRendered\n }\n\n /** Get tickets list for the current widget session */\n async getTickets(options?: GetTicketsOptions): Promise<GetTicketsResponse> {\n const token = this._config.token\n\n const queryParams: Record<string, string> = {\n widget_session_id: this._widgetSessionId,\n limit: String(options?.limit ?? 20),\n offset: String(options?.offset ?? 0),\n }\n\n if (options?.status) {\n queryParams.status = options.status\n }\n\n // eslint-disable-next-line compat/compat\n return new Promise((resolve, reject) => {\n this._posthog._send_request({\n url: this._posthog.requestRouter.endpointFor(\n 'api',\n `/api/conversations/v1/widget/tickets?${formDataToQuery(queryParams)}`\n ),\n method: 'GET',\n headers: {\n 'X-Conversations-Token': token,\n },\n callback: (response) => {\n if (response.statusCode === 429) {\n reject(new Error('Too many requests. Please wait before trying again.'))\n return\n }\n\n if (response.statusCode !== 200) {\n const errorMsg = response.json?.detail || response.json?.message || 'Failed to fetch tickets'\n logger.error('Failed to fetch tickets', { status: response.statusCode })\n reject(new Error(errorMsg))\n return\n }\n\n if (!response.json) {\n reject(new Error('Invalid response from server'))\n return\n }\n\n const data = response.json as GetTicketsResponse\n resolve(data)\n },\n })\n })\n }\n\n /**\n * Get the current active ticket ID\n * Returns null if no conversation has been started yet\n */\n getCurrentTicketId(): string | null {\n return this._currentTicketId\n }\n\n /**\n * Get the widget session ID (persistent browser identifier)\n * This ID is used for access control and stays the same across page loads\n */\n getWidgetSessionId(): string {\n return this._widgetSessionId\n }\n\n /**\n * Clean up the widget\n */\n destroy(): void {\n this._stopPolling()\n\n // Unsubscribe from identify events\n if (this._unsubscribeIdentifyListener) {\n this._unsubscribeIdentifyListener()\n this._unsubscribeIdentifyListener = null\n }\n\n if (this._containerElement) {\n render(null, this._containerElement)\n this._containerElement.remove()\n this._containerElement = null\n }\n\n this._widgetRef = null\n logger.info('Widget destroyed')\n }\n\n /**\n * Reset all conversation data and destroy the widget.\n * Called on posthog.reset() to start fresh.\n */\n reset(): void {\n // Clear all persisted conversation data\n this._persistence.clearAll()\n\n // Reset local state\n this._currentTicketId = null\n this._lastMessageTimestamp = null\n this._unreadCount = 0\n\n // Destroy the widget\n this.destroy()\n\n logger.info('Conversations reset')\n }\n\n /**\n * Render the widget to the DOM\n */\n private _renderWidget(\n initialState: ConversationsWidgetState,\n initialUserTraits: UserProvidedTraits | null,\n initialView: WidgetView = 'messages',\n initialTickets: Ticket[] = []\n ): void {\n if (!document) {\n logger.info('Conversations widget not rendered: Document not available')\n return\n }\n\n // Create container if it doesn't exist\n let container = document.getElementById(WIDGET_CONTAINER_ID) as HTMLDivElement\n if (!container) {\n if (!document.body) {\n logger.info('Conversations widget not rendered: Document body not available yet')\n return\n }\n container = document.createElement('div')\n container.id = WIDGET_CONTAINER_ID\n document.body.appendChild(container)\n }\n this._containerElement = container\n\n // Render widget with ref\n render(\n <ConversationsWidget\n ref={(ref: ConversationsWidget | null) => {\n this._widgetRef = ref\n }}\n config={this._config}\n initialState={initialState}\n initialUserTraits={initialUserTraits}\n isUserIdentified={this._posthog._isIdentified()}\n initialView={initialView}\n initialTickets={initialTickets}\n hasMultipleTickets={this._hasMultipleTickets}\n onSendMessage={this._handleSendMessage}\n onStateChange={this._handleStateChange}\n onIdentify={this._handleIdentify}\n onSelectTicket={this._handleSelectTicket}\n onNewConversation={this._handleNewConversation}\n onBackToTickets={this._handleBackToTickets}\n onViewChange={this._handleViewChange}\n />,\n container\n )\n }\n}\n\n/**\n * Initialize the conversations widget\n * This is the entry point called from the lazy-loaded bundle\n */\nexport function initConversations(config: ConversationsRemoteConfig, posthog: PostHog): ConversationsManager {\n logger.info('initConversations called', { hasConfig: !!config, hasPosthog: !!posthog })\n return new ConversationsManager(config, posthog)\n}\n"]}