@memberjunction/ng-conversations 5.43.0 → 5.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (405) hide show
  1. package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts +0 -1
  2. package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts.map +1 -1
  3. package/dist/lib/components/active-tasks/active-tasks-panel.component.js +56 -52
  4. package/dist/lib/components/active-tasks/active-tasks-panel.component.js.map +1 -1
  5. package/dist/lib/components/artifact/artifact-share-modal.component.d.ts +3 -1
  6. package/dist/lib/components/artifact/artifact-share-modal.component.d.ts.map +1 -1
  7. package/dist/lib/components/artifact/artifact-share-modal.component.js +52 -52
  8. package/dist/lib/components/artifact/artifact-share-modal.component.js.map +1 -1
  9. package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
  10. package/dist/lib/components/collection/collection-form-modal.component.js +10 -14
  11. package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
  12. package/dist/lib/components/collection/collection-share-modal.component.d.ts +3 -1
  13. package/dist/lib/components/collection/collection-share-modal.component.d.ts.map +1 -1
  14. package/dist/lib/components/collection/collection-share-modal.component.js +56 -56
  15. package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -1
  16. package/dist/lib/components/collection/collection-tree.component.d.ts +3 -1
  17. package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
  18. package/dist/lib/components/collection/collection-tree.component.js +10 -7
  19. package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
  20. package/dist/lib/components/collection/collection-view.component.d.ts +3 -1
  21. package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
  22. package/dist/lib/components/collection/collection-view.component.js +29 -41
  23. package/dist/lib/components/collection/collection-view.component.js.map +1 -1
  24. package/dist/lib/components/collection/collections-full-view.component.d.ts +4 -0
  25. package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
  26. package/dist/lib/components/collection/collections-full-view.component.js +134 -166
  27. package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
  28. package/dist/lib/components/composer/ai-composer.component.d.ts +103 -0
  29. package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -0
  30. package/dist/lib/components/composer/ai-composer.component.js +263 -0
  31. package/dist/lib/components/composer/ai-composer.component.js.map +1 -0
  32. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +76 -12
  33. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  34. package/dist/lib/components/conversation/conversation-chat-area.component.js +522 -158
  35. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  36. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +1 -1
  37. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
  38. package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
  39. package/dist/lib/components/conversation/pinned-messages-panel.component.js +6 -9
  40. package/dist/lib/components/conversation/pinned-messages-panel.component.js.map +1 -1
  41. package/dist/lib/components/library/library-full-view.component.d.ts.map +1 -1
  42. package/dist/lib/components/library/library-full-view.component.js +20 -24
  43. package/dist/lib/components/library/library-full-view.component.js.map +1 -1
  44. package/dist/lib/components/members/members-modal.component.d.ts.map +1 -1
  45. package/dist/lib/components/members/members-modal.component.js +10 -11
  46. package/dist/lib/components/members/members-modal.component.js.map +1 -1
  47. package/dist/lib/components/message/message-input.component.d.ts +87 -23
  48. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  49. package/dist/lib/components/message/message-input.component.js +245 -158
  50. package/dist/lib/components/message/message-input.component.js.map +1 -1
  51. package/dist/lib/components/message/message-item.component.d.ts +11 -3
  52. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  53. package/dist/lib/components/message/message-item.component.js +73 -21
  54. package/dist/lib/components/message/message-item.component.js.map +1 -1
  55. package/dist/lib/components/message/message-list.component.js +6 -9
  56. package/dist/lib/components/message/message-list.component.js.map +1 -1
  57. package/dist/lib/components/overlay/chat-overlay.component.d.ts +4 -1
  58. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  59. package/dist/lib/components/overlay/chat-overlay.component.js +9 -4
  60. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  61. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +45 -0
  62. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +1 -1
  63. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +10 -0
  64. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +1 -1
  65. package/dist/lib/components/realtime/channels/client-context-channel.d.ts +46 -0
  66. package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -0
  67. package/dist/lib/components/realtime/channels/client-context-channel.js +174 -0
  68. package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -0
  69. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.d.ts +123 -0
  70. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.d.ts.map +1 -0
  71. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js +397 -0
  72. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js.map +1 -0
  73. package/dist/lib/components/realtime/media/media-channel-state.d.ts +103 -0
  74. package/dist/lib/components/realtime/media/media-channel-state.d.ts.map +1 -0
  75. package/dist/lib/components/realtime/media/media-channel-state.js +143 -0
  76. package/dist/lib/components/realtime/media/media-channel-state.js.map +1 -0
  77. package/dist/lib/components/realtime/media/media-channel-tools.d.ts +24 -0
  78. package/dist/lib/components/realtime/media/media-channel-tools.d.ts.map +1 -0
  79. package/dist/lib/components/realtime/media/media-channel-tools.js +107 -0
  80. package/dist/lib/components/realtime/media/media-channel-tools.js.map +1 -0
  81. package/dist/lib/components/realtime/media/media-channel.d.ts +89 -0
  82. package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -0
  83. package/dist/lib/components/realtime/media/media-channel.js +253 -0
  84. package/dist/lib/components/realtime/media/media-channel.js.map +1 -0
  85. package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts +141 -0
  86. package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts.map +1 -0
  87. package/dist/lib/components/realtime/media/realtime-media-surface.component.js +574 -0
  88. package/dist/lib/components/realtime/media/realtime-media-surface.component.js.map +1 -0
  89. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +59 -14
  90. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -1
  91. package/dist/lib/components/realtime/realtime-activity-rail.component.js +277 -74
  92. package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
  93. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +28 -27
  94. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  95. package/dist/lib/components/realtime/realtime-agent-banner.component.js +144 -143
  96. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  97. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +12 -0
  98. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
  99. package/dist/lib/components/realtime/realtime-agent-picker.component.js +105 -43
  100. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
  101. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +2 -2
  102. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -1
  103. package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -1
  104. package/dist/lib/components/realtime/realtime-composer.component.d.ts +41 -7
  105. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
  106. package/dist/lib/components/realtime/realtime-composer.component.js +216 -102
  107. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  108. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +0 -2
  109. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -1
  110. package/dist/lib/components/realtime/realtime-delegation-card.component.js +67 -71
  111. package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
  112. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +364 -44
  113. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  114. package/dist/lib/components/realtime/realtime-session-overlay.component.js +839 -153
  115. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  116. package/dist/lib/components/realtime/realtime-session-state.d.ts +5 -5
  117. package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -1
  118. package/dist/lib/components/realtime/realtime-session-state.js.map +1 -1
  119. package/dist/lib/components/realtime/realtime-surface-tab-style.d.ts +70 -0
  120. package/dist/lib/components/realtime/realtime-surface-tab-style.d.ts.map +1 -0
  121. package/dist/lib/components/realtime/realtime-surface-tab-style.js +115 -0
  122. package/dist/lib/components/realtime/realtime-surface-tab-style.js.map +1 -0
  123. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +55 -57
  124. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
  125. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +165 -143
  126. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
  127. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +80 -71
  128. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
  129. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +83 -113
  130. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
  131. package/dist/lib/components/realtime/realtime-ui-config.d.ts +270 -0
  132. package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -0
  133. package/dist/lib/components/realtime/realtime-ui-config.js +212 -0
  134. package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -0
  135. package/dist/lib/components/search/search-panel.component.d.ts +2 -0
  136. package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
  137. package/dist/lib/components/search/search-panel.component.js +92 -101
  138. package/dist/lib/components/search/search-panel.component.js.map +1 -1
  139. package/dist/lib/components/share/share-modal.component.d.ts.map +1 -1
  140. package/dist/lib/components/share/share-modal.component.js +10 -11
  141. package/dist/lib/components/share/share-modal.component.js.map +1 -1
  142. package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -1
  143. package/dist/lib/components/shared/user-picker.component.js +12 -15
  144. package/dist/lib/components/shared/user-picker.component.js.map +1 -1
  145. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +11 -3
  146. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
  147. package/dist/lib/components/sidebar/conversation-sidebar.component.js +34 -10
  148. package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
  149. package/dist/lib/components/sidebar/routines-section.component.d.ts +73 -0
  150. package/dist/lib/components/sidebar/routines-section.component.d.ts.map +1 -0
  151. package/dist/lib/components/sidebar/routines-section.component.js +211 -0
  152. package/dist/lib/components/sidebar/routines-section.component.js.map +1 -0
  153. package/dist/lib/components/tasks/tasks-dropdown.component.d.ts +12 -0
  154. package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
  155. package/dist/lib/components/tasks/tasks-dropdown.component.js +37 -1
  156. package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
  157. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +16 -5
  158. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  159. package/dist/lib/components/workspace/conversation-workspace.component.js +51 -31
  160. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  161. package/dist/lib/composer-plugins/agent-mention.provider.d.ts +16 -0
  162. package/dist/lib/composer-plugins/agent-mention.provider.d.ts.map +1 -0
  163. package/dist/lib/composer-plugins/agent-mention.provider.js +28 -0
  164. package/dist/lib/composer-plugins/agent-mention.provider.js.map +1 -0
  165. package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts +20 -0
  166. package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts.map +1 -0
  167. package/dist/lib/composer-plugins/base-conversation-mention.provider.js +32 -0
  168. package/dist/lib/composer-plugins/base-conversation-mention.provider.js.map +1 -0
  169. package/dist/lib/composer-plugins/load-composer-plugins.d.ts +9 -0
  170. package/dist/lib/composer-plugins/load-composer-plugins.d.ts.map +1 -0
  171. package/dist/lib/composer-plugins/load-composer-plugins.js +17 -0
  172. package/dist/lib/composer-plugins/load-composer-plugins.js.map +1 -0
  173. package/dist/lib/composer-plugins/record-mention.provider.d.ts +14 -0
  174. package/dist/lib/composer-plugins/record-mention.provider.d.ts.map +1 -0
  175. package/dist/lib/composer-plugins/record-mention.provider.js +26 -0
  176. package/dist/lib/composer-plugins/record-mention.provider.js.map +1 -0
  177. package/dist/lib/composer-plugins/skill-command.provider.d.ts +15 -0
  178. package/dist/lib/composer-plugins/skill-command.provider.d.ts.map +1 -0
  179. package/dist/lib/composer-plugins/skill-command.provider.js +27 -0
  180. package/dist/lib/composer-plugins/skill-command.provider.js.map +1 -0
  181. package/dist/lib/conversations.module.d.ts +68 -64
  182. package/dist/lib/conversations.module.d.ts.map +1 -1
  183. package/dist/lib/conversations.module.js +69 -18
  184. package/dist/lib/conversations.module.js.map +1 -1
  185. package/dist/lib/models/conversation-state.model.d.ts +6 -3
  186. package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
  187. package/dist/lib/models/conversation-state.model.js.map +1 -1
  188. package/dist/lib/services/conversation-agent.service.d.ts +9 -2
  189. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  190. package/dist/lib/services/conversation-agent.service.js +26 -2
  191. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  192. package/dist/lib/services/conversation-attachment.service.d.ts +1 -1
  193. package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
  194. package/dist/lib/services/conversation-attachment.service.js.map +1 -1
  195. package/dist/lib/services/mention-autocomplete.service.d.ts +42 -19
  196. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  197. package/dist/lib/services/mention-autocomplete.service.js +113 -18
  198. package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
  199. package/dist/lib/services/realtime-audio-recorder.d.ts +143 -0
  200. package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -0
  201. package/dist/lib/services/realtime-audio-recorder.js +379 -0
  202. package/dist/lib/services/realtime-audio-recorder.js.map +1 -0
  203. package/dist/lib/services/realtime-pcm-wav.d.ts +75 -0
  204. package/dist/lib/services/realtime-pcm-wav.d.ts.map +1 -0
  205. package/dist/lib/services/realtime-pcm-wav.js +205 -0
  206. package/dist/lib/services/realtime-pcm-wav.js.map +1 -0
  207. package/dist/lib/services/realtime-session-review.service.d.ts +28 -1
  208. package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -1
  209. package/dist/lib/services/realtime-session-review.service.js +12 -3
  210. package/dist/lib/services/realtime-session-review.service.js.map +1 -1
  211. package/dist/lib/services/realtime-session.service.d.ts +210 -20
  212. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  213. package/dist/lib/services/realtime-session.service.js +452 -21
  214. package/dist/lib/services/realtime-session.service.js.map +1 -1
  215. package/dist/lib/services/realtime-sessions-adapter.js +1 -1
  216. package/dist/lib/services/realtime-sessions-adapter.js.map +1 -1
  217. package/dist/lib/services/ui-command-handler.service.d.ts +7 -2
  218. package/dist/lib/services/ui-command-handler.service.d.ts.map +1 -1
  219. package/dist/lib/services/ui-command-handler.service.js +6 -2
  220. package/dist/lib/services/ui-command-handler.service.js.map +1 -1
  221. package/dist/lib/utils/plan-mode-preference.d.ts +62 -0
  222. package/dist/lib/utils/plan-mode-preference.d.ts.map +1 -0
  223. package/dist/lib/utils/plan-mode-preference.js +130 -0
  224. package/dist/lib/utils/plan-mode-preference.js.map +1 -0
  225. package/dist/public-api.d.ts +29 -3
  226. package/dist/public-api.d.ts.map +1 -1
  227. package/dist/public-api.js +46 -3
  228. package/dist/public-api.js.map +1 -1
  229. package/package.json +30 -26
  230. package/dist/__tests__/attachment-badge.test.d.ts +0 -2
  231. package/dist/__tests__/attachment-badge.test.d.ts.map +0 -1
  232. package/dist/__tests__/attachment-badge.test.js +0 -66
  233. package/dist/__tests__/attachment-badge.test.js.map +0 -1
  234. package/dist/__tests__/channel-optional-surface.test.d.ts +0 -2
  235. package/dist/__tests__/channel-optional-surface.test.d.ts.map +0 -1
  236. package/dist/__tests__/channel-optional-surface.test.js +0 -53
  237. package/dist/__tests__/channel-optional-surface.test.js.map +0 -1
  238. package/dist/__tests__/chat-events.test.d.ts +0 -14
  239. package/dist/__tests__/chat-events.test.d.ts.map +0 -1
  240. package/dist/__tests__/chat-events.test.js +0 -109
  241. package/dist/__tests__/chat-events.test.js.map +0 -1
  242. package/dist/__tests__/collections-full-view.test.d.ts +0 -2
  243. package/dist/__tests__/collections-full-view.test.d.ts.map +0 -1
  244. package/dist/__tests__/collections-full-view.test.js +0 -225
  245. package/dist/__tests__/collections-full-view.test.js.map +0 -1
  246. package/dist/__tests__/conversation-cache.test.d.ts +0 -2
  247. package/dist/__tests__/conversation-cache.test.d.ts.map +0 -1
  248. package/dist/__tests__/conversation-cache.test.js +0 -233
  249. package/dist/__tests__/conversation-cache.test.js.map +0 -1
  250. package/dist/__tests__/conversation-naming.test.d.ts +0 -2
  251. package/dist/__tests__/conversation-naming.test.d.ts.map +0 -1
  252. package/dist/__tests__/conversation-naming.test.js +0 -110
  253. package/dist/__tests__/conversation-naming.test.js.map +0 -1
  254. package/dist/__tests__/delegation-result-parser.test.d.ts +0 -2
  255. package/dist/__tests__/delegation-result-parser.test.d.ts.map +0 -1
  256. package/dist/__tests__/delegation-result-parser.test.js +0 -107
  257. package/dist/__tests__/delegation-result-parser.test.js.map +0 -1
  258. package/dist/__tests__/distinct-artifacts.test.d.ts +0 -2
  259. package/dist/__tests__/distinct-artifacts.test.d.ts.map +0 -1
  260. package/dist/__tests__/distinct-artifacts.test.js +0 -56
  261. package/dist/__tests__/distinct-artifacts.test.js.map +0 -1
  262. package/dist/__tests__/event-wiring.test.d.ts +0 -15
  263. package/dist/__tests__/event-wiring.test.d.ts.map +0 -1
  264. package/dist/__tests__/event-wiring.test.js +0 -100
  265. package/dist/__tests__/event-wiring.test.js.map +0 -1
  266. package/dist/__tests__/index.test.d.ts +0 -2
  267. package/dist/__tests__/index.test.d.ts.map +0 -1
  268. package/dist/__tests__/index.test.js +0 -7
  269. package/dist/__tests__/index.test.js.map +0 -1
  270. package/dist/__tests__/narration-template.test.d.ts +0 -2
  271. package/dist/__tests__/narration-template.test.d.ts.map +0 -1
  272. package/dist/__tests__/narration-template.test.js +0 -76
  273. package/dist/__tests__/narration-template.test.js.map +0 -1
  274. package/dist/__tests__/notification-model.test.d.ts +0 -2
  275. package/dist/__tests__/notification-model.test.d.ts.map +0 -1
  276. package/dist/__tests__/notification-model.test.js +0 -68
  277. package/dist/__tests__/notification-model.test.js.map +0 -1
  278. package/dist/__tests__/realtime-agent-picker-models.test.d.ts +0 -2
  279. package/dist/__tests__/realtime-agent-picker-models.test.d.ts.map +0 -1
  280. package/dist/__tests__/realtime-agent-picker-models.test.js +0 -49
  281. package/dist/__tests__/realtime-agent-picker-models.test.js.map +0 -1
  282. package/dist/__tests__/realtime-audio-visuals.test.d.ts +0 -2
  283. package/dist/__tests__/realtime-audio-visuals.test.d.ts.map +0 -1
  284. package/dist/__tests__/realtime-audio-visuals.test.js +0 -123
  285. package/dist/__tests__/realtime-audio-visuals.test.js.map +0 -1
  286. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts +0 -2
  287. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts.map +0 -1
  288. package/dist/__tests__/realtime-delegation-card-cancel.test.js +0 -48
  289. package/dist/__tests__/realtime-delegation-card-cancel.test.js.map +0 -1
  290. package/dist/__tests__/realtime-disclosure.test.d.ts +0 -2
  291. package/dist/__tests__/realtime-disclosure.test.d.ts.map +0 -1
  292. package/dist/__tests__/realtime-disclosure.test.js +0 -164
  293. package/dist/__tests__/realtime-disclosure.test.js.map +0 -1
  294. package/dist/__tests__/realtime-pairing.test.d.ts +0 -2
  295. package/dist/__tests__/realtime-pairing.test.d.ts.map +0 -1
  296. package/dist/__tests__/realtime-pairing.test.js +0 -207
  297. package/dist/__tests__/realtime-pairing.test.js.map +0 -1
  298. package/dist/__tests__/realtime-review-lifecycle.test.d.ts +0 -2
  299. package/dist/__tests__/realtime-review-lifecycle.test.d.ts.map +0 -1
  300. package/dist/__tests__/realtime-review-lifecycle.test.js +0 -154
  301. package/dist/__tests__/realtime-review-lifecycle.test.js.map +0 -1
  302. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts +0 -2
  303. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts.map +0 -1
  304. package/dist/__tests__/realtime-session-cancel-usage.test.js +0 -230
  305. package/dist/__tests__/realtime-session-cancel-usage.test.js.map +0 -1
  306. package/dist/__tests__/realtime-session-channels.test.d.ts +0 -2
  307. package/dist/__tests__/realtime-session-channels.test.d.ts.map +0 -1
  308. package/dist/__tests__/realtime-session-channels.test.js +0 -252
  309. package/dist/__tests__/realtime-session-channels.test.js.map +0 -1
  310. package/dist/__tests__/realtime-session-client-tools.test.d.ts +0 -2
  311. package/dist/__tests__/realtime-session-client-tools.test.d.ts.map +0 -1
  312. package/dist/__tests__/realtime-session-client-tools.test.js +0 -103
  313. package/dist/__tests__/realtime-session-client-tools.test.js.map +0 -1
  314. package/dist/__tests__/realtime-session-minimized.test.d.ts +0 -2
  315. package/dist/__tests__/realtime-session-minimized.test.d.ts.map +0 -1
  316. package/dist/__tests__/realtime-session-minimized.test.js +0 -32
  317. package/dist/__tests__/realtime-session-minimized.test.js.map +0 -1
  318. package/dist/__tests__/realtime-session-mint.test.d.ts +0 -2
  319. package/dist/__tests__/realtime-session-mint.test.d.ts.map +0 -1
  320. package/dist/__tests__/realtime-session-mint.test.js +0 -69
  321. package/dist/__tests__/realtime-session-mint.test.js.map +0 -1
  322. package/dist/__tests__/realtime-session-policy.test.d.ts +0 -2
  323. package/dist/__tests__/realtime-session-policy.test.d.ts.map +0 -1
  324. package/dist/__tests__/realtime-session-policy.test.js +0 -303
  325. package/dist/__tests__/realtime-session-policy.test.js.map +0 -1
  326. package/dist/__tests__/realtime-session-review.service.test.d.ts +0 -2
  327. package/dist/__tests__/realtime-session-review.service.test.d.ts.map +0 -1
  328. package/dist/__tests__/realtime-session-review.service.test.js +0 -743
  329. package/dist/__tests__/realtime-session-review.service.test.js.map +0 -1
  330. package/dist/__tests__/realtime-session-state.test.d.ts +0 -2
  331. package/dist/__tests__/realtime-session-state.test.d.ts.map +0 -1
  332. package/dist/__tests__/realtime-session-state.test.js +0 -83
  333. package/dist/__tests__/realtime-session-state.test.js.map +0 -1
  334. package/dist/__tests__/realtime-session-timeline-card.test.d.ts +0 -2
  335. package/dist/__tests__/realtime-session-timeline-card.test.d.ts.map +0 -1
  336. package/dist/__tests__/realtime-session-timeline-card.test.js +0 -106
  337. package/dist/__tests__/realtime-session-timeline-card.test.js.map +0 -1
  338. package/dist/__tests__/realtime-session-timeline.test.d.ts +0 -2
  339. package/dist/__tests__/realtime-session-timeline.test.d.ts.map +0 -1
  340. package/dist/__tests__/realtime-session-timeline.test.js +0 -142
  341. package/dist/__tests__/realtime-session-timeline.test.js.map +0 -1
  342. package/dist/__tests__/realtime-sessions-adapter.test.d.ts +0 -19
  343. package/dist/__tests__/realtime-sessions-adapter.test.d.ts.map +0 -1
  344. package/dist/__tests__/realtime-sessions-adapter.test.js +0 -188
  345. package/dist/__tests__/realtime-sessions-adapter.test.js.map +0 -1
  346. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts +0 -2
  347. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts.map +0 -1
  348. package/dist/__tests__/realtime-surface-panel-prefs.test.js +0 -100
  349. package/dist/__tests__/realtime-surface-panel-prefs.test.js.map +0 -1
  350. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts +0 -2
  351. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts.map +0 -1
  352. package/dist/__tests__/realtime-surface-tabs-model.test.js +0 -193
  353. package/dist/__tests__/realtime-surface-tabs-model.test.js.map +0 -1
  354. package/dist/__tests__/remote-browser-audio-player.test.d.ts +0 -2
  355. package/dist/__tests__/remote-browser-audio-player.test.d.ts.map +0 -1
  356. package/dist/__tests__/remote-browser-audio-player.test.js +0 -137
  357. package/dist/__tests__/remote-browser-audio-player.test.js.map +0 -1
  358. package/dist/__tests__/remote-browser-channel.test.d.ts +0 -2
  359. package/dist/__tests__/remote-browser-channel.test.d.ts.map +0 -1
  360. package/dist/__tests__/remote-browser-channel.test.js +0 -585
  361. package/dist/__tests__/remote-browser-channel.test.js.map +0 -1
  362. package/dist/__tests__/search-service.test.d.ts +0 -2
  363. package/dist/__tests__/search-service.test.d.ts.map +0 -1
  364. package/dist/__tests__/search-service.test.js +0 -114
  365. package/dist/__tests__/search-service.test.js.map +0 -1
  366. package/dist/__tests__/slot-defaults.test.d.ts +0 -24
  367. package/dist/__tests__/slot-defaults.test.d.ts.map +0 -1
  368. package/dist/__tests__/slot-defaults.test.js +0 -63
  369. package/dist/__tests__/slot-defaults.test.js.map +0 -1
  370. package/dist/__tests__/toast-service.test.d.ts +0 -2
  371. package/dist/__tests__/toast-service.test.d.ts.map +0 -1
  372. package/dist/__tests__/toast-service.test.js +0 -143
  373. package/dist/__tests__/toast-service.test.js.map +0 -1
  374. package/dist/__tests__/user-authorization.test.d.ts +0 -2
  375. package/dist/__tests__/user-authorization.test.d.ts.map +0 -1
  376. package/dist/__tests__/user-authorization.test.js +0 -97
  377. package/dist/__tests__/user-authorization.test.js.map +0 -1
  378. package/dist/__tests__/voice-session-narration.test.d.ts +0 -2
  379. package/dist/__tests__/voice-session-narration.test.d.ts.map +0 -1
  380. package/dist/__tests__/voice-session-narration.test.js +0 -609
  381. package/dist/__tests__/voice-session-narration.test.js.map +0 -1
  382. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts +0 -2
  383. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts.map +0 -1
  384. package/dist/__tests__/whiteboard-artifact-viewer.test.js +0 -101
  385. package/dist/__tests__/whiteboard-artifact-viewer.test.js.map +0 -1
  386. package/dist/__tests__/whiteboard-channel.test.d.ts +0 -2
  387. package/dist/__tests__/whiteboard-channel.test.d.ts.map +0 -1
  388. package/dist/__tests__/whiteboard-channel.test.js +0 -260
  389. package/dist/__tests__/whiteboard-channel.test.js.map +0 -1
  390. package/dist/__tests__/whiteboard-restore-state.test.d.ts +0 -2
  391. package/dist/__tests__/whiteboard-restore-state.test.d.ts.map +0 -1
  392. package/dist/__tests__/whiteboard-restore-state.test.js +0 -108
  393. package/dist/__tests__/whiteboard-restore-state.test.js.map +0 -1
  394. package/dist/lib/components/mention/mention-dropdown.component.d.ts +0 -53
  395. package/dist/lib/components/mention/mention-dropdown.component.d.ts.map +0 -1
  396. package/dist/lib/components/mention/mention-dropdown.component.js +0 -276
  397. package/dist/lib/components/mention/mention-dropdown.component.js.map +0 -1
  398. package/dist/lib/components/mention/mention-editor.component.d.ts +0 -256
  399. package/dist/lib/components/mention/mention-editor.component.d.ts.map +0 -1
  400. package/dist/lib/components/mention/mention-editor.component.js +0 -1233
  401. package/dist/lib/components/mention/mention-editor.component.js.map +0 -1
  402. package/dist/lib/components/message/message-input-box.component.d.ts +0 -137
  403. package/dist/lib/components/message/message-input-box.component.d.ts.map +0 -1
  404. package/dist/lib/components/message/message-input-box.component.js +0 -321
  405. package/dist/lib/components/message/message-input-box.component.js.map +0 -1
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @fileoverview Pure, browser-and-node-safe helpers for the CLIENT-DIRECT realtime recorder:
3
+ * encoding accumulated Float32 PCM into a seekable 16-bit PCM **WAV** container and computing a
4
+ * bounded, downsampled waveform **peak** array at capture time.
5
+ *
6
+ * These functions are deliberately free of any browser API (`AudioContext`, `Blob`, …) so they can
7
+ * be unit-tested in a plain Node environment. {@link RealtimeAudioRecorder} owns the live audio
8
+ * graph and feeds the captured samples here.
9
+ *
10
+ * Why WAV (PCM) over webm/opus: a RIFF/WAVE header carries the exact duration and maps a byte
11
+ * offset linearly to a time offset, so HTTP-range seeking is exact (no client-side duration nudge),
12
+ * and peak extraction is trivial. The tradeoff is size — PCM WAV is larger than opus — which is
13
+ * acceptable for these short session recordings.
14
+ *
15
+ * @module @memberjunction/ng-conversations/realtime-pcm-wav
16
+ */
17
+ /** Canonical WAV/PCM header size in bytes (RIFF + fmt + data chunk headers). */
18
+ export declare const WAV_HEADER_BYTES = 44;
19
+ /**
20
+ * Encodes mono Float32 PCM samples as a canonical single-chunk 16-bit PCM WAV (RIFF/WAVE).
21
+ * The returned `ArrayBuffer` is `WAV_HEADER_BYTES + samples.length * 2` bytes — a proper
22
+ * 44-byte header followed by little-endian PCM16 data, so it is seekable and self-describing.
23
+ *
24
+ * @param samples Mono Float32 PCM in `[-1, 1]` (downmixed by the caller).
25
+ * @param sampleRate Sample rate in Hz (from the capturing `AudioContext`).
26
+ * @returns A standalone `ArrayBuffer` containing the full WAV file.
27
+ */
28
+ export declare function encodePcm16Wav(samples: Float32Array, sampleRate: number): ArrayBuffer;
29
+ /**
30
+ * A bounded, streaming waveform-peak accumulator. It maintains a fixed number of buckets
31
+ * (`targetBuckets`) of max-absolute amplitude across the WHOLE recording regardless of length:
32
+ * once every bucket has absorbed `samplesPerBucket` samples, the buckets are halved (pairwise
33
+ * max-merged) and the per-bucket capacity doubles — so memory + cost stay O(targetBuckets) for an
34
+ * arbitrarily long call. {@link Normalize} returns the final 0..1 peaks.
35
+ */
36
+ export declare class PeakAccumulator {
37
+ /** Target (max) number of buckets in the produced peak array. */
38
+ private readonly targetBuckets;
39
+ /** Current max-abs amplitude per bucket (length grows up to `2 * targetBuckets` before folding). */
40
+ private buckets;
41
+ /** How many samples each bucket currently absorbs before a new bucket opens. */
42
+ private samplesPerBucket;
43
+ /** Samples absorbed into the current (last) bucket so far. */
44
+ private samplesInCurrent;
45
+ /**
46
+ * @param targetBuckets Desired bucket count (waveform resolution). Clamped to >= 1.
47
+ * ~600 gives a smooth overview waveform at trivial cost.
48
+ */
49
+ constructor(targetBuckets?: number);
50
+ /** Number of buckets currently held (for tests/inspection). */
51
+ get BucketCount(): number;
52
+ /** Absorbs a block of Float32 PCM samples, updating the running per-bucket max-abs. */
53
+ Push(samples: Float32Array): void;
54
+ /** Absorbs one sample into the current bucket, opening/folding buckets as capacity is reached. */
55
+ private pushSample;
56
+ /** Pairwise max-merges adjacent buckets, halving the count and doubling per-bucket capacity. */
57
+ private fold;
58
+ /**
59
+ * Produces the final normalized peak array (each value 0..1, divided by the global max).
60
+ * Trailing empty buckets are trimmed; an all-silent / empty recording yields `[]`.
61
+ */
62
+ Normalize(): number[];
63
+ }
64
+ /**
65
+ * One-shot peak downsampling of a complete Float32 PCM buffer into `targetBuckets` normalized
66
+ * max-abs peaks (0..1). The streaming {@link PeakAccumulator} is the production path; this is the
67
+ * direct, allocation-light equivalent used where the whole buffer is already in hand (and in tests).
68
+ *
69
+ * @param samples The full mono Float32 PCM buffer.
70
+ * @param targetBuckets Desired bucket count (clamped to >= 1). Buckets beyond the sample count are
71
+ * not produced — a short buffer yields at most `samples.length` peaks.
72
+ * @returns Normalized peaks; `[]` for an empty or all-silent buffer.
73
+ */
74
+ export declare function downsamplePeaks(samples: Float32Array, targetBuckets?: number): number[];
75
+ //# sourceMappingURL=realtime-pcm-wav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-pcm-wav.d.ts","sourceRoot":"","sources":["../../../src/lib/services/realtime-pcm-wav.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAcnC;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAkCrF;AASD;;;;;;GAMG;AACH,qBAAa,eAAe;IACxB,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,oGAAoG;IACpG,OAAO,CAAC,OAAO,CAAgB;IAC/B,gFAAgF;IAChF,OAAO,CAAC,gBAAgB,CAAK;IAC7B,8DAA8D;IAC9D,OAAO,CAAC,gBAAgB,CAAK;IAE7B;;;OAGG;gBACS,aAAa,SAAM;IAI/B,+DAA+D;IAC/D,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED,uFAAuF;IAChF,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAMxC,kGAAkG;IAClG,OAAO,CAAC,UAAU;IAsBlB,gGAAgG;IAChG,OAAO,CAAC,IAAI;IAYZ;;;OAGG;IACI,SAAS,IAAI,MAAM,EAAE;CAgB/B;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,aAAa,SAAM,GAAG,MAAM,EAAE,CA4BpF"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * @fileoverview Pure, browser-and-node-safe helpers for the CLIENT-DIRECT realtime recorder:
3
+ * encoding accumulated Float32 PCM into a seekable 16-bit PCM **WAV** container and computing a
4
+ * bounded, downsampled waveform **peak** array at capture time.
5
+ *
6
+ * These functions are deliberately free of any browser API (`AudioContext`, `Blob`, …) so they can
7
+ * be unit-tested in a plain Node environment. {@link RealtimeAudioRecorder} owns the live audio
8
+ * graph and feeds the captured samples here.
9
+ *
10
+ * Why WAV (PCM) over webm/opus: a RIFF/WAVE header carries the exact duration and maps a byte
11
+ * offset linearly to a time offset, so HTTP-range seeking is exact (no client-side duration nudge),
12
+ * and peak extraction is trivial. The tradeoff is size — PCM WAV is larger than opus — which is
13
+ * acceptable for these short session recordings.
14
+ *
15
+ * @module @memberjunction/ng-conversations/realtime-pcm-wav
16
+ */
17
+ /** Lowest value representable by signed 16-bit PCM. */
18
+ const PCM16_MIN = -32768;
19
+ /** Highest value representable by signed 16-bit PCM. */
20
+ const PCM16_MAX = 32767;
21
+ /** Canonical WAV/PCM header size in bytes (RIFF + fmt + data chunk headers). */
22
+ export const WAV_HEADER_BYTES = 44;
23
+ /**
24
+ * Converts one Float32 sample (nominally in `[-1, 1]`) to a clamped signed 16-bit integer.
25
+ * Out-of-range values (a hot mix can briefly exceed unity) are clamped, not wrapped.
26
+ */
27
+ function floatToPcm16(sample) {
28
+ const clamped = sample < -1 ? -1 : sample > 1 ? 1 : sample;
29
+ // Asymmetric scaling: negative full-scale is -32768, positive is +32767.
30
+ const scaled = clamped < 0 ? clamped * -PCM16_MIN : clamped * PCM16_MAX;
31
+ const rounded = Math.round(scaled);
32
+ return rounded < PCM16_MIN ? PCM16_MIN : rounded > PCM16_MAX ? PCM16_MAX : rounded;
33
+ }
34
+ /**
35
+ * Encodes mono Float32 PCM samples as a canonical single-chunk 16-bit PCM WAV (RIFF/WAVE).
36
+ * The returned `ArrayBuffer` is `WAV_HEADER_BYTES + samples.length * 2` bytes — a proper
37
+ * 44-byte header followed by little-endian PCM16 data, so it is seekable and self-describing.
38
+ *
39
+ * @param samples Mono Float32 PCM in `[-1, 1]` (downmixed by the caller).
40
+ * @param sampleRate Sample rate in Hz (from the capturing `AudioContext`).
41
+ * @returns A standalone `ArrayBuffer` containing the full WAV file.
42
+ */
43
+ export function encodePcm16Wav(samples, sampleRate) {
44
+ const numChannels = 1;
45
+ const bitsPerSample = 16;
46
+ const bytesPerSample = bitsPerSample / 8;
47
+ const blockAlign = numChannels * bytesPerSample;
48
+ const byteRate = sampleRate * blockAlign;
49
+ const dataSize = samples.length * bytesPerSample;
50
+ const buffer = new ArrayBuffer(WAV_HEADER_BYTES + dataSize);
51
+ const view = new DataView(buffer);
52
+ writeAscii(view, 0, 'RIFF');
53
+ view.setUint32(4, 36 + dataSize, true); // ChunkSize = 36 + Subchunk2Size
54
+ writeAscii(view, 8, 'WAVE');
55
+ writeAscii(view, 12, 'fmt ');
56
+ view.setUint32(16, 16, true); // Subchunk1Size (16 for PCM)
57
+ view.setUint16(20, 1, true); // AudioFormat = PCM
58
+ view.setUint16(22, numChannels, true);
59
+ view.setUint32(24, sampleRate, true);
60
+ view.setUint32(28, byteRate, true);
61
+ view.setUint16(32, blockAlign, true);
62
+ view.setUint16(34, bitsPerSample, true);
63
+ writeAscii(view, 36, 'data');
64
+ view.setUint32(40, dataSize, true);
65
+ let offset = WAV_HEADER_BYTES;
66
+ for (let i = 0; i < samples.length; i++) {
67
+ view.setInt16(offset, floatToPcm16(samples[i]), true);
68
+ offset += bytesPerSample;
69
+ }
70
+ return buffer;
71
+ }
72
+ /** Writes an ASCII string into a {@link DataView} byte-by-byte at `offset`. */
73
+ function writeAscii(view, offset, text) {
74
+ for (let i = 0; i < text.length; i++) {
75
+ view.setUint8(offset + i, text.charCodeAt(i));
76
+ }
77
+ }
78
+ /**
79
+ * A bounded, streaming waveform-peak accumulator. It maintains a fixed number of buckets
80
+ * (`targetBuckets`) of max-absolute amplitude across the WHOLE recording regardless of length:
81
+ * once every bucket has absorbed `samplesPerBucket` samples, the buckets are halved (pairwise
82
+ * max-merged) and the per-bucket capacity doubles — so memory + cost stay O(targetBuckets) for an
83
+ * arbitrarily long call. {@link Normalize} returns the final 0..1 peaks.
84
+ */
85
+ export class PeakAccumulator {
86
+ /** Target (max) number of buckets in the produced peak array. */
87
+ targetBuckets;
88
+ /** Current max-abs amplitude per bucket (length grows up to `2 * targetBuckets` before folding). */
89
+ buckets = [];
90
+ /** How many samples each bucket currently absorbs before a new bucket opens. */
91
+ samplesPerBucket = 1;
92
+ /** Samples absorbed into the current (last) bucket so far. */
93
+ samplesInCurrent = 0;
94
+ /**
95
+ * @param targetBuckets Desired bucket count (waveform resolution). Clamped to >= 1.
96
+ * ~600 gives a smooth overview waveform at trivial cost.
97
+ */
98
+ constructor(targetBuckets = 600) {
99
+ this.targetBuckets = Math.max(1, Math.floor(targetBuckets));
100
+ }
101
+ /** Number of buckets currently held (for tests/inspection). */
102
+ get BucketCount() {
103
+ return this.buckets.length;
104
+ }
105
+ /** Absorbs a block of Float32 PCM samples, updating the running per-bucket max-abs. */
106
+ Push(samples) {
107
+ for (let i = 0; i < samples.length; i++) {
108
+ this.pushSample(samples[i]);
109
+ }
110
+ }
111
+ /** Absorbs one sample into the current bucket, opening/folding buckets as capacity is reached. */
112
+ pushSample(sample) {
113
+ if (this.buckets.length === 0) {
114
+ this.buckets.push(0);
115
+ this.samplesInCurrent = 0;
116
+ }
117
+ const abs = sample < 0 ? -sample : sample;
118
+ const last = this.buckets.length - 1;
119
+ if (abs > this.buckets[last]) {
120
+ this.buckets[last] = abs;
121
+ }
122
+ this.samplesInCurrent++;
123
+ if (this.samplesInCurrent >= this.samplesPerBucket) {
124
+ this.buckets.push(0);
125
+ this.samplesInCurrent = 0;
126
+ // Keep the bucket array bounded: once it reaches 2x the target, fold pairwise so the
127
+ // resolution stays under the cap while the per-bucket sample capacity doubles.
128
+ if (this.buckets.length >= this.targetBuckets * 2) {
129
+ this.fold();
130
+ }
131
+ }
132
+ }
133
+ /** Pairwise max-merges adjacent buckets, halving the count and doubling per-bucket capacity. */
134
+ fold() {
135
+ const folded = [];
136
+ for (let i = 0; i < this.buckets.length; i += 2) {
137
+ const a = this.buckets[i];
138
+ const b = i + 1 < this.buckets.length ? this.buckets[i + 1] : 0;
139
+ folded.push(a > b ? a : b);
140
+ }
141
+ this.buckets = folded;
142
+ this.samplesPerBucket *= 2;
143
+ this.samplesInCurrent = 0;
144
+ }
145
+ /**
146
+ * Produces the final normalized peak array (each value 0..1, divided by the global max).
147
+ * Trailing empty buckets are trimmed; an all-silent / empty recording yields `[]`.
148
+ */
149
+ Normalize() {
150
+ // Drop a trailing freshly-opened empty bucket that absorbed nothing.
151
+ const raw = this.buckets.length > 0 && this.samplesInCurrent === 0 && this.buckets.length > 1
152
+ ? this.buckets.slice(0, -1)
153
+ : this.buckets.slice();
154
+ let max = 0;
155
+ for (const v of raw) {
156
+ if (v > max) {
157
+ max = v;
158
+ }
159
+ }
160
+ if (max <= 0) {
161
+ return [];
162
+ }
163
+ return raw.map(v => v / max);
164
+ }
165
+ }
166
+ /**
167
+ * One-shot peak downsampling of a complete Float32 PCM buffer into `targetBuckets` normalized
168
+ * max-abs peaks (0..1). The streaming {@link PeakAccumulator} is the production path; this is the
169
+ * direct, allocation-light equivalent used where the whole buffer is already in hand (and in tests).
170
+ *
171
+ * @param samples The full mono Float32 PCM buffer.
172
+ * @param targetBuckets Desired bucket count (clamped to >= 1). Buckets beyond the sample count are
173
+ * not produced — a short buffer yields at most `samples.length` peaks.
174
+ * @returns Normalized peaks; `[]` for an empty or all-silent buffer.
175
+ */
176
+ export function downsamplePeaks(samples, targetBuckets = 600) {
177
+ const target = Math.max(1, Math.floor(targetBuckets));
178
+ if (samples.length === 0) {
179
+ return [];
180
+ }
181
+ const buckets = Math.min(target, samples.length);
182
+ const samplesPerBucket = samples.length / buckets;
183
+ const peaks = new Array(buckets).fill(0);
184
+ let globalMax = 0;
185
+ for (let b = 0; b < buckets; b++) {
186
+ const start = Math.floor(b * samplesPerBucket);
187
+ const end = b === buckets - 1 ? samples.length : Math.floor((b + 1) * samplesPerBucket);
188
+ let localMax = 0;
189
+ for (let i = start; i < end; i++) {
190
+ const abs = samples[i] < 0 ? -samples[i] : samples[i];
191
+ if (abs > localMax) {
192
+ localMax = abs;
193
+ }
194
+ }
195
+ peaks[b] = localMax;
196
+ if (localMax > globalMax) {
197
+ globalMax = localMax;
198
+ }
199
+ }
200
+ if (globalMax <= 0) {
201
+ return [];
202
+ }
203
+ return peaks.map(v => v / globalMax);
204
+ }
205
+ //# sourceMappingURL=realtime-pcm-wav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-pcm-wav.js","sourceRoot":"","sources":["../../../src/lib/services/realtime-pcm-wav.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Pure, browser-and-node-safe helpers for the CLIENT-DIRECT realtime recorder:\n * encoding accumulated Float32 PCM into a seekable 16-bit PCM **WAV** container and computing a\n * bounded, downsampled waveform **peak** array at capture time.\n *\n * These functions are deliberately free of any browser API (`AudioContext`, `Blob`, …) so they can\n * be unit-tested in a plain Node environment. {@link RealtimeAudioRecorder} owns the live audio\n * graph and feeds the captured samples here.\n *\n * Why WAV (PCM) over webm/opus: a RIFF/WAVE header carries the exact duration and maps a byte\n * offset linearly to a time offset, so HTTP-range seeking is exact (no client-side duration nudge),\n * and peak extraction is trivial. The tradeoff is size — PCM WAV is larger than opus — which is\n * acceptable for these short session recordings.\n *\n * @module @memberjunction/ng-conversations/realtime-pcm-wav\n */\n\n/** Lowest value representable by signed 16-bit PCM. */\nconst PCM16_MIN = -32768;\n/** Highest value representable by signed 16-bit PCM. */\nconst PCM16_MAX = 32767;\n/** Canonical WAV/PCM header size in bytes (RIFF + fmt + data chunk headers). */\nexport const WAV_HEADER_BYTES = 44;\n\n/**\n * Converts one Float32 sample (nominally in `[-1, 1]`) to a clamped signed 16-bit integer.\n * Out-of-range values (a hot mix can briefly exceed unity) are clamped, not wrapped.\n */\nfunction floatToPcm16(sample: number): number {\n const clamped = sample < -1 ? -1 : sample > 1 ? 1 : sample;\n // Asymmetric scaling: negative full-scale is -32768, positive is +32767.\n const scaled = clamped < 0 ? clamped * -PCM16_MIN : clamped * PCM16_MAX;\n const rounded = Math.round(scaled);\n return rounded < PCM16_MIN ? PCM16_MIN : rounded > PCM16_MAX ? PCM16_MAX : rounded;\n}\n\n/**\n * Encodes mono Float32 PCM samples as a canonical single-chunk 16-bit PCM WAV (RIFF/WAVE).\n * The returned `ArrayBuffer` is `WAV_HEADER_BYTES + samples.length * 2` bytes — a proper\n * 44-byte header followed by little-endian PCM16 data, so it is seekable and self-describing.\n *\n * @param samples Mono Float32 PCM in `[-1, 1]` (downmixed by the caller).\n * @param sampleRate Sample rate in Hz (from the capturing `AudioContext`).\n * @returns A standalone `ArrayBuffer` containing the full WAV file.\n */\nexport function encodePcm16Wav(samples: Float32Array, sampleRate: number): ArrayBuffer {\n const numChannels = 1;\n const bitsPerSample = 16;\n const bytesPerSample = bitsPerSample / 8;\n const blockAlign = numChannels * bytesPerSample;\n const byteRate = sampleRate * blockAlign;\n const dataSize = samples.length * bytesPerSample;\n\n const buffer = new ArrayBuffer(WAV_HEADER_BYTES + dataSize);\n const view = new DataView(buffer);\n\n writeAscii(view, 0, 'RIFF');\n view.setUint32(4, 36 + dataSize, true); // ChunkSize = 36 + Subchunk2Size\n writeAscii(view, 8, 'WAVE');\n\n writeAscii(view, 12, 'fmt ');\n view.setUint32(16, 16, true); // Subchunk1Size (16 for PCM)\n view.setUint16(20, 1, true); // AudioFormat = PCM\n view.setUint16(22, numChannels, true);\n view.setUint32(24, sampleRate, true);\n view.setUint32(28, byteRate, true);\n view.setUint16(32, blockAlign, true);\n view.setUint16(34, bitsPerSample, true);\n\n writeAscii(view, 36, 'data');\n view.setUint32(40, dataSize, true);\n\n let offset = WAV_HEADER_BYTES;\n for (let i = 0; i < samples.length; i++) {\n view.setInt16(offset, floatToPcm16(samples[i]), true);\n offset += bytesPerSample;\n }\n\n return buffer;\n}\n\n/** Writes an ASCII string into a {@link DataView} byte-by-byte at `offset`. */\nfunction writeAscii(view: DataView, offset: number, text: string): void {\n for (let i = 0; i < text.length; i++) {\n view.setUint8(offset + i, text.charCodeAt(i));\n }\n}\n\n/**\n * A bounded, streaming waveform-peak accumulator. It maintains a fixed number of buckets\n * (`targetBuckets`) of max-absolute amplitude across the WHOLE recording regardless of length:\n * once every bucket has absorbed `samplesPerBucket` samples, the buckets are halved (pairwise\n * max-merged) and the per-bucket capacity doubles — so memory + cost stay O(targetBuckets) for an\n * arbitrarily long call. {@link Normalize} returns the final 0..1 peaks.\n */\nexport class PeakAccumulator {\n /** Target (max) number of buckets in the produced peak array. */\n private readonly targetBuckets: number;\n /** Current max-abs amplitude per bucket (length grows up to `2 * targetBuckets` before folding). */\n private buckets: number[] = [];\n /** How many samples each bucket currently absorbs before a new bucket opens. */\n private samplesPerBucket = 1;\n /** Samples absorbed into the current (last) bucket so far. */\n private samplesInCurrent = 0;\n\n /**\n * @param targetBuckets Desired bucket count (waveform resolution). Clamped to >= 1.\n * ~600 gives a smooth overview waveform at trivial cost.\n */\n constructor(targetBuckets = 600) {\n this.targetBuckets = Math.max(1, Math.floor(targetBuckets));\n }\n\n /** Number of buckets currently held (for tests/inspection). */\n public get BucketCount(): number {\n return this.buckets.length;\n }\n\n /** Absorbs a block of Float32 PCM samples, updating the running per-bucket max-abs. */\n public Push(samples: Float32Array): void {\n for (let i = 0; i < samples.length; i++) {\n this.pushSample(samples[i]);\n }\n }\n\n /** Absorbs one sample into the current bucket, opening/folding buckets as capacity is reached. */\n private pushSample(sample: number): void {\n if (this.buckets.length === 0) {\n this.buckets.push(0);\n this.samplesInCurrent = 0;\n }\n const abs = sample < 0 ? -sample : sample;\n const last = this.buckets.length - 1;\n if (abs > this.buckets[last]) {\n this.buckets[last] = abs;\n }\n this.samplesInCurrent++;\n if (this.samplesInCurrent >= this.samplesPerBucket) {\n this.buckets.push(0);\n this.samplesInCurrent = 0;\n // Keep the bucket array bounded: once it reaches 2x the target, fold pairwise so the\n // resolution stays under the cap while the per-bucket sample capacity doubles.\n if (this.buckets.length >= this.targetBuckets * 2) {\n this.fold();\n }\n }\n }\n\n /** Pairwise max-merges adjacent buckets, halving the count and doubling per-bucket capacity. */\n private fold(): void {\n const folded: number[] = [];\n for (let i = 0; i < this.buckets.length; i += 2) {\n const a = this.buckets[i];\n const b = i + 1 < this.buckets.length ? this.buckets[i + 1] : 0;\n folded.push(a > b ? a : b);\n }\n this.buckets = folded;\n this.samplesPerBucket *= 2;\n this.samplesInCurrent = 0;\n }\n\n /**\n * Produces the final normalized peak array (each value 0..1, divided by the global max).\n * Trailing empty buckets are trimmed; an all-silent / empty recording yields `[]`.\n */\n public Normalize(): number[] {\n // Drop a trailing freshly-opened empty bucket that absorbed nothing.\n const raw = this.buckets.length > 0 && this.samplesInCurrent === 0 && this.buckets.length > 1\n ? this.buckets.slice(0, -1)\n : this.buckets.slice();\n let max = 0;\n for (const v of raw) {\n if (v > max) {\n max = v;\n }\n }\n if (max <= 0) {\n return [];\n }\n return raw.map(v => v / max);\n }\n}\n\n/**\n * One-shot peak downsampling of a complete Float32 PCM buffer into `targetBuckets` normalized\n * max-abs peaks (0..1). The streaming {@link PeakAccumulator} is the production path; this is the\n * direct, allocation-light equivalent used where the whole buffer is already in hand (and in tests).\n *\n * @param samples The full mono Float32 PCM buffer.\n * @param targetBuckets Desired bucket count (clamped to >= 1). Buckets beyond the sample count are\n * not produced — a short buffer yields at most `samples.length` peaks.\n * @returns Normalized peaks; `[]` for an empty or all-silent buffer.\n */\nexport function downsamplePeaks(samples: Float32Array, targetBuckets = 600): number[] {\n const target = Math.max(1, Math.floor(targetBuckets));\n if (samples.length === 0) {\n return [];\n }\n const buckets = Math.min(target, samples.length);\n const samplesPerBucket = samples.length / buckets;\n const peaks = new Array<number>(buckets).fill(0);\n let globalMax = 0;\n for (let b = 0; b < buckets; b++) {\n const start = Math.floor(b * samplesPerBucket);\n const end = b === buckets - 1 ? samples.length : Math.floor((b + 1) * samplesPerBucket);\n let localMax = 0;\n for (let i = start; i < end; i++) {\n const abs = samples[i] < 0 ? -samples[i] : samples[i];\n if (abs > localMax) {\n localMax = abs;\n }\n }\n peaks[b] = localMax;\n if (localMax > globalMax) {\n globalMax = localMax;\n }\n }\n if (globalMax <= 0) {\n return [];\n }\n return peaks.map(v => v / globalMax);\n}\n"]}
@@ -8,14 +8,31 @@ import * as i0 from "@angular/core";
8
8
  * legacy row was closed before the column existed.
