@memberjunction/ng-conversations 6.2.0-edge.3 → 6.2.0-edge.5

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 (318) hide show
  1. package/README.md +33 -7
  2. package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
  3. package/dist/lib/components/collection/collection-view.component.js +1 -0
  4. package/dist/lib/components/collection/collection-view.component.js.map +1 -1
  5. package/dist/lib/components/composer/ai-composer.component.d.ts +14 -2
  6. package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -1
  7. package/dist/lib/components/composer/ai-composer.component.js +35 -4
  8. package/dist/lib/components/composer/ai-composer.component.js.map +1 -1
  9. package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts +1 -1
  10. package/dist/lib/components/conversation/conversation-agent-picker.component.js +3 -3
  11. package/dist/lib/components/conversation/conversation-agent-picker.component.js.map +1 -1
  12. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +651 -53
  13. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  14. package/dist/lib/components/conversation/conversation-chat-area.component.js +3002 -661
  15. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  16. package/dist/lib/components/conversation/forks-popover.component.d.ts +37 -0
  17. package/dist/lib/components/conversation/forks-popover.component.d.ts.map +1 -0
  18. package/dist/lib/components/conversation/forks-popover.component.js +164 -0
  19. package/dist/lib/components/conversation/forks-popover.component.js.map +1 -0
  20. package/dist/lib/components/export/export-modal.component.d.ts +7 -2
  21. package/dist/lib/components/export/export-modal.component.d.ts.map +1 -1
  22. package/dist/lib/components/export/export-modal.component.js +16 -3
  23. package/dist/lib/components/export/export-modal.component.js.map +1 -1
  24. package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
  25. package/dist/lib/components/message/conversation-message-rating.component.js +11 -9
  26. package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
  27. package/dist/lib/components/message/message-input.component.d.ts +96 -11
  28. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  29. package/dist/lib/components/message/message-input.component.js +253 -112
  30. package/dist/lib/components/message/message-input.component.js.map +1 -1
  31. package/dist/lib/components/message/message-item.component.d.ts +304 -16
  32. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  33. package/dist/lib/components/message/message-item.component.js +2029 -363
  34. package/dist/lib/components/message/message-item.component.js.map +1 -1
  35. package/dist/lib/components/message/message-list.component.d.ts +101 -22
  36. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  37. package/dist/lib/components/message/message-list.component.js +326 -55
  38. package/dist/lib/components/message/message-list.component.js.map +1 -1
  39. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.d.ts +34 -0
  40. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.d.ts.map +1 -0
  41. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.js +75 -0
  42. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.js.map +1 -0
  43. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.d.ts +80 -0
  44. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.d.ts.map +1 -0
  45. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.js +202 -0
  46. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.js.map +1 -0
  47. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.d.ts +45 -0
  48. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.d.ts.map +1 -0
  49. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.js +123 -0
  50. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.js.map +1 -0
  51. package/dist/lib/components/realtime/capture/realtime-capture-channel.d.ts +90 -0
  52. package/dist/lib/components/realtime/capture/realtime-capture-channel.d.ts.map +1 -0
  53. package/dist/lib/components/realtime/capture/realtime-capture-channel.js +223 -0
  54. package/dist/lib/components/realtime/capture/realtime-capture-channel.js.map +1 -0
  55. package/dist/lib/components/realtime/capture/realtime-capture-model.d.ts +98 -0
  56. package/dist/lib/components/realtime/capture/realtime-capture-model.d.ts.map +1 -0
  57. package/dist/lib/components/realtime/capture/realtime-capture-model.js +161 -0
  58. package/dist/lib/components/realtime/capture/realtime-capture-model.js.map +1 -0
  59. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.d.ts +48 -0
  60. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.d.ts.map +1 -0
  61. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.js +205 -0
  62. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.js.map +1 -0
  63. package/dist/lib/components/realtime/channels/client-context-channel.d.ts +19 -2
  64. package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -1
  65. package/dist/lib/components/realtime/channels/client-context-channel.js +83 -9
  66. package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -1
  67. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +30 -9
  68. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -1
  69. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +78 -14
  70. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -1
  71. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.d.ts +71 -0
  72. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.d.ts.map +1 -0
  73. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.js +259 -0
  74. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.js.map +1 -0
  75. package/dist/lib/components/realtime/identity-verification/identity-verification-model.d.ts +129 -0
  76. package/dist/lib/components/realtime/identity-verification/identity-verification-model.d.ts.map +1 -0
  77. package/dist/lib/components/realtime/identity-verification/identity-verification-model.js +373 -0
  78. package/dist/lib/components/realtime/identity-verification/identity-verification-model.js.map +1 -0
  79. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.d.ts +77 -0
  80. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.d.ts.map +1 -0
  81. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.js +420 -0
  82. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.js.map +1 -0
  83. package/dist/lib/components/realtime/interactive-component/component-contract.d.ts +83 -0
  84. package/dist/lib/components/realtime/interactive-component/component-contract.d.ts.map +1 -0
  85. package/dist/lib/components/realtime/interactive-component/component-contract.js +292 -0
  86. package/dist/lib/components/realtime/interactive-component/component-contract.js.map +1 -0
  87. package/dist/lib/components/realtime/interactive-component/component-data-state.d.ts +39 -0
  88. package/dist/lib/components/realtime/interactive-component/component-data-state.d.ts.map +1 -0
  89. package/dist/lib/components/realtime/interactive-component/component-data-state.js +152 -0
  90. package/dist/lib/components/realtime/interactive-component/component-data-state.js.map +1 -0
  91. package/dist/lib/components/realtime/interactive-component/component-instance-engine.d.ts +109 -0
  92. package/dist/lib/components/realtime/interactive-component/component-instance-engine.d.ts.map +1 -0
  93. package/dist/lib/components/realtime/interactive-component/component-instance-engine.js +146 -0
  94. package/dist/lib/components/realtime/interactive-component/component-instance-engine.js.map +1 -0
  95. package/dist/lib/components/realtime/interactive-component/component-spec-content.d.ts +19 -0
  96. package/dist/lib/components/realtime/interactive-component/component-spec-content.d.ts.map +1 -0
  97. package/dist/lib/components/realtime/interactive-component/component-spec-content.js +39 -0
  98. package/dist/lib/components/realtime/interactive-component/component-spec-content.js.map +1 -0
  99. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.d.ts +183 -0
  100. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.d.ts.map +1 -0
  101. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.js +761 -0
  102. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.js.map +1 -0
  103. package/dist/lib/components/realtime/interactive-component/interactive-component-config.d.ts +25 -0
  104. package/dist/lib/components/realtime/interactive-component/interactive-component-config.d.ts.map +1 -0
  105. package/dist/lib/components/realtime/interactive-component/interactive-component-config.js +57 -0
  106. package/dist/lib/components/realtime/interactive-component/interactive-component-config.js.map +1 -0
  107. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.d.ts +40 -0
  108. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.d.ts.map +1 -0
  109. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.js +97 -0
  110. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.js.map +1 -0
  111. package/dist/lib/components/realtime/interactive-component/interactive-component-types.d.ts +144 -0
  112. package/dist/lib/components/realtime/interactive-component/interactive-component-types.d.ts.map +1 -0
  113. package/dist/lib/components/realtime/interactive-component/interactive-component-types.js +57 -0
  114. package/dist/lib/components/realtime/interactive-component/interactive-component-types.js.map +1 -0
  115. package/dist/lib/components/realtime/interactive-component/react-component-handle.d.ts +36 -0
  116. package/dist/lib/components/realtime/interactive-component/react-component-handle.d.ts.map +1 -0
  117. package/dist/lib/components/realtime/interactive-component/react-component-handle.js +55 -0
  118. package/dist/lib/components/realtime/interactive-component/react-component-handle.js.map +1 -0
  119. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.d.ts +55 -0
  120. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.d.ts.map +1 -0
  121. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.js +210 -0
  122. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.js.map +1 -0
  123. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.d.ts +32 -0
  124. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.d.ts.map +1 -0
  125. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js +90 -0
  126. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js.map +1 -0
  127. package/dist/lib/components/realtime/media/media-channel.d.ts +7 -0
  128. package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -1
  129. package/dist/lib/components/realtime/media/media-channel.js +28 -1
  130. package/dist/lib/components/realtime/media/media-channel.js.map +1 -1
  131. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +8 -1
  132. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  133. package/dist/lib/components/realtime/realtime-agent-banner.component.js +89 -71
  134. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  135. package/dist/lib/components/realtime/realtime-agent-orb.component.d.ts +21 -0
  136. package/dist/lib/components/realtime/realtime-agent-orb.component.d.ts.map +1 -0
  137. package/dist/lib/components/realtime/realtime-agent-orb.component.js +49 -0
  138. package/dist/lib/components/realtime/realtime-agent-orb.component.js.map +1 -0
  139. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +44 -11
  140. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
  141. package/dist/lib/components/realtime/realtime-agent-picker.component.js +162 -50
  142. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
  143. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +8 -2
  144. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -1
  145. package/dist/lib/components/realtime/realtime-audio-visuals.js +14 -18
  146. package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -1
  147. package/dist/lib/components/realtime/realtime-composer.component.d.ts +42 -2
  148. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
  149. package/dist/lib/components/realtime/realtime-composer.component.js +137 -102
  150. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  151. package/dist/lib/components/realtime/realtime-perception-chip.component.d.ts +71 -0
  152. package/dist/lib/components/realtime/realtime-perception-chip.component.d.ts.map +1 -0
  153. package/dist/lib/components/realtime/realtime-perception-chip.component.js +221 -0
  154. package/dist/lib/components/realtime/realtime-perception-chip.component.js.map +1 -0
  155. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +264 -22
  156. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  157. package/dist/lib/components/realtime/realtime-session-overlay.component.js +851 -135
  158. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  159. package/dist/lib/components/realtime/realtime-surface-placement-prefs.d.ts +14 -0
  160. package/dist/lib/components/realtime/realtime-surface-placement-prefs.d.ts.map +1 -0
  161. package/dist/lib/components/realtime/realtime-surface-placement-prefs.js +14 -0
  162. package/dist/lib/components/realtime/realtime-surface-placement-prefs.js.map +1 -0
  163. package/dist/lib/components/realtime/realtime-surface-stage.model.d.ts +74 -0
  164. package/dist/lib/components/realtime/realtime-surface-stage.model.d.ts.map +1 -0
  165. package/dist/lib/components/realtime/realtime-surface-stage.model.js +171 -0
  166. package/dist/lib/components/realtime/realtime-surface-stage.model.js.map +1 -0
  167. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +71 -13
  168. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
  169. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +232 -73
  170. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
  171. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +5 -0
  172. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
  173. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +8 -0
  174. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
  175. package/dist/lib/components/realtime/realtime-ui-config.d.ts +12 -2
  176. package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -1
  177. package/dist/lib/components/realtime/realtime-ui-config.js +5 -1
  178. package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -1
  179. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +10 -1
  180. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
  181. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +42 -2
  182. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
  183. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts +20 -3
  184. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts.map +1 -1
  185. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js +44 -10
  186. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js.map +1 -1
  187. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +28 -44
  188. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
  189. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +76 -162
  190. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
  191. package/dist/lib/components/search/search-panel.component.d.ts +2 -0
  192. package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
  193. package/dist/lib/components/search/search-panel.component.js +25 -12
  194. package/dist/lib/components/search/search-panel.component.js.map +1 -1
  195. package/dist/lib/components/sidebar/routines-section.component.js +1 -1
  196. package/dist/lib/components/sidebar/routines-section.component.js.map +1 -1
  197. package/dist/lib/components/task/tasks-full-view.component.d.ts +152 -31
  198. package/dist/lib/components/task/tasks-full-view.component.d.ts.map +1 -1
  199. package/dist/lib/components/task/tasks-full-view.component.js +2227 -214
  200. package/dist/lib/components/task/tasks-full-view.component.js.map +1 -1
  201. package/dist/lib/components/tasks/tasks-dropdown.component.js +4 -4
  202. package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
  203. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +33 -32
  204. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  205. package/dist/lib/components/workspace/conversation-workspace.component.js +72 -88
  206. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  207. package/dist/lib/conversations.module.d.ts +30 -29
  208. package/dist/lib/conversations.module.d.ts.map +1 -1
  209. package/dist/lib/conversations.module.js +27 -5
  210. package/dist/lib/conversations.module.js.map +1 -1
  211. package/dist/lib/events/chat-events.d.ts +25 -0
  212. package/dist/lib/events/chat-events.d.ts.map +1 -1
  213. package/dist/lib/events/chat-events.js +36 -0
  214. package/dist/lib/events/chat-events.js.map +1 -1
  215. package/dist/lib/models/agent-turn.model.d.ts +5 -0
  216. package/dist/lib/models/agent-turn.model.d.ts.map +1 -1
  217. package/dist/lib/models/agent-turn.model.js.map +1 -1
  218. package/dist/lib/services/agent-state.service.d.ts +34 -8
  219. package/dist/lib/services/agent-state.service.d.ts.map +1 -1
  220. package/dist/lib/services/agent-state.service.js +90 -37
  221. package/dist/lib/services/agent-state.service.js.map +1 -1
  222. package/dist/lib/services/artifact-state.service.d.ts +0 -9
  223. package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
  224. package/dist/lib/services/artifact-state.service.js +1 -32
  225. package/dist/lib/services/artifact-state.service.js.map +1 -1
  226. package/dist/lib/services/browser-realtime-media-host.d.ts +19 -7
  227. package/dist/lib/services/browser-realtime-media-host.d.ts.map +1 -1
  228. package/dist/lib/services/browser-realtime-media-host.js +21 -72
  229. package/dist/lib/services/browser-realtime-media-host.js.map +1 -1
  230. package/dist/lib/services/conversation-agent.service.d.ts +48 -16
  231. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  232. package/dist/lib/services/conversation-agent.service.js +110 -35
  233. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  234. package/dist/lib/services/conversation-detail-window.store.d.ts +22 -4
  235. package/dist/lib/services/conversation-detail-window.store.d.ts.map +1 -1
  236. package/dist/lib/services/conversation-detail-window.store.js +50 -9
  237. package/dist/lib/services/conversation-detail-window.store.js.map +1 -1
  238. package/dist/lib/services/conversation-naming.d.ts +72 -22
  239. package/dist/lib/services/conversation-naming.d.ts.map +1 -1
  240. package/dist/lib/services/conversation-naming.js +93 -12
  241. package/dist/lib/services/conversation-naming.js.map +1 -1
  242. package/dist/lib/services/conversation-tasks-filter.d.ts +15 -0
  243. package/dist/lib/services/conversation-tasks-filter.d.ts.map +1 -0
  244. package/dist/lib/services/conversation-tasks-filter.js +69 -0
  245. package/dist/lib/services/conversation-tasks-filter.js.map +1 -0
  246. package/dist/lib/services/data-cache.service.d.ts +13 -5
  247. package/dist/lib/services/data-cache.service.d.ts.map +1 -1
  248. package/dist/lib/services/data-cache.service.js +39 -19
  249. package/dist/lib/services/data-cache.service.js.map +1 -1
  250. package/dist/lib/services/export.service.d.ts +26 -9
  251. package/dist/lib/services/export.service.d.ts.map +1 -1
  252. package/dist/lib/services/export.service.js +61 -18
  253. package/dist/lib/services/export.service.js.map +1 -1
  254. package/dist/lib/services/realtime-audio-recorder.d.ts +115 -79
  255. package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -1
  256. package/dist/lib/services/realtime-audio-recorder.js +273 -186
  257. package/dist/lib/services/realtime-audio-recorder.js.map +1 -1
  258. package/dist/lib/services/realtime-pairing.d.ts +10 -5
  259. package/dist/lib/services/realtime-pairing.d.ts.map +1 -1
  260. package/dist/lib/services/realtime-pairing.js +15 -6
  261. package/dist/lib/services/realtime-pairing.js.map +1 -1
  262. package/dist/lib/services/realtime-session.service.d.ts +31 -2
  263. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  264. package/dist/lib/services/realtime-session.service.js +34 -2
  265. package/dist/lib/services/realtime-session.service.js.map +1 -1
  266. package/dist/lib/services/recording/libopus-wasm-binary.d.ts +3 -0
  267. package/dist/lib/services/recording/libopus-wasm-binary.d.ts.map +1 -0
  268. package/dist/lib/services/recording/libopus-wasm-binary.js +489 -0
  269. package/dist/lib/services/recording/libopus-wasm-binary.js.map +1 -0
  270. package/dist/lib/services/recording/libopus-worker-source.d.ts +48 -0
  271. package/dist/lib/services/recording/libopus-worker-source.d.ts.map +1 -0
  272. package/dist/lib/services/recording/libopus-worker-source.js +170 -0
  273. package/dist/lib/services/recording/libopus-worker-source.js.map +1 -0
  274. package/dist/lib/services/recording/linear-resampler.d.ts +45 -0
  275. package/dist/lib/services/recording/linear-resampler.d.ts.map +1 -0
  276. package/dist/lib/services/recording/linear-resampler.js +85 -0
  277. package/dist/lib/services/recording/linear-resampler.js.map +1 -0
  278. package/dist/lib/services/recording/opus-packet-encoder.d.ts +50 -0
  279. package/dist/lib/services/recording/opus-packet-encoder.d.ts.map +1 -0
  280. package/dist/lib/services/recording/opus-packet-encoder.js +41 -0
  281. package/dist/lib/services/recording/opus-packet-encoder.js.map +1 -0
  282. package/dist/lib/services/recording/wasm-opus-encoder.d.ts +86 -0
  283. package/dist/lib/services/recording/wasm-opus-encoder.d.ts.map +1 -0
  284. package/dist/lib/services/recording/wasm-opus-encoder.js +232 -0
  285. package/dist/lib/services/recording/wasm-opus-encoder.js.map +1 -0
  286. package/dist/lib/services/recording/webcodecs-opus-encoder.d.ts +39 -0
  287. package/dist/lib/services/recording/webcodecs-opus-encoder.d.ts.map +1 -0
  288. package/dist/lib/services/recording/webcodecs-opus-encoder.js +101 -0
  289. package/dist/lib/services/recording/webcodecs-opus-encoder.js.map +1 -0
  290. package/dist/lib/services/search.service.d.ts +7 -2
  291. package/dist/lib/services/search.service.d.ts.map +1 -1
  292. package/dist/lib/services/search.service.js +16 -20
  293. package/dist/lib/services/search.service.js.map +1 -1
  294. package/dist/lib/utils/conversation-branching.d.ts +4 -0
  295. package/dist/lib/utils/conversation-branching.d.ts.map +1 -0
  296. package/dist/lib/utils/conversation-branching.js +5 -0
  297. package/dist/lib/utils/conversation-branching.js.map +1 -0
  298. package/dist/lib/utils/conversation-forks.d.ts +315 -0
  299. package/dist/lib/utils/conversation-forks.d.ts.map +1 -0
  300. package/dist/lib/utils/conversation-forks.js +456 -0
  301. package/dist/lib/utils/conversation-forks.js.map +1 -0
  302. package/dist/lib/utils/distinct-artifacts.d.ts +9 -3
  303. package/dist/lib/utils/distinct-artifacts.d.ts.map +1 -1
  304. package/dist/lib/utils/distinct-artifacts.js +24 -5
  305. package/dist/lib/utils/distinct-artifacts.js.map +1 -1
  306. package/dist/public-api.d.ts +23 -1
  307. package/dist/public-api.d.ts.map +1 -1
  308. package/dist/public-api.js +30 -1
  309. package/dist/public-api.js.map +1 -1
  310. package/package.json +37 -33
  311. package/dist/lib/components/thread/thread-panel.component.d.ts +0 -126
  312. package/dist/lib/components/thread/thread-panel.component.d.ts.map +0 -1
  313. package/dist/lib/components/thread/thread-panel.component.js +0 -440
  314. package/dist/lib/components/thread/thread-panel.component.js.map +0 -1
  315. package/dist/lib/services/realtime-pcm-wav.d.ts +0 -79
  316. package/dist/lib/services/realtime-pcm-wav.d.ts.map +0 -1
  317. package/dist/lib/services/realtime-pcm-wav.js +0 -213
  318. package/dist/lib/services/realtime-pcm-wav.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-agent-picker.component.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-agent-picker.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n HostListener,\n Input,\n OnInit,\n Output,\n ViewChild,\n AfterViewInit,\n inject,\n} from '@angular/core';\nimport type { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { UserInfo } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { REALTIME_ADVANCED_SESSION_CONTROLS, UserHoldsAuthorization } from '../../services/user-authorization';\nimport {\n BuildRealtimeModelOptions,\n ConstrainTargetsToPairings,\n DefaultPairedTargetId,\n LoadCoAgentPairings,\n RealtimeModelOption,\n RealtimePairedAgentRow,\n} from '../../services/realtime-pairing';\nimport { GraphQLLiveKitClient, GraphQLDataProvider, RealtimeModelVoices, RealtimeVoiceOption } from '@memberjunction/graphql-dataprovider';\n\n/**\n * The user's confirmed choice from the realtime picker: the agent to call, an optional\n * EXPLICIT realtime model (`null` = \"Auto (recommended)\", i.e. let the server pick —\n * always `null` for users without the `Realtime: Advanced Session Controls`\n * authorization, who never see the model selector), and an optional EXPLICIT co-agent\n * (`null` = the server's co-agent resolution chain).\n */\nexport interface RealtimeAgentPick {\n /** The agent the voice call should front. */\n Agent: MJAIAgentEntityExtended;\n /** Explicit realtime model id, or `null` for the server's automatic selection. */\n PreferredModelId: string | null;\n /** Explicit provider-native voice id (e.g. `echo`), or `null` for the configured/default voice. */\n PreferredVoice: string | null;\n /** Explicit co-agent id (`MJ: AI Agents.ID`, Realtime type), or `null` for the server's resolution chain. */\n CoAgentId: string | null;\n /** Whether the user consented to recording this call (mic + agent audio). */\n RecordingConsent: boolean;\n}\n\n/** `MJ: User Settings` key for the per-user \"record this call\" consent toggle (string `'true'`/`'false'`). */\nconst RECORDING_CONSENT_KEY = 'mj.realtimeVoice.recordingConsent.v1';\n\n/**\n * Compact anchored popover that lets the user choose WHICH agent a realtime\n * voice call should front — shown by {@link MessageInputComponent} when the\n * phone button is clicked on a conversation with **no prior agent\n * participation** (new / empty conversation), and on demand via the caret\n * button next to the phone (any conversation), where it doubles as the way\n * to pick a specific **co-agent** (the Realtime-type agent that voices the\n * call) and — for authorized users — a specific **voice model**. The plain\n * phone click on an existing conversation keeps its friction-free \"call the\n * resolved agent immediately\" behavior.\n *\n * Mostly dumb: the host supplies the agent list (the same cached set the\n * @mention autocomplete / routing logic uses), the Realtime-type co-agent\n * candidates (filtered from that same set), and the defaults to preselect;\n * the picker emits the user's choice. The data it loads itself:\n * - the compact \"Voice model\" option list (active Realtime models via a\n * narrow RunView) — loaded and rendered ONLY when the current user holds\n * the `Realtime: Advanced Session Controls` authorization (pure UX\n * disclosure; the server enforces the authorization on the mint), and\n * - the chosen co-agent's pairing rows (`MJ: AI Agent Co Agents`, Active 'CoAgent'-type rows): a\n * co-agent with pairing rows may only front its paired targets, so the\n * agent list constrains to those rows (Sequence order) with the IsDefault\n * row preselected; a co-agent with zero rows is universal and the list is\n * untouched.\n *\n * It does NOT persist anything (the host persists the co-agent preference\n * via `UserInfoEngine`; `mj-conversation-agent-picker` pins\n * `MJConversationEntity.DefaultAgentID` — different jobs, which is why this\n * is a separate component).\n *\n * Anchors itself bottom-right above the composer — the host's\n * `.message-input-wrapper` is `position: relative`.\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-agent-picker',\n imports: [MJButtonDirective],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"mj-voice-picker\" (click)=\"$event.stopPropagation()\">\n <div class=\"mj-voice-picker__header\">\n <i class=\"fa-solid fa-phone\"></i>\n <span>Start a voice call with…</span>\n </div>\n @if (ShowCoAgentSelect) {\n <div class=\"mj-voice-picker__select-row\">\n <label class=\"mj-voice-picker__select-label\" for=\"mjRealtimeCoAgentSelect\">\n <i class=\"fa-solid fa-headset\"></i>\n <span>Co-agent</span>\n </label>\n <select\n #coAgentSelect\n id=\"mjRealtimeCoAgentSelect\"\n class=\"mj-voice-picker__select\"\n [value]=\"SelectedCoAgentId ?? ''\"\n (change)=\"OnCoAgentChange(coAgentSelect.value)\">\n <option value=\"\">Auto (recommended)</option>\n @for (coAgent of CoAgents; track coAgent.ID) {\n <option [value]=\"coAgent.ID\">{{ coAgent.Name }}</option>\n }\n </select>\n </div>\n }\n <div class=\"mj-voice-picker__search\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n <input\n #searchInput\n type=\"text\"\n placeholder=\"Search agents\"\n [value]=\"SearchText\"\n (input)=\"OnSearchInput(searchInput.value)\"\n (keydown.enter)=\"StartCall()\"\n (keydown.arrowdown)=\"MoveSelection(1); $event.preventDefault()\"\n (keydown.arrowup)=\"MoveSelection(-1); $event.preventDefault()\" />\n </div>\n <div class=\"mj-voice-picker__list\">\n @if (FilteredAgents.length === 0) {\n <div class=\"mj-voice-picker__empty\">{{ IsConstrainedByPairings ? 'No paired agents available' : 'No matching agents' }}</div>\n } @else {\n @for (agent of FilteredAgents; track agent.ID) {\n <button\n type=\"button\"\n class=\"mj-voice-picker__item\"\n [class.mj-voice-picker__item--selected]=\"IsSelected(agent)\"\n [title]=\"agent.Description || agent.Name\"\n (click)=\"Select(agent)\"\n (dblclick)=\"Pick(agent)\">\n <i [class]=\"IconClassFor(agent)\"></i>\n <span class=\"mj-voice-picker__item-name\">{{ agent.Name }}</span>\n @if (IsDefaultChoice(agent)) {\n <span class=\"mj-voice-picker__default-badge\">default</span>\n }\n </button>\n }\n }\n </div>\n @if (CanOverrideSessionConfig && Models.length > 0) {\n <div class=\"mj-voice-picker__select-row mj-voice-picker__select-row--model\">\n <label class=\"mj-voice-picker__select-label\" for=\"mjRealtimeModelSelect\">\n <i class=\"fa-solid fa-microchip\"></i>\n <span>Voice model</span>\n </label>\n <select\n #modelSelect\n id=\"mjRealtimeModelSelect\"\n class=\"mj-voice-picker__select\"\n [value]=\"SelectedModelId ?? ''\"\n (change)=\"OnModelChange(modelSelect.value)\">\n <option value=\"\">Auto (recommended)</option>\n @for (model of Models; track model.ID) {\n <option [value]=\"model.ID\">{{ model.Name }}</option>\n }\n </select>\n </div>\n @if (SelectedModelVoices.length) {\n <div class=\"mj-voice-picker__select-row mj-voice-picker__select-row--model\">\n <label class=\"mj-voice-picker__select-label\" for=\"mjRealtimeVoiceSelect\">\n <i class=\"fa-solid fa-waveform-lines\"></i>\n <span>Voice</span>\n </label>\n <select\n #voiceSelect\n id=\"mjRealtimeVoiceSelect\"\n class=\"mj-voice-picker__select\"\n [value]=\"SelectedVoiceId ?? ''\"\n (change)=\"OnVoiceChange(voiceSelect.value)\">\n <option value=\"\">Default</option>\n @for (v of SelectedModelVoices; track v.ID) {\n <option [value]=\"v.ID\">{{ v.Name }}</option>\n }\n </select>\n </div>\n }\n }\n <div class=\"mj-voice-picker__record-row\">\n <span class=\"mj-voice-picker__record-label\">\n <i class=\"fa-solid fa-microphone\"></i>\n <span class=\"mj-voice-picker__record-copy\">\n Record this call\n <small>Audio stored securely</small>\n </span>\n </span>\n <label class=\"mj-voice-picker__switch\">\n <input\n type=\"checkbox\"\n [checked]=\"RecordingConsent\"\n (change)=\"OnRecordingConsentChange($any($event.target).checked)\"\n aria-label=\"Record this call (audio stored securely)\" />\n <span class=\"mj-voice-picker__switch-track\"></span>\n </label>\n </div>\n <div class=\"mj-voice-picker__footer\">\n <button mjButton variant=\"primary\" size=\"sm\" [disabled]=\"!SelectedAgent\" (click)=\"StartCall()\">\n <i class=\"fa-solid fa-phone\"></i> Start\n </button>\n <button mjButton variant=\"outline\" size=\"sm\" (click)=\"Cancel()\">Cancel</button>\n </div>\n </div>\n `,\n styles: [`\n :host {\n /* Rendered inside a body-level CDK connected overlay (see message-input) — CDK\n owns the positioning + z-index, so the host is just a plain block. The height\n cap keeps the popover from growing past the viewport; the agent list inside\n scrolls when content exceeds it. CDK's push keeps it on-screen, and because\n it lives at the body level it can never be clipped by the chat overlay border. */\n display: block;\n max-height: min(440px, calc(100vh - 24px));\n }\n .mj-voice-picker {\n width: 300px;\n max-width: calc(100vw - 24px);\n display: flex; flex-direction: column;\n /* Match the host cap so the inner flex column knows its bound and lets the agent\n list ('mj-voice-picker__list') take the remaining space + scroll. */\n max-height: min(440px, calc(100vh - 120px));\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);\n overflow: hidden;\n }\n .mj-voice-picker__header {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 12px 8px;\n font-size: 13px; font-weight: 600;\n color: var(--mj-text-primary);\n }\n .mj-voice-picker__header i { color: var(--mj-brand-primary); }\n .mj-voice-picker__search {\n display: flex; align-items: center; gap: 8px;\n margin: 0 12px 8px;\n padding: 0 10px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n }\n .mj-voice-picker__search i { font-size: 12px; color: var(--mj-text-muted); }\n .mj-voice-picker__search input {\n flex: 1; min-width: 0;\n padding: 7px 0;\n background: transparent; border: none; outline: none;\n font-size: 13px; color: var(--mj-text-primary);\n }\n .mj-voice-picker__search input::placeholder { color: var(--mj-text-disabled); }\n .mj-voice-picker__search:focus-within { border-color: var(--mj-border-focus); }\n .mj-voice-picker__list {\n /* The agent list is the flexible region: it scrolls internally and gives way\n first when the whole popup is capped to the overlay height. min-height:0 lets\n it actually shrink inside the flex column; the 220px max keeps it tidy when\n there's plenty of room. */\n flex: 1 1 auto;\n min-height: 0;\n max-height: 220px; overflow-y: auto;\n border-top: 1px solid var(--mj-border-subtle);\n border-bottom: 1px solid var(--mj-border-subtle);\n padding: 4px 0;\n }\n /* Keep the chrome around the list from collapsing when the popup is height-capped. */\n .mj-voice-picker__header,\n .mj-voice-picker__search,\n .mj-voice-picker__select-row,\n .mj-voice-picker__record-row,\n .mj-voice-picker__footer { flex-shrink: 0; }\n .mj-voice-picker__item {\n display: flex; align-items: center; gap: 8px; width: 100%;\n padding: 7px 12px;\n background: transparent; border: none; cursor: pointer;\n color: var(--mj-text-primary); font-size: 13px; text-align: left;\n }\n .mj-voice-picker__item i { width: 16px; text-align: center; color: var(--mj-text-secondary); }\n .mj-voice-picker__item:hover { background: var(--mj-bg-surface-hover); }\n .mj-voice-picker__item--selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n }\n .mj-voice-picker__item--selected i { color: var(--mj-brand-primary); }\n .mj-voice-picker__item-name {\n flex: 1; min-width: 0;\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n }\n .mj-voice-picker__default-badge {\n flex-shrink: 0;\n padding: 1px 6px;\n border-radius: 999px;\n font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n }\n .mj-voice-picker__empty {\n padding: 12px; font-size: 12px; color: var(--mj-text-muted); text-align: center;\n }\n .mj-voice-picker__select-row {\n display: flex; align-items: center; gap: 8px;\n padding: 0 12px 8px;\n }\n .mj-voice-picker__select-row--model {\n padding: 8px 12px 0;\n }\n .mj-voice-picker__select-label {\n display: flex; align-items: center; gap: 6px;\n flex-shrink: 0;\n font-size: 12px; color: var(--mj-text-secondary);\n }\n .mj-voice-picker__select-label i { font-size: 11px; color: var(--mj-text-muted); }\n .mj-voice-picker__select {\n flex: 1; min-width: 0;\n padding: 5px 8px;\n font-size: 12px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n outline: none;\n }\n .mj-voice-picker__select:focus { border-color: var(--mj-border-focus); }\n .mj-voice-picker__record-row {\n display: flex; align-items: center; justify-content: space-between; gap: 10px;\n margin: 10px 12px 2px;\n padding: 10px 0 2px;\n border-top: 1px solid var(--mj-border-subtle);\n }\n .mj-voice-picker__record-label {\n display: flex; align-items: center; gap: 8px;\n font-size: 12px; color: var(--mj-text-secondary);\n }\n .mj-voice-picker__record-label > i { font-size: 12px; color: var(--mj-text-muted); }\n .mj-voice-picker__record-copy { display: flex; flex-direction: column; line-height: 1.3; }\n .mj-voice-picker__record-copy small { font-size: 10px; color: var(--mj-text-muted); }\n .mj-voice-picker__switch { position: relative; flex-shrink: 0; display: inline-flex; cursor: pointer; }\n .mj-voice-picker__switch input {\n position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer;\n }\n .mj-voice-picker__switch-track {\n position: relative; width: 34px; height: 18px; border-radius: 999px;\n background: var(--mj-border-strong); transition: background 150ms ease;\n }\n .mj-voice-picker__switch-track::after {\n content: ''; position: absolute; top: 2px; left: 2px;\n width: 14px; height: 14px; border-radius: 50%;\n background: var(--mj-bg-surface); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);\n transition: transform 150ms ease;\n }\n .mj-voice-picker__switch input:checked + .mj-voice-picker__switch-track { background: var(--mj-brand-primary); }\n .mj-voice-picker__switch input:checked + .mj-voice-picker__switch-track::after { transform: translateX(16px); }\n .mj-voice-picker__switch input:focus-visible + .mj-voice-picker__switch-track {\n outline: 2px solid var(--mj-border-focus); outline-offset: 2px;\n }\n @media (prefers-reduced-motion: reduce) {\n .mj-voice-picker__switch-track, .mj-voice-picker__switch-track::after { transition: none; }\n }\n .mj-voice-picker__footer {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 12px;\n }\n `]\n})\nexport class RealtimeAgentPickerComponent extends BaseAngularComponent implements OnInit, AfterViewInit {\n /**\n * The authenticated user context (forwarded from the host composer / chat area).\n * Falls back to `this.ProviderToUse?.CurrentUser` when not provided.\n */\n @Input() CurrentUser: UserInfo | null = null;\n\n /** Returns the explicit CurrentUser input or falls back to ProviderToUse.CurrentUser. */\n public get EffectiveUser(): UserInfo | null {\n return this.CurrentUser ?? this.ProviderToUse?.CurrentUser ?? null;\n }\n\n /** Agents the user can call — same cached set the @mention / routing logic uses. */\n @Input() Agents: MJAIAgentEntityExtended[] = [];\n\n /** The agent the default resolution would pick — preselected and listed first. */\n @Input() DefaultAgentId: string | null = null;\n\n /**\n * The ACTIVE Realtime-type co-agent candidates the user can run (host-filtered from\n * the same cached, run-permission-filtered agent set as {@link Agents}). The co-agent\n * selector renders only when MORE THAN ONE candidate exists — with zero or one\n * there's nothing meaningful to choose and the server's resolution chain applies.\n */\n @Input() CoAgents: MJAIAgentEntityExtended[] = [];\n\n /**\n * The user's persisted co-agent preference (host-loaded via `UserInfoEngine`) —\n * preselected in the co-agent selector when it's still a valid candidate.\n */\n @Input() DefaultCoAgentId: string | null = null;\n\n /** Emitted with the chosen agent + optional explicit voice model / co-agent when the user confirms. */\n @Output() AgentPicked = new EventEmitter<RealtimeAgentPick>();\n\n /** Emitted when the user dismisses without starting a call. */\n @Output() Cancelled = new EventEmitter<void>();\n\n @ViewChild('searchInput') private searchInput?: ElementRef<HTMLInputElement>;\n\n public SearchText = '';\n public SelectedAgentId: string | null = null;\n\n /** Active Realtime models the model selector offers (loaded only for authorized users). */\n public Models: RealtimeModelOption[] = [];\n\n /** The explicitly chosen voice model id, or `null` for \"Auto (recommended)\" (the default). */\n public SelectedModelId: string | null = null;\n\n /** Active Realtime models + their voices (for the voice selector); loaded only for authorized users. */\n public VoiceModels: RealtimeModelVoices[] = [];\n\n /** The explicitly chosen voice id, or `null` for the configured/default voice. */\n public SelectedVoiceId: string | null = null;\n\n /** Voices for the currently-selected model (empty when no model picked or it declares none). */\n public get SelectedModelVoices(): RealtimeVoiceOption[] {\n return this.VoiceModels.find((m) => UUIDsEqual(m.ModelID, this.SelectedModelId))?.Voices ?? [];\n }\n\n /** The explicitly chosen co-agent id, or `null` for \"Auto (recommended)\" (the server's chain). */\n public SelectedCoAgentId: string | null = null;\n\n /**\n * Whether the user has opted to record this call (mic + agent audio). Loaded from the\n * per-user persisted preference (`mj.realtimeVoice.recordingConsent.v1`) on init and\n * persisted cross-device on change. Defaults to off.\n */\n public RecordingConsent = false;\n\n /**\n * Whether the current user holds the `Realtime: Advanced Session Controls`\n * authorization. Gates the voice-model selector (and any future config-override\n * controls) — pure disclosure; the server enforces the authorization on the mint.\n */\n public CanOverrideSessionConfig = false;\n\n /** The selected co-agent's pairing rows; empty = universal co-agent (no constraint). */\n public Pairings: RealtimePairedAgentRow[] = [];\n\n // Template helper — expose the shared UUID comparator to the view.\n public readonly UUIDsEqual = UUIDsEqual;\n\n private readonly cdr = inject(ChangeDetectorRef);\n private readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n /** Monotonic guard so a stale pairing load can't clobber a newer co-agent choice. */\n private pairingLoadToken = 0;\n\n /** Co-agent selector visibility: only when there is a real choice to make. */\n public get ShowCoAgentSelect(): boolean {\n return this.CoAgents.length > 1;\n }\n\n /** True while the agent list is constrained to the selected co-agent's paired targets. */\n public get IsConstrainedByPairings(): boolean {\n return this.Pairings.length > 0;\n }\n\n public ngOnInit(): void {\n const initial = this.DefaultAgentId && this.findAgent(this.DefaultAgentId)\n ? this.DefaultAgentId\n : this.FilteredAgents[0]?.ID ?? null;\n this.SelectedAgentId = initial;\n void this.checkAuthorizationAndLoadModels();\n // Preselect the persisted co-agent preference when it's still a valid candidate.\n if (this.DefaultCoAgentId && this.CoAgents.some(a => UUIDsEqual(a.ID, this.DefaultCoAgentId))) {\n this.SelectedCoAgentId = this.DefaultCoAgentId;\n void this.reloadPairings();\n }\n this.RecordingConsent = this.readPersistedRecordingConsent();\n }\n\n /**\n * Checks whether the user holds the advanced-session-controls authorization and, if so,\n * loads the available realtime voice models and voices. If the initially evaluated user\n * lacks the authorization, attempts a one-time RefreshCurrentUser() on the provider in\n * case role assignments were granted after client metadata was cached.\n */\n private async checkAuthorizationAndLoadModels(): Promise<void> {\n this.CanOverrideSessionConfig = UserHoldsAuthorization(\n this.EffectiveUser,\n REALTIME_ADVANCED_SESSION_CONTROLS,\n this.ProviderToUse\n );\n\n if (!this.CanOverrideSessionConfig && this.ProviderToUse?.RefreshCurrentUser) {\n try {\n const refreshed = await this.ProviderToUse.RefreshCurrentUser();\n if (refreshed) {\n this.CanOverrideSessionConfig = UserHoldsAuthorization(\n refreshed,\n REALTIME_ADVANCED_SESSION_CONTROLS,\n this.ProviderToUse\n );\n }\n } catch (e) {\n console.warn('[RealtimeAgentPicker] Failed to refresh CurrentUser for authorization check:', e);\n }\n }\n\n if (this.CanOverrideSessionConfig) {\n await this.loadVoiceModels();\n }\n this.cdr.markForCheck();\n }\n\n /** Reads the per-user recording-consent preference (defensive: any failure → off). */\n private readPersistedRecordingConsent(): boolean {\n try {\n return UserInfoEngine.Instance.GetSetting(RECORDING_CONSENT_KEY) === 'true';\n } catch {\n return false;\n }\n }\n\n /** Records + persists (cross-device, debounced) the user's recording-consent choice. */\n public OnRecordingConsentChange(checked: boolean): void {\n this.RecordingConsent = checked;\n try {\n UserInfoEngine.Instance.SetSettingDebounced(RECORDING_CONSENT_KEY, String(checked));\n } catch (error) {\n console.warn('[RealtimeAgentPicker] Failed to persist recording consent:', error);\n }\n this.cdr.markForCheck();\n }\n\n /**\n * Loads the \"Voice model\" options: active models whose type is `Realtime`, filtered from\n * {@link AIEngineBase}'s already-cached `Models` (provider-scoped engine instance, lazy\n * `Config` — no RunView round-trip). Called ONLY for users who hold the\n * advanced-session-controls authorization. Tolerant — a failure simply leaves\n * the selector hidden (the server's automatic selection still applies).\n */\n private async loadVoiceModels(): Promise<void> {\n try {\n const engine = AIEngineBase.GetProviderInstance<AIEngineBase>(this.ProviderToUse, AIEngineBase) as AIEngineBase;\n await engine.Config(false, undefined, this.ProviderToUse);\n this.Models = BuildRealtimeModelOptions(engine.Models ?? []);\n } catch (error) {\n console.error('[RealtimeAgentPicker] Failed to load realtime models:', error);\n this.Models = [];\n }\n // Voices come from the driver via a server query (the cached models carry no voice list).\n try {\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n this.VoiceModels = await client.GetRealtimeModelVoices();\n } catch (error) {\n console.error('[RealtimeAgentPicker] Failed to load realtime voices:', error);\n this.VoiceModels = [];\n }\n this.cdr.markForCheck();\n }\n\n /** Records the voice-model choice (`''` = Auto → `null`); clears the voice so it can't outlive a switch. */\n public OnModelChange(value: string): void {\n this.SelectedModelId = value && value.length > 0 ? value : null;\n this.SelectedVoiceId = null;\n this.cdr.markForCheck();\n }\n\n /** Records the voice choice (`''` = default → `null`). */\n public OnVoiceChange(value: string): void {\n this.SelectedVoiceId = value && value.length > 0 ? value : null;\n this.cdr.markForCheck();\n }\n\n /** Records the co-agent choice (`''` = Auto → `null`) and refreshes the pairing constraint. */\n public OnCoAgentChange(value: string): void {\n this.SelectedCoAgentId = value && value.length > 0 ? value : null;\n void this.reloadPairings();\n }\n\n /**\n * Loads the selected co-agent's pairing rows and re-applies the target constraint:\n * with rows present, the agent list narrows to the paired targets (Sequence order)\n * and the IsDefault row's target is preselected; with zero rows (or Auto co-agent)\n * the list returns to the unconstrained default. Guarded against stale loads when\n * the user changes co-agents quickly.\n */\n private async reloadPairings(): Promise<void> {\n const token = ++this.pairingLoadToken;\n const coAgentId = this.SelectedCoAgentId;\n const pairings = coAgentId ? await LoadCoAgentPairings(this.ProviderToUse, coAgentId) : [];\n if (token !== this.pairingLoadToken) {\n return; // a newer co-agent choice superseded this load\n }\n this.Pairings = pairings;\n this.ensureSelectionVisible();\n this.cdr.markForCheck();\n }\n\n /**\n * Keeps the target selection coherent after the visible list changes: prefers the\n * pairing default (when constrained), then the host default, then keeps the current\n * selection when still visible, then the first visible row.\n */\n private ensureSelectionVisible(): void {\n const visible = this.FilteredAgents;\n if (this.IsConstrainedByPairings) {\n const pairedDefault = DefaultPairedTargetId(this.Pairings);\n if (pairedDefault && visible.some(a => UUIDsEqual(a.ID, pairedDefault))) {\n this.SelectedAgentId = pairedDefault;\n return;\n }\n }\n if (this.SelectedAgentId && visible.some(a => UUIDsEqual(a.ID, this.SelectedAgentId))) {\n return; // current selection still valid\n }\n if (this.DefaultAgentId && visible.some(a => UUIDsEqual(a.ID, this.DefaultAgentId))) {\n this.SelectedAgentId = this.DefaultAgentId;\n return;\n }\n this.SelectedAgentId = visible[0]?.ID ?? null;\n }\n\n public ngAfterViewInit(): void {\n // Microtask so focus lands after the popover renders without\n // triggering ExpressionChangedAfterItHasBeenChecked.\n Promise.resolve().then(() => this.searchInput?.nativeElement.focus());\n }\n\n /**\n * The visible target list: pairing-constrained first (a co-agent WITH pairing rows may\n * only front its paired targets, kept in pairing Sequence order), then search-filtered.\n * Unconstrained lists keep the default-first + alphabetical ordering.\n */\n public get FilteredAgents(): MJAIAgentEntityExtended[] {\n const base = ConstrainTargetsToPairings(this.Agents, this.Pairings);\n const needle = this.SearchText.trim().toLowerCase();\n const filtered = base.filter(a => !needle || (a.Name ?? '').toLowerCase().includes(needle));\n if (this.IsConstrainedByPairings) {\n return filtered; // pairing Sequence order is the canonical order\n }\n return filtered.sort((a, b) => {\n const aDefault = this.isDefault(a) ? 0 : 1;\n const bDefault = this.isDefault(b) ? 0 : 1;\n if (aDefault !== bDefault) return aDefault - bDefault;\n return (a.Name ?? '').localeCompare(b.Name ?? '');\n });\n }\n\n public get SelectedAgent(): MJAIAgentEntityExtended | null {\n return this.SelectedAgentId ? this.findAgent(this.SelectedAgentId) : null;\n }\n\n public IsSelected(agent: MJAIAgentEntityExtended): boolean {\n return !!this.SelectedAgentId && UUIDsEqual(agent.ID, this.SelectedAgentId);\n }\n\n /**\n * Whether `agent` carries the \"default\" badge: under a pairing constraint that's the\n * co-agent's IsDefault target; otherwise the host-resolved default agent.\n */\n public IsDefaultChoice(agent: MJAIAgentEntityExtended): boolean {\n if (this.IsConstrainedByPairings) {\n const pairedDefault = DefaultPairedTargetId(this.Pairings);\n return !!pairedDefault && UUIDsEqual(agent.ID, pairedDefault);\n }\n return this.isDefault(agent);\n }\n\n public IconClassFor(agent: MJAIAgentEntityExtended): string {\n return agent.IconClass?.trim() || 'fa-solid fa-robot';\n }\n\n public OnSearchInput(value: string): void {\n this.SearchText = value;\n // Keep the selection on a visible row.\n const visible = this.FilteredAgents;\n if (!visible.some(a => this.IsSelected(a))) {\n this.SelectedAgentId = visible[0]?.ID ?? null;\n }\n this.cdr.markForCheck();\n }\n\n /** Arrow-key navigation through the filtered list. */\n public MoveSelection(delta: number): void {\n const visible = this.FilteredAgents;\n if (visible.length === 0) return;\n const currentIndex = visible.findIndex(a => this.IsSelected(a));\n const nextIndex = currentIndex < 0\n ? 0\n : Math.min(visible.length - 1, Math.max(0, currentIndex + delta));\n this.SelectedAgentId = visible[nextIndex].ID;\n this.cdr.markForCheck();\n }\n\n public Select(agent: MJAIAgentEntityExtended): void {\n this.SelectedAgentId = agent.ID;\n this.cdr.markForCheck();\n }\n\n /** Confirm a specific agent immediately (double-click shortcut). */\n public Pick(agent: MJAIAgentEntityExtended): void {\n this.AgentPicked.emit(this.buildPick(agent));\n }\n\n public StartCall(): void {\n const agent = this.SelectedAgent;\n if (agent) {\n this.AgentPicked.emit(this.buildPick(agent));\n }\n }\n\n public Cancel(): void {\n this.Cancelled.emit();\n }\n\n /** Dismiss when the user clicks anywhere outside the popover. (The phone\n * button that opens it stops propagation, so the opening click never\n * reaches this handler.) */\n @HostListener('document:click', ['$event'])\n public OnDocumentClick(event: MouseEvent): void {\n if (!this.elementRef.nativeElement.contains(event.target as Node)) {\n this.Cancelled.emit();\n }\n }\n\n @HostListener('document:keydown.escape')\n public OnEscape(): void {\n this.Cancelled.emit();\n }\n\n /**\n * Assembles the emitted pick. The model preference is hard-gated on the\n * authorization here (defense in depth — unauthorized users never see the selector,\n * so `SelectedModelId` should already be null).\n */\n private buildPick(agent: MJAIAgentEntityExtended): RealtimeAgentPick {\n return {\n Agent: agent,\n PreferredModelId: this.CanOverrideSessionConfig ? this.SelectedModelId : null,\n PreferredVoice: this.CanOverrideSessionConfig ? this.SelectedVoiceId : null,\n CoAgentId: this.SelectedCoAgentId,\n RecordingConsent: this.RecordingConsent\n };\n }\n\n private isDefault(agent: MJAIAgentEntityExtended): boolean {\n return !!this.DefaultAgentId && UUIDsEqual(agent.ID, this.DefaultAgentId);\n }\n\n private findAgent(id: string): MJAIAgentEntityExtended | null {\n return this.Agents.find(a => UUIDsEqual(a.ID, id)) ?? null;\n }\n}\n"]}
1
+ {"version":3,"file":"realtime-agent-picker.component.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-agent-picker.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n HostListener,\n Input,\n OnInit,\n Output,\n ViewChild,\n AfterViewInit,\n inject,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport type { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';\nimport { MJButtonDirective, MJDropdownComponent } from '@memberjunction/ng-ui-components';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { UserInfo } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { REALTIME_ADVANCED_SESSION_CONTROLS, UserHoldsAuthorization } from '../../services/user-authorization';\nimport {\n BuildRealtimeModelOptions,\n ConstrainTargetsToPairings,\n DefaultPairedTargetId,\n LoadCoAgentPairings,\n RealtimeModelOption,\n RealtimePairedAgentRow,\n} from '../../services/realtime-pairing';\nimport { GraphQLLiveKitClient, GraphQLDataProvider, RealtimeModelVoices, RealtimeVoiceOption } from '@memberjunction/graphql-dataprovider';\n\n/**\n * The user's confirmed choice from the realtime picker: the agent to call, an optional\n * EXPLICIT realtime model (`null` = \"Auto (recommended)\", i.e. let the server pick —\n * always `null` for users without the `Realtime: Advanced Session Controls`\n * authorization, who never see the model selector), and an optional EXPLICIT co-agent\n * (`null` = the server's co-agent resolution chain).\n */\nexport interface RealtimeAgentPick {\n /** The agent the voice call should front. */\n Agent: MJAIAgentEntityExtended;\n /** Explicit realtime model id, or `null` for the server's automatic selection. */\n PreferredModelId: string | null;\n /** Explicit provider-native voice id (e.g. `echo`), or `null` for the configured/default voice. */\n PreferredVoice: string | null;\n /**\n * The avatar that comes with the picked voice (its `RealtimeVoiceOption.AvatarID`), or `null`/absent when the voice\n * has none or no voice was picked. The session then asks for that face, with video on.\n */\n PreferredAvatarId?: string | null;\n /** Explicit co-agent id (`MJ: AI Agents.ID`, Realtime type), or `null` for the server's resolution chain. */\n CoAgentId: string | null;\n /** Whether the user consented to recording this call (mic + agent audio). */\n RecordingConsent: boolean;\n}\n\n/** `MJ: User Settings` key for the per-user \"record this call\" consent toggle (string `'true'`/`'false'`). */\nconst RECORDING_CONSENT_KEY = 'mj.realtimeVoice.recordingConsent.v1';\n\n/**\n * Compact anchored popover that lets the user choose WHICH agent a realtime\n * voice call should front — shown by {@link MessageInputComponent} when the\n * phone button is clicked on a conversation with **no prior agent\n * participation** (new / empty conversation), and on demand via the caret\n * button next to the phone (any conversation), where it doubles as the way\n * to pick a specific **co-agent** (the Realtime-type agent that voices the\n * call) and — for authorized users — a specific **voice model**. The plain\n * phone click on an existing conversation keeps its friction-free \"call the\n * resolved agent immediately\" behavior.\n *\n * Mostly dumb: the host supplies the agent list (the same cached set the\n * @mention autocomplete / routing logic uses), the Realtime-type co-agent\n * candidates (filtered from that same set), and the defaults to preselect;\n * the picker emits the user's choice. The data it loads itself:\n * - the compact \"Voice model\" option list (active Realtime models via a\n * narrow RunView) and each model's voices — loaded and rendered ONLY when\n * the current user holds the `Realtime: Advanced Session Controls`\n * authorization (pure UX disclosure; the server enforces the authorization\n * on the mint). The voice list marks the voices whose persona comes with an\n * avatar (a camera icon) and shows a persona's preview image when it has\n * one; picking such a voice also picks its avatar, and\n * - the chosen co-agent's pairing rows (`MJ: AI Agent Co Agents`, Active 'CoAgent'-type rows): a\n * co-agent with pairing rows may only front its paired targets, so the\n * agent list constrains to those rows (Sequence order) with the IsDefault\n * row preselected; a co-agent with zero rows is universal and the list is\n * untouched.\n *\n * It does NOT persist anything (the host persists the co-agent preference\n * via `UserInfoEngine`; `mj-conversation-agent-picker` pins\n * `MJConversationEntity.DefaultAgentID` — different jobs, which is why this\n * is a separate component).\n *\n * Anchors itself bottom-right above the composer — the host's\n * `.message-input-wrapper` is `position: relative`.\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-agent-picker',\n imports: [MJButtonDirective, MJDropdownComponent, FormsModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"mj-voice-picker\" (click)=\"$event.stopPropagation()\">\n <div class=\"mj-voice-picker__header\">\n <i class=\"fa-solid fa-phone\"></i>\n <span>Start a voice call with…</span>\n </div>\n @if (ShowCoAgentSelect) {\n <div class=\"mj-voice-picker__select-row\">\n <label class=\"mj-voice-picker__select-label\" for=\"mjRealtimeCoAgentSelect\">\n <i class=\"fa-solid fa-headset\"></i>\n <span>Co-agent</span>\n </label>\n <select\n #coAgentSelect\n id=\"mjRealtimeCoAgentSelect\"\n class=\"mj-voice-picker__select\"\n [value]=\"SelectedCoAgentId ?? ''\"\n (change)=\"OnCoAgentChange(coAgentSelect.value)\">\n <option value=\"\">Auto (recommended)</option>\n @for (coAgent of CoAgents; track coAgent.ID) {\n <option [value]=\"coAgent.ID\">{{ coAgent.Name }}</option>\n }\n </select>\n </div>\n }\n <div class=\"mj-voice-picker__search\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n <input\n #searchInput\n type=\"text\"\n placeholder=\"Search agents\"\n [value]=\"SearchText\"\n (input)=\"OnSearchInput(searchInput.value)\"\n (keydown.enter)=\"StartCall()\"\n (keydown.arrowdown)=\"MoveSelection(1); $event.preventDefault()\"\n (keydown.arrowup)=\"MoveSelection(-1); $event.preventDefault()\" />\n </div>\n <div class=\"mj-voice-picker__list\">\n @if (FilteredAgents.length === 0) {\n <div class=\"mj-voice-picker__empty\">{{ IsConstrainedByPairings ? 'No paired agents available' : 'No matching agents' }}</div>\n } @else {\n @for (agent of FilteredAgents; track agent.ID) {\n <button\n type=\"button\"\n class=\"mj-voice-picker__item\"\n [class.mj-voice-picker__item--selected]=\"IsSelected(agent)\"\n [title]=\"agent.Description || agent.Name\"\n (click)=\"Select(agent)\"\n (dblclick)=\"Pick(agent)\">\n <i [class]=\"IconClassFor(agent)\"></i>\n <span class=\"mj-voice-picker__item-name\">{{ agent.Name }}</span>\n @if (IsDefaultChoice(agent)) {\n <span class=\"mj-voice-picker__default-badge\">default</span>\n }\n </button>\n }\n }\n </div>\n @if (CanOverrideSessionConfig && Models.length > 0) {\n <div class=\"mj-voice-picker__select-row mj-voice-picker__select-row--model\">\n <label class=\"mj-voice-picker__select-label\" for=\"mjRealtimeModelSelect\">\n <i class=\"fa-solid fa-microchip\"></i>\n <span>Voice model</span>\n </label>\n <select\n #modelSelect\n id=\"mjRealtimeModelSelect\"\n class=\"mj-voice-picker__select\"\n [value]=\"SelectedModelId ?? ''\"\n (change)=\"OnModelChange(modelSelect.value)\">\n <option value=\"\">Auto (recommended)</option>\n @for (model of Models; track model.ID) {\n <option [value]=\"model.ID\">{{ model.Name }}</option>\n }\n </select>\n </div>\n @if (SelectedModelVoices.length) {\n <div class=\"mj-voice-picker__select-row mj-voice-picker__select-row--model mj-voice-picker__voice-row\">\n <span class=\"mj-voice-picker__select-label\" id=\"mjRealtimeVoiceLabel\">\n <i class=\"fa-solid fa-wave-square\"></i>\n <span>Voice</span>\n </span>\n <!-- No ValueField: an option is its voice object, one per persona, because two personas\n can share a voice id (a voice, and the same voice with a face). -->\n <mj-dropdown\n class=\"mj-voice-picker__voice-dropdown\"\n InputId=\"mjRealtimeVoiceSelect\"\n AriaLabelledBy=\"mjRealtimeVoiceLabel\"\n AriaDescribedBy=\"mjRealtimeVoiceHint\"\n [Data]=\"SelectedModelVoices\"\n TextField=\"Name\"\n DefaultItem=\"Default\"\n [ngModel]=\"SelectedVoice\"\n (ValueChange)=\"OnVoiceChange($event)\">\n <ng-template #mjDropdownItem let-item>\n @if (VoiceOptionFor(item); as voice) {\n <span class=\"mj-voice-picker__voice\">\n @if (PreviewImageFor(voice); as image) {\n <img class=\"mj-voice-picker__voice-image\" [src]=\"image\" alt=\"\" (error)=\"OnPreviewImageError(image)\" />\n }\n <span class=\"mj-voice-picker__voice-name\">{{ voice.Name }}</span>\n @if (voice.AvatarID) {\n <span class=\"mj-voice-picker__voice-avatar\" title=\"Comes with an avatar\">\n <i class=\"fa-solid fa-video\" aria-hidden=\"true\"></i>\n <span class=\"mj-voice-picker__sr-only\">Comes with an avatar</span>\n </span>\n }\n </span>\n }\n </ng-template>\n </mj-dropdown>\n <!-- Always present, so screen readers announce the hint when a pick adds it. -->\n <div class=\"mj-voice-picker__voice-hint\" id=\"mjRealtimeVoiceHint\" aria-live=\"polite\">\n @if (SelectedVoiceHasAvatar) {\n <span class=\"mj-voice-picker__voice-hint-line\">\n <i class=\"fa-solid fa-video\" aria-hidden=\"true\"></i>\n <span>Comes with an avatar</span>\n </span>\n }\n </div>\n </div>\n }\n }\n <div class=\"mj-voice-picker__record-row\">\n <span class=\"mj-voice-picker__record-label\">\n <i class=\"fa-solid fa-microphone\"></i>\n <span class=\"mj-voice-picker__record-copy\">\n Record this call\n <small>Audio stored securely</small>\n </span>\n </span>\n <label class=\"mj-voice-picker__switch\">\n <input\n type=\"checkbox\"\n [checked]=\"RecordingConsent\"\n (change)=\"OnRecordingConsentChange($any($event.target).checked)\"\n aria-label=\"Record this call (audio stored securely)\" />\n <span class=\"mj-voice-picker__switch-track\"></span>\n </label>\n </div>\n <div class=\"mj-voice-picker__footer\">\n <button mjButton variant=\"primary\" size=\"sm\" [disabled]=\"!SelectedAgent\" (click)=\"StartCall()\">\n <i class=\"fa-solid fa-phone\"></i> Start\n </button>\n <button mjButton variant=\"outline\" size=\"sm\" (click)=\"Cancel()\">Cancel</button>\n </div>\n </div>\n `,\n styles: [`\n :host {\n /* Rendered inside a body-level CDK connected overlay (see message-input) — CDK\n owns the positioning + z-index, so the host is just a plain block. The height\n cap keeps the popover from growing past the viewport; the agent list inside\n scrolls when content exceeds it. CDK's push keeps it on-screen, and because\n it lives at the body level it can never be clipped by the chat overlay border. */\n display: block;\n max-height: min(440px, calc(100vh - 24px));\n }\n .mj-voice-picker {\n width: 300px;\n max-width: calc(100vw - 24px);\n display: flex; flex-direction: column;\n /* Match the host cap so the inner flex column knows its bound and lets the agent\n list ('mj-voice-picker__list') take the remaining space + scroll. */\n max-height: min(440px, calc(100vh - 120px));\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);\n overflow: hidden;\n }\n .mj-voice-picker__header {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 12px 8px;\n font-size: 13px; font-weight: 600;\n color: var(--mj-text-primary);\n }\n .mj-voice-picker__header i { color: var(--mj-brand-primary); }\n .mj-voice-picker__search {\n display: flex; align-items: center; gap: 8px;\n margin: 0 12px 8px;\n padding: 0 10px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n }\n .mj-voice-picker__search i { font-size: 12px; color: var(--mj-text-muted); }\n .mj-voice-picker__search input {\n flex: 1; min-width: 0;\n padding: 7px 0;\n background: transparent; border: none; outline: none;\n font-size: 13px; color: var(--mj-text-primary);\n }\n .mj-voice-picker__search input::placeholder { color: var(--mj-text-disabled); }\n .mj-voice-picker__search:focus-within { border-color: var(--mj-border-focus); }\n .mj-voice-picker__list {\n /* The agent list is the flexible region: it scrolls internally and gives way\n first when the whole popup is capped to the overlay height. min-height:0 lets\n it actually shrink inside the flex column; the 220px max keeps it tidy when\n there's plenty of room. */\n flex: 1 1 auto;\n min-height: 0;\n max-height: 220px; overflow-y: auto;\n border-top: 1px solid var(--mj-border-subtle);\n border-bottom: 1px solid var(--mj-border-subtle);\n padding: 4px 0;\n }\n /* Keep the chrome around the list from collapsing when the popup is height-capped. */\n .mj-voice-picker__header,\n .mj-voice-picker__search,\n .mj-voice-picker__select-row,\n .mj-voice-picker__record-row,\n .mj-voice-picker__footer { flex-shrink: 0; }\n .mj-voice-picker__item {\n display: flex; align-items: center; gap: 8px; width: 100%;\n padding: 7px 12px;\n background: transparent; border: none; cursor: pointer;\n color: var(--mj-text-primary); font-size: 13px; text-align: left;\n }\n .mj-voice-picker__item i { width: 16px; text-align: center; color: var(--mj-text-secondary); }\n .mj-voice-picker__item:hover { background: var(--mj-bg-surface-hover); }\n .mj-voice-picker__item--selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n }\n .mj-voice-picker__item--selected i { color: var(--mj-brand-primary); }\n .mj-voice-picker__item-name {\n flex: 1; min-width: 0;\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n }\n .mj-voice-picker__default-badge {\n flex-shrink: 0;\n padding: 1px 6px;\n border-radius: 999px;\n font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n }\n .mj-voice-picker__empty {\n padding: 12px; font-size: 12px; color: var(--mj-text-muted); text-align: center;\n }\n .mj-voice-picker__select-row {\n display: flex; align-items: center; gap: 8px;\n padding: 0 12px 8px;\n }\n .mj-voice-picker__select-row--model {\n padding: 8px 12px 0;\n }\n .mj-voice-picker__select-label {\n display: flex; align-items: center; gap: 6px;\n flex-shrink: 0;\n font-size: 12px; color: var(--mj-text-secondary);\n }\n .mj-voice-picker__select-label i { font-size: 11px; color: var(--mj-text-muted); }\n .mj-voice-picker__select {\n flex: 1; min-width: 0;\n padding: 5px 8px;\n font-size: 12px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n outline: none;\n }\n .mj-voice-picker__select:focus { border-color: var(--mj-border-focus); }\n /* The voice list is an mj-dropdown so its options can carry the avatar mark. The global dropdown styles size\n it for forms; scoped to this row, its trigger matches the native selects above it. The row is a grid so\n the hint sits under the dropdown, and an empty hint takes no space. */\n .mj-voice-picker__voice-row {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n column-gap: 8px;\n align-items: center;\n }\n .mj-voice-picker__voice-dropdown { min-width: 0; }\n .mj-voice-picker__voice-hint { grid-column: 2; }\n .mj-voice-picker__voice-hint-line {\n display: flex; align-items: center; gap: 6px;\n padding-top: 4px;\n font-size: 11px; color: var(--mj-text-secondary);\n }\n .mj-voice-picker__voice-hint-line i { font-size: 10px; color: var(--mj-brand-primary); }\n :host ::ng-deep .mj-voice-picker__voice-row .mj-dropdown {\n min-height: 0;\n padding: 5px 8px;\n font-size: 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n }\n :host ::ng-deep .mj-voice-picker__voice-row .mj-dropdown--open,\n :host ::ng-deep .mj-voice-picker__voice-row .mj-dropdown:focus-visible { border-color: var(--mj-border-focus); }\n .mj-voice-picker__voice { display: flex; align-items: center; gap: 8px; width: 100%; min-width: 0; }\n .mj-voice-picker__voice-image {\n width: 20px; height: 20px; flex-shrink: 0;\n border-radius: 50%; object-fit: cover;\n background: var(--mj-bg-surface-sunken);\n }\n .mj-voice-picker__voice-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .mj-voice-picker__voice-avatar { flex-shrink: 0; font-size: 11px; color: var(--mj-brand-primary); }\n .mj-voice-picker__sr-only {\n position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;\n overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;\n }\n .mj-voice-picker__record-row {\n display: flex; align-items: center; justify-content: space-between; gap: 10px;\n margin: 10px 12px 2px;\n padding: 10px 0 2px;\n border-top: 1px solid var(--mj-border-subtle);\n }\n .mj-voice-picker__record-label {\n display: flex; align-items: center; gap: 8px;\n font-size: 12px; color: var(--mj-text-secondary);\n }\n .mj-voice-picker__record-label > i { font-size: 12px; color: var(--mj-text-muted); }\n .mj-voice-picker__record-copy { display: flex; flex-direction: column; line-height: 1.3; }\n .mj-voice-picker__record-copy small { font-size: 10px; color: var(--mj-text-muted); }\n .mj-voice-picker__switch { position: relative; flex-shrink: 0; display: inline-flex; cursor: pointer; }\n .mj-voice-picker__switch input {\n position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer;\n }\n .mj-voice-picker__switch-track {\n position: relative; width: 34px; height: 18px; border-radius: 999px;\n background: var(--mj-border-strong); transition: background 150ms ease;\n }\n .mj-voice-picker__switch-track::after {\n content: ''; position: absolute; top: 2px; left: 2px;\n width: 14px; height: 14px; border-radius: 50%;\n background: var(--mj-bg-surface); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);\n transition: transform 150ms ease;\n }\n .mj-voice-picker__switch input:checked + .mj-voice-picker__switch-track { background: var(--mj-brand-primary); }\n .mj-voice-picker__switch input:checked + .mj-voice-picker__switch-track::after { transform: translateX(16px); }\n .mj-voice-picker__switch input:focus-visible + .mj-voice-picker__switch-track {\n outline: 2px solid var(--mj-border-focus); outline-offset: 2px;\n }\n @media (prefers-reduced-motion: reduce) {\n .mj-voice-picker__switch-track, .mj-voice-picker__switch-track::after { transition: none; }\n }\n .mj-voice-picker__footer {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 12px;\n }\n `]\n})\nexport class RealtimeAgentPickerComponent extends BaseAngularComponent implements OnInit, AfterViewInit {\n /**\n * The authenticated user context (forwarded from the host composer / chat area).\n * Falls back to `this.ProviderToUse?.CurrentUser` when not provided.\n */\n @Input() CurrentUser: UserInfo | null = null;\n\n /** Returns the explicit CurrentUser input or falls back to ProviderToUse.CurrentUser. */\n public get EffectiveUser(): UserInfo | null {\n return this.CurrentUser ?? this.ProviderToUse?.CurrentUser ?? null;\n }\n\n /** Agents the user can call — same cached set the @mention / routing logic uses. */\n @Input() Agents: MJAIAgentEntityExtended[] = [];\n\n /** The agent the default resolution would pick — preselected and listed first. */\n @Input() DefaultAgentId: string | null = null;\n\n /**\n * The ACTIVE Realtime-type co-agent candidates the user can run (host-filtered from\n * the same cached, run-permission-filtered agent set as {@link Agents}). The co-agent\n * selector renders only when MORE THAN ONE candidate exists — with zero or one\n * there's nothing meaningful to choose and the server's resolution chain applies.\n */\n @Input() CoAgents: MJAIAgentEntityExtended[] = [];\n\n /**\n * The user's persisted co-agent preference (host-loaded via `UserInfoEngine`) —\n * preselected in the co-agent selector when it's still a valid candidate.\n */\n @Input() DefaultCoAgentId: string | null = null;\n\n /** Emitted with the chosen agent + optional explicit voice model / co-agent when the user confirms. */\n @Output() AgentPicked = new EventEmitter<RealtimeAgentPick>();\n\n /** Emitted when the user dismisses without starting a call. */\n @Output() Cancelled = new EventEmitter<void>();\n\n @ViewChild('searchInput') private searchInput?: ElementRef<HTMLInputElement>;\n\n public SearchText = '';\n public SelectedAgentId: string | null = null;\n\n /** Active Realtime models the model selector offers (loaded only for authorized users). */\n public Models: RealtimeModelOption[] = [];\n\n /** The explicitly chosen voice model id, or `null` for \"Auto (recommended)\" (the default). */\n public SelectedModelId: string | null = null;\n\n /** Active Realtime models + their voices (for the voice selector); loaded only for authorized users. */\n public VoiceModels: RealtimeModelVoices[] = [];\n\n /**\n * The explicitly chosen voice option (one of {@link SelectedModelVoices}: a persona, so two personas sharing a voice\n * id stay apart), or `null` for the configured/default voice.\n */\n public SelectedVoice: RealtimeVoiceOption | null = null;\n\n /** The explicitly chosen voice id, or `null` for the configured/default voice. */\n public get SelectedVoiceId(): string | null {\n return this.SelectedVoice?.ID ?? null;\n }\n\n /** Whether the chosen voice comes with an avatar: the hint under the voice list says so. */\n public get SelectedVoiceHasAvatar(): boolean {\n return !!this.SelectedVoice?.AvatarID?.trim();\n }\n\n /** Voices for the currently-selected model (empty when no model picked or it declares none). */\n public get SelectedModelVoices(): RealtimeVoiceOption[] {\n return this.VoiceModels.find((m) => UUIDsEqual(m.ModelID, this.SelectedModelId))?.Voices ?? [];\n }\n\n /** Preview images that failed to load; their voices show no image rather than a broken one. */\n private readonly failedPreviewImages = new Set<string>();\n\n /** The explicitly chosen co-agent id, or `null` for \"Auto (recommended)\" (the server's chain). */\n public SelectedCoAgentId: string | null = null;\n\n /**\n * Whether the user has opted to record this call (mic + agent audio). Loaded from the\n * per-user persisted preference (`mj.realtimeVoice.recordingConsent.v1`) on init and\n * persisted cross-device on change. Defaults to off.\n */\n public RecordingConsent = false;\n\n /**\n * Whether the current user holds the `Realtime: Advanced Session Controls`\n * authorization. Gates the voice-model selector (and any future config-override\n * controls) — pure disclosure; the server enforces the authorization on the mint.\n */\n public CanOverrideSessionConfig = false;\n\n /** The selected co-agent's pairing rows; empty = universal co-agent (no constraint). */\n public Pairings: RealtimePairedAgentRow[] = [];\n\n // Template helper — expose the shared UUID comparator to the view.\n public readonly UUIDsEqual = UUIDsEqual;\n\n private readonly cdr = inject(ChangeDetectorRef);\n private readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n /** Monotonic guard so a stale pairing load can't clobber a newer co-agent choice. */\n private pairingLoadToken = 0;\n\n /** Co-agent selector visibility: only when there is a real choice to make. */\n public get ShowCoAgentSelect(): boolean {\n return this.CoAgents.length > 1;\n }\n\n /** True while the agent list is constrained to the selected co-agent's paired targets. */\n public get IsConstrainedByPairings(): boolean {\n return this.Pairings.length > 0;\n }\n\n public ngOnInit(): void {\n const initial = this.DefaultAgentId && this.findAgent(this.DefaultAgentId)\n ? this.DefaultAgentId\n : this.FilteredAgents[0]?.ID ?? null;\n this.SelectedAgentId = initial;\n void this.checkAuthorizationAndLoadModels();\n // Preselect the persisted co-agent preference when it's still a valid candidate.\n if (this.DefaultCoAgentId && this.CoAgents.some(a => UUIDsEqual(a.ID, this.DefaultCoAgentId))) {\n this.SelectedCoAgentId = this.DefaultCoAgentId;\n void this.reloadPairings();\n }\n this.RecordingConsent = this.readPersistedRecordingConsent();\n }\n\n /**\n * Checks whether the user holds the advanced-session-controls authorization and, if so,\n * loads the available realtime voice models and voices. If the initially evaluated user\n * lacks the authorization, attempts a one-time RefreshCurrentUser() on the provider in\n * case role assignments were granted after client metadata was cached.\n */\n private async checkAuthorizationAndLoadModels(): Promise<void> {\n this.CanOverrideSessionConfig = UserHoldsAuthorization(\n this.EffectiveUser,\n REALTIME_ADVANCED_SESSION_CONTROLS,\n this.ProviderToUse\n );\n\n if (!this.CanOverrideSessionConfig && this.ProviderToUse?.RefreshCurrentUser) {\n try {\n const refreshed = await this.ProviderToUse.RefreshCurrentUser();\n if (refreshed) {\n this.CanOverrideSessionConfig = UserHoldsAuthorization(\n refreshed,\n REALTIME_ADVANCED_SESSION_CONTROLS,\n this.ProviderToUse\n );\n }\n } catch (e) {\n console.warn('[RealtimeAgentPicker] Failed to refresh CurrentUser for authorization check:', e);\n }\n }\n\n if (this.CanOverrideSessionConfig) {\n await this.loadVoiceModels();\n }\n this.cdr.markForCheck();\n }\n\n /** Reads the per-user recording-consent preference (defensive: any failure → off). */\n private readPersistedRecordingConsent(): boolean {\n try {\n return UserInfoEngine.Instance.GetSetting(RECORDING_CONSENT_KEY) === 'true';\n } catch {\n return false;\n }\n }\n\n /** Records + persists (cross-device, debounced) the user's recording-consent choice. */\n public OnRecordingConsentChange(checked: boolean): void {\n this.RecordingConsent = checked;\n try {\n UserInfoEngine.Instance.SetSettingDebounced(RECORDING_CONSENT_KEY, String(checked));\n } catch (error) {\n console.warn('[RealtimeAgentPicker] Failed to persist recording consent:', error);\n }\n this.cdr.markForCheck();\n }\n\n /**\n * Loads the \"Voice model\" options: active models whose type is `Realtime`, filtered from\n * {@link AIEngineBase}'s already-cached `Models` (provider-scoped engine instance, lazy\n * `Config` — no RunView round-trip). Called ONLY for users who hold the\n * advanced-session-controls authorization. Tolerant — a failure simply leaves\n * the selector hidden (the server's automatic selection still applies).\n */\n private async loadVoiceModels(): Promise<void> {\n try {\n const engine = AIEngineBase.GetProviderInstance<AIEngineBase>(this.ProviderToUse, AIEngineBase) as AIEngineBase;\n await engine.Config(false, undefined, this.ProviderToUse);\n this.Models = BuildRealtimeModelOptions(engine.Models ?? []);\n } catch (error) {\n console.error('[RealtimeAgentPicker] Failed to load realtime models:', error);\n this.Models = [];\n }\n // Voices come from the driver via a server query (the cached models carry no voice list).\n try {\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n this.VoiceModels = await client.GetRealtimeModelVoices();\n } catch (error) {\n console.error('[RealtimeAgentPicker] Failed to load realtime voices:', error);\n this.VoiceModels = [];\n }\n this.cdr.markForCheck();\n }\n\n /** Records the voice-model choice (`''` = Auto → `null`); clears the voice (and its avatar) so it can't outlive a switch. */\n public OnModelChange(value: string): void {\n this.SelectedModelId = value && value.length > 0 ? value : null;\n this.SelectedVoice = null;\n this.cdr.markForCheck();\n }\n\n /**\n * Records the voice choice from the voice list: one of {@link SelectedModelVoices}, or `null` for \"Default\". The\n * voice's avatar, when it has one, goes with it.\n */\n public OnVoiceChange(value: unknown): void {\n this.SelectedVoice = this.VoiceOptionFor(value) ?? null;\n this.cdr.markForCheck();\n }\n\n /**\n * The voice an item of the voice list is. The list's items are {@link SelectedModelVoices}' own objects, matched by\n * identity: an option is a persona, and two personas can share a voice id.\n */\n public VoiceOptionFor(item: unknown): RealtimeVoiceOption | undefined {\n return this.SelectedModelVoices.find((voice) => voice === item);\n }\n\n /** The voice's persona preview image to show, or `null` when it has none or the image failed to load. */\n public PreviewImageFor(voice: RealtimeVoiceOption): string | null {\n const url = voice.PreviewImageURL?.trim();\n return url && !this.failedPreviewImages.has(url) ? url : null;\n }\n\n /** Hides a preview image that failed to load. */\n public OnPreviewImageError(url: string): void {\n this.failedPreviewImages.add(url);\n this.cdr.markForCheck();\n }\n\n /** Records the co-agent choice (`''` = Auto → `null`) and refreshes the pairing constraint. */\n public OnCoAgentChange(value: string): void {\n this.SelectedCoAgentId = value && value.length > 0 ? value : null;\n void this.reloadPairings();\n }\n\n /**\n * Loads the selected co-agent's pairing rows and re-applies the target constraint:\n * with rows present, the agent list narrows to the paired targets (Sequence order)\n * and the IsDefault row's target is preselected; with zero rows (or Auto co-agent)\n * the list returns to the unconstrained default. Guarded against stale loads when\n * the user changes co-agents quickly.\n */\n private async reloadPairings(): Promise<void> {\n const token = ++this.pairingLoadToken;\n const coAgentId = this.SelectedCoAgentId;\n const pairings = coAgentId ? await LoadCoAgentPairings(this.ProviderToUse, coAgentId) : [];\n if (token !== this.pairingLoadToken) {\n return; // a newer co-agent choice superseded this load\n }\n this.Pairings = pairings;\n this.ensureSelectionVisible();\n this.cdr.markForCheck();\n }\n\n /**\n * Keeps the target selection coherent after the visible list changes: prefers the\n * pairing default (when constrained), then the host default, then keeps the current\n * selection when still visible, then the first visible row.\n */\n private ensureSelectionVisible(): void {\n const visible = this.FilteredAgents;\n if (this.IsConstrainedByPairings) {\n const pairedDefault = DefaultPairedTargetId(this.Pairings);\n if (pairedDefault && visible.some(a => UUIDsEqual(a.ID, pairedDefault))) {\n this.SelectedAgentId = pairedDefault;\n return;\n }\n }\n if (this.SelectedAgentId && visible.some(a => UUIDsEqual(a.ID, this.SelectedAgentId))) {\n return; // current selection still valid\n }\n if (this.DefaultAgentId && visible.some(a => UUIDsEqual(a.ID, this.DefaultAgentId))) {\n this.SelectedAgentId = this.DefaultAgentId;\n return;\n }\n this.SelectedAgentId = visible[0]?.ID ?? null;\n }\n\n public ngAfterViewInit(): void {\n // Microtask so focus lands after the popover renders without\n // triggering ExpressionChangedAfterItHasBeenChecked.\n Promise.resolve().then(() => this.searchInput?.nativeElement.focus());\n }\n\n /**\n * The visible target list: pairing-constrained first (a co-agent WITH pairing rows may\n * only front its paired targets, kept in pairing Sequence order), then search-filtered.\n * Unconstrained lists keep the default-first + alphabetical ordering.\n */\n public get FilteredAgents(): MJAIAgentEntityExtended[] {\n const base = ConstrainTargetsToPairings(this.Agents, this.Pairings);\n const needle = this.SearchText.trim().toLowerCase();\n const filtered = base.filter(a => !needle || (a.Name ?? '').toLowerCase().includes(needle));\n if (this.IsConstrainedByPairings) {\n return filtered; // pairing Sequence order is the canonical order\n }\n return filtered.sort((a, b) => {\n const aDefault = this.isDefault(a) ? 0 : 1;\n const bDefault = this.isDefault(b) ? 0 : 1;\n if (aDefault !== bDefault) return aDefault - bDefault;\n return (a.Name ?? '').localeCompare(b.Name ?? '');\n });\n }\n\n public get SelectedAgent(): MJAIAgentEntityExtended | null {\n return this.SelectedAgentId ? this.findAgent(this.SelectedAgentId) : null;\n }\n\n public IsSelected(agent: MJAIAgentEntityExtended): boolean {\n return !!this.SelectedAgentId && UUIDsEqual(agent.ID, this.SelectedAgentId);\n }\n\n /**\n * Whether `agent` carries the \"default\" badge: under a pairing constraint that's the\n * co-agent's IsDefault target; otherwise the host-resolved default agent.\n */\n public IsDefaultChoice(agent: MJAIAgentEntityExtended): boolean {\n if (this.IsConstrainedByPairings) {\n const pairedDefault = DefaultPairedTargetId(this.Pairings);\n return !!pairedDefault && UUIDsEqual(agent.ID, pairedDefault);\n }\n return this.isDefault(agent);\n }\n\n public IconClassFor(agent: MJAIAgentEntityExtended): string {\n return agent.IconClass?.trim() || 'fa-solid fa-robot';\n }\n\n public OnSearchInput(value: string): void {\n this.SearchText = value;\n // Keep the selection on a visible row.\n const visible = this.FilteredAgents;\n if (!visible.some(a => this.IsSelected(a))) {\n this.SelectedAgentId = visible[0]?.ID ?? null;\n }\n this.cdr.markForCheck();\n }\n\n /** Arrow-key navigation through the filtered list. */\n public MoveSelection(delta: number): void {\n const visible = this.FilteredAgents;\n if (visible.length === 0) return;\n const currentIndex = visible.findIndex(a => this.IsSelected(a));\n const nextIndex = currentIndex < 0\n ? 0\n : Math.min(visible.length - 1, Math.max(0, currentIndex + delta));\n this.SelectedAgentId = visible[nextIndex].ID;\n this.cdr.markForCheck();\n }\n\n public Select(agent: MJAIAgentEntityExtended): void {\n this.SelectedAgentId = agent.ID;\n this.cdr.markForCheck();\n }\n\n /** Confirm a specific agent immediately (double-click shortcut). */\n public Pick(agent: MJAIAgentEntityExtended): void {\n this.AgentPicked.emit(this.buildPick(agent));\n }\n\n public StartCall(): void {\n const agent = this.SelectedAgent;\n if (agent) {\n this.AgentPicked.emit(this.buildPick(agent));\n }\n }\n\n public Cancel(): void {\n this.Cancelled.emit();\n }\n\n /** Dismiss when the user clicks anywhere outside the popover. (The phone\n * button that opens it stops propagation, so the opening click never\n * reaches this handler.) The voice list opens in its own overlay outside\n * this element; a click on it, or on the backdrop that closes it, only\n * closes the list. */\n @HostListener('document:click', ['$event'])\n public OnDocumentClick(event: MouseEvent): void {\n if (!this.elementRef.nativeElement.contains(event.target as Node) && !this.isInDropdownOverlay(event.target)) {\n this.Cancelled.emit();\n }\n }\n\n @HostListener('document:keydown.escape')\n public OnEscape(): void {\n this.Cancelled.emit();\n }\n\n /**\n * Assembles the emitted pick. The model, voice and avatar preferences are hard-gated\n * on the authorization here (defense in depth — unauthorized users never see the\n * selectors, so they should already be null).\n */\n private buildPick(agent: MJAIAgentEntityExtended): RealtimeAgentPick {\n const voice = this.CanOverrideSessionConfig ? this.SelectedVoice : null;\n return {\n Agent: agent,\n PreferredModelId: this.CanOverrideSessionConfig ? this.SelectedModelId : null,\n PreferredVoice: voice?.ID ?? null,\n PreferredAvatarId: voice?.AvatarID?.trim() || null,\n CoAgentId: this.SelectedCoAgentId,\n RecordingConsent: this.RecordingConsent\n };\n }\n\n /** Whether a click landed in a dropdown's overlay (its option panel or the backdrop that closes it). */\n private isInDropdownOverlay(target: EventTarget | null): boolean {\n return target instanceof Element && target.closest('.mj-dropdown-panel, .mj-dropdown-backdrop') != null;\n }\n\n private isDefault(agent: MJAIAgentEntityExtended): boolean {\n return !!this.DefaultAgentId && UUIDsEqual(agent.ID, this.DefaultAgentId);\n }\n\n private findAgent(id: string): MJAIAgentEntityExtended | null {\n return this.Agents.find(a => UUIDsEqual(a.ID, id)) ?? null;\n }\n}\n"]}
@@ -5,8 +5,9 @@ import { RealtimeAudioActivity } from '@memberjunction/ai-realtime-client';
5
5
  * that make the hero orb vibrate like a speaker cone and the EQ render a true spectrum.
6
6
  *
7
7
  * Raw analyser levels are jittery; rendering them directly strobes. This module applies:
8
- * - **Attack/decay envelope smoothing** ({@link SmoothLevel}) — fast attack so speech
9
- * onset feels instant, slow decay so the cone "rings down" instead of snapping shut.
8
+ * - **Attack/decay envelope smoothing** (`SmoothAudioLevel` from
9
+ * `@memberjunction/ai-realtime-client/media`, the smoothing every meter display shares) — fast
10
+ * attack so speech onset feels instant, slow decay so the cone "rings down" instead of snapping shut.
10
11
  * - **Direction resolution with hysteresis** — who is audibly speaking (`agent` / `user` /
11
12
  * `none`) with a presence floor and a hold window, so the direction color never
12
13
  * flickers across syllable gaps.
@@ -49,11 +50,15 @@ export declare const AUDIO_INPUT_NOISE_GATE = 0.045;
49
50
  /**
50
51
  * Soft-knee noise gate: at/below `gate` → 0; above it the remaining range rescales to
51
52
  * 0..1 (so the gate never visibly "clips" the bottom off real speech). Pure.
53
+ *
54
+ * @deprecated Use `GateAudioLevel` from `@memberjunction/ai-realtime-client/media`.
52
55
  */
53
56
  export declare function GateLevel(level: number, gate: number): number;
54
57
  /**
55
58
  * One smoothing step: fast attack (speech onset reads instantly), slow decay (the level
56
59
  * rings down like a speaker cone instead of snapping). Pure.
60
+ *
61
+ * @deprecated Use `SmoothAudioLevel` from `@memberjunction/ai-realtime-client/media`.
57
62
  */
58
63
  export declare function SmoothLevel(previous: number, next: number, attack?: number, decay?: number): number;
59
64
  /**
@@ -83,6 +88,7 @@ export declare class RealtimeAudioVisualSmoother {
83
88
  * an idle mic's room-noise bins must not keep the EQ dancing.
84
89
  */
85
90
  private pickRawBins;
91
+ /** Moves the bars toward the spectrum, or toward silence when there is none. */
86
92
  private smoothBins;
87
93
  /**
88
94
  * Direction rules (hysteresis):
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-audio-visuals.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-audio-visuals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAE3E;;;;;;;;;;;;;;GAcG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1D,+CAA+C;AAC/C,MAAM,WAAW,wBAAwB;IACvC,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,uDAAuD;IACvD,SAAS,EAAE,iBAAiB,CAAC;CAC9B;AAED,0EAA0E;AAC1E,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,QAAQ,CAAC;AAE1C,kGAAkG;AAClG,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C,0FAA0F;AAC1F,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,sBAAsB,QAAQ,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAY,EAAE,KAAK,GAAE,MAAa,GAAG,MAAM,CAI9G;AAED;;;;GAIG;AACH,qBAAa,2BAA2B;IACtC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,IAAI,CAA+D;IAC3E,OAAO,CAAC,SAAS,CAA6B;IAC9C,oFAAoF;IACpF,OAAO,CAAC,eAAe,CAAK;IAE5B,0DAA0D;IACnD,KAAK,IAAI,IAAI;IAQpB;;;;;OAKG;IACI,IAAI,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,wBAAwB,GAAG,IAAI;IAmB9F;;;;OAIG;IACH,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,UAAU;IASlB;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;CA4BzB"}
1
+ {"version":3,"file":"realtime-audio-visuals.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-audio-visuals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAG3E;;;;;;;;;;;;;;;GAeG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1D,+CAA+C;AAC/C,MAAM,WAAW,wBAAwB;IACvC,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,uDAAuD;IACvD,SAAS,EAAE,iBAAiB,CAAC;CAC9B;AAED,0EAA0E;AAC1E,eAAO,MAAM,sBAAsB,IAA2B,CAAC;AAE/D,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,QAAQ,CAAC;AAE1C,kGAAkG;AAClG,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C,0FAA0F;AAC1F,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,sBAAsB,QAAQ,CAAC;AAE5C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAY,EAAE,KAAK,GAAE,MAAa,GAAG,MAAM,CAE9G;AAED;;;;GAIG;AACH,qBAAa,2BAA2B;IACtC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,IAAI,CAA+D;IAC3E,OAAO,CAAC,SAAS,CAA6B;IAC9C,oFAAoF;IACpF,OAAO,CAAC,eAAe,CAAK;IAE5B,0DAA0D;IACnD,KAAK,IAAI,IAAI;IAQpB;;;;;OAKG;IACI,IAAI,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,wBAAwB,GAAG,IAAI;IAmB9F;;;;OAIG;IACH,OAAO,CAAC,WAAW;IASnB,gFAAgF;IAChF,OAAO,CAAC,UAAU;IAIlB;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;CA4BzB"}
@@ -1,5 +1,6 @@
1
+ import { GateAudioLevel, REALTIME_AUDIO_BIN_COUNT, SmoothAudioBars, SmoothAudioLevel } from '@memberjunction/ai-realtime-client/media';
1
2
  /** Number of EQ bars the hero renders (matches the meter's bin count). */
2
- export const AUDIO_VISUAL_BIN_COUNT = 9;
3
+ export const AUDIO_VISUAL_BIN_COUNT = REALTIME_AUDIO_BIN_COUNT;
3
4
  /** Levels below this are treated as silence for direction purposes. */
4
5
  export const AUDIO_PRESENCE_FLOOR = 0.045;
5
6
  /** How long a direction is HELD after its audio drops below the floor (syllable-gap proofing). */
@@ -20,21 +21,20 @@ export const AUDIO_INPUT_NOISE_GATE = 0.045;
20
21
  /**
21
22
  * Soft-knee noise gate: at/below `gate` → 0; above it the remaining range rescales to
22
23
  * 0..1 (so the gate never visibly "clips" the bottom off real speech). Pure.
24
+ *
25
+ * @deprecated Use `GateAudioLevel` from `@memberjunction/ai-realtime-client/media`.
23
26
  */
24
27
  export function GateLevel(level, gate) {
25
- if (!Number.isFinite(level) || level <= gate) {
26
- return 0;
27
- }
28
- return Math.min(1, (level - gate) / (1 - gate));
28
+ return GateAudioLevel(level, gate);
29
29
  }
30
30
  /**
31
31
  * One smoothing step: fast attack (speech onset reads instantly), slow decay (the level
32
32
  * rings down like a speaker cone instead of snapping). Pure.
33
+ *
34
+ * @deprecated Use `SmoothAudioLevel` from `@memberjunction/ai-realtime-client/media`.
33
35
  */
34
36
  export function SmoothLevel(previous, next, attack = 0.5, decay = 0.12) {
35
- const factor = next > previous ? attack : decay;
36
- const value = previous + (next - previous) * factor;
37
- return Math.min(1, Math.max(0, value));
37
+ return SmoothAudioLevel(previous, next, attack, decay);
38
38
  }
39
39
  /**
40
40
  * Per-overlay smoothing state machine. Feed it one raw {@link RealtimeAudioActivity}
@@ -67,10 +67,10 @@ export class RealtimeAudioVisualSmoother {
67
67
  return null;
68
68
  }
69
69
  // Gate BEFORE smoothing: silence is true zero, the decay still rings down smoothly.
70
- const gatedOut = GateLevel(raw.OutputLevel ?? 0, AUDIO_OUTPUT_NOISE_GATE);
71
- const gatedIn = GateLevel(raw.InputLevel ?? 0, AUDIO_INPUT_NOISE_GATE);
72
- this.outputLevel = SmoothLevel(this.outputLevel, gatedOut);
73
- this.inputLevel = SmoothLevel(this.inputLevel, gatedIn);
70
+ const gatedOut = GateAudioLevel(raw.OutputLevel ?? 0, AUDIO_OUTPUT_NOISE_GATE);
71
+ const gatedIn = GateAudioLevel(raw.InputLevel ?? 0, AUDIO_INPUT_NOISE_GATE);
72
+ this.outputLevel = SmoothAudioLevel(this.outputLevel, gatedOut);
73
+ this.inputLevel = SmoothAudioLevel(this.inputLevel, gatedIn);
74
74
  this.smoothBins(this.pickRawBins(raw, gatedOut, gatedIn));
75
75
  this.resolveDirection(nowMs);
76
76
  return {
@@ -93,13 +93,9 @@ export class RealtimeAudioVisualSmoother {
93
93
  }
94
94
  return outBins ?? inBins;
95
95
  }
96
+ /** Moves the bars toward the spectrum, or toward silence when there is none. */
96
97
  smoothBins(rawBins) {
97
- if (!rawBins) {
98
- // No spectrum available — decay the bars toward silence.
99
- this.bins = this.bins.map(b => SmoothLevel(b, 0));
100
- return;
101
- }
102
- this.bins = this.bins.map((prev, i) => SmoothLevel(prev, rawBins[i] ?? 0));
98
+ this.bins = SmoothAudioBars(this.bins, rawBins);
103
99
  }
104
100
  /**
105
101
  * Direction rules (hysteresis):
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-audio-visuals.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-audio-visuals.ts"],"names":[],"mappings":"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","sourcesContent":["import { RealtimeAudioActivity } from '@memberjunction/ai-realtime-client';\n\n/**\n * @fileoverview AUDIO-REACTIVE VISUAL SMOOTHING for the call overlay — the framework-free\n * math between raw per-frame {@link RealtimeAudioActivity} samples and the CSS variables\n * that make the hero orb vibrate like a speaker cone and the EQ render a true spectrum.\n *\n * Raw analyser levels are jittery; rendering them directly strobes. This module applies:\n * - **Attack/decay envelope smoothing** ({@link SmoothLevel}) — fast attack so speech\n * onset feels instant, slow decay so the cone \"rings down\" instead of snapping shut.\n * - **Direction resolution with hysteresis** — who is audibly speaking (`agent` / `user` /\n * `none`) with a presence floor and a hold window, so the direction color never\n * flickers across syllable gaps.\n *\n * Owned by the overlay's requestAnimationFrame loop (outside Angular); kept pure so every\n * rule unit-tests without Web Audio or a browser clock.\n */\n\n/** Who is audibly speaking right now (drives the orb/EQ direction color). */\nexport type RealtimeDirection = 'agent' | 'user' | 'none';\n\n/** One smoothed, render-ready visual frame. */\nexport interface RealtimeAudioVisualFrame {\n /** Smoothed agent-output level, 0..1. */\n OutputLevel: number;\n /** Smoothed user-mic level, 0..1. */\n InputLevel: number;\n /** Smoothed spectrum bins (length {@link AUDIO_VISUAL_BIN_COUNT}) of the dominant direction. */\n Bins: number[];\n /** Resolved speaking direction (hysteresis-stable). */\n Direction: RealtimeDirection;\n}\n\n/** Number of EQ bars the hero renders (matches the meter's bin count). */\nexport const AUDIO_VISUAL_BIN_COUNT = 9;\n\n/** Levels below this are treated as silence for direction purposes. */\nexport const AUDIO_PRESENCE_FLOOR = 0.045;\n\n/** How long a direction is HELD after its audio drops below the floor (syllable-gap proofing). */\nexport const AUDIO_DIRECTION_HOLD_MS = 280;\n\n/** The factor by which the other side must dominate to steal the direction mid-speech. */\nexport const AUDIO_DIRECTION_STEAL_FACTOR = 1.15;\n\n/**\n * NOISE GATES (per direction): raw analyser levels at/below the gate render as TRUE\n * silence — without this, an idle microphone's room-noise/auto-gain floor keeps the EQ\n * dancing and the direction stuck on \"user\" while nobody is speaking. The mic gate sits\n * a touch above the output gate (playback silence is actual zero; mic silence isn't), but\n * NOT so high it swallows normal speech: 0.08 over-gated — typical Mac-mic normalized speech\n * peaks well under it, so the meter read silence the whole time the user was talking. 0.045\n * (≈ the presence floor) suppresses idle room-noise while letting real speech drive the EQ.\n */\nexport const AUDIO_OUTPUT_NOISE_GATE = 0.03;\nexport const AUDIO_INPUT_NOISE_GATE = 0.045;\n\n/**\n * Soft-knee noise gate: at/below `gate` → 0; above it the remaining range rescales to\n * 0..1 (so the gate never visibly \"clips\" the bottom off real speech). Pure.\n */\nexport function GateLevel(level: number, gate: number): number {\n if (!Number.isFinite(level) || level <= gate) {\n return 0;\n }\n return Math.min(1, (level - gate) / (1 - gate));\n}\n\n/**\n * One smoothing step: fast attack (speech onset reads instantly), slow decay (the level\n * rings down like a speaker cone instead of snapping). Pure.\n */\nexport function SmoothLevel(previous: number, next: number, attack: number = 0.5, decay: number = 0.12): number {\n const factor = next > previous ? attack : decay;\n const value = previous + (next - previous) * factor;\n return Math.min(1, Math.max(0, value));\n}\n\n/**\n * Per-overlay smoothing state machine. Feed it one raw {@link RealtimeAudioActivity}\n * sample per animation frame via {@link Next}; render the returned frame. `null` in →\n * `null` out (the driver attached no meters — the host keeps turn-state visuals).\n */\nexport class RealtimeAudioVisualSmoother {\n private outputLevel = 0;\n private inputLevel = 0;\n private bins: number[] = new Array<number>(AUDIO_VISUAL_BIN_COUNT).fill(0);\n private direction: RealtimeDirection = 'none';\n /** Last time (ms) the current direction's level was at/above the presence floor. */\n private directionHeldAt = 0;\n\n /** Resets all smoothing state (call between sessions). */\n public Reset(): void {\n this.outputLevel = 0;\n this.inputLevel = 0;\n this.bins = new Array<number>(AUDIO_VISUAL_BIN_COUNT).fill(0);\n this.direction = 'none';\n this.directionHeldAt = 0;\n }\n\n /**\n * Advances the smoother with one raw sample.\n * @param raw The client's current audio activity (`null` = no metering capability).\n * @param nowMs A monotonic clock reading (e.g. `performance.now()`).\n * @returns The render-ready frame, or `null` when un-metered.\n */\n public Next(raw: RealtimeAudioActivity | null, nowMs: number): RealtimeAudioVisualFrame | null {\n if (!raw) {\n return null;\n }\n // Gate BEFORE smoothing: silence is true zero, the decay still rings down smoothly.\n const gatedOut = GateLevel(raw.OutputLevel ?? 0, AUDIO_OUTPUT_NOISE_GATE);\n const gatedIn = GateLevel(raw.InputLevel ?? 0, AUDIO_INPUT_NOISE_GATE);\n this.outputLevel = SmoothLevel(this.outputLevel, gatedOut);\n this.inputLevel = SmoothLevel(this.inputLevel, gatedIn);\n this.smoothBins(this.pickRawBins(raw, gatedOut, gatedIn));\n this.resolveDirection(nowMs);\n return {\n OutputLevel: this.outputLevel,\n InputLevel: this.inputLevel,\n Bins: [...this.bins],\n Direction: this.direction\n };\n }\n\n /**\n * The spectrum follows whichever direction is louder (falling back to whichever\n * exists) — but a side whose GATED level is silence contributes no spectrum at all:\n * an idle mic's room-noise bins must not keep the EQ dancing.\n */\n private pickRawBins(raw: RealtimeAudioActivity, gatedOut: number, gatedIn: number): number[] | null {\n const outBins = gatedOut > 0 ? raw.OutputBins : null;\n const inBins = gatedIn > 0 ? raw.InputBins : null;\n if (outBins && inBins) {\n return this.outputLevel >= this.inputLevel ? outBins : inBins;\n }\n return outBins ?? inBins;\n }\n\n private smoothBins(rawBins: number[] | null): void {\n if (!rawBins) {\n // No spectrum available — decay the bars toward silence.\n this.bins = this.bins.map(b => SmoothLevel(b, 0));\n return;\n }\n this.bins = this.bins.map((prev, i) => SmoothLevel(prev, rawBins[i] ?? 0));\n }\n\n /**\n * Direction rules (hysteresis):\n * - silence adopts nothing; speech from silence adopts the louder side immediately;\n * - a live direction RENEWS its hold while at/above the presence floor;\n * - the other side steals the direction only by dominating ({@link AUDIO_DIRECTION_STEAL_FACTOR});\n * - a direction releases to `none` only after {@link AUDIO_DIRECTION_HOLD_MS} of silence —\n * syllable gaps never flicker the color.\n */\n private resolveDirection(nowMs: number): void {\n const out = this.outputLevel;\n const inp = this.inputLevel;\n const audible = out >= AUDIO_PRESENCE_FLOOR || inp >= AUDIO_PRESENCE_FLOOR;\n const louder: RealtimeDirection = out >= inp ? 'agent' : 'user';\n\n if (this.direction === 'none') {\n if (audible) {\n this.direction = louder;\n this.directionHeldAt = nowMs;\n }\n return;\n }\n\n const currentLevel = this.direction === 'agent' ? out : inp;\n const otherLevel = this.direction === 'agent' ? inp : out;\n if (currentLevel >= AUDIO_PRESENCE_FLOOR) {\n this.directionHeldAt = nowMs;\n }\n if (otherLevel >= AUDIO_PRESENCE_FLOOR && otherLevel >= currentLevel * AUDIO_DIRECTION_STEAL_FACTOR) {\n this.direction = this.direction === 'agent' ? 'user' : 'agent';\n this.directionHeldAt = nowMs;\n return;\n }\n if (!audible && nowMs - this.directionHeldAt > AUDIO_DIRECTION_HOLD_MS) {\n this.direction = 'none';\n }\n }\n}\n"]}
1
+ {"version":3,"file":"realtime-audio-visuals.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-audio-visuals.ts"],"names":[],"mappings":"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","sourcesContent":["import { RealtimeAudioActivity } from '@memberjunction/ai-realtime-client';\nimport { GateAudioLevel, REALTIME_AUDIO_BIN_COUNT, SmoothAudioBars, SmoothAudioLevel } from '@memberjunction/ai-realtime-client/media';\n\n/**\n * @fileoverview AUDIO-REACTIVE VISUAL SMOOTHING for the call overlay — the framework-free\n * math between raw per-frame {@link RealtimeAudioActivity} samples and the CSS variables\n * that make the hero orb vibrate like a speaker cone and the EQ render a true spectrum.\n *\n * Raw analyser levels are jittery; rendering them directly strobes. This module applies:\n * - **Attack/decay envelope smoothing** (`SmoothAudioLevel` from\n * `@memberjunction/ai-realtime-client/media`, the smoothing every meter display shares) — fast\n * attack so speech onset feels instant, slow decay so the cone \"rings down\" instead of snapping shut.\n * - **Direction resolution with hysteresis** — who is audibly speaking (`agent` / `user` /\n * `none`) with a presence floor and a hold window, so the direction color never\n * flickers across syllable gaps.\n *\n * Owned by the overlay's requestAnimationFrame loop (outside Angular); kept pure so every\n * rule unit-tests without Web Audio or a browser clock.\n */\n\n/** Who is audibly speaking right now (drives the orb/EQ direction color). */\nexport type RealtimeDirection = 'agent' | 'user' | 'none';\n\n/** One smoothed, render-ready visual frame. */\nexport interface RealtimeAudioVisualFrame {\n /** Smoothed agent-output level, 0..1. */\n OutputLevel: number;\n /** Smoothed user-mic level, 0..1. */\n InputLevel: number;\n /** Smoothed spectrum bins (length {@link AUDIO_VISUAL_BIN_COUNT}) of the dominant direction. */\n Bins: number[];\n /** Resolved speaking direction (hysteresis-stable). */\n Direction: RealtimeDirection;\n}\n\n/** Number of EQ bars the hero renders (matches the meter's bin count). */\nexport const AUDIO_VISUAL_BIN_COUNT = REALTIME_AUDIO_BIN_COUNT;\n\n/** Levels below this are treated as silence for direction purposes. */\nexport const AUDIO_PRESENCE_FLOOR = 0.045;\n\n/** How long a direction is HELD after its audio drops below the floor (syllable-gap proofing). */\nexport const AUDIO_DIRECTION_HOLD_MS = 280;\n\n/** The factor by which the other side must dominate to steal the direction mid-speech. */\nexport const AUDIO_DIRECTION_STEAL_FACTOR = 1.15;\n\n/**\n * NOISE GATES (per direction): raw analyser levels at/below the gate render as TRUE\n * silence — without this, an idle microphone's room-noise/auto-gain floor keeps the EQ\n * dancing and the direction stuck on \"user\" while nobody is speaking. The mic gate sits\n * a touch above the output gate (playback silence is actual zero; mic silence isn't), but\n * NOT so high it swallows normal speech: 0.08 over-gated — typical Mac-mic normalized speech\n * peaks well under it, so the meter read silence the whole time the user was talking. 0.045\n * (≈ the presence floor) suppresses idle room-noise while letting real speech drive the EQ.\n */\nexport const AUDIO_OUTPUT_NOISE_GATE = 0.03;\nexport const AUDIO_INPUT_NOISE_GATE = 0.045;\n\n/**\n * Soft-knee noise gate: at/below `gate` → 0; above it the remaining range rescales to\n * 0..1 (so the gate never visibly \"clips\" the bottom off real speech). Pure.\n *\n * @deprecated Use `GateAudioLevel` from `@memberjunction/ai-realtime-client/media`.\n */\nexport function GateLevel(level: number, gate: number): number {\n return GateAudioLevel(level, gate);\n}\n\n/**\n * One smoothing step: fast attack (speech onset reads instantly), slow decay (the level\n * rings down like a speaker cone instead of snapping). Pure.\n *\n * @deprecated Use `SmoothAudioLevel` from `@memberjunction/ai-realtime-client/media`.\n */\nexport function SmoothLevel(previous: number, next: number, attack: number = 0.5, decay: number = 0.12): number {\n return SmoothAudioLevel(previous, next, attack, decay);\n}\n\n/**\n * Per-overlay smoothing state machine. Feed it one raw {@link RealtimeAudioActivity}\n * sample per animation frame via {@link Next}; render the returned frame. `null` in →\n * `null` out (the driver attached no meters — the host keeps turn-state visuals).\n */\nexport class RealtimeAudioVisualSmoother {\n private outputLevel = 0;\n private inputLevel = 0;\n private bins: number[] = new Array<number>(AUDIO_VISUAL_BIN_COUNT).fill(0);\n private direction: RealtimeDirection = 'none';\n /** Last time (ms) the current direction's level was at/above the presence floor. */\n private directionHeldAt = 0;\n\n /** Resets all smoothing state (call between sessions). */\n public Reset(): void {\n this.outputLevel = 0;\n this.inputLevel = 0;\n this.bins = new Array<number>(AUDIO_VISUAL_BIN_COUNT).fill(0);\n this.direction = 'none';\n this.directionHeldAt = 0;\n }\n\n /**\n * Advances the smoother with one raw sample.\n * @param raw The client's current audio activity (`null` = no metering capability).\n * @param nowMs A monotonic clock reading (e.g. `performance.now()`).\n * @returns The render-ready frame, or `null` when un-metered.\n */\n public Next(raw: RealtimeAudioActivity | null, nowMs: number): RealtimeAudioVisualFrame | null {\n if (!raw) {\n return null;\n }\n // Gate BEFORE smoothing: silence is true zero, the decay still rings down smoothly.\n const gatedOut = GateAudioLevel(raw.OutputLevel ?? 0, AUDIO_OUTPUT_NOISE_GATE);\n const gatedIn = GateAudioLevel(raw.InputLevel ?? 0, AUDIO_INPUT_NOISE_GATE);\n this.outputLevel = SmoothAudioLevel(this.outputLevel, gatedOut);\n this.inputLevel = SmoothAudioLevel(this.inputLevel, gatedIn);\n this.smoothBins(this.pickRawBins(raw, gatedOut, gatedIn));\n this.resolveDirection(nowMs);\n return {\n OutputLevel: this.outputLevel,\n InputLevel: this.inputLevel,\n Bins: [...this.bins],\n Direction: this.direction\n };\n }\n\n /**\n * The spectrum follows whichever direction is louder (falling back to whichever\n * exists) — but a side whose GATED level is silence contributes no spectrum at all:\n * an idle mic's room-noise bins must not keep the EQ dancing.\n */\n private pickRawBins(raw: RealtimeAudioActivity, gatedOut: number, gatedIn: number): number[] | null {\n const outBins = gatedOut > 0 ? raw.OutputBins : null;\n const inBins = gatedIn > 0 ? raw.InputBins : null;\n if (outBins && inBins) {\n return this.outputLevel >= this.inputLevel ? outBins : inBins;\n }\n return outBins ?? inBins;\n }\n\n /** Moves the bars toward the spectrum, or toward silence when there is none. */\n private smoothBins(rawBins: number[] | null): void {\n this.bins = SmoothAudioBars(this.bins, rawBins);\n }\n\n /**\n * Direction rules (hysteresis):\n * - silence adopts nothing; speech from silence adopts the louder side immediately;\n * - a live direction RENEWS its hold while at/above the presence floor;\n * - the other side steals the direction only by dominating ({@link AUDIO_DIRECTION_STEAL_FACTOR});\n * - a direction releases to `none` only after {@link AUDIO_DIRECTION_HOLD_MS} of silence —\n * syllable gaps never flicker the color.\n */\n private resolveDirection(nowMs: number): void {\n const out = this.outputLevel;\n const inp = this.inputLevel;\n const audible = out >= AUDIO_PRESENCE_FLOOR || inp >= AUDIO_PRESENCE_FLOOR;\n const louder: RealtimeDirection = out >= inp ? 'agent' : 'user';\n\n if (this.direction === 'none') {\n if (audible) {\n this.direction = louder;\n this.directionHeldAt = nowMs;\n }\n return;\n }\n\n const currentLevel = this.direction === 'agent' ? out : inp;\n const otherLevel = this.direction === 'agent' ? inp : out;\n if (currentLevel >= AUDIO_PRESENCE_FLOOR) {\n this.directionHeldAt = nowMs;\n }\n if (otherLevel >= AUDIO_PRESENCE_FLOOR && otherLevel >= currentLevel * AUDIO_DIRECTION_STEAL_FACTOR) {\n this.direction = this.direction === 'agent' ? 'user' : 'agent';\n this.directionHeldAt = nowMs;\n return;\n }\n if (!audible && nowMs - this.directionHeldAt > AUDIO_DIRECTION_HOLD_MS) {\n this.direction = 'none';\n }\n }\n}\n"]}
@@ -1,4 +1,6 @@
1
1
  import { EventEmitter } from '@angular/core';
2
+ import { type MediaSharePanel, type MediaShareRequest } from '@memberjunction/ng-realtime-media';
3
+ import type { MediaDevice, MediaDeviceSelection } from '@memberjunction/ai-realtime-client/media';
2
4
  import * as i0 from "@angular/core";
3
5
  /**
4
6
  * The call overlay's BOTTOM DOCK — the progressive-disclosure composer
@@ -11,11 +13,17 @@ import * as i0 from "@angular/core";
11
13
  * Activity/Whiteboard panels on demand), the Type control, and End call. There's no visible
12
14
  * composer yet — the Type control opens it, and so does simply starting to type (the overlay
13
15
  * captures the first printable keystroke and seeds it via {@link AppendAndFocus}).
14
- * - **Level 2+ (the dock)** — mute/captions shrink to compact minis and the in-call text
16
+ * - **Level 2+ (the dock)** — mute/captions shrink to small circles and the in-call text
15
17
  * input docks beside them (one bottom bar, per Redesign A's fused composer+controls).
16
18
  * Submit calls {@link RealtimeSessionService.SendText}, which injects the text as a user
17
19
  * turn into the SAME live voice call.
18
20
  *
21
+ * The controls are the design system's: the microphone, the camera and Share are `mj-media-controls` (the call controls
22
+ * the LiveKit room uses too) and every other control an `mjButton` circle, sized per shape (52, 44 or 32 px). The camera
23
+ * and Share show only when the overlay says the call offers them; the camera is optional here, so it is neutral while off.
24
+ * In the strip and the lean dock the microphone carries the device chevron, whose menu picks the microphone and, while the
25
+ * camera is open, the camera ({@link Devices}); the fused dock, short of room, leaves it out, as it does the Share arrow.
26
+ *
19
27
  * Mute talks to the session service directly (pure local toggle); captions / Details /
20
28
  * End are emitted up so the overlay shell owns that state and lifecycle.
21
29
  */
@@ -52,6 +60,36 @@ export declare class RealtimeComposerComponent {
52
60
  MuteChanged: EventEmitter<boolean>;
53
61
  /** Current draft text in the dock's composer input. */
54
62
  Draft: string;
63
+ /** Show the camera button: the call offers the camera (the runtime's `CaptureOffers$`). */
64
+ ShowCamera: boolean;
65
+ /** Show the Share button: the call offers a screen share. */
66
+ ShowShare: boolean;
67
+ /** Whether the camera is on (or starting). */
68
+ CameraOn: boolean;
69
+ /** Whether the user is sharing (or choosing what to share). */
70
+ Sharing: boolean;
71
+ /**
72
+ * The panels of the page the Share menu offers under "This panel" (the overlay's on-screen panels). The typed-input
73
+ * dock, whose Share button has no menu, leaves them out.
74
+ */
75
+ SharePanels: readonly MediaSharePanel[];
76
+ /**
77
+ * The microphones and cameras the device menu offers: the call's microphones, and its cameras while the camera is
78
+ * open. With none there is no device chevron. The typed-input dock leaves the chevron out.
79
+ */
80
+ Devices: readonly MediaDevice[];
81
+ /** The microphone the device menu shows as picked. */
82
+ SelectedMicrophoneID: string | null;
83
+ /** The camera the device menu shows as picked. */
84
+ SelectedCameraID: string | null;
85
+ /** The user asked to turn the camera on (`true`) or off (`false`). The overlay starts or stops it. */
86
+ CameraToggled: EventEmitter<boolean>;
87
+ /** The user asked to share a screen, window or tab, or one of {@link SharePanels}. */
88
+ ShareRequested: EventEmitter<MediaShareRequest>;
89
+ /** The user asked to stop sharing. */
90
+ StopShareRequested: EventEmitter<void>;
91
+ /** The user picked a microphone or a camera in the device menu. The overlay switches to it. */
92
+ DeviceSelected: EventEmitter<MediaDeviceSelection>;
55
93
  /**
56
94
  * The mic mute state. A two-way reflection: the overlay may push it down (e.g. its
57
95
  * `SetMuted()` / focus-pill toggle) so all mute affordances stay in sync, and this
@@ -60,6 +98,8 @@ export declare class RealtimeComposerComponent {
60
98
  IsMuted: boolean;
61
99
  private dockInput?;
62
100
  private realtime;
101
+ /** The captions control's tooltip: what a click does. */
102
+ get CaptionsTitle(): string;
63
103
  /** True when there's non-whitespace text to send. */
64
104
  get CanSend(): boolean;
65
105
  /** True while the big-controls phone-call strip renders (instead of the dock). */
@@ -96,6 +136,6 @@ export declare class RealtimeComposerComponent {
96
136
  /** Enter sends (Shift+Enter inserts a newline in textarea). */
97
137
  OnKeydown(event: KeyboardEvent): void;
98
138
  static ɵfac: i0.ɵɵFactoryDeclaration<RealtimeComposerComponent, never>;
99
- static ɵcmp: i0.ɵɵComponentDeclaration<RealtimeComposerComponent, "mj-realtime-composer", never, { "Open": { "alias": "Open"; "required": false; }; "Compact": { "alias": "Compact"; "required": false; }; "CaptionsOn": { "alias": "CaptionsOn"; "required": false; }; "ShowDetails": { "alias": "ShowDetails"; "required": false; }; "DetailsOn": { "alias": "DetailsOn"; "required": false; }; "IsMuted": { "alias": "IsMuted"; "required": false; }; }, { "OpenChanged": "OpenChanged"; "CaptionsToggled": "CaptionsToggled"; "DetailsToggled": "DetailsToggled"; "EndRequested": "EndRequested"; "MuteChanged": "MuteChanged"; }, never, never, true, never>;
139
+ static ɵcmp: i0.ɵɵComponentDeclaration<RealtimeComposerComponent, "mj-realtime-composer", never, { "Open": { "alias": "Open"; "required": false; }; "Compact": { "alias": "Compact"; "required": false; }; "CaptionsOn": { "alias": "CaptionsOn"; "required": false; }; "ShowDetails": { "alias": "ShowDetails"; "required": false; }; "DetailsOn": { "alias": "DetailsOn"; "required": false; }; "ShowCamera": { "alias": "ShowCamera"; "required": false; }; "ShowShare": { "alias": "ShowShare"; "required": false; }; "CameraOn": { "alias": "CameraOn"; "required": false; }; "Sharing": { "alias": "Sharing"; "required": false; }; "SharePanels": { "alias": "SharePanels"; "required": false; }; "Devices": { "alias": "Devices"; "required": false; }; "SelectedMicrophoneID": { "alias": "SelectedMicrophoneID"; "required": false; }; "SelectedCameraID": { "alias": "SelectedCameraID"; "required": false; }; "IsMuted": { "alias": "IsMuted"; "required": false; }; }, { "OpenChanged": "OpenChanged"; "CaptionsToggled": "CaptionsToggled"; "DetailsToggled": "DetailsToggled"; "EndRequested": "EndRequested"; "MuteChanged": "MuteChanged"; "CameraToggled": "CameraToggled"; "ShareRequested": "ShareRequested"; "StopShareRequested": "StopShareRequested"; "DeviceSelected": "DeviceSelected"; }, never, never, true, never>;
100
140
  }
101
141
  //# sourceMappingURL=realtime-composer.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-composer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-composer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,YAAY,EAAkD,MAAM,eAAe,CAAC;;AAKpH;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAOa,yBAAyB;IACpC;;;;OAIG;IACM,IAAI,UAAS;IAEtB;;;;;;OAMG;IACM,OAAO,UAAS;IAEzB,6FAA6F;IACnF,WAAW,wBAA+B;IAEpD,yFAAyF;IAChF,UAAU,UAAQ;IAE3B,yFAAyF;IAChF,WAAW,UAAS;IAE7B,gFAAgF;IACvE,SAAS,UAAS;IAE3B,mFAAmF;IACzE,eAAe,wBAA+B;IAExD,oFAAoF;IAC1E,cAAc,qBAA4B;IAEpD,wEAAwE;IAC9D,YAAY,qBAA4B;IAElD,wFAAwF;IAC9E,WAAW,wBAA+B;IAEpD,uDAAuD;IAChD,KAAK,SAAM;IAElB;;;;OAIG;IACM,OAAO,UAAS;IAED,OAAO,CAAC,SAAS,CAAC,CAAqD;IAE/F,OAAO,CAAC,QAAQ,CAAkC;IAElD,qDAAqD;IACrD,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED,kFAAkF;IAClF,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;;OAGG;IACI,QAAQ,UAAS;IAExB,qGAAqG;IAC9F,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAK1C,2DAA2D;IAEpD,eAAe,IAAI,IAAI;IAM9B,iFAAiF;IAC1E,UAAU,IAAI,IAAI;IAKzB,yDAAyD;IAClD,cAAc,IAAI,IAAI;IAK7B,6EAA6E;IACtE,UAAU,IAAI,IAAI;IAIzB;;;;;;;;OAQG;IACI,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAWzC,+EAA+E;IACxE,UAAU,IAAI,IAAI;IASzB,uEAAuE;IAChE,IAAI,IAAI,IAAI;IAYnB,+DAA+D;IACxD,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;yCAlJjC,yBAAyB;2CAAzB,yBAAyB;CAwJrC"}
1
+ {"version":3,"file":"realtime-composer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-composer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,YAAY,EAAkD,MAAM,eAAe,CAAC;AAIpH,OAAO,EAA0B,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACzH,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;;AAGlG;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAOa,yBAAyB;IACpC;;;;OAIG;IACM,IAAI,UAAS;IAEtB;;;;;;OAMG;IACM,OAAO,UAAS;IAEzB,6FAA6F;IACnF,WAAW,wBAA+B;IAEpD,yFAAyF;IAChF,UAAU,UAAQ;IAE3B,yFAAyF;IAChF,WAAW,UAAS;IAE7B,gFAAgF;IACvE,SAAS,UAAS;IAE3B,mFAAmF;IACzE,eAAe,wBAA+B;IAExD,oFAAoF;IAC1E,cAAc,qBAA4B;IAEpD,wEAAwE;IAC9D,YAAY,qBAA4B;IAElD,wFAAwF;IAC9E,WAAW,wBAA+B;IAEpD,uDAAuD;IAChD,KAAK,SAAM;IAElB,2FAA2F;IAClF,UAAU,UAAS;IAE5B,6DAA6D;IACpD,SAAS,UAAS;IAE3B,8CAA8C;IACrC,QAAQ,UAAS;IAE1B,+DAA+D;IACtD,OAAO,UAAS;IAEzB;;;OAGG;IACM,WAAW,EAAE,SAAS,eAAe,EAAE,CAAM;IAEtD;;;OAGG;IACM,OAAO,EAAE,SAAS,WAAW,EAAE,CAAM;IAE9C,sDAAsD;IAC7C,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEpD,kDAAkD;IACzC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEhD,sGAAsG;IAC5F,aAAa,wBAA+B;IAEtD,sFAAsF;IAC5E,cAAc,kCAAyC;IAEjE,sCAAsC;IAC5B,kBAAkB,qBAA4B;IAExD,+FAA+F;IACrF,cAAc,qCAA4C;IAEpE;;;;OAIG;IACM,OAAO,UAAS;IAED,OAAO,CAAC,SAAS,CAAC,CAAqD;IAE/F,OAAO,CAAC,QAAQ,CAAkC;IAElD,yDAAyD;IACzD,IAAW,aAAa,IAAI,MAAM,CAEjC;IAED,qDAAqD;IACrD,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED,kFAAkF;IAClF,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;;OAGG;IACI,QAAQ,UAAS;IAExB,qGAAqG;IAC9F,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAK1C,2DAA2D;IAEpD,eAAe,IAAI,IAAI;IAM9B,iFAAiF;IAC1E,UAAU,IAAI,IAAI;IAKzB,yDAAyD;IAClD,cAAc,IAAI,IAAI;IAK7B,6EAA6E;IACtE,UAAU,IAAI,IAAI;IAIzB;;;;;;;;OAQG;IACI,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAWzC,+EAA+E;IACxE,UAAU,IAAI,IAAI;IASzB,uEAAuE;IAChE,IAAI,IAAI,IAAI;IAYnB,+DAA+D;IACxD,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;yCAjMjC,yBAAyB;2CAAzB,yBAAyB;CAuMrC"}