@cstar.help/js 0.16.1 → 0.17.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.
@@ -47,6 +47,7 @@ var RealtimeManager = class {
47
47
  this.channels = /* @__PURE__ */ new Map();
48
48
  this.refreshTimer = null;
49
49
  this.currentToken = null;
50
+ this.destroyed = false;
50
51
  this.options = options;
51
52
  }
52
53
  /**
@@ -54,6 +55,7 @@ var RealtimeManager = class {
54
55
  * Returns true if successful, false if the realtime runtime is unavailable.
55
56
  */
56
57
  init() {
58
+ if (this.destroyed) return Promise.resolve(false);
57
59
  if (this.initPromise) return this.initPromise;
58
60
  this.initPromise = this.doInit();
59
61
  return this.initPromise;
@@ -61,10 +63,12 @@ var RealtimeManager = class {
61
63
  async doInit() {
62
64
  try {
63
65
  const tokenData = await this.options.fetchToken();
66
+ if (this.destroyed) return false;
64
67
  const { createClient } = await import(
65
68
  /* webpackIgnore: true */
66
69
  "@supabase/supabase-js"
67
70
  );
71
+ if (this.destroyed) return false;
68
72
  this.client = createClient(tokenData.realtimeUrl, tokenData.realtimeKey, {
69
73
  auth: { persistSession: false, autoRefreshToken: false },
70
74
  realtime: { params: { eventsPerSecond: 10 } }
@@ -92,10 +96,13 @@ var RealtimeManager = class {
92
96
  this.refreshTimer = setTimeout(() => this.doRefresh(), delay);
93
97
  }
94
98
  async doRefresh() {
99
+ if (this.destroyed) return;
95
100
  try {
96
101
  const tokenData = await this.options.fetchToken();
102
+ if (this.destroyed) return;
97
103
  this.setToken(tokenData);
98
104
  } catch {
105
+ if (this.destroyed) return;
99
106
  this.refreshTimer = setTimeout(() => this.doRefresh(), 3e4);
100
107
  }
101
108
  }
@@ -160,6 +167,7 @@ var RealtimeManager = class {
160
167
  }
161
168
  /** Clean up all channels, timers, and the client. */
162
169
  destroy() {
170
+ this.destroyed = true;
163
171
  if (this.refreshTimer) {
164
172
  clearTimeout(this.refreshTimer);
165
173
  this.refreshTimer = null;
@@ -333,6 +341,94 @@ var ChatClientNetworkError = class extends ChatClientError {
333
341
  }
334
342
  };
335
343
 
344
+ // src/chat/attachments.ts
345
+ var UUID = /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/i;
346
+ function downloadFilename(header) {
347
+ const extended = header?.match(/(?:^|;)\s*filename\*\s*=\s*UTF-8''([^;]*)/i);
348
+ let name = "";
349
+ if (extended) {
350
+ try {
351
+ name = decodeURIComponent(extended[1]);
352
+ } catch {
353
+ }
354
+ }
355
+ if (!name) {
356
+ const fallback = header?.match(/(?:^|;)\s*filename\s*=\s*(?:"((?:\\.|[^"\\])*)"|([^;]*))/i);
357
+ name = fallback?.[1]?.replace(/\\(.)/g, "$1") ?? fallback?.[2] ?? "";
358
+ }
359
+ return name.split(/[\\/]/).pop()?.replace(/[\x00-\x1f\x7f]/g, "").replace(/^[\s.]+|[\s.]+$/g, "") || "download";
360
+ }
361
+ var AttachmentsApi = class {
362
+ constructor(chat) {
363
+ this.chat = chat;
364
+ }
365
+ async download(reference, options = {}) {
366
+ const assertCurrent = this.chat.captureSession();
367
+ if (!this.chat.getAuthMode())
368
+ throw new ChatClientAuthError("Sign in before downloading a file.");
369
+ const { ticketId, messageId, attachmentIndex } = reference;
370
+ if (typeof ticketId !== "string" || typeof messageId !== "string" || !UUID.test(ticketId) || !UUID.test(messageId) || !Number.isSafeInteger(attachmentIndex) || attachmentIndex < 0) {
371
+ throw new TypeError("A saved ticket, message and nonnegative attachment index are required.");
372
+ }
373
+ const controller = new AbortController();
374
+ const signal = options.signal;
375
+ const download = options.download === false ? "0" : "1";
376
+ const abort = () => controller.abort();
377
+ const assertOwned = () => {
378
+ assertCurrent();
379
+ controller.signal.throwIfAborted();
380
+ };
381
+ const unsubscribe = this.chat.subscribe(() => {
382
+ try {
383
+ assertCurrent();
384
+ } catch {
385
+ abort();
386
+ }
387
+ });
388
+ signal?.addEventListener("abort", abort, { once: true });
389
+ if (signal?.aborted) abort();
390
+ try {
391
+ assertOwned();
392
+ const teamId = await this.chat.ensureTeamId(controller.signal);
393
+ assertOwned();
394
+ const result = await this.chat.fetch(
395
+ "/api/widget/attachments/download",
396
+ {
397
+ method: "GET",
398
+ query: {
399
+ teamId,
400
+ ticketId,
401
+ messageId,
402
+ attachmentIndex: String(attachmentIndex),
403
+ download
404
+ },
405
+ signal: controller.signal,
406
+ cache: "no-store",
407
+ readBody: async (response) => {
408
+ assertOwned();
409
+ const blob = await response.blob();
410
+ assertOwned();
411
+ return {
412
+ blob,
413
+ filename: downloadFilename(response.headers.get("Content-Disposition")),
414
+ contentType: blob.type.split(";")[0] || "application/octet-stream",
415
+ size: blob.size
416
+ };
417
+ }
418
+ }
419
+ );
420
+ assertOwned();
421
+ return result;
422
+ } catch (error) {
423
+ assertOwned();
424
+ throw error;
425
+ } finally {
426
+ unsubscribe();
427
+ signal?.removeEventListener("abort", abort);
428
+ }
429
+ }
430
+ };
431
+
336
432
  // src/chat/index.ts
337
433
  var DEFAULT_BASE_URL = "https://www.cstar.help";
338
434
  var DEFAULT_POLLING_INTERVAL = 3e3;
@@ -342,7 +438,8 @@ var ChatClient = class {
342
438
  this.teamId = null;
343
439
  this.customerId = null;
344
440
  this.authMode = null;
345
- this.pollingTimers = /* @__PURE__ */ new Map();
441
+ this.sessionGeneration = 0;
442
+ this.pollingSubscriptions = /* @__PURE__ */ new Set();
346
443
  this.stateListeners = /* @__PURE__ */ new Set();
347
444
  this.realtimeManager = null;
348
445
  this.presenceManager = null;
@@ -354,6 +451,7 @@ var ChatClient = class {
354
451
  this.realtimeEnabled = config.realtime !== false;
355
452
  this.tickets = new TicketsApi(this);
356
453
  this.messages = new MessagesApi(this);
454
+ this.attachments = new AttachmentsApi(this);
357
455
  this.community = new ChatCommunityApi(this);
358
456
  }
359
457
  /**
@@ -368,6 +466,8 @@ var ChatClient = class {
368
466
  * @param testMode - Whether to use test mode (relaxed timestamp validation)
369
467
  */
370
468
  async identify(customer, signature, testMode = false) {
469
+ const generation = this.retireSession();
470
+ this.assertSession(generation);
371
471
  const response = await this.fetch(
372
472
  "/api/widget/verify-identity",
373
473
  {
@@ -380,15 +480,18 @@ var ChatClient = class {
380
480
  }
381
481
  }
382
482
  );
483
+ this.assertSession(generation);
383
484
  this.sessionToken = response.data.sessionToken;
384
485
  this.teamId = response.data.teamId;
385
486
  this.customerId = response.data.customer.id;
386
487
  this.authMode = "hmac";
387
488
  this.notifyStateChanged();
489
+ this.assertSession(generation);
388
490
  if (this.realtimeEnabled) {
389
491
  this.realtimeInitPromise = this.initRealtime(
390
492
  response.data.customer.id,
391
- response.data.customer.name || customer.name || customer.email
493
+ response.data.customer.name || customer.name || customer.email,
494
+ generation
392
495
  );
393
496
  }
394
497
  return response.data;
@@ -403,11 +506,15 @@ var ChatClient = class {
403
506
  * Supabase session, use `loginWithSession({ accessToken })` instead.
404
507
  */
405
508
  async loginWithCredentials(params) {
509
+ const generation = this.retireSession();
510
+ this.assertSession(generation);
406
511
  const teamId = await this.resolveTeamIdFromSlug();
512
+ this.assertSession(generation);
407
513
  const response = await this.fetch("/api/widget/auth/login", {
408
514
  method: "POST",
409
515
  body: { email: params.email, password: params.password, teamId }
410
516
  });
517
+ this.assertSession(generation);
411
518
  if (!response.accessToken) {
412
519
  throw new ChatClientAuthError({
413
520
  message: "Login succeeded but no session was issued",
@@ -416,11 +523,14 @@ var ChatClient = class {
416
523
  requestId: null
417
524
  });
418
525
  }
419
- await this.loginWithSession({
420
- accessToken: response.accessToken,
421
- teamId,
422
- customerName: response.customer.name ?? response.customer.email
423
- });
526
+ this.applySession(
527
+ {
528
+ accessToken: response.accessToken,
529
+ teamId,
530
+ customerName: response.customer.name ?? response.customer.email
531
+ },
532
+ generation
533
+ );
424
534
  return {
425
535
  customer: {
426
536
  id: this.customerId ?? response.customer.id,
@@ -439,15 +549,22 @@ var ChatClient = class {
439
549
  * every request — there is no client-side validation here.
440
550
  */
441
551
  async loginWithSession(params) {
552
+ const teamId = params.teamId ?? this.teamId;
553
+ const generation = this.retireSession();
554
+ this.applySession({ ...params, ...teamId ? { teamId } : {} }, generation);
555
+ }
556
+ applySession(params, generation) {
557
+ this.assertSession(generation);
442
558
  this.sessionToken = params.accessToken;
443
559
  if (params.teamId) {
444
560
  this.teamId = params.teamId;
445
561
  }
446
562
  this.authMode = "session";
447
563
  this.notifyStateChanged();
564
+ this.assertSession(generation);
448
565
  if (this.realtimeEnabled) {
449
566
  const customerName = params.customerName ?? "";
450
- this.realtimeInitPromise = this.initRealtimeFromSession(customerName);
567
+ this.realtimeInitPromise = this.initRealtimeFromSession(customerName, generation);
451
568
  }
452
569
  }
453
570
  /**
@@ -488,8 +605,11 @@ var ChatClient = class {
488
605
  * @returns Unsubscribe function
489
606
  */
490
607
  onMessage(ticketId, callback) {
608
+ const generation = this.sessionGeneration;
491
609
  if (this.realtimeReady && this.realtimeManager) {
492
- return this.realtimeManager.subscribeToMessages(ticketId, callback);
610
+ return this.realtimeManager.subscribeToMessages(ticketId, (message) => {
611
+ if (generation === this.sessionGeneration) callback(message);
612
+ });
493
613
  }
494
614
  return this.pollMessages(ticketId, callback);
495
615
  }
@@ -500,8 +620,11 @@ var ChatClient = class {
500
620
  * @returns Unsubscribe function
501
621
  */
502
622
  onTyping(ticketId, callback) {
623
+ const generation = this.sessionGeneration;
503
624
  if (this.realtimeReady && this.presenceManager) {
504
- return this.presenceManager.subscribeToTyping(ticketId, callback);
625
+ return this.presenceManager.subscribeToTyping(ticketId, (typing) => {
626
+ if (generation === this.sessionGeneration) callback(typing);
627
+ });
505
628
  }
506
629
  return () => {
507
630
  };
@@ -517,6 +640,10 @@ var ChatClient = class {
517
640
  }
518
641
  /** Disconnect all subscriptions and clean up. */
519
642
  disconnect() {
643
+ this.retireSession();
644
+ }
645
+ retireSession() {
646
+ const generation = ++this.sessionGeneration;
520
647
  if (this.realtimeManager) {
521
648
  this.realtimeManager.destroy();
522
649
  this.realtimeManager = null;
@@ -527,15 +654,29 @@ var ChatClient = class {
527
654
  }
528
655
  this.realtimeReady = false;
529
656
  this.realtimeInitPromise = null;
530
- for (const timer of this.pollingTimers.values()) {
531
- clearInterval(timer);
657
+ for (const unsubscribe of this.pollingSubscriptions) {
658
+ unsubscribe();
532
659
  }
533
- this.pollingTimers.clear();
660
+ this.pollingSubscriptions.clear();
534
661
  this.sessionToken = null;
535
662
  this.teamId = null;
536
663
  this.customerId = null;
537
664
  this.authMode = null;
538
665
  this.notifyStateChanged();
666
+ return generation;
667
+ }
668
+ assertSession(generation) {
669
+ if (generation !== this.sessionGeneration) {
670
+ throw new ChatClientAuthError({
671
+ code: "SESSION_CHANGED",
672
+ message: "Your sign-in session changed. This operation belongs to the previous session."
673
+ });
674
+ }
675
+ }
676
+ /** @internal Keep a public operation owned across its asynchronous prerequisites. */
677
+ captureSession() {
678
+ const generation = this.sessionGeneration;
679
+ return () => this.assertSession(generation);
539
680
  }
540
681
  /**
541
682
  * @internal Make an authenticated request to the widget API.
@@ -550,6 +691,12 @@ var ChatClient = class {
550
691
  * server-confirmed mode.
551
692
  */
552
693
  async fetch(path, options) {
694
+ const generation = this.sessionGeneration;
695
+ const assertRequest = () => {
696
+ this.assertSession(generation);
697
+ options.signal?.throwIfAborted();
698
+ };
699
+ assertRequest();
553
700
  const url = this.buildUrl(path, options.query);
554
701
  const headers = {
555
702
  "Content-Type": "application/json"
@@ -562,14 +709,18 @@ var ChatClient = class {
562
709
  response = await globalThis.fetch(url, {
563
710
  method: options.method,
564
711
  headers,
712
+ ...options.signal ? { signal: options.signal } : {},
713
+ ...options.cache ? { cache: options.cache } : {},
565
714
  body: options.body ? JSON.stringify(options.body) : void 0
566
715
  });
567
716
  } catch (networkErr) {
717
+ assertRequest();
568
718
  throw new ChatClientNetworkError({
569
719
  message: networkErr instanceof Error ? networkErr.message : "Network request failed",
570
720
  originalError: networkErr
571
721
  });
572
722
  }
723
+ assertRequest();
573
724
  const responseHeaders = response.headers && typeof response.headers.get === "function" ? response.headers : null;
574
725
  const headerMode = responseHeaders?.get("X-Cstar-Auth-Mode") ?? null;
575
726
  if (headerMode === "hmac" || headerMode === "session") {
@@ -577,9 +728,11 @@ var ChatClient = class {
577
728
  this.authMode = headerMode;
578
729
  if (previous !== headerMode) this.notifyStateChanged();
579
730
  }
731
+ assertRequest();
580
732
  const requestId = responseHeaders?.get("X-Request-Id") ?? null;
581
733
  if (!response.ok) {
582
734
  const errorBody = await response.json().catch(() => ({ error: { code: "UNKNOWN", message: "Request failed" } }));
735
+ assertRequest();
583
736
  const code = errorBody.error?.code ?? "UNKNOWN";
584
737
  const message = errorBody.error?.message ?? `Widget API error: ${response.status}`;
585
738
  if (response.status === 401 || response.status === 403) {
@@ -616,7 +769,14 @@ var ChatClient = class {
616
769
  requestId
617
770
  });
618
771
  }
619
- return response.json();
772
+ try {
773
+ const body = options.readBody ? await options.readBody(response) : await response.json();
774
+ assertRequest();
775
+ return body;
776
+ } catch (error) {
777
+ assertRequest();
778
+ throw error;
779
+ }
620
780
  }
621
781
  /**
622
782
  * Look up the team UUID from the configured `teamSlug`. Used by
@@ -625,37 +785,41 @@ var ChatClient = class {
625
785
  *
626
786
  * @internal
627
787
  */
628
- async resolveTeamIdFromSlug() {
788
+ async resolveTeamIdFromSlug(signal) {
629
789
  const response = await this.fetch(
630
790
  "/api/widget/team-by-slug",
631
791
  {
632
792
  method: "GET",
793
+ signal,
633
794
  query: { teamSlug: this.teamSlug }
634
795
  }
635
796
  );
636
797
  return response.data.teamId;
637
798
  }
638
799
  /** @internal Bootstrap realtime from a session login (no precomputed customerId). */
639
- async initRealtimeFromSession(customerName) {
800
+ async initRealtimeFromSession(customerName, generation) {
801
+ const manager = new RealtimeManager({ fetchToken: () => this.fetchRealtimeToken(generation) });
802
+ this.realtimeManager = manager;
640
803
  try {
641
- this.realtimeManager = new RealtimeManager({
642
- fetchToken: () => this.fetchRealtimeToken()
643
- });
644
- const ready = await this.realtimeManager.init();
804
+ const ready = await manager.init();
805
+ if (generation !== this.sessionGeneration || this.realtimeManager !== manager) {
806
+ manager.destroy();
807
+ return;
808
+ }
645
809
  if (!ready) return;
646
810
  this.realtimeReady = true;
647
- const token = this.realtimeManager.getCurrentToken();
811
+ const token = manager.getCurrentToken();
648
812
  const customerId = token ? decodeJwtSub(token) : null;
649
813
  if (customerId) {
650
814
  this.customerId = customerId;
651
815
  this.presenceManager = new PresenceManager({ customerId, customerName });
652
- const client = this.realtimeManager.getClient();
816
+ const client = manager.getClient();
653
817
  if (client) {
654
818
  this.presenceManager.setClient(client);
655
819
  }
656
820
  }
657
821
  } catch {
658
- this.realtimeReady = false;
822
+ if (generation === this.sessionGeneration) this.realtimeReady = false;
659
823
  }
660
824
  }
661
825
  /** @internal Get the stored team ID for requests that need it. */
@@ -673,14 +837,19 @@ var ChatClient = class {
673
837
  * `"Missing teamId"` when the chat client was teamSlug-only because the
674
838
  * tickets sub-resource read `getTeamId()` synchronously and bailed.
675
839
  */
676
- async ensureTeamId() {
840
+ async ensureTeamId(signal) {
841
+ const assertCurrent = this.captureSession();
842
+ signal?.throwIfAborted();
677
843
  if (this.teamId) return this.teamId;
678
844
  if (!this.teamSlug) {
679
845
  throw new ChatClientAuthError(
680
846
  "Missing teamId. Construct ChatClient with `teamSlug` or call `setTeamId()` / `identify()` / `loginWithCredentials()` first."
681
847
  );
682
848
  }
683
- this.teamId = await this.resolveTeamIdFromSlug();
849
+ const teamId = await this.resolveTeamIdFromSlug(signal);
850
+ assertCurrent();
851
+ signal?.throwIfAborted();
852
+ this.teamId = teamId;
684
853
  return this.teamId;
685
854
  }
686
855
  /** @internal Set team ID from identify response or other source. */
@@ -693,28 +862,32 @@ var ChatClient = class {
693
862
  await this.realtimeInitPromise;
694
863
  }
695
864
  }
696
- async initRealtime(customerId, customerName) {
865
+ async initRealtime(customerId, customerName, generation) {
866
+ const manager = new RealtimeManager({ fetchToken: () => this.fetchRealtimeToken(generation) });
867
+ this.realtimeManager = manager;
697
868
  try {
698
- this.realtimeManager = new RealtimeManager({
699
- fetchToken: () => this.fetchRealtimeToken()
700
- });
701
- const ready = await this.realtimeManager.init();
869
+ const ready = await manager.init();
870
+ if (generation !== this.sessionGeneration || this.realtimeManager !== manager) {
871
+ manager.destroy();
872
+ return;
873
+ }
702
874
  if (ready) {
703
875
  this.realtimeReady = true;
704
876
  this.presenceManager = new PresenceManager({
705
877
  customerId,
706
878
  customerName
707
879
  });
708
- const client = this.realtimeManager.getClient();
880
+ const client = manager.getClient();
709
881
  if (client) {
710
882
  this.presenceManager.setClient(client);
711
883
  }
712
884
  }
713
885
  } catch {
714
- this.realtimeReady = false;
886
+ if (generation === this.sessionGeneration) this.realtimeReady = false;
715
887
  }
716
888
  }
717
- async fetchRealtimeToken() {
889
+ async fetchRealtimeToken(generation) {
890
+ this.assertSession(generation);
718
891
  const response = await this.fetch(
719
892
  "/api/widget/realtime-token",
720
893
  {
@@ -722,34 +895,47 @@ var ChatClient = class {
722
895
  body: { teamId: this.teamId }
723
896
  }
724
897
  );
898
+ this.assertSession(generation);
725
899
  return response.data;
726
900
  }
727
901
  pollMessages(ticketId, callback) {
728
902
  let lastMessageId = null;
903
+ let initialized = false;
904
+ let active = true;
905
+ let inFlight = false;
729
906
  const poll = async () => {
907
+ if (!active || inFlight) return;
908
+ inFlight = true;
730
909
  try {
731
910
  const messages = await this.messages.list(ticketId);
911
+ if (!active) return;
732
912
  if (messages.length > 0) {
733
913
  const latest = messages[messages.length - 1];
734
- if (lastMessageId && latest.id !== lastMessageId) {
914
+ if (initialized && latest.id !== lastMessageId) {
735
915
  const lastIdx = messages.findIndex((m) => m.id === lastMessageId);
736
- const newMessages = lastIdx >= 0 ? messages.slice(lastIdx + 1) : [latest];
916
+ const newMessages = lastIdx >= 0 ? messages.slice(lastIdx + 1) : lastMessageId ? [latest] : messages;
737
917
  for (const msg of newMessages) {
918
+ if (!active) return;
738
919
  callback(msg);
739
920
  }
740
921
  }
741
922
  lastMessageId = latest.id;
742
923
  }
924
+ initialized = true;
743
925
  } catch {
926
+ } finally {
927
+ inFlight = false;
744
928
  }
745
929
  };
746
930
  poll();
747
931
  const timer = setInterval(poll, this.pollingInterval);
748
- this.pollingTimers.set(ticketId, timer);
749
- return () => {
932
+ const unsubscribe = () => {
933
+ active = false;
750
934
  clearInterval(timer);
751
- this.pollingTimers.delete(ticketId);
935
+ this.pollingSubscriptions.delete(unsubscribe);
752
936
  };
937
+ this.pollingSubscriptions.add(unsubscribe);
938
+ return unsubscribe;
753
939
  }
754
940
  buildUrl(path, query) {
755
941
  const base = `${this.baseUrl}${path}`;
@@ -768,10 +954,12 @@ var TicketsApi = class {
768
954
  }
769
955
  /** List tickets for the identified customer. */
770
956
  async list(params) {
957
+ const assertCurrent = this.chat.captureSession();
771
958
  if (this.chat.getAuthMode() === null) {
772
959
  throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
773
960
  }
774
961
  const teamId = await this.chat.ensureTeamId();
962
+ assertCurrent();
775
963
  const response = await this.chat.fetch("/api/widget/conversations", {
776
964
  method: "GET",
777
965
  query: {
@@ -780,6 +968,7 @@ var TicketsApi = class {
780
968
  cursor: params?.cursor
781
969
  }
782
970
  });
971
+ assertCurrent();
783
972
  const data = response.data.tickets ?? response.data.conversations ?? [];
784
973
  const cursor = response.data.cursor;
785
974
  const hasMore = response.data.hasMore;
@@ -791,10 +980,12 @@ var TicketsApi = class {
791
980
  }
792
981
  /** Create a new ticket. */
793
982
  async create(params) {
983
+ const assertCurrent = this.chat.captureSession();
794
984
  if (this.chat.getAuthMode() === null) {
795
985
  throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
796
986
  }
797
987
  const teamId = await this.chat.ensureTeamId();
988
+ assertCurrent();
798
989
  const response = await this.chat.fetch("/api/widget/tickets", {
799
990
  method: "POST",
800
991
  body: {
@@ -803,6 +994,7 @@ var TicketsApi = class {
803
994
  message: params.message
804
995
  }
805
996
  });
997
+ assertCurrent();
806
998
  const messages = (response.data.messages ?? []).map((m) => ({
807
999
  id: m.id,
808
1000
  content: m.content,
@@ -961,6 +1153,7 @@ var MessagesApi = class {
961
1153
  }
962
1154
  /** List messages for a ticket. */
963
1155
  async list(ticketId) {
1156
+ const assertCurrent = this.chat.captureSession();
964
1157
  const teamId = this.chat.getTeamId();
965
1158
  const response = await this.chat.fetch(
966
1159
  "/api/widget/messages",
@@ -972,10 +1165,12 @@ var MessagesApi = class {
972
1165
  }
973
1166
  }
974
1167
  );
1168
+ assertCurrent();
975
1169
  return response.data.messages;
976
1170
  }
977
1171
  /** Send a message to a ticket. */
978
1172
  async send(ticketId, content) {
1173
+ const assertCurrent = this.chat.captureSession();
979
1174
  const teamId = this.chat.getTeamId();
980
1175
  const response = await this.chat.fetch(
981
1176
  "/api/widget/messages",
@@ -988,6 +1183,7 @@ var MessagesApi = class {
988
1183
  }
989
1184
  }
990
1185
  );
1186
+ assertCurrent();
991
1187
  return response.data.message;
992
1188
  }
993
1189
  };