@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
@@ -0,0 +1,244 @@
1
+ import { Subject } from 'rxjs';
2
+ /**
3
+ * Maps a raw delegation step id to a human-friendly phrase. Unknown steps fall back to
4
+ * the raw progress message (per product direction) so the UI never shows snake_case ids.
5
+ */
6
+ export function FriendlyStepLabel(step, message) {
7
+ switch (step) {
8
+ case 'prompt_execution': return 'Thinking it through';
9
+ case 'action_execution': return 'Running actions';
10
+ case 'subagent_execution': return 'Working with another agent';
11
+ case 'decision_processing': return 'Deciding next steps';
12
+ default: return message || 'Working';
13
+ }
14
+ }
15
+ /** Formats an elapsed duration in ms as a compact human string ("8s", "1m 04s"). */
16
+ export function FormatElapsed(ms) {
17
+ const totalSec = Math.max(0, Math.round(ms / 1000));
18
+ if (totalSec < 60) {
19
+ return `${totalSec}s`;
20
+ }
21
+ const m = Math.floor(totalSec / 60);
22
+ const s = totalSec % 60;
23
+ return `${m}m ${s.toString().padStart(2, '0')}s`;
24
+ }
25
+ /**
26
+ * SINGLE SOURCE of merged live-session state, owned by the overlay shell
27
+ * (`RealtimeSessionOverlayComponent`) and passed via `@Input()` to BOTH the session
28
+ * thread and the activity rail — so the per-CallID card bookkeeping and subscription
29
+ * logic exists exactly once.
30
+ *
31
+ * Merges FOUR reactive streams from {@link RealtimeSessionService}:
32
+ * - `Captions$` — growing user/assistant caption list → appended to {@link Items}.
33
+ * - `DelegationProgress$` — first event per `CallID` inserts a working card at the thread
34
+ * tail; later events REPLACE the card immutably (new object +
35
+ * new arrays) so change detection always fires.
36
+ * - `DelegationResult$` — flips the card to Done/Failed with the real result text.
37
+ * - `DelegationNarration$` — the EPHEMERAL spoken progress note (latest only, never
38
+ * accumulated), cleared when no delegation is running anymore.
39
+ *
40
+ * Consumers subscribe to {@link Changed$} and `markForCheck()`; all exposed collections
41
+ * are replaced (never mutated) on change.
42
+ */
43
+ export class RealtimeSessionState {
44
+ /** Display name used for new delegation cards (set by the overlay's AgentName input). */
45
+ AgentName = 'Sage';
46
+ /** The merged, chronological thread (captions + delegation cards), oldest first. */
47
+ Items = [];
48
+ /** All delegation cards of the session, NEWEST first — the activity rail's list. */
49
+ Cards = [];
50
+ /** Latest ephemeral narration text, or null when none should be shown. */
51
+ Narration = null;
52
+ /** CallID of the most recently started, still-running delegation (anchors the live note). */
53
+ ActiveCallId = null;
54
+ /** Emits after every state change so views can mark themselves for check. */
55
+ Changed$ = new Subject();
56
+ /** Number of captions already merged into {@link Items} (append-only bookkeeping). */
57
+ placedCaptionCount = 0;
58
+ /** Live card lookup by CallID (insertion order = start order). */
59
+ cardsByCallId = new Map();
60
+ subs = [];
61
+ /** True while at least one delegation is still running. */
62
+ get HasRunningDelegation() {
63
+ return this.ActiveCallId !== null;
64
+ }
65
+ /** Subscribes to the session streams. Call once from the owning overlay shell. */
66
+ Attach(voice) {
67
+ if (this.subs.length > 0) {
68
+ return; // already attached
69
+ }
70
+ this.subs.push(voice.Captions$.subscribe(c => this.onCaptions(c)), voice.DelegationProgress$.subscribe(p => this.onProgress(p)), voice.DelegationResult$.subscribe(r => this.onResult(r)), voice.DelegationNarration$.subscribe(n => this.onNarration(n)));
71
+ }
72
+ /** Unsubscribes from all session streams. Call from the owning shell's ngOnDestroy. */
73
+ Detach() {
74
+ for (const s of this.subs) {
75
+ s.unsubscribe();
76
+ }
77
+ this.subs = [];
78
+ }
79
+ /**
80
+ * SESSION REVIEW population path: replaces ALL merged state with a pre-built
81
+ * HISTORICAL thread (caption turns + done delegation cards, oldest first — see
82
+ * `BuildReviewThreadItems`). Resets the live-stream bookkeeping first, so a later
83
+ * live session starts from a clean merge baseline; delegation cards are indexed by
84
+ * CallID so the rail's {@link Cards} list and {@link ActiveCallId} derive normally.
85
+ */
86
+ LoadHistoricalItems(items) {
87
+ this.reset();
88
+ this.Items = [...items];
89
+ for (const item of items) {
90
+ if (item.Kind === 'delegation') {
91
+ this.cardsByCallId.set(item.Card.CallID, item.Card);
92
+ }
93
+ }
94
+ this.rebuildCards();
95
+ this.recomputeActive();
96
+ this.Changed$.next();
97
+ }
98
+ /** Clears all merged state and notifies subscribers (e.g. leaving session review). */
99
+ Clear() {
100
+ this.reset();
101
+ this.Changed$.next();
102
+ }
103
+ /**
104
+ * REVIEW→LIVE continuation path: KEEPS the historical thread (and its delegation cards
105
+ * in the rail) and appends a "Resumed live session" {@link RealtimeThreadDividerItem},
106
+ * then resets only the LIVE-merge bookkeeping so the new session's captions and cards
107
+ * append cleanly AFTER the divider:
108
+ * - `placedCaptionCount` → 0 (the fresh session's caption stream starts empty, so the
109
+ * start-of-session `[]` emission is a no-op rather than a reset);
110
+ * - the ephemeral narration is dropped (nothing is running yet);
111
+ * - historical cards stay indexed by CallID — new live CallIDs are unique, so live
112
+ * cards insert alongside them and `ActiveCallId` recomputes normally.
113
+ */
114
+ StartLiveContinuation(at = new Date()) {
115
+ const divider = {
116
+ Kind: 'divider',
117
+ Label: 'Resumed live session',
118
+ At: at,
119
+ Icon: 'fa-solid fa-phone'
120
+ };
121
+ this.Items = [...this.Items, divider];
122
+ this.Narration = null;
123
+ this.placedCaptionCount = 0;
124
+ this.recomputeActive();
125
+ this.Changed$.next();
126
+ }
127
+ /** Appends any newly-arrived captions, keeping order relative to delegation cards. */
128
+ onCaptions(captions) {
129
+ if (captions.length <= this.placedCaptionCount) {
130
+ // Captions are cleared on a fresh session — reset all merge state.
131
+ if (captions.length < this.placedCaptionCount) {
132
+ this.reset();
133
+ this.Changed$.next();
134
+ }
135
+ return;
136
+ }
137
+ const appended = [];
138
+ for (let i = this.placedCaptionCount; i < captions.length; i++) {
139
+ appended.push({ Kind: 'caption', Role: captions[i].Role, Text: captions[i].Text });
140
+ }
141
+ this.placedCaptionCount = captions.length;
142
+ this.Items = [...this.Items, ...appended];
143
+ this.Changed$.next();
144
+ }
145
+ /** Inserts a new working card, or immutably replaces the existing one for this CallID. */
146
+ onProgress(progress) {
147
+ const existing = this.cardsByCallId.get(progress.CallID);
148
+ if (existing) {
149
+ this.replaceCard({
150
+ ...existing,
151
+ LatestStep: progress.Step,
152
+ LatestMessage: progress.Message,
153
+ Percentage: progress.Percentage
154
+ });
155
+ }
156
+ else {
157
+ this.insertCard(progress);
158
+ }
159
+ this.Changed$.next();
160
+ }
161
+ /** Creates a working card for a first-seen CallID and appends it to the thread tail. */
162
+ insertCard(progress) {
163
+ const card = {
164
+ CallID: progress.CallID,
165
+ AgentName: this.AgentName,
166
+ LatestStep: progress.Step,
167
+ LatestMessage: progress.Message,
168
+ Percentage: progress.Percentage,
169
+ Done: false,
170
+ Success: false,
171
+ RunRef: this.shortRunRef(progress.CallID),
172
+ StartedAt: Date.now()
173
+ };
174
+ this.cardsByCallId.set(progress.CallID, card);
175
+ this.Items = [...this.Items, { Kind: 'delegation', Card: card }];
176
+ this.rebuildCards();
177
+ this.recomputeActive();
178
+ }
179
+ /** Flips the card for a finished delegation to Done/Failed with its real result. */
180
+ onResult(result) {
181
+ const existing = this.cardsByCallId.get(result.CallID);
182
+ if (!existing) {
183
+ return; // non-delegation tool result (no card was ever created) — ignore
184
+ }
185
+ this.replaceCard({
186
+ ...existing,
187
+ Done: true,
188
+ Success: result.Success,
189
+ Result: result.Output,
190
+ RunID: result.RunID ?? existing.RunID,
191
+ Artifacts: result.Artifacts ?? existing.Artifacts,
192
+ FinishedAt: Date.now()
193
+ });
194
+ if (!this.HasRunningDelegation) {
195
+ // All delegations finished — the live narration note fades away.
196
+ this.Narration = null;
197
+ }
198
+ this.Changed$.next();
199
+ }
200
+ /** Latest narration REPLACES the previous one (never accumulated). */
201
+ onNarration(narration) {
202
+ this.Narration = narration.Text;
203
+ this.Changed$.next();
204
+ }
205
+ /**
206
+ * Immutable replacement of a card: new card object, new thread-item wrapper, new
207
+ * Items array, rebuilt Cards array — so every binding sees a fresh reference.
208
+ */
209
+ replaceCard(card) {
210
+ this.cardsByCallId.set(card.CallID, card);
211
+ const idx = this.Items.findIndex(i => i.Kind === 'delegation' && i.Card.CallID === card.CallID);
212
+ if (idx >= 0) {
213
+ const next = [...this.Items];
214
+ next[idx] = { Kind: 'delegation', Card: card };
215
+ this.Items = next;
216
+ }
217
+ this.rebuildCards();
218
+ this.recomputeActive();
219
+ }
220
+ /** Rebuilds the rail's newest-first card list from the (start-ordered) map. */
221
+ rebuildCards() {
222
+ this.Cards = Array.from(this.cardsByCallId.values()).reverse();
223
+ }
224
+ /** Recomputes which still-running delegation anchors the live narration note. */
225
+ recomputeActive() {
226
+ const running = this.Cards.find(c => !c.Done);
227
+ this.ActiveCallId = running ? running.CallID : null;
228
+ }
229
+ /** Derives a short, stable run reference (e.g. "#a3f1") from the call id. */
230
+ shortRunRef(callId) {
231
+ const compact = callId.replace(/[^a-z0-9]/gi, '');
232
+ return compact.length >= 4 ? `#${compact.slice(-4).toLowerCase()}` : `#${compact.toLowerCase()}`;
233
+ }
234
+ /** Clears all merged state (fresh session). */
235
+ reset() {
236
+ this.Items = [];
237
+ this.Cards = [];
238
+ this.Narration = null;
239
+ this.ActiveCallId = null;
240
+ this.placedCaptionCount = 0;
241
+ this.cardsByCallId.clear();
242
+ }
243
+ }
244
+ //# sourceMappingURL=realtime-session-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-session-state.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-session-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { Observable, Subject, Subscription } from 'rxjs';\nimport {\n VoiceCaption, VoiceDelegationProgress, VoiceDelegationResult, VoiceDelegationNarration\n} from '../../services/realtime-session.service';\nimport { ParsedDelegationArtifact } from '../../services/delegation-result-parser';\n\n/**\n * The four reactive session streams {@link RealtimeSessionState} merges — structurally\n * satisfied by `RealtimeSessionService`. Narrowed to an interface so the state (and its unit\n * tests) depend only on the streams, not on the full service / GraphQL import chain.\n */\nexport interface RealtimeSessionStreams {\n /** Growing user/assistant caption list. */\n Captions$: Observable<VoiceCaption[]>;\n /** Progress updates from delegated agent runs. */\n DelegationProgress$: Observable<VoiceDelegationProgress>;\n /** Terminal delegation results. */\n DelegationResult$: Observable<VoiceDelegationResult>;\n /** Ephemeral spoken progress narrations. */\n DelegationNarration$: Observable<VoiceDelegationNarration>;\n}\n\n/**\n * The view-model for one delegated tool/agent call in the live session. Built by\n * {@link RealtimeSessionState} from the `DelegationProgress$` / `DelegationResult$`\n * streams (correlated by `CallID`) and rendered both inline in the session thread\n * and as a compact card in the activity rail.\n *\n * Card objects are treated as IMMUTABLE — every progress/result event REPLACES the\n * card object (and the arrays containing it) so Angular bindings always see fresh\n * references and in-place updates reliably re-render.\n */\nexport interface RealtimeDelegationCardVM {\n /** The `invoke-target-agent` call this card represents. */\n CallID: string;\n /** Display name of the delegated agent (e.g. \"Sage\"). */\n AgentName: string;\n /** Latest human-readable progress message from the stream. */\n LatestMessage: string;\n /** The delegation phase (`prompt_execution` | `action_execution` | …). */\n LatestStep: string;\n /** Optional completion percentage (0–100) when the server supplies it. */\n Percentage?: number;\n /** `true` once the delegation reached a terminal result. */\n Done: boolean;\n /** Whether the delegated work succeeded (meaningful once {@link Done} is true). */\n Success: boolean;\n /** Short run identifier (e.g. \"#a3f1\") if known; shown in expanded provenance detail. */\n RunRef?: string;\n /**\n * ID of the delegated agent run (`MJ: AI Agent Runs`) once the result reports it.\n * Powers the gear-gated \"Open run\" developer link on the card / rail entry.\n */\n RunID?: string;\n /** The real result text once the delegation completes. */\n Result?: string | null;\n /**\n * Artifacts the delegated run produced (set with the terminal result). Powers the\n * \"View\" affordance on done cards / rail entries and the surface panel's artifact tabs.\n */\n Artifacts?: ParsedDelegationArtifact[];\n /** Epoch ms when the first progress event for this call arrived. */\n StartedAt: number;\n /** Epoch ms when the terminal result arrived. */\n FinishedAt?: number;\n}\n\n/** A caption turn (user or assistant) in the unified thread. */\nexport interface RealtimeThreadCaptionItem {\n Kind: 'caption';\n Role: 'User' | 'Assistant';\n Text: string;\n}\n\n/** A delegation card in the unified thread (working → done chip). */\nexport interface RealtimeThreadDelegationItem {\n Kind: 'delegation';\n Card: RealtimeDelegationCardVM;\n}\n\n/**\n * A SESSION-BOUNDARY divider in the unified thread — a subtle, token-styled rule marking\n * where one session leg ends and another begins. Two producers:\n * - review→live continuation ({@link RealtimeSessionState.StartLiveContinuation}):\n * \"Resumed live session · <time>\" before the new live items;\n * - multi-leg session review (`BuildReviewThreadItems` over a `lastSessionId` chain):\n * \"Session leg · started <time>\" between legs, carrying the PREVIOUS leg's CloseReason\n * as a small chip so the reader sees why that leg ended.\n */\nexport interface RealtimeThreadDividerItem {\n Kind: 'divider';\n /** The divider's label (e.g. \"Resumed live session\", \"Session leg\"). */\n Label: string;\n /** Timestamp rendered after the label (\"· <time>\"), or null when unknown. */\n At: Date | null;\n /** Font Awesome icon class rendered before the label (e.g. `fa-solid fa-phone`). */\n Icon: string;\n /** Why the PRECEDING leg closed (review chains only) — rendered as a small chip. */\n CloseReason?: string | null;\n}\n\n/** One entry in the chronological thread: a caption bubble, a delegation card, or a leg divider. */\nexport type RealtimeThreadItem = RealtimeThreadCaptionItem | RealtimeThreadDelegationItem | RealtimeThreadDividerItem;\n\n/**\n * Maps a raw delegation step id to a human-friendly phrase. Unknown steps fall back to\n * the raw progress message (per product direction) so the UI never shows snake_case ids.\n */\nexport function FriendlyStepLabel(step: string, message: string): string {\n switch (step) {\n case 'prompt_execution': return 'Thinking it through';\n case 'action_execution': return 'Running actions';\n case 'subagent_execution': return 'Working with another agent';\n case 'decision_processing': return 'Deciding next steps';\n default: return message || 'Working';\n }\n}\n\n/** Formats an elapsed duration in ms as a compact human string (\"8s\", \"1m 04s\"). */\nexport function FormatElapsed(ms: number): string {\n const totalSec = Math.max(0, Math.round(ms / 1000));\n if (totalSec < 60) {\n return `${totalSec}s`;\n }\n const m = Math.floor(totalSec / 60);\n const s = totalSec % 60;\n return `${m}m ${s.toString().padStart(2, '0')}s`;\n}\n\n/**\n * SINGLE SOURCE of merged live-session state, owned by the overlay shell\n * (`RealtimeSessionOverlayComponent`) and passed via `@Input()` to BOTH the session\n * thread and the activity rail — so the per-CallID card bookkeeping and subscription\n * logic exists exactly once.\n *\n * Merges FOUR reactive streams from {@link RealtimeSessionService}:\n * - `Captions$` — growing user/assistant caption list → appended to {@link Items}.\n * - `DelegationProgress$` — first event per `CallID` inserts a working card at the thread\n * tail; later events REPLACE the card immutably (new object +\n * new arrays) so change detection always fires.\n * - `DelegationResult$` — flips the card to Done/Failed with the real result text.\n * - `DelegationNarration$` — the EPHEMERAL spoken progress note (latest only, never\n * accumulated), cleared when no delegation is running anymore.\n *\n * Consumers subscribe to {@link Changed$} and `markForCheck()`; all exposed collections\n * are replaced (never mutated) on change.\n */\nexport class RealtimeSessionState {\n /** Display name used for new delegation cards (set by the overlay's AgentName input). */\n public AgentName = 'Sage';\n\n /** The merged, chronological thread (captions + delegation cards), oldest first. */\n public Items: RealtimeThreadItem[] = [];\n\n /** All delegation cards of the session, NEWEST first — the activity rail's list. */\n public Cards: RealtimeDelegationCardVM[] = [];\n\n /** Latest ephemeral narration text, or null when none should be shown. */\n public Narration: string | null = null;\n\n /** CallID of the most recently started, still-running delegation (anchors the live note). */\n public ActiveCallId: string | null = null;\n\n /** Emits after every state change so views can mark themselves for check. */\n public readonly Changed$ = new Subject<void>();\n\n /** Number of captions already merged into {@link Items} (append-only bookkeeping). */\n private placedCaptionCount = 0;\n /** Live card lookup by CallID (insertion order = start order). */\n private cardsByCallId = new Map<string, RealtimeDelegationCardVM>();\n private subs: Subscription[] = [];\n\n /** True while at least one delegation is still running. */\n public get HasRunningDelegation(): boolean {\n return this.ActiveCallId !== null;\n }\n\n /** Subscribes to the session streams. Call once from the owning overlay shell. */\n public Attach(voice: RealtimeSessionStreams): void {\n if (this.subs.length > 0) {\n return; // already attached\n }\n this.subs.push(\n voice.Captions$.subscribe(c => this.onCaptions(c)),\n voice.DelegationProgress$.subscribe(p => this.onProgress(p)),\n voice.DelegationResult$.subscribe(r => this.onResult(r)),\n voice.DelegationNarration$.subscribe(n => this.onNarration(n))\n );\n }\n\n /** Unsubscribes from all session streams. Call from the owning shell's ngOnDestroy. */\n public Detach(): void {\n for (const s of this.subs) {\n s.unsubscribe();\n }\n this.subs = [];\n }\n\n /**\n * SESSION REVIEW population path: replaces ALL merged state with a pre-built\n * HISTORICAL thread (caption turns + done delegation cards, oldest first — see\n * `BuildReviewThreadItems`). Resets the live-stream bookkeeping first, so a later\n * live session starts from a clean merge baseline; delegation cards are indexed by\n * CallID so the rail's {@link Cards} list and {@link ActiveCallId} derive normally.\n */\n public LoadHistoricalItems(items: RealtimeThreadItem[]): void {\n this.reset();\n this.Items = [...items];\n for (const item of items) {\n if (item.Kind === 'delegation') {\n this.cardsByCallId.set(item.Card.CallID, item.Card);\n }\n }\n this.rebuildCards();\n this.recomputeActive();\n this.Changed$.next();\n }\n\n /** Clears all merged state and notifies subscribers (e.g. leaving session review). */\n public Clear(): void {\n this.reset();\n this.Changed$.next();\n }\n\n /**\n * REVIEW→LIVE continuation path: KEEPS the historical thread (and its delegation cards\n * in the rail) and appends a \"Resumed live session\" {@link RealtimeThreadDividerItem},\n * then resets only the LIVE-merge bookkeeping so the new session's captions and cards\n * append cleanly AFTER the divider:\n * - `placedCaptionCount` → 0 (the fresh session's caption stream starts empty, so the\n * start-of-session `[]` emission is a no-op rather than a reset);\n * - the ephemeral narration is dropped (nothing is running yet);\n * - historical cards stay indexed by CallID — new live CallIDs are unique, so live\n * cards insert alongside them and `ActiveCallId` recomputes normally.\n */\n public StartLiveContinuation(at: Date = new Date()): void {\n const divider: RealtimeThreadDividerItem = {\n Kind: 'divider',\n Label: 'Resumed live session',\n At: at,\n Icon: 'fa-solid fa-phone'\n };\n this.Items = [...this.Items, divider];\n this.Narration = null;\n this.placedCaptionCount = 0;\n this.recomputeActive();\n this.Changed$.next();\n }\n\n /** Appends any newly-arrived captions, keeping order relative to delegation cards. */\n private onCaptions(captions: VoiceCaption[]): void {\n if (captions.length <= this.placedCaptionCount) {\n // Captions are cleared on a fresh session — reset all merge state.\n if (captions.length < this.placedCaptionCount) {\n this.reset();\n this.Changed$.next();\n }\n return;\n }\n const appended: RealtimeThreadItem[] = [];\n for (let i = this.placedCaptionCount; i < captions.length; i++) {\n appended.push({ Kind: 'caption', Role: captions[i].Role, Text: captions[i].Text });\n }\n this.placedCaptionCount = captions.length;\n this.Items = [...this.Items, ...appended];\n this.Changed$.next();\n }\n\n /** Inserts a new working card, or immutably replaces the existing one for this CallID. */\n private onProgress(progress: VoiceDelegationProgress): void {\n const existing = this.cardsByCallId.get(progress.CallID);\n if (existing) {\n this.replaceCard({\n ...existing,\n LatestStep: progress.Step,\n LatestMessage: progress.Message,\n Percentage: progress.Percentage\n });\n } else {\n this.insertCard(progress);\n }\n this.Changed$.next();\n }\n\n /** Creates a working card for a first-seen CallID and appends it to the thread tail. */\n private insertCard(progress: VoiceDelegationProgress): void {\n const card: RealtimeDelegationCardVM = {\n CallID: progress.CallID,\n AgentName: this.AgentName,\n LatestStep: progress.Step,\n LatestMessage: progress.Message,\n Percentage: progress.Percentage,\n Done: false,\n Success: false,\n RunRef: this.shortRunRef(progress.CallID),\n StartedAt: Date.now()\n };\n this.cardsByCallId.set(progress.CallID, card);\n this.Items = [...this.Items, { Kind: 'delegation', Card: card }];\n this.rebuildCards();\n this.recomputeActive();\n }\n\n /** Flips the card for a finished delegation to Done/Failed with its real result. */\n private onResult(result: VoiceDelegationResult): void {\n const existing = this.cardsByCallId.get(result.CallID);\n if (!existing) {\n return; // non-delegation tool result (no card was ever created) — ignore\n }\n this.replaceCard({\n ...existing,\n Done: true,\n Success: result.Success,\n Result: result.Output,\n RunID: result.RunID ?? existing.RunID,\n Artifacts: result.Artifacts ?? existing.Artifacts,\n FinishedAt: Date.now()\n });\n if (!this.HasRunningDelegation) {\n // All delegations finished — the live narration note fades away.\n this.Narration = null;\n }\n this.Changed$.next();\n }\n\n /** Latest narration REPLACES the previous one (never accumulated). */\n private onNarration(narration: VoiceDelegationNarration): void {\n this.Narration = narration.Text;\n this.Changed$.next();\n }\n\n /**\n * Immutable replacement of a card: new card object, new thread-item wrapper, new\n * Items array, rebuilt Cards array — so every binding sees a fresh reference.\n */\n private replaceCard(card: RealtimeDelegationCardVM): void {\n this.cardsByCallId.set(card.CallID, card);\n const idx = this.Items.findIndex(i => i.Kind === 'delegation' && i.Card.CallID === card.CallID);\n if (idx >= 0) {\n const next = [...this.Items];\n next[idx] = { Kind: 'delegation', Card: card };\n this.Items = next;\n }\n this.rebuildCards();\n this.recomputeActive();\n }\n\n /** Rebuilds the rail's newest-first card list from the (start-ordered) map. */\n private rebuildCards(): void {\n this.Cards = Array.from(this.cardsByCallId.values()).reverse();\n }\n\n /** Recomputes which still-running delegation anchors the live narration note. */\n private recomputeActive(): void {\n const running = this.Cards.find(c => !c.Done);\n this.ActiveCallId = running ? running.CallID : null;\n }\n\n /** Derives a short, stable run reference (e.g. \"#a3f1\") from the call id. */\n private shortRunRef(callId: string): string {\n const compact = callId.replace(/[^a-z0-9]/gi, '');\n return compact.length >= 4 ? `#${compact.slice(-4).toLowerCase()}` : `#${compact.toLowerCase()}`;\n }\n\n /** Clears all merged state (fresh session). */\n private reset(): void {\n this.Items = [];\n this.Cards = [];\n this.Narration = null;\n this.ActiveCallId = null;\n this.placedCaptionCount = 0;\n this.cardsByCallId.clear();\n }\n}\n"]}
@@ -0,0 +1,56 @@
1
+ import { EventEmitter, AfterViewChecked, OnInit, OnDestroy } from '@angular/core';
2
+ import { RealtimeSessionState, RealtimeThreadItem } from './realtime-session-state';
3
+ import { ParsedDelegationArtifact } from '../../services/delegation-result-parser';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * The unified, chronological live thread for the call overlay: caption bubbles
7
+ * interleaved with delegation cards exactly where they happened.
8
+ *
9
+ * PURELY PRESENTATIONAL over {@link RealtimeSessionState} — the overlay shell owns the
10
+ * state object (which merges the service streams once) and passes it here AND to the
11
+ * activity rail, so there is exactly one copy of the per-CallID merge logic.
12
+ *
13
+ * Also renders the EPHEMERAL narration "live note": indented, muted, italic text under
14
+ * the ACTIVE working card (latest narration only — replaced, never accumulated).
15
+ */
16
+ export declare class RealtimeSessionThreadComponent implements OnInit, AfterViewChecked, OnDestroy {
17
+ private scrollAnchor?;
18
+ /** Display name of the agent (caption avatar / meta line). */
19
+ AgentName: string;
20
+ /**
21
+ * Display name of the signed-in user for their turns — consistent with the main
22
+ * chat's sender names, and ready for multi-user sessions where "You" stops meaning
23
+ * anything. Hosts bind the current user's name; the default keeps old hosts working.
24
+ */
25
+ UserName: string;
26
+ /** Shared live-session state, owned by the overlay shell. */
27
+ State: RealtimeSessionState;
28
+ /** Whether to render caption bubbles (toggled by the controls' captions button). */
29
+ ShowCaptions: boolean;
30
+ /** Whether developer affordances on delegation cards are revealed (gear-gated). */
31
+ DevMode: boolean;
32
+ /** Re-emitted from a delegation card's dev "Open run" link (the delegated run's ID). */
33
+ OpenRunRequested: EventEmitter<string>;
34
+ /** Re-emitted from a delegation card's "View" artifact chip (focuses the artifact's surface tab). */
35
+ OpenArtifactRequested: EventEmitter<ParsedDelegationArtifact>;
36
+ /** Re-emitted from a WORKING delegation card's ✕ cancel affordance (the call's ID). */
37
+ CancelRequested: EventEmitter<string>;
38
+ /** Item count at the last change notification, to auto-scroll only when the list grows. */
39
+ private lastItemCount;
40
+ /** Drives auto-scroll: set whenever the list grows. */
41
+ private pendingScroll;
42
+ private changedSub?;
43
+ private cdr;
44
+ ngOnInit(): void;
45
+ ngAfterViewChecked(): void;
46
+ ngOnDestroy(): void;
47
+ /** track fn for the @for over thread items. */
48
+ TrackItem(index: number, item: RealtimeThreadItem): string;
49
+ /** True when the live narration note should render under THIS delegation item. */
50
+ ShowsLiveNote(item: RealtimeThreadItem): boolean;
51
+ /** Marks for check on every state change; auto-scrolls when the thread grew. */
52
+ private onStateChanged;
53
+ static ɵfac: i0.ɵɵFactoryDeclaration<RealtimeSessionThreadComponent, never>;
54
+ static ɵcmp: i0.ɵɵComponentDeclaration<RealtimeSessionThreadComponent, "mj-realtime-session-thread", never, { "AgentName": { "alias": "AgentName"; "required": false; }; "UserName": { "alias": "UserName"; "required": false; }; "State": { "alias": "State"; "required": true; }; "ShowCaptions": { "alias": "ShowCaptions"; "required": false; }; "DevMode": { "alias": "DevMode"; "required": false; }; }, { "OpenRunRequested": "OpenRunRequested"; "OpenArtifactRequested": "OpenArtifactRequested"; "CancelRequested": "CancelRequested"; }, never, never, true, never>;
55
+ }
56
+ //# sourceMappingURL=realtime-session-thread.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-session-thread.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-session-thread.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACM,YAAY,EAAwC,gBAAgB,EAAE,MAAM,EAAE,SAAS,EAEnG,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;;AAEnF;;;;;;;;;;GAUG;AACH,qBAOa,8BAA+B,YAAW,MAAM,EAAE,gBAAgB,EAAE,SAAS;IAC7D,OAAO,CAAC,YAAY,CAAC,CAA0B;IAE1E,8DAA8D;IACrD,SAAS,SAAU;IAE5B;;;;OAIG;IACM,QAAQ,SAAS;IAE1B,6DAA6D;IAClC,KAAK,EAAG,oBAAoB,CAAC;IAExD,oFAAoF;IAC3E,YAAY,UAAQ;IAE7B,mFAAmF;IAC1E,OAAO,UAAS;IAEzB,wFAAwF;IAC9E,gBAAgB,uBAA8B;IAExD,qGAAqG;IAC3F,qBAAqB,yCAAgD;IAE/E,uFAAuF;IAC7E,eAAe,uBAA8B;IAEvD,2FAA2F;IAC3F,OAAO,CAAC,aAAa,CAAK;IAC1B,uDAAuD;IACvD,OAAO,CAAC,aAAa,CAAS;IAE9B,OAAO,CAAC,UAAU,CAAC,CAAe;IAClC,OAAO,CAAC,GAAG,CAA6B;IAExC,QAAQ,IAAI,IAAI;IAKhB,kBAAkB,IAAI,IAAI;IAO1B,WAAW,IAAI,IAAI;IAInB,+CAA+C;IACxC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,MAAM;IAQjE,kFAAkF;IAC3E,aAAa,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO;IAOvD,gFAAgF;IAChF,OAAO,CAAC,cAAc;yCAzEX,8BAA8B;2CAA9B,8BAA8B;CAgF1C"}
@@ -0,0 +1,246 @@
1
+ import { Component, EventEmitter, Input, Output, ViewChild, ChangeDetectorRef, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { RealtimeDelegationCardComponent } from './realtime-delegation-card.component';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+ const _c0 = ["scrollAnchor"];
7
+ function RealtimeSessionThreadComponent_For_2_Case_0_Conditional_0_Conditional_5_Template(rf, ctx) { if (rf & 1) {
8
+ i0.ɵɵelementStart(0, "span", 10);
9
+ i0.ɵɵtext(1);
10
+ i0.ɵɵelementEnd();
11
+ } if (rf & 2) {
12
+ const ctx_r0 = i0.ɵɵnextContext(4);
13
+ i0.ɵɵadvance();
14
+ i0.ɵɵtextInterpolate(ctx_r0.UserName);
15
+ } }
16
+ function RealtimeSessionThreadComponent_For_2_Case_0_Conditional_0_Conditional_6_Template(rf, ctx) { if (rf & 1) {
17
+ i0.ɵɵtext(0);
18
+ i0.ɵɵelementStart(1, "span", 12);
19
+ i0.ɵɵtext(2, "\u00B7 voice");
20
+ i0.ɵɵelementEnd();
21
+ } if (rf & 2) {
22
+ const ctx_r0 = i0.ɵɵnextContext(4);
23
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.AgentName, " ");
24
+ } }
25
+ function RealtimeSessionThreadComponent_For_2_Case_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
26
+ i0.ɵɵelementStart(0, "div", 6)(1, "div", 7);
27
+ i0.ɵɵtext(2);
28
+ i0.ɵɵelementEnd();
29
+ i0.ɵɵelementStart(3, "div", 8)(4, "div", 9);
30
+ i0.ɵɵconditionalCreate(5, RealtimeSessionThreadComponent_For_2_Case_0_Conditional_0_Conditional_5_Template, 2, 1, "span", 10)(6, RealtimeSessionThreadComponent_For_2_Case_0_Conditional_0_Conditional_6_Template, 3, 1);
31
+ i0.ɵɵelementEnd();
32
+ i0.ɵɵelementStart(7, "div", 11);
33
+ i0.ɵɵtext(8);
34
+ i0.ɵɵelementEnd()()();
35
+ } if (rf & 2) {
36
+ const item_r2 = i0.ɵɵnextContext(2).$implicit;
37
+ const ctx_r0 = i0.ɵɵnextContext();
38
+ i0.ɵɵclassProp("turn--user", item_r2.Role === "User")("turn--agent", item_r2.Role === "Assistant");
39
+ i0.ɵɵadvance(2);
40
+ i0.ɵɵtextInterpolate((item_r2.Role === "User" ? ctx_r0.UserName : ctx_r0.AgentName).charAt(0).toUpperCase());
41
+ i0.ɵɵadvance(3);
42
+ i0.ɵɵconditional(item_r2.Role === "User" ? 5 : 6);
43
+ i0.ɵɵadvance(3);
44
+ i0.ɵɵtextInterpolate(item_r2.Text);
45
+ } }
46
+ function RealtimeSessionThreadComponent_For_2_Case_0_Template(rf, ctx) { if (rf & 1) {
47
+ i0.ɵɵconditionalCreate(0, RealtimeSessionThreadComponent_For_2_Case_0_Conditional_0_Template, 9, 7, "div", 5);
48
+ } if (rf & 2) {
49
+ const ctx_r0 = i0.ɵɵnextContext(2);
50
+ i0.ɵɵconditional(ctx_r0.ShowCaptions ? 0 : -1);
51
+ } }
52
+ function RealtimeSessionThreadComponent_For_2_Case_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
53
+ i0.ɵɵelementStart(0, "span", 16);
54
+ i0.ɵɵtext(1);
55
+ i0.ɵɵpipe(2, "date");
56
+ i0.ɵɵelementEnd();
57
+ } if (rf & 2) {
58
+ const item_r2 = i0.ɵɵnextContext(2).$implicit;
59
+ i0.ɵɵadvance();
60
+ i0.ɵɵtextInterpolate1("\u00B7 ", i0.ɵɵpipeBind2(2, 1, item_r2.At, "MMM d, h:mm a"));
61
+ } }
62
+ function RealtimeSessionThreadComponent_For_2_Case_1_Conditional_6_Template(rf, ctx) { if (rf & 1) {
63
+ i0.ɵɵelementStart(0, "span", 17);
64
+ i0.ɵɵtext(1);
65
+ i0.ɵɵelementEnd();
66
+ } if (rf & 2) {
67
+ const item_r2 = i0.ɵɵnextContext(2).$implicit;
68
+ i0.ɵɵadvance();
69
+ i0.ɵɵtextInterpolate(item_r2.CloseReason);
70
+ } }
71
+ function RealtimeSessionThreadComponent_For_2_Case_1_Template(rf, ctx) { if (rf & 1) {
72
+ i0.ɵɵelementStart(0, "div", 3);
73
+ i0.ɵɵelement(1, "span", 13);
74
+ i0.ɵɵelementStart(2, "span", 14);
75
+ i0.ɵɵelement(3, "i", 15);
76
+ i0.ɵɵtext(4);
77
+ i0.ɵɵconditionalCreate(5, RealtimeSessionThreadComponent_For_2_Case_1_Conditional_5_Template, 3, 4, "span", 16);
78
+ i0.ɵɵelementEnd();
79
+ i0.ɵɵconditionalCreate(6, RealtimeSessionThreadComponent_For_2_Case_1_Conditional_6_Template, 2, 1, "span", 17);
80
+ i0.ɵɵelement(7, "span", 13);
81
+ i0.ɵɵelementEnd();
82
+ } if (rf & 2) {
83
+ const item_r2 = i0.ɵɵnextContext().$implicit;
84
+ i0.ɵɵadvance(3);
85
+ i0.ɵɵclassMap(item_r2.Icon);
86
+ i0.ɵɵadvance();
87
+ i0.ɵɵtextInterpolate1(" ", item_r2.Label, " ");
88
+ i0.ɵɵadvance();
89
+ i0.ɵɵconditional(item_r2.At ? 5 : -1);
90
+ i0.ɵɵadvance();
91
+ i0.ɵɵconditional(item_r2.CloseReason ? 6 : -1);
92
+ } }
93
+ function RealtimeSessionThreadComponent_For_2_Case_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
94
+ i0.ɵɵelementStart(0, "div", 19);
95
+ i0.ɵɵelement(1, "i", 20);
96
+ i0.ɵɵtext(2);
97
+ i0.ɵɵelementEnd();
98
+ } if (rf & 2) {
99
+ const ctx_r0 = i0.ɵɵnextContext(3);
100
+ i0.ɵɵadvance(2);
101
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.State.Narration, " ");
102
+ } }
103
+ function RealtimeSessionThreadComponent_For_2_Case_2_Template(rf, ctx) { if (rf & 1) {
104
+ const _r3 = i0.ɵɵgetCurrentView();
105
+ i0.ɵɵelementStart(0, "div", 4)(1, "mj-realtime-delegation-card", 18);
106
+ i0.ɵɵlistener("OpenRunRequested", function RealtimeSessionThreadComponent_For_2_Case_2_Template_mj_realtime_delegation_card_OpenRunRequested_1_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OpenRunRequested.emit($event)); })("OpenArtifactRequested", function RealtimeSessionThreadComponent_For_2_Case_2_Template_mj_realtime_delegation_card_OpenArtifactRequested_1_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OpenArtifactRequested.emit($event)); })("CancelRequested", function RealtimeSessionThreadComponent_For_2_Case_2_Template_mj_realtime_delegation_card_CancelRequested_1_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.CancelRequested.emit($event)); });
107
+ i0.ɵɵelementEnd();
108
+ i0.ɵɵconditionalCreate(2, RealtimeSessionThreadComponent_For_2_Case_2_Conditional_2_Template, 3, 1, "div", 19);
109
+ i0.ɵɵelementEnd();
110
+ } if (rf & 2) {
111
+ const item_r2 = i0.ɵɵnextContext().$implicit;
112
+ const ctx_r0 = i0.ɵɵnextContext();
113
+ i0.ɵɵadvance();
114
+ i0.ɵɵproperty("Card", item_r2.Card)("DevMode", ctx_r0.DevMode);
115
+ i0.ɵɵadvance();
116
+ i0.ɵɵconditional(ctx_r0.ShowsLiveNote(item_r2) ? 2 : -1);
117
+ } }
118
+ function RealtimeSessionThreadComponent_For_2_Template(rf, ctx) { if (rf & 1) {
119
+ i0.ɵɵconditionalCreate(0, RealtimeSessionThreadComponent_For_2_Case_0_Template, 1, 1)(1, RealtimeSessionThreadComponent_For_2_Case_1_Template, 8, 5, "div", 3)(2, RealtimeSessionThreadComponent_For_2_Case_2_Template, 3, 3, "div", 4);
120
+ } if (rf & 2) {
121
+ let tmp_11_0;
122
+ const item_r2 = ctx.$implicit;
123
+ i0.ɵɵconditional((tmp_11_0 = item_r2.Kind) === "caption" ? 0 : tmp_11_0 === "divider" ? 1 : tmp_11_0 === "delegation" ? 2 : -1);
124
+ } }
125
+ function RealtimeSessionThreadComponent_ForEmpty_3_Template(rf, ctx) { if (rf & 1) {
126
+ i0.ɵɵelementStart(0, "div", 2);
127
+ i0.ɵɵtext(1, "The live transcript and any delegated work will appear here.");
128
+ i0.ɵɵelementEnd();
129
+ } }
130
+ /**
131
+ * The unified, chronological live thread for the call overlay: caption bubbles
132
+ * interleaved with delegation cards exactly where they happened.
133
+ *
134
+ * PURELY PRESENTATIONAL over {@link RealtimeSessionState} — the overlay shell owns the
135
+ * state object (which merges the service streams once) and passes it here AND to the
136
+ * activity rail, so there is exactly one copy of the per-CallID merge logic.
137
+ *
138
+ * Also renders the EPHEMERAL narration "live note": indented, muted, italic text under
139
+ * the ACTIVE working card (latest narration only — replaced, never accumulated).
140
+ */
141
+ export class RealtimeSessionThreadComponent {
142
+ scrollAnchor;
143
+ /** Display name of the agent (caption avatar / meta line). */
144
+ AgentName = 'Sage';
145
+ /**
146
+ * Display name of the signed-in user for their turns — consistent with the main
147
+ * chat's sender names, and ready for multi-user sessions where "You" stops meaning
148
+ * anything. Hosts bind the current user's name; the default keeps old hosts working.
149
+ */
150
+ UserName = 'You';
151
+ /** Shared live-session state, owned by the overlay shell. */
152
+ State;
153
+ /** Whether to render caption bubbles (toggled by the controls' captions button). */
154
+ ShowCaptions = true;
155
+ /** Whether developer affordances on delegation cards are revealed (gear-gated). */
156
+ DevMode = false;
157
+ /** Re-emitted from a delegation card's dev "Open run" link (the delegated run's ID). */
158
+ OpenRunRequested = new EventEmitter();
159
+ /** Re-emitted from a delegation card's "View" artifact chip (focuses the artifact's surface tab). */
160
+ OpenArtifactRequested = new EventEmitter();
161
+ /** Re-emitted from a WORKING delegation card's ✕ cancel affordance (the call's ID). */
162
+ CancelRequested = new EventEmitter();
163
+ /** Item count at the last change notification, to auto-scroll only when the list grows. */
164
+ lastItemCount = 0;
165
+ /** Drives auto-scroll: set whenever the list grows. */
166
+ pendingScroll = false;
167
+ changedSub;
168
+ cdr = inject(ChangeDetectorRef);
169
+ ngOnInit() {
170
+ this.changedSub = this.State.Changed$.subscribe(() => this.onStateChanged());
171
+ this.lastItemCount = this.State.Items.length;
172
+ }
173
+ ngAfterViewChecked() {
174
+ if (this.pendingScroll) {
175
+ this.pendingScroll = false;
176
+ this.scrollAnchor?.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'end' });
177
+ }
178
+ }
179
+ ngOnDestroy() {
180
+ this.changedSub?.unsubscribe();
181
+ }
182
+ /** track fn for the @for over thread items. */
183
+ TrackItem(index, item) {
184
+ switch (item.Kind) {
185
+ case 'delegation': return `d:${item.Card.CallID}`;
186
+ case 'divider': return `s:${index}`;
187
+ default: return `c:${index}`;
188
+ }
189
+ }
190
+ /** True when the live narration note should render under THIS delegation item. */
191
+ ShowsLiveNote(item) {
192
+ return item.Kind === 'delegation'
193
+ && !item.Card.Done
194
+ && this.State.Narration !== null
195
+ && item.Card.CallID === this.State.ActiveCallId;
196
+ }
197
+ /** Marks for check on every state change; auto-scrolls when the thread grew. */
198
+ onStateChanged() {
199
+ if (this.State.Items.length > this.lastItemCount) {
200
+ this.pendingScroll = true;
201
+ }
202
+ this.lastItemCount = this.State.Items.length;
203
+ this.cdr.markForCheck();
204
+ }
205
+ static ɵfac = function RealtimeSessionThreadComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RealtimeSessionThreadComponent)(); };
206
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RealtimeSessionThreadComponent, selectors: [["mj-realtime-session-thread"]], viewQuery: function RealtimeSessionThreadComponent_Query(rf, ctx) { if (rf & 1) {
207
+ i0.ɵɵviewQuery(_c0, 5);
208
+ } if (rf & 2) {
209
+ let _t;
210
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.scrollAnchor = _t.first);
211
+ } }, inputs: { AgentName: "AgentName", UserName: "UserName", State: "State", ShowCaptions: "ShowCaptions", DevMode: "DevMode" }, outputs: { OpenRunRequested: "OpenRunRequested", OpenArtifactRequested: "OpenArtifactRequested", CancelRequested: "CancelRequested" }, decls: 6, vars: 1, consts: [["scrollAnchor", ""], [1, "thread"], [1, "thread-empty"], ["role", "separator", 1, "thread-divider"], [1, "delegation-block"], [1, "turn", 3, "turn--user", "turn--agent"], [1, "turn"], [1, "turn-avatar"], [1, "turn-body"], [1, "turn-meta"], [1, "typed-tag"], [1, "bubble"], [1, "muted"], ["aria-hidden", "true", 1, "thread-divider__line"], [1, "thread-divider__label"], ["aria-hidden", "true"], [1, "thread-divider__time"], ["title", "Why the previous session leg ended", 1, "thread-divider__chip"], [3, "OpenRunRequested", "OpenArtifactRequested", "CancelRequested", "Card", "DevMode"], ["role", "status", "aria-live", "polite", 1, "live-note"], ["aria-hidden", "true", 1, "fa-solid", "fa-comment-dots"]], template: function RealtimeSessionThreadComponent_Template(rf, ctx) { if (rf & 1) {
212
+ i0.ɵɵelementStart(0, "div", 1);
213
+ i0.ɵɵrepeaterCreate(1, RealtimeSessionThreadComponent_For_2_Template, 3, 1, null, null, ctx.TrackItem, true, RealtimeSessionThreadComponent_ForEmpty_3_Template, 2, 0, "div", 2);
214
+ i0.ɵɵelement(4, "div", null, 0);
215
+ i0.ɵɵelementEnd();
216
+ } if (rf & 2) {
217
+ i0.ɵɵadvance();
218
+ i0.ɵɵrepeater(ctx.State.Items);
219
+ } }, dependencies: [CommonModule, RealtimeDelegationCardComponent, i1.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n}\n\n.thread[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.thread-empty[_ngcontent-%COMP%] {\n text-align: center;\n font-size: 12.5px;\n color: var(--mj-text-disabled);\n padding: 24px 0;\n}\n\n\n\n.turn[_ngcontent-%COMP%] {\n display: flex;\n gap: 10px;\n max-width: 100%;\n}\n.turn--user[_ngcontent-%COMP%] {\n flex-direction: row-reverse;\n}\n.turn-body[_ngcontent-%COMP%] {\n min-width: 0;\n}\n.turn-avatar[_ngcontent-%COMP%] {\n width: 26px;\n height: 26px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n flex-shrink: 0;\n font-size: 11px;\n font-weight: 700;\n margin-top: 2px;\n}\n.turn--agent[_ngcontent-%COMP%] .turn-avatar[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--mj-brand-primary), var(--mj-brand-accent, var(--mj-brand-primary)));\n color: var(--mj-text-inverse, #fff);\n}\n.turn--user[_ngcontent-%COMP%] .turn-avatar[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-elevated);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-strong);\n}\n.bubble[_ngcontent-%COMP%] {\n padding: 8px 12px;\n border-radius: 12px;\n max-width: 560px;\n font-size: 13.5px;\n line-height: 1.5;\n position: relative;\n}\n.turn--agent[_ngcontent-%COMP%] .bubble[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-top-left-radius: 4px;\n color: var(--mj-text-primary);\n}\n.turn--user[_ngcontent-%COMP%] .bubble[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n border-top-right-radius: 4px;\n}\n.turn-meta[_ngcontent-%COMP%] {\n font-size: 10.5px;\n color: var(--mj-text-muted);\n margin-bottom: 3px;\n display: flex;\n align-items: center;\n gap: 6px;\n font-weight: 600;\n}\n.turn--user[_ngcontent-%COMP%] .turn-meta[_ngcontent-%COMP%] {\n justify-content: flex-end;\n}\n.muted[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n.typed-tag[_ngcontent-%COMP%] {\n font-size: 9.5px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n padding: 1px 5px;\n}\n\n\n\n.delegation-block[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.live-note[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 7px;\n margin-left: 22px;\n max-width: 520px;\n font-size: 12px;\n font-style: italic;\n color: var(--mj-text-muted);\n animation: _ngcontent-%COMP%_live-note-in 220ms ease;\n}\n.live-note[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n margin-top: 3px;\n flex-shrink: 0;\n}\n@keyframes _ngcontent-%COMP%_live-note-in {\n from { opacity: 0; transform: translateY(2px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n\n\n.thread-divider[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 10px 0 6px;\n user-select: none;\n}\n.thread-divider__line[_ngcontent-%COMP%] {\n flex: 1;\n height: 1px;\n background: var(--mj-border-subtle);\n}\n.thread-divider__label[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n.thread-divider__label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n.thread-divider__time[_ngcontent-%COMP%] {\n font-weight: 400;\n}\n.thread-divider__chip[_ngcontent-%COMP%] {\n font-size: 9.5px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n padding: 1px 7px;\n background: var(--mj-bg-surface-card);\n white-space: nowrap;\n}"] });
220
+ }
221
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RealtimeSessionThreadComponent, [{
222
+ type: Component,
223
+ args: [{ standalone: true, selector: 'mj-realtime-session-thread', imports: [CommonModule, RealtimeDelegationCardComponent], template: "<div class=\"thread\">\n @for (item of State.Items; track TrackItem($index, item)) {\n @switch (item.Kind) {\n @case ('caption') {\n @if (ShowCaptions) {\n <div class=\"turn\" [class.turn--user]=\"item.Role === 'User'\" [class.turn--agent]=\"item.Role === 'Assistant'\">\n <div class=\"turn-avatar\">{{ (item.Role === 'User' ? UserName : AgentName).charAt(0).toUpperCase() }}</div>\n <div class=\"turn-body\">\n <div class=\"turn-meta\">\n @if (item.Role === 'User') {\n <span class=\"typed-tag\">{{ UserName }}</span>\n } @else {\n {{ AgentName }} <span class=\"muted\">\u00B7 voice</span>\n }\n </div>\n <div class=\"bubble\">{{ item.Text }}</div>\n </div>\n </div>\n }\n }\n @case ('divider') {\n <!-- Session-leg boundary: subtle rule marking a resume / chained leg -->\n <div class=\"thread-divider\" role=\"separator\">\n <span class=\"thread-divider__line\" aria-hidden=\"true\"></span>\n <span class=\"thread-divider__label\">\n <i [class]=\"item.Icon\" aria-hidden=\"true\"></i>\n {{ item.Label }}\n @if (item.At) {\n <span class=\"thread-divider__time\">\u00B7 {{ item.At | date:'MMM d, h:mm a' }}</span>\n }\n </span>\n @if (item.CloseReason) {\n <span class=\"thread-divider__chip\" title=\"Why the previous session leg ended\">{{ item.CloseReason }}</span>\n }\n <span class=\"thread-divider__line\" aria-hidden=\"true\"></span>\n </div>\n }\n @case ('delegation') {\n <div class=\"delegation-block\">\n <mj-realtime-delegation-card\n [Card]=\"item.Card\"\n [DevMode]=\"DevMode\"\n (OpenRunRequested)=\"OpenRunRequested.emit($event)\"\n (OpenArtifactRequested)=\"OpenArtifactRequested.emit($event)\"\n (CancelRequested)=\"CancelRequested.emit($event)\">\n </mj-realtime-delegation-card>\n @if (ShowsLiveNote(item)) {\n <!-- Ephemeral narration: latest only, never persisted, fades with completion -->\n <div class=\"live-note\" role=\"status\" aria-live=\"polite\">\n <i class=\"fa-solid fa-comment-dots\" aria-hidden=\"true\"></i>\n {{ State.Narration }}\n </div>\n }\n </div>\n }\n }\n } @empty {\n <div class=\"thread-empty\">The live transcript and any delegated work will appear here.</div>\n }\n <div #scrollAnchor></div>\n</div>\n", styles: [":host {\n display: block;\n}\n\n.thread {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.thread-empty {\n text-align: center;\n font-size: 12.5px;\n color: var(--mj-text-disabled);\n padding: 24px 0;\n}\n\n/* ---------- Transcript bubbles ---------- */\n.turn {\n display: flex;\n gap: 10px;\n max-width: 100%;\n}\n.turn--user {\n flex-direction: row-reverse;\n}\n.turn-body {\n min-width: 0;\n}\n.turn-avatar {\n width: 26px;\n height: 26px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n flex-shrink: 0;\n font-size: 11px;\n font-weight: 700;\n margin-top: 2px;\n}\n.turn--agent .turn-avatar {\n background: linear-gradient(135deg, var(--mj-brand-primary), var(--mj-brand-accent, var(--mj-brand-primary)));\n color: var(--mj-text-inverse, #fff);\n}\n.turn--user .turn-avatar {\n background: var(--mj-bg-surface-elevated);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-strong);\n}\n.bubble {\n padding: 8px 12px;\n border-radius: 12px;\n max-width: 560px;\n font-size: 13.5px;\n line-height: 1.5;\n position: relative;\n}\n.turn--agent .bubble {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-top-left-radius: 4px;\n color: var(--mj-text-primary);\n}\n.turn--user .bubble {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n border-top-right-radius: 4px;\n}\n.turn-meta {\n font-size: 10.5px;\n color: var(--mj-text-muted);\n margin-bottom: 3px;\n display: flex;\n align-items: center;\n gap: 6px;\n font-weight: 600;\n}\n.turn--user .turn-meta {\n justify-content: flex-end;\n}\n.muted {\n color: var(--mj-text-muted);\n}\n.typed-tag {\n font-size: 9.5px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n padding: 1px 5px;\n}\n\n/* ---------- Delegation block + ephemeral live note ---------- */\n.delegation-block {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.live-note {\n display: flex;\n align-items: flex-start;\n gap: 7px;\n margin-left: 22px;\n max-width: 520px;\n font-size: 12px;\n font-style: italic;\n color: var(--mj-text-muted);\n animation: live-note-in 220ms ease;\n}\n.live-note i {\n font-size: 10px;\n margin-top: 3px;\n flex-shrink: 0;\n}\n@keyframes live-note-in {\n from { opacity: 0; transform: translateY(2px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* ---------- Session-leg divider (resume / chained-leg boundary) ---------- */\n.thread-divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 10px 0 6px;\n user-select: none;\n}\n.thread-divider__line {\n flex: 1;\n height: 1px;\n background: var(--mj-border-subtle);\n}\n.thread-divider__label {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n.thread-divider__label i {\n font-size: 10px;\n}\n.thread-divider__time {\n font-weight: 400;\n}\n.thread-divider__chip {\n font-size: 9.5px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n padding: 1px 7px;\n background: var(--mj-bg-surface-card);\n white-space: nowrap;\n}\n"] }]
224
+ }], null, { scrollAnchor: [{
225
+ type: ViewChild,
226
+ args: ['scrollAnchor']
227
+ }], AgentName: [{
228
+ type: Input
229
+ }], UserName: [{
230
+ type: Input
231
+ }], State: [{
232
+ type: Input,
233
+ args: [{ required: true }]
234
+ }], ShowCaptions: [{
235
+ type: Input
236
+ }], DevMode: [{
237
+ type: Input
238
+ }], OpenRunRequested: [{
239
+ type: Output
240
+ }], OpenArtifactRequested: [{
241
+ type: Output
242
+ }], CancelRequested: [{
243
+ type: Output
244
+ }] }); })();
245
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RealtimeSessionThreadComponent, { className: "RealtimeSessionThreadComponent", filePath: "src/lib/components/realtime/realtime-session-thread.component.ts", lineNumber: 29 }); })();
246
+ //# sourceMappingURL=realtime-session-thread.component.js.map