@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,5 +1,6 @@
1
1
  import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, Input, Output, ViewChild, inject, } from '@angular/core';
2
- import { MJButtonDirective } from '@memberjunction/ng-ui-components';
2
+ import { FormsModule } from '@angular/forms';
3
+ import { MJButtonDirective, MJDropdownComponent } from '@memberjunction/ng-ui-components';
3
4
  import { UUIDsEqual } from '@memberjunction/global';
4
5
  import { AIEngineBase } from '@memberjunction/ai-engine-base';
5
6
  import { UserInfoEngine } from '@memberjunction/core-entities';
@@ -8,6 +9,7 @@ import { REALTIME_ADVANCED_SESSION_CONTROLS, UserHoldsAuthorization } from '../.
8
9
  import { BuildRealtimeModelOptions, ConstrainTargetsToPairings, DefaultPairedTargetId, LoadCoAgentPairings, } from '../../services/realtime-pairing';
9
10
  import { GraphQLLiveKitClient } from '@memberjunction/graphql-dataprovider';
10
11
  import * as i0 from "@angular/core";
12
+ import * as i1 from "@angular/forms";
11
13
  const _c0 = ["searchInput"];
12
14
  const _forTrack0 = ($index, $item) => $item.ID;
13
15
  function RealtimeAgentPickerComponent_Conditional_5_For_10_Template(rf, ctx) { if (rf & 1) {
@@ -93,36 +95,75 @@ function RealtimeAgentPickerComponent_Conditional_13_For_10_Template(rf, ctx) {
93
95
  i0.ɵɵadvance();
94
96
  i0.ɵɵtextInterpolate(model_r11.Name);
95
97
  } }
96
- function RealtimeAgentPickerComponent_Conditional_13_Conditional_11_For_10_Template(rf, ctx) { if (rf & 1) {
97
- i0.ɵɵelementStart(0, "option", 27);
98
- i0.ɵɵtext(1);
98
+ function RealtimeAgentPickerComponent_Conditional_13_Conditional_11_ng_template_6_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
99
+ const _r13 = i0.ɵɵgetCurrentView();
100
+ i0.ɵɵelementStart(0, "img", 46);
101
+ i0.ɵɵlistener("error", function RealtimeAgentPickerComponent_Conditional_13_Conditional_11_ng_template_6_Conditional_0_Conditional_1_Template_img_error_0_listener() { const image_r14 = i0.ɵɵrestoreView(_r13); const ctx_r3 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r3.OnPreviewImageError(image_r14)); });
99
102
  i0.ɵɵelementEnd();
100
103
  } if (rf & 2) {
101
- const v_r14 = ctx.$implicit;
102
- i0.ɵɵproperty("value", v_r14.ID);
104
+ i0.ɵɵproperty("src", ctx, i0.ɵɵsanitizeUrl);
105
+ } }
106
+ function RealtimeAgentPickerComponent_Conditional_13_Conditional_11_ng_template_6_Conditional_0_Conditional_4_Template(rf, ctx) { if (rf & 1) {
107
+ i0.ɵɵelementStart(0, "span", 45);
108
+ i0.ɵɵelement(1, "i", 47);
109
+ i0.ɵɵelementStart(2, "span", 48);
110
+ i0.ɵɵtext(3, "Comes with an avatar");
111
+ i0.ɵɵelementEnd()();
112
+ } }
113
+ function RealtimeAgentPickerComponent_Conditional_13_Conditional_11_ng_template_6_Conditional_0_Template(rf, ctx) { if (rf & 1) {
114
+ i0.ɵɵelementStart(0, "span", 42);
115
+ i0.ɵɵconditionalCreate(1, RealtimeAgentPickerComponent_Conditional_13_Conditional_11_ng_template_6_Conditional_0_Conditional_1_Template, 1, 1, "img", 43);
116
+ i0.ɵɵelementStart(2, "span", 44);
117
+ i0.ɵɵtext(3);
118
+ i0.ɵɵelementEnd();
119
+ i0.ɵɵconditionalCreate(4, RealtimeAgentPickerComponent_Conditional_13_Conditional_11_ng_template_6_Conditional_0_Conditional_4_Template, 4, 0, "span", 45);
120
+ i0.ɵɵelementEnd();
121
+ } if (rf & 2) {
122
+ let tmp_9_0;
123
+ const voice_r15 = ctx;
124
+ const ctx_r3 = i0.ɵɵnextContext(4);
125
+ i0.ɵɵadvance();
126
+ i0.ɵɵconditional((tmp_9_0 = ctx_r3.PreviewImageFor(voice_r15)) ? 1 : -1, tmp_9_0);
127
+ i0.ɵɵadvance(2);
128
+ i0.ɵɵtextInterpolate(voice_r15.Name);
103
129
  i0.ɵɵadvance();
104
- i0.ɵɵtextInterpolate(v_r14.Name);
130
+ i0.ɵɵconditional(voice_r15.AvatarID ? 4 : -1);
131
+ } }
132
+ function RealtimeAgentPickerComponent_Conditional_13_Conditional_11_ng_template_6_Template(rf, ctx) { if (rf & 1) {
133
+ i0.ɵɵconditionalCreate(0, RealtimeAgentPickerComponent_Conditional_13_Conditional_11_ng_template_6_Conditional_0_Template, 5, 3, "span", 42);
134
+ } if (rf & 2) {
135
+ let tmp_7_0;
136
+ const item_r16 = ctx.$implicit;
137
+ const ctx_r3 = i0.ɵɵnextContext(3);
138
+ i0.ɵɵconditional((tmp_7_0 = ctx_r3.VoiceOptionFor(item_r16)) ? 0 : -1, tmp_7_0);
139
+ } }
140
+ function RealtimeAgentPickerComponent_Conditional_13_Conditional_11_Conditional_9_Template(rf, ctx) { if (rf & 1) {
141
+ i0.ɵɵelementStart(0, "span", 41);
142
+ i0.ɵɵelement(1, "i", 47);
143
+ i0.ɵɵelementStart(2, "span");
144
+ i0.ɵɵtext(3, "Comes with an avatar");
145
+ i0.ɵɵelementEnd()();
105
146
  } }
