@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
@@ -0,0 +1,129 @@
1
+ import { Observable } from 'rxjs';
2
+ import type { JSONObject } from '@memberjunction/ai';
3
+ import type { IdentityVerifiedEventPayload, RealtimeChannelActor } from '@memberjunction/ai-core-plus';
4
+ import type { RealtimeChannelVerbResult } from '@memberjunction/realtime-runtime';
5
+ import type { RealtimeSessionVerificationResult } from '@memberjunction/graphql-dataprovider';
6
+ /** Where a field's current value came from. */
7
+ export type IdentityFieldSource = 'user' | 'agent' | 'host';
8
+ /** The two things a person is asked for. */
9
+ export type IdentityField = 'name' | 'email';
10
+ /** The channel's lifecycle. `collecting` covers "still getting the values" and "must send (again)". */
11
+ export type IdentityVerificationStatus = 'collecting' | 'sending' | 'code_sent' | 'verifying' | 'verified';
12
+ /** What the channel needs from the server — the two calls it makes. `GraphQLRealtimeSessionClient` fits. */
13
+ export interface IdentityVerificationService {
14
+ Request(input: {
15
+ Name: string;
16
+ Email: string;
17
+ }): Promise<RealtimeSessionVerificationResult>;
18
+ SubmitCode(code: string): Promise<RealtimeSessionVerificationResult>;
19
+ }
20
+ /** One field as the surface renders it. */
21
+ export interface IdentityFieldView {
22
+ Value: string;
23
+ /** Who supplied the value; `null` while empty. */
24
+ Source: IdentityFieldSource | null;
25
+ /** The user wrote it, or approved it. Anything else must not be sent. */
26
+ Confirmed: boolean;
27
+ }
28
+ /** Everything the surface renders — an immutable snapshot, replaced on every change. */
29
+ export interface IdentityVerificationView {
30
+ Status: IdentityVerificationStatus;
31
+ Name: IdentityFieldView;
32
+ Email: IdentityFieldView;
33
+ /** The latest problem, in words a person can act on; `''` when there is none. */
34
+ Problem: string;
35
+ /** The server's machine-readable code for {@link Problem}, when it gave one. */
36
+ ProblemCode: string;
37
+ /** Both values present and confirmed, and nothing in flight or already sent for them. */
38
+ CanSubmit: boolean;
39
+ /** Epoch ms before which another send is refused (server back-off); `0` when none. */
40
+ ResendAvailableAt: number;
41
+ /** Sends the server will still allow for this session, when it said. */
42
+ SendsRemaining: number | null;
43
+ /** Code attempts left, when the server said. */
44
+ AttemptsRemaining: number | null;
45
+ /** The address the code went to (`code_sent`/`verifying`), or the verified one. */
46
+ Destination: string;
47
+ }
48
+ /** A change the model reports so the channel can record it (events + coalesced perception). */
49
+ export interface IdentityVerificationChange {
50
+ /** Who caused it (`system` for the server's answer / event). */
51
+ Author: RealtimeChannelActor | 'system';
52
+ /** The channel event this change is announced as, with its payload. */
53
+ Event?: {
54
+ Name: string;
55
+ Payload: JSONObject;
56
+ };
57
+ }
58
+ /**
59
+ * The identity-verification state machine — framework-free, so it is testable without Angular and shared
60
+ * by the channel (which adds the descriptor, events and perception) and the surface (which only renders
61
+ * {@link View$} and sends the user's actions back through the channel).
62
+ *
63
+ * The invariants it exists to hold:
64
+ * - **The user is the author or the approver of everything that is sent.** A value the user typed is
65
+ * confirmed by being theirs; a value the agent (or the host) supplied is NOT, until the user confirms
66
+ * it — and only the user can ({@link Confirm} refuses any other actor). Changing a value un-sends it.
67
+ * - **The server's `identity.verified` event is what makes a session verified.** A successful code
68
+ * submission also applies it, but only as a fallback for a transport without events, and idempotently.
69
+ * - **A code is never stored, echoed or put in a result** — it passes through {@link EnterCode} to the
70
+ * server and no further.
71
+ */
72
+ export declare class IdentityVerificationModel {
73
+ private readonly service;
74
+ private readonly now;
75
+ private view;
76
+ private readonly viewSubject;
77
+ private changeListener;
78
+ /** The values the live code was sent for, so a later change can tell it is stale. */
79
+ private sentFor;
80
+ /**
81
+ * @param service The server calls.
82
+ * @param now Clock, injectable for tests.
83
+ */
84
+ constructor(service: IdentityVerificationService | null, now?: () => number);
85
+ /** The current view, then every change. */
86
+ get View$(): Observable<IdentityVerificationView>;
87
+ get View(): IdentityVerificationView;
88
+ /** Registers the (single) listener told about every change — the channel. */
89
+ OnChange(listener: ((change: IdentityVerificationChange) => void) | null): void;
90
+ /** The channel's `GetState` snapshot (the descriptor's nouns). */
91
+ ToState(): JSONObject;
92
+ /** Seeds values the HOST knows (open inputs). They are unconfirmed — the user still has to approve them. */
93
+ Seed(inputs: JSONObject): void;
94
+ /** `fill` — set a field. A value the user types is confirmed by being theirs; anyone else's is not. */
95
+ Fill(args: JSONObject, actor: RealtimeChannelActor): RealtimeChannelVerbResult;
96
+ /** `confirm` — the user approves what is shown. Refused for anyone but the user, whatever the schema says. */
97
+ Confirm(args: JSONObject, actor: RealtimeChannelActor): RealtimeChannelVerbResult;
98
+ /** `submit` — send the code to the confirmed address. */
99
+ Submit(): Promise<RealtimeChannelVerbResult>;
100
+ /** `resend` — send a fresh code to the same, already-confirmed address. */
101
+ Resend(): Promise<RealtimeChannelVerbResult>;
102
+ /** `enter_code` — hand the code the person received to the server. The code is never kept. */
103
+ EnterCode(args: JSONObject): Promise<RealtimeChannelVerbResult>;
104
+ /**
105
+ * The server says the person is verified (the `identity.verified` event). Idempotent. Returns whether
106
+ * this call made the change, so the channel completes exactly once.
107
+ */
108
+ MarkVerified(payload: IdentityVerifiedEventPayload): boolean;
109
+ private sendCode;
110
+ private applySent;
111
+ private applySendFailure;
112
+ private applyCodeFailure;
113
+ private applyVerifiedFromResult;
114
+ /** Why a send must not go ahead, as a ready-made failure; `null` when it may. */
115
+ private blockReasonForSend;
116
+ /** A change to the values a code was sent for makes that code stale: back to collecting. */
117
+ private dropStaleCodeIfChanged;
118
+ private setField;
119
+ private setConfirmed;
120
+ private key;
121
+ private readField;
122
+ private problemFor;
123
+ private ok;
124
+ private fail;
125
+ private initialView;
126
+ /** Recomputes the derived flag, publishes the snapshot, and tells the channel. */
127
+ private publish;
128
+ }
129
+ //# sourceMappingURL=identity-verification-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-verification-model.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/identity-verification/identity-verification-model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,373 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ const MAX_FIELD_LENGTH = 200;
3
+ const MAX_CODE_LENGTH = 16;
4
+ /** A deliberately permissive shape check — the server owns real validation; this only catches "not an email". */
5
+ const EMAIL_SHAPE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
6
+ /** Server error codes whose cause the person cannot fix by retrying the same code: they must request a new one. */
7
+ const NEEDS_NEW_CODE = new Set(['code_expired', 'attempts_exhausted', 'no_pending_verification']);
8
+ /** What to say for an error code when the server gave no message of its own. */
9
+ const DEFAULT_PROBLEMS = {
10
+ verification_unavailable: 'Email verification is not available right now.',
11
+ invalid_input: 'Please check the details and try again.',
12
+ invalid_email: 'That does not look like a valid email address.',
13
+ session_not_found: 'This call is no longer active.',
14
+ session_closed: 'This call has ended.',
15
+ domain_blocked: 'That email address cannot be used here.',
16
+ consumer_domain: 'Please use your work email address.',
17
+ send_limit_reached: 'No more codes can be sent for this call.',
18
+ rate_limited: 'Too many attempts. Please wait a moment and try again.',
19
+ email_send_failed: 'We could not send the email. Please check the address and try again.',
20
+ no_pending_verification: 'There is no code waiting. Please request a new one.',
21
+ code_expired: 'That code has expired. Please request a new one.',
22
+ invalid_code: 'That code is not right. Please check it and try again.',
23
+ attempts_exhausted: 'Too many wrong codes. Please request a new one.',
24
+ invalid_link: 'That link is no longer valid.',
25
+ persist_failed: 'Something went wrong on our side. Please try again.',
26
+ transport_error: 'We could not reach the server. Please try again.'
27
+ };
28
+ function clean(value, max) {
29
+ return typeof value === 'string' ? value.trim().slice(0, max) : '';
30
+ }
31
+ function emptyField() {
32
+ return { Value: '', Source: null, Confirmed: false };
33
+ }
34
+ /**
35
+ * The identity-verification state machine — framework-free, so it is testable without Angular and shared
36
+ * by the channel (which adds the descriptor, events and perception) and the surface (which only renders
37
+ * {@link View$} and sends the user's actions back through the channel).
38
+ *
39
+ * The invariants it exists to hold:
40
+ * - **The user is the author or the approver of everything that is sent.** A value the user typed is
41
+ * confirmed by being theirs; a value the agent (or the host) supplied is NOT, until the user confirms
42
+ * it — and only the user can ({@link Confirm} refuses any other actor). Changing a value un-sends it.
43
+ * - **The server's `identity.verified` event is what makes a session verified.** A successful code
44
+ * submission also applies it, but only as a fallback for a transport without events, and idempotently.
45
+ * - **A code is never stored, echoed or put in a result** — it passes through {@link EnterCode} to the
46
+ * server and no further.
47
+ */
48
+ export class IdentityVerificationModel {
49
+ service;
50
+ now;
51
+ view = this.initialView();
52
+ viewSubject = new BehaviorSubject(this.view);
53
+ changeListener = null;
54
+ /** The values the live code was sent for, so a later change can tell it is stale. */
55
+ sentFor = null;
56
+ /**
57
+ * @param service The server calls.
58
+ * @param now Clock, injectable for tests.
59
+ */
60
+ constructor(service, now = () => Date.now()) {
61
+ this.service = service;
62
+ this.now = now;
63
+ }
64
+ /** The current view, then every change. */
65
+ get View$() {
66
+ return this.viewSubject.asObservable();
67
+ }
68
+ get View() {
69
+ return this.view;
70
+ }
71
+ /** Registers the (single) listener told about every change — the channel. */
72
+ OnChange(listener) {
73
+ this.changeListener = listener;
74
+ }
75
+ /** The channel's `GetState` snapshot (the descriptor's nouns). */
76
+ ToState() {
77
+ const v = this.view;
78
+ return {
79
+ name: v.Name.Value,
80
+ email: v.Email.Value,
81
+ status: v.Status,
82
+ confirmed: { name: v.Name.Confirmed, email: v.Email.Confirmed },
83
+ problem: v.Problem
84
+ };
85
+ }
86
+ // ── Verbs ──────────────────────────────────────────────────────────────────
87
+ /** Seeds values the HOST knows (open inputs). They are unconfirmed — the user still has to approve them. */
88
+ Seed(inputs) {
89
+ for (const field of ['name', 'email']) {
90
+ const value = clean(inputs[field], MAX_FIELD_LENGTH);
91
+ if (value.length > 0 && this.view[this.key(field)].Value.length === 0) {
92
+ this.setField(field, value, 'host');
93
+ }
94
+ }
95
+ this.publish({ Author: 'system' });
96
+ }
97
+ /** `fill` — set a field. A value the user types is confirmed by being theirs; anyone else's is not. */
98
+ Fill(args, actor) {
99
+ if (this.view.Status === 'verified') {
100
+ return this.fail('already_verified', 'This person is already verified; there is nothing to fill in.');
101
+ }
102
+ if (this.view.Status === 'sending' || this.view.Status === 'verifying') {
103
+ return this.fail('verb_failed', 'A request is in progress; wait for it to finish.');
104
+ }
105
+ const field = this.readField(args['field']);
106
+ const value = clean(args['value'], MAX_FIELD_LENGTH);
107
+ if (field === null) {
108
+ return this.fail('invalid_params', 'field must be "name" or "email".');
109
+ }
110
+ if (value.length === 0) {
111
+ return this.fail('invalid_params', 'value must not be empty.');
112
+ }
113
+ if (field === 'email' && !EMAIL_SHAPE.test(value)) {
114
+ return this.fail('invalid_params', 'That does not look like an email address. Ask the user to spell it out, then fill it again.');
115
+ }
116
+ const current = this.view[this.key(field)];
117
+ // The same value again changes nothing — in particular an agent repeating what the user typed must
118
+ // not un-confirm it. The one exception: the user typing exactly what the agent suggested IS them
119
+ // confirming it, so that falls through and records the user as the author.
120
+ if (current.Value === value && !(actor === 'user' && !current.Confirmed)) {
121
+ return this.ok(`The ${field} was already set to that.`);
122
+ }
123
+ this.setField(field, value, actor);
124
+ this.dropStaleCodeIfChanged();
125
+ this.view = { ...this.view, Status: 'collecting', Problem: '', ProblemCode: '' };
126
+ this.publish({ Author: actor, Event: { Name: 'field_filled', Payload: { field, actor, confirmed: this.view[this.key(field)].Confirmed } } });
127
+ return this.ok(actor === 'agent'
128
+ ? `The ${field} is filled in and shown to the user, who must confirm it before anything is sent.`
129
+ : `The user entered their ${field}.`);
130
+ }
131
+ /** `confirm` — the user approves what is shown. Refused for anyone but the user, whatever the schema says. */
132
+ Confirm(args, actor) {
133
+ if (actor !== 'user') {
134
+ return this.fail('not_invokable_by_agent', 'Only the user can confirm their own details. Ask them to check the form and confirm.');
135
+ }
136
+ const requested = args['field'] === undefined ? null : this.readField(args['field']);
137
+ if (args['field'] !== undefined && requested === null) {
138
+ return this.fail('invalid_params', 'field must be "name" or "email" (or omitted to confirm both).');
139
+ }
140
+ const fields = requested ? [requested] : ['name', 'email'];
141
+ const confirmed = [];
142
+ for (const field of fields) {
143
+ const f = this.view[this.key(field)];
144
+ if (f.Value.length > 0 && !f.Confirmed) {
145
+ this.setConfirmed(field);
146
+ confirmed.push(field);
147
+ }
148
+ }
149
+ if (confirmed.length === 0) {
150
+ return this.fail('verb_failed', 'There is nothing to confirm.');
151
+ }
152
+ this.publish({ Author: 'user', Event: { Name: 'confirmed', Payload: { fields: confirmed } } });
153
+ return this.ok('Confirmed.');
154
+ }
155
+ /** `submit` — send the code to the confirmed address. */
156
+ async Submit() {
157
+ const blocked = this.blockReasonForSend('submit');
158
+ if (blocked) {
159
+ return blocked;
160
+ }
161
+ return this.sendCode();
162
+ }
163
+ /** `resend` — send a fresh code to the same, already-confirmed address. */
164
+ async Resend() {
165
+ if (this.view.Status !== 'code_sent') {
166
+ return this.fail('verb_failed', 'No code has been sent yet. Use submit first.');
167
+ }
168
+ const blocked = this.blockReasonForSend('resend');
169
+ if (blocked) {
170
+ return blocked;
171
+ }
172
+ return this.sendCode();
173
+ }
174
+ /** `enter_code` — hand the code the person received to the server. The code is never kept. */
175
+ async EnterCode(args) {
176
+ if (this.view.Status === 'verified') {
177
+ return this.fail('already_verified', 'This person is already verified.');
178
+ }
179
+ if (this.view.Status !== 'code_sent') {
180
+ return this.fail('verb_failed', this.view.Status === 'verifying' ? 'A code is being checked; wait for the answer.' : 'No code has been sent yet. Send one first.');
181
+ }
182
+ const code = clean(args['code'], MAX_CODE_LENGTH);
183
+ if (code.length === 0) {
184
+ return this.fail('invalid_params', 'code must not be empty.');
185
+ }
186
+ if (!this.service) {
187
+ return this.fail('verb_failed', 'Verification is not available in this session.');
188
+ }
189
+ this.view = { ...this.view, Status: 'verifying', Problem: '', ProblemCode: '' };
190
+ this.publish({ Author: 'user', Event: { Name: 'code_entered', Payload: {} } });
191
+ const result = await this.service.SubmitCode(code);
192
+ if (this.view.Status === 'verified') {
193
+ return this.ok('Verified.'); // the server's event got there first
194
+ }
195
+ return result.Success && result.VerificationState === 'verified' ? this.applyVerifiedFromResult(result) : this.applyCodeFailure(result);
196
+ }
197
+ // ── Server's word ──────────────────────────────────────────────────────────
198
+ /**
199
+ * The server says the person is verified (the `identity.verified` event). Idempotent. Returns whether
200
+ * this call made the change, so the channel completes exactly once.
201
+ */
202
+ MarkVerified(payload) {
203
+ if (this.view.Status === 'verified') {
204
+ return false;
205
+ }
206
+ const email = clean(payload.VerifiedEmail, MAX_FIELD_LENGTH);
207
+ const name = clean(payload.VerifiedName, MAX_FIELD_LENGTH);
208
+ this.view = {
209
+ ...this.view,
210
+ Status: 'verified',
211
+ Name: name.length > 0 ? { Value: name, Source: this.view.Name.Source ?? 'user', Confirmed: true } : this.view.Name,
212
+ Email: { Value: email, Source: this.view.Email.Source ?? 'user', Confirmed: true },
213
+ Destination: email,
214
+ Problem: '',
215
+ ProblemCode: '',
216
+ ResendAvailableAt: 0
217
+ };
218
+ this.sentFor = null;
219
+ this.publish({ Author: 'system', Event: { Name: 'verified', Payload: { email, name, method: payload.Method } } });
220
+ return true;
221
+ }
222
+ // ── Internals ──────────────────────────────────────────────────────────────
223
+ async sendCode() {
224
+ if (!this.service) {
225
+ return this.fail('verb_failed', 'Verification is not available in this session.');
226
+ }
227
+ const { Name, Email } = { Name: this.view.Name.Value, Email: this.view.Email.Value };
228
+ this.view = { ...this.view, Status: 'sending', Problem: '', ProblemCode: '' };
229
+ this.publish({ Author: 'system' });
230
+ const result = await this.service.Request({ Name, Email });
231
+ if (this.view.Status === 'verified') {
232
+ return this.ok('Verified.');
233
+ }
234
+ return result.Success ? this.applySent(result, Name, Email) : this.applySendFailure(result);
235
+ }
236
+ applySent(result, name, email) {
237
+ this.sentFor = { Name: name, Email: email };
238
+ this.view = {
239
+ ...this.view,
240
+ Status: 'code_sent',
241
+ Destination: email,
242
+ Problem: '',
243
+ ProblemCode: '',
244
+ SendsRemaining: result.SendsRemaining ?? null,
245
+ AttemptsRemaining: result.AttemptsRemaining ?? null,
246
+ ResendAvailableAt: result.RetryAfterSeconds ? this.now() + result.RetryAfterSeconds * 1000 : 0
247
+ };
248
+ this.publish({ Author: 'system', Event: { Name: 'code_sent', Payload: { email } } });
249
+ return this.ok(`A code was emailed to ${email}. The user can type it in, or open the link in the email. Do not ask them to read the code aloud.`);
250
+ }
251
+ applySendFailure(result) {
252
+ const problem = this.problemFor(result);
253
+ this.view = {
254
+ ...this.view,
255
+ Status: 'collecting',
256
+ Problem: problem,
257
+ ProblemCode: result.ErrorCode ?? '',
258
+ ResendAvailableAt: result.RetryAfterSeconds ? this.now() + result.RetryAfterSeconds * 1000 : this.view.ResendAvailableAt,
259
+ SendsRemaining: result.SendsRemaining ?? this.view.SendsRemaining
260
+ };
261
+ this.publish({ Author: 'system', Event: { Name: 'error', Payload: { code: result.ErrorCode ?? 'unknown', stage: 'send' } } });
262
+ return this.fail(result.ErrorCode ?? 'verb_failed', problem);
263
+ }
264
+ applyCodeFailure(result) {
265
+ const problem = this.problemFor(result);
266
+ const code = result.ErrorCode ?? '';
267
+ this.view = {
268
+ ...this.view,
269
+ Status: NEEDS_NEW_CODE.has(code) ? 'collecting' : 'code_sent',
270
+ Problem: problem,
271
+ ProblemCode: code,
272
+ AttemptsRemaining: result.AttemptsRemaining ?? this.view.AttemptsRemaining
273
+ };
274
+ if (NEEDS_NEW_CODE.has(code)) {
275
+ this.sentFor = null;
276
+ }
277
+ this.publish({ Author: 'system', Event: { Name: 'error', Payload: { code: code || 'unknown', stage: 'code' } } });
278
+ return this.fail(code || 'verb_failed', problem);
279
+ }
280
+ applyVerifiedFromResult(result) {
281
+ const email = result.VerifiedEmail ?? this.view.Email.Value;
282
+ this.MarkVerified({
283
+ VerifiedEmail: email,
284
+ VerifiedName: this.view.Name.Value,
285
+ VerifiedAt: result.VerifiedAt ?? new Date(this.now()).toISOString(),
286
+ Method: 'code',
287
+ ...(result.MaxSessionDeadlineIso ? { MaxSessionDeadlineIso: result.MaxSessionDeadlineIso } : {})
288
+ });
289
+ return this.ok('Verified.');
290
+ }
291
+ /** Why a send must not go ahead, as a ready-made failure; `null` when it may. */
292
+ blockReasonForSend(verb) {
293
+ const v = this.view;
294
+ if (v.Status === 'verified') {
295
+ return this.fail('already_verified', 'This person is already verified.');
296
+ }
297
+ if (v.Status === 'sending' || v.Status === 'verifying') {
298
+ return this.fail('verb_failed', 'A request is in progress; wait for it to finish.');
299
+ }
300
+ if (verb === 'submit' && v.Status === 'code_sent') {
301
+ return this.fail('verb_failed', 'A code was already sent to this address. Wait for the user to enter it, or use resend.');
302
+ }
303
+ if (v.Name.Value.length === 0 || v.Email.Value.length === 0) {
304
+ return this.fail('verb_failed', 'Both the name and the email are needed first. Fill in what is missing.');
305
+ }
306
+ if (!v.Name.Confirmed || !v.Email.Confirmed) {
307
+ return this.fail('verb_failed', 'The user has not confirmed their details yet. Ask them to check the form and confirm; you cannot confirm for them.');
308
+ }
309
+ if (v.SendsRemaining === 0) {
310
+ return this.fail('send_limit_reached', DEFAULT_PROBLEMS['send_limit_reached']);
311
+ }
312
+ const wait = v.ResendAvailableAt - this.now();
313
+ if (wait > 0) {
314
+ return this.fail('rate_limited', `Another code can be sent in ${Math.ceil(wait / 1000)} seconds.`);
315
+ }
316
+ return null;
317
+ }
318
+ /** A change to the values a code was sent for makes that code stale: back to collecting. */
319
+ dropStaleCodeIfChanged() {
320
+ if (this.sentFor && (this.sentFor.Name !== this.view.Name.Value || this.sentFor.Email !== this.view.Email.Value)) {
321
+ this.sentFor = null;
322
+ this.view = { ...this.view, Destination: '', AttemptsRemaining: null };
323
+ }
324
+ }
325
+ setField(field, value, source) {
326
+ const next = { Value: value, Source: source, Confirmed: source === 'user' };
327
+ this.view = { ...this.view, [this.key(field)]: next };
328
+ }
329
+ setConfirmed(field) {
330
+ const key = this.key(field);
331
+ this.view = { ...this.view, [key]: { ...this.view[key], Confirmed: true } };
332
+ }
333
+ key(field) {
334
+ return field === 'name' ? 'Name' : 'Email';
335
+ }
336
+ readField(raw) {
337
+ return raw === 'name' || raw === 'email' ? raw : null;
338
+ }
339
+ problemFor(result) {
340
+ return (result.Message && result.Message.trim()) || DEFAULT_PROBLEMS[result.ErrorCode ?? ''] || 'Something went wrong. Please try again.';
341
+ }
342
+ ok(message, extra = {}) {
343
+ return { Success: true, Result: { message, status: this.view.Status, ...extra } };
344
+ }
345
+ fail(code, message) {
346
+ return { Success: false, ErrorCode: code, Error: message };
347
+ }
348
+ initialView() {
349
+ return {
350
+ Status: 'collecting',
351
+ Name: emptyField(),
352
+ Email: emptyField(),
353
+ Problem: '',
354
+ ProblemCode: '',
355
+ CanSubmit: false,
356
+ ResendAvailableAt: 0,
357
+ SendsRemaining: null,
358
+ AttemptsRemaining: null,
359
+ Destination: ''
360
+ };
361
+ }
362
+ /** Recomputes the derived flag, publishes the snapshot, and tells the channel. */
363
+ publish(change) {
364
+ const v = this.view;
365
+ this.view = {
366
+ ...v,
367
+ CanSubmit: v.Status === 'collecting' && v.Name.Value.length > 0 && v.Email.Value.length > 0 && v.Name.Confirmed && v.Email.Confirmed
368
+ };
369
+ this.viewSubject.next(this.view);
370
+ this.changeListener?.(change);
371
+ }
372
+ }
373
+ //# sourceMappingURL=identity-verification-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-verification-model.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/identity-verification/identity-verification-model.ts"],"names":[],"mappings":"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","sourcesContent":["import { BehaviorSubject, Observable } from 'rxjs';\nimport type { JSONObject } from '@memberjunction/ai';\nimport type { IdentityVerifiedEventPayload, RealtimeChannelActor } from '@memberjunction/ai-core-plus';\nimport type { RealtimeChannelVerbResult } from '@memberjunction/realtime-runtime';\nimport type { RealtimeSessionVerificationResult } from '@memberjunction/graphql-dataprovider';\n\n/** Where a field's current value came from. */\nexport type IdentityFieldSource = 'user' | 'agent' | 'host';\n\n/** The two things a person is asked for. */\nexport type IdentityField = 'name' | 'email';\n\n/** The channel's lifecycle. `collecting` covers \"still getting the values\" and \"must send (again)\". */\nexport type IdentityVerificationStatus = 'collecting' | 'sending' | 'code_sent' | 'verifying' | 'verified';\n\n/** What the channel needs from the server — the two calls it makes. `GraphQLRealtimeSessionClient` fits. */\nexport interface IdentityVerificationService {\n Request(input: { Name: string; Email: string }): Promise<RealtimeSessionVerificationResult>;\n SubmitCode(code: string): Promise<RealtimeSessionVerificationResult>;\n}\n\n/** One field as the surface renders it. */\nexport interface IdentityFieldView {\n Value: string;\n /** Who supplied the value; `null` while empty. */\n Source: IdentityFieldSource | null;\n /** The user wrote it, or approved it. Anything else must not be sent. */\n Confirmed: boolean;\n}\n\n/** Everything the surface renders — an immutable snapshot, replaced on every change. */\nexport interface IdentityVerificationView {\n Status: IdentityVerificationStatus;\n Name: IdentityFieldView;\n Email: IdentityFieldView;\n /** The latest problem, in words a person can act on; `''` when there is none. */\n Problem: string;\n /** The server's machine-readable code for {@link Problem}, when it gave one. */\n ProblemCode: string;\n /** Both values present and confirmed, and nothing in flight or already sent for them. */\n CanSubmit: boolean;\n /** Epoch ms before which another send is refused (server back-off); `0` when none. */\n ResendAvailableAt: number;\n /** Sends the server will still allow for this session, when it said. */\n SendsRemaining: number | null;\n /** Code attempts left, when the server said. */\n AttemptsRemaining: number | null;\n /** The address the code went to (`code_sent`/`verifying`), or the verified one. */\n Destination: string;\n}\n\n/** A change the model reports so the channel can record it (events + coalesced perception). */\nexport interface IdentityVerificationChange {\n /** Who caused it (`system` for the server's answer / event). */\n Author: RealtimeChannelActor | 'system';\n /** The channel event this change is announced as, with its payload. */\n Event?: { Name: string; Payload: JSONObject };\n}\n\nconst MAX_FIELD_LENGTH = 200;\nconst MAX_CODE_LENGTH = 16;\n/** A deliberately permissive shape check — the server owns real validation; this only catches \"not an email\". */\nconst EMAIL_SHAPE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n/** Server error codes whose cause the person cannot fix by retrying the same code: they must request a new one. */\nconst NEEDS_NEW_CODE: ReadonlySet<string> = new Set(['code_expired', 'attempts_exhausted', 'no_pending_verification']);\n\n/** What to say for an error code when the server gave no message of its own. */\nconst DEFAULT_PROBLEMS: Readonly<Record<string, string>> = {\n verification_unavailable: 'Email verification is not available right now.',\n invalid_input: 'Please check the details and try again.',\n invalid_email: 'That does not look like a valid email address.',\n session_not_found: 'This call is no longer active.',\n session_closed: 'This call has ended.',\n domain_blocked: 'That email address cannot be used here.',\n consumer_domain: 'Please use your work email address.',\n send_limit_reached: 'No more codes can be sent for this call.',\n rate_limited: 'Too many attempts. Please wait a moment and try again.',\n email_send_failed: 'We could not send the email. Please check the address and try again.',\n no_pending_verification: 'There is no code waiting. Please request a new one.',\n code_expired: 'That code has expired. Please request a new one.',\n invalid_code: 'That code is not right. Please check it and try again.',\n attempts_exhausted: 'Too many wrong codes. Please request a new one.',\n invalid_link: 'That link is no longer valid.',\n persist_failed: 'Something went wrong on our side. Please try again.',\n transport_error: 'We could not reach the server. Please try again.'\n};\n\nfunction clean(value: unknown, max: number): string {\n return typeof value === 'string' ? value.trim().slice(0, max) : '';\n}\n\nfunction emptyField(): IdentityFieldView {\n return { Value: '', Source: null, Confirmed: false };\n}\n\n/**\n * The identity-verification state machine — framework-free, so it is testable without Angular and shared\n * by the channel (which adds the descriptor, events and perception) and the surface (which only renders\n * {@link View$} and sends the user's actions back through the channel).\n *\n * The invariants it exists to hold:\n * - **The user is the author or the approver of everything that is sent.** A value the user typed is\n * confirmed by being theirs; a value the agent (or the host) supplied is NOT, until the user confirms\n * it — and only the user can ({@link Confirm} refuses any other actor). Changing a value un-sends it.\n * - **The server's `identity.verified` event is what makes a session verified.** A successful code\n * submission also applies it, but only as a fallback for a transport without events, and idempotently.\n * - **A code is never stored, echoed or put in a result** — it passes through {@link EnterCode} to the\n * server and no further.\n */\nexport class IdentityVerificationModel {\n private view: IdentityVerificationView = this.initialView();\n private readonly viewSubject = new BehaviorSubject<IdentityVerificationView>(this.view);\n private changeListener: ((change: IdentityVerificationChange) => void) | null = null;\n /** The values the live code was sent for, so a later change can tell it is stale. */\n private sentFor: { Name: string; Email: string } | null = null;\n\n /**\n * @param service The server calls.\n * @param now Clock, injectable for tests.\n */\n constructor(\n private readonly service: IdentityVerificationService | null,\n private readonly now: () => number = () => Date.now()\n ) {}\n\n /** The current view, then every change. */\n public get View$(): Observable<IdentityVerificationView> {\n return this.viewSubject.asObservable();\n }\n\n public get View(): IdentityVerificationView {\n return this.view;\n }\n\n /** Registers the (single) listener told about every change — the channel. */\n public OnChange(listener: ((change: IdentityVerificationChange) => void) | null): void {\n this.changeListener = listener;\n }\n\n /** The channel's `GetState` snapshot (the descriptor's nouns). */\n public ToState(): JSONObject {\n const v = this.view;\n return {\n name: v.Name.Value,\n email: v.Email.Value,\n status: v.Status,\n confirmed: { name: v.Name.Confirmed, email: v.Email.Confirmed },\n problem: v.Problem\n };\n }\n\n // ── Verbs ──────────────────────────────────────────────────────────────────\n\n /** Seeds values the HOST knows (open inputs). They are unconfirmed — the user still has to approve them. */\n public Seed(inputs: JSONObject): void {\n for (const field of ['name', 'email'] as const) {\n const value = clean(inputs[field], MAX_FIELD_LENGTH);\n if (value.length > 0 && this.view[this.key(field)].Value.length === 0) {\n this.setField(field, value, 'host');\n }\n }\n this.publish({ Author: 'system' });\n }\n\n /** `fill` — set a field. A value the user types is confirmed by being theirs; anyone else's is not. */\n public Fill(args: JSONObject, actor: RealtimeChannelActor): RealtimeChannelVerbResult {\n if (this.view.Status === 'verified') {\n return this.fail('already_verified', 'This person is already verified; there is nothing to fill in.');\n }\n if (this.view.Status === 'sending' || this.view.Status === 'verifying') {\n return this.fail('verb_failed', 'A request is in progress; wait for it to finish.');\n }\n const field = this.readField(args['field']);\n const value = clean(args['value'], MAX_FIELD_LENGTH);\n if (field === null) {\n return this.fail('invalid_params', 'field must be \"name\" or \"email\".');\n }\n if (value.length === 0) {\n return this.fail('invalid_params', 'value must not be empty.');\n }\n if (field === 'email' && !EMAIL_SHAPE.test(value)) {\n return this.fail('invalid_params', 'That does not look like an email address. Ask the user to spell it out, then fill it again.');\n }\n const current = this.view[this.key(field)];\n // The same value again changes nothing — in particular an agent repeating what the user typed must\n // not un-confirm it. The one exception: the user typing exactly what the agent suggested IS them\n // confirming it, so that falls through and records the user as the author.\n if (current.Value === value && !(actor === 'user' && !current.Confirmed)) {\n return this.ok(`The ${field} was already set to that.`);\n }\n this.setField(field, value, actor);\n this.dropStaleCodeIfChanged();\n this.view = { ...this.view, Status: 'collecting', Problem: '', ProblemCode: '' };\n this.publish({ Author: actor, Event: { Name: 'field_filled', Payload: { field, actor, confirmed: this.view[this.key(field)].Confirmed } } });\n return this.ok(\n actor === 'agent'\n ? `The ${field} is filled in and shown to the user, who must confirm it before anything is sent.`\n : `The user entered their ${field}.`\n );\n }\n\n /** `confirm` — the user approves what is shown. Refused for anyone but the user, whatever the schema says. */\n public Confirm(args: JSONObject, actor: RealtimeChannelActor): RealtimeChannelVerbResult {\n if (actor !== 'user') {\n return this.fail('not_invokable_by_agent', 'Only the user can confirm their own details. Ask them to check the form and confirm.');\n }\n const requested = args['field'] === undefined ? null : this.readField(args['field']);\n if (args['field'] !== undefined && requested === null) {\n return this.fail('invalid_params', 'field must be \"name\" or \"email\" (or omitted to confirm both).');\n }\n const fields: IdentityField[] = requested ? [requested] : ['name', 'email'];\n const confirmed: IdentityField[] = [];\n for (const field of fields) {\n const f = this.view[this.key(field)];\n if (f.Value.length > 0 && !f.Confirmed) {\n this.setConfirmed(field);\n confirmed.push(field);\n }\n }\n if (confirmed.length === 0) {\n return this.fail('verb_failed', 'There is nothing to confirm.');\n }\n this.publish({ Author: 'user', Event: { Name: 'confirmed', Payload: { fields: confirmed } } });\n return this.ok('Confirmed.');\n }\n\n /** `submit` — send the code to the confirmed address. */\n public async Submit(): Promise<RealtimeChannelVerbResult> {\n const blocked = this.blockReasonForSend('submit');\n if (blocked) {\n return blocked;\n }\n return this.sendCode();\n }\n\n /** `resend` — send a fresh code to the same, already-confirmed address. */\n public async Resend(): Promise<RealtimeChannelVerbResult> {\n if (this.view.Status !== 'code_sent') {\n return this.fail('verb_failed', 'No code has been sent yet. Use submit first.');\n }\n const blocked = this.blockReasonForSend('resend');\n if (blocked) {\n return blocked;\n }\n return this.sendCode();\n }\n\n /** `enter_code` — hand the code the person received to the server. The code is never kept. */\n public async EnterCode(args: JSONObject): Promise<RealtimeChannelVerbResult> {\n if (this.view.Status === 'verified') {\n return this.fail('already_verified', 'This person is already verified.');\n }\n if (this.view.Status !== 'code_sent') {\n return this.fail('verb_failed', this.view.Status === 'verifying' ? 'A code is being checked; wait for the answer.' : 'No code has been sent yet. Send one first.');\n }\n const code = clean(args['code'], MAX_CODE_LENGTH);\n if (code.length === 0) {\n return this.fail('invalid_params', 'code must not be empty.');\n }\n if (!this.service) {\n return this.fail('verb_failed', 'Verification is not available in this session.');\n }\n this.view = { ...this.view, Status: 'verifying', Problem: '', ProblemCode: '' };\n this.publish({ Author: 'user', Event: { Name: 'code_entered', Payload: {} } });\n const result = await this.service.SubmitCode(code);\n if (this.view.Status === 'verified') {\n return this.ok('Verified.'); // the server's event got there first\n }\n return result.Success && result.VerificationState === 'verified' ? this.applyVerifiedFromResult(result) : this.applyCodeFailure(result);\n }\n\n // ── Server's word ──────────────────────────────────────────────────────────\n\n /**\n * The server says the person is verified (the `identity.verified` event). Idempotent. Returns whether\n * this call made the change, so the channel completes exactly once.\n */\n public MarkVerified(payload: IdentityVerifiedEventPayload): boolean {\n if (this.view.Status === 'verified') {\n return false;\n }\n const email = clean(payload.VerifiedEmail, MAX_FIELD_LENGTH);\n const name = clean(payload.VerifiedName, MAX_FIELD_LENGTH);\n this.view = {\n ...this.view,\n Status: 'verified',\n Name: name.length > 0 ? { Value: name, Source: this.view.Name.Source ?? 'user', Confirmed: true } : this.view.Name,\n Email: { Value: email, Source: this.view.Email.Source ?? 'user', Confirmed: true },\n Destination: email,\n Problem: '',\n ProblemCode: '',\n ResendAvailableAt: 0\n };\n this.sentFor = null;\n this.publish({ Author: 'system', Event: { Name: 'verified', Payload: { email, name, method: payload.Method } } });\n return true;\n }\n\n // ── Internals ──────────────────────────────────────────────────────────────\n\n private async sendCode(): Promise<RealtimeChannelVerbResult> {\n if (!this.service) {\n return this.fail('verb_failed', 'Verification is not available in this session.');\n }\n const { Name, Email } = { Name: this.view.Name.Value, Email: this.view.Email.Value };\n this.view = { ...this.view, Status: 'sending', Problem: '', ProblemCode: '' };\n this.publish({ Author: 'system' });\n const result = await this.service.Request({ Name, Email });\n if (this.view.Status === 'verified') {\n return this.ok('Verified.');\n }\n return result.Success ? this.applySent(result, Name, Email) : this.applySendFailure(result);\n }\n\n private applySent(result: RealtimeSessionVerificationResult, name: string, email: string): RealtimeChannelVerbResult {\n this.sentFor = { Name: name, Email: email };\n this.view = {\n ...this.view,\n Status: 'code_sent',\n Destination: email,\n Problem: '',\n ProblemCode: '',\n SendsRemaining: result.SendsRemaining ?? null,\n AttemptsRemaining: result.AttemptsRemaining ?? null,\n ResendAvailableAt: result.RetryAfterSeconds ? this.now() + result.RetryAfterSeconds * 1000 : 0\n };\n this.publish({ Author: 'system', Event: { Name: 'code_sent', Payload: { email } } });\n return this.ok(`A code was emailed to ${email}. The user can type it in, or open the link in the email. Do not ask them to read the code aloud.`);\n }\n\n private applySendFailure(result: RealtimeSessionVerificationResult): RealtimeChannelVerbResult {\n const problem = this.problemFor(result);\n this.view = {\n ...this.view,\n Status: 'collecting',\n Problem: problem,\n ProblemCode: result.ErrorCode ?? '',\n ResendAvailableAt: result.RetryAfterSeconds ? this.now() + result.RetryAfterSeconds * 1000 : this.view.ResendAvailableAt,\n SendsRemaining: result.SendsRemaining ?? this.view.SendsRemaining\n };\n this.publish({ Author: 'system', Event: { Name: 'error', Payload: { code: result.ErrorCode ?? 'unknown', stage: 'send' } } });\n return this.fail(result.ErrorCode ?? 'verb_failed', problem);\n }\n\n private applyCodeFailure(result: RealtimeSessionVerificationResult): RealtimeChannelVerbResult {\n const problem = this.problemFor(result);\n const code = result.ErrorCode ?? '';\n this.view = {\n ...this.view,\n Status: NEEDS_NEW_CODE.has(code) ? 'collecting' : 'code_sent',\n Problem: problem,\n ProblemCode: code,\n AttemptsRemaining: result.AttemptsRemaining ?? this.view.AttemptsRemaining\n };\n if (NEEDS_NEW_CODE.has(code)) {\n this.sentFor = null;\n }\n this.publish({ Author: 'system', Event: { Name: 'error', Payload: { code: code || 'unknown', stage: 'code' } } });\n return this.fail(code || 'verb_failed', problem);\n }\n\n private applyVerifiedFromResult(result: RealtimeSessionVerificationResult): RealtimeChannelVerbResult {\n const email = result.VerifiedEmail ?? this.view.Email.Value;\n this.MarkVerified({\n VerifiedEmail: email,\n VerifiedName: this.view.Name.Value,\n VerifiedAt: result.VerifiedAt ?? new Date(this.now()).toISOString(),\n Method: 'code',\n ...(result.MaxSessionDeadlineIso ? { MaxSessionDeadlineIso: result.MaxSessionDeadlineIso } : {})\n });\n return this.ok('Verified.');\n }\n\n /** Why a send must not go ahead, as a ready-made failure; `null` when it may. */\n private blockReasonForSend(verb: 'submit' | 'resend'): RealtimeChannelVerbResult | null {\n const v = this.view;\n if (v.Status === 'verified') {\n return this.fail('already_verified', 'This person is already verified.');\n }\n if (v.Status === 'sending' || v.Status === 'verifying') {\n return this.fail('verb_failed', 'A request is in progress; wait for it to finish.');\n }\n if (verb === 'submit' && v.Status === 'code_sent') {\n return this.fail('verb_failed', 'A code was already sent to this address. Wait for the user to enter it, or use resend.');\n }\n if (v.Name.Value.length === 0 || v.Email.Value.length === 0) {\n return this.fail('verb_failed', 'Both the name and the email are needed first. Fill in what is missing.');\n }\n if (!v.Name.Confirmed || !v.Email.Confirmed) {\n return this.fail('verb_failed', 'The user has not confirmed their details yet. Ask them to check the form and confirm; you cannot confirm for them.');\n }\n if (v.SendsRemaining === 0) {\n return this.fail('send_limit_reached', DEFAULT_PROBLEMS['send_limit_reached']);\n }\n const wait = v.ResendAvailableAt - this.now();\n if (wait > 0) {\n return this.fail('rate_limited', `Another code can be sent in ${Math.ceil(wait / 1000)} seconds.`);\n }\n return null;\n }\n\n /** A change to the values a code was sent for makes that code stale: back to collecting. */\n private dropStaleCodeIfChanged(): void {\n if (this.sentFor && (this.sentFor.Name !== this.view.Name.Value || this.sentFor.Email !== this.view.Email.Value)) {\n this.sentFor = null;\n this.view = { ...this.view, Destination: '', AttemptsRemaining: null };\n }\n }\n\n private setField(field: IdentityField, value: string, source: IdentityFieldSource): void {\n const next: IdentityFieldView = { Value: value, Source: source, Confirmed: source === 'user' };\n this.view = { ...this.view, [this.key(field)]: next };\n }\n\n private setConfirmed(field: IdentityField): void {\n const key = this.key(field);\n this.view = { ...this.view, [key]: { ...this.view[key], Confirmed: true } };\n }\n\n private key(field: IdentityField): 'Name' | 'Email' {\n return field === 'name' ? 'Name' : 'Email';\n }\n\n private readField(raw: unknown): IdentityField | null {\n return raw === 'name' || raw === 'email' ? raw : null;\n }\n\n private problemFor(result: RealtimeSessionVerificationResult): string {\n return (result.Message && result.Message.trim()) || DEFAULT_PROBLEMS[result.ErrorCode ?? ''] || 'Something went wrong. Please try again.';\n }\n\n private ok(message: string, extra: JSONObject = {}): RealtimeChannelVerbResult {\n return { Success: true, Result: { message, status: this.view.Status, ...extra } };\n }\n\n private fail(code: string, message: string): RealtimeChannelVerbResult {\n return { Success: false, ErrorCode: code, Error: message };\n }\n\n private initialView(): IdentityVerificationView {\n return {\n Status: 'collecting',\n Name: emptyField(),\n Email: emptyField(),\n Problem: '',\n ProblemCode: '',\n CanSubmit: false,\n ResendAvailableAt: 0,\n SendsRemaining: null,\n AttemptsRemaining: null,\n Destination: ''\n };\n }\n\n /** Recomputes the derived flag, publishes the snapshot, and tells the channel. */\n private publish(change: IdentityVerificationChange): void {\n const v = this.view;\n this.view = {\n ...v,\n CanSubmit: v.Status === 'collecting' && v.Name.Value.length > 0 && v.Email.Value.length > 0 && v.Name.Confirmed && v.Email.Confirmed\n };\n this.viewSubject.next(this.view);\n this.changeListener?.(change);\n }\n}\n"]}