@memberjunction/ng-conversations 5.40.2 → 5.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/README.md +57 -0
  2. package/dist/__tests__/channel-optional-surface.test.d.ts +2 -0
  3. package/dist/__tests__/channel-optional-surface.test.d.ts.map +1 -0
  4. package/dist/__tests__/channel-optional-surface.test.js +53 -0
  5. package/dist/__tests__/channel-optional-surface.test.js.map +1 -0
  6. package/dist/__tests__/chat-events.test.d.ts +14 -0
  7. package/dist/__tests__/chat-events.test.d.ts.map +1 -0
  8. package/dist/__tests__/chat-events.test.js +109 -0
  9. package/dist/__tests__/chat-events.test.js.map +1 -0
  10. package/dist/__tests__/conversation-naming.test.d.ts +2 -0
  11. package/dist/__tests__/conversation-naming.test.d.ts.map +1 -0
  12. package/dist/__tests__/conversation-naming.test.js +110 -0
  13. package/dist/__tests__/conversation-naming.test.js.map +1 -0
  14. package/dist/__tests__/delegation-result-parser.test.d.ts +2 -0
  15. package/dist/__tests__/delegation-result-parser.test.d.ts.map +1 -0
  16. package/dist/__tests__/delegation-result-parser.test.js +107 -0
  17. package/dist/__tests__/delegation-result-parser.test.js.map +1 -0
  18. package/dist/__tests__/event-wiring.test.d.ts +15 -0
  19. package/dist/__tests__/event-wiring.test.d.ts.map +1 -0
  20. package/dist/__tests__/event-wiring.test.js +100 -0
  21. package/dist/__tests__/event-wiring.test.js.map +1 -0
  22. package/dist/__tests__/narration-template.test.d.ts +2 -0
  23. package/dist/__tests__/narration-template.test.d.ts.map +1 -0
  24. package/dist/__tests__/narration-template.test.js +76 -0
  25. package/dist/__tests__/narration-template.test.js.map +1 -0
  26. package/dist/__tests__/realtime-agent-picker-models.test.d.ts +2 -0
  27. package/dist/__tests__/realtime-agent-picker-models.test.d.ts.map +1 -0
  28. package/dist/__tests__/realtime-agent-picker-models.test.js +49 -0
  29. package/dist/__tests__/realtime-agent-picker-models.test.js.map +1 -0
  30. package/dist/__tests__/realtime-audio-visuals.test.d.ts +2 -0
  31. package/dist/__tests__/realtime-audio-visuals.test.d.ts.map +1 -0
  32. package/dist/__tests__/realtime-audio-visuals.test.js +123 -0
  33. package/dist/__tests__/realtime-audio-visuals.test.js.map +1 -0
  34. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts +2 -0
  35. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts.map +1 -0
  36. package/dist/__tests__/realtime-delegation-card-cancel.test.js +48 -0
  37. package/dist/__tests__/realtime-delegation-card-cancel.test.js.map +1 -0
  38. package/dist/__tests__/realtime-disclosure.test.d.ts +2 -0
  39. package/dist/__tests__/realtime-disclosure.test.d.ts.map +1 -0
  40. package/dist/__tests__/realtime-disclosure.test.js +164 -0
  41. package/dist/__tests__/realtime-disclosure.test.js.map +1 -0
  42. package/dist/__tests__/realtime-pairing.test.d.ts +2 -0
  43. package/dist/__tests__/realtime-pairing.test.d.ts.map +1 -0
  44. package/dist/__tests__/realtime-pairing.test.js +207 -0
  45. package/dist/__tests__/realtime-pairing.test.js.map +1 -0
  46. package/dist/__tests__/realtime-review-lifecycle.test.d.ts +2 -0
  47. package/dist/__tests__/realtime-review-lifecycle.test.d.ts.map +1 -0
  48. package/dist/__tests__/realtime-review-lifecycle.test.js +154 -0
  49. package/dist/__tests__/realtime-review-lifecycle.test.js.map +1 -0
  50. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts +2 -0
  51. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts.map +1 -0
  52. package/dist/__tests__/realtime-session-cancel-usage.test.js +230 -0
  53. package/dist/__tests__/realtime-session-cancel-usage.test.js.map +1 -0
  54. package/dist/__tests__/realtime-session-channels.test.d.ts +2 -0
  55. package/dist/__tests__/realtime-session-channels.test.d.ts.map +1 -0
  56. package/dist/__tests__/realtime-session-channels.test.js +252 -0
  57. package/dist/__tests__/realtime-session-channels.test.js.map +1 -0
  58. package/dist/__tests__/realtime-session-client-tools.test.d.ts +2 -0
  59. package/dist/__tests__/realtime-session-client-tools.test.d.ts.map +1 -0
  60. package/dist/__tests__/realtime-session-client-tools.test.js +103 -0
  61. package/dist/__tests__/realtime-session-client-tools.test.js.map +1 -0
  62. package/dist/__tests__/realtime-session-minimized.test.d.ts +2 -0
  63. package/dist/__tests__/realtime-session-minimized.test.d.ts.map +1 -0
  64. package/dist/__tests__/realtime-session-minimized.test.js +32 -0
  65. package/dist/__tests__/realtime-session-minimized.test.js.map +1 -0
  66. package/dist/__tests__/realtime-session-mint.test.d.ts +2 -0
  67. package/dist/__tests__/realtime-session-mint.test.d.ts.map +1 -0
  68. package/dist/__tests__/realtime-session-mint.test.js +69 -0
  69. package/dist/__tests__/realtime-session-mint.test.js.map +1 -0
  70. package/dist/__tests__/realtime-session-policy.test.d.ts +2 -0
  71. package/dist/__tests__/realtime-session-policy.test.d.ts.map +1 -0
  72. package/dist/__tests__/realtime-session-policy.test.js +303 -0
  73. package/dist/__tests__/realtime-session-policy.test.js.map +1 -0
  74. package/dist/__tests__/realtime-session-review.service.test.d.ts +2 -0
  75. package/dist/__tests__/realtime-session-review.service.test.d.ts.map +1 -0
  76. package/dist/__tests__/realtime-session-review.service.test.js +743 -0
  77. package/dist/__tests__/realtime-session-review.service.test.js.map +1 -0
  78. package/dist/__tests__/realtime-session-state.test.d.ts +2 -0
  79. package/dist/__tests__/realtime-session-state.test.d.ts.map +1 -0
  80. package/dist/__tests__/realtime-session-state.test.js +83 -0
  81. package/dist/__tests__/realtime-session-state.test.js.map +1 -0
  82. package/dist/__tests__/realtime-session-timeline-card.test.d.ts +2 -0
  83. package/dist/__tests__/realtime-session-timeline-card.test.d.ts.map +1 -0
  84. package/dist/__tests__/realtime-session-timeline-card.test.js +106 -0
  85. package/dist/__tests__/realtime-session-timeline-card.test.js.map +1 -0
  86. package/dist/__tests__/realtime-session-timeline.test.d.ts +2 -0
  87. package/dist/__tests__/realtime-session-timeline.test.d.ts.map +1 -0
  88. package/dist/__tests__/realtime-session-timeline.test.js +142 -0
  89. package/dist/__tests__/realtime-session-timeline.test.js.map +1 -0
  90. package/dist/__tests__/realtime-sessions-adapter.test.d.ts +19 -0
  91. package/dist/__tests__/realtime-sessions-adapter.test.d.ts.map +1 -0
  92. package/dist/__tests__/realtime-sessions-adapter.test.js +188 -0
  93. package/dist/__tests__/realtime-sessions-adapter.test.js.map +1 -0
  94. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts +2 -0
  95. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts.map +1 -0
  96. package/dist/__tests__/realtime-surface-panel-prefs.test.js +100 -0
  97. package/dist/__tests__/realtime-surface-panel-prefs.test.js.map +1 -0
  98. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts +2 -0
  99. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts.map +1 -0
  100. package/dist/__tests__/realtime-surface-tabs-model.test.js +193 -0
  101. package/dist/__tests__/realtime-surface-tabs-model.test.js.map +1 -0
  102. package/dist/__tests__/remote-browser-audio-player.test.d.ts +2 -0
  103. package/dist/__tests__/remote-browser-audio-player.test.d.ts.map +1 -0
  104. package/dist/__tests__/remote-browser-audio-player.test.js +137 -0
  105. package/dist/__tests__/remote-browser-audio-player.test.js.map +1 -0
  106. package/dist/__tests__/remote-browser-channel.test.d.ts +2 -0
  107. package/dist/__tests__/remote-browser-channel.test.d.ts.map +1 -0
  108. package/dist/__tests__/remote-browser-channel.test.js +423 -0
  109. package/dist/__tests__/remote-browser-channel.test.js.map +1 -0
  110. package/dist/__tests__/slot-defaults.test.d.ts +24 -0
  111. package/dist/__tests__/slot-defaults.test.d.ts.map +1 -0
  112. package/dist/__tests__/slot-defaults.test.js +63 -0
  113. package/dist/__tests__/slot-defaults.test.js.map +1 -0
  114. package/dist/__tests__/user-authorization.test.d.ts +2 -0
  115. package/dist/__tests__/user-authorization.test.d.ts.map +1 -0
  116. package/dist/__tests__/user-authorization.test.js +97 -0
  117. package/dist/__tests__/user-authorization.test.js.map +1 -0
  118. package/dist/__tests__/voice-session-narration.test.d.ts +2 -0
  119. package/dist/__tests__/voice-session-narration.test.d.ts.map +1 -0
  120. package/dist/__tests__/voice-session-narration.test.js +609 -0
  121. package/dist/__tests__/voice-session-narration.test.js.map +1 -0
  122. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts +2 -0
  123. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts.map +1 -0
  124. package/dist/__tests__/whiteboard-artifact-viewer.test.js +101 -0
  125. package/dist/__tests__/whiteboard-artifact-viewer.test.js.map +1 -0
  126. package/dist/__tests__/whiteboard-channel.test.d.ts +2 -0
  127. package/dist/__tests__/whiteboard-channel.test.d.ts.map +1 -0
  128. package/dist/__tests__/whiteboard-channel.test.js +260 -0
  129. package/dist/__tests__/whiteboard-channel.test.js.map +1 -0
  130. package/dist/__tests__/whiteboard-restore-state.test.d.ts +2 -0
  131. package/dist/__tests__/whiteboard-restore-state.test.d.ts.map +1 -0
  132. package/dist/__tests__/whiteboard-restore-state.test.js +108 -0
  133. package/dist/__tests__/whiteboard-restore-state.test.js.map +1 -0
  134. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +205 -3
  135. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  136. package/dist/lib/components/conversation/conversation-chat-area.component.js +911 -342
  137. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  138. package/dist/lib/components/mention/mention-dropdown.component.js +35 -17
  139. package/dist/lib/components/mention/mention-dropdown.component.js.map +1 -1
  140. package/dist/lib/components/mention/mention-editor.component.d.ts +4 -0
  141. package/dist/lib/components/mention/mention-editor.component.d.ts.map +1 -1
  142. package/dist/lib/components/mention/mention-editor.component.js +43 -19
  143. package/dist/lib/components/mention/mention-editor.component.js.map +1 -1
  144. package/dist/lib/components/message/message-input-box.component.d.ts +17 -1
  145. package/dist/lib/components/message/message-input-box.component.d.ts.map +1 -1
  146. package/dist/lib/components/message/message-input-box.component.js +73 -15
  147. package/dist/lib/components/message/message-input-box.component.js.map +1 -1
  148. package/dist/lib/components/message/message-input.component.d.ts +142 -6
  149. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  150. package/dist/lib/components/message/message-input.component.js +328 -82
  151. package/dist/lib/components/message/message-input.component.js.map +1 -1
  152. package/dist/lib/components/message/message-item.component.d.ts +28 -3
  153. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  154. package/dist/lib/components/message/message-item.component.js +180 -108
  155. package/dist/lib/components/message/message-item.component.js.map +1 -1
  156. package/dist/lib/components/message/message-list.component.d.ts +81 -2
  157. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  158. package/dist/lib/components/message/message-list.component.js +252 -87
  159. package/dist/lib/components/message/message-list.component.js.map +1 -1
  160. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +282 -0
  161. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +1 -0
  162. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +158 -0
  163. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +1 -0
  164. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts +25 -0
  165. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts.map +1 -0
  166. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.js +140 -0
  167. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.js.map +1 -0
  168. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +35 -0
  169. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -0
  170. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +58 -0
  171. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -0
  172. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +63 -0
  173. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -0
  174. package/dist/lib/components/realtime/realtime-activity-rail.component.js +260 -0
  175. package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -0
  176. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +117 -0
  177. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -0
  178. package/dist/lib/components/realtime/realtime-agent-banner.component.js +504 -0
  179. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -0
  180. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +168 -0
  181. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -0
  182. package/dist/lib/components/realtime/realtime-agent-picker.component.js +556 -0
  183. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -0
  184. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +97 -0
  185. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -0
  186. package/dist/lib/components/realtime/realtime-audio-visuals.js +139 -0
  187. package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -0
  188. package/dist/lib/components/realtime/realtime-channel-strip.component.d.ts +29 -0
  189. package/dist/lib/components/realtime/realtime-channel-strip.component.d.ts.map +1 -0
  190. package/dist/lib/components/realtime/realtime-channel-strip.component.js +69 -0
  191. package/dist/lib/components/realtime/realtime-channel-strip.component.js.map +1 -0
  192. package/dist/lib/components/realtime/realtime-composer.component.d.ts +65 -0
  193. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -0
  194. package/dist/lib/components/realtime/realtime-composer.component.js +256 -0
  195. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -0
  196. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +71 -0
  197. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -0
  198. package/dist/lib/components/realtime/realtime-delegation-card.component.js +324 -0
  199. package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -0
  200. package/dist/lib/components/realtime/realtime-disclosure.d.ts +135 -0
  201. package/dist/lib/components/realtime/realtime-disclosure.d.ts.map +1 -0
  202. package/dist/lib/components/realtime/realtime-disclosure.js +188 -0
  203. package/dist/lib/components/realtime/realtime-disclosure.js.map +1 -0
  204. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +491 -0
  205. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -0
  206. package/dist/lib/components/realtime/realtime-session-overlay.component.js +1274 -0
  207. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -0
  208. package/dist/lib/components/realtime/realtime-session-state.d.ts +191 -0
  209. package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -0
  210. package/dist/lib/components/realtime/realtime-session-state.js +244 -0
  211. package/dist/lib/components/realtime/realtime-session-state.js.map +1 -0
  212. package/dist/lib/components/realtime/realtime-session-thread.component.d.ts +56 -0
  213. package/dist/lib/components/realtime/realtime-session-thread.component.d.ts.map +1 -0
  214. package/dist/lib/components/realtime/realtime-session-thread.component.js +246 -0
  215. package/dist/lib/components/realtime/realtime-session-thread.component.js.map +1 -0
  216. package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts +51 -0
  217. package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts.map +1 -0
  218. package/dist/lib/components/realtime/realtime-session-timeline-card.component.js +193 -0
  219. package/dist/lib/components/realtime/realtime-session-timeline-card.component.js.map +1 -0
  220. package/dist/lib/components/realtime/realtime-surface-panel-prefs.d.ts +77 -0
  221. package/dist/lib/components/realtime/realtime-surface-panel-prefs.d.ts.map +1 -0
  222. package/dist/lib/components/realtime/realtime-surface-panel-prefs.js +114 -0
  223. package/dist/lib/components/realtime/realtime-surface-panel-prefs.js.map +1 -0
  224. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +173 -0
  225. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -0
  226. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +496 -0
  227. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -0
  228. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +181 -0
  229. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -0
  230. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +223 -0
  231. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -0
  232. package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.d.ts +163 -0
  233. package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.d.ts.map +1 -0
  234. package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.js +309 -0
  235. package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.js.map +1 -0
  236. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +168 -0
  237. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -0
  238. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +524 -0
  239. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -0
  240. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts +346 -0
  241. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts.map +1 -0
  242. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js +851 -0
  243. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js.map +1 -0
  244. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.d.ts +86 -0
  245. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.d.ts.map +1 -0
  246. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.js +210 -0
  247. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.js.map +1 -0
  248. package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.d.ts +48 -0
  249. package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.d.ts.map +1 -0
  250. package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.js +180 -0
  251. package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.js.map +1 -0
  252. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +119 -0
  253. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -0
  254. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +274 -0
  255. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -0
  256. package/dist/lib/components/slots/mj-chat-agent-presence-default.component.d.ts +11 -0
  257. package/dist/lib/components/slots/mj-chat-agent-presence-default.component.d.ts.map +1 -0
  258. package/dist/lib/components/slots/mj-chat-agent-presence-default.component.js +98 -0
  259. package/dist/lib/components/slots/mj-chat-agent-presence-default.component.js.map +1 -0
  260. package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.d.ts +9 -0
  261. package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.d.ts.map +1 -0
  262. package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.js +35 -0
  263. package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.js.map +1 -0
  264. package/dist/lib/components/slots/mj-chat-empty-state-default.component.d.ts +28 -0
  265. package/dist/lib/components/slots/mj-chat-empty-state-default.component.d.ts.map +1 -0
  266. package/dist/lib/components/slots/mj-chat-empty-state-default.component.js +104 -0
  267. package/dist/lib/components/slots/mj-chat-empty-state-default.component.js.map +1 -0
  268. package/dist/lib/components/slots/mj-chat-header-default.component.d.ts +11 -0
  269. package/dist/lib/components/slots/mj-chat-header-default.component.d.ts.map +1 -0
  270. package/dist/lib/components/slots/mj-chat-header-default.component.js +103 -0
  271. package/dist/lib/components/slots/mj-chat-header-default.component.js.map +1 -0
  272. package/dist/lib/components/slots/mj-chat-message-bubble-default.component.d.ts +15 -0
  273. package/dist/lib/components/slots/mj-chat-message-bubble-default.component.d.ts.map +1 -0
  274. package/dist/lib/components/slots/mj-chat-message-bubble-default.component.js +73 -0
  275. package/dist/lib/components/slots/mj-chat-message-bubble-default.component.js.map +1 -0
  276. package/dist/lib/components/slots/mj-chat-message-extra-default.component.d.ts +9 -0
  277. package/dist/lib/components/slots/mj-chat-message-extra-default.component.d.ts.map +1 -0
  278. package/dist/lib/components/slots/mj-chat-message-extra-default.component.js +34 -0
  279. package/dist/lib/components/slots/mj-chat-message-extra-default.component.js.map +1 -0
  280. package/dist/lib/components/slots/slot-interfaces.d.ts +95 -0
  281. package/dist/lib/components/slots/slot-interfaces.d.ts.map +1 -0
  282. package/dist/lib/components/slots/slot-interfaces.js +18 -0
  283. package/dist/lib/components/slots/slot-interfaces.js.map +1 -0
  284. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +11 -0
  285. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  286. package/dist/lib/components/workspace/conversation-workspace.component.js +28 -4
  287. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  288. package/dist/lib/conversations.module.d.ts +12 -1
  289. package/dist/lib/conversations.module.d.ts.map +1 -1
  290. package/dist/lib/conversations.module.js +93 -5
  291. package/dist/lib/conversations.module.js.map +1 -1
  292. package/dist/lib/directives/chat-slot.directive.d.ts +44 -0
  293. package/dist/lib/directives/chat-slot.directive.d.ts.map +1 -0
  294. package/dist/lib/directives/chat-slot.directive.js +54 -0
  295. package/dist/lib/directives/chat-slot.directive.js.map +1 -0
  296. package/dist/lib/events/chat-events.d.ts +137 -0
  297. package/dist/lib/events/chat-events.d.ts.map +1 -0
  298. package/dist/lib/events/chat-events.js +189 -0
  299. package/dist/lib/events/chat-events.js.map +1 -0
  300. package/dist/lib/models/conversation-state.model.d.ts +2 -1
  301. package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
  302. package/dist/lib/models/conversation-state.model.js.map +1 -1
  303. package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
  304. package/dist/lib/services/artifact-state.service.js +23 -6
  305. package/dist/lib/services/artifact-state.service.js.map +1 -1
  306. package/dist/lib/services/conversation-agent.service.d.ts +60 -74
  307. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  308. package/dist/lib/services/conversation-agent.service.js +100 -313
  309. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  310. package/dist/lib/services/conversation-bridge.service.d.ts +11 -70
  311. package/dist/lib/services/conversation-bridge.service.d.ts.map +1 -1
  312. package/dist/lib/services/conversation-bridge.service.js +51 -85
  313. package/dist/lib/services/conversation-bridge.service.js.map +1 -1
  314. package/dist/lib/services/conversation-naming.d.ts +63 -0
  315. package/dist/lib/services/conversation-naming.d.ts.map +1 -0
  316. package/dist/lib/services/conversation-naming.js +58 -0
  317. package/dist/lib/services/conversation-naming.js.map +1 -0
  318. package/dist/lib/services/conversation-streaming.service.d.ts +24 -154
  319. package/dist/lib/services/conversation-streaming.service.d.ts.map +1 -1
  320. package/dist/lib/services/conversation-streaming.service.js +39 -361
  321. package/dist/lib/services/conversation-streaming.service.js.map +1 -1
  322. package/dist/lib/services/conversations-runtime-bootstrap.service.d.ts +10 -0
  323. package/dist/lib/services/conversations-runtime-bootstrap.service.d.ts.map +1 -0
  324. package/dist/lib/services/conversations-runtime-bootstrap.service.js +104 -0
  325. package/dist/lib/services/conversations-runtime-bootstrap.service.js.map +1 -0
  326. package/dist/lib/services/delegation-result-parser.d.ts +45 -0
  327. package/dist/lib/services/delegation-result-parser.d.ts.map +1 -0
  328. package/dist/lib/services/delegation-result-parser.js +48 -0
  329. package/dist/lib/services/delegation-result-parser.js.map +1 -0
  330. package/dist/lib/services/mention-autocomplete.service.d.ts +19 -4
  331. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  332. package/dist/lib/services/mention-autocomplete.service.js +65 -4
  333. package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
  334. package/dist/lib/services/mention-parser.service.d.ts +8 -53
  335. package/dist/lib/services/mention-parser.service.d.ts.map +1 -1
  336. package/dist/lib/services/mention-parser.service.js +32 -243
  337. package/dist/lib/services/mention-parser.service.js.map +1 -1
  338. package/dist/lib/services/narration-template.d.ts +42 -0
  339. package/dist/lib/services/narration-template.d.ts.map +1 -0
  340. package/dist/lib/services/narration-template.js +73 -0
  341. package/dist/lib/services/narration-template.js.map +1 -0
  342. package/dist/lib/services/realtime-pairing.d.ts +120 -0
  343. package/dist/lib/services/realtime-pairing.d.ts.map +1 -0
  344. package/dist/lib/services/realtime-pairing.js +150 -0
  345. package/dist/lib/services/realtime-pairing.js.map +1 -0
  346. package/dist/lib/services/realtime-session-review.service.d.ts +233 -0
  347. package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -0
  348. package/dist/lib/services/realtime-session-review.service.js +417 -0
  349. package/dist/lib/services/realtime-session-review.service.js.map +1 -0
  350. package/dist/lib/services/realtime-session.service.d.ts +739 -0
  351. package/dist/lib/services/realtime-session.service.d.ts.map +1 -0
  352. package/dist/lib/services/realtime-session.service.js +1647 -0
  353. package/dist/lib/services/realtime-session.service.js.map +1 -0
  354. package/dist/lib/services/realtime-sessions-adapter.d.ts +54 -0
  355. package/dist/lib/services/realtime-sessions-adapter.d.ts.map +1 -0
  356. package/dist/lib/services/realtime-sessions-adapter.js +154 -0
  357. package/dist/lib/services/realtime-sessions-adapter.js.map +1 -0
  358. package/dist/lib/services/user-authorization.d.ts +67 -0
  359. package/dist/lib/services/user-authorization.d.ts.map +1 -0
  360. package/dist/lib/services/user-authorization.js +66 -0
  361. package/dist/lib/services/user-authorization.js.map +1 -0
  362. package/dist/lib/utils/realtime-session-timeline.d.ts +84 -0
  363. package/dist/lib/utils/realtime-session-timeline.d.ts.map +1 -0
  364. package/dist/lib/utils/realtime-session-timeline.js +94 -0
  365. package/dist/lib/utils/realtime-session-timeline.js.map +1 -0
  366. package/dist/public-api.d.ts +41 -0
  367. package/dist/public-api.d.ts.map +1 -1
  368. package/dist/public-api.js +50 -0
  369. package/dist/public-api.js.map +1 -1
  370. package/package.json +27 -24
  371. package/dist/__tests__/conversation-bridge.service.test.d.ts +0 -2
  372. package/dist/__tests__/conversation-bridge.service.test.d.ts.map +0 -1
  373. package/dist/__tests__/conversation-bridge.service.test.js +0 -98
  374. package/dist/__tests__/conversation-bridge.service.test.js.map +0 -1
  375. package/dist/__tests__/mention-parser.test.d.ts +0 -2
  376. package/dist/__tests__/mention-parser.test.d.ts.map +0 -1
  377. package/dist/__tests__/mention-parser.test.js +0 -154
  378. package/dist/__tests__/mention-parser.test.js.map +0 -1