106
147
  function RealtimeAgentPickerComponent_Conditional_13_Conditional_11_Template(rf, ctx) { if (rf & 1) {
107
148
  const _r12 = i0.ɵɵgetCurrentView();
108
- i0.ɵɵelementStart(0, "div", 32)(1, "label", 36);
109
- i0.ɵɵelement(2, "i", 37);
149
+ i0.ɵɵelementStart(0, "div", 36)(1, "span", 37);
150
+ i0.ɵɵelement(2, "i", 38);
110
151
  i0.ɵɵelementStart(3, "span");
111
152
  i0.ɵɵtext(4, "Voice");
112
153
  i0.ɵɵelementEnd()();
113
- i0.ɵɵelementStart(5, "select", 38, 3);
114
- i0.ɵɵlistener("change", function RealtimeAgentPickerComponent_Conditional_13_Conditional_11_Template_select_change_5_listener() { i0.ɵɵrestoreView(_r12); const voiceSelect_r13 = i0.ɵɵreference(6); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnVoiceChange(voiceSelect_r13.value)); });
115
- i0.ɵɵelementStart(7, "option", 26);
116
- i0.ɵɵtext(8, "Default");
154
+ i0.ɵɵelementStart(5, "mj-dropdown", 39);
155
+ i0.ɵɵlistener("ValueChange", function RealtimeAgentPickerComponent_Conditional_13_Conditional_11_Template_mj_dropdown_ValueChange_5_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnVoiceChange($event)); });
156
+ i0.ɵɵtemplate(6, RealtimeAgentPickerComponent_Conditional_13_Conditional_11_ng_template_6_Template, 1, 1, "ng-template", null, 3, i0.ɵɵtemplateRefExtractor);
117
157
  i0.ɵɵelementEnd();
118
- i0.ɵɵrepeaterCreate(9, RealtimeAgentPickerComponent_Conditional_13_Conditional_11_For_10_Template, 2, 2, "option", 27, _forTrack0);
158
+ i0.ɵɵelementStart(8, "div", 40);
159
+ i0.ɵɵconditionalCreate(9, RealtimeAgentPickerComponent_Conditional_13_Conditional_11_Conditional_9_Template, 4, 0, "span", 41);
119
160
  i0.ɵɵelementEnd()();
120
161
  } if (rf & 2) {
121
162
  const ctx_r3 = i0.ɵɵnextContext(2);
122
163
  i0.ɵɵadvance(5);
123
- i0.ɵɵproperty("value", ctx_r3.SelectedVoiceId ?? "");
164
+ i0.ɵɵproperty("Data", ctx_r3.SelectedModelVoices)("ngModel", ctx_r3.SelectedVoice);
124
165
  i0.ɵɵadvance(4);
125
- i0.ɵɵrepeater(ctx_r3.SelectedModelVoices);
166
+ i0.ɵɵconditional(ctx_r3.SelectedVoiceHasAvatar ? 9 : -1);
126
167
  } }
127
168
  function RealtimeAgentPickerComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
128
169
  const _r9 = i0.ɵɵgetCurrentView();
