@webex/plugin-meetings 3.12.0-next.53 → 3.12.0-next.54

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.
@@ -1 +1 @@
1
- {"version":3,"names":["ReactionServerType","exports","SkinToneType"],"sources":["reactions.type.ts"],"sourcesContent":["import {REACTION_RELAY_TYPES} from './constants';\n\nexport type EmoticonData = {\n type: string;\n codepoints?: string;\n shortcodes?: string;\n};\n\nexport type SkinTone = EmoticonData;\n\nexport type Reaction = EmoticonData & {\n tone?: SkinTone;\n};\n\n// eslint-disable-next-line no-shadow\nexport enum ReactionServerType {\n smile = 'smile',\n sad = 'sad',\n wow = 'wow',\n haha = 'haha',\n celebrate = 'celebrate',\n clap = 'clap',\n thumb_up = 'thumb_up',\n thumb_down = 'thumb_down',\n heart = 'heart',\n fire = 'fire',\n prayer = 'prayer',\n speed_up = 'speed_up',\n slow_down = 'slow_down',\n}\n\n// eslint-disable-next-line no-shadow\nexport enum SkinToneType {\n normal = 'normal',\n light = 'light',\n medium_light = 'medium_light',\n medium = 'medium',\n medium_dark = 'medium_dark',\n dark = 'dark',\n}\n\nexport type Sender = {\n displayName: string;\n participantId: string;\n};\n\nexport type ProcessedReaction = {\n reaction: Reaction;\n sender: {\n id: Sender['participantId'];\n name: string;\n };\n};\n\ntype RelayEventData = {\n relayType: (typeof REACTION_RELAY_TYPES)['REACTION'];\n reaction: Reaction;\n sender: Sender;\n};\n\nexport type RelayEvent = {\n data: RelayEventData;\n};\n"],"mappings":";;;;;;;AAcA;AAAA,IACYA,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,0BAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAA,OAAlBA,kBAAkB;AAAA,OAgB9B;AAAA,IACYE,YAAY,GAAAD,OAAA,CAAAC,YAAA,0BAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAA,OAAZA,YAAY;AAAA","ignoreList":[]}
1
+ {"version":3,"names":["ReactionServerType","exports","SkinToneType"],"sources":["reactions.type.ts"],"sourcesContent":["import {REACTION_RELAY_TYPES} from './constants';\n\nexport type EmoticonData = {\n type: string;\n codepoints?: string;\n shortcodes?: string;\n};\n\nexport type SkinTone = EmoticonData;\n\nexport type Reaction = EmoticonData & {\n tone?: SkinTone;\n};\n\n// eslint-disable-next-line no-shadow\nexport enum ReactionServerType {\n smile = 'smile',\n sad = 'sad',\n wow = 'wow',\n haha = 'haha',\n celebrate = 'celebrate',\n clap = 'clap',\n thumb_up = 'thumb_up',\n thumb_down = 'thumb_down',\n heart = 'heart',\n fire = 'fire',\n prayer = 'prayer',\n speed_up = 'speed_up',\n slow_down = 'slow_down',\n}\n\n// eslint-disable-next-line no-shadow\nexport enum SkinToneType {\n normal = 'normal',\n light = 'light',\n medium_light = 'medium_light',\n medium = 'medium',\n medium_dark = 'medium_dark',\n dark = 'dark',\n}\n\nexport type Sender = {\n displayName: string;\n participantId: string;\n};\n\nexport type ProcessedReaction = {\n reaction: Reaction;\n sender: {\n id: Sender['participantId'];\n name: string;\n };\n};\n\ntype RelayEventData = {\n relayType: (typeof REACTION_RELAY_TYPES)['REACTION'];\n reaction: Reaction;\n sender: Sender;\n};\n\nexport type RelayEvent = {\n data: RelayEventData;\n headers?: {\n route?: string;\n };\n};\n"],"mappings":";;;;;;;AAcA;AAAA,IACYA,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,0BAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAA,OAAlBA,kBAAkB;AAAA,OAgB9B;AAAA,IACYE,YAAY,GAAAD,OAAA,CAAAC,YAAA,0BAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAA,OAAZA,YAAY;AAAA","ignoreList":[]}
@@ -1324,6 +1324,12 @@ export default class Meeting extends StatelessWebexPlugin {
1324
1324
  * @returns {void}
1325
1325
  */
1326
1326
  private processLocusLLMEvent;
1327
+ /**
1328
+ * Verifies the relay event was delivered for the active LLM session binding.
1329
+ * @param {RelayEvent} event Event object coming from LLM Connection
1330
+ * @returns {boolean}
1331
+ */
1332
+ private isRelayEventRouteValid;
1327
1333
  /**
1328
1334
  * Callback called when a relay event is received from meeting LLM Connection
1329
1335
  * @param {RelayEvent} e Event object coming from LLM Connection
@@ -49,5 +49,8 @@ type RelayEventData = {
49
49
  };
50
50
  export type RelayEvent = {
51
51
  data: RelayEventData;
52
+ headers?: {
53
+ route?: string;
54
+ };
52
55
  };
53
56
  export {};
@@ -774,7 +774,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
774
774
  }, _callee1);
775
775
  }))();
776
776
  },
777
- version: "3.12.0-next.53"
777
+ version: "3.12.0-next.54"
778
778
  });
779
779
  var _default = exports.default = Webinar;
780
780
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -94,5 +94,5 @@
94
94
  "//": [
95
95
  "TODO: upgrade jwt-decode when moving to node 18"
96
96
  ],
97
- "version": "3.12.0-next.53"
97
+ "version": "3.12.0-next.54"
98
98
  }
@@ -137,6 +137,7 @@ import {
137
137
  STAGE_MANAGER_TYPE,
138
138
  LOCUSEVENT,
139
139
  LOCUS_LLM_EVENT,
140
+ LLM_PRACTICE_SESSION,
140
141
  } from '../constants';
141
142
  import BEHAVIORAL_METRICS from '../metrics/constants';
142
143
  import ParameterError from '../common/errors/parameter';
@@ -5931,6 +5932,31 @@ export default class Meeting extends StatelessWebexPlugin {
5931
5932
  }
5932
5933
  };
5933
5934
 
5935
+ /**
5936
+ * Verifies the relay event was delivered for the active LLM session binding.
5937
+ * @param {RelayEvent} event Event object coming from LLM Connection
5938
+ * @returns {boolean}
5939
+ */
5940
+ private isRelayEventRouteValid(event: RelayEvent): boolean {
5941
+ const route = event?.headers?.route;
5942
+
5943
+ if (!route) {
5944
+ return true;
5945
+ }
5946
+
5947
+ const {llm} = (this as any).webex.internal;
5948
+ const isPracticeSession = llm.isConnected(LLM_PRACTICE_SESSION);
5949
+ const expectedBinding = isPracticeSession
5950
+ ? llm.getBinding(LLM_PRACTICE_SESSION)
5951
+ : llm.getBinding();
5952
+
5953
+ if (!expectedBinding || route === expectedBinding) {
5954
+ return true;
5955
+ }
5956
+
5957
+ return false;
5958
+ }
5959
+
5934
5960
  /**
5935
5961
  * Callback called when a relay event is received from meeting LLM Connection
5936
5962
  * @param {RelayEvent} e Event object coming from LLM Connection
@@ -5938,6 +5964,9 @@ export default class Meeting extends StatelessWebexPlugin {
5938
5964
  * @returns {void}
5939
5965
  */
5940
5966
  private processRelayEvent = (e: RelayEvent): void => {
5967
+ if (!this.isRelayEventRouteValid(e)) {
5968
+ return;
5969
+ }
5941
5970
  switch (e.data.relayType) {
5942
5971
  case REACTION_RELAY_TYPES.REACTION:
5943
5972
  if (
@@ -60,4 +60,7 @@ type RelayEventData = {
60
60
 
61
61
  export type RelayEvent = {
62
62
  data: RelayEventData;
63
+ headers?: {
64
+ route?: string;
65
+ };
63
66
  };
@@ -35,6 +35,7 @@ import {
35
35
  OFFLINE,
36
36
  ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT,
37
37
  LOCUS_LLM_EVENT,
38
+ LLM_PRACTICE_SESSION,
38
39
  RECORDING_STATE,
39
40
  } from '@webex/plugin-meetings/src/constants';
40
41
  import {
@@ -1979,6 +1980,113 @@ describe('plugin-meetings', () => {
1979
1980
  fakeProcessedReaction
1980
1981
  );
1981
1982
  });
1983
+
1984
+ [
1985
+ {
1986
+ title: 'should skip a reaction when the default relay route does not match the LLM binding',
1987
+ isPracticeSessionConnected: false,
1988
+ route: 'wrong-default-route',
1989
+ defaultBinding: 'default-route',
1990
+ practiceBinding: 'practice-route',
1991
+ shouldProcess: false,
1992
+ expectedSessionLabel: 'default session',
1993
+ },
1994
+ {
1995
+ title: 'should process a reaction when the default relay route matches the LLM binding',
1996
+ isPracticeSessionConnected: false,
1997
+ route: 'default-route',
1998
+ defaultBinding: 'default-route',
1999
+ practiceBinding: 'practice-route',
2000
+ shouldProcess: true,
2001
+ },
2002
+ {
2003
+ title:
2004
+ 'should process a reaction when the practice-session relay route matches the practice-session LLM binding',
2005
+ isPracticeSessionConnected: true,
2006
+ route: 'practice-route',
2007
+ defaultBinding: 'default-route',
2008
+ practiceBinding: 'practice-route',
2009
+ shouldProcess: true,
2010
+ },
2011
+ {
2012
+ title:
2013
+ 'should skip a reaction when the practice-session relay route does not match the practice-session LLM binding',
2014
+ isPracticeSessionConnected: true,
2015
+ route: 'default-route',
2016
+ defaultBinding: 'default-route',
2017
+ practiceBinding: 'practice-route',
2018
+ shouldProcess: false,
2019
+ expectedSessionLabel: 'practice session',
2020
+ },
2021
+ ].forEach(
2022
+ ({
2023
+ title,
2024
+ isPracticeSessionConnected,
2025
+ route,
2026
+ defaultBinding,
2027
+ practiceBinding,
2028
+ shouldProcess,
2029
+ expectedSessionLabel,
2030
+ }) => {
2031
+ it(title, () => {
2032
+ meeting.isReactionsSupported = sinon.stub().returns(true);
2033
+ meeting.config.receiveReactions = true;
2034
+ const fakeSendersName = 'Fake reactors name';
2035
+ meeting.members.membersCollection.get = sinon.stub().returns({name: fakeSendersName});
2036
+ webex.internal.llm.isConnected = sinon.stub().callsFake((llmSessionId) => {
2037
+ return llmSessionId === LLM_PRACTICE_SESSION && isPracticeSessionConnected;
2038
+ });
2039
+ webex.internal.llm.getBinding = sinon.stub().callsFake((llmSessionId) => {
2040
+ if (llmSessionId === LLM_PRACTICE_SESSION) {
2041
+ return practiceBinding;
2042
+ }
2043
+
2044
+ return defaultBinding;
2045
+ });
2046
+ const fakeReactionPayload = {
2047
+ type: 'fake_type',
2048
+ codepoints: 'fake_codepoints',
2049
+ shortcodes: 'fake_shortcodes',
2050
+ };
2051
+ const fakeSenderPayload = {
2052
+ participantId: 'fake_participant_id',
2053
+ };
2054
+ const fakeRelayEvent = {
2055
+ headers: {route},
2056
+ data: {
2057
+ relayType: REACTION_RELAY_TYPES.REACTION,
2058
+ reaction: fakeReactionPayload,
2059
+ sender: fakeSenderPayload,
2060
+ },
2061
+ };
2062
+ const fakeProcessedReaction = {
2063
+ reaction: fakeReactionPayload,
2064
+ sender: {
2065
+ id: fakeSenderPayload.participantId,
2066
+ name: fakeSendersName,
2067
+ },
2068
+ };
2069
+
2070
+ TriggerProxy.trigger.resetHistory();
2071
+ meeting.processRelayEvent(fakeRelayEvent);
2072
+
2073
+ if (shouldProcess) {
2074
+ assert.calledWith(
2075
+ TriggerProxy.trigger,
2076
+ sinon.match.instanceOf(Meeting),
2077
+ {
2078
+ file: 'meeting/index',
2079
+ function: 'join',
2080
+ },
2081
+ EVENT_TRIGGERS.MEETING_RECEIVE_REACTIONS,
2082
+ fakeProcessedReaction
2083
+ );
2084
+ } else {
2085
+ assert.notCalled(TriggerProxy.trigger);
2086
+ }
2087
+ });
2088
+ }
2089
+ );
1982
2090
  });
1983
2091
 
1984
2092
  describe('#handleLLMOnline', () => {
@@ -16825,4 +16933,4 @@ describe('plugin-meetings', () => {
16825
16933
  assert.calledOnceWithExactly(meeting.meetingRequest.cancelSipCallOut, participantId);
16826
16934
  });
16827
16935
  });
16828
- });
16936
+ });