@webex/contact-center 0.0.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README.md +81 -0
  2. package/__mocks__/workerMock.js +15 -0
  3. package/babel.config.js +15 -0
  4. package/dist/cc.js +1416 -0
  5. package/dist/cc.js.map +1 -0
  6. package/dist/config.js +72 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/constants.js +58 -0
  9. package/dist/constants.js.map +1 -0
  10. package/dist/index.js +142 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/logger-proxy.js +115 -0
  13. package/dist/logger-proxy.js.map +1 -0
  14. package/dist/metrics/MetricsManager.js +474 -0
  15. package/dist/metrics/MetricsManager.js.map +1 -0
  16. package/dist/metrics/behavioral-events.js +322 -0
  17. package/dist/metrics/behavioral-events.js.map +1 -0
  18. package/dist/metrics/constants.js +134 -0
  19. package/dist/metrics/constants.js.map +1 -0
  20. package/dist/services/WebCallingService.js +323 -0
  21. package/dist/services/WebCallingService.js.map +1 -0
  22. package/dist/services/agent/index.js +177 -0
  23. package/dist/services/agent/index.js.map +1 -0
  24. package/dist/services/agent/types.js +137 -0
  25. package/dist/services/agent/types.js.map +1 -0
  26. package/dist/services/config/Util.js +203 -0
  27. package/dist/services/config/Util.js.map +1 -0
  28. package/dist/services/config/constants.js +221 -0
  29. package/dist/services/config/constants.js.map +1 -0
  30. package/dist/services/config/index.js +607 -0
  31. package/dist/services/config/index.js.map +1 -0
  32. package/dist/services/config/types.js +334 -0
  33. package/dist/services/config/types.js.map +1 -0
  34. package/dist/services/constants.js +117 -0
  35. package/dist/services/constants.js.map +1 -0
  36. package/dist/services/core/Err.js +43 -0
  37. package/dist/services/core/Err.js.map +1 -0
  38. package/dist/services/core/GlobalTypes.js +6 -0
  39. package/dist/services/core/GlobalTypes.js.map +1 -0
  40. package/dist/services/core/Utils.js +126 -0
  41. package/dist/services/core/Utils.js.map +1 -0
  42. package/dist/services/core/WebexRequest.js +96 -0
  43. package/dist/services/core/WebexRequest.js.map +1 -0
  44. package/dist/services/core/aqm-reqs.js +246 -0
  45. package/dist/services/core/aqm-reqs.js.map +1 -0
  46. package/dist/services/core/constants.js +109 -0
  47. package/dist/services/core/constants.js.map +1 -0
  48. package/dist/services/core/types.js +6 -0
  49. package/dist/services/core/types.js.map +1 -0
  50. package/dist/services/core/websocket/WebSocketManager.js +187 -0
  51. package/dist/services/core/websocket/WebSocketManager.js.map +1 -0
  52. package/dist/services/core/websocket/connection-service.js +111 -0
  53. package/dist/services/core/websocket/connection-service.js.map +1 -0
  54. package/dist/services/core/websocket/keepalive.worker.js +94 -0
  55. package/dist/services/core/websocket/keepalive.worker.js.map +1 -0
  56. package/dist/services/core/websocket/types.js +6 -0
  57. package/dist/services/core/websocket/types.js.map +1 -0
  58. package/dist/services/index.js +78 -0
  59. package/dist/services/index.js.map +1 -0
  60. package/dist/services/task/AutoWrapup.js +88 -0
  61. package/dist/services/task/AutoWrapup.js.map +1 -0
  62. package/dist/services/task/TaskManager.js +369 -0
  63. package/dist/services/task/TaskManager.js.map +1 -0
  64. package/dist/services/task/constants.js +58 -0
  65. package/dist/services/task/constants.js.map +1 -0
  66. package/dist/services/task/contact.js +464 -0
  67. package/dist/services/task/contact.js.map +1 -0
  68. package/dist/services/task/dialer.js +60 -0
  69. package/dist/services/task/dialer.js.map +1 -0
  70. package/dist/services/task/index.js +1188 -0
  71. package/dist/services/task/index.js.map +1 -0
  72. package/dist/services/task/types.js +214 -0
  73. package/dist/services/task/types.js.map +1 -0
  74. package/dist/types/cc.d.ts +676 -0
  75. package/dist/types/config.d.ts +66 -0
  76. package/dist/types/constants.d.ts +45 -0
  77. package/dist/types/index.d.ts +178 -0
  78. package/dist/types/logger-proxy.d.ts +71 -0
  79. package/dist/types/metrics/MetricsManager.d.ts +223 -0
  80. package/dist/types/metrics/behavioral-events.d.ts +29 -0
  81. package/dist/types/metrics/constants.d.ts +127 -0
  82. package/dist/types/services/WebCallingService.d.ts +1 -0
  83. package/dist/types/services/agent/index.d.ts +46 -0
  84. package/dist/types/services/agent/types.d.ts +413 -0
  85. package/dist/types/services/config/Util.d.ts +19 -0
  86. package/dist/types/services/config/constants.d.ts +203 -0
  87. package/dist/types/services/config/index.d.ts +171 -0
  88. package/dist/types/services/config/types.d.ts +1113 -0
  89. package/dist/types/services/constants.d.ts +97 -0
  90. package/dist/types/services/core/Err.d.ts +119 -0
  91. package/dist/types/services/core/GlobalTypes.d.ts +33 -0
  92. package/dist/types/services/core/Utils.d.ts +36 -0
  93. package/dist/types/services/core/WebexRequest.d.ts +22 -0
  94. package/dist/types/services/core/aqm-reqs.d.ts +16 -0
  95. package/dist/types/services/core/constants.d.ts +85 -0
  96. package/dist/types/services/core/types.d.ts +47 -0
  97. package/dist/types/services/core/websocket/WebSocketManager.d.ts +34 -0
  98. package/dist/types/services/core/websocket/connection-service.d.ts +27 -0
  99. package/dist/types/services/core/websocket/keepalive.worker.d.ts +2 -0
  100. package/dist/types/services/core/websocket/types.d.ts +37 -0
  101. package/dist/types/services/index.d.ts +52 -0
  102. package/dist/types/services/task/AutoWrapup.d.ts +40 -0
  103. package/dist/types/services/task/TaskManager.d.ts +1 -0
  104. package/dist/types/services/task/constants.d.ts +46 -0
  105. package/dist/types/services/task/contact.d.ts +59 -0
  106. package/dist/types/services/task/dialer.d.ts +28 -0
  107. package/dist/types/services/task/index.d.ts +569 -0
  108. package/dist/types/services/task/types.d.ts +1041 -0
  109. package/dist/types/types.d.ts +452 -0
  110. package/dist/types/webex-config.d.ts +53 -0
  111. package/dist/types/webex.d.ts +7 -0
  112. package/dist/types.js +292 -0
  113. package/dist/types.js.map +1 -0
  114. package/dist/webex-config.js +60 -0
  115. package/dist/webex-config.js.map +1 -0
  116. package/dist/webex.js +99 -0
  117. package/dist/webex.js.map +1 -0
  118. package/jest.config.js +45 -0
  119. package/package.json +83 -0
  120. package/src/cc.ts +1618 -0
  121. package/src/config.ts +65 -0
  122. package/src/constants.ts +51 -0
  123. package/src/index.ts +220 -0
  124. package/src/logger-proxy.ts +110 -0
  125. package/src/metrics/MetricsManager.ts +512 -0
  126. package/src/metrics/behavioral-events.ts +332 -0
  127. package/src/metrics/constants.ts +135 -0
  128. package/src/services/WebCallingService.ts +351 -0
  129. package/src/services/agent/index.ts +149 -0
  130. package/src/services/agent/types.ts +440 -0
  131. package/src/services/config/Util.ts +261 -0
  132. package/src/services/config/constants.ts +249 -0
  133. package/src/services/config/index.ts +743 -0
  134. package/src/services/config/types.ts +1117 -0
  135. package/src/services/constants.ts +111 -0
  136. package/src/services/core/Err.ts +126 -0
  137. package/src/services/core/GlobalTypes.ts +34 -0
  138. package/src/services/core/Utils.ts +132 -0
  139. package/src/services/core/WebexRequest.ts +103 -0
  140. package/src/services/core/aqm-reqs.ts +272 -0
  141. package/src/services/core/constants.ts +106 -0
  142. package/src/services/core/types.ts +48 -0
  143. package/src/services/core/websocket/WebSocketManager.ts +196 -0
  144. package/src/services/core/websocket/connection-service.ts +142 -0
  145. package/src/services/core/websocket/keepalive.worker.js +88 -0
  146. package/src/services/core/websocket/types.ts +40 -0
  147. package/src/services/index.ts +71 -0
  148. package/src/services/task/AutoWrapup.ts +86 -0
  149. package/src/services/task/TaskManager.ts +420 -0
  150. package/src/services/task/constants.ts +52 -0
  151. package/src/services/task/contact.ts +429 -0
  152. package/src/services/task/dialer.ts +52 -0
  153. package/src/services/task/index.ts +1375 -0
  154. package/src/services/task/types.ts +1113 -0
  155. package/src/types.ts +639 -0
  156. package/src/webex-config.ts +54 -0
  157. package/src/webex.js +96 -0
  158. package/test/unit/spec/cc.ts +1985 -0
  159. package/test/unit/spec/metrics/MetricsManager.ts +491 -0
  160. package/test/unit/spec/metrics/behavioral-events.ts +102 -0
  161. package/test/unit/spec/services/WebCallingService.ts +416 -0
  162. package/test/unit/spec/services/agent/index.ts +65 -0
  163. package/test/unit/spec/services/config/index.ts +1035 -0
  164. package/test/unit/spec/services/core/Utils.ts +279 -0
  165. package/test/unit/spec/services/core/WebexRequest.ts +144 -0
  166. package/test/unit/spec/services/core/aqm-reqs.ts +570 -0
  167. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +378 -0
  168. package/test/unit/spec/services/core/websocket/connection-service.ts +178 -0
  169. package/test/unit/spec/services/task/TaskManager.ts +1351 -0
  170. package/test/unit/spec/services/task/contact.ts +204 -0
  171. package/test/unit/spec/services/task/dialer.ts +157 -0
  172. package/test/unit/spec/services/task/index.ts +1474 -0
  173. package/tsconfig.json +6 -0
  174. package/typedoc.json +37 -0
  175. package/typedoc.md +240 -0
  176. package/umd/contact-center.min.js +3 -0
  177. package/umd/contact-center.min.js.map +1 -0
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _agent = _interopRequireDefault(require("./agent"));
8
+ var _contact = _interopRequireDefault(require("./task/contact"));
9
+ var _config = _interopRequireDefault(require("./config"));
10
+ var _aqmReqs = _interopRequireDefault(require("./core/aqm-reqs"));
11
+ var _WebSocketManager = require("./core/websocket/WebSocketManager");
12
+ var _connectionService = require("./core/websocket/connection-service");
13
+ var _dialer = _interopRequireDefault(require("./task/dialer"));
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+ /**
16
+ * Services class provides centralized access to all contact center plugin services
17
+ * using a singleton pattern to ensure a single instance throughout the application.
18
+ * @private
19
+ * @ignore
20
+ * @class
21
+ */
22
+ class Services {
23
+ /** Agent services for managing agent state and capabilities */
24
+
25
+ /** Configuration services for agent settings */
26
+
27
+ /** Contact services for managing customer interactions */
28
+
29
+ /** Dialer services for outbound calling features */
30
+
31
+ /** WebSocket manager for handling real-time communications */
32
+
33
+ /** Connection service for managing websocket connections */
34
+
35
+ /** Singleton instance of the Services class */
36
+
37
+ /**
38
+ * Creates a new Services instance
39
+ * @param options - Configuration options
40
+ * @param options.webex - WebexSDK instance
41
+ * @param options.connectionConfig - Subscription configuration for websocket connection
42
+ */
43
+ constructor(options) {
44
+ const {
45
+ webex,
46
+ connectionConfig
47
+ } = options;
48
+ this.webSocketManager = new _WebSocketManager.WebSocketManager({
49
+ webex
50
+ });
51
+ const aqmReq = new _aqmReqs.default(this.webSocketManager);
52
+ this.config = new _config.default();
53
+ this.agent = (0, _agent.default)(aqmReq);
54
+ this.contact = (0, _contact.default)(aqmReq);
55
+ this.dialer = (0, _dialer.default)(aqmReq);
56
+ this.connectionService = new _connectionService.ConnectionService({
57
+ webSocketManager: this.webSocketManager,
58
+ subscribeRequest: connectionConfig
59
+ });
60
+ }
61
+
62
+ /**
63
+ * Gets singleton instance of Services class
64
+ * Creates a new instance if one doesn't exist
65
+ * @param options - Configuration options
66
+ * @param options.webex - WebexSDK instance
67
+ * @param options.connectionConfig - Subscription configuration for websocket connection
68
+ * @returns The singleton Services instance
69
+ */
70
+ static getInstance(options) {
71
+ if (!this.instance) {
72
+ this.instance = new Services(options);
73
+ }
74
+ return this.instance;
75
+ }
76
+ }
77
+ exports.default = Services;
78
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_agent","_interopRequireDefault","require","_contact","_config","_aqmReqs","_WebSocketManager","_connectionService","_dialer","obj","__esModule","default","Services","constructor","options","webex","connectionConfig","webSocketManager","WebSocketManager","aqmReq","AqmReqs","config","AgentConfigService","agent","routingAgent","contact","routingContact","dialer","aqmDialer","connectionService","ConnectionService","subscribeRequest","getInstance","instance","exports"],"sources":["index.ts"],"sourcesContent":["import routingAgent from './agent';\nimport routingContact from './task/contact';\nimport AgentConfigService from './config';\nimport AqmReqs from './core/aqm-reqs';\nimport {WebSocketManager} from './core/websocket/WebSocketManager';\nimport {ConnectionService} from './core/websocket/connection-service';\nimport {WebexSDK, SubscribeRequest} from '../types';\nimport aqmDialer from './task/dialer';\n\n/**\n * Services class provides centralized access to all contact center plugin services\n * using a singleton pattern to ensure a single instance throughout the application.\n * @private\n * @ignore\n * @class\n */\nexport default class Services {\n /** Agent services for managing agent state and capabilities */\n public readonly agent: ReturnType<typeof routingAgent>;\n /** Configuration services for agent settings */\n public readonly config: AgentConfigService;\n /** Contact services for managing customer interactions */\n public readonly contact: ReturnType<typeof routingContact>;\n /** Dialer services for outbound calling features */\n public readonly dialer: ReturnType<typeof aqmDialer>;\n /** WebSocket manager for handling real-time communications */\n public readonly webSocketManager: WebSocketManager;\n /** Connection service for managing websocket connections */\n public readonly connectionService: ConnectionService;\n /** Singleton instance of the Services class */\n private static instance: Services;\n\n /**\n * Creates a new Services instance\n * @param options - Configuration options\n * @param options.webex - WebexSDK instance\n * @param options.connectionConfig - Subscription configuration for websocket connection\n */\n constructor(options: {webex: WebexSDK; connectionConfig: SubscribeRequest}) {\n const {webex, connectionConfig} = options;\n this.webSocketManager = new WebSocketManager({webex});\n const aqmReq = new AqmReqs(this.webSocketManager);\n this.config = new AgentConfigService();\n this.agent = routingAgent(aqmReq);\n this.contact = routingContact(aqmReq);\n this.dialer = aqmDialer(aqmReq);\n this.connectionService = new ConnectionService({\n webSocketManager: this.webSocketManager,\n subscribeRequest: connectionConfig,\n });\n }\n\n /**\n * Gets singleton instance of Services class\n * Creates a new instance if one doesn't exist\n * @param options - Configuration options\n * @param options.webex - WebexSDK instance\n * @param options.connectionConfig - Subscription configuration for websocket connection\n * @returns The singleton Services instance\n */\n public static getInstance(options: {\n webex: WebexSDK;\n connectionConfig: SubscribeRequest;\n }): Services {\n if (!this.instance) {\n this.instance = new Services(options);\n }\n\n return this.instance;\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,QAAA,GAAAF,sBAAA,CAAAC,OAAA;AACA,IAAAE,OAAA,GAAAH,sBAAA,CAAAC,OAAA;AACA,IAAAG,QAAA,GAAAJ,sBAAA,CAAAC,OAAA;AACA,IAAAI,iBAAA,GAAAJ,OAAA;AACA,IAAAK,kBAAA,GAAAL,OAAA;AAEA,IAAAM,OAAA,GAAAP,sBAAA,CAAAC,OAAA;AAAsC,SAAAD,uBAAAQ,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAEtC;AACA;AACA;AACA;AACA;AACA;AACA;AACe,MAAMG,QAAQ,CAAC;EAC5B;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAGA;AACF;AACA;AACA;AACA;AACA;EACEC,WAAWA,CAACC,OAA8D,EAAE;IAC1E,MAAM;MAACC,KAAK;MAAEC;IAAgB,CAAC,GAAGF,OAAO;IACzC,IAAI,CAACG,gBAAgB,GAAG,IAAIC,kCAAgB,CAAC;MAACH;IAAK,CAAC,CAAC;IACrD,MAAMI,MAAM,GAAG,IAAIC,gBAAO,CAAC,IAAI,CAACH,gBAAgB,CAAC;IACjD,IAAI,CAACI,MAAM,GAAG,IAAIC,eAAkB,CAAC,CAAC;IACtC,IAAI,CAACC,KAAK,GAAG,IAAAC,cAAY,EAACL,MAAM,CAAC;IACjC,IAAI,CAACM,OAAO,GAAG,IAAAC,gBAAc,EAACP,MAAM,CAAC;IACrC,IAAI,CAACQ,MAAM,GAAG,IAAAC,eAAS,EAACT,MAAM,CAAC;IAC/B,IAAI,CAACU,iBAAiB,GAAG,IAAIC,oCAAiB,CAAC;MAC7Cb,gBAAgB,EAAE,IAAI,CAACA,gBAAgB;MACvCc,gBAAgB,EAAEf;IACpB,CAAC,CAAC;EACJ;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACE,OAAcgB,WAAWA,CAAClB,OAGzB,EAAY;IACX,IAAI,CAAC,IAAI,CAACmB,QAAQ,EAAE;MAClB,IAAI,CAACA,QAAQ,GAAG,IAAIrB,QAAQ,CAACE,OAAO,CAAC;IACvC;IAEA,OAAO,IAAI,CAACmB,QAAQ;EACtB;AACF;AAACC,OAAA,CAAAvB,OAAA,GAAAC,QAAA"}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _loggerProxy = _interopRequireDefault(require("../../logger-proxy"));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ /**
10
+ * AutoWrapup class implements a timer for automatic wrap-up functionality.
11
+ * It handles timing the wrap-up period and executing a callback when the timer completes.
12
+ */
13
+ class AutoWrapup {
14
+ timer = null;
15
+ startTime = 0;
16
+ allowCancelAutoWrapup = false;
17
+
18
+ /**
19
+ * Creates a new AutoWrapup timer
20
+ * @param interval - Time in milliseconds before auto wrap-up executes
21
+ * @param allowCancelAutoWrapup - Whether to allow canceling the auto wrap-up
22
+ */
23
+ constructor(interval, allowCancelAutoWrapup = false) {
24
+ this.interval = interval;
25
+ this.allowCancelAutoWrapup = allowCancelAutoWrapup;
26
+ }
27
+
28
+ /**
29
+ * Starts the auto wrap-up timer
30
+ * @param onComplete - Callback function to execute when timer completes
31
+ */
32
+ start(onComplete) {
33
+ _loggerProxy.default.info('AutoWrapup: clear called', {
34
+ module: 'AutoWrapup',
35
+ method: 'clear'
36
+ });
37
+ if (this.timer) {
38
+ this.clear();
39
+ }
40
+ this.startTime = Date.now();
41
+ this.timer = setTimeout(() => {
42
+ onComplete();
43
+ this.timer = null;
44
+ }, this.interval);
45
+ }
46
+
47
+ /**
48
+ * Clears the auto wrap-up timer if it's running
49
+ */
50
+ clear() {
51
+ _loggerProxy.default.info('AutoWrapup: clear called', {
52
+ module: 'AutoWrapup',
53
+ method: 'clear'
54
+ });
55
+ if (this.timer) {
56
+ clearTimeout(this.timer);
57
+ this.timer = null;
58
+ this.startTime = 0;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Gets the remaining time in milliseconds
64
+ * @returns Time left in milliseconds
65
+ */
66
+ getTimeLeft() {
67
+ const elapsed = Date.now() - this.startTime;
68
+ return Math.max(0, this.interval - elapsed);
69
+ }
70
+
71
+ /**
72
+ * Checks if the timer is currently running
73
+ * @returns True if the timer is running, false otherwise
74
+ */
75
+ isRunning() {
76
+ return this.timer !== null;
77
+ }
78
+
79
+ /**
80
+ * Gets the remaining time in seconds (rounded)
81
+ * @returns Time left in seconds
82
+ */
83
+ getTimeLeftSeconds() {
84
+ return Math.ceil(this.getTimeLeft() / 1000);
85
+ }
86
+ }
87
+ exports.default = AutoWrapup;
88
+ //# sourceMappingURL=AutoWrapup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_loggerProxy","_interopRequireDefault","require","obj","__esModule","default","AutoWrapup","timer","startTime","allowCancelAutoWrapup","constructor","interval","start","onComplete","LoggerProxy","info","module","method","clear","Date","now","setTimeout","clearTimeout","getTimeLeft","elapsed","Math","max","isRunning","getTimeLeftSeconds","ceil","exports"],"sources":["AutoWrapup.ts"],"sourcesContent":["import LoggerProxy from '../../logger-proxy';\n\n/**\n * AutoWrapup class implements a timer for automatic wrap-up functionality.\n * It handles timing the wrap-up period and executing a callback when the timer completes.\n */\nexport default class AutoWrapup {\n private timer: ReturnType<typeof setTimeout> | null = null;\n private startTime = 0;\n private readonly interval: number;\n public allowCancelAutoWrapup = false;\n\n /**\n * Creates a new AutoWrapup timer\n * @param interval - Time in milliseconds before auto wrap-up executes\n * @param allowCancelAutoWrapup - Whether to allow canceling the auto wrap-up\n */\n constructor(interval: number, allowCancelAutoWrapup = false) {\n this.interval = interval;\n this.allowCancelAutoWrapup = allowCancelAutoWrapup;\n }\n\n /**\n * Starts the auto wrap-up timer\n * @param onComplete - Callback function to execute when timer completes\n */\n public start(onComplete: () => void): void {\n LoggerProxy.info('AutoWrapup: clear called', {\n module: 'AutoWrapup',\n method: 'clear',\n });\n\n if (this.timer) {\n this.clear();\n }\n\n this.startTime = Date.now();\n\n this.timer = setTimeout(() => {\n onComplete();\n this.timer = null;\n }, this.interval);\n }\n\n /**\n * Clears the auto wrap-up timer if it's running\n */\n public clear(): void {\n LoggerProxy.info('AutoWrapup: clear called', {\n module: 'AutoWrapup',\n method: 'clear',\n });\n\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n this.startTime = 0;\n }\n }\n\n /**\n * Gets the remaining time in milliseconds\n * @returns Time left in milliseconds\n */\n public getTimeLeft(): number {\n const elapsed = Date.now() - this.startTime;\n\n return Math.max(0, this.interval - elapsed);\n }\n\n /**\n * Checks if the timer is currently running\n * @returns True if the timer is running, false otherwise\n */\n public isRunning(): boolean {\n return this.timer !== null;\n }\n\n /**\n * Gets the remaining time in seconds (rounded)\n * @returns Time left in seconds\n */\n public getTimeLeftSeconds(): number {\n return Math.ceil(this.getTimeLeft() / 1000);\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA6C,SAAAD,uBAAAE,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAE7C;AACA;AACA;AACA;AACe,MAAMG,UAAU,CAAC;EACtBC,KAAK,GAAyC,IAAI;EAClDC,SAAS,GAAG,CAAC;EAEdC,qBAAqB,GAAG,KAAK;;EAEpC;AACF;AACA;AACA;AACA;EACEC,WAAWA,CAACC,QAAgB,EAAEF,qBAAqB,GAAG,KAAK,EAAE;IAC3D,IAAI,CAACE,QAAQ,GAAGA,QAAQ;IACxB,IAAI,CAACF,qBAAqB,GAAGA,qBAAqB;EACpD;;EAEA;AACF;AACA;AACA;EACSG,KAAKA,CAACC,UAAsB,EAAQ;IACzCC,oBAAW,CAACC,IAAI,CAAC,0BAA0B,EAAE;MAC3CC,MAAM,EAAE,YAAY;MACpBC,MAAM,EAAE;IACV,CAAC,CAAC;IAEF,IAAI,IAAI,CAACV,KAAK,EAAE;MACd,IAAI,CAACW,KAAK,CAAC,CAAC;IACd;IAEA,IAAI,CAACV,SAAS,GAAGW,IAAI,CAACC,GAAG,CAAC,CAAC;IAE3B,IAAI,CAACb,KAAK,GAAGc,UAAU,CAAC,MAAM;MAC5BR,UAAU,CAAC,CAAC;MACZ,IAAI,CAACN,KAAK,GAAG,IAAI;IACnB,CAAC,EAAE,IAAI,CAACI,QAAQ,CAAC;EACnB;;EAEA;AACF;AACA;EACSO,KAAKA,CAAA,EAAS;IACnBJ,oBAAW,CAACC,IAAI,CAAC,0BAA0B,EAAE;MAC3CC,MAAM,EAAE,YAAY;MACpBC,MAAM,EAAE;IACV,CAAC,CAAC;IAEF,IAAI,IAAI,CAACV,KAAK,EAAE;MACde,YAAY,CAAC,IAAI,CAACf,KAAK,CAAC;MACxB,IAAI,CAACA,KAAK,GAAG,IAAI;MACjB,IAAI,CAACC,SAAS,GAAG,CAAC;IACpB;EACF;;EAEA;AACF;AACA;AACA;EACSe,WAAWA,CAAA,EAAW;IAC3B,MAAMC,OAAO,GAAGL,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG,IAAI,CAACZ,SAAS;IAE3C,OAAOiB,IAAI,CAACC,GAAG,CAAC,CAAC,EAAE,IAAI,CAACf,QAAQ,GAAGa,OAAO,CAAC;EAC7C;;EAEA;AACF;AACA;AACA;EACSG,SAASA,CAAA,EAAY;IAC1B,OAAO,IAAI,CAACpB,KAAK,KAAK,IAAI;EAC5B;;EAEA;AACF;AACA;AACA;EACSqB,kBAAkBA,CAAA,EAAW;IAClC,OAAOH,IAAI,CAACI,IAAI,CAAC,IAAI,CAACN,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC;EAC7C;AACF;AAACO,OAAA,CAAAzB,OAAA,GAAAC,UAAA"}
@@ -0,0 +1,369 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _events = _interopRequireDefault(require("events"));
8
+ var _calling = require("@webex/calling");
9
+ var _types = require("./types");
10
+ var _constants = require("../../constants");
11
+ var _constants2 = require("./constants");
12
+ var _types2 = require("../config/types");
13
+ var _types3 = require("../../types");
14
+ var _loggerProxy = _interopRequireDefault(require("../../logger-proxy"));
15
+ var _ = _interopRequireDefault(require("."));
16
+ var _MetricsManager = _interopRequireDefault(require("../../metrics/MetricsManager"));
17
+ var _constants3 = require("../../metrics/constants");
18
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
+ /** @internal */
20
+ class TaskManager extends _events.default {
21
+ /**
22
+ * Collection of tasks indexed by TaskId
23
+ * @type {Record<TaskId, ITask>}
24
+ * @private
25
+ */
26
+
27
+ /**
28
+ * @param contact - Routing Contact layer. Talks to AQMReq layer to convert events to promises
29
+ * @param webCallingService - Webrtc Service Layer
30
+ * @param webSocketManager - Websocket Manager to maintain websocket connection and keepalives
31
+ */
32
+ constructor(contact, webCallingService, webSocketManager) {
33
+ super();
34
+ this.contact = contact;
35
+ this.taskCollection = {};
36
+ this.webCallingService = webCallingService;
37
+ this.webSocketManager = webSocketManager;
38
+ this.metricsManager = _MetricsManager.default.getInstance();
39
+ this.registerTaskListeners();
40
+ this.registerIncomingCallEvent();
41
+ }
42
+ setWrapupData(wrapupData) {
43
+ this.wrapupData = wrapupData;
44
+ }
45
+ handleIncomingWebCall = call => {
46
+ const currentTask = Object.values(this.taskCollection).find(task => task.data.interaction.mediaType === 'telephony');
47
+ if (currentTask) {
48
+ this.webCallingService.mapCallToTask(call.getCallId(), currentTask.data.interactionId);
49
+ _loggerProxy.default.log(`Call mapped to task`, {
50
+ module: _constants.TASK_MANAGER_FILE,
51
+ method: _constants2.METHODS.HANDLE_INCOMING_WEB_CALL,
52
+ interactionId: currentTask.data.interactionId
53
+ });
54
+ this.emit(_types.TASK_EVENTS.TASK_INCOMING, currentTask);
55
+ }
56
+ this.call = call;
57
+ };
58
+ registerIncomingCallEvent() {
59
+ this.webCallingService.on(_calling.LINE_EVENTS.INCOMING_CALL, this.handleIncomingWebCall);
60
+ }
61
+ unregisterIncomingCallEvent() {
62
+ this.webCallingService.off(_calling.LINE_EVENTS.INCOMING_CALL, this.handleIncomingWebCall);
63
+ }
64
+ registerTaskListeners() {
65
+ this.webSocketManager.on('message', event => {
66
+ const payload = JSON.parse(event);
67
+ // Re-emit the task events to the task object
68
+ let task;
69
+ if (payload.data?.type) {
70
+ if (Object.values(_types2.CC_TASK_EVENTS).includes(payload.data.type)) {
71
+ task = this.taskCollection[payload.data.interactionId];
72
+ }
73
+ _loggerProxy.default.info(`Handling task event ${payload.data?.type}`, {
74
+ module: _constants.TASK_MANAGER_FILE,
75
+ method: _constants2.METHODS.REGISTER_TASK_LISTENERS,
76
+ interactionId: payload.data?.interactionId
77
+ });
78
+ switch (payload.data.type) {
79
+ case _types2.CC_EVENTS.AGENT_CONTACT:
80
+ // Case1 : Task is already present in taskCollection
81
+ if (this.taskCollection[payload.data.interactionId]) {
82
+ _loggerProxy.default.log(`Got AGENT_CONTACT: Task already exists in collection`, {
83
+ module: _constants.TASK_MANAGER_FILE,
84
+ method: _constants2.METHODS.REGISTER_TASK_LISTENERS,
85
+ interactionId: payload.data.interactionId
86
+ });
87
+ break;
88
+ } else if (!this.taskCollection[payload.data.interactionId]) {
89
+ // Case2 : Task is not present in taskCollection
90
+ _loggerProxy.default.log(`Got AGENT_CONTACT : Creating new task in taskManager`, {
91
+ module: _constants.TASK_MANAGER_FILE,
92
+ method: _constants2.METHODS.REGISTER_TASK_LISTENERS,
93
+ interactionId: payload.data.interactionId
94
+ });
95
+ task = new _.default(this.contact, this.webCallingService, {
96
+ ...payload.data,
97
+ wrapUpRequired: payload.data.interaction?.participants?.[payload.data.agentId]?.isWrapUp || false
98
+ }, this.wrapupData);
99
+ this.taskCollection[payload.data.interactionId] = task;
100
+ // Condition 1: The state is=new i.e it is a incoming task
101
+ if (payload.data.interaction.state === 'new') {
102
+ _loggerProxy.default.log(`Got AGENT_CONTACT for a task with state=new, sending TASK_INCOMING event`, {
103
+ module: _constants.TASK_MANAGER_FILE,
104
+ method: _constants2.METHODS.REGISTER_TASK_LISTENERS,
105
+ interactionId: payload.data.interactionId
106
+ });
107
+ this.emit(_types.TASK_EVENTS.TASK_INCOMING, task);
108
+ } else {
109
+ // Condition 2: The state is anything else i.e the task was connected
110
+ _loggerProxy.default.log(`Got AGENT_CONTACT for a task with state=${payload.data.interaction.state}, sending TASK_HYDRATE event`, {
111
+ module: _constants.TASK_MANAGER_FILE,
112
+ method: _constants2.METHODS.REGISTER_TASK_LISTENERS,
113
+ interactionId: payload.data.interactionId
114
+ });
115
+ this.emit(_types.TASK_EVENTS.TASK_HYDRATE, task);
116
+ }
117
+ }
118
+ break;
119
+ case _types2.CC_EVENTS.AGENT_CONTACT_RESERVED:
120
+ task = new _.default(this.contact, this.webCallingService, {
121
+ ...payload.data,
122
+ isConsulted: false
123
+ }, this.wrapupData); // Ensure isConsulted prop exists
124
+ this.taskCollection[payload.data.interactionId] = task;
125
+ if (this.webCallingService.loginOption !== _types3.LoginOption.BROWSER || task.data.interaction.mediaType !== _types.MEDIA_CHANNEL.TELEPHONY // for digital channels
126
+ ) {
127
+ this.emit(_types.TASK_EVENTS.TASK_INCOMING, task);
128
+ } else if (this.call) {
129
+ this.emit(_types.TASK_EVENTS.TASK_INCOMING, task);
130
+ }
131
+ break;
132
+ case _types2.CC_EVENTS.AGENT_OFFER_CONTACT:
133
+ // We don't have to emit any event here since this will be result of promise.
134
+ task = this.updateTaskData(task, payload.data);
135
+ _loggerProxy.default.log(`Agent offer contact received for task`, {
136
+ module: _constants.TASK_MANAGER_FILE,
137
+ method: _constants2.METHODS.REGISTER_TASK_LISTENERS,
138
+ interactionId: payload.data?.interactionId
139
+ });
140
+ this.emit(_types.TASK_EVENTS.TASK_OFFER_CONTACT, task);
141
+ break;
142
+ case _types2.CC_EVENTS.AGENT_OUTBOUND_FAILED:
143
+ // We don't have to emit any event here since this will be result of promise.
144
+ if (task.data) {
145
+ this.removeTaskFromCollection(task);
146
+ }
147
+ _loggerProxy.default.log(`Agent outbound failed for task`, {
148
+ module: _constants.TASK_MANAGER_FILE,
149
+ method: _constants2.METHODS.REGISTER_TASK_LISTENERS,
150
+ interactionId: payload.data?.interactionId
151
+ });
152
+ break;
153
+ case _types2.CC_EVENTS.AGENT_CONTACT_ASSIGNED:
154
+ task = this.updateTaskData(task, payload.data);
155
+ task.emit(_types.TASK_EVENTS.TASK_ASSIGNED, task);
156
+ break;
157
+ case _types2.CC_EVENTS.AGENT_CONTACT_UNASSIGNED:
158
+ task = this.updateTaskData(task, {
159
+ ...payload.data,
160
+ wrapUpRequired: true
161
+ });
162
+ task.emit(_types.TASK_EVENTS.TASK_END, task);
163
+ break;
164
+ case _types2.CC_EVENTS.AGENT_CONTACT_OFFER_RONA:
165
+ case _types2.CC_EVENTS.AGENT_CONTACT_ASSIGN_FAILED:
166
+ case _types2.CC_EVENTS.AGENT_INVITE_FAILED:
167
+ {
168
+ task = this.updateTaskData(task, payload.data);
169
+ const eventTypeToMetricMap = {
170
+ [_types2.CC_EVENTS.AGENT_CONTACT_ASSIGN_FAILED]: 'AGENT_CONTACT_ASSIGN_FAILED',
171
+ [_types2.CC_EVENTS.AGENT_INVITE_FAILED]: 'AGENT_INVITE_FAILED'
172
+ };
173
+ const metricEventName = eventTypeToMetricMap[payload.data.type] || 'AGENT_RONA';
174
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES[metricEventName], {
175
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(payload.data),
176
+ taskId: payload.data.interactionId,
177
+ reason: payload.data.reason
178
+ }, ['behavioral', 'operational']);
179
+ this.handleTaskCleanup(task);
180
+ task.emit(_types.TASK_EVENTS.TASK_REJECT, payload.data.reason);
181
+ break;
182
+ }
183
+ case _types2.CC_EVENTS.CONTACT_ENDED:
184
+ task = this.updateTaskData(task, {
185
+ ...payload.data,
186
+ wrapUpRequired: payload.data.interaction.state !== 'new'
187
+ });
188
+ this.handleTaskCleanup(task);
189
+ task.emit(_types.TASK_EVENTS.TASK_END, task);
190
+ break;
191
+ case _types2.CC_EVENTS.AGENT_CONTACT_HELD:
192
+ // As soon as the main interaction is held, we need to emit TASK_HOLD
193
+ task = this.updateTaskData(task, payload.data);
194
+ task.emit(_types.TASK_EVENTS.TASK_HOLD, task);
195
+ break;
196
+ case _types2.CC_EVENTS.AGENT_CONTACT_UNHELD:
197
+ // As soon as the main interaction is unheld, we need to emit TASK_RESUME
198
+ task = this.updateTaskData(task, payload.data);
199
+ task.emit(_types.TASK_EVENTS.TASK_RESUME, task);
200
+ break;
201
+ case _types2.CC_EVENTS.AGENT_VTEAM_TRANSFERRED:
202
+ task = this.updateTaskData(task, {
203
+ ...payload.data,
204
+ wrapUpRequired: true
205
+ });
206
+ task.emit(_types.TASK_EVENTS.TASK_END, task);
207
+ break;
208
+ case _types2.CC_EVENTS.AGENT_CTQ_CANCEL_FAILED:
209
+ task = this.updateTaskData(task, payload.data);
210
+ task.emit(_types.TASK_EVENTS.TASK_CONSULT_QUEUE_FAILED, task);
211
+ break;
212
+ case _types2.CC_EVENTS.AGENT_CONSULT_CREATED:
213
+ // Received when self agent initiates a consult
214
+ task = this.updateTaskData(task, {
215
+ ...payload.data,
216
+ isConsulted: false // This ensures that the task consult status is always reset
217
+ });
218
+
219
+ task.emit(_types.TASK_EVENTS.TASK_CONSULT_CREATED, task);
220
+ break;
221
+ case _types2.CC_EVENTS.AGENT_OFFER_CONSULT:
222
+ // Received when other agent sends us a consult offer
223
+ task = this.updateTaskData(task, {
224
+ ...payload.data,
225
+ isConsulted: true // This ensures that the task is marked as us being requested for a consult
226
+ });
227
+
228
+ task.emit(_types.TASK_EVENTS.TASK_OFFER_CONSULT, task);
229
+ break;
230
+ case _types2.CC_EVENTS.AGENT_CONSULTING:
231
+ // Received when agent is in an active consult state
232
+ task = this.updateTaskData(task, payload.data);
233
+ if (task.data.isConsulted) {
234
+ // Fire only if you are the agent who received the consult request
235
+ task.emit(_types.TASK_EVENTS.TASK_CONSULT_ACCEPTED, task);
236
+ } else {
237
+ // Fire only if you are the agent who initiated the consult
238
+ task.emit(_types.TASK_EVENTS.TASK_CONSULTING, task);
239
+ }
240
+ break;
241
+ case _types2.CC_EVENTS.AGENT_CONSULT_FAILED:
242
+ // This can only be received by the agent who initiated the consult.
243
+ // We need not emit any event here since this will be result of promise
244
+ task = this.updateTaskData(task, payload.data);
245
+ break;
246
+ case _types2.CC_EVENTS.AGENT_CONSULT_ENDED:
247
+ task = this.updateTaskData(task, payload.data);
248
+ if (task.data.isConsulted) {
249
+ // This will be the end state of the task as soon as we end the consult in case of
250
+ // us being offered a consult
251
+ this.removeTaskFromCollection(task);
252
+ }
253
+ task.emit(_types.TASK_EVENTS.TASK_CONSULT_END, task);
254
+ break;
255
+ case _types2.CC_EVENTS.AGENT_CTQ_CANCELLED:
256
+ // This event is received when the consult using queue is cancelled using API
257
+ task = this.updateTaskData(task, payload.data);
258
+ task.emit(_types.TASK_EVENTS.TASK_CONSULT_QUEUE_CANCELLED, task);
259
+ break;
260
+ case _types2.CC_EVENTS.AGENT_WRAPUP:
261
+ task = this.updateTaskData(task, {
262
+ ...payload.data,
263
+ wrapUpRequired: true
264
+ });
265
+ task.emit(_types.TASK_EVENTS.TASK_END, task);
266
+ break;
267
+ case _types2.CC_EVENTS.AGENT_WRAPPEDUP:
268
+ task.cancelAutoWrapupTimer();
269
+ this.removeTaskFromCollection(task);
270
+ task.emit(_types.TASK_EVENTS.TASK_WRAPPEDUP, task);
271
+ break;
272
+ case _types2.CC_EVENTS.CONTACT_RECORDING_PAUSED:
273
+ task = this.updateTaskData(task, payload.data);
274
+ task.emit(_types.TASK_EVENTS.TASK_RECORDING_PAUSED, task);
275
+ break;
276
+ case _types2.CC_EVENTS.CONTACT_RECORDING_PAUSE_FAILED:
277
+ task = this.updateTaskData(task, payload.data);
278
+ task.emit(_types.TASK_EVENTS.TASK_RECORDING_PAUSE_FAILED, task);
279
+ break;
280
+ case _types2.CC_EVENTS.CONTACT_RECORDING_RESUMED:
281
+ task = this.updateTaskData(task, payload.data);
282
+ task.emit(_types.TASK_EVENTS.TASK_RECORDING_RESUMED, task);
283
+ break;
284
+ case _types2.CC_EVENTS.CONTACT_RECORDING_RESUME_FAILED:
285
+ task = this.updateTaskData(task, payload.data);
286
+ task.emit(_types.TASK_EVENTS.TASK_RECORDING_RESUME_FAILED, task);
287
+ break;
288
+ default:
289
+ break;
290
+ }
291
+ if (task) {
292
+ task.emit(payload.data.type, payload.data);
293
+ }
294
+ }
295
+ });
296
+ }
297
+ updateTaskData(task, taskData) {
298
+ if (!task) {
299
+ return undefined;
300
+ }
301
+ if (!taskData?.interactionId) {
302
+ _loggerProxy.default.warn('Received task update with missing interactionId', {
303
+ module: _constants.TASK_MANAGER_FILE,
304
+ method: _constants2.METHODS.UPDATE_TASK_DATA
305
+ });
306
+ }
307
+ try {
308
+ const currentTask = task.updateTaskData(taskData);
309
+ this.taskCollection[taskData.interactionId] = currentTask;
310
+ return currentTask;
311
+ } catch (error) {
312
+ _loggerProxy.default.error(`Failed to update task`, {
313
+ module: _constants.TASK_MANAGER_FILE,
314
+ method: _constants2.METHODS.UPDATE_TASK_DATA,
315
+ interactionId: taskData.interactionId
316
+ });
317
+ return task;
318
+ }
319
+ }
320
+ removeTaskFromCollection(task) {
321
+ if (task?.data?.interactionId) {
322
+ delete this.taskCollection[task.data.interactionId];
323
+ _loggerProxy.default.info(`Task removed from collection`, {
324
+ module: _constants.TASK_MANAGER_FILE,
325
+ method: _constants2.METHODS.REMOVE_TASK_FROM_COLLECTION,
326
+ interactionId: task.data.interactionId
327
+ });
328
+ }
329
+ }
330
+ handleTaskCleanup(task) {
331
+ if (this.webCallingService.loginOption === _types3.LoginOption.BROWSER && task.data.interaction.mediaType === 'telephony') {
332
+ task.unregisterWebCallListeners();
333
+ this.webCallingService.cleanUpCall();
334
+ }
335
+ if (task.data.interaction.state === 'new') {
336
+ // Only remove tasks in 'new' state immediately. For other states,
337
+ // retain tasks until they complete wrap-up, unless the task disconnected before being answered.
338
+ this.removeTaskFromCollection(task);
339
+ }
340
+ }
341
+
342
+ /**
343
+ * @param taskId - Unique identifier for each task
344
+ */
345
+ getTask = taskId => {
346
+ return this.taskCollection[taskId];
347
+ };
348
+
349
+ /**
350
+ * @param taskId - Unique identifier for each task
351
+ */
352
+ getAllTasks = () => {
353
+ return this.taskCollection;
354
+ };
355
+
356
+ /**
357
+ * @param contact - Routing Contact layer. Talks to AQMReq layer to convert events to promises
358
+ * @param webCallingService - Webrtc Service Layer
359
+ * @param webSocketManager - Websocket Manager to maintain websocket connection and keepalives
360
+ */
361
+ static getTaskManager = (contact, webCallingService, webSocketManager) => {
362
+ if (!this.taskManager) {
363
+ this.taskManager = new TaskManager(contact, webCallingService, webSocketManager);
364
+ }
365
+ return this.taskManager;
366
+ };
367
+ }
368
+ exports.default = TaskManager;
369
+ //# sourceMappingURL=TaskManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_events","_interopRequireDefault","require","_calling","_types","_constants","_constants2","_types2","_types3","_loggerProxy","_","_MetricsManager","_constants3","obj","__esModule","default","TaskManager","EventEmitter","constructor","contact","webCallingService","webSocketManager","taskCollection","metricsManager","MetricsManager","getInstance","registerTaskListeners","registerIncomingCallEvent","setWrapupData","wrapupData","handleIncomingWebCall","call","currentTask","Object","values","find","task","data","interaction","mediaType","mapCallToTask","getCallId","interactionId","LoggerProxy","log","module","TASK_MANAGER_FILE","method","METHODS","HANDLE_INCOMING_WEB_CALL","emit","TASK_EVENTS","TASK_INCOMING","on","LINE_EVENTS","INCOMING_CALL","unregisterIncomingCallEvent","off","event","payload","JSON","parse","type","CC_TASK_EVENTS","includes","info","REGISTER_TASK_LISTENERS","CC_EVENTS","AGENT_CONTACT","Task","wrapUpRequired","participants","agentId","isWrapUp","state","TASK_HYDRATE","AGENT_CONTACT_RESERVED","isConsulted","loginOption","LoginOption","BROWSER","MEDIA_CHANNEL","TELEPHONY","AGENT_OFFER_CONTACT","updateTaskData","TASK_OFFER_CONTACT","AGENT_OUTBOUND_FAILED","removeTaskFromCollection","AGENT_CONTACT_ASSIGNED","TASK_ASSIGNED","AGENT_CONTACT_UNASSIGNED","TASK_END","AGENT_CONTACT_OFFER_RONA","AGENT_CONTACT_ASSIGN_FAILED","AGENT_INVITE_FAILED","eventTypeToMetricMap","metricEventName","trackEvent","METRIC_EVENT_NAMES","getCommonTrackingFieldForAQMResponse","taskId","reason","handleTaskCleanup","TASK_REJECT","CONTACT_ENDED","AGENT_CONTACT_HELD","TASK_HOLD","AGENT_CONTACT_UNHELD","TASK_RESUME","AGENT_VTEAM_TRANSFERRED","AGENT_CTQ_CANCEL_FAILED","TASK_CONSULT_QUEUE_FAILED","AGENT_CONSULT_CREATED","TASK_CONSULT_CREATED","AGENT_OFFER_CONSULT","TASK_OFFER_CONSULT","AGENT_CONSULTING","TASK_CONSULT_ACCEPTED","TASK_CONSULTING","AGENT_CONSULT_FAILED","AGENT_CONSULT_ENDED","TASK_CONSULT_END","AGENT_CTQ_CANCELLED","TASK_CONSULT_QUEUE_CANCELLED","AGENT_WRAPUP","AGENT_WRAPPEDUP","cancelAutoWrapupTimer","TASK_WRAPPEDUP","CONTACT_RECORDING_PAUSED","TASK_RECORDING_PAUSED","CONTACT_RECORDING_PAUSE_FAILED","TASK_RECORDING_PAUSE_FAILED","CONTACT_RECORDING_RESUMED","TASK_RECORDING_RESUMED","CONTACT_RECORDING_RESUME_FAILED","TASK_RECORDING_RESUME_FAILED","taskData","undefined","warn","UPDATE_TASK_DATA","error","REMOVE_TASK_FROM_COLLECTION","unregisterWebCallListeners","cleanUpCall","getTask","getAllTasks","getTaskManager","taskManager","exports"],"sources":["TaskManager.ts"],"sourcesContent":["import EventEmitter from 'events';\nimport {ICall, LINE_EVENTS} from '@webex/calling';\nimport {WebSocketManager} from '../core/websocket/WebSocketManager';\nimport routingContact from './contact';\nimport WebCallingService from '../WebCallingService';\nimport {ITask, MEDIA_CHANNEL, TASK_EVENTS, TaskData, TaskId} from './types';\nimport {TASK_MANAGER_FILE} from '../../constants';\nimport {METHODS} from './constants';\nimport {CC_EVENTS, CC_TASK_EVENTS, WrapupData} from '../config/types';\nimport {LoginOption} from '../../types';\nimport LoggerProxy from '../../logger-proxy';\nimport Task from '.';\nimport MetricsManager from '../../metrics/MetricsManager';\nimport {METRIC_EVENT_NAMES} from '../../metrics/constants';\n\n/** @internal */\nexport default class TaskManager extends EventEmitter {\n private call: ICall;\n private contact: ReturnType<typeof routingContact>;\n /**\n * Collection of tasks indexed by TaskId\n * @type {Record<TaskId, ITask>}\n * @private\n */\n private taskCollection: Record<TaskId, ITask>;\n private webCallingService: WebCallingService;\n private webSocketManager: WebSocketManager;\n private metricsManager: MetricsManager;\n private static taskManager;\n private wrapupData: WrapupData;\n /**\n * @param contact - Routing Contact layer. Talks to AQMReq layer to convert events to promises\n * @param webCallingService - Webrtc Service Layer\n * @param webSocketManager - Websocket Manager to maintain websocket connection and keepalives\n */\n constructor(\n contact: ReturnType<typeof routingContact>,\n webCallingService: WebCallingService,\n webSocketManager: WebSocketManager\n ) {\n super();\n this.contact = contact;\n this.taskCollection = {};\n this.webCallingService = webCallingService;\n this.webSocketManager = webSocketManager;\n this.metricsManager = MetricsManager.getInstance();\n this.registerTaskListeners();\n this.registerIncomingCallEvent();\n }\n\n public setWrapupData(wrapupData: WrapupData) {\n this.wrapupData = wrapupData;\n }\n\n private handleIncomingWebCall = (call: ICall) => {\n const currentTask = Object.values(this.taskCollection).find(\n (task) => task.data.interaction.mediaType === 'telephony'\n );\n\n if (currentTask) {\n this.webCallingService.mapCallToTask(call.getCallId(), currentTask.data.interactionId);\n LoggerProxy.log(`Call mapped to task`, {\n module: TASK_MANAGER_FILE,\n method: METHODS.HANDLE_INCOMING_WEB_CALL,\n interactionId: currentTask.data.interactionId,\n });\n this.emit(TASK_EVENTS.TASK_INCOMING, currentTask);\n }\n this.call = call;\n };\n\n public registerIncomingCallEvent() {\n this.webCallingService.on(LINE_EVENTS.INCOMING_CALL, this.handleIncomingWebCall);\n }\n\n public unregisterIncomingCallEvent() {\n this.webCallingService.off(LINE_EVENTS.INCOMING_CALL, this.handleIncomingWebCall);\n }\n\n private registerTaskListeners() {\n this.webSocketManager.on('message', (event) => {\n const payload = JSON.parse(event);\n // Re-emit the task events to the task object\n let task: ITask;\n if (payload.data?.type) {\n if (Object.values(CC_TASK_EVENTS).includes(payload.data.type)) {\n task = this.taskCollection[payload.data.interactionId];\n }\n LoggerProxy.info(`Handling task event ${payload.data?.type}`, {\n module: TASK_MANAGER_FILE,\n method: METHODS.REGISTER_TASK_LISTENERS,\n interactionId: payload.data?.interactionId,\n });\n switch (payload.data.type) {\n case CC_EVENTS.AGENT_CONTACT:\n // Case1 : Task is already present in taskCollection\n if (this.taskCollection[payload.data.interactionId]) {\n LoggerProxy.log(`Got AGENT_CONTACT: Task already exists in collection`, {\n module: TASK_MANAGER_FILE,\n method: METHODS.REGISTER_TASK_LISTENERS,\n interactionId: payload.data.interactionId,\n });\n break;\n } else if (!this.taskCollection[payload.data.interactionId]) {\n // Case2 : Task is not present in taskCollection\n LoggerProxy.log(`Got AGENT_CONTACT : Creating new task in taskManager`, {\n module: TASK_MANAGER_FILE,\n method: METHODS.REGISTER_TASK_LISTENERS,\n interactionId: payload.data.interactionId,\n });\n task = new Task(\n this.contact,\n this.webCallingService,\n {\n ...payload.data,\n wrapUpRequired:\n payload.data.interaction?.participants?.[payload.data.agentId]?.isWrapUp ||\n false,\n },\n this.wrapupData\n );\n this.taskCollection[payload.data.interactionId] = task;\n // Condition 1: The state is=new i.e it is a incoming task\n if (payload.data.interaction.state === 'new') {\n LoggerProxy.log(\n `Got AGENT_CONTACT for a task with state=new, sending TASK_INCOMING event`,\n {\n module: TASK_MANAGER_FILE,\n method: METHODS.REGISTER_TASK_LISTENERS,\n interactionId: payload.data.interactionId,\n }\n );\n this.emit(TASK_EVENTS.TASK_INCOMING, task);\n } else {\n // Condition 2: The state is anything else i.e the task was connected\n LoggerProxy.log(\n `Got AGENT_CONTACT for a task with state=${payload.data.interaction.state}, sending TASK_HYDRATE event`,\n {\n module: TASK_MANAGER_FILE,\n method: METHODS.REGISTER_TASK_LISTENERS,\n interactionId: payload.data.interactionId,\n }\n );\n this.emit(TASK_EVENTS.TASK_HYDRATE, task);\n }\n }\n break;\n case CC_EVENTS.AGENT_CONTACT_RESERVED:\n task = new Task(\n this.contact,\n this.webCallingService,\n {\n ...payload.data,\n isConsulted: false,\n },\n this.wrapupData\n ); // Ensure isConsulted prop exists\n this.taskCollection[payload.data.interactionId] = task;\n if (\n this.webCallingService.loginOption !== LoginOption.BROWSER ||\n task.data.interaction.mediaType !== MEDIA_CHANNEL.TELEPHONY // for digital channels\n ) {\n this.emit(TASK_EVENTS.TASK_INCOMING, task);\n } else if (this.call) {\n this.emit(TASK_EVENTS.TASK_INCOMING, task);\n }\n break;\n case CC_EVENTS.AGENT_OFFER_CONTACT:\n // We don't have to emit any event here since this will be result of promise.\n task = this.updateTaskData(task, payload.data);\n LoggerProxy.log(`Agent offer contact received for task`, {\n module: TASK_MANAGER_FILE,\n method: METHODS.REGISTER_TASK_LISTENERS,\n interactionId: payload.data?.interactionId,\n });\n this.emit(TASK_EVENTS.TASK_OFFER_CONTACT, task);\n break;\n case CC_EVENTS.AGENT_OUTBOUND_FAILED:\n // We don't have to emit any event here since this will be result of promise.\n if (task.data) {\n this.removeTaskFromCollection(task);\n }\n LoggerProxy.log(`Agent outbound failed for task`, {\n module: TASK_MANAGER_FILE,\n method: METHODS.REGISTER_TASK_LISTENERS,\n interactionId: payload.data?.interactionId,\n });\n break;\n case CC_EVENTS.AGENT_CONTACT_ASSIGNED:\n task = this.updateTaskData(task, payload.data);\n task.emit(TASK_EVENTS.TASK_ASSIGNED, task);\n break;\n case CC_EVENTS.AGENT_CONTACT_UNASSIGNED:\n task = this.updateTaskData(task, {\n ...payload.data,\n wrapUpRequired: true,\n });\n task.emit(TASK_EVENTS.TASK_END, task);\n break;\n case CC_EVENTS.AGENT_CONTACT_OFFER_RONA:\n case CC_EVENTS.AGENT_CONTACT_ASSIGN_FAILED:\n case CC_EVENTS.AGENT_INVITE_FAILED: {\n task = this.updateTaskData(task, payload.data);\n\n const eventTypeToMetricMap: Record<string, keyof typeof METRIC_EVENT_NAMES> = {\n [CC_EVENTS.AGENT_CONTACT_ASSIGN_FAILED]: 'AGENT_CONTACT_ASSIGN_FAILED',\n [CC_EVENTS.AGENT_INVITE_FAILED]: 'AGENT_INVITE_FAILED',\n };\n const metricEventName: keyof typeof METRIC_EVENT_NAMES =\n eventTypeToMetricMap[payload.data.type] || 'AGENT_RONA';\n\n this.metricsManager.trackEvent(\n METRIC_EVENT_NAMES[metricEventName],\n {\n ...MetricsManager.getCommonTrackingFieldForAQMResponse(payload.data),\n taskId: payload.data.interactionId,\n reason: payload.data.reason,\n },\n ['behavioral', 'operational']\n );\n this.handleTaskCleanup(task);\n task.emit(TASK_EVENTS.TASK_REJECT, payload.data.reason);\n break;\n }\n case CC_EVENTS.CONTACT_ENDED:\n task = this.updateTaskData(task, {\n ...payload.data,\n wrapUpRequired: payload.data.interaction.state !== 'new',\n });\n this.handleTaskCleanup(task);\n task.emit(TASK_EVENTS.TASK_END, task);\n\n break;\n case CC_EVENTS.AGENT_CONTACT_HELD:\n // As soon as the main interaction is held, we need to emit TASK_HOLD\n task = this.updateTaskData(task, payload.data);\n task.emit(TASK_EVENTS.TASK_HOLD, task);\n break;\n case CC_EVENTS.AGENT_CONTACT_UNHELD:\n // As soon as the main interaction is unheld, we need to emit TASK_RESUME\n task = this.updateTaskData(task, payload.data);\n task.emit(TASK_EVENTS.TASK_RESUME, task);\n break;\n case CC_EVENTS.AGENT_VTEAM_TRANSFERRED:\n task = this.updateTaskData(task, {\n ...payload.data,\n wrapUpRequired: true,\n });\n task.emit(TASK_EVENTS.TASK_END, task);\n break;\n case CC_EVENTS.AGENT_CTQ_CANCEL_FAILED:\n task = this.updateTaskData(task, payload.data);\n task.emit(TASK_EVENTS.TASK_CONSULT_QUEUE_FAILED, task);\n break;\n case CC_EVENTS.AGENT_CONSULT_CREATED:\n // Received when self agent initiates a consult\n task = this.updateTaskData(task, {\n ...payload.data,\n isConsulted: false, // This ensures that the task consult status is always reset\n });\n task.emit(TASK_EVENTS.TASK_CONSULT_CREATED, task);\n break;\n case CC_EVENTS.AGENT_OFFER_CONSULT:\n // Received when other agent sends us a consult offer\n task = this.updateTaskData(task, {\n ...payload.data,\n isConsulted: true, // This ensures that the task is marked as us being requested for a consult\n });\n task.emit(TASK_EVENTS.TASK_OFFER_CONSULT, task);\n break;\n case CC_EVENTS.AGENT_CONSULTING:\n // Received when agent is in an active consult state\n task = this.updateTaskData(task, payload.data);\n if (task.data.isConsulted) {\n // Fire only if you are the agent who received the consult request\n task.emit(TASK_EVENTS.TASK_CONSULT_ACCEPTED, task);\n } else {\n // Fire only if you are the agent who initiated the consult\n task.emit(TASK_EVENTS.TASK_CONSULTING, task);\n }\n break;\n case CC_EVENTS.AGENT_CONSULT_FAILED:\n // This can only be received by the agent who initiated the consult.\n // We need not emit any event here since this will be result of promise\n task = this.updateTaskData(task, payload.data);\n break;\n case CC_EVENTS.AGENT_CONSULT_ENDED:\n task = this.updateTaskData(task, payload.data);\n if (task.data.isConsulted) {\n // This will be the end state of the task as soon as we end the consult in case of\n // us being offered a consult\n this.removeTaskFromCollection(task);\n }\n task.emit(TASK_EVENTS.TASK_CONSULT_END, task);\n break;\n case CC_EVENTS.AGENT_CTQ_CANCELLED:\n // This event is received when the consult using queue is cancelled using API\n task = this.updateTaskData(task, payload.data);\n task.emit(TASK_EVENTS.TASK_CONSULT_QUEUE_CANCELLED, task);\n break;\n case CC_EVENTS.AGENT_WRAPUP:\n task = this.updateTaskData(task, {...payload.data, wrapUpRequired: true});\n task.emit(TASK_EVENTS.TASK_END, task);\n break;\n case CC_EVENTS.AGENT_WRAPPEDUP:\n task.cancelAutoWrapupTimer();\n this.removeTaskFromCollection(task);\n task.emit(TASK_EVENTS.TASK_WRAPPEDUP, task);\n break;\n case CC_EVENTS.CONTACT_RECORDING_PAUSED:\n task = this.updateTaskData(task, payload.data);\n task.emit(TASK_EVENTS.TASK_RECORDING_PAUSED, task);\n break;\n case CC_EVENTS.CONTACT_RECORDING_PAUSE_FAILED:\n task = this.updateTaskData(task, payload.data);\n task.emit(TASK_EVENTS.TASK_RECORDING_PAUSE_FAILED, task);\n break;\n case CC_EVENTS.CONTACT_RECORDING_RESUMED:\n task = this.updateTaskData(task, payload.data);\n task.emit(TASK_EVENTS.TASK_RECORDING_RESUMED, task);\n break;\n case CC_EVENTS.CONTACT_RECORDING_RESUME_FAILED:\n task = this.updateTaskData(task, payload.data);\n task.emit(TASK_EVENTS.TASK_RECORDING_RESUME_FAILED, task);\n break;\n default:\n break;\n }\n if (task) {\n task.emit(payload.data.type, payload.data);\n }\n }\n });\n }\n\n private updateTaskData(task: ITask, taskData: TaskData): ITask {\n if (!task) {\n return undefined;\n }\n\n if (!taskData?.interactionId) {\n LoggerProxy.warn('Received task update with missing interactionId', {\n module: TASK_MANAGER_FILE,\n method: METHODS.UPDATE_TASK_DATA,\n });\n }\n\n try {\n const currentTask = task.updateTaskData(taskData);\n this.taskCollection[taskData.interactionId] = currentTask;\n\n return currentTask;\n } catch (error) {\n LoggerProxy.error(`Failed to update task`, {\n module: TASK_MANAGER_FILE,\n method: METHODS.UPDATE_TASK_DATA,\n interactionId: taskData.interactionId,\n });\n\n return task;\n }\n }\n\n private removeTaskFromCollection(task: ITask) {\n if (task?.data?.interactionId) {\n delete this.taskCollection[task.data.interactionId];\n LoggerProxy.info(`Task removed from collection`, {\n module: TASK_MANAGER_FILE,\n method: METHODS.REMOVE_TASK_FROM_COLLECTION,\n interactionId: task.data.interactionId,\n });\n }\n }\n\n private handleTaskCleanup(task: ITask) {\n if (\n this.webCallingService.loginOption === LoginOption.BROWSER &&\n task.data.interaction.mediaType === 'telephony'\n ) {\n task.unregisterWebCallListeners();\n this.webCallingService.cleanUpCall();\n }\n if (task.data.interaction.state === 'new') {\n // Only remove tasks in 'new' state immediately. For other states,\n // retain tasks until they complete wrap-up, unless the task disconnected before being answered.\n this.removeTaskFromCollection(task);\n }\n }\n\n /**\n * @param taskId - Unique identifier for each task\n */\n public getTask = (taskId: string) => {\n return this.taskCollection[taskId];\n };\n\n /**\n * @param taskId - Unique identifier for each task\n */\n public getAllTasks = (): Record<TaskId, ITask> => {\n return this.taskCollection;\n };\n\n /**\n * @param contact - Routing Contact layer. Talks to AQMReq layer to convert events to promises\n * @param webCallingService - Webrtc Service Layer\n * @param webSocketManager - Websocket Manager to maintain websocket connection and keepalives\n */\n public static getTaskManager = (\n contact: ReturnType<typeof routingContact>,\n webCallingService: WebCallingService,\n webSocketManager: WebSocketManager\n ): TaskManager => {\n if (!this.taskManager) {\n this.taskManager = new TaskManager(contact, webCallingService, webSocketManager);\n }\n\n return this.taskManager;\n };\n}\n"],"mappings":"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"}