@@ -138,7 +179,7 @@ function RealtimeAgentPickerComponent_Conditional_13_Template(rf, ctx) { if (rf
138
179
  i0.ɵɵelementEnd();
139
180
  i0.ɵɵrepeaterCreate(9, RealtimeAgentPickerComponent_Conditional_13_For_10_Template, 2, 2, "option", 27, _forTrack0);
140
181
  i0.ɵɵelementEnd()();
141
- i0.ɵɵconditionalCreate(11, RealtimeAgentPickerComponent_Conditional_13_Conditional_11_Template, 11, 1, "div", 32);
182
+ i0.ɵɵconditionalCreate(11, RealtimeAgentPickerComponent_Conditional_13_Conditional_11_Template, 10, 3, "div", 36);
142
183
  } if (rf & 2) {
143
184
  const ctx_r3 = i0.ɵɵnextContext();
144
185
  i0.ɵɵadvance(5);
@@ -166,9 +207,12 @@ const RECORDING_CONSENT_KEY = 'mj.realtimeVoice.recordingConsent.v1';
166
207
  * candidates (filtered from that same set), and the defaults to preselect;
167
208
  * the picker emits the user's choice. The data it loads itself:
168
209
  * - the compact "Voice model" option list (active Realtime models via a
169
- * narrow RunView) — loaded and rendered ONLY when the current user holds
170
- * the `Realtime: Advanced Session Controls` authorization (pure UX
171
- * disclosure; the server enforces the authorization on the mint), and
210
+ * narrow RunView) and each model's voices — loaded and rendered ONLY when
211
+ * the current user holds the `Realtime: Advanced Session Controls`
212
+ * authorization (pure UX disclosure; the server enforces the authorization
213
+ * on the mint). The voice list marks the voices whose persona comes with an
214
+ * avatar (a camera icon) and shows a persona's preview image when it has
215
+ * one; picking such a voice also picks its avatar, and
172
216
  * - the chosen co-agent's pairing rows (`MJ: AI Agent Co Agents`, Active 'CoAgent'-type rows): a
173
217
  * co-agent with pairing rows may only front its paired targets, so the
174
218
  * agent list constrains to those rows (Sequence order) with the IsDefault
@@ -222,12 +266,25 @@ export class RealtimeAgentPickerComponent extends BaseAngularComponent {
222
266
  SelectedModelId = null;
223
267
  /** Active Realtime models + their voices (for the voice selector); loaded only for authorized users. */
224
268
  VoiceModels = [];
269
+ /**
270
+ * The explicitly chosen voice option (one of {@link SelectedModelVoices}: a persona, so two personas sharing a voice
271
+ * id stay apart), or `null` for the configured/default voice.
272
+ */
273
+ SelectedVoice = null;
225
274
  /** The explicitly chosen voice id, or `null` for the configured/default voice. */
226
- SelectedVoiceId = null;
275
+ get SelectedVoiceId() {
276
+ return this.SelectedVoice?.ID ?? null;
277
+ }
278
+ /** Whether the chosen voice comes with an avatar: the hint under the voice list says so. */
279
+ get SelectedVoiceHasAvatar() {
280
+ return !!this.SelectedVoice?.AvatarID?.trim();
281
+ }
227
282
  /** Voices for the currently-selected model (empty when no model picked or it declares none). */
228
283
  get SelectedModelVoices() {
229
284
  return this.VoiceModels.find((m) => UUIDsEqual(m.ModelID, this.SelectedModelId))?.Voices ?? [];
230
285
  }
286
+ /** Preview images that failed to load; their voices show no image rather than a broken one. */
287
+ failedPreviewImages = new Set();
231
288
  /** The explicitly chosen co-agent id, or `null` for "Auto (recommended)" (the server's chain). */
232
289
  SelectedCoAgentId = null;
233
290
  /**
@@ -343,15 +400,35 @@ export class RealtimeAgentPickerComponent extends BaseAngularComponent {
343
400
  }
344
401
  this.cdr.markForCheck();
345
402
  }
346
- /** Records the voice-model choice (`''` = Auto → `null`); clears the voice so it can't outlive a switch. */
403
+ /** Records the voice-model choice (`''` = Auto → `null`); clears the voice (and its avatar) so it can't outlive a switch. */
347
404
  OnModelChange(value) {
348
405
  this.SelectedModelId = value && value.length > 0 ? value : null;
349
- this.SelectedVoiceId = null;
406
+ this.SelectedVoice = null;
350
407
  this.cdr.markForCheck();
351
408
  }
352
- /** Records the voice choice (`''` = default → `null`). */
409
+ /**
410
+ * Records the voice choice from the voice list: one of {@link SelectedModelVoices}, or `null` for "Default". The
411
+ * voice's avatar, when it has one, goes with it.
412
+ */
353
413
  OnVoiceChange(value) {
354
- this.SelectedVoiceId = value && value.length > 0 ? value : null;
414
+ this.SelectedVoice = this.VoiceOptionFor(value) ?? null;
415
+ this.cdr.markForCheck();
416
+ }
417
+ /**
418
+ * The voice an item of the voice list is. The list's items are {@link SelectedModelVoices}' own objects, matched by
419
+ * identity: an option is a persona, and two personas can share a voice id.
420
+ */
421
+ VoiceOptionFor(item) {
422
+ return this.SelectedModelVoices.find((voice) => voice === item);
423
+ }
424
+ /** The voice's persona preview image to show, or `null` when it has none or the image failed to load. */
425
+ PreviewImageFor(voice) {
426
+ const url = voice.PreviewImageURL?.trim();
427
+ return url && !this.failedPreviewImages.has(url) ? url : null;
428
+ }
429
+ /** Hides a preview image that failed to load. */
430
+ OnPreviewImageError(url) {
431
+ this.failedPreviewImages.add(url);
355
432
  this.cdr.markForCheck();
356
433
  }
357
434
  /** Records the co-agent choice (`''` = Auto → `null`) and refreshes the pairing constraint. */
@@ -485,9 +562,11 @@ export class RealtimeAgentPickerComponent extends BaseAngularComponent {
485
562
  }
486
563
  /** Dismiss when the user clicks anywhere outside the popover. (The phone
487
564
  * button that opens it stops propagation, so the opening click never
488
- * reaches this handler.) */
565
+ * reaches this handler.) The voice list opens in its own overlay outside
566
+ * this element; a click on it, or on the backdrop that closes it, only
567
+ * closes the list. */
489
568
  OnDocumentClick(event) {
490
- if (!this.elementRef.nativeElement.contains(event.target)) {
569
+ if (!this.elementRef.nativeElement.contains(event.target) && !this.isInDropdownOverlay(event.target)) {
491
570
  this.Cancelled.emit();
492
571
  }
493
572
  }
@@ -495,19 +574,25 @@ export class RealtimeAgentPickerComponent extends BaseAngularComponent {
495
574
  this.Cancelled.emit();
496
575
  }
497
576
  /**
498
- * Assembles the emitted pick. The model preference is hard-gated on the
499
- * authorization here (defense in depth — unauthorized users never see the selector,
500
- * so `SelectedModelId` should already be null).
577
+ * Assembles the emitted pick. The model, voice and avatar preferences are hard-gated
578
+ * on the authorization here (defense in depth — unauthorized users never see the
579
+ * selectors, so they should already be null).
501
580
  */
502
581
  buildPick(agent) {
582
+ const voice = this.CanOverrideSessionConfig ? this.SelectedVoice : null;
503
583
  return {
504
584
  Agent: agent,
505
585
  PreferredModelId: this.CanOverrideSessionConfig ? this.SelectedModelId : null,
506
- PreferredVoice: this.CanOverrideSessionConfig ? this.SelectedVoiceId : null,
586
+ PreferredVoice: voice?.ID ?? null,
587
+ PreferredAvatarId: voice?.AvatarID?.trim() || null,
507
588
  CoAgentId: this.SelectedCoAgentId,
508
589
  RecordingConsent: this.RecordingConsent
509
590
  };
510
591
  }
592
+ /** Whether a click landed in a dropdown's overlay (its option panel or the backdrop that closes it). */
593
+ isInDropdownOverlay(target) {
594
+ return target instanceof Element && target.closest('.mj-dropdown-panel, .mj-dropdown-backdrop') != null;
595
+ }
511
596
  isDefault(agent) {
512
597
  return !!this.DefaultAgentId && UUIDsEqual(agent.ID, this.DefaultAgentId);
513
598
  }
@@ -522,7 +607,7 @@ export class RealtimeAgentPickerComponent extends BaseAngularComponent {
522
607
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.searchInput = _t.first);
523
608
  } }, hostBindings: function RealtimeAgentPickerComponent_HostBindings(rf, ctx) { if (rf & 1) {
524
609
  i0.ɵɵlistener("click", function RealtimeAgentPickerComponent_click_HostBindingHandler($event) { return ctx.OnDocumentClick($event); }, i0.ɵɵresolveDocument)("keydown.escape", function RealtimeAgentPickerComponent_keydown_escape_HostBindingHandler() { return ctx.OnEscape(); }, i0.ɵɵresolveDocument);
525
- } }, inputs: { CurrentUser: "CurrentUser", Agents: "Agents", DefaultAgentId: "DefaultAgentId", CoAgents: "CoAgents", DefaultCoAgentId: "DefaultCoAgentId" }, outputs: { AgentPicked: "AgentPicked", Cancelled: "Cancelled" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 30, vars: 6, consts: [["searchInput", ""], ["coAgentSelect", ""], ["modelSelect", ""], ["voiceSelect", ""], [1, "mj-voice-picker", 3, "click"], [1, "mj-voice-picker__header"], [1, "fa-solid", "fa-phone"], [1, "mj-voice-picker__select-row"], [1, "mj-voice-picker__search"], [1, "fa-solid", "fa-magnifying-glass"], ["type", "text", "placeholder", "Search agents", 3, "input", "keydown.enter", "keydown.arrowdown", "keydown.arrowup", "value"], [1, "mj-voice-picker__list"], [1, "mj-voice-picker__empty"], [1, "mj-voice-picker__record-row"], [1, "mj-voice-picker__record-label"], [1, "fa-solid", "fa-microphone"], [1, "mj-voice-picker__record-copy"], [1, "mj-voice-picker__switch"], ["type", "checkbox", "aria-label", "Record this call (audio stored securely)", 3, "change", "checked"], [1, "mj-voice-picker__switch-track"], [1, "mj-voice-picker__footer"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click", "disabled"], ["mjButton", "", "variant", "outline", "size", "sm", 3, "click"], ["for", "mjRealtimeCoAgentSelect", 1, "mj-voice-picker__select-label"], [1, "fa-solid", "fa-headset"], ["id", "mjRealtimeCoAgentSelect", 1, "mj-voice-picker__select", 3, "change", "value"], ["value", ""], [3, "value"], ["type", "button", 1, "mj-voice-picker__item", 3, "mj-voice-picker__item--selected", "title"], ["type", "button", 1, "mj-voice-picker__item", 3, "click", "dblclick", "title"], [1, "mj-voice-picker__item-name"], [1, "mj-voice-picker__default-badge"], [1, "mj-voice-picker__select-row", "mj-voice-picker__select-row--model"], ["for", "mjRealtimeModelSelect", 1, "mj-voice-picker__select-label"], [1, "fa-solid", "fa-microchip"], ["id", "mjRealtimeModelSelect", 1, "mj-voice-picker__select", 3, "change", "value"], ["for", "mjRealtimeVoiceSelect", 1, "mj-voice-picker__select-label"], [1, "fa-solid", "fa-waveform-lines"], ["id", "mjRealtimeVoiceSelect", 1, "mj-voice-picker__select", 3, "change", "value"]], template: function RealtimeAgentPickerComponent_Template(rf, ctx) { if (rf & 1) {
610
+ } }, inputs: { CurrentUser: "CurrentUser", Agents: "Agents", DefaultAgentId: "DefaultAgentId", CoAgents: "CoAgents", DefaultCoAgentId: "DefaultCoAgentId" }, outputs: { AgentPicked: "AgentPicked", Cancelled: "Cancelled" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 30, vars: 6, consts: [["searchInput", ""], ["coAgentSelect", ""], ["modelSelect", ""], ["mjDropdownItem", ""], [1, "mj-voice-picker", 3, "click"], [1, "mj-voice-picker__header"], [1, "fa-solid", "fa-phone"], [1, "mj-voice-picker__select-row"], [1, "mj-voice-picker__search"], [1, "fa-solid", "fa-magnifying-glass"], ["type", "text", "placeholder", "Search agents", 3, "input", "keydown.enter", "keydown.arrowdown", "keydown.arrowup", "value"], [1, "mj-voice-picker__list"], [1, "mj-voice-picker__empty"], [1, "mj-voice-picker__record-row"], [1, "mj-voice-picker__record-label"], [1, "fa-solid", "fa-microphone"], [1, "mj-voice-picker__record-copy"], [1, "mj-voice-picker__switch"], ["type", "checkbox", "aria-label", "Record this call (audio stored securely)", 3, "change", "checked"], [1, "mj-voice-picker__switch-track"], [1, "mj-voice-picker__footer"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click", "disabled"], ["mjButton", "", "variant", "outline", "size", "sm", 3, "click"], ["for", "mjRealtimeCoAgentSelect", 1, "mj-voice-picker__select-label"], [1, "fa-solid", "fa-headset"], ["id", "mjRealtimeCoAgentSelect", 1, "mj-voice-picker__select", 3, "change", "value"], ["value", ""], [3, "value"], ["type", "button", 1, "mj-voice-picker__item", 3, "mj-voice-picker__item--selected", "title"], ["type", "button", 1, "mj-voice-picker__item", 3, "click", "dblclick", "title"], [1, "mj-voice-picker__item-name"], [1, "mj-voice-picker__default-badge"], [1, "mj-voice-picker__select-row", "mj-voice-picker__select-row--model"], ["for", "mjRealtimeModelSelect", 1, "mj-voice-picker__select-label"], [1, "fa-solid", "fa-microchip"], ["id", "mjRealtimeModelSelect", 1, "mj-voice-picker__select", 3, "change", "value"], [1, "mj-voice-picker__select-row", "mj-voice-picker__select-row--model", "mj-voice-picker__voice-row"], ["id", "mjRealtimeVoiceLabel", 1, "mj-voice-picker__select-label"], [1, "fa-solid", "fa-wave-square"], ["InputId", "mjRealtimeVoiceSelect", "AriaLabelledBy", "mjRealtimeVoiceLabel", "AriaDescribedBy", "mjRealtimeVoiceHint", "TextField", "Name", "DefaultItem", "Default", 1, "mj-voice-picker__voice-dropdown", 3, "ValueChange", "Data", "ngModel"], ["id", "mjRealtimeVoiceHint", "aria-live", "polite", 1, "mj-voice-picker__voice-hint"], [1, "mj-voice-picker__voice-hint-line"], [1, "mj-voice-picker__voice"], ["alt", "", 1, "mj-voice-picker__voice-image", 3, "src"], [1, "mj-voice-picker__voice-name"], ["title", "Comes with an avatar", 1, "mj-voice-picker__voice-avatar"], ["alt", "", 1, "mj-voice-picker__voice-image", 3, "error", "src"], ["aria-hidden", "true", 1, "fa-solid", "fa-video"], [1, "mj-voice-picker__sr-only"]], template: function RealtimeAgentPickerComponent_Template(rf, ctx) { if (rf & 1) {
526
611
  const _r1 = i0.ɵɵgetCurrentView();
527
612
  i0.ɵɵelementStart(0, "div", 4);
528
613
  i0.ɵɵlistener("click", function RealtimeAgentPickerComponent_Template_div_click_0_listener($event) { return $event.stopPropagation(); });
@@ -575,11 +660,11 @@ export class RealtimeAgentPickerComponent extends BaseAngularComponent {
575
660
  i0.ɵɵproperty("checked", ctx.RecordingConsent);
576
661
  i0.ɵɵadvance(3);
577
662
  i0.ɵɵproperty("disabled", !ctx.SelectedAgent);
578
- } }, dependencies: [MJButtonDirective], styles: ["[_nghost-%COMP%] {\n \n\n\n\n\n display: block;\n max-height: min(440px, calc(100vh - 24px));\n }\n .mj-voice-picker[_ngcontent-%COMP%] {\n width: 300px;\n max-width: calc(100vw - 24px);\n display: flex; flex-direction: column;\n \n\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n .mj-voice-picker__search[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 12px; color: var(--mj-text-muted); }\n .mj-voice-picker__search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder { color: var(--mj-text-disabled); }\n .mj-voice-picker__search[_ngcontent-%COMP%]:focus-within { border-color: var(--mj-border-focus); }\n .mj-voice-picker__list[_ngcontent-%COMP%] {\n \n\n\n\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 \n .mj-voice-picker__header[_ngcontent-%COMP%], \n .mj-voice-picker__search[_ngcontent-%COMP%], \n .mj-voice-picker__select-row[_ngcontent-%COMP%], \n .mj-voice-picker__record-row[_ngcontent-%COMP%], \n .mj-voice-picker__footer[_ngcontent-%COMP%] { flex-shrink: 0; }\n .mj-voice-picker__item[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { width: 16px; text-align: center; color: var(--mj-text-secondary); }\n .mj-voice-picker__item[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); }\n .mj-voice-picker__item--selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n }\n .mj-voice-picker__item--selected[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n .mj-voice-picker__item-name[_ngcontent-%COMP%] {\n flex: 1; min-width: 0;\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n }\n .mj-voice-picker__default-badge[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n padding: 12px; font-size: 12px; color: var(--mj-text-muted); text-align: center;\n }\n .mj-voice-picker__select-row[_ngcontent-%COMP%] {\n display: flex; align-items: center; gap: 8px;\n padding: 0 12px 8px;\n }\n .mj-voice-picker__select-row--model[_ngcontent-%COMP%] {\n padding: 8px 12px 0;\n }\n .mj-voice-picker__select-label[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 11px; color: var(--mj-text-muted); }\n .mj-voice-picker__select[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:focus { border-color: var(--mj-border-focus); }\n .mj-voice-picker__record-row[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n display: flex; align-items: center; gap: 8px;\n font-size: 12px; color: var(--mj-text-secondary);\n }\n .mj-voice-picker__record-label[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] { font-size: 12px; color: var(--mj-text-muted); }\n .mj-voice-picker__record-copy[_ngcontent-%COMP%] { display: flex; flex-direction: column; line-height: 1.3; }\n .mj-voice-picker__record-copy[_ngcontent-%COMP%] small[_ngcontent-%COMP%] { font-size: 10px; color: var(--mj-text-muted); }\n .mj-voice-picker__switch[_ngcontent-%COMP%] { position: relative; flex-shrink: 0; display: inline-flex; cursor: pointer; }\n .mj-voice-picker__switch[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer;\n }\n .mj-voice-picker__switch-track[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]::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[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:checked + .mj-voice-picker__switch-track[_ngcontent-%COMP%] { background: var(--mj-brand-primary); }\n .mj-voice-picker__switch[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:checked + .mj-voice-picker__switch-track[_ngcontent-%COMP%]::after { transform: translateX(16px); }\n .mj-voice-picker__switch[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus-visible + .mj-voice-picker__switch-track[_ngcontent-%COMP%] {\n outline: 2px solid var(--mj-border-focus); outline-offset: 2px;\n }\n @media (prefers-reduced-motion: reduce) {\n .mj-voice-picker__switch-track[_ngcontent-%COMP%], .mj-voice-picker__switch-track[_ngcontent-%COMP%]::after { transition: none; }\n }\n .mj-voice-picker__footer[_ngcontent-%COMP%] {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 12px;\n }"], changeDetection: 0 });
663
+ } }, dependencies: [MJButtonDirective, MJDropdownComponent, FormsModule, i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.NgControlStatus, i1.NgModel], styles: ["[_nghost-%COMP%] {\n \n\n\n\n\n display: block;\n max-height: min(440px, calc(100vh - 24px));\n }\n .mj-voice-picker[_ngcontent-%COMP%] {\n width: 300px;\n max-width: calc(100vw - 24px);\n display: flex; flex-direction: column;\n \n\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n .mj-voice-picker__search[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 12px; color: var(--mj-text-muted); }\n .mj-voice-picker__search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder { color: var(--mj-text-disabled); }\n .mj-voice-picker__search[_ngcontent-%COMP%]:focus-within { border-color: var(--mj-border-focus); }\n .mj-voice-picker__list[_ngcontent-%COMP%] {\n \n\n\n\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 \n .mj-voice-picker__header[_ngcontent-%COMP%], \n .mj-voice-picker__search[_ngcontent-%COMP%], \n .mj-voice-picker__select-row[_ngcontent-%COMP%], \n .mj-voice-picker__record-row[_ngcontent-%COMP%], \n .mj-voice-picker__footer[_ngcontent-%COMP%] { flex-shrink: 0; }\n .mj-voice-picker__item[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { width: 16px; text-align: center; color: var(--mj-text-secondary); }\n .mj-voice-picker__item[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); }\n .mj-voice-picker__item--selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n }\n .mj-voice-picker__item--selected[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n .mj-voice-picker__item-name[_ngcontent-%COMP%] {\n flex: 1; min-width: 0;\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n }\n .mj-voice-picker__default-badge[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n padding: 12px; font-size: 12px; color: var(--mj-text-muted); text-align: center;\n }\n .mj-voice-picker__select-row[_ngcontent-%COMP%] {\n display: flex; align-items: center; gap: 8px;\n padding: 0 12px 8px;\n }\n .mj-voice-picker__select-row--model[_ngcontent-%COMP%] {\n padding: 8px 12px 0;\n }\n .mj-voice-picker__select-label[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 11px; color: var(--mj-text-muted); }\n .mj-voice-picker__select[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:focus { border-color: var(--mj-border-focus); }\n \n\n\n .mj-voice-picker__voice-row[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] { min-width: 0; }\n .mj-voice-picker__voice-hint[_ngcontent-%COMP%] { grid-column: 2; }\n .mj-voice-picker__voice-hint-line[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 10px; color: var(--mj-brand-primary); }\n [_nghost-%COMP%] .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 [_nghost-%COMP%] .mj-voice-picker__voice-row .mj-dropdown--open, \n [_nghost-%COMP%] .mj-voice-picker__voice-row .mj-dropdown:focus-visible { border-color: var(--mj-border-focus); }\n .mj-voice-picker__voice[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 8px; width: 100%; min-width: 0; }\n .mj-voice-picker__voice-image[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .mj-voice-picker__voice-avatar[_ngcontent-%COMP%] { flex-shrink: 0; font-size: 11px; color: var(--mj-brand-primary); }\n .mj-voice-picker__sr-only[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n display: flex; align-items: center; gap: 8px;\n font-size: 12px; color: var(--mj-text-secondary);\n }\n .mj-voice-picker__record-label[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] { font-size: 12px; color: var(--mj-text-muted); }\n .mj-voice-picker__record-copy[_ngcontent-%COMP%] { display: flex; flex-direction: column; line-height: 1.3; }\n .mj-voice-picker__record-copy[_ngcontent-%COMP%] small[_ngcontent-%COMP%] { font-size: 10px; color: var(--mj-text-muted); }\n .mj-voice-picker__switch[_ngcontent-%COMP%] { position: relative; flex-shrink: 0; display: inline-flex; cursor: pointer; }\n .mj-voice-picker__switch[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer;\n }\n .mj-voice-picker__switch-track[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]::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[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:checked + .mj-voice-picker__switch-track[_ngcontent-%COMP%] { background: var(--mj-brand-primary); }\n .mj-voice-picker__switch[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:checked + .mj-voice-picker__switch-track[_ngcontent-%COMP%]::after { transform: translateX(16px); }\n .mj-voice-picker__switch[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus-visible + .mj-voice-picker__switch-track[_ngcontent-%COMP%] {\n outline: 2px solid var(--mj-border-focus); outline-offset: 2px;\n }\n @media (prefers-reduced-motion: reduce) {\n .mj-voice-picker__switch-track[_ngcontent-%COMP%], .mj-voice-picker__switch-track[_ngcontent-%COMP%]::after { transition: none; }\n }\n .mj-voice-picker__footer[_ngcontent-%COMP%] {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 12px;\n }"], changeDetection: 0 });
579
664
  }