9
9
  */
10
10
  export type RealtimeReviewCloseReason = 'Error' | 'Explicit' | 'Janitor' | 'Shutdown';
11
- /** One historical caption turn of a reviewed session (a persisted `MJ: Conversation Details` row). */
11
+ /**
12
+ * One historical caption turn of a reviewed session (a persisted `MJ: Conversation Details` row).
13
+ *
14
+ * Carries BOTH the thread-rendering fields (`Role`/`Text`/`At`) AND the raw fields the time-aligned
15
+ * evidence player reads (`ID`, `Message`, `__mj_CreatedAt`, `UtteranceStartMs`, `UtteranceEndMs`) so
16
+ * a review's turns can be handed straight to {@link RealtimeEvidencePlaybackComponent} for the
17
+ * Recording tab — this shape structurally satisfies that player's `EvidencePlaybackTurn` input.
18
+ */
12
19
  export interface RealtimeSessionReviewTurn {
20
+ /** `MJ: Conversation Details.ID` — the player's `@for` track key. */
21
+ ID: string;
13
22
  /** Who spoke the turn. Persisted `AI` rows map to `Assistant`. */
14
23
  Role: 'User' | 'Assistant';
15
24
  /** The transcript text. */
16
25
  Text: string;
26
+ /** The raw transcript text (mirrors {@link Text}) — the player reads `Message`. */
27
+ Message: string | null;
28
+ /** When the turn was persisted (`__mj_CreatedAt`), or null when unknown. Aliases {@link At}. */
29
+ __mj_CreatedAt: Date | null;
17
30
  /** When the turn was persisted (`__mj_CreatedAt`), or null when unknown. */
18
31
  At: Date | null;
32
+ /** Precise media-relative start (ms from recording t0), or null when the driver supplied no timing. */
33
+ UtteranceStartMs: number | null;
34
+ /** Precise media-relative end (ms from recording t0), or null. */
35
+ UtteranceEndMs: number | null;
19
36
  }
