@memberjunction/ng-conversations 5.40.1 → 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
@@ -1 +1 @@
1
- {"version":3,"file":"message-list.component.js","sourceRoot":"","sources":["../../../../src/lib/components/message/message-list.component.ts","../../../../src/lib/components/message/message-list.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n ViewChild,\n ViewContainerRef,\n OnInit,\n OnDestroy,\n OnChanges,\n SimpleChanges,\n ChangeDetectorRef,\n ElementRef,\n AfterViewInit,\n AfterViewChecked\n} from '@angular/core';\nimport { MJConversationDetailEntity, MJConversationEntity, RatingJSON } from '@memberjunction/core-entities';\nimport { UserInfo, CompositeKey } from '@memberjunction/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MessageItemComponent, MessageAttachment } from './message-item.component';\nimport { LazyArtifactInfo } from '../../models/lazy-artifact-info';\nimport { selectDistinctLatestArtifacts } from '../../utils/distinct-artifacts';\nimport { MJAIAgentRunEntityExtended } from '@memberjunction/ai-core-plus';\n\n/**\n * Container component for displaying a list of messages\n * Uses dynamic component creation (like skip-chat) to avoid Angular binding overhead\n * This dramatically improves performance when messages are added/removed\n */\n@Component({\n standalone: false,\n selector: 'mj-conversation-message-list',\n templateUrl: './message-list.component.html',\n styleUrls: ['./message-list.component.css']\n})\nexport class MessageListComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit, AfterViewChecked {\n @Input() public messages: MJConversationDetailEntity[] = [];\n @Input() public conversation!: MJConversationEntity | null;\n @Input() public currentUser!: UserInfo;\n @Input() public isProcessing: boolean = false;\n @Input() public artifactMap: Map<string, LazyArtifactInfo[]> = new Map();\n @Input() public agentRunMap: Map<string, MJAIAgentRunEntityExtended> = new Map();\n @Input() public ratingsMap: Map<string, RatingJSON[]> = new Map();\n @Input() public userAvatarMap: Map<string, {imageUrl: string | null; iconClass: string | null}> = new Map();\n @Input() public attachmentsMap: Map<string, MessageAttachment[]> = new Map();\n\n @Output() public editMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public deleteMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public retryMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public testFeedbackMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public artifactClicked = new EventEmitter<{artifactId: string; versionId?: string}>();\n @Output() public replyInThread = new EventEmitter<MJConversationDetailEntity>();\n @Output() public viewThread = new EventEmitter<MJConversationDetailEntity>();\n @Output() public messageEdited = new EventEmitter<MJConversationDetailEntity>();\n @Output() public openEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n @Output() public suggestedResponseSelected = new EventEmitter<{text: string; customInput?: string}>();\n @Output() public attachmentClicked = new EventEmitter<MessageAttachment>();\n @Output() public diagnosticRequested = new EventEmitter<string>(); // emits messageId\n @Output() public messagePinToggled = new EventEmitter<MJConversationDetailEntity>();\n\n @ViewChild('messageContainer', { read: ViewContainerRef }) messageContainerRef!: ViewContainerRef;\n @ViewChild('scrollContainer') scrollContainer!: ElementRef;\n\n private _renderedMessages = new Map<string, any>();\n private _shouldScrollToBottom = false;\n private _previousMessageCount = 0; // Track previous count to detect new messages\n\n public currentDateDisplay: string = 'Today';\n public showDateNav: boolean = false;\n public shouldShowDateFilter: boolean = false;\n\n constructor(private cdRef: ChangeDetectorRef) {\n super();\n }\n\n public toggleDateNav(): void {\n this.showDateNav = !this.showDateNav;\n }\n\n public jumpToDate(period: string): void {\n // TODO: Implement date jumping logic\n console.log('Jump to date:', period);\n this.showDateNav = false;\n\n // Update display based on period\n switch(period) {\n case 'today':\n this.currentDateDisplay = 'Today';\n break;\n case 'yesterday':\n this.currentDateDisplay = 'Yesterday';\n break;\n case 'last-week':\n this.currentDateDisplay = 'Last week';\n break;\n case 'last-month':\n this.currentDateDisplay = 'Last month';\n break;\n }\n }\n\n // Track whether initial render has happened\n private _initialRenderComplete = false;\n\n ngOnInit() {\n // Initial render will happen in ngAfterViewInit when ViewContainerRef is available\n }\n\n ngAfterViewInit() {\n // ViewContainerRef is now available - perform initial render if we have messages\n if (this.messages && this.messages.length > 0 && this.messageContainerRef && !this._initialRenderComplete) {\n this._initialRenderComplete = true;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // React to messages array changes\n // Note: On initial load, messageContainerRef may not be available yet (ngOnChanges runs before ngAfterViewInit)\n // In that case, ngAfterViewInit will handle the initial render\n if (changes['messages'] && this.messages && this.messageContainerRef) {\n this._initialRenderComplete = true;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n\n // Watch for artifactMap changes to handle newly created artifacts\n // While artifacts are pre-loaded during initial peripheral data load,\n // new artifacts can be created mid-conversation (e.g., by agent runs)\n // This ensures artifact cards appear in messages immediately without requiring a refresh\n if (changes['artifactMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for attachmentsMap changes to handle newly created attachments\n // This ensures media attachments (e.g., images generated by agents) appear\n // immediately without requiring a page refresh\n if (changes['attachmentsMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n }\n\n ngAfterViewChecked() {\n if (this._shouldScrollToBottom) {\n this.scrollToBottom();\n this._shouldScrollToBottom = false;\n }\n }\n\n ngOnDestroy() {\n // Clean up all dynamically created components\n this._renderedMessages.forEach((componentRef) => {\n if (componentRef) {\n componentRef.destroy();\n }\n });\n this._renderedMessages.clear();\n\n if (this.messageContainerRef) {\n this.messageContainerRef.clear();\n }\n }\n\n /**\n * Called when messages array changes\n * Efficiently updates the DOM without re-rendering everything\n */\n @Input()\n set messagesUpdate(messages: MJConversationDetailEntity[]) {\n if (messages && this.messageContainerRef) {\n this.updateMessages(messages);\n }\n }\n\n /**\n * Updates the message list using dynamic component creation\n * Only adds/removes changed messages for optimal performance\n */\n private updateMessages(messages: MJConversationDetailEntity[]): void {\n // Temporarily detach change detection for performance\n this.cdRef.detach();\n\n try {\n // Remove messages that no longer exist\n const currentIds = new Set(messages.map(m => this.getMessageKey(m)));\n this._renderedMessages.forEach((componentRef, key) => {\n if (!currentIds.has(key)) {\n componentRef.destroy();\n this._renderedMessages.delete(key);\n }\n });\n\n // Add or update messages\n messages.forEach((message, index) => {\n const key = this.getMessageKey(message);\n const existing = this._renderedMessages.get(key);\n\n if (existing) {\n // Update existing component\n const instance = existing.instance as MessageItemComponent;\n\n // Store previous message for comparison\n const previousMessage = instance.message;\n\n instance.message = message;\n instance.allMessages = messages;\n instance.isProcessing = this.isProcessing;\n instance.userAvatarMap = this.userAvatarMap;\n instance.isLastMessage = (index === messages.length - 1); // Update last message flag\n\n // Surface ALL distinct artifacts on this message (latest version each),\n // not just the most recent one. Loads lazily in the background.\n this.applyArtifactsToInstance(instance, message.ID, existing.changeDetectorRef);\n\n // Update agent run from map\n instance.agentRun = this.agentRunMap.get(message.ID) || null;\n\n // Update ratings from map\n instance.ratings = this.ratingsMap.get(message.ID);\n\n // Update attachments from map\n instance.attachments = this.attachmentsMap.get(message.ID) || [];\n\n // Manually trigger change detection in child component when message status changes\n // This is necessary because we're using OnPush change detection and direct property assignment\n // doesn't trigger ngOnChanges (only reference changes do)\n if (previousMessage && previousMessage.Status !== message.Status) {\n // Use ComponentRef.changeDetectorRef to force update on dynamic child\n existing.changeDetectorRef.markForCheck();\n }\n } else {\n // Create new component\n const componentRef = this.messageContainerRef.createComponent(MessageItemComponent);\n const instance = componentRef.instance;\n\n // Set inputs\n instance.message = message;\n instance.conversation = this.conversation;\n instance.currentUser = this.currentUser;\n instance.allMessages = messages;\n instance.isProcessing = this.isProcessing;\n instance.userAvatarMap = this.userAvatarMap;\n instance.isLastMessage = (index === messages.length - 1); // Mark last message\n\n // Surface ALL distinct artifacts on this message (latest version each).\n this.applyArtifactsToInstance(instance, message.ID, componentRef.changeDetectorRef);\n\n // Pass agent run from map (loaded once per conversation)\n instance.agentRun = this.agentRunMap.get(message.ID) || null;\n\n // Pass ratings from map (parsed once per conversation)\n instance.ratings = this.ratingsMap.get(message.ID);\n\n // Pass attachments from map\n instance.attachments = this.attachmentsMap.get(message.ID) || [];\n\n // Subscribe to outputs\n instance.editClicked.subscribe((msg: MJConversationDetailEntity) => this.editMessage.emit(msg));\n instance.deleteClicked.subscribe((msg: MJConversationDetailEntity) => this.deleteMessage.emit(msg));\n instance.retryClicked.subscribe((msg: MJConversationDetailEntity) => this.retryMessage.emit(msg));\n instance.testFeedbackClicked.subscribe((msg: MJConversationDetailEntity) => this.testFeedbackMessage.emit(msg));\n instance.artifactClicked.subscribe((data: {artifactId: string; versionId?: string}) => this.artifactClicked.emit(data));\n instance.messageEdited.subscribe((msg: MJConversationDetailEntity) => this.messageEdited.emit(msg));\n instance.openEntityRecord.subscribe((data: {entityName: string; compositeKey: CompositeKey}) => this.openEntityRecord.emit(data));\n instance.suggestedResponseSelected.subscribe((data: {text: string; customInput?: string}) => this.suggestedResponseSelected.emit(data));\n instance.attachmentClicked.subscribe((attachment: MessageAttachment) => this.attachmentClicked.emit(attachment));\n instance.diagnosticRequested.subscribe((messageId: string) => this.diagnosticRequested.emit(messageId));\n instance.messagePinToggled.subscribe((msg: MJConversationDetailEntity) => this.messagePinToggled.emit(msg));\n\n // Handle artifact actions if the output exists\n if (instance.artifactActionPerformed) {\n instance.artifactActionPerformed.subscribe((data: {action: string; artifactId: string}) => {\n // Parent can handle artifact actions (save, fork, history, share)\n console.log('Artifact action:', data);\n });\n }\n\n // Store reference\n this._renderedMessages.set(key, componentRef);\n\n // Store reference on the message entity for later access (like skip-chat pattern)\n (message as any)._componentRef = componentRef;\n }\n });\n\n // Only scroll to bottom if new messages were added (not just updates)\n // This prevents scrolling when the message list is merely refreshed (e.g., during agent run timer)\n const previousCount = this._previousMessageCount;\n this._previousMessageCount = messages.length;\n\n if (messages.length > previousCount) {\n this._shouldScrollToBottom = true;\n }\n } finally {\n // Re-attach change detection\n this.cdRef.reattach();\n this.cdRef.detectChanges();\n }\n }\n\n /**\n * Resolves the DISTINCT artifacts for a message (one entry per artifactId at its\n * latest version), lazy-loads them all, and applies them to the rendered\n * message-item. Loads in the background so the UI never blocks.\n *\n * WHY WE SURFACE THEM ALL (design rationale — see PR discussion w/ Pranav & Ethan):\n * A single message can legitimately carry more than one DISTINCT artifact — e.g. a\n * research report PLUS a *standalone* generated infographic. This is deliberately\n * NOT in conflict with the server-side consolidation in AgentRunner\n * (Pranav, 5664b86: \"keep the report's embedded image in the report, not as a\n * duplicate artifact\"): that logic only suppresses media that is *embedded inline*\n * (base64) in another artifact's payload — a true duplicate. Genuinely standalone\n * sibling artifacts (the report uses SVG charts; the infographic is a separate JPEG)\n * are correctly kept as separate artifacts, and the UI must show every one of them.\n *\n * The earlier `artifactList[length - 1]` (\"show only the most recent\") approach\n * (EL-BC, 95492622) assumed consolidation always left exactly one artifact per\n * message; when it legitimately leaves two, that silently hid the report behind the\n * image. Grouping by artifactId (latest version each) shows all distinct artifacts\n * while still collapsing multiple *versions* of the same artifact to one card.\n */\n private applyArtifactsToInstance(\n instance: MessageItemComponent,\n messageId: string,\n childCdRef: ChangeDetectorRef\n ): void {\n const infos = this.resolveDistinctArtifacts(messageId);\n if (infos.length === 0) {\n instance.artifacts = [];\n instance.artifact = undefined;\n instance.artifactVersion = undefined;\n return;\n }\n\n Promise.all(\n infos.map(info =>\n Promise.all([info.getArtifact(), info.getVersion()]).then(([artifact, version]) => ({ artifact, version }))\n )\n )\n .then(refs => {\n instance.artifacts = refs;\n // Keep the legacy single inputs pointed at the first entry for back-compat.\n instance.artifact = refs[0]?.artifact;\n instance.artifactVersion = refs[0]?.version;\n // zone.js 0.15: parent detectChanges doesn't propagate to dynamically created children\n childCdRef.detectChanges();\n this.cdRef.detectChanges();\n })\n .catch(err => {\n console.error('Failed to lazy-load artifacts:', err);\n });\n }\n\n /**\n * Groups a message's artifact list by artifactId, keeping the highest version of\n * each. Multiple versions of the SAME artifact collapse to one card (latest wins),\n * while genuinely distinct artifacts are all retained.\n */\n private resolveDistinctArtifacts(messageId: string): LazyArtifactInfo[] {\n const list = this.artifactMap.get(messageId);\n if (!list || list.length === 0) {\n return [];\n }\n return selectDistinctLatestArtifacts(list);\n }\n\n /**\n * Generates a unique key for a message\n * Uses ID if available, otherwise uses a temporary key\n */\n private getMessageKey(message: MJConversationDetailEntity): string {\n return message.ID && message.ID.length > 0\n ? message.ID\n : `temp_${message.__mj_CreatedAt?.getTime() || Date.now()}`;\n }\n\n /**\n * Determines whether to show the date filter dropdown\n * Only show if conversation is long and spans multiple days\n */\n private updateDateFilterVisibility(): void {\n if (!this.messages || this.messages.length < 20) {\n this.shouldShowDateFilter = false;\n return;\n }\n\n // Check if messages span more than 2 days\n const dates = this.messages\n .map(m => m.__mj_CreatedAt)\n .filter(d => d != null)\n .map(d => new Date(d!).setHours(0, 0, 0, 0));\n\n if (dates.length === 0) {\n this.shouldShowDateFilter = false;\n return;\n }\n\n const uniqueDates = new Set(dates);\n const daySpan = uniqueDates.size;\n\n // Show filter if conversation has 20+ messages and spans 3+ days\n this.shouldShowDateFilter = daySpan >= 3;\n }\n\n /**\n * Scrolls the message list to the bottom\n */\n private scrollToBottom(): void {\n if (this.scrollContainer && this.scrollContainer.nativeElement) {\n Promise.resolve().then(() => {\n const element = this.scrollContainer.nativeElement;\n element.scrollTop = element.scrollHeight;\n });\n }\n }\n\n /**\n * Removes a message from the rendered list\n * Called externally when a message is deleted\n */\n public removeMessage(message: MJConversationDetailEntity): void {\n const key = this.getMessageKey(message);\n const componentRef = this._renderedMessages.get(key);\n if (componentRef) {\n componentRef.destroy();\n this._renderedMessages.delete(key);\n }\n }\n}","<div class=\"message-list-container\" #scrollContainer>\n <!-- Sticky Date Header (only show for long conversations spanning multiple days) -->\n @if (shouldShowDateFilter && messages.length > 0) {\n <div class=\"sticky-date-header\">\n <div class=\"sticky-date-wrapper\">\n <button class=\"sticky-date-button\" (click)=\"toggleDateNav()\">\n <span>{{ currentDateDisplay }}</span>\n <i class=\"fas fa-chevron-down\"></i>\n </button>\n <div class=\"date-nav-dropdown\" [class.show]=\"showDateNav\">\n <div class=\"date-nav-option jump-to\">Jump to...</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('today')\">Today</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('yesterday')\">Yesterday</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-week')\">Last week</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-month')\">Last month</div>\n </div>\n </div>\n </div>\n }\n\n <ng-container #messageContainer></ng-container>\n\n @if (messages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fas fa-comments\"></i>\n <p>No messages yet. Start a conversation!</p>\n </div>\n }\n</div>"]}
1
+ {"version":3,"file":"message-list.component.js","sourceRoot":"","sources":["../../../../src/lib/components/message/message-list.component.ts","../../../../src/lib/components/message/message-list.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n ViewChild,\n ViewContainerRef,\n OnInit,\n OnDestroy,\n OnChanges,\n SimpleChanges,\n ChangeDetectorRef,\n ElementRef,\n AfterViewInit,\n AfterViewChecked,\n ComponentRef,\n EmbeddedViewRef,\n TemplateRef\n} from '@angular/core';\nimport { MJConversationDetailEntity, MJConversationEntity, RatingJSON } from '@memberjunction/core-entities';\nimport { UserInfo, CompositeKey } from '@memberjunction/core';\nimport { NormalizeUUID } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MessageItemComponent, MessageAttachment } from './message-item.component';\nimport {\n BeforeResponseFormSubmittedEventArgs,\n AfterResponseFormSubmittedEventArgs,\n} from '../../events/chat-events';\nimport { RealtimeSessionTimelineCardComponent } from '../realtime/realtime-session-timeline-card.component';\nimport { LazyArtifactInfo } from '../../models/lazy-artifact-info';\nimport { selectDistinctLatestArtifacts } from '../../utils/distinct-artifacts';\nimport {\n BuildConversationTimeline,\n ConversationTimelineItem,\n RealtimeSessionTimelineGroup,\n RealtimeSessionTimelineMeta\n} from '../../utils/realtime-session-timeline';\nimport { MJAIAgentRunEntityExtended } from '@memberjunction/ai-core-plus';\n\n/** Context handed to the `messageRenderer` slot template per message. */\ninterface MessageRendererContext {\n $implicit: MJConversationDetailEntity;\n message: MJConversationDetailEntity;\n}\n\n/**\n * One per rendered message in the list. Three paths can produce an entry:\n * - `component` — the default `MessageItemComponent` (single message).\n * - `embedded` — an `EmbeddedViewRef` from the consumer's\n * `messageRenderer` slot template (full per-message\n * replacement, PR 2c slot system).\n * - `realtime-session` — a `RealtimeSessionTimelineCardComponent` collapsing\n * an entire past realtime session into one timeline\n * card (PR #2787 co-agent timeline). The grouping pass\n * (`BuildConversationTimeline`) emits these alongside\n * normal messages — see the timeline utility for the\n * rules.\n *\n * Discriminated by the `kind` tag for ergonomic narrowing.\n */\ntype RenderedMessageEntry =\n | { kind: 'component'; ref: ComponentRef<MessageItemComponent> }\n | { kind: 'embedded'; ref: EmbeddedViewRef<MessageRendererContext> }\n | { kind: 'realtime-session'; ref: ComponentRef<RealtimeSessionTimelineCardComponent> };\n\n/**\n * Container component for displaying a list of messages\n * Uses dynamic component creation (like skip-chat) to avoid Angular binding overhead\n * This dramatically improves performance when messages are added/removed\n */\n@Component({\n standalone: false,\n selector: 'mj-conversation-message-list',\n templateUrl: './message-list.component.html',\n styleUrls: ['./message-list.component.css']\n})\nexport class MessageListComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit, AfterViewChecked {\n @Input() public messages: MJConversationDetailEntity[] = [];\n @Input() public conversation!: MJConversationEntity | null;\n @Input() public currentUser!: UserInfo;\n @Input() public isProcessing: boolean = false;\n @Input() public artifactMap: Map<string, LazyArtifactInfo[]> = new Map();\n @Input() public agentRunMap: Map<string, MJAIAgentRunEntityExtended> = new Map();\n @Input() public ratingsMap: Map<string, RatingJSON[]> = new Map();\n @Input() public userAvatarMap: Map<string, {imageUrl: string | null; iconClass: string | null}> = new Map();\n @Input() public attachmentsMap: Map<string, MessageAttachment[]> = new Map();\n /**\n * Optional session-row enrichment for realtime SESSION BLOCKS, keyed by\n * `NormalizeUUID(sessionId)` (agent name / status / close reason). Details stamped\n * with an `AgentSessionID` collapse into one timeline card per session — see\n * `BuildConversationTimeline` — and this map dresses those cards up when present.\n */\n @Input() public sessionMetaMap: Map<string, RealtimeSessionTimelineMeta> = new Map();\n\n /**\n * Optional per-iteration custom message renderer. When set, the list renders each\n * message via this template (full replacement) instead of the default\n * `MessageItemComponent`. Forwarded by chat-area when a consumer projects\n * `mjChatSlot=\"messageRenderer\"`. The template receives the message as\n * `$implicit` and as a named `message` context binding.\n *\n * Consumers opting into a custom renderer take full responsibility for displaying\n * the message — edit/delete/retry affordances, artifacts, ratings, attachments,\n * etc. The minimal `MJChatMessageBubbleDefaultComponent` ships as a ready-to-use\n * bubble renderer.\n */\n @Input() public messageRendererTemplate: TemplateRef<unknown> | null = null;\n\n /**\n * Optional per-message additive decoration template, projected INSIDE the default\n * `MessageItemComponent` (after the message text). Forwarded by chat-area when a\n * consumer projects `mjChatSlot=\"messageExtra\"`. Ignored when\n * `messageRendererTemplate` is set (custom renderers own all per-message content).\n */\n @Input() public messageExtraTemplate: TemplateRef<unknown> | null = null;\n\n @Output() public editMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public deleteMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public retryMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public testFeedbackMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public artifactClicked = new EventEmitter<{artifactId: string; versionId?: string}>();\n @Output() public replyInThread = new EventEmitter<MJConversationDetailEntity>();\n @Output() public viewThread = new EventEmitter<MJConversationDetailEntity>();\n @Output() public messageEdited = new EventEmitter<MJConversationDetailEntity>();\n @Output() public openEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n @Output() public suggestedResponseSelected = new EventEmitter<{text: string; customInput?: string}>();\n @Output() public attachmentClicked = new EventEmitter<MessageAttachment>();\n @Output() public diagnosticRequested = new EventEmitter<string>(); // emits messageId\n @Output() public messagePinToggled = new EventEmitter<MJConversationDetailEntity>();\n /** Emitted with the `MJ: AI Agent Sessions.ID` when a realtime session block's Open affordance is clicked. */\n @Output() public realtimeSessionOpenRequested = new EventEmitter<string>();\n\n /** Forwarded from MessageItemComponent — see its docs. */\n @Output() public beforeResponseFormSubmitted = new EventEmitter<BeforeResponseFormSubmittedEventArgs>();\n /** Forwarded from MessageItemComponent — see its docs. */\n @Output() public afterResponseFormSubmitted = new EventEmitter<AfterResponseFormSubmittedEventArgs>();\n\n @ViewChild('messageContainer', { read: ViewContainerRef }) messageContainerRef!: ViewContainerRef;\n @ViewChild('scrollContainer') scrollContainer!: ElementRef;\n\n /**\n * Per-message rendered entries — see `RenderedMessageEntry` for the 3-way\n * union (default MessageItemComponent / consumer messageRenderer slot\n * embedded view / collapsed realtime session timeline card).\n */\n private _renderedMessages = new Map<string, RenderedMessageEntry>();\n private _shouldScrollToBottom = false;\n private _previousMessageCount = 0; // Track previous count to detect new messages\n\n public currentDateDisplay: string = 'Today';\n public showDateNav: boolean = false;\n public shouldShowDateFilter: boolean = false;\n\n constructor(private cdRef: ChangeDetectorRef) {\n super();\n }\n\n public toggleDateNav(): void {\n this.showDateNav = !this.showDateNav;\n }\n\n public jumpToDate(period: string): void {\n // TODO: Implement date jumping logic\n console.log('Jump to date:', period);\n this.showDateNav = false;\n\n // Update display based on period\n switch(period) {\n case 'today':\n this.currentDateDisplay = 'Today';\n break;\n case 'yesterday':\n this.currentDateDisplay = 'Yesterday';\n break;\n case 'last-week':\n this.currentDateDisplay = 'Last week';\n break;\n case 'last-month':\n this.currentDateDisplay = 'Last month';\n break;\n }\n }\n\n // Track whether initial render has happened\n private _initialRenderComplete = false;\n\n ngOnInit() {\n // Initial render will happen in ngAfterViewInit when ViewContainerRef is available\n }\n\n ngAfterViewInit() {\n // ViewContainerRef is now available - perform initial render if we have messages\n if (this.messages && this.messages.length > 0 && this.messageContainerRef && !this._initialRenderComplete) {\n this._initialRenderComplete = true;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // React to messages array changes\n // Note: On initial load, messageContainerRef may not be available yet (ngOnChanges runs before ngAfterViewInit)\n // In that case, ngAfterViewInit will handle the initial render\n if (changes['messages'] && this.messages && this.messageContainerRef) {\n this._initialRenderComplete = true;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n\n // Watch for artifactMap changes to handle newly created artifacts\n // While artifacts are pre-loaded during initial peripheral data load,\n // new artifacts can be created mid-conversation (e.g., by agent runs)\n // This ensures artifact cards appear in messages immediately without requiring a refresh\n if (changes['artifactMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for attachmentsMap changes to handle newly created attachments\n // This ensures media attachments (e.g., images generated by agents) appear\n // immediately without requiring a page refresh\n if (changes['attachmentsMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for session-meta changes so realtime session blocks pick up their\n // agent name / status chip once the (async, batched) session lookup lands\n if (changes['sessionMetaMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n }\n\n ngAfterViewChecked() {\n if (this._shouldScrollToBottom) {\n this.scrollToBottom();\n this._shouldScrollToBottom = false;\n }\n }\n\n ngOnDestroy() {\n // Clean up all dynamically created components AND embedded views (both have destroy()).\n this._renderedMessages.forEach((entry) => {\n if (entry) {\n entry.ref.destroy();\n }\n });\n this._renderedMessages.clear();\n\n if (this.messageContainerRef) {\n this.messageContainerRef.clear();\n }\n }\n\n /**\n * Called when messages array changes\n * Efficiently updates the DOM without re-rendering everything\n */\n @Input()\n set messagesUpdate(messages: MJConversationDetailEntity[]) {\n if (messages && this.messageContainerRef) {\n this.updateMessages(messages);\n }\n }\n\n /**\n * Updates the message list using dynamic component creation\n * Only adds/removes changed messages for optimal performance\n *\n * REALTIME SESSIONS: details stamped with an `AgentSessionID` (turns persisted during\n * a live realtime session) do NOT render as normal chat bubbles. The timeline pass\n * (`BuildConversationTimeline`) collapses each session's stamped rows into ONE session\n * block, rendered as a `RealtimeSessionTimelineCardComponent` at the session's\n * chronological position. Everything else renders exactly as before.\n */\n private updateMessages(messages: MJConversationDetailEntity[]): void {\n // Temporarily detach change detection for performance\n this.cdRef.detach();\n\n try {\n // Build the timeline first — collapses contiguous realtime-session rows\n // into ONE session block per session, leaving normal messages in place.\n // See `BuildConversationTimeline` in `utils/realtime-session-timeline`.\n const timeline = BuildConversationTimeline(messages);\n\n // Remove rendered items (messages AND session blocks) that no longer exist\n const currentKeys = new Set(timeline.map(item => this.getTimelineKey(item)));\n this._renderedMessages.forEach((entry, key) => {\n if (!currentKeys.has(key)) {\n entry.ref.destroy();\n this._renderedMessages.delete(key);\n }\n });\n\n // Add or update timeline items in chronological order. `renderMessageItem`\n // internally branches on the slot template (messageRenderer) vs the\n // default MessageItemComponent; `renderSessionBlock` always creates a\n // RealtimeSessionTimelineCardComponent.\n const lastMessageKey = this.findLastMessageKey(timeline);\n for (const item of timeline) {\n if (item.Kind === 'session') {\n this.renderSessionBlock(item.Group);\n } else {\n this.renderMessageItem(item.Detail, messages, this.getMessageKey(item.Detail) === lastMessageKey);\n }\n }\n\n // Only scroll to bottom if new messages were added (not just updates)\n // This prevents scrolling when the message list is merely refreshed (e.g., during agent run timer)\n const previousCount = this._previousMessageCount;\n this._previousMessageCount = messages.length;\n\n if (messages.length > previousCount) {\n this._shouldScrollToBottom = true;\n }\n } finally {\n // Re-attach change detection\n this.cdRef.reattach();\n this.cdRef.detectChanges();\n }\n }\n\n /** Stable render key for a timeline item — message ID, or a prefixed session key for session blocks. */\n private getTimelineKey(item: ConversationTimelineItem<MJConversationDetailEntity>): string {\n return item.Kind === 'session' ? this.getSessionKey(item.Group.SessionID) : this.getMessageKey(item.Detail);\n }\n\n /** Render key for a session block (case-insensitive on the session id; prefixed so it can't collide with message IDs). */\n private getSessionKey(sessionId: string): string {\n return `session:${NormalizeUUID(sessionId)}`;\n }\n\n /** The render key of the LAST normal message item in the timeline (drives `isLastMessage`), or null when none. */\n private findLastMessageKey(timeline: ConversationTimelineItem<MJConversationDetailEntity>[]): string | null {\n for (let i = timeline.length - 1; i >= 0; i--) {\n const item = timeline[i];\n if (item.Kind === 'message') {\n return this.getMessageKey(item.Detail);\n }\n }\n return null;\n }\n\n /**\n * Creates or updates the ONE timeline card a realtime session collapses to.\n * Click/Open on the card bubbles up via {@link realtimeSessionOpenRequested} so the\n * chat area can host the SESSION REVIEW overlay for it.\n */\n private renderSessionBlock(group: RealtimeSessionTimelineGroup): void {\n const key = this.getSessionKey(group.SessionID);\n const meta = this.sessionMetaMap.get(NormalizeUUID(group.SessionID)) ?? null;\n const existing = this._renderedMessages.get(key);\n\n if (existing && existing.kind === 'realtime-session') {\n // Update existing card in place.\n const instance = existing.ref.instance;\n instance.Group = group;\n instance.Meta = meta;\n existing.ref.changeDetectorRef.markForCheck();\n return;\n }\n\n // Different kind at this key (e.g. mode changed) — drop the old entry, fall through to create.\n if (existing) {\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n const componentRef = this.messageContainerRef.createComponent(RealtimeSessionTimelineCardComponent);\n componentRef.instance.Group = group;\n componentRef.instance.Meta = meta;\n componentRef.instance.UserName = this.currentUser?.Name || 'You';\n componentRef.instance.OpenRequested.subscribe((sessionId: string) => this.realtimeSessionOpenRequested.emit(sessionId));\n this._renderedMessages.set(key, { kind: 'realtime-session', ref: componentRef });\n }\n\n /**\n * Creates or updates one normal chat message item. Routes to the\n * consumer-projected `messageRenderer` slot template (EmbeddedViewRef path)\n * when present, otherwise falls back to the default `MessageItemComponent`\n * dynamic-component path. Both paths flow through the shared\n * `createRenderedEntry` / `updateMessageItemInstance` helpers.\n */\n private renderMessageItem(message: MJConversationDetailEntity, messages: MJConversationDetailEntity[], isLastMessage: boolean): void {\n const key = this.getMessageKey(message);\n // `index` is only used for the `isLastMessage` heuristic inside\n // updateMessageItemInstance — synthesize a value that produces the right\n // boolean (last index when `isLastMessage` is true, else 0 — any non-last\n // index works since it just affects that one comparison).\n const index = isLastMessage ? messages.length - 1 : 0;\n const useCustomRenderer = this.messageRendererTemplate !== null;\n const existing = this._renderedMessages.get(key);\n\n if (existing && existing.kind === 'embedded' && useCustomRenderer) {\n // Update existing embedded view from messageRenderer slot\n existing.ref.context.$implicit = message;\n existing.ref.context.message = message;\n existing.ref.markForCheck();\n return;\n }\n if (existing && existing.kind === 'component' && !useCustomRenderer) {\n // Update existing MessageItemComponent in place\n this.updateMessageItemInstance(existing.ref, message, messages, index);\n return;\n }\n if (existing) {\n // Rendering kind changed (e.g. component↔embedded, or a session block was\n // overwritten with a message). Destroy + recreate.\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n this.createRenderedEntry(message, messages, index, key, useCustomRenderer);\n }\n\n /**\n * Updates an existing `MessageItemComponent` in place — used on the default\n * (non-custom-renderer) path when a message's status / artifacts / agent-run /\n * etc. changes mid-stream.\n */\n private updateMessageItemInstance(\n ref: ComponentRef<MessageItemComponent>,\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n index: number\n ): void {\n const instance = ref.instance;\n const previousMessage = instance.message;\n\n instance.message = message;\n instance.allMessages = messages;\n instance.isProcessing = this.isProcessing;\n instance.userAvatarMap = this.userAvatarMap;\n instance.isLastMessage = (index === messages.length - 1);\n instance.messageExtraTemplate = this.messageExtraTemplate;\n\n this.applyArtifactsToInstance(instance, message.ID, ref.changeDetectorRef);\n\n instance.agentRun = this.agentRunMap.get(message.ID) || null;\n instance.ratings = this.ratingsMap.get(message.ID);\n instance.attachments = this.attachmentsMap.get(message.ID) || [];\n\n // Status change requires explicit markForCheck on the OnPush dynamic child.\n if (previousMessage && previousMessage.Status !== message.Status) {\n ref.changeDetectorRef.markForCheck();\n }\n }\n\n /**\n * Creates a new rendered entry — either a `MessageItemComponent` (default path)\n * or an `EmbeddedViewRef` from the consumer's `messageRenderer` slot template.\n * Stores the entry in `_renderedMessages` and stamps a back-reference on the\n * message entity.\n */\n private createRenderedEntry(\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n index: number,\n key: string,\n useCustomRenderer: boolean\n ): void {\n if (useCustomRenderer && this.messageRendererTemplate) {\n // The slot directive carries TemplateRef<unknown>; assert the contract here\n // (consumers' `let-message` bindings consume the message context shape below).\n const template = this.messageRendererTemplate as TemplateRef<MessageRendererContext>;\n const viewRef = this.messageContainerRef.createEmbeddedView<MessageRendererContext>(\n template,\n { $implicit: message, message }\n );\n this._renderedMessages.set(key, { kind: 'embedded', ref: viewRef });\n // Stamp back-ref for parity with the component path.\n (message as unknown as { _viewRef?: EmbeddedViewRef<MessageRendererContext> })._viewRef = viewRef;\n return;\n }\n\n const componentRef = this.messageContainerRef.createComponent(MessageItemComponent);\n const instance = componentRef.instance;\n\n instance.message = message;\n instance.conversation = this.conversation;\n instance.currentUser = this.currentUser;\n instance.allMessages = messages;\n instance.isProcessing = this.isProcessing;\n instance.userAvatarMap = this.userAvatarMap;\n instance.isLastMessage = (index === messages.length - 1);\n instance.messageExtraTemplate = this.messageExtraTemplate;\n\n this.applyArtifactsToInstance(instance, message.ID, componentRef.changeDetectorRef);\n\n instance.agentRun = this.agentRunMap.get(message.ID) || null;\n instance.ratings = this.ratingsMap.get(message.ID);\n instance.attachments = this.attachmentsMap.get(message.ID) || [];\n\n instance.editClicked.subscribe((msg: MJConversationDetailEntity) => this.editMessage.emit(msg));\n instance.deleteClicked.subscribe((msg: MJConversationDetailEntity) => this.deleteMessage.emit(msg));\n instance.retryClicked.subscribe((msg: MJConversationDetailEntity) => this.retryMessage.emit(msg));\n instance.testFeedbackClicked.subscribe((msg: MJConversationDetailEntity) => this.testFeedbackMessage.emit(msg));\n instance.artifactClicked.subscribe((data: {artifactId: string; versionId?: string}) => this.artifactClicked.emit(data));\n instance.messageEdited.subscribe((msg: MJConversationDetailEntity) => this.messageEdited.emit(msg));\n instance.openEntityRecord.subscribe((data: {entityName: string; compositeKey: CompositeKey}) => this.openEntityRecord.emit(data));\n instance.suggestedResponseSelected.subscribe((data: {text: string; customInput?: string}) => this.suggestedResponseSelected.emit(data));\n instance.attachmentClicked.subscribe((attachment: MessageAttachment) => this.attachmentClicked.emit(attachment));\n instance.diagnosticRequested.subscribe((messageId: string) => this.diagnosticRequested.emit(messageId));\n instance.messagePinToggled.subscribe((msg: MJConversationDetailEntity) => this.messagePinToggled.emit(msg));\n instance.beforeResponseFormSubmitted.subscribe((e: BeforeResponseFormSubmittedEventArgs) => this.beforeResponseFormSubmitted.emit(e));\n instance.afterResponseFormSubmitted.subscribe((e: AfterResponseFormSubmittedEventArgs) => this.afterResponseFormSubmitted.emit(e));\n\n if (instance.artifactActionPerformed) {\n instance.artifactActionPerformed.subscribe((data: {action: string; artifactId: string}) => {\n // Parent can handle artifact actions (save, fork, history, share)\n console.log('Artifact action:', data);\n });\n }\n\n this._renderedMessages.set(key, { kind: 'component', ref: componentRef });\n // Preserve the existing back-ref pattern from the skip-chat performance design.\n (message as unknown as { _componentRef?: ComponentRef<MessageItemComponent> })._componentRef = componentRef;\n }\n\n /**\n * Resolves the DISTINCT artifacts for a message (one entry per artifactId at its\n * latest version), lazy-loads them all, and applies them to the rendered\n * message-item. Loads in the background so the UI never blocks.\n *\n * WHY WE SURFACE THEM ALL (design rationale — see PR discussion w/ Pranav & Ethan):\n * A single message can legitimately carry more than one DISTINCT artifact — e.g. a\n * research report PLUS a *standalone* generated infographic. This is deliberately\n * NOT in conflict with the server-side consolidation in AgentRunner\n * (Pranav, 5664b86: \"keep the report's embedded image in the report, not as a\n * duplicate artifact\"): that logic only suppresses media that is *embedded inline*\n * (base64) in another artifact's payload — a true duplicate. Genuinely standalone\n * sibling artifacts (the report uses SVG charts; the infographic is a separate JPEG)\n * are correctly kept as separate artifacts, and the UI must show every one of them.\n *\n * The earlier `artifactList[length - 1]` (\"show only the most recent\") approach\n * (EL-BC, 95492622) assumed consolidation always left exactly one artifact per\n * message; when it legitimately leaves two, that silently hid the report behind the\n * image. Grouping by artifactId (latest version each) shows all distinct artifacts\n * while still collapsing multiple *versions* of the same artifact to one card.\n */\n private applyArtifactsToInstance(\n instance: MessageItemComponent,\n messageId: string,\n childCdRef: ChangeDetectorRef\n ): void {\n const infos = this.resolveDistinctArtifacts(messageId);\n if (infos.length === 0) {\n instance.artifacts = [];\n instance.artifact = undefined;\n instance.artifactVersion = undefined;\n return;\n }\n\n Promise.all(\n infos.map(info =>\n Promise.all([info.getArtifact(), info.getVersion()]).then(([artifact, version]) => ({ artifact, version }))\n )\n )\n .then(refs => {\n instance.artifacts = refs;\n // Keep the legacy single inputs pointed at the first entry for back-compat.\n instance.artifact = refs[0]?.artifact;\n instance.artifactVersion = refs[0]?.version;\n // zone.js 0.15: parent detectChanges doesn't propagate to dynamically created children\n childCdRef.detectChanges();\n this.cdRef.detectChanges();\n })\n .catch(err => {\n console.error('Failed to lazy-load artifacts:', err);\n });\n }\n\n /**\n * Groups a message's artifact list by artifactId, keeping the highest version of\n * each. Multiple versions of the SAME artifact collapse to one card (latest wins),\n * while genuinely distinct artifacts are all retained.\n */\n private resolveDistinctArtifacts(messageId: string): LazyArtifactInfo[] {\n const list = this.artifactMap.get(messageId);\n if (!list || list.length === 0) {\n return [];\n }\n return selectDistinctLatestArtifacts(list);\n }\n\n /**\n * Generates a unique key for a message\n * Uses ID if available, otherwise uses a temporary key\n */\n private getMessageKey(message: MJConversationDetailEntity): string {\n return message.ID && message.ID.length > 0\n ? message.ID\n : `temp_${message.__mj_CreatedAt?.getTime() || Date.now()}`;\n }\n\n /**\n * Determines whether to show the date filter dropdown\n * Only show if conversation is long and spans multiple days\n */\n private updateDateFilterVisibility(): void {\n if (!this.messages || this.messages.length < 20) {\n this.shouldShowDateFilter = false;\n return;\n }\n\n // Check if messages span more than 2 days\n const dates = this.messages\n .map(m => m.__mj_CreatedAt)\n .filter(d => d != null)\n .map(d => new Date(d!).setHours(0, 0, 0, 0));\n\n if (dates.length === 0) {\n this.shouldShowDateFilter = false;\n return;\n }\n\n const uniqueDates = new Set(dates);\n const daySpan = uniqueDates.size;\n\n // Show filter if conversation has 20+ messages and spans 3+ days\n this.shouldShowDateFilter = daySpan >= 3;\n }\n\n /**\n * Scrolls the message list to the bottom\n */\n private scrollToBottom(): void {\n if (this.scrollContainer && this.scrollContainer.nativeElement) {\n Promise.resolve().then(() => {\n const element = this.scrollContainer.nativeElement;\n element.scrollTop = element.scrollHeight;\n });\n }\n }\n\n /**\n * Removes a message from the rendered list\n * Called externally when a message is deleted\n */\n public removeMessage(message: MJConversationDetailEntity): void {\n const key = this.getMessageKey(message);\n const entry = this._renderedMessages.get(key);\n if (entry) {\n entry.ref.destroy();\n this._renderedMessages.delete(key);\n }\n }\n}","<div class=\"message-list-container\" #scrollContainer>\n <!-- Sticky Date Header (only show for long conversations spanning multiple days) -->\n @if (shouldShowDateFilter && messages.length > 0) {\n <div class=\"sticky-date-header\">\n <div class=\"sticky-date-wrapper\">\n <button class=\"sticky-date-button\" (click)=\"toggleDateNav()\">\n <span>{{ currentDateDisplay }}</span>\n <i class=\"fas fa-chevron-down\"></i>\n </button>\n <div class=\"date-nav-dropdown\" [class.show]=\"showDateNav\">\n <div class=\"date-nav-option jump-to\">Jump to...</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('today')\">Today</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('yesterday')\">Yesterday</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-week')\">Last week</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-month')\">Last month</div>\n </div>\n </div>\n </div>\n }\n\n <ng-container #messageContainer></ng-container>\n\n @if (messages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fas fa-comments\"></i>\n <p>No messages yet. Start a conversation!</p>\n </div>\n }\n</div>"]}
@@ -0,0 +1,282 @@
1
+ import type { Type } from '@angular/core';
2
+ import { JSONValue, RealtimeToolDefinition } from '@memberjunction/ai';
3
+ /**
4
+ * Host services handed to a {@link BaseRealtimeChannelClient} at {@link BaseRealtimeChannelClient.Initialize}.
5
+ *
6
+ * The context is the plugin's ONLY line back to the live session — channels never talk to
7
+ * `RealtimeSessionService` (or any host component) directly, which is what keeps them drop-in
8
+ * plugins. Every member is host-implemented:
9
+ *
10
+ * - the SESSION SERVICE supplies {@link SendContextNote} (perception feed into the live
11
+ * model), {@link RequestSave} (debounced state-of-record persistence onto the session's
12
+ * `MJ: AI Agent Session Channels` row) and {@link AgentName};
13
+ * - the OVERLAY SHELL wires {@link SetFocusMode} (through the service's focus stream) so a
14
+ * channel surface can request the focus layout — main call column collapsed, surface
15
+ * panel filling the overlay, floating call pill riding on top.
16
+ */
17
+ export interface RealtimeChannelContext {
18
+ /** Display name of the agent the live session fronts (e.g. `"Sage"`), fixed at session start. */
19
+ AgentName: string;
20
+ /**
21
+ * Feeds a background context note into the live realtime model (no spoken reply is
22
+ * requested) — the PERCEPTION direction of the channel: serialized state deltas flow here
23
+ * so the agent stays aware of what's on the surface. No-op when the session isn't live.
24
+ */
25
+ SendContextNote(text: string): void;
26
+ /**
27
+ * Asks the host to persist `stateJson` as this channel's state of record. The host
28
+ * DEBOUNCES (a change burst becomes one save) and flushes any pending save at session
29
+ * teardown — the plugin just calls this on every state mutation and never schedules
30
+ * timers itself. Best-effort: persistence failures are logged host-side, never thrown.
31
+ */
32
+ RequestSave(stateJson: string): void;
33
+ /**
34
+ * Requests (or releases) the FOCUS layout for this channel's surface: the overlay
35
+ * collapses the main call column so the surface owns the screen, with a compact floating
36
+ * call pill keeping mute / thread / end reachable. Any channel may request it; the host
37
+ * tracks which channel holds focus and routes the pill's "exit" back to it via
38
+ * {@link BaseRealtimeChannelClient.RequestFocusExit}.
39
+ */
40
+ SetFocusMode(on: boolean): void;
41
+ /**
42
+ * Asks the live model to SPEAK a response to the supplied instructions RIGHT NOW —
43
+ * the channel's "react to this" path, e.g. a widget submission the user expects an
44
+ * audible reaction to ({@link SendContextNote} deliberately never triggers speech).
45
+ * Rides the realtime client's spoken-update channel, so on some providers the spoken
46
+ * reply is narration-kind (ephemeral, not persisted as a caption). OPTIONAL member:
47
+ * older host contexts may not supply it — plugins must call it null-safely.
48
+ */
49
+ RequestSpokenResponse?(instructions: string): void;
50
+ /**
51
+ * Persists a snapshot of the channel's state as a first-class versioned artifact
52
+ * (`MJ: Artifacts` + version, linked into conversation history when possible) — e.g. the
53
+ * whiteboard's "Save to artifacts". Distinct from {@link RealtimeChannelContext.RequestSave},
54
+ * which maintains the session's rolling state of record. Best-effort: resolves to the
55
+ * created Artifact ID, or `null` on failure (logged host-side, never thrown). Works during
56
+ * the call AND right after it ends (the host retains the session id for late saves).
57
+ */
58
+ SaveAsArtifact(name: string, contentJson: string): Promise<string | null>;
59
+ /**
60
+ * The live `MJ: AI Agent Sessions` id this channel belongs to, or `null` before the
61
+ * session has minted / after it has torn down. A channel whose tools or surface drive a
62
+ * SERVER-SIDE resource (e.g. the Remote Browser channel's server-hosted browser) passes
63
+ * this as the `agentSessionID` argument to its own GraphQL resolvers via
64
+ * {@link ExecuteServerAction}. Most channels (whiteboard, shared doc) keep all state
65
+ * client-side and never read it.
66
+ */
67
+ AgentSessionID: string | null;
68
+ /**
69
+ * Executes a CHANNEL-SPECIFIC GraphQL operation against the session's MJ server — the
70
+ * escape hatch for channels backed by a SERVER-SIDE resource that the generic
71
+ * {@link RequestSave} / {@link SaveAsArtifact} contract doesn't cover (e.g. the Remote
72
+ * Browser channel driving a server-hosted browser through its own
73
+ * `ExecuteRemoteBrowserAction` mutation + `RemoteBrowserSnapshot` query).
74
+ *
75
+ * The host runs the operation through the SAME provider the live session uses, so the
76
+ * request rides the authenticated session. Best-effort and tolerant: a transport or
77
+ * server error resolves to `null` (logged host-side) rather than throwing, so a channel
78
+ * can map the failure to a model-readable result string without `try/catch`.
79
+ *
80
+ * @typeParam TResult The expected shape of the GraphQL operation's data payload.
81
+ * @param query The GraphQL query/mutation document.
82
+ * @param variables The operation variables (all JSON-serializable).
83
+ * @returns The operation's `data` payload, or `null` on any failure / when no session is live.
84
+ */
85
+ ExecuteServerAction<TResult>(query: string, variables: Record<string, JSONValue>): Promise<TResult | null>;
86
+ }
87
+ /**
88
+ * The first-run INTRO content for an interactive channel — the concise "what is this surface
89
+ * and how do I use it" copy the overlay shows the very first time a user opens this channel's
90
+ * tab (persisted "seen" per user, so it's shown ONCE per channel per user).
91
+ *
92
+ * A channel opts in by overriding {@link BaseRealtimeChannelClient.GetOnboardingDetails}; the
93
+ * default returns `null`, so the base Voice/text channel (which has no plugin at all) AND any
94
+ * plugin that doesn't override it show nothing.
95
+ */
96
+ export interface ChannelOnboardingDetails {
97
+ /** Short title, usually the surface name (e.g. `"Whiteboard"`). */
98
+ Heading: string;
99
+ /** One or two sentences: what the surface is and what the user can expect to see on it. */
100
+ Description: string;
101
+ /** Optional quick-tip bullets (kept to 2-3 short, scannable lines). */
102
+ Tips?: string[];
103
+ /** Optional Font Awesome icon class for the intro panel (e.g. `'fa-solid fa-chalkboard'`). */
104
+ IconClass?: string;
105
+ }
106
+ /**
107
+ * Base class for CLIENT-SIDE interactive-channel plugins (per
108
+ * `plans/ai-agent-sessions.md` → "Interactive Channels" / "Pluggable Channel Interfaces").
109
+ *
110
+ * An interactive channel is a bidirectional surface the session's single realtime agent
111
+ * both PERCEIVES and ACTS UPON (whiteboard, shared doc, map, …). A concrete plugin
112
+ * contributes everything the channel needs, so the session service / call overlay carry
113
+ * ZERO channel-specific wiring:
114
+ *
115
+ * 1. a CLIENT-EXECUTED TOOL SET ({@link GetToolDefinitions}, declared to the realtime
116
+ * model at session mint) plus the local executor ({@link ApplyAgentTool}) the host
117
+ * routes `{@link ToolNamePrefix}*` calls to — the ACTION direction;
118
+ * 2. a STATE→CONTEXT SERIALIZER policy — the plugin owns its state engine and pushes
119
+ * coalesced deltas through {@link RealtimeChannelContext.SendContextNote} — the
120
+ * PERCEPTION direction;
121
+ * 3. an OPTIONAL ANGULAR SURFACE ({@link GetSurfaceComponent}) the overlay creates dynamically
122
+ * in a channel tab, handed back through {@link BindSurface} so the plugin wires its own
123
+ * inputs/outputs (the host never knows the component's API). A channel may be **server-only**
124
+ * (no rendered surface) — e.g. a bridge-contributed meeting-controls or native-whiteboard
125
+ * channel whose surface lives on the external platform, not in MJ. Such a channel returns
126
+ * `null` from {@link GetSurfaceComponent} ({@link HasSurface} is `false`) and the overlay
127
+ * simply skips its tab while still wiring its tools + perception;
128
+ * 4. a STATE OF RECORD ({@link SerializeState}, persisted via
129
+ * {@link RealtimeChannelContext.RequestSave} under {@link ChannelName}).
130
+ *
131
+ * ### Registration & resolution (mirrors the realtime model drivers)
132
+ * Concrete plugins are `@RegisterClass(BaseRealtimeChannelClient, '<ClientPluginClass>')`
133
+ * and are resolved at session start from the `MJ: AI Agent Channels` registry: each ACTIVE
134
+ * row's `ClientPluginClass` is the ClassFactory key (exactly how `BaseRealtimeClient`
135
+ * drivers resolve by provider key). Ship a `Load<YourChannel>()` no-op alongside the class
136
+ * and call it from a static code path to defeat tree-shaking.
137
+ *
138
+ * ### Lifecycle — ONE INSTANCE PER SESSION (not a singleton)
139
+ * `ClassFactory.CreateInstance` → {@link Initialize}(ctx) → zero or more
140
+ * {@link BindSurface}/{@link UnbindSurface} cycles (the surface pane is created/destroyed
141
+ * with the overlay's tab panel, e.g. collapse/expand) → {@link Dispose} at teardown.
142
+ * {@link ApplyAgentTool} MUST work with NO surface bound (apply to the state engine
143
+ * directly; skip the UI garnish) — tool calls can arrive while the panel is collapsed.
144
+ *
145
+ * @typeParam TSurface The plugin's Angular surface component type. The host only ever
146
+ * sees the default (`object`) — the typed parameter exists so concrete plugins get a
147
+ * fully typed {@link BindSurface} without casts.
148
+ */
149
+ export declare abstract class BaseRealtimeChannelClient<TSurface extends object = object> {
150
+ /**
151
+ * The host context, available from {@link Initialize} until {@link Dispose}.
152
+ * `null` outside that window — guard with `?.` in any code that can run early/late.
153
+ */
154
+ protected Context: RealtimeChannelContext | null;
155
+ /**
156
+ * The channel definition name — MUST match the `MJ: AI Agent Channels` row's `Name`
157
+ * (e.g. `'Whiteboard'`). Used as the persistence key for {@link SerializeState} saves
158
+ * and as the channel tab's stable key.
159
+ */
160
+ abstract get ChannelName(): string;
161
+ /**
162
+ * The shared name prefix of every tool this channel exposes (e.g. `'Whiteboard_'`).
163
+ * The host registers ONE local-execution route per plugin: tool calls whose name starts
164
+ * with this prefix go to {@link ApplyAgentTool} instead of the server relay.
165
+ */
166
+ abstract get ToolNamePrefix(): string;
167
+ /** Label for the channel's tab on the overlay's surface panel (e.g. `'Whiteboard'`). */
168
+ abstract get TabTitle(): string;
169
+ /** Font Awesome icon class for the channel's tab (e.g. `'fa-solid fa-chalkboard'`). */
170
+ abstract get TabIcon(): string;
171
+ /**
172
+ * The channel's CLIENT-EXECUTED tool declarations, aggregated by the session service
173
+ * into the `clientTools` set declared to the realtime model at session mint. The server
174
+ * only DECLARES these — execution stays in the browser via {@link ApplyAgentTool}.
175
+ */
176
+ abstract GetToolDefinitions(): RealtimeToolDefinition[];
177
+ /**
178
+ * Executes ONE agent tool call locally (the ACTION direction) and returns the result
179
+ * JSON string fed back to the model as the `tool_response`. Called for every tool whose
180
+ * name starts with {@link ToolNamePrefix}. Must work both WITH a bound surface (apply +
181
+ * UI garnish) and WITHOUT one (apply to the state engine directly — the tab pane may not
182
+ * exist, e.g. the surface panel is collapsed). Should not throw: return a
183
+ * `{ success: false, error }` payload so the model can narrate the failure (the host
184
+ * additionally wraps anything thrown).
185
+ */
186
+ abstract ApplyAgentTool(toolName: string, argsJson: string): string | Promise<string>;
187
+ /**
188
+ * The Angular component the overlay creates dynamically as this channel's tab pane, or `null`
189
+ * for a **server-only** channel that renders no MJ surface (its surface, if any, lives on the
190
+ * external platform — e.g. a bridge-contributed native whiteboard or meeting-controls channel).
191
+ *
192
+ * When this returns `null`, the overlay renders NO tab for the channel and never calls
193
+ * {@link BindSurface}/{@link UnbindSurface} — but the channel's tools ({@link GetToolDefinitions} /
194
+ * {@link ApplyAgentTool}) and perception ({@link RealtimeChannelContext.SendContextNote}) still run.
195
+ * A created surface instance is handed straight back via {@link BindSurface}; the host treats it as
196
+ * opaque.
197
+ *
198
+ * Default: `null` (server-only). A channel with a rendered surface overrides this to return its
199
+ * component type.
200
+ */
201
+ GetSurfaceComponent(): Type<TSurface> | null;
202
+ /**
203
+ * Whether this channel has a rendered MJ surface ({@link GetSurfaceComponent} returns non-null).
204
+ * The overlay uses this to decide whether to register a surface tab; server-only channels are
205
+ * `false`. Override only if surface availability must be decided WITHOUT constructing the type
206
+ * (the default calls {@link GetSurfaceComponent} once).
207
+ */
208
+ HasSurface(): boolean;
209
+ /**
210
+ * The channel's FIRST-RUN INTRO content, or `null` when the channel offers no onboarding.
211
+ * The overlay shows this once per channel per user — the first time the user opens this
212
+ * channel's surface tab — and remembers "seen" via the user's settings (NOT localStorage),
213
+ * so it never re-appears on later sessions or other devices.
214
+ *
215
+ * Default: `null` (no intro). The base Voice/text channel has no plugin at all, so it never
216
+ * shows an intro; an interactive channel with a surface worth explaining (whiteboard, remote
217
+ * browser, …) overrides this to return its {@link ChannelOnboardingDetails}. A plugin that
218
+ * doesn't override it simply shows nothing — onboarding is strictly opt-in.
219
+ */
220
+ GetOnboardingDetails(): ChannelOnboardingDetails | null;
221
+ /**
222
+ * Called by the host right after it created the surface component (and BEFORE the
223
+ * component's first change detection, so inputs set here are visible in its `ngOnInit`).
224
+ * The plugin — which knows its own component type — sets inputs (state engine, agent
225
+ * name, …) and subscribes outputs here, wiring perception/garnish flows back through
226
+ * {@link Context}. May be called again with a NEW instance after an
227
+ * {@link UnbindSurface} (the pane is destroyed/recreated with the tab panel).
228
+ */
229
+ abstract BindSurface(instance: TSurface): void;
230
+ /**
231
+ * Called by the host when the surface component is being destroyed (tab panel
232
+ * collapsed / overlay torn down). Drop the instance reference and unsubscribe any
233
+ * output subscriptions — after this, {@link ApplyAgentTool} runs in its no-surface
234
+ * mode. Default: no-op.
235
+ */
236
+ UnbindSurface(): void;
237
+ /**
238
+ * Binds the host context and invokes the {@link OnInitialize} hook. Called exactly once
239
+ * per session, right after ClassFactory instantiation and before any tool call or
240
+ * surface bind.
241
+ */
242
+ Initialize(ctx: RealtimeChannelContext): void;
243
+ /**
244
+ * Subclass hook invoked from {@link Initialize} once {@link Context} is bound — wire
245
+ * state-engine subscriptions (e.g. state change → `Context.RequestSave(...)`) here.
246
+ * Default: no-op.
247
+ */
248
+ protected OnInitialize(): void;
249
+ /**
250
+ * Serializes the channel's current state of record (the payload persisted on the
251
+ * session's channel row), or `null` when the channel keeps no persistent state.
252
+ * Default: `null`.
253
+ */
254
+ SerializeState(): string | null;
255
+ /**
256
+ * Restores a PRIOR session's saved channel state (the payload a previous session
257
+ * persisted via {@link SerializeState} / {@link RealtimeChannelContext.RequestSave}).
258
+ * Invoked by the session host AFTER {@link Initialize} and BEFORE any surface binding,
259
+ * when a prior session's saved state exists for this channel.
260
+ *
261
+ * Returns `true` when the state was applied; `false` when the channel ignored it —
262
+ * either because it keeps no persistent state (this default) or because the payload was
263
+ * malformed/incompatible. Implementations MUST be tolerant: never throw on bad input,
264
+ * just return `false` and start fresh.
265
+ */
266
+ RestoreState(stateJson: string): boolean;
267
+ /**
268
+ * The focus pill's "exit" affordance, routed by the overlay to the channel that holds
269
+ * focus. Implementations should leave focus mode through their OWN surface (so surface
270
+ * toggles stay in sync), ultimately emitting `Context.SetFocusMode(false)`. The overlay
271
+ * defensively clears its layout flag as well, so a no-op default is safe.
272
+ */
273
+ RequestFocusExit(): void;
274
+ /**
275
+ * Tears the plugin down at session end: release the surface binding, unsubscribe
276
+ * state-engine subscriptions, then drop the context. Subclasses overriding this MUST
277
+ * call `super.Dispose()`. Any final state save has already been flushed by the host
278
+ * (the debounced {@link RealtimeChannelContext.RequestSave} pipeline) before disposal.
279
+ */
280
+ Dispose(): void;
281
+ }
282
+ //# sourceMappingURL=base-realtime-channel-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-realtime-channel-client.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/base-realtime-channel-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEvE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,sBAAsB;IACrC,iGAAiG;IACjG,SAAS,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC;;;;;OAKG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAErC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IAEhC;;;;;;;OAOG;IACH,qBAAqB,CAAC,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnD;;;;;;;OAOG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE1E;;;;;;;OAOG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;;;;;;;;;;;;;;OAgBG;IACH,mBAAmB,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CAC5G;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,wBAAwB;IACvC,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,8FAA8F;IAC9F,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,8BAAsB,yBAAyB,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM;IAC9E;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAQ;IAExD;;;;OAIG;IACH,aAAoB,WAAW,IAAI,MAAM,CAAC;IAE1C;;;;OAIG;IACH,aAAoB,cAAc,IAAI,MAAM,CAAC;IAE7C,wFAAwF;IACxF,aAAoB,QAAQ,IAAI,MAAM,CAAC;IAEvC,uFAAuF;IACvF,aAAoB,OAAO,IAAI,MAAM,CAAC;IAEtC;;;;OAIG;aACa,kBAAkB,IAAI,sBAAsB,EAAE;IAE9D;;;;;;;;OAQG;aACa,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAE5F;;;;;;;;;;;;;OAaG;IACI,mBAAmB,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI;IAInD;;;;;OAKG;IACI,UAAU,IAAI,OAAO;IAI5B;;;;;;;;;;OAUG;IACI,oBAAoB,IAAI,wBAAwB,GAAG,IAAI;IAI9D;;;;;;;OAOG;aACa,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAErD;;;;;OAKG;IACI,aAAa,IAAI,IAAI;IAI5B;;;;OAIG;IACI,UAAU,CAAC,GAAG,EAAE,sBAAsB,GAAG,IAAI;IAKpD;;;;OAIG;IACH,SAAS,CAAC,YAAY,IAAI,IAAI;IAI9B;;;;OAIG;IACI,cAAc,IAAI,MAAM,GAAG,IAAI;IAItC;;;;;;;;;;OAUG;IACI,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI/C;;;;;OAKG;IACI,gBAAgB,IAAI,IAAI;IAI/B;;;;;OAKG;IACI,OAAO,IAAI,IAAI;CAIvB"}