580
665
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RealtimeAgentPickerComponent, [{
581
666
  type: Component,
582
- args: [{ standalone: true, selector: 'mj-realtime-agent-picker', imports: [MJButtonDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: `
667
+ args: [{ standalone: true, selector: 'mj-realtime-agent-picker', imports: [MJButtonDirective, MJDropdownComponent, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
583
668
  <div class="mj-voice-picker" (click)="$event.stopPropagation()">
584
669
  <div class="mj-voice-picker__header">
585
670
  <i class="fa-solid fa-phone"></i>
@@ -656,22 +741,49 @@ export class RealtimeAgentPickerComponent extends BaseAngularComponent {
656
741
  </select>
657
742
  </div>
658
743
  @if (SelectedModelVoices.length) {
659
- <div class="mj-voice-picker__select-row mj-voice-picker__select-row--model">
660
- <label class="mj-voice-picker__select-label" for="mjRealtimeVoiceSelect">
661
- <i class="fa-solid fa-waveform-lines"></i>
744
+ <div class="mj-voice-picker__select-row mj-voice-picker__select-row--model mj-voice-picker__voice-row">
745
+ <span class="mj-voice-picker__select-label" id="mjRealtimeVoiceLabel">
746
+ <i class="fa-solid fa-wave-square"></i>
662
747
  <span>Voice</span>
663
- </label>
664
- <select
665
- #voiceSelect
666
- id="mjRealtimeVoiceSelect"
667
- class="mj-voice-picker__select"
668
- [value]="SelectedVoiceId ?? ''"
669
- (change)="OnVoiceChange(voiceSelect.value)">
670
- <option value="">Default</option>
671
- @for (v of SelectedModelVoices; track v.ID) {
672
- <option [value]="v.ID">{{ v.Name }}</option>
748
+ </span>
749
+ <!-- No ValueField: an option is its voice object, one per persona, because two personas
750
+ can share a voice id (a voice, and the same voice with a face). -->
751
+ <mj-dropdown
752
+ class="mj-voice-picker__voice-dropdown"
753
+ InputId="mjRealtimeVoiceSelect"
754
+ AriaLabelledBy="mjRealtimeVoiceLabel"
755
+ AriaDescribedBy="mjRealtimeVoiceHint"
756
+ [Data]="SelectedModelVoices"
757
+ TextField="Name"
758
+ DefaultItem="Default"
759
+ [ngModel]="SelectedVoice"
760
+ (ValueChange)="OnVoiceChange($event)">
761
+ <ng-template #mjDropdownItem let-item>
762
+ @if (VoiceOptionFor(item); as voice) {
763
+ <span class="mj-voice-picker__voice">
764
+ @if (PreviewImageFor(voice); as image) {
765
+ <img class="mj-voice-picker__voice-image" [src]="image" alt="" (error)="OnPreviewImageError(image)" />
766
+ }
767
+ <span class="mj-voice-picker__voice-name">{{ voice.Name }}</span>
768
+ @if (voice.AvatarID) {
769
+ <span class="mj-voice-picker__voice-avatar" title="Comes with an avatar">
770
+ <i class="fa-solid fa-video" aria-hidden="true"></i>
771
+ <span class="mj-voice-picker__sr-only">Comes with an avatar</span>
772
+ </span>
773
+ }
774
+ </span>
775
+ }
776
+ </ng-template>
777
+ </mj-dropdown>
778
+ <!-- Always present, so screen readers announce the hint when a pick adds it. -->
779
+ <div class="mj-voice-picker__voice-hint" id="mjRealtimeVoiceHint" aria-live="polite">
780
+ @if (SelectedVoiceHasAvatar) {
781
+ <span class="mj-voice-picker__voice-hint-line">
782
+ <i class="fa-solid fa-video" aria-hidden="true"></i>
783
+ <span>Comes with an avatar</span>
784
+ </span>
673
785
  }
674
- </select>
786
+ </div>
675
787
  </div>
676
788
  }
677
789
  }
@@ -699,7 +811,7 @@ export class RealtimeAgentPickerComponent extends BaseAngularComponent {
699
811
  <button mjButton variant="outline" size="sm" (click)="Cancel()">Cancel</button>
700
812
  </div>
701
813
  </div>
702
- `, styles: ["\n :host {\n /* Rendered inside a body-level CDK connected overlay (see message-input) \u2014 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 "] }]
814
+ `, styles: ["\n :host {\n /* Rendered inside a body-level CDK connected overlay (see message-input) \u2014 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 "] }]
703
815
  }], null, { CurrentUser: [{
704
816
  type: Input
705
817
  }], Agents: [{
@@ -724,5 +836,5 @@ export class RealtimeAgentPickerComponent extends BaseAngularComponent {
724
836
  type: HostListener,
725
837
  args: ['document:keydown.escape']
726
838
  }] }); })();
727
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RealtimeAgentPickerComponent, { className: "RealtimeAgentPickerComponent", filePath: "src/lib/components/realtime/realtime-agent-picker.component.ts", lineNumber: 372 }); })();
839
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RealtimeAgentPickerComponent, { className: "RealtimeAgentPickerComponent", filePath: "src/lib/components/realtime/realtime-agent-picker.component.ts", lineNumber: 447 }); })();
728
840
  //# sourceMappingURL=realtime-agent-picker.component.js.map