20
37
  /**
21
38
  * A compact preview of one DELEGATED agent run the reviewed session spawned (an
@@ -108,6 +125,16 @@ export interface RealtimeSessionReview {
108
125
  StartedAt: Date | null;
109
126
  LastActiveAt: Date | null;
110
127
  ClosedAt: Date | null;
128
+ /**
129
+ * The `MJ: Files` id of the reviewed session's recorded audio, or null when nothing was recorded.
130
+ * When set, review mode resolves a signed download URL and shows a Recording tab with the
131
+ * time-aligned evidence player. From the PRIMARY (reviewed) leg only.
132
+ */
133
+ RecordingFileID: string | null;
134
+ /** Recording alignment origin (t0), used by the playback transcript sync. From the primary leg. */
135
+ RecordingStartedAt: Date | null;
136
+ /** What was captured (`Audio` / `AudioVideo`), or null. From the primary leg. */
137
+ RecordingMedia: string | null;
111
138
  /** Chronological caption turns (oldest first) — ALL legs of the chain, flattened. */
112
139
  Turns: RealtimeSessionReviewTurn[];
113
140
  /** Delegated run previews (oldest first, all legs), minus each leg's co-agent observability run. */
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-session-review.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/realtime-session-review.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"realtime-session-review.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/realtime-session-review.service.ts"],"names":[],"mappings":"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"}
@@ -33,8 +33,8 @@ export function MergeChainChannelStates(legChannelStates) {
33
33
  }