@@ -0,0 +1,181 @@
1
+ import { Subject } from 'rxjs';
2
+ import type { TemplateRef } from '@angular/core';
3
+ import type { BaseRealtimeChannelClient } from './channels/base-realtime-channel-client';
4
+ import { ParsedDelegationArtifact } from '../../services/delegation-result-parser';
5
+ /**
6
+ * The kind of a surface-panel tab:
7
+ * - `activity` — the always-present first tab hosting the session activity rail.
8
+ * - `artifact` — one tab per artifact produced by a delegated run (auto-opened on arrival).
9
+ * - `channel` — an interactive-channel surface (e.g. the Whiteboard). Registered per
10
+ * registry-resolved plugin via {@link RealtimeSurfaceTabsModel.RegisterChannelTab};
11
+ * renders the plugin's dynamically-created surface component (or a registered template
12
+ * for legacy/template-based panes), with the "coming online…" placeholder until either
13
+ * is supplied.
14
+ */
15
+ export type RealtimeSurfaceTabKind = 'activity' | 'artifact' | 'channel';
16
+ /**
17
+ * Per-kind payload carried on a {@link RealtimeSurfaceTab}.
18
+ */
19
+ export interface RealtimeSurfaceTabData {
20
+ /** For `artifact` tabs: the artifact this tab views (loaded by ArtifactID, latest version). */
21
+ Artifact?: ParsedDelegationArtifact;
22
+ /**
23
+ * For `channel` tabs: the channel PLUGIN whose surface component the pane creates
24
+ * dynamically (and binds back to the plugin) — the registry-driven path every real
25
+ * channel uses. Takes precedence over {@link Content}.
26
+ */
27
+ Plugin?: BaseRealtimeChannelClient;
28
+ /**
29
+ * For `channel` tabs: a TEMPLATE-based pane body. Backward-compatible alternative to
30
+ * {@link Plugin} for hosts that render a bespoke surface without a channel plugin.
31
+ * When BOTH are absent the pane renders the built-in "coming online…" placeholder.
32
+ */
33
+ Content?: TemplateRef<unknown>;
34
+ }
35
+ /**
36
+ * One tab on the call overlay's tabbed surface panel (the right panel): Activity, an
37
+ * artifact viewer, or an interactive-channel surface.
38
+ */
39
+ export interface RealtimeSurfaceTab {
40
+ /** Stable unique key (`activity`, `artifact:<versionId>`, or the channel's registered key). */
41
+ Key: string;
42
+ /** Tab strip label (artifact tabs use the artifact's name). */
43
+ Title: string;
44
+ /** Font Awesome icon class for the tab strip (e.g. `fa-solid fa-file-lines`). */
45
+ Icon: string;
46
+ /** What the tab renders. */
47
+ Kind: RealtimeSurfaceTabKind;
48
+ /** Kind-specific payload. */
49
+ Data?: RealtimeSurfaceTabData;
50
+ }
51
+ /**
52
+ * Registration for an interactive-channel tab. The overlay shell registers one per
53
+ * registry-resolved channel plugin (supplying {@link Plugin}); supplying {@link Plugin}
54
+ * or {@link Content} later under the same `Key` upgrades a placeholder tab to the real
55
+ * surface.
56
+ */
57
+ export interface RealtimeChannelTabRegistration {
58
+ /** Stable channel key (the plugin's `ChannelName`, e.g. `Whiteboard`). Re-registering the same key updates the tab. */
59
+ Key: string;
60
+ /** Tab strip label (e.g. `Whiteboard`). */
61
+ Title: string;
62
+ /** Font Awesome icon class (e.g. `fa-solid fa-chalkboard`). */
63
+ Icon: string;
64
+ /** The channel plugin whose surface the pane creates + binds. Preferred over {@link Content}. */
65
+ Plugin?: BaseRealtimeChannelClient;
66
+ /** A template-based pane body (legacy/bespoke panes). Omit both to show the "coming online…" placeholder. */
67
+ Content?: TemplateRef<unknown>;
68
+ /** Focus the tab immediately after registration (default `false`). */
69
+ Focus?: boolean;
70
+ }
71
+ /**
72
+ * Framework-free state for the call overlay's tabbed surface panel: the ordered tab list
73
+ * (CHANNEL tabs first — the marquee surfaces — then artifact tabs in arrival order, with
74
+ * Activity pinned LAST), the active tab, the transient "flash" highlight for a
75
+ * just-arrived tab, and the persistent UNSEEN glow for content that arrived without
76
+ * stealing focus (an artifact tab glows until the user visits it).
77
+ *
78
+ * Owned by `RealtimeSurfaceTabsComponent`; kept free of Angular runtime imports so the
79
+ * add / focus / dedupe / flash / unseen logic is unit-testable in isolation. All
80
+ * collections are REPLACED (never mutated) on change, and every change emits {@link Changed$}.
81
+ */
82
+ export declare class RealtimeSurfaceTabsModel {
83
+ /** The fixed key of the always-present Activity tab (pinned as the LAST tab). */
84
+ static readonly ActivityTabKey = "activity";
85
+ /** The ordered tabs (channels… · artifacts… · Activity last). Replaced immutably on every change. */
86
+ Tabs: RealtimeSurfaceTab[];
87
+ /** Key of the currently focused tab. */
88
+ ActiveKey: string;
89
+ /**
90
+ * Key of the tab currently "flashing" (the brief violet highlight a just-arrived
91
+ * artifact tab gets, per the mockup). Cleared by the owning component after a beat
92
+ * via {@link ClearFlash}.
93
+ */
94
+ FlashKey: string | null;
95
+ /**
96
+ * Tabs holding content the user hasn't visited yet (the persistent glow): an artifact
97
+ * tab that arrived WITHOUT stealing focus stays marked until it is focused. Replaced
98
+ * immutably on change.
99
+ */
100
+ private unseenKeys;
101
+ /** Emits after every model change so the owning component can mark for check. */
102
+ readonly Changed$: Subject<void>;
103
+ /** The currently focused tab (always resolvable — Activity is never removed). */
104
+ get ActiveTab(): RealtimeSurfaceTab;
105
+ /** True while the tab with `key` holds content the user hasn't visited (glow state). */
106
+ IsUnseen(key: string): boolean;
107
+ /** The stable tab key for an artifact (one tab per produced artifact VERSION). */
108
+ static ArtifactTabKey(artifact: ParsedDelegationArtifact): string;
109
+ /**
110
+ * Opens (or re-focuses) the tab for an artifact a delegated run produced.
111
+ *
112
+ * First arrival: inserts an `artifact` tab AFTER existing channel/artifact tabs but
113
+ * BEFORE the pinned-last Activity tab, marks it as the {@link FlashKey}, and — unless
114
+ * `focus` is true — leaves focus alone and marks the tab UNSEEN (it glows until
115
+ * visited; per product direction a finished artifact never steals the screen, only the
116
+ * agent's first channel activity does). Subsequent calls for the same artifact version
117
+ * just (optionally) focus the existing tab — no duplicate, no re-flash.
118
+ *
119
+ * @param artifact The produced artifact (id + version id + display name).
120
+ * @param focus Whether to focus the tab (default `false` — glow, don't grab).
121
+ * @param markUnseen Whether an unfocused first arrival glows (default `true`). Pass
122
+ * `false` for HISTORY artifacts (session-review carryover) — they're context, not news.
123
+ * @returns The (new or existing) tab.
124
+ */
125
+ OpenArtifactTab(artifact: ParsedDelegationArtifact, focus?: boolean, markUnseen?: boolean): RealtimeSurfaceTab;
126
+ /**
127
+ * Registers (or updates) an interactive-channel tab. Re-registering an existing key
128
+ * replaces its title/icon/plugin/content in place (this is how a placeholder upgrades
129
+ * to the real surface once the channel comes online). New channel tabs lead the strip
130
+ * (before artifact tabs and the pinned-last Activity tab) — the marquee surfaces.
131
+ *
132
+ * @param registration The channel tab registration.
133
+ * @returns The (new or updated) tab.
134
+ */
135
+ RegisterChannelTab(registration: RealtimeChannelTabRegistration): RealtimeSurfaceTab;
136
+ /** Focuses the tab with `key` (no-op when it doesn't exist); visiting clears its unseen glow. */
137
+ Focus(key: string): void;
138
+ /** The index of the pinned-last Activity tab (insertion boundary for content tabs). */
139
+ private activityIndex;
140
+ /** Clears a tab's unseen glow (no emission of its own — callers emit). */
141
+ private markSeen;
142
+ /**
143
+ * Marks the tab with `key` as the {@link FlashKey} (the brief violet "just arrived"
144
+ * highlight) WITHOUT changing focus — used by the auto-reveal path when the agent first
145
+ * acts on a channel, so the user's eye lands on the tab that just came alive. No-op for
146
+ * unknown keys; the owning component clears it after a beat via {@link ClearFlash}.
147
+ */
148
+ FlashTab(key: string): void;
149
+ /**
150
+ * Removes the tab with `key`. Rules:
151
+ * - the Activity tab is IRREMOVABLE (always the panel's first tab) — removing it is a no-op;
152
+ * - an unknown key is a no-op (returns `false`);
153
+ * - when the removed tab was focused, focus falls back to the Activity tab;
154
+ * - a pending flash on the removed tab is cleaned up so the highlight can't dangle.
155
+ *
156
+ * @param key The tab key to remove.
157
+ * @returns `true` when a tab was removed.
158
+ */
159
+ RemoveTab(key: string): boolean;
160
+ /** Clears the transient flash highlight (called by the component after a beat). */
161
+ ClearFlash(): void;
162
+ }
163
+ /**
164
+ * Pure decision helper for the REVIEW→LIVE continuation edge: should the overlay REMOVE the
165
+ * review-registered (template-based, read-only) Whiteboard tab?
166
+ *
167
+ * Yes only when ALL hold:
168
+ * - a live session is active (the channel set emission belongs to a real session start, not
169
+ * the initial/teardown `[]` replay);
170
+ * - review mode actually registered a whiteboard tab (otherwise there is nothing stale);
171
+ * - the live session's resolved channel set has NO Whiteboard channel — when it HAS one, the
172
+ * live plugin re-registers the same tab key and upgrades the pane in place instead.
173
+ *
174
+ * Review ARTIFACT tabs are deliberately NOT removed — they are wanted carryover.
175
+ *
176
+ * Kept framework-free (like the model) so the rule is unit-testable in isolation.
177
+ */
178
+ export declare function ShouldRemoveReviewWhiteboardTab(liveSessionActive: boolean, reviewWhiteboardTabRegistered: boolean, liveChannels: ReadonlyArray<{
179
+ ChannelName: string;
180
+ }>): boolean;
181
+ //# sourceMappingURL=realtime-surface-tabs.model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-surface-tabs.model.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-surface-tabs.model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,223 @@
1
+ import { Subject } from 'rxjs';
2
+ /**
3
+ * Framework-free state for the call overlay's tabbed surface panel: the ordered tab list
4
+ * (CHANNEL tabs first — the marquee surfaces — then artifact tabs in arrival order, with
5
+ * Activity pinned LAST), the active tab, the transient "flash" highlight for a
6
+ * just-arrived tab, and the persistent UNSEEN glow for content that arrived without
7
+ * stealing focus (an artifact tab glows until the user visits it).
8
+ *
9
+ * Owned by `RealtimeSurfaceTabsComponent`; kept free of Angular runtime imports so the
10
+ * add / focus / dedupe / flash / unseen logic is unit-testable in isolation. All
11
+ * collections are REPLACED (never mutated) on change, and every change emits {@link Changed$}.
12
+ */
13
+ export class RealtimeSurfaceTabsModel {
14
+ /** The fixed key of the always-present Activity tab (pinned as the LAST tab). */
15
+ static ActivityTabKey = 'activity';
16
+ /** The ordered tabs (channels… · artifacts… · Activity last). Replaced immutably on every change. */
17
+ Tabs = [
18
+ { Key: RealtimeSurfaceTabsModel.ActivityTabKey, Title: 'Activity', Icon: 'fa-solid fa-list-check', Kind: 'activity' }
19
+ ];
20
+ /** Key of the currently focused tab. */
21
+ ActiveKey = RealtimeSurfaceTabsModel.ActivityTabKey;
22
+ /**
23
+ * Key of the tab currently "flashing" (the brief violet highlight a just-arrived
24
+ * artifact tab gets, per the mockup). Cleared by the owning component after a beat
25
+ * via {@link ClearFlash}.
26
+ */
27
+ FlashKey = null;
28
+ /**
29
+ * Tabs holding content the user hasn't visited yet (the persistent glow): an artifact
30
+ * tab that arrived WITHOUT stealing focus stays marked until it is focused. Replaced
31
+ * immutably on change.
32
+ */
33
+ unseenKeys = new Set();
34
+ /** Emits after every model change so the owning component can mark for check. */
35
+ Changed$ = new Subject();
36
+ /** The currently focused tab (always resolvable — Activity is never removed). */
37
+ get ActiveTab() {
38
+ return this.Tabs.find(t => t.Key === this.ActiveKey)
39
+ ?? this.Tabs.find(t => t.Key === RealtimeSurfaceTabsModel.ActivityTabKey)
40
+ ?? this.Tabs[0];
41
+ }
42
+ /** True while the tab with `key` holds content the user hasn't visited (glow state). */
43
+ IsUnseen(key) {
44
+ return this.unseenKeys.has(key);
45
+ }
46
+ /** The stable tab key for an artifact (one tab per produced artifact VERSION). */
47
+ static ArtifactTabKey(artifact) {
48
+ return `artifact:${artifact.ArtifactVersionID}`;
49
+ }
50
+ /**
51
+ * Opens (or re-focuses) the tab for an artifact a delegated run produced.
52
+ *
53
+ * First arrival: inserts an `artifact` tab AFTER existing channel/artifact tabs but
54
+ * BEFORE the pinned-last Activity tab, marks it as the {@link FlashKey}, and — unless
55
+ * `focus` is true — leaves focus alone and marks the tab UNSEEN (it glows until
56
+ * visited; per product direction a finished artifact never steals the screen, only the
57
+ * agent's first channel activity does). Subsequent calls for the same artifact version
58
+ * just (optionally) focus the existing tab — no duplicate, no re-flash.
59
+ *
60
+ * @param artifact The produced artifact (id + version id + display name).
61
+ * @param focus Whether to focus the tab (default `false` — glow, don't grab).
62
+ * @param markUnseen Whether an unfocused first arrival glows (default `true`). Pass
63
+ * `false` for HISTORY artifacts (session-review carryover) — they're context, not news.
64
+ * @returns The (new or existing) tab.
65
+ */
66
+ OpenArtifactTab(artifact, focus = false, markUnseen = true) {
67
+ const key = RealtimeSurfaceTabsModel.ArtifactTabKey(artifact);
68
+ const existing = this.Tabs.find(t => t.Key === key);
69
+ if (existing) {
70
+ if (focus) {
71
+ this.Focus(key);
72
+ }
73
+ return existing;
74
+ }
75
+ const tab = {
76
+ Key: key,
77
+ Title: artifact.Name,
78
+ Icon: 'fa-solid fa-file-lines',
79
+ Kind: 'artifact',
80
+ Data: { Artifact: artifact }
81
+ };
82
+ // Insert before the pinned-last Activity tab: channels… | artifacts… | Activity.
83
+ const at = this.activityIndex();
84
+ this.Tabs = [...this.Tabs.slice(0, at), tab, ...this.Tabs.slice(at)];
85
+ this.FlashKey = key;
86
+ if (focus) {
87
+ this.ActiveKey = key;
88
+ }
89
+ else if (markUnseen) {
90
+ this.unseenKeys = new Set([...this.unseenKeys, key]);
91
+ }
92
+ this.Changed$.next();
93
+ return tab;
94
+ }
95
+ /**
96
+ * Registers (or updates) an interactive-channel tab. Re-registering an existing key
97
+ * replaces its title/icon/plugin/content in place (this is how a placeholder upgrades
98
+ * to the real surface once the channel comes online). New channel tabs lead the strip
99
+ * (before artifact tabs and the pinned-last Activity tab) — the marquee surfaces.
100
+ *
101
+ * @param registration The channel tab registration.
102
+ * @returns The (new or updated) tab.
103
+ */
104
+ RegisterChannelTab(registration) {
105
+ const tab = {
106
+ Key: registration.Key,
107
+ Title: registration.Title,
108
+ Icon: registration.Icon,
109
+ Kind: 'channel',
110
+ Data: { Plugin: registration.Plugin, Content: registration.Content }
111
+ };
112
+ const idx = this.Tabs.findIndex(t => t.Key === registration.Key);
113
+ if (idx >= 0) {
114
+ const next = [...this.Tabs];
115
+ next[idx] = tab;
116
+ this.Tabs = next;
117
+ }
118
+ else {
119
+ // Insert after existing channel tabs, before artifacts and the pinned-last Activity.
120
+ const firstNonChannel = this.Tabs.findIndex(t => t.Kind !== 'channel');
121
+ const at = firstNonChannel >= 0 ? firstNonChannel : this.Tabs.length;
122
+ this.Tabs = [...this.Tabs.slice(0, at), tab, ...this.Tabs.slice(at)];
123
+ }
124
+ if (registration.Focus) {
125
+ this.ActiveKey = tab.Key;
126
+ this.markSeen(tab.Key);
127
+ }
128
+ this.Changed$.next();
129
+ return tab;
130
+ }
131
+ /** Focuses the tab with `key` (no-op when it doesn't exist); visiting clears its unseen glow. */
132
+ Focus(key) {
133
+ if (!this.Tabs.some(t => t.Key === key)) {
134
+ return;
135
+ }
136
+ const changed = this.ActiveKey !== key || this.unseenKeys.has(key);
137
+ this.ActiveKey = key;
138
+ this.markSeen(key);
139
+ if (changed) {
140
+ this.Changed$.next();
141
+ }
142
+ }
143
+ /** The index of the pinned-last Activity tab (insertion boundary for content tabs). */
144
+ activityIndex() {
145
+ const idx = this.Tabs.findIndex(t => t.Key === RealtimeSurfaceTabsModel.ActivityTabKey);
146
+ return idx >= 0 ? idx : this.Tabs.length;
147
+ }
148
+ /** Clears a tab's unseen glow (no emission of its own — callers emit). */
149
+ markSeen(key) {
150
+ if (this.unseenKeys.has(key)) {
151
+ const next = new Set(this.unseenKeys);
152
+ next.delete(key);
153
+ this.unseenKeys = next;
154
+ }
155
+ }
156
+ /**
157
+ * Marks the tab with `key` as the {@link FlashKey} (the brief violet "just arrived"
158
+ * highlight) WITHOUT changing focus — used by the auto-reveal path when the agent first
159
+ * acts on a channel, so the user's eye lands on the tab that just came alive. No-op for
160
+ * unknown keys; the owning component clears it after a beat via {@link ClearFlash}.
161
+ */
162
+ FlashTab(key) {
163
+ if (this.FlashKey === key || !this.Tabs.some(t => t.Key === key)) {
164
+ return;
165
+ }
166
+ this.FlashKey = key;
167
+ this.Changed$.next();
168
+ }
169
+ /**
170
+ * Removes the tab with `key`. Rules:
171
+ * - the Activity tab is IRREMOVABLE (always the panel's first tab) — removing it is a no-op;
172
+ * - an unknown key is a no-op (returns `false`);
173
+ * - when the removed tab was focused, focus falls back to the Activity tab;
174
+ * - a pending flash on the removed tab is cleaned up so the highlight can't dangle.
175
+ *
176
+ * @param key The tab key to remove.
177
+ * @returns `true` when a tab was removed.
178
+ */
179
+ RemoveTab(key) {
180
+ if (key === RealtimeSurfaceTabsModel.ActivityTabKey || !this.Tabs.some(t => t.Key === key)) {
181
+ return false;
182
+ }
183
+ this.Tabs = this.Tabs.filter(t => t.Key !== key);
184
+ if (this.ActiveKey === key) {
185
+ this.ActiveKey = RealtimeSurfaceTabsModel.ActivityTabKey;
186
+ }
187
+ if (this.FlashKey === key) {
188
+ this.FlashKey = null;
189
+ }
190
+ this.markSeen(key); // a removed tab can't dangle an unseen glow
191
+ this.Changed$.next();
192
+ return true;
193
+ }
194
+ /** Clears the transient flash highlight (called by the component after a beat). */
195
+ ClearFlash() {
196
+ if (this.FlashKey !== null) {
197
+ this.FlashKey = null;
198
+ this.Changed$.next();
199
+ }
200
+ }
201
+ }
202
+ /**
203
+ * Pure decision helper for the REVIEW→LIVE continuation edge: should the overlay REMOVE the
204
+ * review-registered (template-based, read-only) Whiteboard tab?
205
+ *
206
+ * Yes only when ALL hold:
207
+ * - a live session is active (the channel set emission belongs to a real session start, not
208
+ * the initial/teardown `[]` replay);
209
+ * - review mode actually registered a whiteboard tab (otherwise there is nothing stale);
210
+ * - the live session's resolved channel set has NO Whiteboard channel — when it HAS one, the
211
+ * live plugin re-registers the same tab key and upgrades the pane in place instead.
212
+ *
213
+ * Review ARTIFACT tabs are deliberately NOT removed — they are wanted carryover.
214
+ *
215
+ * Kept framework-free (like the model) so the rule is unit-testable in isolation.
216
+ */
217
+ export function ShouldRemoveReviewWhiteboardTab(liveSessionActive, reviewWhiteboardTabRegistered, liveChannels) {
218
+ if (!liveSessionActive || !reviewWhiteboardTabRegistered) {
219
+ return false;
220
+ }
221
+ return !liveChannels.some(c => c.ChannelName?.trim().toLowerCase() === 'whiteboard');
222
+ }
223
+ //# sourceMappingURL=realtime-surface-tabs.model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-surface-tabs.model.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-surface-tabs.model.ts"],"names":[],"mappings":"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","sourcesContent":["import { Subject } from 'rxjs';\nimport type { TemplateRef } from '@angular/core';\nimport type { BaseRealtimeChannelClient } from './channels/base-realtime-channel-client';\nimport { ParsedDelegationArtifact } from '../../services/delegation-result-parser';\n\n/**\n * The kind of a surface-panel tab:\n * - `activity` — the always-present first tab hosting the session activity rail.\n * - `artifact` — one tab per artifact produced by a delegated run (auto-opened on arrival).\n * - `channel` — an interactive-channel surface (e.g. the Whiteboard). Registered per\n * registry-resolved plugin via {@link RealtimeSurfaceTabsModel.RegisterChannelTab};\n * renders the plugin's dynamically-created surface component (or a registered template\n * for legacy/template-based panes), with the \"coming online…\" placeholder until either\n * is supplied.\n */\nexport type RealtimeSurfaceTabKind = 'activity' | 'artifact' | 'channel';\n\n/**\n * Per-kind payload carried on a {@link RealtimeSurfaceTab}.\n */\nexport interface RealtimeSurfaceTabData {\n /** For `artifact` tabs: the artifact this tab views (loaded by ArtifactID, latest version). */\n Artifact?: ParsedDelegationArtifact;\n /**\n * For `channel` tabs: the channel PLUGIN whose surface component the pane creates\n * dynamically (and binds back to the plugin) — the registry-driven path every real\n * channel uses. Takes precedence over {@link Content}.\n */\n Plugin?: BaseRealtimeChannelClient;\n /**\n * For `channel` tabs: a TEMPLATE-based pane body. Backward-compatible alternative to\n * {@link Plugin} for hosts that render a bespoke surface without a channel plugin.\n * When BOTH are absent the pane renders the built-in \"coming online…\" placeholder.\n */\n Content?: TemplateRef<unknown>;\n}\n\n/**\n * One tab on the call overlay's tabbed surface panel (the right panel): Activity, an\n * artifact viewer, or an interactive-channel surface.\n */\nexport interface RealtimeSurfaceTab {\n /** Stable unique key (`activity`, `artifact:<versionId>`, or the channel's registered key). */\n Key: string;\n /** Tab strip label (artifact tabs use the artifact's name). */\n Title: string;\n /** Font Awesome icon class for the tab strip (e.g. `fa-solid fa-file-lines`). */\n Icon: string;\n /** What the tab renders. */\n Kind: RealtimeSurfaceTabKind;\n /** Kind-specific payload. */\n Data?: RealtimeSurfaceTabData;\n}\n\n/**\n * Registration for an interactive-channel tab. The overlay shell registers one per\n * registry-resolved channel plugin (supplying {@link Plugin}); supplying {@link Plugin}\n * or {@link Content} later under the same `Key` upgrades a placeholder tab to the real\n * surface.\n */\nexport interface RealtimeChannelTabRegistration {\n /** Stable channel key (the plugin's `ChannelName`, e.g. `Whiteboard`). Re-registering the same key updates the tab. */\n Key: string;\n /** Tab strip label (e.g. `Whiteboard`). */\n Title: string;\n /** Font Awesome icon class (e.g. `fa-solid fa-chalkboard`). */\n Icon: string;\n /** The channel plugin whose surface the pane creates + binds. Preferred over {@link Content}. */\n Plugin?: BaseRealtimeChannelClient;\n /** A template-based pane body (legacy/bespoke panes). Omit both to show the \"coming online…\" placeholder. */\n Content?: TemplateRef<unknown>;\n /** Focus the tab immediately after registration (default `false`). */\n Focus?: boolean;\n}\n\n/**\n * Framework-free state for the call overlay's tabbed surface panel: the ordered tab list\n * (CHANNEL tabs first — the marquee surfaces — then artifact tabs in arrival order, with\n * Activity pinned LAST), the active tab, the transient \"flash\" highlight for a\n * just-arrived tab, and the persistent UNSEEN glow for content that arrived without\n * stealing focus (an artifact tab glows until the user visits it).\n *\n * Owned by `RealtimeSurfaceTabsComponent`; kept free of Angular runtime imports so the\n * add / focus / dedupe / flash / unseen logic is unit-testable in isolation. All\n * collections are REPLACED (never mutated) on change, and every change emits {@link Changed$}.\n */\nexport class RealtimeSurfaceTabsModel {\n /** The fixed key of the always-present Activity tab (pinned as the LAST tab). */\n public static readonly ActivityTabKey = 'activity';\n\n /** The ordered tabs (channels… · artifacts… · Activity last). Replaced immutably on every change. */\n public Tabs: RealtimeSurfaceTab[] = [\n { Key: RealtimeSurfaceTabsModel.ActivityTabKey, Title: 'Activity', Icon: 'fa-solid fa-list-check', Kind: 'activity' }\n ];\n\n /** Key of the currently focused tab. */\n public ActiveKey: string = RealtimeSurfaceTabsModel.ActivityTabKey;\n\n /**\n * Key of the tab currently \"flashing\" (the brief violet highlight a just-arrived\n * artifact tab gets, per the mockup). Cleared by the owning component after a beat\n * via {@link ClearFlash}.\n */\n public FlashKey: string | null = null;\n\n /**\n * Tabs holding content the user hasn't visited yet (the persistent glow): an artifact\n * tab that arrived WITHOUT stealing focus stays marked until it is focused. Replaced\n * immutably on change.\n */\n private unseenKeys: ReadonlySet<string> = new Set<string>();\n\n /** Emits after every model change so the owning component can mark for check. */\n public readonly Changed$ = new Subject<void>();\n\n /** The currently focused tab (always resolvable — Activity is never removed). */\n public get ActiveTab(): RealtimeSurfaceTab {\n return this.Tabs.find(t => t.Key === this.ActiveKey)\n ?? this.Tabs.find(t => t.Key === RealtimeSurfaceTabsModel.ActivityTabKey)\n ?? this.Tabs[0];\n }\n\n /** True while the tab with `key` holds content the user hasn't visited (glow state). */\n public IsUnseen(key: string): boolean {\n return this.unseenKeys.has(key);\n }\n\n /** The stable tab key for an artifact (one tab per produced artifact VERSION). */\n public static ArtifactTabKey(artifact: ParsedDelegationArtifact): string {\n return `artifact:${artifact.ArtifactVersionID}`;\n }\n\n /**\n * Opens (or re-focuses) the tab for an artifact a delegated run produced.\n *\n * First arrival: inserts an `artifact` tab AFTER existing channel/artifact tabs but\n * BEFORE the pinned-last Activity tab, marks it as the {@link FlashKey}, and — unless\n * `focus` is true — leaves focus alone and marks the tab UNSEEN (it glows until\n * visited; per product direction a finished artifact never steals the screen, only the\n * agent's first channel activity does). Subsequent calls for the same artifact version\n * just (optionally) focus the existing tab — no duplicate, no re-flash.\n *\n * @param artifact The produced artifact (id + version id + display name).\n * @param focus Whether to focus the tab (default `false` — glow, don't grab).\n * @param markUnseen Whether an unfocused first arrival glows (default `true`). Pass\n * `false` for HISTORY artifacts (session-review carryover) — they're context, not news.\n * @returns The (new or existing) tab.\n */\n public OpenArtifactTab(artifact: ParsedDelegationArtifact, focus: boolean = false, markUnseen: boolean = true): RealtimeSurfaceTab {\n const key = RealtimeSurfaceTabsModel.ArtifactTabKey(artifact);\n const existing = this.Tabs.find(t => t.Key === key);\n if (existing) {\n if (focus) {\n this.Focus(key);\n }\n return existing;\n }\n const tab: RealtimeSurfaceTab = {\n Key: key,\n Title: artifact.Name,\n Icon: 'fa-solid fa-file-lines',\n Kind: 'artifact',\n Data: { Artifact: artifact }\n };\n // Insert before the pinned-last Activity tab: channels… | artifacts… | Activity.\n const at = this.activityIndex();\n this.Tabs = [...this.Tabs.slice(0, at), tab, ...this.Tabs.slice(at)];\n this.FlashKey = key;\n if (focus) {\n this.ActiveKey = key;\n } else if (markUnseen) {\n this.unseenKeys = new Set([...this.unseenKeys, key]);\n }\n this.Changed$.next();\n return tab;\n }\n\n /**\n * Registers (or updates) an interactive-channel tab. Re-registering an existing key\n * replaces its title/icon/plugin/content in place (this is how a placeholder upgrades\n * to the real surface once the channel comes online). New channel tabs lead the strip\n * (before artifact tabs and the pinned-last Activity tab) — the marquee surfaces.\n *\n * @param registration The channel tab registration.\n * @returns The (new or updated) tab.\n */\n public RegisterChannelTab(registration: RealtimeChannelTabRegistration): RealtimeSurfaceTab {\n const tab: RealtimeSurfaceTab = {\n Key: registration.Key,\n Title: registration.Title,\n Icon: registration.Icon,\n Kind: 'channel',\n Data: { Plugin: registration.Plugin, Content: registration.Content }\n };\n const idx = this.Tabs.findIndex(t => t.Key === registration.Key);\n if (idx >= 0) {\n const next = [...this.Tabs];\n next[idx] = tab;\n this.Tabs = next;\n } else {\n // Insert after existing channel tabs, before artifacts and the pinned-last Activity.\n const firstNonChannel = this.Tabs.findIndex(t => t.Kind !== 'channel');\n const at = firstNonChannel >= 0 ? firstNonChannel : this.Tabs.length;\n this.Tabs = [...this.Tabs.slice(0, at), tab, ...this.Tabs.slice(at)];\n }\n if (registration.Focus) {\n this.ActiveKey = tab.Key;\n this.markSeen(tab.Key);\n }\n this.Changed$.next();\n return tab;\n }\n\n /** Focuses the tab with `key` (no-op when it doesn't exist); visiting clears its unseen glow. */\n public Focus(key: string): void {\n if (!this.Tabs.some(t => t.Key === key)) {\n return;\n }\n const changed = this.ActiveKey !== key || this.unseenKeys.has(key);\n this.ActiveKey = key;\n this.markSeen(key);\n if (changed) {\n this.Changed$.next();\n }\n }\n\n /** The index of the pinned-last Activity tab (insertion boundary for content tabs). */\n private activityIndex(): number {\n const idx = this.Tabs.findIndex(t => t.Key === RealtimeSurfaceTabsModel.ActivityTabKey);\n return idx >= 0 ? idx : this.Tabs.length;\n }\n\n /** Clears a tab's unseen glow (no emission of its own — callers emit). */\n private markSeen(key: string): void {\n if (this.unseenKeys.has(key)) {\n const next = new Set(this.unseenKeys);\n next.delete(key);\n this.unseenKeys = next;\n }\n }\n\n /**\n * Marks the tab with `key` as the {@link FlashKey} (the brief violet \"just arrived\"\n * highlight) WITHOUT changing focus — used by the auto-reveal path when the agent first\n * acts on a channel, so the user's eye lands on the tab that just came alive. No-op for\n * unknown keys; the owning component clears it after a beat via {@link ClearFlash}.\n */\n public FlashTab(key: string): void {\n if (this.FlashKey === key || !this.Tabs.some(t => t.Key === key)) {\n return;\n }\n this.FlashKey = key;\n this.Changed$.next();\n }\n\n /**\n * Removes the tab with `key`. Rules:\n * - the Activity tab is IRREMOVABLE (always the panel's first tab) — removing it is a no-op;\n * - an unknown key is a no-op (returns `false`);\n * - when the removed tab was focused, focus falls back to the Activity tab;\n * - a pending flash on the removed tab is cleaned up so the highlight can't dangle.\n *\n * @param key The tab key to remove.\n * @returns `true` when a tab was removed.\n */\n public RemoveTab(key: string): boolean {\n if (key === RealtimeSurfaceTabsModel.ActivityTabKey || !this.Tabs.some(t => t.Key === key)) {\n return false;\n }\n this.Tabs = this.Tabs.filter(t => t.Key !== key);\n if (this.ActiveKey === key) {\n this.ActiveKey = RealtimeSurfaceTabsModel.ActivityTabKey;\n }\n if (this.FlashKey === key) {\n this.FlashKey = null;\n }\n this.markSeen(key); // a removed tab can't dangle an unseen glow\n this.Changed$.next();\n return true;\n }\n\n /** Clears the transient flash highlight (called by the component after a beat). */\n public ClearFlash(): void {\n if (this.FlashKey !== null) {\n this.FlashKey = null;\n this.Changed$.next();\n }\n }\n}\n\n/**\n * Pure decision helper for the REVIEW→LIVE continuation edge: should the overlay REMOVE the\n * review-registered (template-based, read-only) Whiteboard tab?\n *\n * Yes only when ALL hold:\n * - a live session is active (the channel set emission belongs to a real session start, not\n * the initial/teardown `[]` replay);\n * - review mode actually registered a whiteboard tab (otherwise there is nothing stale);\n * - the live session's resolved channel set has NO Whiteboard channel — when it HAS one, the\n * live plugin re-registers the same tab key and upgrades the pane in place instead.\n *\n * Review ARTIFACT tabs are deliberately NOT removed — they are wanted carryover.\n *\n * Kept framework-free (like the model) so the rule is unit-testable in isolation.\n */\nexport function ShouldRemoveReviewWhiteboardTab(\n liveSessionActive: boolean,\n reviewWhiteboardTabRegistered: boolean,\n liveChannels: ReadonlyArray<{ ChannelName: string }>\n): boolean {\n if (!liveSessionActive || !reviewWhiteboardTabRegistered) {\n return false;\n }\n return !liveChannels.some(c => c.ChannelName?.trim().toLowerCase() === 'whiteboard');\n}\n"]}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * The CLIENT-SIDE player for the Remote Browser tab-audio stream — the audio sibling of the surface's
3
+ * screencast canvas. The channel feeds it each pushed {@link RemoteBrowserAudioChunkInput} (a base64
4
+ * `audio/webm;codecs=opus` slice); the player appends them to a `MediaSource` `SourceBuffer` feeding a
5
+ * hidden `<audio>` element so the user HEARS what the co-agent is playing in the browser.
6
+ *
7
+ * The append/queue/seq logic is split from the DOM so it's unit-testable without a browser:
8
+ * - {@link IAudioSink} is the thin DOM seam (create/append/error/muted) — faked in tests, wired to a real
9
+ * `MediaSource` + `<audio>` in {@link MediaSourceAudioSink}.
10
+ * - {@link RemoteBrowserAudioPlayer} owns the queue, sequential append (a `SourceBuffer` can only take one
11
+ * append at a time), overflow drop, and sequence-gap resync — all framework- and DOM-free.
12
+ *
13
+ * Codec note: only `'webm-opus'` chunks are appendable to the `audio/webm;codecs=opus` SourceBuffer; other
14
+ * codecs (reserved for future backend capture paths) are dropped with a one-time warning.
15
+ */
16
+ /** The narrow shape of a pushed audio chunk the player consumes (mirrors the server envelope fields). */
17
+ export interface RemoteBrowserAudioChunkInput {
18
+ /** The encoded audio slice as raw base64 (no `data:` prefix). */
19
+ dataBase64: string;
20
+ /** The codec / container. Only `'webm-opus'` is currently playable. */
21
+ codec: string;
22
+ /** Sample rate in Hz (informational; the webm container is self-describing). */
23
+ sampleRate: number;
24
+ /** Channel count (informational). */
25
+ channels: number;
26
+ /** Monotonic sequence number for ordering / gap detection. */
27
+ seq: number;
28
+ }
29
+ /**
30
+ * The DOM seam the {@link RemoteBrowserAudioPlayer} drives. A real implementation wires a `MediaSource` +
31
+ * `SourceBuffer` + hidden `<audio>`; tests provide a fake that records appends. Kept deliberately tiny so
32
+ * the player's queueing logic is the part under test, not the browser media stack.
33
+ */
34
+ export interface IAudioSink {
35
+ /**
36
+ * Prepares the sink for playback: creates the media source / source buffer / audio element and resolves
37
+ * once it is ready to accept {@link AppendChunk}. Idempotent — a second call while ready is a no-op.
38
+ */
39
+ Open(): Promise<void>;
40
+ /**
41
+ * Appends one decoded-container byte slice to the underlying buffer. Rejects if the sink isn't open or
42
+ * the underlying buffer rejects the append (the player then drops the chunk and continues).
43
+ *
44
+ * @param bytes The raw container bytes (e.g. a webm-opus slice) to append.
45
+ */
46
+ AppendChunk(bytes: Uint8Array): Promise<void>;
47
+ /** Whether the sink can currently accept an append (open and not mid-error / closed). */
48
+ readonly IsOpen: boolean;
49
+ /** Mutes or unmutes playback (the speaker toggle). */
50
+ SetMuted(muted: boolean): void;
51
+ /** Tears the sink down: stops playback and releases the media source / audio element. Idempotent. */
52
+ Close(): void;
53
+ }
54
+ /**
55
+ * Sequential, overflow-bounded player for a continuous webm-opus chunk stream. Construct it with an
56
+ * {@link IAudioSink}; call {@link Enqueue} for each pushed chunk and {@link SetMuted} for the speaker
57
+ * toggle; call {@link Dispose} on teardown.
58
+ */
59
+ export declare class RemoteBrowserAudioPlayer {
60
+ /** The DOM (or fake) sink chunks are appended to. */
61
+ private readonly sink;
62
+ /** Pending decoded chunks awaiting append, oldest first. Bounded by {@link MAX_QUEUE_DEPTH}. */
63
+ private readonly queue;
64
+ /** True while an append is in flight (a SourceBuffer accepts one append at a time). */
65
+ private appending;
66
+ /** The sequence number of the last chunk we ACCEPTED, or `null` before the first. Drives gap detection. */
67
+ private lastSeq;
68
+ /** True once {@link Open} has been kicked off, so we don't re-open on every chunk. */
69
+ private opening;
70
+ /** True after {@link Dispose} so a late append / open resolution becomes a no-op. */
71
+ private disposed;
72
+ /** Pending muted state to apply once the sink opens (the toggle can fire before the first chunk). */
73
+ private muted;
74
+ /** Set once we've warned about an unplayable codec, so the log isn't spammed per chunk. */
75
+ private warnedUnplayableCodec;
76
+ /**
77
+ * Constructs a player over the given sink.
78
+ *
79
+ * @param sink The audio sink (real {@link MediaSourceAudioSink} in the app, a fake in tests).
80
+ */
81
+ constructor(sink: IAudioSink);
82
+ /** The current queue depth — exposed for tests / diagnostics. */
83
+ get QueueDepth(): number;
84
+ /**
85
+ * Enqueues one pushed audio chunk for playback. Drops chunks whose codec isn't playable, opens the sink
86
+ * lazily on the first playable chunk, detects sequence gaps (logged; the webm stream self-recovers on the
87
+ * next keyframe), and bounds the queue by dropping the oldest on overflow. Never throws.
88
+ *
89
+ * @param chunk The pushed chunk to play.
90
+ */
91
+ Enqueue(chunk: RemoteBrowserAudioChunkInput): void;
92
+ /**
93
+ * Mutes / unmutes playback (the speaker toggle). Safe to call before the sink opens — the state is
94
+ * applied once it does.
95
+ *
96
+ * @param muted `true` to mute, `false` to unmute.
97
+ */
98
+ SetMuted(muted: boolean): void;
99
+ /** Tears the player down: clears the queue and closes the sink. Idempotent. */
100
+ Dispose(): void;
101
+ /**
102
+ * Records a chunk's sequence number and logs a one-line note when a gap is detected (a non-consecutive
103
+ * seq). We don't try to reorder — webm-opus self-recovers at the next cluster — but the note aids
104
+ * diagnosis of a lossy transport.
105
+ *
106
+ * @param seq The incoming chunk's sequence number.
107
+ */
108
+ private noteSequence;
109
+ /** Pushes bytes onto the queue, dropping the OLDEST when the queue is at {@link MAX_QUEUE_DEPTH}. */
110
+ private pushBounded;
111
+ /**
112
+ * Ensures the sink is open (opening it lazily on first use) and then drains the queue. The open is
113
+ * kicked off once; subsequent calls just drain. Best-effort — an open/append failure is logged and the
114
+ * player keeps trying on the next chunk.
115
+ */
116
+ private ensureOpenThenDrain;
117
+ /**
118
+ * Appends queued chunks to the sink one at a time (a SourceBuffer rejects concurrent appends). Re-entrant
119
+ * safe via the {@link appending} guard; stops when the queue empties, the sink closes, or on disposal.
120
+ */
121
+ private drain;
122
+ /**
123
+ * Decodes a base64 string to bytes WITHOUT the DOM `atob` so the queueing logic is testable in Node too.
124
+ * Returns `null` on malformed input (the chunk is then skipped).
125
+ *
126
+ * @param base64 The base64 string to decode.
127
+ * @returns The decoded bytes, or `null` when the input can't be decoded.
128
+ */
129
+ private decodeBase64;
130
+ }
131
+ /**
132
+ * The real, DOM-backed {@link IAudioSink}: a `MediaSource` whose single `audio/webm;codecs=opus`
133
+ * `SourceBuffer` is fed appended chunks, attached to a hidden `<audio>` element that auto-plays. Autoplay
134
+ * is permitted because the realtime call the user already started is the activating gesture.
135
+ *
136
+ * Kept out of the player's hot path so the queueing logic stays unit-testable; this class is exercised in
137
+ * the live app (it can't be meaningfully unit-tested without a browser media stack).
138
+ */
139
+ export declare class MediaSourceAudioSink implements IAudioSink {
140
+ /** MIME the SourceBuffer is created with — the in-page recorder's output container/codec. */
141
+ private static readonly MIME;
142
+ /** The hidden audio element playback is routed through; `null` before {@link Open} / after {@link Close}. */
143
+ private audio;
144
+ /** The MediaSource backing the audio element; `null` before {@link Open} / after {@link Close}. */
145
+ private mediaSource;
146
+ /** The single source buffer chunks are appended to; `null` until `sourceopen` wires it. */
147
+ private sourceBuffer;
148
+ /** Object URL bound to the audio element's `src`, revoked on {@link Close}. */
149
+ private objectUrl;
150
+ /** Latched muted state applied to the audio element as it (re)opens. */
151
+ private mutedState;
152
+ /** @inheritdoc */
153
+ get IsOpen(): boolean;
154
+ /** @inheritdoc */
155
+ Open(): Promise<void>;
156
+ /** @inheritdoc */
157
+ AppendChunk(bytes: Uint8Array): Promise<void>;
158
+ /** @inheritdoc */
159
+ SetMuted(muted: boolean): void;
160
+ /** @inheritdoc */
161
+ Close(): void;
162
+ }
163
+ //# sourceMappingURL=remote-browser-audio-player.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-browser-audio-player.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/remote-browser/remote-browser-audio-player.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,yGAAyG;AACzG,MAAM,WAAW,4BAA4B;IAC3C,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;;;;OAKG;IACH,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAE/B,qGAAqG;IACrG,KAAK,IAAI,IAAI,CAAC;CACf;AAKD;;;;GAIG;AACH,qBAAa,wBAAwB;IACnC,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAElC,gGAAgG;IAChG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAE1C,uFAAuF;IACvF,OAAO,CAAC,SAAS,CAAS;IAE1B,2GAA2G;IAC3G,OAAO,CAAC,OAAO,CAAuB;IAEtC,sFAAsF;IACtF,OAAO,CAAC,OAAO,CAAS;IAExB,qFAAqF;IACrF,OAAO,CAAC,QAAQ,CAAS;IAEzB,qGAAqG;IACrG,OAAO,CAAC,KAAK,CAAS;IAEtB,2FAA2F;IAC3F,OAAO,CAAC,qBAAqB,CAAS;IAEtC;;;;OAIG;gBACS,IAAI,EAAE,UAAU;IAI5B,iEAAiE;IACjE,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED;;;;;;OAMG;IACI,OAAO,CAAC,KAAK,EAAE,4BAA4B,GAAG,IAAI;IAqBzD;;;;;OAKG;IACI,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAOrC,+EAA+E;IACxE,OAAO,IAAI,IAAI;IAMtB;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAQpB,qGAAqG;IACrG,OAAO,CAAC,WAAW;IAOnB;;;;OAIG;YACW,mBAAmB;IAmBjC;;;OAGG;YACW,KAAK;IAoBnB;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;CAqBrB;AAED;;;;;;;GAOG;AACH,qBAAa,oBAAqB,YAAW,UAAU;IACrD,6FAA6F;IAC7F,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAA4B;IAExD,6GAA6G;IAC7G,OAAO,CAAC,KAAK,CAAiC;IAC9C,mGAAmG;IACnG,OAAO,CAAC,WAAW,CAA4B;IAC/C,2FAA2F;IAC3F,OAAO,CAAC,YAAY,CAA6B;IACjD,+EAA+E;IAC/E,OAAO,CAAC,SAAS,CAAuB;IACxC,wEAAwE;IACxE,OAAO,CAAC,UAAU,CAAS;IAE3B,kBAAkB;IAClB,IAAW,MAAM,IAAI,OAAO,CAE3B;IAED,kBAAkB;IACL,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqClC,kBAAkB;IACL,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC1D,kBAAkB;IACX,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAOrC,kBAAkB;IACX,KAAK,IAAI,IAAI;CAcrB"}