@memberjunction/ng-conversations 5.40.2 → 5.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/README.md +57 -0
  2. package/dist/__tests__/channel-optional-surface.test.d.ts +2 -0
  3. package/dist/__tests__/channel-optional-surface.test.d.ts.map +1 -0
  4. package/dist/__tests__/channel-optional-surface.test.js +53 -0
  5. package/dist/__tests__/channel-optional-surface.test.js.map +1 -0
  6. package/dist/__tests__/chat-events.test.d.ts +14 -0
  7. package/dist/__tests__/chat-events.test.d.ts.map +1 -0
  8. package/dist/__tests__/chat-events.test.js +109 -0
  9. package/dist/__tests__/chat-events.test.js.map +1 -0
  10. package/dist/__tests__/conversation-naming.test.d.ts +2 -0
  11. package/dist/__tests__/conversation-naming.test.d.ts.map +1 -0
  12. package/dist/__tests__/conversation-naming.test.js +110 -0
  13. package/dist/__tests__/conversation-naming.test.js.map +1 -0
  14. package/dist/__tests__/delegation-result-parser.test.d.ts +2 -0
  15. package/dist/__tests__/delegation-result-parser.test.d.ts.map +1 -0
  16. package/dist/__tests__/delegation-result-parser.test.js +107 -0
  17. package/dist/__tests__/delegation-result-parser.test.js.map +1 -0
  18. package/dist/__tests__/event-wiring.test.d.ts +15 -0
  19. package/dist/__tests__/event-wiring.test.d.ts.map +1 -0
  20. package/dist/__tests__/event-wiring.test.js +100 -0
  21. package/dist/__tests__/event-wiring.test.js.map +1 -0
  22. package/dist/__tests__/narration-template.test.d.ts +2 -0
  23. package/dist/__tests__/narration-template.test.d.ts.map +1 -0
  24. package/dist/__tests__/narration-template.test.js +76 -0
  25. package/dist/__tests__/narration-template.test.js.map +1 -0
  26. package/dist/__tests__/realtime-agent-picker-models.test.d.ts +2 -0
  27. package/dist/__tests__/realtime-agent-picker-models.test.d.ts.map +1 -0
  28. package/dist/__tests__/realtime-agent-picker-models.test.js +49 -0
  29. package/dist/__tests__/realtime-agent-picker-models.test.js.map +1 -0
  30. package/dist/__tests__/realtime-audio-visuals.test.d.ts +2 -0
  31. package/dist/__tests__/realtime-audio-visuals.test.d.ts.map +1 -0
  32. package/dist/__tests__/realtime-audio-visuals.test.js +123 -0
  33. package/dist/__tests__/realtime-audio-visuals.test.js.map +1 -0
  34. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts +2 -0
  35. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts.map +1 -0
  36. package/dist/__tests__/realtime-delegation-card-cancel.test.js +48 -0
  37. package/dist/__tests__/realtime-delegation-card-cancel.test.js.map +1 -0
  38. package/dist/__tests__/realtime-disclosure.test.d.ts +2 -0
  39. package/dist/__tests__/realtime-disclosure.test.d.ts.map +1 -0
  40. package/dist/__tests__/realtime-disclosure.test.js +164 -0
  41. package/dist/__tests__/realtime-disclosure.test.js.map +1 -0
  42. package/dist/__tests__/realtime-pairing.test.d.ts +2 -0
  43. package/dist/__tests__/realtime-pairing.test.d.ts.map +1 -0
  44. package/dist/__tests__/realtime-pairing.test.js +207 -0
  45. package/dist/__tests__/realtime-pairing.test.js.map +1 -0
  46. package/dist/__tests__/realtime-review-lifecycle.test.d.ts +2 -0
  47. package/dist/__tests__/realtime-review-lifecycle.test.d.ts.map +1 -0
  48. package/dist/__tests__/realtime-review-lifecycle.test.js +154 -0
  49. package/dist/__tests__/realtime-review-lifecycle.test.js.map +1 -0
  50. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts +2 -0
  51. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts.map +1 -0
  52. package/dist/__tests__/realtime-session-cancel-usage.test.js +230 -0
  53. package/dist/__tests__/realtime-session-cancel-usage.test.js.map +1 -0
  54. package/dist/__tests__/realtime-session-channels.test.d.ts +2 -0
  55. package/dist/__tests__/realtime-session-channels.test.d.ts.map +1 -0
  56. package/dist/__tests__/realtime-session-channels.test.js +252 -0
  57. package/dist/__tests__/realtime-session-channels.test.js.map +1 -0
  58. package/dist/__tests__/realtime-session-client-tools.test.d.ts +2 -0
  59. package/dist/__tests__/realtime-session-client-tools.test.d.ts.map +1 -0
  60. package/dist/__tests__/realtime-session-client-tools.test.js +103 -0
  61. package/dist/__tests__/realtime-session-client-tools.test.js.map +1 -0
  62. package/dist/__tests__/realtime-session-minimized.test.d.ts +2 -0
  63. package/dist/__tests__/realtime-session-minimized.test.d.ts.map +1 -0
  64. package/dist/__tests__/realtime-session-minimized.test.js +32 -0
  65. package/dist/__tests__/realtime-session-minimized.test.js.map +1 -0
  66. package/dist/__tests__/realtime-session-mint.test.d.ts +2 -0
  67. package/dist/__tests__/realtime-session-mint.test.d.ts.map +1 -0
  68. package/dist/__tests__/realtime-session-mint.test.js +69 -0
  69. package/dist/__tests__/realtime-session-mint.test.js.map +1 -0
  70. package/dist/__tests__/realtime-session-policy.test.d.ts +2 -0
  71. package/dist/__tests__/realtime-session-policy.test.d.ts.map +1 -0
  72. package/dist/__tests__/realtime-session-policy.test.js +303 -0
  73. package/dist/__tests__/realtime-session-policy.test.js.map +1 -0
  74. package/dist/__tests__/realtime-session-review.service.test.d.ts +2 -0
  75. package/dist/__tests__/realtime-session-review.service.test.d.ts.map +1 -0
  76. package/dist/__tests__/realtime-session-review.service.test.js +743 -0
  77. package/dist/__tests__/realtime-session-review.service.test.js.map +1 -0
  78. package/dist/__tests__/realtime-session-state.test.d.ts +2 -0
  79. package/dist/__tests__/realtime-session-state.test.d.ts.map +1 -0
  80. package/dist/__tests__/realtime-session-state.test.js +83 -0
  81. package/dist/__tests__/realtime-session-state.test.js.map +1 -0
  82. package/dist/__tests__/realtime-session-timeline-card.test.d.ts +2 -0
  83. package/dist/__tests__/realtime-session-timeline-card.test.d.ts.map +1 -0
  84. package/dist/__tests__/realtime-session-timeline-card.test.js +106 -0
  85. package/dist/__tests__/realtime-session-timeline-card.test.js.map +1 -0
  86. package/dist/__tests__/realtime-session-timeline.test.d.ts +2 -0
  87. package/dist/__tests__/realtime-session-timeline.test.d.ts.map +1 -0
  88. package/dist/__tests__/realtime-session-timeline.test.js +142 -0
  89. package/dist/__tests__/realtime-session-timeline.test.js.map +1 -0
  90. package/dist/__tests__/realtime-sessions-adapter.test.d.ts +19 -0
  91. package/dist/__tests__/realtime-sessions-adapter.test.d.ts.map +1 -0
  92. package/dist/__tests__/realtime-sessions-adapter.test.js +188 -0
  93. package/dist/__tests__/realtime-sessions-adapter.test.js.map +1 -0
  94. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts +2 -0
  95. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts.map +1 -0
  96. package/dist/__tests__/realtime-surface-panel-prefs.test.js +100 -0
  97. package/dist/__tests__/realtime-surface-panel-prefs.test.js.map +1 -0
  98. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts +2 -0
  99. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts.map +1 -0
  100. package/dist/__tests__/realtime-surface-tabs-model.test.js +193 -0
  101. package/dist/__tests__/realtime-surface-tabs-model.test.js.map +1 -0
  102. package/dist/__tests__/remote-browser-audio-player.test.d.ts +2 -0
  103. package/dist/__tests__/remote-browser-audio-player.test.d.ts.map +1 -0
  104. package/dist/__tests__/remote-browser-audio-player.test.js +137 -0
  105. package/dist/__tests__/remote-browser-audio-player.test.js.map +1 -0
  106. package/dist/__tests__/remote-browser-channel.test.d.ts +2 -0
  107. package/dist/__tests__/remote-browser-channel.test.d.ts.map +1 -0
  108. package/dist/__tests__/remote-browser-channel.test.js +423 -0
  109. package/dist/__tests__/remote-browser-channel.test.js.map +1 -0
  110. package/dist/__tests__/slot-defaults.test.d.ts +24 -0
  111. package/dist/__tests__/slot-defaults.test.d.ts.map +1 -0
  112. package/dist/__tests__/slot-defaults.test.js +63 -0
  113. package/dist/__tests__/slot-defaults.test.js.map +1 -0
  114. package/dist/__tests__/user-authorization.test.d.ts +2 -0
  115. package/dist/__tests__/user-authorization.test.d.ts.map +1 -0
  116. package/dist/__tests__/user-authorization.test.js +97 -0
  117. package/dist/__tests__/user-authorization.test.js.map +1 -0
  118. package/dist/__tests__/voice-session-narration.test.d.ts +2 -0
  119. package/dist/__tests__/voice-session-narration.test.d.ts.map +1 -0
  120. package/dist/__tests__/voice-session-narration.test.js +609 -0
  121. package/dist/__tests__/voice-session-narration.test.js.map +1 -0
  122. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts +2 -0
  123. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts.map +1 -0
  124. package/dist/__tests__/whiteboard-artifact-viewer.test.js +101 -0
  125. package/dist/__tests__/whiteboard-artifact-viewer.test.js.map +1 -0
  126. package/dist/__tests__/whiteboard-channel.test.d.ts +2 -0
  127. package/dist/__tests__/whiteboard-channel.test.d.ts.map +1 -0
  128. package/dist/__tests__/whiteboard-channel.test.js +260 -0
  129. package/dist/__tests__/whiteboard-channel.test.js.map +1 -0
  130. package/dist/__tests__/whiteboard-restore-state.test.d.ts +2 -0
  131. package/dist/__tests__/whiteboard-restore-state.test.d.ts.map +1 -0
  132. package/dist/__tests__/whiteboard-restore-state.test.js +108 -0
  133. package/dist/__tests__/whiteboard-restore-state.test.js.map +1 -0
  134. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +205 -3
  135. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  136. package/dist/lib/components/conversation/conversation-chat-area.component.js +911 -342
  137. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  138. package/dist/lib/components/mention/mention-dropdown.component.js +35 -17
  139. package/dist/lib/components/mention/mention-dropdown.component.js.map +1 -1
  140. package/dist/lib/components/mention/mention-editor.component.d.ts +4 -0
  141. package/dist/lib/components/mention/mention-editor.component.d.ts.map +1 -1
  142. package/dist/lib/components/mention/mention-editor.component.js +43 -19
  143. package/dist/lib/components/mention/mention-editor.component.js.map +1 -1
  144. package/dist/lib/components/message/message-input-box.component.d.ts +17 -1
  145. package/dist/lib/components/message/message-input-box.component.d.ts.map +1 -1
  146. package/dist/lib/components/message/message-input-box.component.js +73 -15
  147. package/dist/lib/components/message/message-input-box.component.js.map +1 -1
  148. package/dist/lib/components/message/message-input.component.d.ts +142 -6
  149. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  150. package/dist/lib/components/message/message-input.component.js +328 -82
  151. package/dist/lib/components/message/message-input.component.js.map +1 -1
  152. package/dist/lib/components/message/message-item.component.d.ts +28 -3
  153. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  154. package/dist/lib/components/message/message-item.component.js +180 -108
  155. package/dist/lib/components/message/message-item.component.js.map +1 -1
  156. package/dist/lib/components/message/message-list.component.d.ts +81 -2
  157. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  158. package/dist/lib/components/message/message-list.component.js +252 -87
  159. package/dist/lib/components/message/message-list.component.js.map +1 -1
  160. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +282 -0
  161. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +1 -0
  162. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +158 -0
  163. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +1 -0
  164. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts +25 -0
  165. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts.map +1 -0
  166. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.js +140 -0
  167. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.js.map +1 -0
  168. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +35 -0
  169. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -0
  170. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +58 -0
  171. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -0
  172. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +63 -0
  173. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -0
  174. package/dist/lib/components/realtime/realtime-activity-rail.component.js +260 -0
  175. package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -0
  176. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +117 -0
  177. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -0
  178. package/dist/lib/components/realtime/realtime-agent-banner.component.js +504 -0
  179. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -0
  180. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +168 -0
  181. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -0
  182. package/dist/lib/components/realtime/realtime-agent-picker.component.js +556 -0
  183. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -0
  184. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +97 -0
  185. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -0
  186. package/dist/lib/components/realtime/realtime-audio-visuals.js +139 -0
  187. package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -0
  188. package/dist/lib/components/realtime/realtime-channel-strip.component.d.ts +29 -0
  189. package/dist/lib/components/realtime/realtime-channel-strip.component.d.ts.map +1 -0
  190. package/dist/lib/components/realtime/realtime-channel-strip.component.js +69 -0
  191. package/dist/lib/components/realtime/realtime-channel-strip.component.js.map +1 -0
  192. package/dist/lib/components/realtime/realtime-composer.component.d.ts +65 -0
  193. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -0
  194. package/dist/lib/components/realtime/realtime-composer.component.js +256 -0
  195. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -0
  196. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +71 -0
  197. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -0
  198. package/dist/lib/components/realtime/realtime-delegation-card.component.js +324 -0
  199. package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -0
  200. package/dist/lib/components/realtime/realtime-disclosure.d.ts +135 -0
  201. package/dist/lib/components/realtime/realtime-disclosure.d.ts.map +1 -0
  202. package/dist/lib/components/realtime/realtime-disclosure.js +188 -0
  203. package/dist/lib/components/realtime/realtime-disclosure.js.map +1 -0
  204. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +491 -0
  205. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -0
  206. package/dist/lib/components/realtime/realtime-session-overlay.component.js +1274 -0
  207. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -0
  208. package/dist/lib/components/realtime/realtime-session-state.d.ts +191 -0
  209. package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -0
  210. package/dist/lib/components/realtime/realtime-session-state.js +244 -0
  211. package/dist/lib/components/realtime/realtime-session-state.js.map +1 -0
  212. package/dist/lib/components/realtime/realtime-session-thread.component.d.ts +56 -0
  213. package/dist/lib/components/realtime/realtime-session-thread.component.d.ts.map +1 -0
  214. package/dist/lib/components/realtime/realtime-session-thread.component.js +246 -0
  215. package/dist/lib/components/realtime/realtime-session-thread.component.js.map +1 -0
  216. package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts +51 -0
  217. package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts.map +1 -0
  218. package/dist/lib/components/realtime/realtime-session-timeline-card.component.js +193 -0
  219. package/dist/lib/components/realtime/realtime-session-timeline-card.component.js.map +1 -0
  220. package/dist/lib/components/realtime/realtime-surface-panel-prefs.d.ts +77 -0
  221. package/dist/lib/components/realtime/realtime-surface-panel-prefs.d.ts.map +1 -0
  222. package/dist/lib/components/realtime/realtime-surface-panel-prefs.js +114 -0
  223. package/dist/lib/components/realtime/realtime-surface-panel-prefs.js.map +1 -0
  224. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +173 -0
  225. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -0
  226. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +496 -0
  227. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -0
  228. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +181 -0
  229. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -0
  230. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +223 -0
  231. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -0
  232. package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.d.ts +163 -0
  233. package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.d.ts.map +1 -0
  234. package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.js +309 -0
  235. package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.js.map +1 -0
  236. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +168 -0
  237. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -0
  238. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +524 -0
  239. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -0
  240. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts +346 -0
  241. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts.map +1 -0
  242. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js +851 -0
  243. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js.map +1 -0
  244. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.d.ts +86 -0
  245. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.d.ts.map +1 -0
  246. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.js +210 -0
  247. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.js.map +1 -0
  248. package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.d.ts +48 -0
  249. package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.d.ts.map +1 -0
  250. package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.js +180 -0
  251. package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.js.map +1 -0
  252. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +119 -0
  253. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -0
  254. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +274 -0
  255. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -0
  256. package/dist/lib/components/slots/mj-chat-agent-presence-default.component.d.ts +11 -0
  257. package/dist/lib/components/slots/mj-chat-agent-presence-default.component.d.ts.map +1 -0
  258. package/dist/lib/components/slots/mj-chat-agent-presence-default.component.js +98 -0
  259. package/dist/lib/components/slots/mj-chat-agent-presence-default.component.js.map +1 -0
  260. package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.d.ts +9 -0
  261. package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.d.ts.map +1 -0
  262. package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.js +35 -0
  263. package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.js.map +1 -0
  264. package/dist/lib/components/slots/mj-chat-empty-state-default.component.d.ts +28 -0
  265. package/dist/lib/components/slots/mj-chat-empty-state-default.component.d.ts.map +1 -0
  266. package/dist/lib/components/slots/mj-chat-empty-state-default.component.js +104 -0
  267. package/dist/lib/components/slots/mj-chat-empty-state-default.component.js.map +1 -0
  268. package/dist/lib/components/slots/mj-chat-header-default.component.d.ts +11 -0
  269. package/dist/lib/components/slots/mj-chat-header-default.component.d.ts.map +1 -0
  270. package/dist/lib/components/slots/mj-chat-header-default.component.js +103 -0
  271. package/dist/lib/components/slots/mj-chat-header-default.component.js.map +1 -0
  272. package/dist/lib/components/slots/mj-chat-message-bubble-default.component.d.ts +15 -0
  273. package/dist/lib/components/slots/mj-chat-message-bubble-default.component.d.ts.map +1 -0
  274. package/dist/lib/components/slots/mj-chat-message-bubble-default.component.js +73 -0
  275. package/dist/lib/components/slots/mj-chat-message-bubble-default.component.js.map +1 -0
  276. package/dist/lib/components/slots/mj-chat-message-extra-default.component.d.ts +9 -0
  277. package/dist/lib/components/slots/mj-chat-message-extra-default.component.d.ts.map +1 -0
  278. package/dist/lib/components/slots/mj-chat-message-extra-default.component.js +34 -0
  279. package/dist/lib/components/slots/mj-chat-message-extra-default.component.js.map +1 -0
  280. package/dist/lib/components/slots/slot-interfaces.d.ts +95 -0
  281. package/dist/lib/components/slots/slot-interfaces.d.ts.map +1 -0
  282. package/dist/lib/components/slots/slot-interfaces.js +18 -0
  283. package/dist/lib/components/slots/slot-interfaces.js.map +1 -0
  284. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +11 -0
  285. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  286. package/dist/lib/components/workspace/conversation-workspace.component.js +28 -4
  287. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  288. package/dist/lib/conversations.module.d.ts +12 -1
  289. package/dist/lib/conversations.module.d.ts.map +1 -1
  290. package/dist/lib/conversations.module.js +93 -5
  291. package/dist/lib/conversations.module.js.map +1 -1
  292. package/dist/lib/directives/chat-slot.directive.d.ts +44 -0
  293. package/dist/lib/directives/chat-slot.directive.d.ts.map +1 -0
  294. package/dist/lib/directives/chat-slot.directive.js +54 -0
  295. package/dist/lib/directives/chat-slot.directive.js.map +1 -0
  296. package/dist/lib/events/chat-events.d.ts +137 -0
  297. package/dist/lib/events/chat-events.d.ts.map +1 -0
  298. package/dist/lib/events/chat-events.js +189 -0
  299. package/dist/lib/events/chat-events.js.map +1 -0
  300. package/dist/lib/models/conversation-state.model.d.ts +2 -1
  301. package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
  302. package/dist/lib/models/conversation-state.model.js.map +1 -1
  303. package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
  304. package/dist/lib/services/artifact-state.service.js +23 -6
  305. package/dist/lib/services/artifact-state.service.js.map +1 -1
  306. package/dist/lib/services/conversation-agent.service.d.ts +60 -74
  307. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  308. package/dist/lib/services/conversation-agent.service.js +100 -313
  309. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  310. package/dist/lib/services/conversation-bridge.service.d.ts +11 -70
  311. package/dist/lib/services/conversation-bridge.service.d.ts.map +1 -1
  312. package/dist/lib/services/conversation-bridge.service.js +51 -85
  313. package/dist/lib/services/conversation-bridge.service.js.map +1 -1
  314. package/dist/lib/services/conversation-naming.d.ts +63 -0
  315. package/dist/lib/services/conversation-naming.d.ts.map +1 -0
  316. package/dist/lib/services/conversation-naming.js +58 -0
  317. package/dist/lib/services/conversation-naming.js.map +1 -0
  318. package/dist/lib/services/conversation-streaming.service.d.ts +24 -154
  319. package/dist/lib/services/conversation-streaming.service.d.ts.map +1 -1
  320. package/dist/lib/services/conversation-streaming.service.js +39 -361
  321. package/dist/lib/services/conversation-streaming.service.js.map +1 -1
  322. package/dist/lib/services/conversations-runtime-bootstrap.service.d.ts +10 -0
  323. package/dist/lib/services/conversations-runtime-bootstrap.service.d.ts.map +1 -0
  324. package/dist/lib/services/conversations-runtime-bootstrap.service.js +104 -0
  325. package/dist/lib/services/conversations-runtime-bootstrap.service.js.map +1 -0
  326. package/dist/lib/services/delegation-result-parser.d.ts +45 -0
  327. package/dist/lib/services/delegation-result-parser.d.ts.map +1 -0
  328. package/dist/lib/services/delegation-result-parser.js +48 -0
  329. package/dist/lib/services/delegation-result-parser.js.map +1 -0
  330. package/dist/lib/services/mention-autocomplete.service.d.ts +19 -4
  331. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  332. package/dist/lib/services/mention-autocomplete.service.js +65 -4
  333. package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
  334. package/dist/lib/services/mention-parser.service.d.ts +8 -53
  335. package/dist/lib/services/mention-parser.service.d.ts.map +1 -1
  336. package/dist/lib/services/mention-parser.service.js +32 -243
  337. package/dist/lib/services/mention-parser.service.js.map +1 -1
  338. package/dist/lib/services/narration-template.d.ts +42 -0
  339. package/dist/lib/services/narration-template.d.ts.map +1 -0
  340. package/dist/lib/services/narration-template.js +73 -0
  341. package/dist/lib/services/narration-template.js.map +1 -0
  342. package/dist/lib/services/realtime-pairing.d.ts +120 -0
  343. package/dist/lib/services/realtime-pairing.d.ts.map +1 -0
  344. package/dist/lib/services/realtime-pairing.js +150 -0
  345. package/dist/lib/services/realtime-pairing.js.map +1 -0
  346. package/dist/lib/services/realtime-session-review.service.d.ts +233 -0
  347. package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -0
  348. package/dist/lib/services/realtime-session-review.service.js +417 -0
  349. package/dist/lib/services/realtime-session-review.service.js.map +1 -0
  350. package/dist/lib/services/realtime-session.service.d.ts +739 -0
  351. package/dist/lib/services/realtime-session.service.d.ts.map +1 -0
  352. package/dist/lib/services/realtime-session.service.js +1647 -0
  353. package/dist/lib/services/realtime-session.service.js.map +1 -0
  354. package/dist/lib/services/realtime-sessions-adapter.d.ts +54 -0
  355. package/dist/lib/services/realtime-sessions-adapter.d.ts.map +1 -0
  356. package/dist/lib/services/realtime-sessions-adapter.js +154 -0
  357. package/dist/lib/services/realtime-sessions-adapter.js.map +1 -0
  358. package/dist/lib/services/user-authorization.d.ts +67 -0
  359. package/dist/lib/services/user-authorization.d.ts.map +1 -0
  360. package/dist/lib/services/user-authorization.js +66 -0
  361. package/dist/lib/services/user-authorization.js.map +1 -0
  362. package/dist/lib/utils/realtime-session-timeline.d.ts +84 -0
  363. package/dist/lib/utils/realtime-session-timeline.d.ts.map +1 -0
  364. package/dist/lib/utils/realtime-session-timeline.js +94 -0
  365. package/dist/lib/utils/realtime-session-timeline.js.map +1 -0
  366. package/dist/public-api.d.ts +41 -0
  367. package/dist/public-api.d.ts.map +1 -1
  368. package/dist/public-api.js +50 -0
  369. package/dist/public-api.js.map +1 -1
  370. package/package.json +27 -24
  371. package/dist/__tests__/conversation-bridge.service.test.d.ts +0 -2
  372. package/dist/__tests__/conversation-bridge.service.test.d.ts.map +0 -1
  373. package/dist/__tests__/conversation-bridge.service.test.js +0 -98
  374. package/dist/__tests__/conversation-bridge.service.test.js.map +0 -1
  375. package/dist/__tests__/mention-parser.test.d.ts +0 -2
  376. package/dist/__tests__/mention-parser.test.d.ts.map +0 -1
  377. package/dist/__tests__/mention-parser.test.js +0 -154
  378. package/dist/__tests__/mention-parser.test.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-session-narration.test.js","sourceRoot":"","sources":["../../src/__tests__/voice-session-narration.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';\nimport { Subject } from 'rxjs';\nimport { IMetadataProvider } from '@memberjunction/core';\nimport {\n RealtimeSessionService,\n VoiceConnectionState,\n VoiceDelegationNarration,\n VoiceDelegationProgress,\n VoiceDelegationResult\n} from '../lib/services/realtime-session.service';\n\n/**\n * The NARRATION PACING / AGGREGATION state machine — the provider-agnostic policy that\n * decides WHEN the realtime model is asked to speak an interim progress update while a\n * delegated tool call runs, and WHAT digest it speaks:\n *\n * - first spoken update no earlier than ~5s into a delegation burst (FirstNarrationDelayMs),\n * - ≥8s between spoken updates, SESSION-global (NarrationIntervalMs — sequential tool calls\n * must never re-arm the faster first-update path),\n * - floods of progress AGGREGATE into one ' → ' digest (max 4, oldest dropped),\n * - busy / audio-playing fire moments RETRY at 1.5s with the buffer intact,\n * - the buffer is DISCARDED when the result lands first (never narrate over the answer),\n * - what the model actually SAID is chained into the next instructions (≤3, anti-repeat).\n *\n * The machine lives behind private members, so these tests use the same narrow typed-seam\n * approach as the channels/client-tools suites: a fake realtime client capturing\n * `SendContextNote` / `RequestSpokenUpdate`, direct invocation of the private handlers\n * (`handleToolCall`, `dispatchProgress`, `onClientTranscript`), and a fake Provider whose\n * `ExecuteGQL` returns controllable deferred promises so tool calls stay in-flight exactly\n * as long as each test needs. `vi.useFakeTimers` (timers + Date) walks the 5s/8s/1.5s\n * schedule deterministically.\n */\n\n// ── Test doubles ──────────────────────────────────────────────────────────────\n\nclass FakeRealtimeClient {\n public ContextNotes: string[] = [];\n public SpokenUpdates: string[] = [];\n public ToolResults: Array<{ CallID: string; ResultJson: string }> = [];\n public IsBusy = false;\n public IsAudioPlaying = false;\n public SendContextNote(text: string): void {\n this.ContextNotes.push(text);\n }\n public RequestSpokenUpdate(instructions: string): void {\n this.SpokenUpdates.push(instructions);\n }\n public SendToolResult(callId: string, resultJson: string): void {\n this.ToolResults.push({ CallID: callId, ResultJson: resultJson });\n }\n public async Disconnect(): Promise<void> {\n // no-op for teardown\n }\n}\n\n/** Shape of a client transcript event as the service consumes it. */\ninterface TranscriptEvent {\n Role: 'User' | 'Assistant';\n Text: string;\n IsFinal: boolean;\n Kind: 'normal' | 'narration';\n}\n\n/** The private surface the tests drive — no `any`, just the members under test. */\ninterface VoiceSessionNarrationInternals {\n client: FakeRealtimeClient | null;\n agentSessionId: string | null;\n narrationTemplate: string | null;\n inFlightCallIds: Set<string>;\n narrationTimer: ReturnType<typeof setTimeout> | null;\n pendingNarrationMessages: string[];\n lastDelegationNarrationAt: number;\n delegationBurstStartedAt: number;\n narrationCount: number;\n spokenNarrations: string[];\n lastNarratedTail: string;\n handleToolCall(call: { CallID: string; ToolName: string; ArgumentsJson: string }): Promise<void>;\n dispatchProgress(progress: VoiceDelegationProgress): void;\n onDelegationStatusMessage(raw: string): void;\n subscribeDelegationProgress(): void;\n onClientTranscript(transcript: TranscriptEvent): Promise<void>;\n fireDeferredNarration(): void;\n teardownDelegationProgress(): void;\n teardown(closeServerSession: boolean): Promise<void>;\n wireClientHandlers(client: unknown): void;\n}\n\nfunction internals(service: RealtimeSessionService): VoiceSessionNarrationInternals {\n return service as unknown as VoiceSessionNarrationInternals;\n}\n\ninterface Deferred<T> {\n promise: Promise<T>;\n resolve: (value: T) => void;\n reject: (reason: Error) => void;\n}\n\nfunction createDeferred<T>(): Deferred<T> {\n let resolve!: (value: T) => void;\n let reject!: (reason: Error) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n}\n\n/** One harness per test: service + fake client + controllable tool-execution deferreds. */\ninterface Harness {\n service: RealtimeSessionService;\n client: FakeRealtimeClient;\n i: VoiceSessionNarrationInternals;\n /** One deferred per ExecuteRealtimeSessionTool invocation, in call order. */\n pendingTools: Array<Deferred<{ ExecuteRealtimeSessionTool: string }>>;\n executeGQL: ReturnType<typeof vi.fn>;\n pushStatus$: Subject<string>;\n}\n\nfunction createHarness(): Harness {\n const service = new RealtimeSessionService();\n const client = new FakeRealtimeClient();\n const i = internals(service);\n const pendingTools: Array<Deferred<{ ExecuteRealtimeSessionTool: string }>> = [];\n const pushStatus$ = new Subject<string>();\n const executeGQL = vi.fn((mutation: string) => {\n if (mutation.includes('ExecuteRealtimeSessionTool')) {\n const deferred = createDeferred<{ ExecuteRealtimeSessionTool: string }>();\n pendingTools.push(deferred);\n return deferred.promise;\n }\n return Promise.resolve({});\n });\n service.Provider = {\n ExecuteGQL: executeGQL,\n sessionId: 'transport-1',\n PushStatusUpdates: () => pushStatus$.asObservable()\n } as unknown as IMetadataProvider;\n i.client = client;\n i.agentSessionId = 'sess-1';\n return { service, client, i, pendingTools, executeGQL, pushStatus$ };\n}\n\n/**\n * Starts a server-relayed delegation. The returned promise settles when the call's\n * deferred is resolved/rejected; until then the call is IN-FLIGHT (the realistic state\n * while progress streams in).\n */\nfunction beginDelegation(h: Harness, callId: string): Promise<void> {\n return h.i.handleToolCall({ CallID: callId, ToolName: 'invoke-target-agent', ArgumentsJson: '{}' });\n}\n\n/** Resolves the OLDEST unresolved tool deferred with a delegation result and settles the call. */\nasync function completeDelegation(h: Harness, call: Promise<void>, resultJson = '{\"success\":true,\"output\":\"done\"}'): Promise<void> {\n const deferred = h.pendingTools.shift();\n if (!deferred) {\n throw new Error('No pending tool execution to complete');\n }\n deferred.resolve({ ExecuteRealtimeSessionTool: resultJson });\n await call;\n}\n\nfunction progress(h: Harness, callId: string, message: string): void {\n h.i.dispatchProgress({ CallID: callId, Step: 'subagent_execution', Message: message });\n}\n\ndescribe('RealtimeSessionService — narration timing (5s anchor + session-global 8s floor)', () => {\n let h: Harness;\n\n beforeEach(() => {\n vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout', 'Date'] });\n h = createHarness();\n });\n\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it('the first spoken update fires no earlier than 5s after the burst started', () => {\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'warming up');\n\n vi.advanceTimersByTime(4999);\n expect(h.client.SpokenUpdates).toHaveLength(0);\n\n vi.advanceTimersByTime(1);\n expect(h.client.SpokenUpdates).toHaveLength(1);\n expect(h.client.SpokenUpdates[0]).toContain('warming up');\n });\n\n it('anchors the 5s delay at burst START — progress arriving at 6s fires after the 250ms minimum', () => {\n void beginDelegation(h, 'c1');\n vi.advanceTimersByTime(6000); // burst is already 6s old when the first progress lands\n\n progress(h, 'c1', 'late progress');\n vi.advanceTimersByTime(249);\n expect(h.client.SpokenUpdates).toHaveLength(0);\n\n vi.advanceTimersByTime(1);\n expect(h.client.SpokenUpdates).toHaveLength(1);\n });\n\n it('spaces the SECOND spoken update ≥8s after the first', () => {\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'first');\n vi.advanceTimersByTime(5000);\n expect(h.client.SpokenUpdates).toHaveLength(1);\n\n progress(h, 'c1', 'second');\n vi.advanceTimersByTime(7999);\n expect(h.client.SpokenUpdates).toHaveLength(1);\n\n vi.advanceTimersByTime(1);\n expect(h.client.SpokenUpdates).toHaveLength(2);\n expect(h.client.SpokenUpdates[1]).toContain('second');\n });\n\n it('REGRESSION: a sequential tool call seconds later does NOT re-arm the fast first-update path — the 8s floor is session-global', async () => {\n // Burst 1: narrate once at T+5s, then the result lands.\n const call1 = beginDelegation(h, 'c1');\n progress(h, 'c1', 'burst one');\n vi.advanceTimersByTime(5000); // narration #1 at T=5000\n expect(h.client.SpokenUpdates).toHaveLength(1);\n await completeDelegation(h, call1);\n\n // Burst 2 starts only 2s later (T=7000). Its 5s anchor would allow T=12000,\n // but the session-global floor (5000 + 8000 = 13000) must win.\n vi.advanceTimersByTime(2000);\n void beginDelegation(h, 'c2');\n progress(h, 'c2', 'burst two');\n\n vi.advanceTimersByTime(5999); // T=12999 — past the burst anchor, still under the floor\n expect(h.client.SpokenUpdates).toHaveLength(1);\n\n vi.advanceTimersByTime(1); // T=13000 — exactly 8s after the last narration\n expect(h.client.SpokenUpdates).toHaveLength(2);\n expect(h.client.SpokenUpdates[1]).toContain('burst two');\n });\n\n it('a new burst resets the per-burst state (count/buffer/tail) but PRESERVES the floor and spoken history', async () => {\n const call1 = beginDelegation(h, 'c1');\n progress(h, 'c1', 'burst one');\n vi.advanceTimersByTime(5000);\n await h.i.onClientTranscript({ Role: 'Assistant', Text: 'I said this already', IsFinal: true, Kind: 'narration' });\n await completeDelegation(h, call1);\n const floorBefore = h.i.lastDelegationNarrationAt;\n expect(floorBefore).toBeGreaterThan(0);\n\n void beginDelegation(h, 'c2');\n\n expect(h.i.narrationCount).toBe(0);\n expect(h.i.pendingNarrationMessages).toEqual([]);\n expect(h.i.lastNarratedTail).toBe('');\n expect(h.i.lastDelegationNarrationAt).toBe(floorBefore); // floor NOT reset\n expect(h.i.spokenNarrations).toEqual(['I said this already']); // history NOT reset\n });\n\n it('the second burst restarts narration numbering at update #1 while chaining the prior utterance', async () => {\n const call1 = beginDelegation(h, 'c1');\n progress(h, 'c1', 'burst one');\n vi.advanceTimersByTime(5000);\n await h.i.onClientTranscript({ Role: 'Assistant', Text: 'Pulling that up now', IsFinal: true, Kind: 'narration' });\n await completeDelegation(h, call1);\n\n vi.advanceTimersByTime(2000);\n void beginDelegation(h, 'c2');\n progress(h, 'c2', 'burst two');\n vi.advanceTimersByTime(6000); // the 8s session floor elapses\n\n expect(h.client.SpokenUpdates).toHaveLength(2);\n expect(h.client.SpokenUpdates[1]).toContain('spoken update #1'); // per-burst numbering reset\n expect(h.client.SpokenUpdates[1]).toContain('- \"Pulling that up now\"'); // history chained across bursts\n });\n\n it('teardown → new session resets the 8s floor (the next first update honors only the 5s anchor)', async () => {\n const call1 = beginDelegation(h, 'c1');\n progress(h, 'c1', 'old session');\n vi.advanceTimersByTime(5000);\n expect(h.client.SpokenUpdates).toHaveLength(1);\n await completeDelegation(h, call1);\n\n await h.i.teardown(false);\n\n // New session on the same service instance: fresh client + session id.\n const freshClient = new FakeRealtimeClient();\n h.i.client = freshClient;\n h.i.agentSessionId = 'sess-2';\n void beginDelegation(h, 'c9');\n progress(h, 'c9', 'new session');\n\n vi.advanceTimersByTime(4999);\n expect(freshClient.SpokenUpdates).toHaveLength(0);\n vi.advanceTimersByTime(1);\n expect(freshClient.SpokenUpdates).toHaveLength(1); // 5s anchor only — floor was reset\n });\n\n it('teardownDelegationProgress resets ALL narration state', () => {\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'm1');\n vi.advanceTimersByTime(5000);\n expect(h.client.SpokenUpdates).toHaveLength(1);\n h.i.spokenNarrations.push('something said');\n progress(h, 'c1', 'm2'); // re-arms the timer + refills the buffer\n\n h.i.teardownDelegationProgress();\n\n expect(h.i.inFlightCallIds.size).toBe(0);\n expect(h.i.narrationTimer).toBeNull();\n expect(h.i.pendingNarrationMessages).toEqual([]);\n expect(h.i.lastDelegationNarrationAt).toBe(0);\n expect(h.i.delegationBurstStartedAt).toBe(0);\n expect(h.i.narrationCount).toBe(0);\n expect(h.i.spokenNarrations).toEqual([]);\n expect(h.i.lastNarratedTail).toBe('');\n });\n});\n\ndescribe('RealtimeSessionService — narration aggregation (digest buffer)', () => {\n let h: Harness;\n\n beforeEach(() => {\n vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout', 'Date'] });\n h = createHarness();\n });\n\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it('a flood of 6 distinct messages becomes ONE spoken digest of the LAST 4, joined \" → \"', () => {\n void beginDelegation(h, 'c1');\n for (const m of ['m1', 'm2', 'm3', 'm4', 'm5', 'm6']) {\n progress(h, 'c1', m);\n }\n\n vi.advanceTimersByTime(5000);\n\n expect(h.client.SpokenUpdates).toHaveLength(1);\n expect(h.client.SpokenUpdates[0]).toContain('m3 → m4 → m5 → m6');\n expect(h.client.SpokenUpdates[0]).not.toContain('m1');\n expect(h.client.SpokenUpdates[0]).not.toContain('m2');\n });\n\n it('every progress event STILL feeds a context note, even when the digest dedupes/caps', () => {\n void beginDelegation(h, 'c1');\n for (const m of ['m1', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6']) {\n progress(h, 'c1', m);\n }\n\n expect(h.client.ContextNotes).toHaveLength(7);\n expect(h.client.ContextNotes[0]).toBe('[delegated-agent progress] m1');\n });\n\n it('an already-buffered duplicate message is not re-buffered', () => {\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'dup');\n progress(h, 'c1', 'dup');\n progress(h, 'c1', 'next');\n\n vi.advanceTimersByTime(5000);\n\n expect(h.client.SpokenUpdates).toHaveLength(1);\n expect(h.client.SpokenUpdates[0]).toContain('dup → next');\n expect(h.client.SpokenUpdates[0]).not.toContain('dup → dup');\n });\n\n it('a message equal to the LAST NARRATED TAIL is not re-buffered (no empty re-narration)', () => {\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'still working');\n vi.advanceTimersByTime(5000);\n expect(h.client.SpokenUpdates).toHaveLength(1);\n\n // The same trailing message arrives again — context note yes, narration no.\n progress(h, 'c1', 'still working');\n expect(h.i.pendingNarrationMessages).toEqual([]);\n expect(h.i.narrationTimer).toBeNull();\n\n vi.advanceTimersByTime(30000);\n expect(h.client.SpokenUpdates).toHaveLength(1);\n expect(h.client.ContextNotes).toHaveLength(2);\n });\n\n it('a DISTINCT message after a tail-dedupe re-arms the machine normally', () => {\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'still working');\n vi.advanceTimersByTime(5000);\n progress(h, 'c1', 'still working'); // tail dedupe\n vi.advanceTimersByTime(20000); // well past the 8s floor\n\n progress(h, 'c1', 'finishing touches');\n vi.advanceTimersByTime(250); // floor already satisfied → minimum delay\n\n expect(h.client.SpokenUpdates).toHaveLength(2);\n expect(h.client.SpokenUpdates[1]).toContain('finishing touches');\n });\n\n it('discards the buffer when the result lands before the fire moment — nothing is spoken', async () => {\n const call = beginDelegation(h, 'c1');\n progress(h, 'c1', 'never spoken');\n vi.advanceTimersByTime(3000);\n\n await completeDelegation(h, call);\n\n expect(h.i.narrationTimer).toBeNull();\n expect(h.i.pendingNarrationMessages).toEqual([]);\n vi.advanceTimersByTime(60000);\n expect(h.client.SpokenUpdates).toHaveLength(0);\n });\n\n it('a result for ONE of several in-flight calls still cancels the pending digest (result speaks next)', async () => {\n const call1 = beginDelegation(h, 'c1');\n void beginDelegation(h, 'c2');\n progress(h, 'c1', 'from c1');\n progress(h, 'c2', 'from c2');\n\n await completeDelegation(h, call1);\n expect(h.i.pendingNarrationMessages).toEqual([]);\n expect(h.i.inFlightCallIds.has('c2')).toBe(true);\n\n vi.advanceTimersByTime(60000);\n expect(h.client.SpokenUpdates).toHaveLength(0); // buffer was discarded with the timer\n });\n});\n\ndescribe('RealtimeSessionService — busy / audio-playing retry', () => {\n let h: Harness;\n\n beforeEach(() => {\n vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout', 'Date'] });\n h = createHarness();\n });\n\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it('a busy fire moment retries 1.5s later with the SAME buffer', () => {\n h.client.IsBusy = true;\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'kept safe');\n\n vi.advanceTimersByTime(5000);\n expect(h.client.SpokenUpdates).toHaveLength(0);\n expect(h.i.pendingNarrationMessages).toEqual(['kept safe']); // buffer intact\n\n h.client.IsBusy = false;\n vi.advanceTimersByTime(1499);\n expect(h.client.SpokenUpdates).toHaveLength(0);\n vi.advanceTimersByTime(1);\n expect(h.client.SpokenUpdates).toHaveLength(1);\n expect(h.client.SpokenUpdates[0]).toContain('kept safe');\n });\n\n it('keeps retrying while the model stays busy, then fires once when it frees up', () => {\n h.client.IsBusy = true;\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'patient update');\n\n vi.advanceTimersByTime(5000); // initial fire → busy\n vi.advanceTimersByTime(1500); // retry 1 → busy\n vi.advanceTimersByTime(1500); // retry 2 → busy\n expect(h.client.SpokenUpdates).toHaveLength(0);\n\n h.client.IsBusy = false;\n vi.advanceTimersByTime(1500); // retry 3 → fires\n expect(h.client.SpokenUpdates).toHaveLength(1);\n });\n\n it('progress arriving during the retry window joins the digest', () => {\n h.client.IsBusy = true;\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'part one');\n\n vi.advanceTimersByTime(5000); // busy → retry armed\n progress(h, 'c1', 'part two'); // buffered while waiting\n\n h.client.IsBusy = false;\n vi.advanceTimersByTime(1500);\n\n expect(h.client.SpokenUpdates).toHaveLength(1);\n expect(h.client.SpokenUpdates[0]).toContain('part one → part two');\n });\n\n it('IsAudioPlaying gates exactly like IsBusy', () => {\n h.client.IsAudioPlaying = true;\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'audio gate');\n\n vi.advanceTimersByTime(5000);\n expect(h.client.SpokenUpdates).toHaveLength(0);\n\n h.client.IsAudioPlaying = false;\n vi.advanceTimersByTime(1500);\n expect(h.client.SpokenUpdates).toHaveLength(1);\n });\n\n it('a result landing during the retry window cancels the retry (nothing spoken)', async () => {\n h.client.IsBusy = true;\n const call = beginDelegation(h, 'c1');\n progress(h, 'c1', 'moot now');\n vi.advanceTimersByTime(5000); // busy → retry armed\n\n await completeDelegation(h, call);\n h.client.IsBusy = false;\n vi.advanceTimersByTime(60000);\n\n expect(h.client.SpokenUpdates).toHaveLength(0);\n });\n\n it('defensive: a fire with the in-flight set EMPTY drops the buffer silently', () => {\n h.i.pendingNarrationMessages.push('orphaned');\n h.i.inFlightCallIds.clear();\n\n h.i.fireDeferredNarration();\n\n expect(h.client.SpokenUpdates).toHaveLength(0);\n expect(h.i.pendingNarrationMessages).toEqual([]);\n });\n\n it('defensive: a fire with NO client drops the buffer without throwing', () => {\n h.i.inFlightCallIds.add('c1');\n h.i.pendingNarrationMessages.push('orphaned');\n h.i.client = null;\n\n expect(() => h.i.fireDeferredNarration()).not.toThrow();\n expect(h.i.pendingNarrationMessages).toEqual([]);\n });\n\n it('defensive: a fire with an EMPTY buffer is a no-op (no spoken update, no retry)', () => {\n h.i.inFlightCallIds.add('c1');\n\n h.i.fireDeferredNarration();\n\n expect(h.client.SpokenUpdates).toHaveLength(0);\n expect(h.i.narrationTimer).toBeNull();\n });\n});\n\ndescribe('RealtimeSessionService — narration instructions + spoken-history capture', () => {\n let h: Harness;\n\n beforeEach(() => {\n vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout', 'Date'] });\n h = createHarness();\n });\n\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it('chains what the model ACTUALLY SAID into the next instructions, with per-burst numbering', async () => {\n void beginDelegation(h, 'c1');\n progress(h, 'c1', 'step one');\n vi.advanceTimersByTime(5000);\n expect(h.client.SpokenUpdates[0]).toContain('spoken update #1');\n expect(h.client.SpokenUpdates[0]).toContain('first spoken update'); // \"none yet\" wording\n\n await h.i.onClientTranscript({ Role: 'Assistant', Text: 'On it — digging in', IsFinal: true, Kind: 'narration' });\n\n progress(h, 'c1', 'step two');\n vi.advanceTimersByTime(8000);\n\n expect(h.client.SpokenUpdates).toHaveLength(2);\n expect(h.client.SpokenUpdates[1]).toContain('spoken update #2');\n expect(h.client.SpokenUpdates[1]).toContain('- \"On it — digging in\"');\n });\n\n it('caps the chained prior narrations at the LAST 3', async () => {\n void beginDelegation(h, 'c1');\n for (const said of ['utterance 1', 'utterance 2', 'utterance 3', 'utterance 4']) {\n await h.i.onClientTranscript({ Role: 'Assistant', Text: said, IsFinal: true, Kind: 'narration' });\n }\n expect(h.i.spokenNarrations).toEqual(['utterance 2', 'utterance 3', 'utterance 4']);\n\n progress(h, 'c1', 'wrap up');\n vi.advanceTimersByTime(5000);\n\n const instructions = h.client.SpokenUpdates[0];\n expect(instructions).toContain('- \"utterance 2\"');\n expect(instructions).toContain('- \"utterance 4\"');\n expect(instructions).not.toContain('utterance 1');\n });\n\n it('threads digest / update number / prior narrations through a DB-driven template', async () => {\n h.i.narrationTemplate = 'T[{{ progressMessage }}][#{{ updateNumber }}][{{ priorNarrations }}]';\n void beginDelegation(h, 'c1');\n await h.i.onClientTranscript({ Role: 'Assistant', Text: 'prior words', IsFinal: true, Kind: 'narration' });\n\n progress(h, 'c1', 'alpha');\n progress(h, 'c1', 'beta');\n vi.advanceTimersByTime(5000);\n\n expect(h.client.SpokenUpdates).toEqual(['T[alpha → beta][#1][- \"prior words\"]']);\n });\n\n it('narration-kind final transcripts are EPHEMERAL: emitted on DelegationNarration$, never a caption, never relayed', async () => {\n const narrations: VoiceDelegationNarration[] = [];\n const captionCounts: number[] = [];\n h.service.DelegationNarration$.subscribe(n => narrations.push(n));\n h.service.Captions$.subscribe(c => captionCounts.push(c.length));\n\n await h.i.onClientTranscript({ Role: 'Assistant', Text: 'ephemeral note', IsFinal: true, Kind: 'narration' });\n\n expect(narrations).toEqual([{ Text: 'ephemeral note' }]);\n expect(captionCounts).toEqual([0]); // only the BehaviorSubject replay — no caption emission\n expect(h.executeGQL).not.toHaveBeenCalled(); // no RelayRealtimeTranscript\n });\n\n it('NORMAL assistant final transcripts become captions and are relayed', async () => {\n await h.i.onClientTranscript({ Role: 'Assistant', Text: 'a real answer', IsFinal: true, Kind: 'normal' });\n\n let captions: Array<{ Role: string; Text: string }> = [];\n h.service.Captions$.subscribe(c => (captions = c)).unsubscribe();\n expect(captions).toEqual([{ Role: 'Assistant', Text: 'a real answer' }]);\n expect(h.executeGQL).toHaveBeenCalledWith(\n expect.stringContaining('RelayRealtimeTranscript'),\n expect.objectContaining({ role: 'assistant', text: 'a real answer' })\n );\n });\n\n it('interim (non-final) transcripts are ignored entirely', async () => {\n const narrations: VoiceDelegationNarration[] = [];\n h.service.DelegationNarration$.subscribe(n => narrations.push(n));\n\n await h.i.onClientTranscript({ Role: 'Assistant', Text: 'partial…', IsFinal: false, Kind: 'narration' });\n await h.i.onClientTranscript({ Role: 'Assistant', Text: 'partial…', IsFinal: false, Kind: 'normal' });\n\n expect(narrations).toEqual([]);\n expect(h.i.spokenNarrations).toEqual([]);\n expect(h.executeGQL).not.toHaveBeenCalled();\n });\n});\n\ndescribe('RealtimeSessionService — progress dispatch + stale filtering + push-status parsing', () => {\n let h: Harness;\n\n beforeEach(() => {\n vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout', 'Date'] });\n h = createHarness();\n });\n\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it('drops STALE progress for a CallID not in flight — no UI emission, no context note, no timer', () => {\n const seen: VoiceDelegationProgress[] = [];\n h.service.DelegationProgress$.subscribe(p => seen.push(p));\n\n progress(h, 'never-started', 'stale message');\n\n expect(seen).toEqual([]);\n expect(h.client.ContextNotes).toEqual([]);\n expect(h.i.narrationTimer).toBeNull();\n });\n\n it('drops progress that arrives AFTER the call completed (the PubSub-lag case)', async () => {\n const call = beginDelegation(h, 'c1');\n await completeDelegation(h, call);\n\n const seen: VoiceDelegationProgress[] = [];\n h.service.DelegationProgress$.subscribe(p => seen.push(p));\n progress(h, 'c1', 'too late');\n\n expect(seen).toEqual([]);\n expect(h.client.ContextNotes).toEqual([]);\n });\n\n it('emits in-flight progress on DelegationProgress$ AND feeds the model a context note', () => {\n void beginDelegation(h, 'c1');\n const seen: VoiceDelegationProgress[] = [];\n h.service.DelegationProgress$.subscribe(p => seen.push(p));\n\n progress(h, 'c1', 'live update');\n\n expect(seen).toEqual([{ CallID: 'c1', Step: 'subagent_execution', Message: 'live update' }]);\n expect(h.client.ContextNotes).toEqual(['[delegated-agent progress] live update']);\n });\n\n it('parses a matching push-status frame end-to-end (raw JSON → DelegationProgress$)', () => {\n h.i.subscribeDelegationProgress();\n void beginDelegation(h, 'c1');\n const seen: VoiceDelegationProgress[] = [];\n h.service.DelegationProgress$.subscribe(p => seen.push(p));\n\n h.pushStatus$.next(\n JSON.stringify({\n resolver: 'RealtimeClientSessionResolver',\n type: 'RealtimeDelegationProgress',\n agentSessionID: 'sess-1',\n callID: 'c1',\n step: 'prompt_execution',\n message: 'thinking hard',\n percentage: 42\n })\n );\n\n expect(seen).toEqual([{ CallID: 'c1', Step: 'prompt_execution', Message: 'thinking hard', Percentage: 42 }]);\n });\n\n it('ignores non-JSON frames and frames with the wrong resolver / type / session', () => {\n h.i.subscribeDelegationProgress();\n void beginDelegation(h, 'c1');\n const seen: VoiceDelegationProgress[] = [];\n h.service.DelegationProgress$.subscribe(p => seen.push(p));\n\n h.pushStatus$.next('not json at all');\n h.pushStatus$.next(JSON.stringify({ resolver: 'SomeOtherResolver', type: 'RealtimeDelegationProgress', agentSessionID: 'sess-1', callID: 'c1', step: 's', message: 'x' }));\n h.pushStatus$.next(JSON.stringify({ resolver: 'RealtimeClientSessionResolver', type: 'AgentRunProgress', agentSessionID: 'sess-1', callID: 'c1', step: 's', message: 'x' }));\n h.pushStatus$.next(JSON.stringify({ resolver: 'RealtimeClientSessionResolver', type: 'RealtimeDelegationProgress', agentSessionID: 'OTHER-session', callID: 'c1', step: 's', message: 'x' }));\n\n expect(seen).toEqual([]);\n expect(h.client.ContextNotes).toEqual([]);\n });\n\n it('subscribeDelegationProgress is idempotent for a session (one PushStatusUpdates subscription)', () => {\n const pushSpy = vi.spyOn(h.service.Provider as unknown as { PushStatusUpdates(id: string): unknown }, 'PushStatusUpdates');\n\n h.i.subscribeDelegationProgress();\n h.i.subscribeDelegationProgress();\n\n expect(pushSpy).toHaveBeenCalledTimes(1);\n });\n});\n\ndescribe('RealtimeSessionService — delegation lifecycle (thinking state, results, errors)', () => {\n let h: Harness;\n\n beforeEach(() => {\n vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout', 'Date'] });\n h = createHarness();\n });\n\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it('a server-relayed tool call flips the connection state to thinking', () => {\n const states: VoiceConnectionState[] = [];\n h.service.ConnectionState$.subscribe(s => states.push(s));\n\n void beginDelegation(h, 'c1');\n\n expect(states[states.length - 1]).toBe('thinking');\n });\n\n it('emits the parsed delegation result (incl. RunID) and feeds the raw JSON back to the model', async () => {\n const results: VoiceDelegationResult[] = [];\n h.service.DelegationResult$.subscribe(r => results.push(r));\n const call = beginDelegation(h, 'c1');\n\n await completeDelegation(h, call, '{\"success\":true,\"output\":\"all done\",\"runId\":\"run-9\"}');\n\n expect(results).toEqual([\n expect.objectContaining({ CallID: 'c1', Success: true, Output: 'all done', RunID: 'run-9' })\n ]);\n expect(h.client.ToolResults).toEqual([\n { CallID: 'c1', ResultJson: '{\"success\":true,\"output\":\"all done\",\"runId\":\"run-9\"}' }\n ]);\n expect(h.i.inFlightCallIds.size).toBe(0);\n });\n\n it('a tool-execution failure feeds an error payload to the model and surfaces the error as the result output', async () => {\n vi.spyOn(console, 'error').mockImplementation(() => undefined);\n const results: VoiceDelegationResult[] = [];\n h.service.DelegationResult$.subscribe(r => results.push(r));\n const call = beginDelegation(h, 'c1');\n\n h.pendingTools.shift()!.reject(new Error('broker down'));\n await call;\n\n expect(results).toHaveLength(1);\n expect(results[0]).toMatchObject({ CallID: 'c1', Output: 'broker down' });\n // The catch path serializes success:false (matching the server broker's failure\n // shape) so the overlay renders a FAILURE card — a coverage-exposed bug fix.\n expect(results[0].Success).toBe(false);\n expect(JSON.parse(h.client.ToolResults[0].ResultJson)).toEqual({ success: false, error: 'broker down' });\n expect(h.i.inFlightCallIds.size).toBe(0);\n });\n\n it('a SECOND tool call while one is in flight joins the SAME burst (no anchor reset)', () => {\n void beginDelegation(h, 'c1');\n const burstStart = h.i.delegationBurstStartedAt;\n vi.advanceTimersByTime(3000);\n\n void beginDelegation(h, 'c2');\n\n expect(h.i.delegationBurstStartedAt).toBe(burstStart); // inFlight was non-empty → same burst\n expect(h.i.inFlightCallIds.size).toBe(2);\n });\n\n it('TRUE BARGE-IN cancels pending narration (user took the floor) but leaves delegations in flight', () => {\n // capture the OnInterruption handler through the real wiring path\n let interrupt: (() => void) | null = null;\n const wiringClient = {\n OnStateChange: () => undefined,\n OnTranscript: () => undefined,\n OnToolCall: () => undefined,\n OnError: () => undefined,\n OnUsage: () => undefined,\n OnInterruption: (handler: () => void) => { interrupt = handler; }\n };\n h.i.wireClientHandlers(wiringClient);\n expect(interrupt).not.toBeNull();\n\n void beginDelegation(h, 'c1');\n h.i.dispatchProgress({ CallID: 'c1', Step: 'action_execution', Message: 'fetching data' });\n expect(h.i.pendingNarrationMessages).toEqual(['fetching data']);\n expect(h.i.narrationTimer).not.toBeNull();\n\n interrupt!();\n\n expect(h.i.pendingNarrationMessages).toEqual([]); // stale narration discarded\n expect(h.i.narrationTimer).toBeNull();\n expect(h.i.inFlightCallIds.has('c1')).toBe(true); // the delegated run keeps running\n vi.advanceTimersByTime(20000);\n expect(h.client.SpokenUpdates).toEqual([]); // nothing stale ever spoken\n });\n});"]}
@@ -0,0 +1,2 @@
1
+ import '@angular/compiler';
2
+ //# sourceMappingURL=whiteboard-artifact-viewer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whiteboard-artifact-viewer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/whiteboard-artifact-viewer.test.ts"],"names":[],"mappings":"AAEA,OAAO,mBAAmB,CAAC"}
@@ -0,0 +1,101 @@
1
+ // The plugin imports Angular surface components (partial-compiled Angular libs require
2
+ // the JIT compiler in this node test environment), so load the compiler FIRST.
3
+ import '@angular/compiler';
4
+ import { describe, it, expect } from 'vitest';
5
+ import { MJGlobal } from '@memberjunction/global';
6
+ import { BaseArtifactViewerPluginComponent } from '@memberjunction/ng-artifacts';
7
+ import { ParseBoardStateJson, WhiteboardState } from '@memberjunction/ng-whiteboard';
8
+ import { WhiteboardArtifactViewerComponent, LoadWhiteboardArtifactViewer } from '../lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component';
9
+ /**
10
+ * The whiteboard ARTIFACT VIEWER plugin + read-only snapshot helper — the pure
11
+ * ParseBoardStateJson parse contract (tolerant of malformed payloads), the ClassFactory
12
+ * registration the artifact plugin host resolves by DriverClass, and the plugin's
13
+ * content-driven state (hasDisplayContent / GetCurrentStateSnapshot) using a STRUCTURAL
14
+ * fake artifact version (the real entity requires a metadata provider).
15
+ */
16
+ /** Build a persisted board payload with one agent note + one user text item. */
17
+ function buildBoardJson() {
18
+ const state = new WhiteboardState();
19
+ state.AddItem({ Kind: 'sticky', X: 10, Y: 20, Text: 'agent note' }, 'agent');
20
+ state.AddItem({ Kind: 'text', X: 100, Y: 40, Text: 'user label' }, 'user');
21
+ return state.ToJSON();
22
+ }
23
+ /** Structural stand-in for the artifact version (plugin only reads Content + Name). */
24
+ function fakeVersion(content, name = null) {
25
+ return { Content: content, Name: name };
26
+ }
27
+ describe('ParseBoardStateJson — tolerant parse of persisted board payloads', () => {
28
+ it('round-trips ToJSON output into a rehydrated WhiteboardState', () => {
29
+ const parsed = ParseBoardStateJson(buildBoardJson());
30
+ expect(parsed).toBeInstanceOf(WhiteboardState);
31
+ expect(parsed?.ElementCount).toBe(2);
32
+ expect(parsed?.CountByAuthor('agent')).toBe(1);
33
+ expect(parsed?.CountByAuthor('user')).toBe(1);
34
+ });
35
+ it('returns null for empty / null / whitespace input', () => {
36
+ expect(ParseBoardStateJson(null)).toBeNull();
37
+ expect(ParseBoardStateJson(undefined)).toBeNull();
38
+ expect(ParseBoardStateJson('')).toBeNull();
39
+ expect(ParseBoardStateJson(' ')).toBeNull();
40
+ });
41
+ it('returns null for non-JSON input instead of throwing', () => {
42
+ expect(ParseBoardStateJson('not json at all {')).toBeNull();
43
+ });
44
+ it('returns null for valid JSON of the wrong shape (no items array)', () => {
45
+ expect(ParseBoardStateJson('{"foo": 1}')).toBeNull();
46
+ expect(ParseBoardStateJson('"just a string"')).toBeNull();
47
+ });
48
+ });
49
+ describe('WhiteboardArtifactViewerComponent — plugin contract', () => {
50
+ it('is resolvable from the ClassFactory by its DriverClass key', () => {
51
+ LoadWhiteboardArtifactViewer();
52
+ const registration = MJGlobal.Instance.ClassFactory.GetRegistration(BaseArtifactViewerPluginComponent, 'WhiteboardArtifactViewerPlugin');
53
+ expect(registration).toBeTruthy();
54
+ expect(registration?.SubClass).toBe(WhiteboardArtifactViewerComponent);
55
+ // the artifact plugin host instantiates with a bare `new` (outside an Angular
56
+ // injection context) to discover the component type — that path must not throw
57
+ const instance = MJGlobal.Instance.ClassFactory.CreateInstance(BaseArtifactViewerPluginComponent, 'WhiteboardArtifactViewerPlugin');
58
+ expect(instance).toBeInstanceOf(WhiteboardArtifactViewerComponent);
59
+ });
60
+ it('exposes board-driven display state: content parses → hasDisplayContent true', () => {
61
+ const viewer = new WhiteboardArtifactViewerComponent();
62
+ viewer.artifactVersion = fakeVersion(buildBoardJson(), 'Sprint Board');
63
+ expect(viewer.HasBoard).toBe(true);
64
+ expect(viewer.hasDisplayContent).toBe(true);
65
+ expect(viewer.ContentJson).toBe(viewer.artifactVersion.Content);
66
+ expect(viewer.BoardState?.ElementCount).toBe(2);
67
+ });
68
+ it('malformed / missing content → no board, no display content, null snapshot', () => {
69
+ const viewer = new WhiteboardArtifactViewerComponent();
70
+ viewer.artifactVersion = fakeVersion('{"broken":');
71
+ expect(viewer.HasBoard).toBe(false);
72
+ expect(viewer.hasDisplayContent).toBe(false);
73
+ expect(viewer.GetCurrentStateSnapshot()).toBeNull();
74
+ });
75
+ it('re-parses when the artifact version content changes (memo keyed by content)', () => {
76
+ const viewer = new WhiteboardArtifactViewerComponent();
77
+ viewer.artifactVersion = fakeVersion(buildBoardJson());
78
+ const first = viewer.BoardState;
79
+ expect(first).toBe(viewer.BoardState); // memoized — same instance for same content
80
+ const single = new WhiteboardState();
81
+ single.AddItem({ Kind: 'text', X: 0, Y: 0, Text: 'v2' }, 'user');
82
+ viewer.artifactVersion = fakeVersion(single.ToJSON());
83
+ expect(viewer.BoardState).not.toBe(first);
84
+ expect(viewer.BoardState?.ElementCount).toBe(1);
85
+ });
86
+ it('GetCurrentStateSnapshot reports the board scene: title, summary, element counts', () => {
87
+ const viewer = new WhiteboardArtifactViewerComponent();
88
+ viewer.artifactVersion = fakeVersion(buildBoardJson(), 'Sprint Board');
89
+ const snap = viewer.GetCurrentStateSnapshot();
90
+ expect(snap).not.toBeNull();
91
+ expect(snap?.title).toBe('Sprint Board');
92
+ expect(snap?.interpretation).toContain('2 elements');
93
+ expect(snap?.custom?.['elementCounts']).toMatchObject({ total: 2, user: 1, agent: 1 });
94
+ });
95
+ it('falls back to a generic title when the artifact version has no name', () => {
96
+ const viewer = new WhiteboardArtifactViewerComponent();
97
+ viewer.artifactVersion = fakeVersion(buildBoardJson());
98
+ expect(viewer.GetCurrentStateSnapshot()?.title).toBe('Whiteboard');
99
+ });
100
+ });
101
+ //# sourceMappingURL=whiteboard-artifact-viewer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whiteboard-artifact-viewer.test.js","sourceRoot":"","sources":["../../src/__tests__/whiteboard-artifact-viewer.test.ts"],"names":[],"mappings":"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","sourcesContent":["// The plugin imports Angular surface components (partial-compiled Angular libs require\n// the JIT compiler in this node test environment), so load the compiler FIRST.\nimport '@angular/compiler';\nimport { describe, it, expect } from 'vitest';\nimport { MJGlobal } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent } from '@memberjunction/ng-artifacts';\nimport { MJArtifactVersionEntity } from '@memberjunction/core-entities';\nimport { ParseBoardStateJson, WhiteboardState } from '@memberjunction/ng-whiteboard';\nimport { WhiteboardArtifactViewerComponent, LoadWhiteboardArtifactViewer } from '../lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component';\n\n/**\n * The whiteboard ARTIFACT VIEWER plugin + read-only snapshot helper — the pure\n * ParseBoardStateJson parse contract (tolerant of malformed payloads), the ClassFactory\n * registration the artifact plugin host resolves by DriverClass, and the plugin's\n * content-driven state (hasDisplayContent / GetCurrentStateSnapshot) using a STRUCTURAL\n * fake artifact version (the real entity requires a metadata provider).\n */\n\n/** Build a persisted board payload with one agent note + one user text item. */\nfunction buildBoardJson(): string {\n const state = new WhiteboardState();\n state.AddItem({ Kind: 'sticky', X: 10, Y: 20, Text: 'agent note' }, 'agent');\n state.AddItem({ Kind: 'text', X: 100, Y: 40, Text: 'user label' }, 'user');\n return state.ToJSON();\n}\n\n/** Structural stand-in for the artifact version (plugin only reads Content + Name). */\nfunction fakeVersion(content: string | null, name: string | null = null): MJArtifactVersionEntity {\n return { Content: content, Name: name } as unknown as MJArtifactVersionEntity;\n}\n\ndescribe('ParseBoardStateJson — tolerant parse of persisted board payloads', () => {\n it('round-trips ToJSON output into a rehydrated WhiteboardState', () => {\n const parsed = ParseBoardStateJson(buildBoardJson());\n expect(parsed).toBeInstanceOf(WhiteboardState);\n expect(parsed?.ElementCount).toBe(2);\n expect(parsed?.CountByAuthor('agent')).toBe(1);\n expect(parsed?.CountByAuthor('user')).toBe(1);\n });\n\n it('returns null for empty / null / whitespace input', () => {\n expect(ParseBoardStateJson(null)).toBeNull();\n expect(ParseBoardStateJson(undefined)).toBeNull();\n expect(ParseBoardStateJson('')).toBeNull();\n expect(ParseBoardStateJson(' ')).toBeNull();\n });\n\n it('returns null for non-JSON input instead of throwing', () => {\n expect(ParseBoardStateJson('not json at all {')).toBeNull();\n });\n\n it('returns null for valid JSON of the wrong shape (no items array)', () => {\n expect(ParseBoardStateJson('{\"foo\": 1}')).toBeNull();\n expect(ParseBoardStateJson('\"just a string\"')).toBeNull();\n });\n});\n\ndescribe('WhiteboardArtifactViewerComponent — plugin contract', () => {\n it('is resolvable from the ClassFactory by its DriverClass key', () => {\n LoadWhiteboardArtifactViewer();\n const registration = MJGlobal.Instance.ClassFactory.GetRegistration(BaseArtifactViewerPluginComponent, 'WhiteboardArtifactViewerPlugin');\n expect(registration).toBeTruthy();\n expect(registration?.SubClass).toBe(WhiteboardArtifactViewerComponent);\n\n // the artifact plugin host instantiates with a bare `new` (outside an Angular\n // injection context) to discover the component type — that path must not throw\n const instance = MJGlobal.Instance.ClassFactory.CreateInstance<BaseArtifactViewerPluginComponent>(\n BaseArtifactViewerPluginComponent, 'WhiteboardArtifactViewerPlugin'\n );\n expect(instance).toBeInstanceOf(WhiteboardArtifactViewerComponent);\n });\n\n it('exposes board-driven display state: content parses → hasDisplayContent true', () => {\n const viewer = new WhiteboardArtifactViewerComponent();\n viewer.artifactVersion = fakeVersion(buildBoardJson(), 'Sprint Board');\n\n expect(viewer.HasBoard).toBe(true);\n expect(viewer.hasDisplayContent).toBe(true);\n expect(viewer.ContentJson).toBe(viewer.artifactVersion.Content);\n expect(viewer.BoardState?.ElementCount).toBe(2);\n });\n\n it('malformed / missing content → no board, no display content, null snapshot', () => {\n const viewer = new WhiteboardArtifactViewerComponent();\n viewer.artifactVersion = fakeVersion('{\"broken\":');\n\n expect(viewer.HasBoard).toBe(false);\n expect(viewer.hasDisplayContent).toBe(false);\n expect(viewer.GetCurrentStateSnapshot()).toBeNull();\n });\n\n it('re-parses when the artifact version content changes (memo keyed by content)', () => {\n const viewer = new WhiteboardArtifactViewerComponent();\n viewer.artifactVersion = fakeVersion(buildBoardJson());\n const first = viewer.BoardState;\n expect(first).toBe(viewer.BoardState); // memoized — same instance for same content\n\n const single = new WhiteboardState();\n single.AddItem({ Kind: 'text', X: 0, Y: 0, Text: 'v2' }, 'user');\n viewer.artifactVersion = fakeVersion(single.ToJSON());\n expect(viewer.BoardState).not.toBe(first);\n expect(viewer.BoardState?.ElementCount).toBe(1);\n });\n\n it('GetCurrentStateSnapshot reports the board scene: title, summary, element counts', () => {\n const viewer = new WhiteboardArtifactViewerComponent();\n viewer.artifactVersion = fakeVersion(buildBoardJson(), 'Sprint Board');\n\n const snap = viewer.GetCurrentStateSnapshot();\n expect(snap).not.toBeNull();\n expect(snap?.title).toBe('Sprint Board');\n expect(snap?.interpretation).toContain('2 elements');\n expect(snap?.custom?.['elementCounts']).toMatchObject({ total: 2, user: 1, agent: 1 });\n });\n\n it('falls back to a generic title when the artifact version has no name', () => {\n const viewer = new WhiteboardArtifactViewerComponent();\n viewer.artifactVersion = fakeVersion(buildBoardJson());\n expect(viewer.GetCurrentStateSnapshot()?.title).toBe('Whiteboard');\n });\n});\n"]}
@@ -0,0 +1,2 @@
1
+ import '@angular/compiler';
2
+ //# sourceMappingURL=whiteboard-channel.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whiteboard-channel.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/whiteboard-channel.test.ts"],"names":[],"mappings":"AAEA,OAAO,mBAAmB,CAAC"}
@@ -0,0 +1,260 @@
1
+ // The whiteboard channel imports its Angular surface component (partial-compiled Angular
2
+ // libs require the JIT compiler in this node test environment), so load the compiler FIRST.
3
+ import '@angular/compiler';
4
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
5
+ import { EventEmitter } from '@angular/core';
6
+ import { MJGlobal } from '@memberjunction/global';
7
+ import { BaseRealtimeChannelClient } from '../lib/components/realtime/channels/base-realtime-channel-client';
8
+ import { RealtimeWhiteboardChannel, WHITEBOARD_INTERACTION_NOTE_THROTTLE_MS } from '../lib/components/realtime/whiteboard/whiteboard-channel';
9
+ import { RealtimeWhiteboardHostComponent, WHITEBOARD_TOOL_DEFINITIONS, WHITEBOARD_TOOL_PREFIX } from '@memberjunction/ng-whiteboard';
10
+ /**
11
+ * The LIVE WHITEBOARD as a registry plugin — contract metadata, ClassFactory registration,
12
+ * the no-surface ApplyAgentTool fallback (panel collapsed), surface binding/unbinding, the
13
+ * save-on-mutation pipeline and Dispose. The "surface" here is a STRUCTURAL fake (the real
14
+ * component needs an Angular injection context); the plugin only touches the members the
15
+ * fake provides.
16
+ */
17
+ /** Structural stand-in for the bound board host. */
18
+ class FakeWhiteboardHost {
19
+ State = null;
20
+ AgentName = '';
21
+ FocusMode = false;
22
+ SceneDelta = new EventEmitter();
23
+ AgentUndo = new EventEmitter();
24
+ FocusModeChange = new EventEmitter();
25
+ SaveToArtifactsRequested = new EventEmitter();
26
+ WidgetSubmitted = new EventEmitter();
27
+ WidgetInteraction = new EventEmitter();
28
+ AppliedTools = [];
29
+ ApplyAgentTool(toolName, argsJson) {
30
+ this.AppliedTools.push({ ToolName: toolName, ArgsJson: argsJson });
31
+ return JSON.stringify({ success: true, itemId: 'host-item', summary: 'host applied' });
32
+ }
33
+ ToggleFocus() {
34
+ this.FocusMode = !this.FocusMode;
35
+ this.FocusModeChange.emit(this.FocusMode);
36
+ }
37
+ }
38
+ function asHost(fake) {
39
+ return fake;
40
+ }
41
+ function makeContext(log) {
42
+ return {
43
+ AgentName: 'Sage',
44
+ SendContextNote: (text) => log.Notes.push(text),
45
+ RequestSpokenResponse: (instructions) => log.Spoken.push(instructions),
46
+ RequestSave: (stateJson) => log.Saves.push(stateJson),
47
+ SetFocusMode: (on) => log.Focus.push(on),
48
+ SaveAsArtifact: async () => null,
49
+ AgentSessionID: null,
50
+ ExecuteServerAction: async () => null
51
+ };
52
+ }
53
+ describe('RealtimeWhiteboardChannel — plugin contract', () => {
54
+ let channel;
55
+ let log;
56
+ beforeEach(() => {
57
+ channel = new RealtimeWhiteboardChannel();
58
+ log = { Notes: [], Spoken: [], Saves: [], Focus: [] };
59
+ channel.Initialize(makeContext(log));
60
+ });
61
+ it('is resolvable from the ClassFactory by its registry ClientPluginClass key', () => {
62
+ const registration = MJGlobal.Instance.ClassFactory.GetRegistration(BaseRealtimeChannelClient, 'RealtimeWhiteboardChannel');
63
+ expect(registration).toBeTruthy();
64
+ const instance = MJGlobal.Instance.ClassFactory.CreateInstance(BaseRealtimeChannelClient, 'RealtimeWhiteboardChannel');
65
+ expect(instance).toBeInstanceOf(RealtimeWhiteboardChannel);
66
+ });
67
+ it('contributes the channel contract: name, prefix, tab chrome, tool set, surface', () => {
68
+ expect(channel.ChannelName).toBe('Whiteboard');
69
+ expect(channel.ToolNamePrefix).toBe(WHITEBOARD_TOOL_PREFIX);
70
+ expect(channel.TabTitle).toBe('Whiteboard');
71
+ expect(channel.TabIcon).toBe('fa-solid fa-chalkboard');
72
+ expect(channel.GetToolDefinitions()).toBe(WHITEBOARD_TOOL_DEFINITIONS);
73
+ expect(channel.GetSurfaceComponent()).toBe(RealtimeWhiteboardHostComponent);
74
+ });
75
+ it('supplies first-run onboarding details (heading, description, tips, icon)', () => {
76
+ const details = channel.GetOnboardingDetails();
77
+ expect(details).not.toBeNull();
78
+ expect(details?.Heading).toBe('Whiteboard');
79
+ expect(details?.IconClass).toBe('fa-solid fa-chalkboard');
80
+ expect(details?.Description?.length).toBeGreaterThan(0);
81
+ expect((details?.Tips?.length ?? 0)).toBeGreaterThan(0);
82
+ });
83
+ it('ApplyAgentTool with NO surface bound falls back to the pure engine (collapsed panel)', () => {
84
+ const resultJson = channel.ApplyAgentTool('Whiteboard_AddNote', JSON.stringify({ text: 'hello' }));
85
+ const result = JSON.parse(resultJson);
86
+ expect(result.success).toBe(true);
87
+ expect(channel.State.ElementCount).toBe(1);
88
+ expect(channel.State.CountByAuthor('agent')).toBe(1);
89
+ });
90
+ it('every board mutation requests a state-of-record save (user edits AND agent tools)', () => {
91
+ channel.ApplyAgentTool('Whiteboard_AddNote', JSON.stringify({ text: 'note' }));
92
+ expect(log.Saves.length).toBeGreaterThan(0);
93
+ const lastSave = JSON.parse(log.Saves[log.Saves.length - 1]);
94
+ expect(JSON.stringify(lastSave)).toBe(channel.SerializeState());
95
+ });
96
+ it('BindSurface wires inputs + outputs; tools then route through the host (UI garnish path)', () => {
97
+ const fake = new FakeWhiteboardHost();
98
+ channel.BindSurface(asHost(fake));
99
+ expect(fake.State).toBe(channel.State);
100
+ expect(fake.AgentName).toBe('Sage');
101
+ const resultJson = channel.ApplyAgentTool('Whiteboard_AddNote', JSON.stringify({ text: 'via host' }));
102
+ expect(fake.AppliedTools).toEqual([{ ToolName: 'Whiteboard_AddNote', ArgsJson: JSON.stringify({ text: 'via host' }) }]);
103
+ expect(JSON.parse(resultJson).itemId).toBe('host-item');
104
+ fake.SceneDelta.emit('{"added":[1]}');
105
+ fake.AgentUndo.emit();
106
+ fake.FocusModeChange.emit(true);
107
+ // scene deltas carry the perception ETIQUETTE inline (don't comment on minor edits)
108
+ expect(log.Notes).toHaveLength(2);
109
+ expect(log.Notes[0]).toContain('[whiteboard] board update');
110
+ expect(log.Notes[0]).toContain('do NOT comment on minor edits');
111
+ expect(log.Notes[0]).toContain('{"added":[1]}');
112
+ expect(log.Notes[1]).toBe('[whiteboard] user undid your last change');
113
+ expect(log.Focus).toEqual([true]);
114
+ });
115
+ it('routes widget MJWhiteboard.submit input to the agent as a [whiteboard] context note', () => {
116
+ const fake = new FakeWhiteboardHost();
117
+ channel.BindSurface(asHost(fake));
118
+ fake.WidgetSubmitted.emit({ ItemID: 'html-2', Title: 'Quick quiz', DataJson: '{"answer":"Mercury"}' });
119
+ expect(log.Notes).toHaveLength(1);
120
+ expect(log.Notes[0]).toBe('[whiteboard] the user submitted input in widget "Quick quiz": {"answer":"Mercury"}');
121
+ // …and the model is asked to REACT audibly (SendContextNote alone is silent by contract)
122
+ expect(log.Spoken).toHaveLength(1);
123
+ expect(log.Spoken[0]).toContain('Quick quiz');
124
+ expect(log.Spoken[0]).toContain('{"answer":"Mercury"}');
125
+ expect(log.Spoken[0]).toContain('React to it now');
126
+ // untitled widgets fall back to the item ID
127
+ fake.WidgetSubmitted.emit({ ItemID: 'html-3', Title: '', DataJson: '{"ok":true}' });
128
+ expect(log.Notes[1]).toBe('[whiteboard] the user submitted input in widget "html-3": {"ok":true}');
129
+ // released with the surface, like the other output subscriptions
130
+ channel.UnbindSurface();
131
+ fake.WidgetSubmitted.emit({ ItemID: 'html-2', Title: 'Quick quiz', DataJson: '{"stale":true}' });
132
+ expect(log.Notes).toHaveLength(2);
133
+ });
134
+ describe('ambient widget-interaction notes — per-widget throttle (latest wins)', () => {
135
+ function interaction(itemId, summary, title = 'Vibe picker') {
136
+ return { ItemID: itemId, Title: title, Summary: summary };
137
+ }
138
+ beforeEach(() => {
139
+ vi.useFakeTimers();
140
+ });
141
+ afterEach(() => {
142
+ vi.useRealTimers();
143
+ });
144
+ it('first activity in a widget sends a note IMMEDIATELY with the ambient framing', () => {
145
+ const fake = new FakeWhiteboardHost();
146
+ channel.BindSurface(asHost(fake));
147
+ fake.WidgetInteraction.emit(interaction('html-2', 'clicked "Playful pink"; changed "vibe" to "pink"'));
148
+ expect(log.Notes).toHaveLength(1);
149
+ expect(log.Notes[0]).toBe('[whiteboard] ambient activity in widget "Vibe picker" ' +
150
+ '(background — do NOT respond unless it is significant or you are asked; ' +
151
+ 'explicit submissions arrive separately): clicked "Playful pink"; changed "vibe" to "pink"');
152
+ });
153
+ it('untitled widgets fall back to the item ID in the framing', () => {
154
+ const fake = new FakeWhiteboardHost();
155
+ channel.BindSurface(asHost(fake));
156
+ fake.WidgetInteraction.emit(interaction('html-7', 'typing in "email"', ''));
157
+ expect(log.Notes[0]).toContain('ambient activity in widget "html-7"');
158
+ });
159
+ it('within the window further activity coalesces — ONE trailing note, LATEST summary wins', () => {
160
+ const fake = new FakeWhiteboardHost();
161
+ channel.BindSurface(asHost(fake));
162
+ fake.WidgetInteraction.emit(interaction('html-2', 'first'));
163
+ fake.WidgetInteraction.emit(interaction('html-2', 'second'));
164
+ fake.WidgetInteraction.emit(interaction('html-2', 'third'));
165
+ expect(log.Notes).toHaveLength(1); // only the immediate first note so far
166
+ vi.advanceTimersByTime(WHITEBOARD_INTERACTION_NOTE_THROTTLE_MS);
167
+ expect(log.Notes).toHaveLength(2);
168
+ expect(log.Notes[1]).toContain(': third'); // latest summary won
169
+ expect(log.Notes.some((n) => n.includes(': second'))).toBe(false);
170
+ });
171
+ it('the trailing send opens a NEW window — chatty widgets stay at ≤1 note per window', () => {
172
+ const fake = new FakeWhiteboardHost();
173
+ channel.BindSurface(asHost(fake));
174
+ fake.WidgetInteraction.emit(interaction('html-2', 'a')); // sent immediately
175
+ fake.WidgetInteraction.emit(interaction('html-2', 'b')); // deferred
176
+ vi.advanceTimersByTime(WHITEBOARD_INTERACTION_NOTE_THROTTLE_MS); // 'b' sent
177
+ fake.WidgetInteraction.emit(interaction('html-2', 'c')); // inside b's window → deferred
178
+ expect(log.Notes).toHaveLength(2);
179
+ vi.advanceTimersByTime(WHITEBOARD_INTERACTION_NOTE_THROTTLE_MS);
180
+ expect(log.Notes).toHaveLength(3);
181
+ expect(log.Notes[2]).toContain(': c');
182
+ });
183
+ it('after a QUIET window expires, the next activity sends immediately again', () => {
184
+ const fake = new FakeWhiteboardHost();
185
+ channel.BindSurface(asHost(fake));
186
+ fake.WidgetInteraction.emit(interaction('html-2', 'early'));
187
+ vi.advanceTimersByTime(WHITEBOARD_INTERACTION_NOTE_THROTTLE_MS + 1);
188
+ fake.WidgetInteraction.emit(interaction('html-2', 'late'));
189
+ expect(log.Notes).toHaveLength(2);
190
+ expect(log.Notes[1]).toContain(': late');
191
+ });
192
+ it('throttles PER WIDGET — concurrent widgets do not share a window', () => {
193
+ const fake = new FakeWhiteboardHost();
194
+ channel.BindSurface(asHost(fake));
195
+ fake.WidgetInteraction.emit(interaction('html-2', 'in widget two'));
196
+ fake.WidgetInteraction.emit(interaction('html-3', 'in widget three', 'Other'));
197
+ expect(log.Notes).toHaveLength(2);
198
+ expect(log.Notes[0]).toContain('"Vibe picker"');
199
+ expect(log.Notes[1]).toContain('"Other"');
200
+ });
201
+ it('UnbindSurface cancels pending trailing notes (nothing stale reaches the agent)', () => {
202
+ const fake = new FakeWhiteboardHost();
203
+ channel.BindSurface(asHost(fake));
204
+ fake.WidgetInteraction.emit(interaction('html-2', 'sent'));
205
+ fake.WidgetInteraction.emit(interaction('html-2', 'pending'));
206
+ channel.UnbindSurface();
207
+ vi.advanceTimersByTime(WHITEBOARD_INTERACTION_NOTE_THROTTLE_MS * 2);
208
+ expect(log.Notes).toHaveLength(1); // the pending trailing note was canceled
209
+ // and the released surface's emitter no longer reaches the channel at all
210
+ fake.WidgetInteraction.emit(interaction('html-2', 'stale'));
211
+ expect(log.Notes).toHaveLength(1);
212
+ });
213
+ });
214
+ it('UnbindSurface flips back to the engine fallback and stops listening to old outputs', () => {
215
+ const fake = new FakeWhiteboardHost();
216
+ channel.BindSurface(asHost(fake));
217
+ channel.UnbindSurface();
218
+ channel.ApplyAgentTool('Whiteboard_AddNote', JSON.stringify({ text: 'after unbind' }));
219
+ expect(fake.AppliedTools).toEqual([]); // host no longer consulted
220
+ expect(channel.State.ElementCount).toBe(1); // engine applied it
221
+ fake.SceneDelta.emit('{"stale":true}');
222
+ expect(log.Notes).toEqual([]); // old subscription released
223
+ });
224
+ it('re-binding a NEW surface replaces the old one (pane recreated after collapse/expand)', () => {
225
+ const first = new FakeWhiteboardHost();
226
+ const second = new FakeWhiteboardHost();
227
+ channel.BindSurface(asHost(first));
228
+ channel.BindSurface(asHost(second));
229
+ channel.ApplyAgentTool('Whiteboard_AddText', JSON.stringify({ text: 'x' }));
230
+ expect(first.AppliedTools).toEqual([]);
231
+ expect(second.AppliedTools).toHaveLength(1);
232
+ first.SceneDelta.emit('{"old":true}');
233
+ expect(log.Notes).toEqual([]); // first surface's outputs were unsubscribed
234
+ });
235
+ it('RequestFocusExit leaves focus THROUGH the bound host so its toggle stays in sync', () => {
236
+ const fake = new FakeWhiteboardHost();
237
+ channel.BindSurface(asHost(fake));
238
+ fake.ToggleFocus(); // enter focus → SetFocusMode(true)
239
+ expect(log.Focus).toEqual([true]);
240
+ channel.RequestFocusExit();
241
+ expect(fake.FocusMode).toBe(false);
242
+ expect(log.Focus).toEqual([true, false]);
243
+ channel.RequestFocusExit(); // not in focus → no double-toggle
244
+ expect(log.Focus).toEqual([true, false]);
245
+ });
246
+ it('Dispose releases the surface, the state subscription and the context', () => {
247
+ const fake = new FakeWhiteboardHost();
248
+ channel.BindSurface(asHost(fake));
249
+ channel.Dispose();
250
+ // State mutations no longer request saves…
251
+ const savesBefore = log.Saves.length;
252
+ channel.State.AddItem({ Kind: 'text', X: 0, Y: 0, Text: 'post-dispose' }, 'user');
253
+ expect(log.Saves.length).toBe(savesBefore);
254
+ // …and tool calls fall back to the engine (no host).
255
+ const spy = vi.spyOn(fake, 'ApplyAgentTool');
256
+ channel.ApplyAgentTool('Whiteboard_AddNote', JSON.stringify({ text: 'still works' }));
257
+ expect(spy).not.toHaveBeenCalled();
258
+ });
259
+ });
260
+ //# sourceMappingURL=whiteboard-channel.test.js.map