34
34
  return [...byName.values()];
35
35
  }
36
- const SESSION_FIELDS = ['ID', 'AgentID', 'Agent', 'Status', 'ConversationID', 'Config', 'LastSessionID', 'LastActiveAt', 'ClosedAt', 'CloseReason', '__mj_CreatedAt'];
37
- const DETAIL_FIELDS = ['ID', 'Role', 'Message', 'HiddenToUser', '__mj_CreatedAt'];
36
+ const SESSION_FIELDS = ['ID', 'AgentID', 'Agent', 'Status', 'ConversationID', 'Config', 'LastSessionID', 'LastActiveAt', 'ClosedAt', 'CloseReason', 'RecordingFileID', 'RecordingStartedAt', 'RecordingMedia', '__mj_CreatedAt'];
37
+ const DETAIL_FIELDS = ['ID', 'Role', 'Message', 'HiddenToUser', 'UserID', 'Status', 'UtteranceStartMs', 'UtteranceEndMs', '__mj_CreatedAt'];
38
38
  const RUN_FIELDS = ['ID', 'AgentID', 'Agent', 'Status', 'Success', 'Message', 'ErrorMessage', 'FinalStep', 'StartedAt', 'CompletedAt'];
39
39
  const CHANNEL_FIELDS = ['ID', 'Channel', 'Config'];
