@whereby.com/assistant-sdk 0.0.0-canary-20250917154617 → 0.0.0-canary-20250923130059

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -35,6 +35,10 @@ const TRIGGER_EVENT_SUCCESS = "trigger_event_success";
35
35
  const AUDIO_STREAM_READY = "AUDIO_STREAM_READY";
36
36
  const ASSISTANT_JOINED_ROOM = "ASSISTANT_JOINED_ROOM";
37
37
  const ASSISTANT_LEFT_ROOM = "ASSISTANT_LEFT_ROOM";
38
+ const PARTICIPANT_VIDEO_TRACK_ADDED = "PARTICIPANT_VIDEO_TRACK_ADDED";
39
+ const PARTICIPANT_VIDEO_TRACK_REMOVED = "PARTICIPANT_VIDEO_TRACK_REMOVED";
40
+ const PARTICIPANT_AUDIO_TRACK_ADDED = "PARTICIPANT_AUDIO_TRACK_ADDED";
41
+ const PARTICIPANT_AUDIO_TRACK_REMOVED = "PARTICIPANT_AUDIO_TRACK_REMOVED";
38
42
 
39
43
  /******************************************************************************
40
44
  Copyright (c) Microsoft Corporation.
@@ -580,6 +584,7 @@ class Assistant extends EventEmitter {
580
584
  this.mediaStream = null;
581
585
  this.audioSource = null;
582
586
  this.combinedStream = null;
587
+ this.remoteMediaTracks = {};
583
588
  this.roomUrl = null;
584
589
  this.handleConnectionStatusChange = (status) => {
585
590
  if (status === "connected") {
@@ -589,6 +594,41 @@ class Assistant extends EventEmitter {
589
594
  this.emit(ASSISTANT_LEFT_ROOM, { roomUrl: this.roomUrl || "" });
590
595
  }
591
596
  };
597
+ this.handleRemoteParticipantsTracksChange = (remoteParticipants) => {
598
+ const currentRemoteMediaTracks = remoteParticipants.flatMap(({ id: participantId, stream }) => {
599
+ if (!stream) {
600
+ return [];
601
+ }
602
+ const tracks = stream.getTracks();
603
+ tracks.forEach((track) => {
604
+ if (!this.remoteMediaTracks[track.id]) {
605
+ const eventName = track.kind === "video" ? PARTICIPANT_VIDEO_TRACK_ADDED : PARTICIPANT_AUDIO_TRACK_ADDED;
606
+ this.emit(eventName, {
607
+ participantId,
608
+ stream,
609
+ track,
610
+ });
611
+ this.remoteMediaTracks[track.id] = {
612
+ participantId,
613
+ stream,
614
+ track,
615
+ };
616
+ }
617
+ });
618
+ return tracks;
619
+ });
620
+ Object.values(this.remoteMediaTracks).forEach(({ participantId, stream, track }) => {
621
+ if (!currentRemoteMediaTracks.includes(track)) {
622
+ const eventName = track.kind === "video" ? PARTICIPANT_VIDEO_TRACK_REMOVED : PARTICIPANT_AUDIO_TRACK_REMOVED;
623
+ this.emit(eventName, {
624
+ participantId,
625
+ stream,
626
+ track,
627
+ });
628
+ delete this.remoteMediaTracks[track.id];
629
+ }
630
+ });
631
+ };
592
632
  this.assistantKey = assistantKey;
593
633
  this.client = new core.WherebyClient();
594
634
  this.roomConnection = this.client.getRoomConnection();
@@ -613,8 +653,9 @@ class Assistant extends EventEmitter {
613
653
  const audioMixer = new AudioMixer(handleStreamReady);
614
654
  this.combinedStream = audioMixer.getCombinedAudioStream();
615
655
  this.roomConnection.subscribeToRemoteParticipants(audioMixer.handleRemoteParticipants.bind(audioMixer));
616
- this.roomConnection.subscribeToConnectionStatus(this.handleConnectionStatusChange);
617
656
  }
657
+ this.roomConnection.subscribeToConnectionStatus(this.handleConnectionStatusChange);
658
+ this.roomConnection.subscribeToRemoteParticipants(this.handleRemoteParticipantsTracksChange);
618
659
  }
619
660
  joinRoom(roomUrl) {
620
661
  return __awaiter(this, void 0, void 0, function* () {
@@ -731,7 +772,7 @@ const webhookRouter = (webhookTriggers, emitter) => {
731
772
  res.status(200);
732
773
  res.end();
733
774
  });
734
- router.post("/", jsonParser, (req, res) => {
775
+ router.post("/", jsonParser, (req, res) => __awaiter(void 0, void 0, void 0, function* () {
735
776
  var _a, _b, _c, _d, _e, _f, _g, _h;
736
777
  assert(req.body, "message body is required");
737
778
  assert("type" in req.body, "webhook type is required");
@@ -739,19 +780,19 @@ const webhookRouter = (webhookTriggers, emitter) => {
739
780
  switch (req.body.type) {
740
781
  case "room.client.joined":
741
782
  shouldTriggerOnReceivedWebhook =
742
- (_b = (_a = webhookTriggers["room.client.joined"]) === null || _a === void 0 ? void 0 : _a.call(webhookTriggers, req.body)) !== null && _b !== void 0 ? _b : false;
783
+ (_b = (yield ((_a = webhookTriggers["room.client.joined"]) === null || _a === void 0 ? void 0 : _a.call(webhookTriggers, req.body)))) !== null && _b !== void 0 ? _b : false;
743
784
  break;
744
785
  case "room.client.left":
745
786
  shouldTriggerOnReceivedWebhook =
746
- (_d = (_c = webhookTriggers["room.client.left"]) === null || _c === void 0 ? void 0 : _c.call(webhookTriggers, req.body)) !== null && _d !== void 0 ? _d : false;
787
+ (_d = (yield ((_c = webhookTriggers["room.client.left"]) === null || _c === void 0 ? void 0 : _c.call(webhookTriggers, req.body)))) !== null && _d !== void 0 ? _d : false;
747
788
  break;
748
789
  case "room.session.started":
749
790
  shouldTriggerOnReceivedWebhook =
750
- (_f = (_e = webhookTriggers["room.session.started"]) === null || _e === void 0 ? void 0 : _e.call(webhookTriggers, req.body)) !== null && _f !== void 0 ? _f : false;
791
+ (_f = (yield ((_e = webhookTriggers["room.session.started"]) === null || _e === void 0 ? void 0 : _e.call(webhookTriggers, req.body)))) !== null && _f !== void 0 ? _f : false;
751
792
  break;
752
793
  case "room.session.ended":
753
794
  shouldTriggerOnReceivedWebhook =
754
- (_h = (_g = webhookTriggers["room.session.ended"]) === null || _g === void 0 ? void 0 : _g.call(webhookTriggers, req.body)) !== null && _h !== void 0 ? _h : false;
795
+ (_h = (yield ((_g = webhookTriggers["room.session.ended"]) === null || _g === void 0 ? void 0 : _g.call(webhookTriggers, req.body)))) !== null && _h !== void 0 ? _h : false;
755
796
  break;
756
797
  }
757
798
  if (shouldTriggerOnReceivedWebhook) {
@@ -760,7 +801,7 @@ const webhookRouter = (webhookTriggers, emitter) => {
760
801
  }
761
802
  res.status(200);
762
803
  res.end();
763
- });
804
+ }));
764
805
  return router;
765
806
  };
766
807
  class Trigger extends EventEmitter.EventEmitter {
@@ -773,12 +814,9 @@ class Trigger extends EventEmitter.EventEmitter {
773
814
  const app = express();
774
815
  const router = webhookRouter(this.webhookTriggers, this);
775
816
  app.use(router);
776
- const server = app.listen(this.port, () => {
817
+ app.listen(this.port, () => {
777
818
  // console.log(`Bot trigger server now running on port[${this.port}]`);
778
819
  });
779
- process.on("SIGTERM", () => {
780
- server.close();
781
- });
782
820
  }
783
821
  }
784
822
 
@@ -788,5 +826,9 @@ exports.AUDIO_STREAM_READY = AUDIO_STREAM_READY;
788
826
  exports.Assistant = Assistant;
789
827
  exports.AudioSink = AudioSink;
790
828
  exports.AudioSource = AudioSource;
829
+ exports.PARTICIPANT_AUDIO_TRACK_ADDED = PARTICIPANT_AUDIO_TRACK_ADDED;
830
+ exports.PARTICIPANT_AUDIO_TRACK_REMOVED = PARTICIPANT_AUDIO_TRACK_REMOVED;
831
+ exports.PARTICIPANT_VIDEO_TRACK_ADDED = PARTICIPANT_VIDEO_TRACK_ADDED;
832
+ exports.PARTICIPANT_VIDEO_TRACK_REMOVED = PARTICIPANT_VIDEO_TRACK_REMOVED;
791
833
  exports.TRIGGER_EVENT_SUCCESS = TRIGGER_EVENT_SUCCESS;
792
834
  exports.Trigger = Trigger;
package/dist/index.d.cts CHANGED
@@ -88,12 +88,16 @@ type WherebyWebhookTriggerTypes = {
88
88
  "room.session.ended": WherebyWebhookRoomSessionEnded;
89
89
  };
90
90
  type WherebyWebhookTriggers = Partial<{
91
- [Type in keyof WherebyWebhookTriggerTypes]: (data: WherebyWebhookTriggerTypes[Type]) => boolean;
91
+ [Type in keyof WherebyWebhookTriggerTypes]: (data: WherebyWebhookTriggerTypes[Type]) => Promise<boolean> | boolean;
92
92
  }>;
93
93
 
94
94
  declare const AUDIO_STREAM_READY = "AUDIO_STREAM_READY";
95
95
  declare const ASSISTANT_JOINED_ROOM = "ASSISTANT_JOINED_ROOM";
96
96
  declare const ASSISTANT_LEFT_ROOM = "ASSISTANT_LEFT_ROOM";
97
+ declare const PARTICIPANT_VIDEO_TRACK_ADDED = "PARTICIPANT_VIDEO_TRACK_ADDED";
98
+ declare const PARTICIPANT_VIDEO_TRACK_REMOVED = "PARTICIPANT_VIDEO_TRACK_REMOVED";
99
+ declare const PARTICIPANT_AUDIO_TRACK_ADDED = "PARTICIPANT_AUDIO_TRACK_ADDED";
100
+ declare const PARTICIPANT_AUDIO_TRACK_REMOVED = "PARTICIPANT_AUDIO_TRACK_REMOVED";
97
101
  type AssistantEvents = {
98
102
  [ASSISTANT_JOINED_ROOM]: [{
99
103
  roomUrl: string;
@@ -105,6 +109,26 @@ type AssistantEvents = {
105
109
  stream: MediaStream;
106
110
  track: MediaStreamTrack;
107
111
  }];
112
+ [PARTICIPANT_VIDEO_TRACK_ADDED]: [{
113
+ participantId: string;
114
+ stream: MediaStream;
115
+ track: MediaStreamTrack;
116
+ }];
117
+ [PARTICIPANT_VIDEO_TRACK_REMOVED]: [{
118
+ participantId: string;
119
+ stream: MediaStream;
120
+ track: MediaStreamTrack;
121
+ }];
122
+ [PARTICIPANT_AUDIO_TRACK_ADDED]: [{
123
+ participantId: string;
124
+ stream: MediaStream;
125
+ track: MediaStreamTrack;
126
+ }];
127
+ [PARTICIPANT_AUDIO_TRACK_REMOVED]: [{
128
+ participantId: string;
129
+ stream: MediaStream;
130
+ track: MediaStreamTrack;
131
+ }];
108
132
  };
109
133
 
110
134
  type AssistantOptions = {
@@ -120,9 +144,11 @@ declare class Assistant extends EventEmitter<AssistantEvents> {
120
144
  private mediaStream;
121
145
  private audioSource;
122
146
  private combinedStream;
147
+ private remoteMediaTracks;
123
148
  private roomUrl;
124
149
  constructor({ assistantKey, startCombinedAudioStream, startLocalMedia }: AssistantOptions);
125
150
  private handleConnectionStatusChange;
151
+ private handleRemoteParticipantsTracksChange;
126
152
  joinRoom(roomUrl: string): Promise<void>;
127
153
  startLocalMedia(): void;
128
154
  getLocalMediaStream(): MediaStream | null;
@@ -169,5 +195,5 @@ declare class AudioSink extends wrtc__default.nonstandard.RTCAudioSink {
169
195
  }) => void): () => void;
170
196
  }
171
197
 
172
- export { ASSISTANT_JOINED_ROOM, ASSISTANT_LEFT_ROOM, AUDIO_STREAM_READY, Assistant, AudioSink, AudioSource, TRIGGER_EVENT_SUCCESS, Trigger };
198
+ export { ASSISTANT_JOINED_ROOM, ASSISTANT_LEFT_ROOM, AUDIO_STREAM_READY, Assistant, AudioSink, AudioSource, PARTICIPANT_AUDIO_TRACK_ADDED, PARTICIPANT_AUDIO_TRACK_REMOVED, PARTICIPANT_VIDEO_TRACK_ADDED, PARTICIPANT_VIDEO_TRACK_REMOVED, TRIGGER_EVENT_SUCCESS, Trigger };
173
199
  export type { AssistantEvents };
package/dist/index.d.mts CHANGED
@@ -88,12 +88,16 @@ type WherebyWebhookTriggerTypes = {
88
88
  "room.session.ended": WherebyWebhookRoomSessionEnded;
89
89
  };
90
90
  type WherebyWebhookTriggers = Partial<{
91
- [Type in keyof WherebyWebhookTriggerTypes]: (data: WherebyWebhookTriggerTypes[Type]) => boolean;
91
+ [Type in keyof WherebyWebhookTriggerTypes]: (data: WherebyWebhookTriggerTypes[Type]) => Promise<boolean> | boolean;
92
92
  }>;
93
93
 
94
94
  declare const AUDIO_STREAM_READY = "AUDIO_STREAM_READY";
95
95
  declare const ASSISTANT_JOINED_ROOM = "ASSISTANT_JOINED_ROOM";
96
96
  declare const ASSISTANT_LEFT_ROOM = "ASSISTANT_LEFT_ROOM";
97
+ declare const PARTICIPANT_VIDEO_TRACK_ADDED = "PARTICIPANT_VIDEO_TRACK_ADDED";
98
+ declare const PARTICIPANT_VIDEO_TRACK_REMOVED = "PARTICIPANT_VIDEO_TRACK_REMOVED";
99
+ declare const PARTICIPANT_AUDIO_TRACK_ADDED = "PARTICIPANT_AUDIO_TRACK_ADDED";
100
+ declare const PARTICIPANT_AUDIO_TRACK_REMOVED = "PARTICIPANT_AUDIO_TRACK_REMOVED";
97
101
  type AssistantEvents = {
98
102
  [ASSISTANT_JOINED_ROOM]: [{
99
103
  roomUrl: string;
@@ -105,6 +109,26 @@ type AssistantEvents = {
105
109
  stream: MediaStream;
106
110
  track: MediaStreamTrack;
107
111
  }];
112
+ [PARTICIPANT_VIDEO_TRACK_ADDED]: [{
113
+ participantId: string;
114
+ stream: MediaStream;
115
+ track: MediaStreamTrack;
116
+ }];
117
+ [PARTICIPANT_VIDEO_TRACK_REMOVED]: [{
118
+ participantId: string;
119
+ stream: MediaStream;
120
+ track: MediaStreamTrack;
121
+ }];
122
+ [PARTICIPANT_AUDIO_TRACK_ADDED]: [{
123
+ participantId: string;
124
+ stream: MediaStream;
125
+ track: MediaStreamTrack;
126
+ }];
127
+ [PARTICIPANT_AUDIO_TRACK_REMOVED]: [{
128
+ participantId: string;
129
+ stream: MediaStream;
130
+ track: MediaStreamTrack;
131
+ }];
108
132
  };
109
133
 
110
134
  type AssistantOptions = {
@@ -120,9 +144,11 @@ declare class Assistant extends EventEmitter<AssistantEvents> {
120
144
  private mediaStream;
121
145
  private audioSource;
122
146
  private combinedStream;
147
+ private remoteMediaTracks;
123
148
  private roomUrl;
124
149
  constructor({ assistantKey, startCombinedAudioStream, startLocalMedia }: AssistantOptions);
125
150
  private handleConnectionStatusChange;
151
+ private handleRemoteParticipantsTracksChange;
126
152
  joinRoom(roomUrl: string): Promise<void>;
127
153
  startLocalMedia(): void;
128
154
  getLocalMediaStream(): MediaStream | null;
@@ -169,5 +195,5 @@ declare class AudioSink extends wrtc__default.nonstandard.RTCAudioSink {
169
195
  }) => void): () => void;
170
196
  }
171
197
 
172
- export { ASSISTANT_JOINED_ROOM, ASSISTANT_LEFT_ROOM, AUDIO_STREAM_READY, Assistant, AudioSink, AudioSource, TRIGGER_EVENT_SUCCESS, Trigger };
198
+ export { ASSISTANT_JOINED_ROOM, ASSISTANT_LEFT_ROOM, AUDIO_STREAM_READY, Assistant, AudioSink, AudioSource, PARTICIPANT_AUDIO_TRACK_ADDED, PARTICIPANT_AUDIO_TRACK_REMOVED, PARTICIPANT_VIDEO_TRACK_ADDED, PARTICIPANT_VIDEO_TRACK_REMOVED, TRIGGER_EVENT_SUCCESS, Trigger };
173
199
  export type { AssistantEvents };
package/dist/index.d.ts CHANGED
@@ -88,12 +88,16 @@ type WherebyWebhookTriggerTypes = {
88
88
  "room.session.ended": WherebyWebhookRoomSessionEnded;
89
89
  };
90
90
  type WherebyWebhookTriggers = Partial<{
91
- [Type in keyof WherebyWebhookTriggerTypes]: (data: WherebyWebhookTriggerTypes[Type]) => boolean;
91
+ [Type in keyof WherebyWebhookTriggerTypes]: (data: WherebyWebhookTriggerTypes[Type]) => Promise<boolean> | boolean;
92
92
  }>;
93
93
 
94
94
  declare const AUDIO_STREAM_READY = "AUDIO_STREAM_READY";
95
95
  declare const ASSISTANT_JOINED_ROOM = "ASSISTANT_JOINED_ROOM";
96
96
  declare const ASSISTANT_LEFT_ROOM = "ASSISTANT_LEFT_ROOM";
97
+ declare const PARTICIPANT_VIDEO_TRACK_ADDED = "PARTICIPANT_VIDEO_TRACK_ADDED";
98
+ declare const PARTICIPANT_VIDEO_TRACK_REMOVED = "PARTICIPANT_VIDEO_TRACK_REMOVED";
99
+ declare const PARTICIPANT_AUDIO_TRACK_ADDED = "PARTICIPANT_AUDIO_TRACK_ADDED";
100
+ declare const PARTICIPANT_AUDIO_TRACK_REMOVED = "PARTICIPANT_AUDIO_TRACK_REMOVED";
97
101
  type AssistantEvents = {
98
102
  [ASSISTANT_JOINED_ROOM]: [{
99
103
  roomUrl: string;
@@ -105,6 +109,26 @@ type AssistantEvents = {
105
109
  stream: MediaStream;
106
110
  track: MediaStreamTrack;
107
111
  }];
112
+ [PARTICIPANT_VIDEO_TRACK_ADDED]: [{
113
+ participantId: string;
114
+ stream: MediaStream;
115
+ track: MediaStreamTrack;
116
+ }];
117
+ [PARTICIPANT_VIDEO_TRACK_REMOVED]: [{
118
+ participantId: string;
119
+ stream: MediaStream;
120
+ track: MediaStreamTrack;
121
+ }];
122
+ [PARTICIPANT_AUDIO_TRACK_ADDED]: [{
123
+ participantId: string;
124
+ stream: MediaStream;
125
+ track: MediaStreamTrack;
126
+ }];
127
+ [PARTICIPANT_AUDIO_TRACK_REMOVED]: [{
128
+ participantId: string;
129
+ stream: MediaStream;
130
+ track: MediaStreamTrack;
131
+ }];
108
132
  };
109
133
 
110
134
  type AssistantOptions = {
@@ -120,9 +144,11 @@ declare class Assistant extends EventEmitter<AssistantEvents> {
120
144
  private mediaStream;
121
145
  private audioSource;
122
146
  private combinedStream;
147
+ private remoteMediaTracks;
123
148
  private roomUrl;
124
149
  constructor({ assistantKey, startCombinedAudioStream, startLocalMedia }: AssistantOptions);
125
150
  private handleConnectionStatusChange;
151
+ private handleRemoteParticipantsTracksChange;
126
152
  joinRoom(roomUrl: string): Promise<void>;
127
153
  startLocalMedia(): void;
128
154
  getLocalMediaStream(): MediaStream | null;
@@ -169,5 +195,5 @@ declare class AudioSink extends wrtc__default.nonstandard.RTCAudioSink {
169
195
  }) => void): () => void;
170
196
  }
171
197
 
172
- export { ASSISTANT_JOINED_ROOM, ASSISTANT_LEFT_ROOM, AUDIO_STREAM_READY, Assistant, AudioSink, AudioSource, TRIGGER_EVENT_SUCCESS, Trigger };
198
+ export { ASSISTANT_JOINED_ROOM, ASSISTANT_LEFT_ROOM, AUDIO_STREAM_READY, Assistant, AudioSink, AudioSource, PARTICIPANT_AUDIO_TRACK_ADDED, PARTICIPANT_AUDIO_TRACK_REMOVED, PARTICIPANT_VIDEO_TRACK_ADDED, PARTICIPANT_VIDEO_TRACK_REMOVED, TRIGGER_EVENT_SUCCESS, Trigger };
173
199
  export type { AssistantEvents };
package/dist/index.mjs CHANGED
@@ -14,6 +14,10 @@ const TRIGGER_EVENT_SUCCESS = "trigger_event_success";
14
14
  const AUDIO_STREAM_READY = "AUDIO_STREAM_READY";
15
15
  const ASSISTANT_JOINED_ROOM = "ASSISTANT_JOINED_ROOM";
16
16
  const ASSISTANT_LEFT_ROOM = "ASSISTANT_LEFT_ROOM";
17
+ const PARTICIPANT_VIDEO_TRACK_ADDED = "PARTICIPANT_VIDEO_TRACK_ADDED";
18
+ const PARTICIPANT_VIDEO_TRACK_REMOVED = "PARTICIPANT_VIDEO_TRACK_REMOVED";
19
+ const PARTICIPANT_AUDIO_TRACK_ADDED = "PARTICIPANT_AUDIO_TRACK_ADDED";
20
+ const PARTICIPANT_AUDIO_TRACK_REMOVED = "PARTICIPANT_AUDIO_TRACK_REMOVED";
17
21
 
18
22
  /******************************************************************************
19
23
  Copyright (c) Microsoft Corporation.
@@ -559,6 +563,7 @@ class Assistant extends EventEmitter$1 {
559
563
  this.mediaStream = null;
560
564
  this.audioSource = null;
561
565
  this.combinedStream = null;
566
+ this.remoteMediaTracks = {};
562
567
  this.roomUrl = null;
563
568
  this.handleConnectionStatusChange = (status) => {
564
569
  if (status === "connected") {
@@ -568,6 +573,41 @@ class Assistant extends EventEmitter$1 {
568
573
  this.emit(ASSISTANT_LEFT_ROOM, { roomUrl: this.roomUrl || "" });
569
574
  }
570
575
  };
576
+ this.handleRemoteParticipantsTracksChange = (remoteParticipants) => {
577
+ const currentRemoteMediaTracks = remoteParticipants.flatMap(({ id: participantId, stream }) => {
578
+ if (!stream) {
579
+ return [];
580
+ }
581
+ const tracks = stream.getTracks();
582
+ tracks.forEach((track) => {
583
+ if (!this.remoteMediaTracks[track.id]) {
584
+ const eventName = track.kind === "video" ? PARTICIPANT_VIDEO_TRACK_ADDED : PARTICIPANT_AUDIO_TRACK_ADDED;
585
+ this.emit(eventName, {
586
+ participantId,
587
+ stream,
588
+ track,
589
+ });
590
+ this.remoteMediaTracks[track.id] = {
591
+ participantId,
592
+ stream,
593
+ track,
594
+ };
595
+ }
596
+ });
597
+ return tracks;
598
+ });
599
+ Object.values(this.remoteMediaTracks).forEach(({ participantId, stream, track }) => {
600
+ if (!currentRemoteMediaTracks.includes(track)) {
601
+ const eventName = track.kind === "video" ? PARTICIPANT_VIDEO_TRACK_REMOVED : PARTICIPANT_AUDIO_TRACK_REMOVED;
602
+ this.emit(eventName, {
603
+ participantId,
604
+ stream,
605
+ track,
606
+ });
607
+ delete this.remoteMediaTracks[track.id];
608
+ }
609
+ });
610
+ };
571
611
  this.assistantKey = assistantKey;
572
612
  this.client = new WherebyClient();
573
613
  this.roomConnection = this.client.getRoomConnection();
@@ -592,8 +632,9 @@ class Assistant extends EventEmitter$1 {
592
632
  const audioMixer = new AudioMixer(handleStreamReady);
593
633
  this.combinedStream = audioMixer.getCombinedAudioStream();
594
634
  this.roomConnection.subscribeToRemoteParticipants(audioMixer.handleRemoteParticipants.bind(audioMixer));
595
- this.roomConnection.subscribeToConnectionStatus(this.handleConnectionStatusChange);
596
635
  }
636
+ this.roomConnection.subscribeToConnectionStatus(this.handleConnectionStatusChange);
637
+ this.roomConnection.subscribeToRemoteParticipants(this.handleRemoteParticipantsTracksChange);
597
638
  }
598
639
  joinRoom(roomUrl) {
599
640
  return __awaiter(this, void 0, void 0, function* () {
@@ -710,7 +751,7 @@ const webhookRouter = (webhookTriggers, emitter) => {
710
751
  res.status(200);
711
752
  res.end();
712
753
  });
713
- router.post("/", jsonParser, (req, res) => {
754
+ router.post("/", jsonParser, (req, res) => __awaiter(void 0, void 0, void 0, function* () {
714
755
  var _a, _b, _c, _d, _e, _f, _g, _h;
715
756
  assert(req.body, "message body is required");
716
757
  assert("type" in req.body, "webhook type is required");
@@ -718,19 +759,19 @@ const webhookRouter = (webhookTriggers, emitter) => {
718
759
  switch (req.body.type) {
719
760
  case "room.client.joined":
720
761
  shouldTriggerOnReceivedWebhook =
721
- (_b = (_a = webhookTriggers["room.client.joined"]) === null || _a === void 0 ? void 0 : _a.call(webhookTriggers, req.body)) !== null && _b !== void 0 ? _b : false;
762
+ (_b = (yield ((_a = webhookTriggers["room.client.joined"]) === null || _a === void 0 ? void 0 : _a.call(webhookTriggers, req.body)))) !== null && _b !== void 0 ? _b : false;
722
763
  break;
723
764
  case "room.client.left":
724
765
  shouldTriggerOnReceivedWebhook =
725
- (_d = (_c = webhookTriggers["room.client.left"]) === null || _c === void 0 ? void 0 : _c.call(webhookTriggers, req.body)) !== null && _d !== void 0 ? _d : false;
766
+ (_d = (yield ((_c = webhookTriggers["room.client.left"]) === null || _c === void 0 ? void 0 : _c.call(webhookTriggers, req.body)))) !== null && _d !== void 0 ? _d : false;
726
767
  break;
727
768
  case "room.session.started":
728
769
  shouldTriggerOnReceivedWebhook =
729
- (_f = (_e = webhookTriggers["room.session.started"]) === null || _e === void 0 ? void 0 : _e.call(webhookTriggers, req.body)) !== null && _f !== void 0 ? _f : false;
770
+ (_f = (yield ((_e = webhookTriggers["room.session.started"]) === null || _e === void 0 ? void 0 : _e.call(webhookTriggers, req.body)))) !== null && _f !== void 0 ? _f : false;
730
771
  break;
731
772
  case "room.session.ended":
732
773
  shouldTriggerOnReceivedWebhook =
733
- (_h = (_g = webhookTriggers["room.session.ended"]) === null || _g === void 0 ? void 0 : _g.call(webhookTriggers, req.body)) !== null && _h !== void 0 ? _h : false;
774
+ (_h = (yield ((_g = webhookTriggers["room.session.ended"]) === null || _g === void 0 ? void 0 : _g.call(webhookTriggers, req.body)))) !== null && _h !== void 0 ? _h : false;
734
775
  break;
735
776
  }
736
777
  if (shouldTriggerOnReceivedWebhook) {
@@ -739,7 +780,7 @@ const webhookRouter = (webhookTriggers, emitter) => {
739
780
  }
740
781
  res.status(200);
741
782
  res.end();
742
- });
783
+ }));
743
784
  return router;
744
785
  };
745
786
  class Trigger extends EventEmitter {
@@ -752,13 +793,10 @@ class Trigger extends EventEmitter {
752
793
  const app = express();
753
794
  const router = webhookRouter(this.webhookTriggers, this);
754
795
  app.use(router);
755
- const server = app.listen(this.port, () => {
796
+ app.listen(this.port, () => {
756
797
  // console.log(`Bot trigger server now running on port[${this.port}]`);
757
798
  });
758
- process.on("SIGTERM", () => {
759
- server.close();
760
- });
761
799
  }
762
800
  }
763
801
 
764
- export { ASSISTANT_JOINED_ROOM, ASSISTANT_LEFT_ROOM, AUDIO_STREAM_READY, Assistant, AudioSink, AudioSource, TRIGGER_EVENT_SUCCESS, Trigger };
802
+ export { ASSISTANT_JOINED_ROOM, ASSISTANT_LEFT_ROOM, AUDIO_STREAM_READY, Assistant, AudioSink, AudioSource, PARTICIPANT_AUDIO_TRACK_ADDED, PARTICIPANT_AUDIO_TRACK_REMOVED, PARTICIPANT_VIDEO_TRACK_ADDED, PARTICIPANT_VIDEO_TRACK_REMOVED, TRIGGER_EVENT_SUCCESS, Trigger };
@@ -14,6 +14,10 @@ const TRIGGER_EVENT_SUCCESS = "trigger_event_success";
14
14
  const AUDIO_STREAM_READY = "AUDIO_STREAM_READY";
15
15
  const ASSISTANT_JOINED_ROOM = "ASSISTANT_JOINED_ROOM";
16
16
  const ASSISTANT_LEFT_ROOM = "ASSISTANT_LEFT_ROOM";
17
+ const PARTICIPANT_VIDEO_TRACK_ADDED = "PARTICIPANT_VIDEO_TRACK_ADDED";
18
+ const PARTICIPANT_VIDEO_TRACK_REMOVED = "PARTICIPANT_VIDEO_TRACK_REMOVED";
19
+ const PARTICIPANT_AUDIO_TRACK_ADDED = "PARTICIPANT_AUDIO_TRACK_ADDED";
20
+ const PARTICIPANT_AUDIO_TRACK_REMOVED = "PARTICIPANT_AUDIO_TRACK_REMOVED";
17
21
 
18
22
  /******************************************************************************
19
23
  Copyright (c) Microsoft Corporation.
@@ -559,6 +563,7 @@ class Assistant extends EventEmitter$1 {
559
563
  this.mediaStream = null;
560
564
  this.audioSource = null;
561
565
  this.combinedStream = null;
566
+ this.remoteMediaTracks = {};
562
567
  this.roomUrl = null;
563
568
  this.handleConnectionStatusChange = (status) => {
564
569
  if (status === "connected") {
@@ -568,6 +573,41 @@ class Assistant extends EventEmitter$1 {
568
573
  this.emit(ASSISTANT_LEFT_ROOM, { roomUrl: this.roomUrl || "" });
569
574
  }
570
575
  };
576
+ this.handleRemoteParticipantsTracksChange = (remoteParticipants) => {
577
+ const currentRemoteMediaTracks = remoteParticipants.flatMap(({ id: participantId, stream }) => {
578
+ if (!stream) {
579
+ return [];
580
+ }
581
+ const tracks = stream.getTracks();
582
+ tracks.forEach((track) => {
583
+ if (!this.remoteMediaTracks[track.id]) {
584
+ const eventName = track.kind === "video" ? PARTICIPANT_VIDEO_TRACK_ADDED : PARTICIPANT_AUDIO_TRACK_ADDED;
585
+ this.emit(eventName, {
586
+ participantId,
587
+ stream,
588
+ track,
589
+ });
590
+ this.remoteMediaTracks[track.id] = {
591
+ participantId,
592
+ stream,
593
+ track,
594
+ };
595
+ }
596
+ });
597
+ return tracks;
598
+ });
599
+ Object.values(this.remoteMediaTracks).forEach(({ participantId, stream, track }) => {
600
+ if (!currentRemoteMediaTracks.includes(track)) {
601
+ const eventName = track.kind === "video" ? PARTICIPANT_VIDEO_TRACK_REMOVED : PARTICIPANT_AUDIO_TRACK_REMOVED;
602
+ this.emit(eventName, {
603
+ participantId,
604
+ stream,
605
+ track,
606
+ });
607
+ delete this.remoteMediaTracks[track.id];
608
+ }
609
+ });
610
+ };
571
611
  this.assistantKey = assistantKey;
572
612
  this.client = new WherebyClient();
573
613
  this.roomConnection = this.client.getRoomConnection();
@@ -592,8 +632,9 @@ class Assistant extends EventEmitter$1 {
592
632
  const audioMixer = new AudioMixer(handleStreamReady);
593
633
  this.combinedStream = audioMixer.getCombinedAudioStream();
594
634
  this.roomConnection.subscribeToRemoteParticipants(audioMixer.handleRemoteParticipants.bind(audioMixer));
595
- this.roomConnection.subscribeToConnectionStatus(this.handleConnectionStatusChange);
596
635
  }
636
+ this.roomConnection.subscribeToConnectionStatus(this.handleConnectionStatusChange);
637
+ this.roomConnection.subscribeToRemoteParticipants(this.handleRemoteParticipantsTracksChange);
597
638
  }
598
639
  joinRoom(roomUrl) {
599
640
  return __awaiter(this, void 0, void 0, function* () {
@@ -710,7 +751,7 @@ const webhookRouter = (webhookTriggers, emitter) => {
710
751
  res.status(200);
711
752
  res.end();
712
753
  });
713
- router.post("/", jsonParser, (req, res) => {
754
+ router.post("/", jsonParser, (req, res) => __awaiter(void 0, void 0, void 0, function* () {
714
755
  var _a, _b, _c, _d, _e, _f, _g, _h;
715
756
  assert(req.body, "message body is required");
716
757
  assert("type" in req.body, "webhook type is required");
@@ -718,19 +759,19 @@ const webhookRouter = (webhookTriggers, emitter) => {
718
759
  switch (req.body.type) {
719
760
  case "room.client.joined":
720
761
  shouldTriggerOnReceivedWebhook =
721
- (_b = (_a = webhookTriggers["room.client.joined"]) === null || _a === void 0 ? void 0 : _a.call(webhookTriggers, req.body)) !== null && _b !== void 0 ? _b : false;
762
+ (_b = (yield ((_a = webhookTriggers["room.client.joined"]) === null || _a === void 0 ? void 0 : _a.call(webhookTriggers, req.body)))) !== null && _b !== void 0 ? _b : false;
722
763
  break;
723
764
  case "room.client.left":
724
765
  shouldTriggerOnReceivedWebhook =
725
- (_d = (_c = webhookTriggers["room.client.left"]) === null || _c === void 0 ? void 0 : _c.call(webhookTriggers, req.body)) !== null && _d !== void 0 ? _d : false;
766
+ (_d = (yield ((_c = webhookTriggers["room.client.left"]) === null || _c === void 0 ? void 0 : _c.call(webhookTriggers, req.body)))) !== null && _d !== void 0 ? _d : false;
726
767
  break;
727
768
  case "room.session.started":
728
769
  shouldTriggerOnReceivedWebhook =
729
- (_f = (_e = webhookTriggers["room.session.started"]) === null || _e === void 0 ? void 0 : _e.call(webhookTriggers, req.body)) !== null && _f !== void 0 ? _f : false;
770
+ (_f = (yield ((_e = webhookTriggers["room.session.started"]) === null || _e === void 0 ? void 0 : _e.call(webhookTriggers, req.body)))) !== null && _f !== void 0 ? _f : false;
730
771
  break;
731
772
  case "room.session.ended":
732
773
  shouldTriggerOnReceivedWebhook =
733
- (_h = (_g = webhookTriggers["room.session.ended"]) === null || _g === void 0 ? void 0 : _g.call(webhookTriggers, req.body)) !== null && _h !== void 0 ? _h : false;
774
+ (_h = (yield ((_g = webhookTriggers["room.session.ended"]) === null || _g === void 0 ? void 0 : _g.call(webhookTriggers, req.body)))) !== null && _h !== void 0 ? _h : false;
734
775
  break;
735
776
  }
736
777
  if (shouldTriggerOnReceivedWebhook) {
@@ -739,7 +780,7 @@ const webhookRouter = (webhookTriggers, emitter) => {
739
780
  }
740
781
  res.status(200);
741
782
  res.end();
742
- });
783
+ }));
743
784
  return router;
744
785
  };
745
786
  class Trigger extends EventEmitter {
@@ -752,13 +793,10 @@ class Trigger extends EventEmitter {
752
793
  const app = express();
753
794
  const router = webhookRouter(this.webhookTriggers, this);
754
795
  app.use(router);
755
- const server = app.listen(this.port, () => {
796
+ app.listen(this.port, () => {
756
797
  // console.log(`Bot trigger server now running on port[${this.port}]`);
757
798
  });
758
- process.on("SIGTERM", () => {
759
- server.close();
760
- });
761
799
  }
762
800
  }
763
801
 
764
- export { ASSISTANT_JOINED_ROOM, ASSISTANT_LEFT_ROOM, AUDIO_STREAM_READY, Assistant, AudioSink, AudioSource, TRIGGER_EVENT_SUCCESS, Trigger };
802
+ export { ASSISTANT_JOINED_ROOM, ASSISTANT_LEFT_ROOM, AUDIO_STREAM_READY, Assistant, AudioSink, AudioSource, PARTICIPANT_AUDIO_TRACK_ADDED, PARTICIPANT_AUDIO_TRACK_REMOVED, PARTICIPANT_VIDEO_TRACK_ADDED, PARTICIPANT_VIDEO_TRACK_REMOVED, TRIGGER_EVENT_SUCCESS, Trigger };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@whereby.com/assistant-sdk",
3
3
  "description": "Assistant SDK for whereby.com",
4
4
  "author": "Whereby AS",
5
- "version": "0.0.0-canary-20250917154617",
5
+ "version": "0.0.0-canary-20250923130059",
6
6
  "license": "MIT",
7
7
  "files": [
8
8
  "dist",
@@ -51,10 +51,10 @@
51
51
  "prettier": "^3.5.3",
52
52
  "typescript": "^5.8.3",
53
53
  "@whereby.com/eslint-config": "0.1.0",
54
+ "@whereby.com/jest-config": "0.1.0",
54
55
  "@whereby.com/prettier-config": "0.1.0",
55
56
  "@whereby.com/rollup-config": "0.1.0",
56
- "@whereby.com/tsconfig": "0.1.0",
57
- "@whereby.com/jest-config": "0.1.0"
57
+ "@whereby.com/tsconfig": "0.1.0"
58
58
  },
59
59
  "dependencies": {
60
60
  "@roamhq/wrtc": "github:whereby/node-webrtc#patch/rtc_audio_source",
@@ -64,7 +64,7 @@
64
64
  "express": "5.1.0",
65
65
  "uuid": "^11.0.3",
66
66
  "ws": "^8.18.0",
67
- "@whereby.com/core": "0.0.0-canary-20250917154617"
67
+ "@whereby.com/core": "0.0.0-canary-20250923130059"
68
68
  },
69
69
  "prettier": "@whereby.com/prettier-config",
70
70
  "scripts": {