40
40
  const JUNCTION_FIELDS = ['ID', 'ConversationDetailID', 'ArtifactVersionID'];
@@ -326,6 +326,9 @@ export class RealtimeSessionReviewService {
326
326
  StartedAt: this.toDate(session.__mj_CreatedAt),
327
327
  LastActiveAt: this.toDate(session.LastActiveAt),
328
328
  ClosedAt: this.toDate(session.ClosedAt),
329
+ RecordingFileID: session.RecordingFileID ?? null,
330
+ RecordingStartedAt: this.toDate(session.RecordingStartedAt),
331
+ RecordingMedia: session.RecordingMedia ?? null,
329
332
  Turns: legs.flatMap(l => l.Turns),
330
333
  DelegatedRuns: legs.flatMap(l => l.DelegatedRuns),
331
334
  // Multi-leg: newest leg with a SAVED state wins per channel — a final leg that
@@ -355,10 +358,16 @@ export class RealtimeSessionReviewService {
355
358
  if (row.HiddenToUser || text.length === 0 || (row.Role !== 'User' && row.Role !== 'AI')) {
356
359
  continue;
357
360
  }
361
+ const createdAt = this.toDate(row.__mj_CreatedAt);
358
362
  turns.push({
363
+ ID: row.ID,
359
364
  Role: row.Role === 'AI' ? 'Assistant' : 'User',
360
365
  Text: text,
361
- At: this.toDate(row.__mj_CreatedAt)
366
+ Message: text,
367
+ __mj_CreatedAt: createdAt,
368
+ At: createdAt,
369
+ UtteranceStartMs: row.UtteranceStartMs ?? null,
370
+ UtteranceEndMs: row.UtteranceEndMs ?? null
362
371
  });
363
372
  }
364
373
  return turns;