@memberjunction/ng-conversations 5.43.0 → 5.44.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 (351) 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.js +37 -41
  6. package/dist/lib/components/artifact/artifact-share-modal.component.js.map +1 -1
  7. package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
  8. package/dist/lib/components/collection/collection-form-modal.component.js +10 -14
  9. package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
  10. package/dist/lib/components/collection/collection-share-modal.component.js +41 -45
  11. package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -1
  12. package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
  13. package/dist/lib/components/collection/collection-view.component.js +22 -36
  14. package/dist/lib/components/collection/collection-view.component.js.map +1 -1
  15. package/dist/lib/components/collection/collections-full-view.component.d.ts +4 -0
  16. package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
  17. package/dist/lib/components/collection/collections-full-view.component.js +134 -166
  18. package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
  19. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +73 -8
  20. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  21. package/dist/lib/components/conversation/conversation-chat-area.component.js +487 -123
  22. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  23. package/dist/lib/components/conversation/pinned-messages-panel.component.js +6 -9
  24. package/dist/lib/components/conversation/pinned-messages-panel.component.js.map +1 -1
  25. package/dist/lib/components/library/library-full-view.component.d.ts.map +1 -1
  26. package/dist/lib/components/library/library-full-view.component.js +20 -24
  27. package/dist/lib/components/library/library-full-view.component.js.map +1 -1
  28. package/dist/lib/components/members/members-modal.component.d.ts.map +1 -1
  29. package/dist/lib/components/members/members-modal.component.js +10 -11
  30. package/dist/lib/components/members/members-modal.component.js.map +1 -1
  31. package/dist/lib/components/mention/mention-dropdown.component.js +49 -28
  32. package/dist/lib/components/mention/mention-dropdown.component.js.map +1 -1
  33. package/dist/lib/components/mention/mention-editor.component.d.ts.map +1 -1
  34. package/dist/lib/components/mention/mention-editor.component.js +24 -10
  35. package/dist/lib/components/mention/mention-editor.component.js.map +1 -1
  36. package/dist/lib/components/message/message-input-box.component.d.ts +11 -16
  37. package/dist/lib/components/message/message-input-box.component.d.ts.map +1 -1
  38. package/dist/lib/components/message/message-input-box.component.js +52 -46
  39. package/dist/lib/components/message/message-input-box.component.js.map +1 -1
  40. package/dist/lib/components/message/message-input.component.d.ts +83 -18
  41. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  42. package/dist/lib/components/message/message-input.component.js +238 -151
  43. package/dist/lib/components/message/message-input.component.js.map +1 -1
  44. package/dist/lib/components/message/message-item.component.d.ts +10 -1
  45. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  46. package/dist/lib/components/message/message-item.component.js +67 -15
  47. package/dist/lib/components/message/message-item.component.js.map +1 -1
  48. package/dist/lib/components/message/message-list.component.js +6 -9
  49. package/dist/lib/components/message/message-list.component.js.map +1 -1
  50. package/dist/lib/components/overlay/chat-overlay.component.d.ts +3 -0
  51. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  52. package/dist/lib/components/overlay/chat-overlay.component.js +9 -4
  53. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  54. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +45 -0
  55. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +1 -1
  56. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +10 -0
  57. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +1 -1
  58. package/dist/lib/components/realtime/channels/client-context-channel.d.ts +46 -0
  59. package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -0
  60. package/dist/lib/components/realtime/channels/client-context-channel.js +174 -0
  61. package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -0
  62. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.d.ts +123 -0
  63. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.d.ts.map +1 -0
  64. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js +397 -0
  65. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js.map +1 -0
  66. package/dist/lib/components/realtime/media/media-channel-state.d.ts +103 -0
  67. package/dist/lib/components/realtime/media/media-channel-state.d.ts.map +1 -0
  68. package/dist/lib/components/realtime/media/media-channel-state.js +143 -0
  69. package/dist/lib/components/realtime/media/media-channel-state.js.map +1 -0
  70. package/dist/lib/components/realtime/media/media-channel-tools.d.ts +24 -0
  71. package/dist/lib/components/realtime/media/media-channel-tools.d.ts.map +1 -0
  72. package/dist/lib/components/realtime/media/media-channel-tools.js +107 -0
  73. package/dist/lib/components/realtime/media/media-channel-tools.js.map +1 -0
  74. package/dist/lib/components/realtime/media/media-channel.d.ts +89 -0
  75. package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -0
  76. package/dist/lib/components/realtime/media/media-channel.js +253 -0
  77. package/dist/lib/components/realtime/media/media-channel.js.map +1 -0
  78. package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts +141 -0
  79. package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts.map +1 -0
  80. package/dist/lib/components/realtime/media/realtime-media-surface.component.js +574 -0
  81. package/dist/lib/components/realtime/media/realtime-media-surface.component.js.map +1 -0
  82. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +59 -14
  83. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -1
  84. package/dist/lib/components/realtime/realtime-activity-rail.component.js +277 -74
  85. package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
  86. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +28 -27
  87. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  88. package/dist/lib/components/realtime/realtime-agent-banner.component.js +144 -143
  89. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  90. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +12 -0
  91. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
  92. package/dist/lib/components/realtime/realtime-agent-picker.component.js +105 -43
  93. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
  94. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +2 -2
  95. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -1
  96. package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -1
  97. package/dist/lib/components/realtime/realtime-composer.component.d.ts +41 -7
  98. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
  99. package/dist/lib/components/realtime/realtime-composer.component.js +216 -102
  100. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  101. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +0 -2
  102. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -1
  103. package/dist/lib/components/realtime/realtime-delegation-card.component.js +67 -71
  104. package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
  105. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +364 -44
  106. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  107. package/dist/lib/components/realtime/realtime-session-overlay.component.js +839 -153
  108. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  109. package/dist/lib/components/realtime/realtime-session-state.d.ts +5 -5
  110. package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -1
  111. package/dist/lib/components/realtime/realtime-session-state.js.map +1 -1
  112. package/dist/lib/components/realtime/realtime-surface-tab-style.d.ts +70 -0
  113. package/dist/lib/components/realtime/realtime-surface-tab-style.d.ts.map +1 -0
  114. package/dist/lib/components/realtime/realtime-surface-tab-style.js +115 -0
  115. package/dist/lib/components/realtime/realtime-surface-tab-style.js.map +1 -0
  116. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +55 -57
  117. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
  118. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +165 -143
  119. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
  120. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +80 -71
  121. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
  122. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +83 -113
  123. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
  124. package/dist/lib/components/realtime/realtime-ui-config.d.ts +270 -0
  125. package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -0
  126. package/dist/lib/components/realtime/realtime-ui-config.js +212 -0
  127. package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -0
  128. package/dist/lib/components/search/search-panel.component.d.ts +2 -0
  129. package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
  130. package/dist/lib/components/search/search-panel.component.js +92 -101
  131. package/dist/lib/components/search/search-panel.component.js.map +1 -1
  132. package/dist/lib/components/share/share-modal.component.d.ts.map +1 -1
  133. package/dist/lib/components/share/share-modal.component.js +10 -11
  134. package/dist/lib/components/share/share-modal.component.js.map +1 -1
  135. package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -1
  136. package/dist/lib/components/shared/user-picker.component.js +12 -15
  137. package/dist/lib/components/shared/user-picker.component.js.map +1 -1
  138. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +5 -0
  139. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  140. package/dist/lib/components/workspace/conversation-workspace.component.js +18 -7
  141. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  142. package/dist/lib/conversations.module.d.ts +29 -26
  143. package/dist/lib/conversations.module.d.ts.map +1 -1
  144. package/dist/lib/conversations.module.js +37 -6
  145. package/dist/lib/conversations.module.js.map +1 -1
  146. package/dist/lib/models/conversation-state.model.d.ts +6 -3
  147. package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
  148. package/dist/lib/models/conversation-state.model.js.map +1 -1
  149. package/dist/lib/services/conversation-agent.service.d.ts +2 -2
  150. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  151. package/dist/lib/services/conversation-agent.service.js +6 -2
  152. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  153. package/dist/lib/services/mention-autocomplete.service.d.ts +17 -1
  154. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  155. package/dist/lib/services/mention-autocomplete.service.js +58 -2
  156. package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
  157. package/dist/lib/services/realtime-audio-recorder.d.ts +143 -0
  158. package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -0
  159. package/dist/lib/services/realtime-audio-recorder.js +379 -0
  160. package/dist/lib/services/realtime-audio-recorder.js.map +1 -0
  161. package/dist/lib/services/realtime-pcm-wav.d.ts +75 -0
  162. package/dist/lib/services/realtime-pcm-wav.d.ts.map +1 -0
  163. package/dist/lib/services/realtime-pcm-wav.js +205 -0
  164. package/dist/lib/services/realtime-pcm-wav.js.map +1 -0
  165. package/dist/lib/services/realtime-session-review.service.d.ts +28 -1
  166. package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -1
  167. package/dist/lib/services/realtime-session-review.service.js +12 -3
  168. package/dist/lib/services/realtime-session-review.service.js.map +1 -1
  169. package/dist/lib/services/realtime-session.service.d.ts +210 -20
  170. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  171. package/dist/lib/services/realtime-session.service.js +452 -21
  172. package/dist/lib/services/realtime-session.service.js.map +1 -1
  173. package/dist/lib/services/realtime-sessions-adapter.js +1 -1
  174. package/dist/lib/services/realtime-sessions-adapter.js.map +1 -1
  175. package/dist/lib/services/ui-command-handler.service.d.ts +7 -2
  176. package/dist/lib/services/ui-command-handler.service.d.ts.map +1 -1
  177. package/dist/lib/services/ui-command-handler.service.js +6 -2
  178. package/dist/lib/services/ui-command-handler.service.js.map +1 -1
  179. package/dist/lib/utils/plan-mode-preference.d.ts +62 -0
  180. package/dist/lib/utils/plan-mode-preference.d.ts.map +1 -0
  181. package/dist/lib/utils/plan-mode-preference.js +130 -0
  182. package/dist/lib/utils/plan-mode-preference.js.map +1 -0
  183. package/dist/public-api.d.ts +6 -0
  184. package/dist/public-api.d.ts.map +1 -1
  185. package/dist/public-api.js +8 -0
  186. package/dist/public-api.js.map +1 -1
  187. package/package.json +28 -26
  188. package/dist/__tests__/attachment-badge.test.d.ts +0 -2
  189. package/dist/__tests__/attachment-badge.test.d.ts.map +0 -1
  190. package/dist/__tests__/attachment-badge.test.js +0 -66
  191. package/dist/__tests__/attachment-badge.test.js.map +0 -1
  192. package/dist/__tests__/channel-optional-surface.test.d.ts +0 -2
  193. package/dist/__tests__/channel-optional-surface.test.d.ts.map +0 -1
  194. package/dist/__tests__/channel-optional-surface.test.js +0 -53
  195. package/dist/__tests__/channel-optional-surface.test.js.map +0 -1
  196. package/dist/__tests__/chat-events.test.d.ts +0 -14
  197. package/dist/__tests__/chat-events.test.d.ts.map +0 -1
  198. package/dist/__tests__/chat-events.test.js +0 -109
  199. package/dist/__tests__/chat-events.test.js.map +0 -1
  200. package/dist/__tests__/collections-full-view.test.d.ts +0 -2
  201. package/dist/__tests__/collections-full-view.test.d.ts.map +0 -1
  202. package/dist/__tests__/collections-full-view.test.js +0 -225
  203. package/dist/__tests__/collections-full-view.test.js.map +0 -1
  204. package/dist/__tests__/conversation-cache.test.d.ts +0 -2
  205. package/dist/__tests__/conversation-cache.test.d.ts.map +0 -1
  206. package/dist/__tests__/conversation-cache.test.js +0 -233
  207. package/dist/__tests__/conversation-cache.test.js.map +0 -1
  208. package/dist/__tests__/conversation-naming.test.d.ts +0 -2
  209. package/dist/__tests__/conversation-naming.test.d.ts.map +0 -1
  210. package/dist/__tests__/conversation-naming.test.js +0 -110
  211. package/dist/__tests__/conversation-naming.test.js.map +0 -1
  212. package/dist/__tests__/delegation-result-parser.test.d.ts +0 -2
  213. package/dist/__tests__/delegation-result-parser.test.d.ts.map +0 -1
  214. package/dist/__tests__/delegation-result-parser.test.js +0 -107
  215. package/dist/__tests__/delegation-result-parser.test.js.map +0 -1
  216. package/dist/__tests__/distinct-artifacts.test.d.ts +0 -2
  217. package/dist/__tests__/distinct-artifacts.test.d.ts.map +0 -1
  218. package/dist/__tests__/distinct-artifacts.test.js +0 -56
  219. package/dist/__tests__/distinct-artifacts.test.js.map +0 -1
  220. package/dist/__tests__/event-wiring.test.d.ts +0 -15
  221. package/dist/__tests__/event-wiring.test.d.ts.map +0 -1
  222. package/dist/__tests__/event-wiring.test.js +0 -100
  223. package/dist/__tests__/event-wiring.test.js.map +0 -1
  224. package/dist/__tests__/index.test.d.ts +0 -2
  225. package/dist/__tests__/index.test.d.ts.map +0 -1
  226. package/dist/__tests__/index.test.js +0 -7
  227. package/dist/__tests__/index.test.js.map +0 -1
  228. package/dist/__tests__/narration-template.test.d.ts +0 -2
  229. package/dist/__tests__/narration-template.test.d.ts.map +0 -1
  230. package/dist/__tests__/narration-template.test.js +0 -76
  231. package/dist/__tests__/narration-template.test.js.map +0 -1
  232. package/dist/__tests__/notification-model.test.d.ts +0 -2
  233. package/dist/__tests__/notification-model.test.d.ts.map +0 -1
  234. package/dist/__tests__/notification-model.test.js +0 -68
  235. package/dist/__tests__/notification-model.test.js.map +0 -1
  236. package/dist/__tests__/realtime-agent-picker-models.test.d.ts +0 -2
  237. package/dist/__tests__/realtime-agent-picker-models.test.d.ts.map +0 -1
  238. package/dist/__tests__/realtime-agent-picker-models.test.js +0 -49
  239. package/dist/__tests__/realtime-agent-picker-models.test.js.map +0 -1
  240. package/dist/__tests__/realtime-audio-visuals.test.d.ts +0 -2
  241. package/dist/__tests__/realtime-audio-visuals.test.d.ts.map +0 -1
  242. package/dist/__tests__/realtime-audio-visuals.test.js +0 -123
  243. package/dist/__tests__/realtime-audio-visuals.test.js.map +0 -1
  244. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts +0 -2
  245. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts.map +0 -1
  246. package/dist/__tests__/realtime-delegation-card-cancel.test.js +0 -48
  247. package/dist/__tests__/realtime-delegation-card-cancel.test.js.map +0 -1
  248. package/dist/__tests__/realtime-disclosure.test.d.ts +0 -2
  249. package/dist/__tests__/realtime-disclosure.test.d.ts.map +0 -1
  250. package/dist/__tests__/realtime-disclosure.test.js +0 -164
  251. package/dist/__tests__/realtime-disclosure.test.js.map +0 -1
  252. package/dist/__tests__/realtime-pairing.test.d.ts +0 -2
  253. package/dist/__tests__/realtime-pairing.test.d.ts.map +0 -1
  254. package/dist/__tests__/realtime-pairing.test.js +0 -207
  255. package/dist/__tests__/realtime-pairing.test.js.map +0 -1
  256. package/dist/__tests__/realtime-review-lifecycle.test.d.ts +0 -2
  257. package/dist/__tests__/realtime-review-lifecycle.test.d.ts.map +0 -1
  258. package/dist/__tests__/realtime-review-lifecycle.test.js +0 -154
  259. package/dist/__tests__/realtime-review-lifecycle.test.js.map +0 -1
  260. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts +0 -2
  261. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts.map +0 -1
  262. package/dist/__tests__/realtime-session-cancel-usage.test.js +0 -230
  263. package/dist/__tests__/realtime-session-cancel-usage.test.js.map +0 -1
  264. package/dist/__tests__/realtime-session-channels.test.d.ts +0 -2
  265. package/dist/__tests__/realtime-session-channels.test.d.ts.map +0 -1
  266. package/dist/__tests__/realtime-session-channels.test.js +0 -252
  267. package/dist/__tests__/realtime-session-channels.test.js.map +0 -1
  268. package/dist/__tests__/realtime-session-client-tools.test.d.ts +0 -2
  269. package/dist/__tests__/realtime-session-client-tools.test.d.ts.map +0 -1
  270. package/dist/__tests__/realtime-session-client-tools.test.js +0 -103
  271. package/dist/__tests__/realtime-session-client-tools.test.js.map +0 -1
  272. package/dist/__tests__/realtime-session-minimized.test.d.ts +0 -2
  273. package/dist/__tests__/realtime-session-minimized.test.d.ts.map +0 -1
  274. package/dist/__tests__/realtime-session-minimized.test.js +0 -32
  275. package/dist/__tests__/realtime-session-minimized.test.js.map +0 -1
  276. package/dist/__tests__/realtime-session-mint.test.d.ts +0 -2
  277. package/dist/__tests__/realtime-session-mint.test.d.ts.map +0 -1
  278. package/dist/__tests__/realtime-session-mint.test.js +0 -69
  279. package/dist/__tests__/realtime-session-mint.test.js.map +0 -1
  280. package/dist/__tests__/realtime-session-policy.test.d.ts +0 -2
  281. package/dist/__tests__/realtime-session-policy.test.d.ts.map +0 -1
  282. package/dist/__tests__/realtime-session-policy.test.js +0 -303
  283. package/dist/__tests__/realtime-session-policy.test.js.map +0 -1
  284. package/dist/__tests__/realtime-session-review.service.test.d.ts +0 -2
  285. package/dist/__tests__/realtime-session-review.service.test.d.ts.map +0 -1
  286. package/dist/__tests__/realtime-session-review.service.test.js +0 -743
  287. package/dist/__tests__/realtime-session-review.service.test.js.map +0 -1
  288. package/dist/__tests__/realtime-session-state.test.d.ts +0 -2
  289. package/dist/__tests__/realtime-session-state.test.d.ts.map +0 -1
  290. package/dist/__tests__/realtime-session-state.test.js +0 -83
  291. package/dist/__tests__/realtime-session-state.test.js.map +0 -1
  292. package/dist/__tests__/realtime-session-timeline-card.test.d.ts +0 -2
  293. package/dist/__tests__/realtime-session-timeline-card.test.d.ts.map +0 -1
  294. package/dist/__tests__/realtime-session-timeline-card.test.js +0 -106
  295. package/dist/__tests__/realtime-session-timeline-card.test.js.map +0 -1
  296. package/dist/__tests__/realtime-session-timeline.test.d.ts +0 -2
  297. package/dist/__tests__/realtime-session-timeline.test.d.ts.map +0 -1
  298. package/dist/__tests__/realtime-session-timeline.test.js +0 -142
  299. package/dist/__tests__/realtime-session-timeline.test.js.map +0 -1
  300. package/dist/__tests__/realtime-sessions-adapter.test.d.ts +0 -19
  301. package/dist/__tests__/realtime-sessions-adapter.test.d.ts.map +0 -1
  302. package/dist/__tests__/realtime-sessions-adapter.test.js +0 -188
  303. package/dist/__tests__/realtime-sessions-adapter.test.js.map +0 -1
  304. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts +0 -2
  305. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts.map +0 -1
  306. package/dist/__tests__/realtime-surface-panel-prefs.test.js +0 -100
  307. package/dist/__tests__/realtime-surface-panel-prefs.test.js.map +0 -1
  308. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts +0 -2
  309. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts.map +0 -1
  310. package/dist/__tests__/realtime-surface-tabs-model.test.js +0 -193
  311. package/dist/__tests__/realtime-surface-tabs-model.test.js.map +0 -1
  312. package/dist/__tests__/remote-browser-audio-player.test.d.ts +0 -2
  313. package/dist/__tests__/remote-browser-audio-player.test.d.ts.map +0 -1
  314. package/dist/__tests__/remote-browser-audio-player.test.js +0 -137
  315. package/dist/__tests__/remote-browser-audio-player.test.js.map +0 -1
  316. package/dist/__tests__/remote-browser-channel.test.d.ts +0 -2
  317. package/dist/__tests__/remote-browser-channel.test.d.ts.map +0 -1
  318. package/dist/__tests__/remote-browser-channel.test.js +0 -585
  319. package/dist/__tests__/remote-browser-channel.test.js.map +0 -1
  320. package/dist/__tests__/search-service.test.d.ts +0 -2
  321. package/dist/__tests__/search-service.test.d.ts.map +0 -1
  322. package/dist/__tests__/search-service.test.js +0 -114
  323. package/dist/__tests__/search-service.test.js.map +0 -1
  324. package/dist/__tests__/slot-defaults.test.d.ts +0 -24
  325. package/dist/__tests__/slot-defaults.test.d.ts.map +0 -1
  326. package/dist/__tests__/slot-defaults.test.js +0 -63
  327. package/dist/__tests__/slot-defaults.test.js.map +0 -1
  328. package/dist/__tests__/toast-service.test.d.ts +0 -2
  329. package/dist/__tests__/toast-service.test.d.ts.map +0 -1
  330. package/dist/__tests__/toast-service.test.js +0 -143
  331. package/dist/__tests__/toast-service.test.js.map +0 -1
  332. package/dist/__tests__/user-authorization.test.d.ts +0 -2
  333. package/dist/__tests__/user-authorization.test.d.ts.map +0 -1
  334. package/dist/__tests__/user-authorization.test.js +0 -97
  335. package/dist/__tests__/user-authorization.test.js.map +0 -1
  336. package/dist/__tests__/voice-session-narration.test.d.ts +0 -2
  337. package/dist/__tests__/voice-session-narration.test.d.ts.map +0 -1
  338. package/dist/__tests__/voice-session-narration.test.js +0 -609
  339. package/dist/__tests__/voice-session-narration.test.js.map +0 -1
  340. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts +0 -2
  341. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts.map +0 -1
  342. package/dist/__tests__/whiteboard-artifact-viewer.test.js +0 -101
  343. package/dist/__tests__/whiteboard-artifact-viewer.test.js.map +0 -1
  344. package/dist/__tests__/whiteboard-channel.test.d.ts +0 -2
  345. package/dist/__tests__/whiteboard-channel.test.d.ts.map +0 -1
  346. package/dist/__tests__/whiteboard-channel.test.js +0 -260
  347. package/dist/__tests__/whiteboard-channel.test.js.map +0 -1
  348. package/dist/__tests__/whiteboard-restore-state.test.d.ts +0 -2
  349. package/dist/__tests__/whiteboard-restore-state.test.d.ts.map +0 -1
  350. package/dist/__tests__/whiteboard-restore-state.test.js +0 -108
  351. package/dist/__tests__/whiteboard-restore-state.test.js.map +0 -1
@@ -1,154 +0,0 @@
1
- // Angular components in this package are partial-compiled — load the JIT compiler first
2
- // (same convention as the other component suites in this node test environment).
3
- import '@angular/compiler';
4
- import { describe, it, expect, vi } from 'vitest';
5
- import { ConversationChatAreaComponent } from '../lib/components/conversation/conversation-chat-area.component';
6
- /**
7
- * SESSION-REVIEW overlay lifecycle on the chat area — every path that must CLEAR (or
8
- * refuse to host) a review so the overlay can never go stale:
9
- *
10
- * 1. Changing the active conversation clears any hosted review (the original stuck
11
- * repro: an old session opened in review mode survived conversation switches).
12
- * 2. The overlay's Close handler clears.
13
- * 3. The async open path discards stale loads: a live call (before or during the
14
- * load) wins; a conversation switch mid-load discards the review UNLESS the
15
- * review belongs to the newly active conversation (the deep-link race).
16
- *
17
- * Class-level tests without TestBed: the component is created via
18
- * `Object.create(prototype)` (skipping ctor/inject) and the few collaborators the
19
- * review paths touch are stubbed directly.
20
- */
21
- function review(overrides = {}) {
22
- return {
23
- SessionID: 'SESSION-1',
24
- AgentID: 'AGENT-1',
25
- AgentName: 'Voice Co-Agent',
26
- TargetAgentID: 'AGENT-1',
27
- ConversationID: 'CONV-A',
28
- Status: 'Closed',
29
- CloseReason: 'Explicit',
30
- StartedAt: new Date(2026, 5, 1, 10, 0, 0),
31
- LastActiveAt: null,
32
- ClosedAt: new Date(2026, 5, 1, 10, 10, 0),
33
- Turns: [],
34
- DelegatedRuns: [],
35
- ChannelStates: [],
36
- Legs: [],
37
- Artifacts: [],
38
- ...overrides
39
- };
40
- }
41
- /** Bare component over the real prototype: real lifecycle methods, stubbed collaborators. */
42
- function createHarness() {
43
- const component = Object.create(ConversationChatAreaComponent.prototype);
44
- const stubs = {
45
- voiceSession: { IsActive: false },
46
- loadSessionReview: vi.fn(),
47
- detectChanges: vi.fn()
48
- };
49
- const open = component;
50
- open['RealtimeReview'] = null;
51
- open['_conversationId'] = null;
52
- open['isInitialized'] = false; // keep the setter from invoking the heavy load path
53
- open['Provider'] = {}; // ProviderToUse resolves to this stub, never the global Metadata.Provider
54
- open['RealtimeSession'] = stubs.voiceSession;
55
- open['realtimeReviewService'] = { LoadSessionReview: stubs.loadSessionReview };
56
- open['cdr'] = { detectChanges: stubs.detectChanges };
57
- return { component, stubs };
58
- }
59
- describe('Conversation change clears the session review (the stuck-overlay repro)', () => {
60
- it('clears a hosted review when the conversationId input changes', () => {
61
- const { component } = createHarness();
62
- component.conversationId = 'CONV-A';
63
- component.RealtimeReview = review();
64
- component.conversationId = 'CONV-B';
65
- expect(component.RealtimeReview).toBeNull();
66
- });
67
- it('clears a hosted review when the conversation changes to NULL (no selection)', () => {
68
- const { component } = createHarness();
69
- component.conversationId = 'CONV-A';
70
- component.RealtimeReview = review();
71
- component.conversationId = null;
72
- expect(component.RealtimeReview).toBeNull();
73
- });
74
- it('keeps the review when the input re-fires with the SAME conversation', () => {
75
- const { component } = createHarness();
76
- component.conversationId = 'CONV-A';
77
- const hosted = review();
78
- component.RealtimeReview = hosted;
79
- component.conversationId = 'CONV-A';
80
- expect(component.RealtimeReview).toBe(hosted);
81
- });
82
- });
83
- describe('Overlay Close + explicit clear', () => {
84
- it('onReviewClosed (the overlay ReviewClosed output) clears the review', () => {
85
- const { component } = createHarness();
86
- component.RealtimeReview = review();
87
- component.onReviewClosed();
88
- expect(component.RealtimeReview).toBeNull();
89
- });
90
- it('ClearRealtimeSessionReview is a safe no-op when nothing is hosted', () => {
91
- const { component } = createHarness();
92
- expect(() => component.ClearRealtimeSessionReview()).not.toThrow();
93
- expect(component.RealtimeReview).toBeNull();
94
- });
95
- });
96
- describe('OpenRealtimeSessionReview — hosting and staleness guards', () => {
97
- it('hosts the loaded review for the current conversation and reports success', async () => {
98
- const { component, stubs } = createHarness();
99
- component.conversationId = 'CONV-A';
100
- stubs.loadSessionReview.mockResolvedValue(review({ ConversationID: 'CONV-A' }));
101
- const opened = await component.OpenRealtimeSessionReview('SESSION-1');
102
- expect(opened).toBe(true);
103
- expect(component.RealtimeReview?.SessionID).toBe('SESSION-1');
104
- expect(stubs.detectChanges).toHaveBeenCalled();
105
- });
106
- it('refuses while a LIVE call is active (never fights the live overlay) and does not even load', async () => {
107
- const { component, stubs } = createHarness();
108
- stubs.voiceSession.IsActive = true;
109
- const opened = await component.OpenRealtimeSessionReview('SESSION-1');
110
- expect(opened).toBe(false);
111
- expect(stubs.loadSessionReview).not.toHaveBeenCalled();
112
- expect(component.RealtimeReview).toBeNull();
113
- });
114
- it('reports failure (and hosts nothing) when the session cannot be loaded', async () => {
115
- const { component, stubs } = createHarness();
116
- stubs.loadSessionReview.mockResolvedValue(null);
117
- const opened = await component.OpenRealtimeSessionReview('SESSION-1');
118
- expect(opened).toBe(false);
119
- expect(component.RealtimeReview).toBeNull();
120
- });
121
- it('discards a load that resolves AFTER a live call started (the call wins)', async () => {
122
- const { component, stubs } = createHarness();
123
- stubs.loadSessionReview.mockImplementation(async () => {
124
- stubs.voiceSession.IsActive = true; // call starts while the review loads
125
- return review();
126
- });
127
- const opened = await component.OpenRealtimeSessionReview('SESSION-1');
128
- expect(opened).toBe(false);
129
- expect(component.RealtimeReview).toBeNull();
130
- });
131
- it('discards a load that resolves after the user switched to a DIFFERENT conversation', async () => {
132
- const { component, stubs } = createHarness();
133
- component.conversationId = 'CONV-A';
134
- stubs.loadSessionReview.mockImplementation(async () => {
135
- component.conversationId = 'CONV-B'; // user moved on mid-load
136
- return review({ ConversationID: 'CONV-A' });
137
- });
138
- const opened = await component.OpenRealtimeSessionReview('SESSION-1');
139
- expect(opened).toBe(false);
140
- expect(component.RealtimeReview).toBeNull();
141
- });
142
- it('still hosts when the conversation switched mid-load but the review BELONGS to the new one (deep-link race)', async () => {
143
- const { component, stubs } = createHarness();
144
- component.conversationId = 'CONV-A';
145
- stubs.loadSessionReview.mockImplementation(async () => {
146
- component.conversationId = 'CONV-B'; // deep link selected the session's own conversation
147
- return review({ ConversationID: 'conv-b' }); // case-insensitive UUID compare
148
- });
149
- const opened = await component.OpenRealtimeSessionReview('SESSION-1');
150
- expect(opened).toBe(true);
151
- expect(component.RealtimeReview?.ConversationID).toBe('conv-b');
152
- });
153
- });
154
- //# sourceMappingURL=realtime-review-lifecycle.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-review-lifecycle.test.js","sourceRoot":"","sources":["../../src/__tests__/realtime-review-lifecycle.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Angular components in this package are partial-compiled — load the JIT compiler first\n// (same convention as the other component suites in this node test environment).\nimport '@angular/compiler';\nimport { describe, it, expect, vi } from 'vitest';\nimport { ConversationChatAreaComponent } from '../lib/components/conversation/conversation-chat-area.component';\nimport { RealtimeSessionReview } from '../lib/services/realtime-session-review.service';\n\n/**\n * SESSION-REVIEW overlay lifecycle on the chat area — every path that must CLEAR (or\n * refuse to host) a review so the overlay can never go stale:\n *\n * 1. Changing the active conversation clears any hosted review (the original stuck\n * repro: an old session opened in review mode survived conversation switches).\n * 2. The overlay's Close handler clears.\n * 3. The async open path discards stale loads: a live call (before or during the\n * load) wins; a conversation switch mid-load discards the review UNLESS the\n * review belongs to the newly active conversation (the deep-link race).\n *\n * Class-level tests without TestBed: the component is created via\n * `Object.create(prototype)` (skipping ctor/inject) and the few collaborators the\n * review paths touch are stubbed directly.\n */\n\nfunction review(overrides: Partial<RealtimeSessionReview> = {}): RealtimeSessionReview {\n return {\n SessionID: 'SESSION-1',\n AgentID: 'AGENT-1',\n AgentName: 'Voice Co-Agent',\n TargetAgentID: 'AGENT-1',\n ConversationID: 'CONV-A',\n Status: 'Closed',\n CloseReason: 'Explicit',\n StartedAt: new Date(2026, 5, 1, 10, 0, 0),\n LastActiveAt: null,\n ClosedAt: new Date(2026, 5, 1, 10, 10, 0),\n Turns: [],\n DelegatedRuns: [],\n ChannelStates: [],\n Legs: [],\n Artifacts: [],\n ...overrides\n };\n}\n\ninterface HarnessStubs {\n voiceSession: { IsActive: boolean };\n loadSessionReview: ReturnType<typeof vi.fn>;\n detectChanges: ReturnType<typeof vi.fn>;\n}\n\n/** Bare component over the real prototype: real lifecycle methods, stubbed collaborators. */\nfunction createHarness(): { component: ConversationChatAreaComponent; stubs: HarnessStubs } {\n const component = Object.create(ConversationChatAreaComponent.prototype) as ConversationChatAreaComponent;\n const stubs: HarnessStubs = {\n voiceSession: { IsActive: false },\n loadSessionReview: vi.fn(),\n detectChanges: vi.fn()\n };\n const open = component as unknown as Record<string, unknown>;\n open['RealtimeReview'] = null;\n open['_conversationId'] = null;\n open['isInitialized'] = false; // keep the setter from invoking the heavy load path\n open['Provider'] = {}; // ProviderToUse resolves to this stub, never the global Metadata.Provider\n open['RealtimeSession'] = stubs.voiceSession;\n open['realtimeReviewService'] = { LoadSessionReview: stubs.loadSessionReview };\n open['cdr'] = { detectChanges: stubs.detectChanges };\n return { component, stubs };\n}\n\ndescribe('Conversation change clears the session review (the stuck-overlay repro)', () => {\n it('clears a hosted review when the conversationId input changes', () => {\n const { component } = createHarness();\n component.conversationId = 'CONV-A';\n component.RealtimeReview = review();\n\n component.conversationId = 'CONV-B';\n\n expect(component.RealtimeReview).toBeNull();\n });\n\n it('clears a hosted review when the conversation changes to NULL (no selection)', () => {\n const { component } = createHarness();\n component.conversationId = 'CONV-A';\n component.RealtimeReview = review();\n\n component.conversationId = null;\n\n expect(component.RealtimeReview).toBeNull();\n });\n\n it('keeps the review when the input re-fires with the SAME conversation', () => {\n const { component } = createHarness();\n component.conversationId = 'CONV-A';\n const hosted = review();\n component.RealtimeReview = hosted;\n\n component.conversationId = 'CONV-A';\n\n expect(component.RealtimeReview).toBe(hosted);\n });\n});\n\ndescribe('Overlay Close + explicit clear', () => {\n it('onReviewClosed (the overlay ReviewClosed output) clears the review', () => {\n const { component } = createHarness();\n component.RealtimeReview = review();\n\n component.onReviewClosed();\n\n expect(component.RealtimeReview).toBeNull();\n });\n\n it('ClearRealtimeSessionReview is a safe no-op when nothing is hosted', () => {\n const { component } = createHarness();\n expect(() => component.ClearRealtimeSessionReview()).not.toThrow();\n expect(component.RealtimeReview).toBeNull();\n });\n});\n\ndescribe('OpenRealtimeSessionReview — hosting and staleness guards', () => {\n it('hosts the loaded review for the current conversation and reports success', async () => {\n const { component, stubs } = createHarness();\n component.conversationId = 'CONV-A';\n stubs.loadSessionReview.mockResolvedValue(review({ ConversationID: 'CONV-A' }));\n\n const opened = await component.OpenRealtimeSessionReview('SESSION-1');\n\n expect(opened).toBe(true);\n expect(component.RealtimeReview?.SessionID).toBe('SESSION-1');\n expect(stubs.detectChanges).toHaveBeenCalled();\n });\n\n it('refuses while a LIVE call is active (never fights the live overlay) and does not even load', async () => {\n const { component, stubs } = createHarness();\n stubs.voiceSession.IsActive = true;\n\n const opened = await component.OpenRealtimeSessionReview('SESSION-1');\n\n expect(opened).toBe(false);\n expect(stubs.loadSessionReview).not.toHaveBeenCalled();\n expect(component.RealtimeReview).toBeNull();\n });\n\n it('reports failure (and hosts nothing) when the session cannot be loaded', async () => {\n const { component, stubs } = createHarness();\n stubs.loadSessionReview.mockResolvedValue(null);\n\n const opened = await component.OpenRealtimeSessionReview('SESSION-1');\n\n expect(opened).toBe(false);\n expect(component.RealtimeReview).toBeNull();\n });\n\n it('discards a load that resolves AFTER a live call started (the call wins)', async () => {\n const { component, stubs } = createHarness();\n stubs.loadSessionReview.mockImplementation(async () => {\n stubs.voiceSession.IsActive = true; // call starts while the review loads\n return review();\n });\n\n const opened = await component.OpenRealtimeSessionReview('SESSION-1');\n\n expect(opened).toBe(false);\n expect(component.RealtimeReview).toBeNull();\n });\n\n it('discards a load that resolves after the user switched to a DIFFERENT conversation', async () => {\n const { component, stubs } = createHarness();\n component.conversationId = 'CONV-A';\n stubs.loadSessionReview.mockImplementation(async () => {\n component.conversationId = 'CONV-B'; // user moved on mid-load\n return review({ ConversationID: 'CONV-A' });\n });\n\n const opened = await component.OpenRealtimeSessionReview('SESSION-1');\n\n expect(opened).toBe(false);\n expect(component.RealtimeReview).toBeNull();\n });\n\n it('still hosts when the conversation switched mid-load but the review BELONGS to the new one (deep-link race)', async () => {\n const { component, stubs } = createHarness();\n component.conversationId = 'CONV-A';\n stubs.loadSessionReview.mockImplementation(async () => {\n component.conversationId = 'CONV-B'; // deep link selected the session's own conversation\n return review({ ConversationID: 'conv-b' }); // case-insensitive UUID compare\n });\n\n const opened = await component.OpenRealtimeSessionReview('SESSION-1');\n\n expect(opened).toBe(true);\n expect(component.RealtimeReview?.ConversationID).toBe('conv-b');\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=realtime-session-cancel-usage.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-session-cancel-usage.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/realtime-session-cancel-usage.test.ts"],"names":[],"mappings":""}
@@ -1,230 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import { RealtimeSessionService } from '../lib/services/realtime-session.service';
3
- function internals(service) {
4
- return service;
5
- }
6
- function collectResults(service) {
7
- const results = [];
8
- service.DelegationResult$.subscribe(r => results.push(r));
9
- return results;
10
- }
11
- describe('RealtimeSessionService — CancelDelegation (per-card ✕, explicit user intent)', () => {
12
- let service;
13
- let executeGQL;
14
- beforeEach(() => {
15
- service = new RealtimeSessionService();
16
- executeGQL = vi.fn(async () => ({ CancelRealtimeSessionTool: { AbortedCount: 1, Success: true } }));
17
- service.Provider = { ExecuteGQL: executeGQL };
18
- internals(service).agentSessionId = 'sess-1';
19
- internals(service).inFlightCallIds.add('call-1');
20
- });
21
- it('calls the CancelRealtimeSessionTool mutation with the session + call id, selecting the structured result', async () => {
22
- await service.CancelDelegation('call-1');
23
- expect(executeGQL).toHaveBeenCalledTimes(1);
24
- expect(executeGQL).toHaveBeenCalledWith(expect.stringContaining('CancelRealtimeSessionTool'), { agentSessionId: 'sess-1', callId: 'call-1' });
25
- // The mutation document selects the structured result fields (server contract).
26
- const mutation = executeGQL.mock.calls[0][0];
27
- expect(mutation).toContain('AbortedCount');
28
- expect(mutation).toContain('Success');
29
- expect(mutation).toContain('ErrorMessage');
30
- });
31
- it('flips the card to a FAILED "Cancelled by user" result when the server aborted the run', async () => {
32
- const results = collectResults(service);
33
- const ok = await service.CancelDelegation('call-1');
34
- expect(ok).toBe(true);
35
- expect(results).toEqual([{ CallID: 'call-1', Success: false, Output: 'Cancelled by user' }]);
36
- expect(internals(service).inFlightCallIds.has('call-1')).toBe(false);
37
- });
38
- it('suppresses the aborted run\'s LATE real result so it cannot overwrite the cancelled card', async () => {
39
- const results = collectResults(service);
40
- await service.CancelDelegation('call-1');
41
- // The original ExecuteRealtimeSessionTool mutation eventually resolves with the aborted outcome.
42
- internals(service).emitDelegationResult('call-1', JSON.stringify({ success: false, error: 'Delegation failed: aborted' }));
43
- expect(results).toHaveLength(1); // only the "Cancelled by user" card flip
44
- expect(internals(service).cancelledCallIds.size).toBe(0); // the suppression marker was consumed
45
- });
46
- it('a DIFFERENT call\'s result still emits normally after a cancel', async () => {
47
- const results = collectResults(service);
48
- internals(service).inFlightCallIds.add('call-2');
49
- await service.CancelDelegation('call-1');
50
- internals(service).emitDelegationResult('call-2', JSON.stringify({ success: true, output: 'done' }));
51
- expect(results).toHaveLength(2);
52
- expect(results[1]).toMatchObject({ CallID: 'call-2', Success: true, Output: 'done' });
53
- });
54
- it('returns false WITHOUT flipping the card when the server had nothing to abort (result is racing in)', async () => {
55
- executeGQL.mockResolvedValue({ CancelRealtimeSessionTool: { AbortedCount: 0, Success: true } });
56
- const results = collectResults(service);
57
- const ok = await service.CancelDelegation('call-1');
58
- expect(ok).toBe(false);
59
- expect(results).toEqual([]);
60
- // The call stays tracked so the racing real result is processed normally.
61
- expect(internals(service).inFlightCallIds.has('call-1')).toBe(true);
62
- });
63
- it('treats a STRUCTURED failure (Success: false) as nothing aborted — card untouched', async () => {
64
- executeGQL.mockResolvedValue({
65
- CancelRealtimeSessionTool: { AbortedCount: 0, Success: false, ErrorMessage: 'registry exploded' },
66
- });
67
- const results = collectResults(service);
68
- const ok = await service.CancelDelegation('call-1');
69
- expect(ok).toBe(false);
70
- expect(results).toEqual([]);
71
- expect(internals(service).inFlightCallIds.has('call-1')).toBe(true);
72
- });
73
- it('is a no-op (no mutation) for a call id that is not tracked in flight', async () => {
74
- const ok = await service.CancelDelegation('call-unknown');
75
- expect(ok).toBe(false);
76
- expect(executeGQL).not.toHaveBeenCalled();
77
- });
78
- it('is a no-op (no mutation) when no session is open', async () => {
79
- internals(service).agentSessionId = null;
80
- const ok = await service.CancelDelegation('call-1');
81
- expect(ok).toBe(false);
82
- expect(executeGQL).not.toHaveBeenCalled();
83
- });
84
- it('tolerates a failed mutation (false, logged, card untouched)', async () => {
85
- executeGQL.mockRejectedValue(new Error('network down'));
86
- const results = collectResults(service);
87
- const ok = await service.CancelDelegation('call-1');
88
- expect(ok).toBe(false);
89
- expect(results).toEqual([]);
90
- });
91
- });
92
- describe('RealtimeSessionService — CancelInFlightDelegations (sweep cancel)', () => {
93
- let service;
94
- let executeGQL;
95
- beforeEach(() => {
96
- service = new RealtimeSessionService();
97
- executeGQL = vi.fn(async () => ({ CancelRealtimeSessionTool: { AbortedCount: 2, Success: true } }));
98
- service.Provider = { ExecuteGQL: executeGQL };
99
- internals(service).agentSessionId = 'sess-1';
100
- });
101
- it('cancels ALL tracked in-flight calls with ONE callId-less mutation and flips every card', async () => {
102
- internals(service).inFlightCallIds.add('call-1');
103
- internals(service).inFlightCallIds.add('call-2');
104
- const results = collectResults(service);
105
- const count = await service.CancelInFlightDelegations();
106
- expect(count).toBe(2);
107
- expect(executeGQL).toHaveBeenCalledTimes(1);
108
- expect(executeGQL).toHaveBeenCalledWith(expect.stringContaining('CancelRealtimeSessionTool'), { agentSessionId: 'sess-1', callId: null });
109
- expect(results.map(r => r.CallID).sort()).toEqual(['call-1', 'call-2']);
110
- expect(results.every(r => !r.Success && r.Output === 'Cancelled by user')).toBe(true);
111
- expect(internals(service).inFlightCallIds.size).toBe(0);
112
- });
113
- it('returns 0 without a mutation when nothing is tracked in flight', async () => {
114
- const count = await service.CancelInFlightDelegations();
115
- expect(count).toBe(0);
116
- expect(executeGQL).not.toHaveBeenCalled();
117
- });
118
- it('returns 0 (cards untouched) when the server aborted nothing', async () => {
119
- executeGQL.mockResolvedValue({ CancelRealtimeSessionTool: { AbortedCount: 0, Success: true } });
120
- internals(service).inFlightCallIds.add('call-1');
121
- const results = collectResults(service);
122
- const count = await service.CancelInFlightDelegations();
123
- expect(count).toBe(0);
124
- expect(results).toEqual([]);
125
- expect(internals(service).inFlightCallIds.has('call-1')).toBe(true);
126
- });
127
- });
128
- describe('RealtimeSessionService — usage telemetry relay (OnUsage → RelayRealtimeUsage)', () => {
129
- let service;
130
- let executeGQL;
131
- beforeEach(() => {
132
- vi.useFakeTimers();
133
- service = new RealtimeSessionService();
134
- executeGQL = vi.fn(async () => ({ RelayRealtimeUsage: true }));
135
- service.Provider = { ExecuteGQL: executeGQL };
136
- internals(service).agentSessionId = 'sess-1';
137
- });
138
- afterEach(() => {
139
- vi.useRealTimers();
140
- });
141
- it('accumulates deltas and relays ONE debounced mutation (~10s) with the summed totals', async () => {
142
- internals(service).onUsageDelta({ InputTokens: 100, OutputTokens: 10 });
143
- internals(service).onUsageDelta({ InputTokens: 20, OutputTokens: 5 });
144
- await vi.advanceTimersByTimeAsync(9999);
145
- expect(executeGQL).not.toHaveBeenCalled();
146
- await vi.advanceTimersByTimeAsync(1);
147
- expect(executeGQL).toHaveBeenCalledTimes(1);
148
- expect(executeGQL).toHaveBeenCalledWith(expect.stringContaining('RelayRealtimeUsage'), { agentSessionId: 'sess-1', inputTokens: 120, outputTokens: 15 });
149
- // Accumulators were consumed by the flush.
150
- expect(internals(service).pendingUsageInput).toBe(0);
151
- expect(internals(service).pendingUsageOutput).toBe(0);
152
- });
153
- it('ignores all-zero / negative / missing deltas (no timer armed, no mutation)', async () => {
154
- internals(service).onUsageDelta({});
155
- internals(service).onUsageDelta({ InputTokens: -5, OutputTokens: 0 });
156
- internals(service).onUsageDelta({ InputTokens: Number.NaN });
157
- await vi.advanceTimersByTimeAsync(60000);
158
- expect(executeGQL).not.toHaveBeenCalled();
159
- expect(internals(service).usageFlushTimer).toBeNull();
160
- });
161
- it('clamps a negative component while accumulating the positive one', async () => {
162
- internals(service).onUsageDelta({ InputTokens: -3, OutputTokens: 7 });
163
- await vi.advanceTimersByTimeAsync(10000);
164
- expect(executeGQL).toHaveBeenCalledWith(expect.stringContaining('RelayRealtimeUsage'), { agentSessionId: 'sess-1', inputTokens: 0, outputTokens: 7 });
165
- });
166
- it('re-accumulates on a failed relay so the next flush retries the same deltas', async () => {
167
- executeGQL.mockRejectedValueOnce(new Error('network down'));
168
- internals(service).onUsageDelta({ InputTokens: 50, OutputTokens: 5 });
169
- await vi.advanceTimersByTimeAsync(10000); // flush fails
170
- expect(internals(service).pendingUsageInput).toBe(50);
171
- expect(internals(service).pendingUsageOutput).toBe(5);
172
- internals(service).onUsageDelta({ InputTokens: 10, OutputTokens: 0 });
173
- await vi.advanceTimersByTimeAsync(10000); // retry carries the combined totals
174
- expect(executeGQL).toHaveBeenLastCalledWith(expect.stringContaining('RelayRealtimeUsage'), { agentSessionId: 'sess-1', inputTokens: 60, outputTokens: 5 });
175
- });
176
- it('flushes the unrelayed remainder at teardown BEFORE closing the server session (no debounce wait)', async () => {
177
- internals(service).onUsageDelta({ InputTokens: 33, OutputTokens: 4 });
178
- await internals(service).teardown(true);
179
- const mutations = executeGQL.mock.calls.map(c => c[0]);
180
- const usageIdx = mutations.findIndex(m => m.includes('RelayRealtimeUsage'));
181
- const closeIdx = mutations.findIndex(m => m.includes('CloseAgentSession'));
182
- expect(usageIdx).toBeGreaterThanOrEqual(0);
183
- expect(closeIdx).toBeGreaterThan(usageIdx); // usage flushed first, then close
184
- expect(executeGQL.mock.calls[usageIdx][1]).toEqual({ agentSessionId: 'sess-1', inputTokens: 33, outputTokens: 4 });
185
- // Teardown leaves the relay reset (no dangling timer / pending totals).
186
- expect(internals(service).usageFlushTimer).toBeNull();
187
- expect(internals(service).pendingUsageInput).toBe(0);
188
- expect(internals(service).pendingUsageOutput).toBe(0);
189
- });
190
- it('teardown without pending usage relays nothing (no spurious zero-delta mutation)', async () => {
191
- await internals(service).teardown(true);
192
- const mutations = executeGQL.mock.calls.map(c => c[0]);
193
- expect(mutations.some(m => m.includes('RelayRealtimeUsage'))).toBe(false);
194
- expect(mutations.some(m => m.includes('CloseAgentSession'))).toBe(true);
195
- });
196
- it('flushPendingUsage is a no-op without a session id', async () => {
197
- internals(service).agentSessionId = null;
198
- internals(service).onUsageDelta({ InputTokens: 9 });
199
- await internals(service).flushPendingUsage();
200
- expect(executeGQL).not.toHaveBeenCalled();
201
- // The deltas survive for a later flush once a session id exists.
202
- expect(internals(service).pendingUsageInput).toBe(9);
203
- });
204
- });
205
- describe('RealtimeSessionService — OnUsage wiring through wireClientHandlers', () => {
206
- /** Fake client capturing every handler wireClientHandlers registers. */
207
- class FakeWiredClient {
208
- UsageHandler = null;
209
- OnStateChange() { }
210
- OnTranscript() { }
211
- OnToolCall() { }
212
- OnError() { }
213
- OnInterruption() { }
214
- OnUsage(handler) {
215
- this.UsageHandler = handler;
216
- }
217
- }
218
- it('registers an OnUsage handler that feeds the accumulator', () => {
219
- const service = new RealtimeSessionService();
220
- const seam = service;
221
- seam.agentSessionId = 'sess-1';
222
- const client = new FakeWiredClient();
223
- seam.wireClientHandlers(client);
224
- expect(client.UsageHandler).toBeTypeOf('function');
225
- client.UsageHandler?.({ InputTokens: 11, OutputTokens: 3 });
226
- expect(seam.pendingUsageInput).toBe(11);
227
- expect(seam.pendingUsageOutput).toBe(3);
228
- });
229
- });
230
- //# sourceMappingURL=realtime-session-cancel-usage.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-session-cancel-usage.test.js","sourceRoot":"","sources":["../../src/__tests__/realtime-session-cancel-usage.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';\nimport { IMetadataProvider } from '@memberjunction/core';\nimport { RealtimeClientUsage } from '@memberjunction/ai-realtime-client';\nimport { RealtimeSessionService, VoiceDelegationResult } from '../lib/services/realtime-session.service';\n\n/**\n * The explicit delegation-CANCEL channel ({@link RealtimeSessionService.CancelDelegation} /\n * {@link RealtimeSessionService.CancelInFlightDelegations}) and the usage-telemetry relay\n * (`OnUsage` deltas → debounced `RelayRealtimeUsage` + teardown flush).\n *\n * Same narrow typed-seam approach as the sibling voice-session suites: a fake Provider whose\n * `ExecuteGQL` captures mutations, with private members reached through a typed internals cast.\n */\n\n/** The private surface the tests drive — no `any`, just the members under test. */\ninterface RealtimeSessionCancelUsageInternals {\n agentSessionId: string | null;\n inFlightCallIds: Set<string>;\n cancelledCallIds: Set<string>;\n pendingUsageInput: number;\n pendingUsageOutput: number;\n usageFlushTimer: ReturnType<typeof setTimeout> | null;\n emitDelegationResult(callId: string, resultJson: string): void;\n onUsageDelta(usage: RealtimeClientUsage): void;\n flushPendingUsage(agentSessionId?: string | null): Promise<void>;\n teardown(closeServerSession: boolean): Promise<void>;\n}\n\nfunction internals(service: RealtimeSessionService): RealtimeSessionCancelUsageInternals {\n return service as unknown as RealtimeSessionCancelUsageInternals;\n}\n\nfunction collectResults(service: RealtimeSessionService): VoiceDelegationResult[] {\n const results: VoiceDelegationResult[] = [];\n service.DelegationResult$.subscribe(r => results.push(r));\n return results;\n}\n\ndescribe('RealtimeSessionService — CancelDelegation (per-card ✕, explicit user intent)', () => {\n let service: RealtimeSessionService;\n let executeGQL: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n service = new RealtimeSessionService();\n executeGQL = vi.fn(async () => ({ CancelRealtimeSessionTool: { AbortedCount: 1, Success: true } }));\n service.Provider = { ExecuteGQL: executeGQL } as unknown as IMetadataProvider;\n internals(service).agentSessionId = 'sess-1';\n internals(service).inFlightCallIds.add('call-1');\n });\n\n it('calls the CancelRealtimeSessionTool mutation with the session + call id, selecting the structured result', async () => {\n await service.CancelDelegation('call-1');\n\n expect(executeGQL).toHaveBeenCalledTimes(1);\n expect(executeGQL).toHaveBeenCalledWith(\n expect.stringContaining('CancelRealtimeSessionTool'),\n { agentSessionId: 'sess-1', callId: 'call-1' }\n );\n // The mutation document selects the structured result fields (server contract).\n const mutation = executeGQL.mock.calls[0][0] as string;\n expect(mutation).toContain('AbortedCount');\n expect(mutation).toContain('Success');\n expect(mutation).toContain('ErrorMessage');\n });\n\n it('flips the card to a FAILED \"Cancelled by user\" result when the server aborted the run', async () => {\n const results = collectResults(service);\n\n const ok = await service.CancelDelegation('call-1');\n\n expect(ok).toBe(true);\n expect(results).toEqual([{ CallID: 'call-1', Success: false, Output: 'Cancelled by user' }]);\n expect(internals(service).inFlightCallIds.has('call-1')).toBe(false);\n });\n\n it('suppresses the aborted run\\'s LATE real result so it cannot overwrite the cancelled card', async () => {\n const results = collectResults(service);\n await service.CancelDelegation('call-1');\n\n // The original ExecuteRealtimeSessionTool mutation eventually resolves with the aborted outcome.\n internals(service).emitDelegationResult('call-1', JSON.stringify({ success: false, error: 'Delegation failed: aborted' }));\n\n expect(results).toHaveLength(1); // only the \"Cancelled by user\" card flip\n expect(internals(service).cancelledCallIds.size).toBe(0); // the suppression marker was consumed\n });\n\n it('a DIFFERENT call\\'s result still emits normally after a cancel', async () => {\n const results = collectResults(service);\n internals(service).inFlightCallIds.add('call-2');\n await service.CancelDelegation('call-1');\n\n internals(service).emitDelegationResult('call-2', JSON.stringify({ success: true, output: 'done' }));\n\n expect(results).toHaveLength(2);\n expect(results[1]).toMatchObject({ CallID: 'call-2', Success: true, Output: 'done' });\n });\n\n it('returns false WITHOUT flipping the card when the server had nothing to abort (result is racing in)', async () => {\n executeGQL.mockResolvedValue({ CancelRealtimeSessionTool: { AbortedCount: 0, Success: true } });\n const results = collectResults(service);\n\n const ok = await service.CancelDelegation('call-1');\n\n expect(ok).toBe(false);\n expect(results).toEqual([]);\n // The call stays tracked so the racing real result is processed normally.\n expect(internals(service).inFlightCallIds.has('call-1')).toBe(true);\n });\n\n it('treats a STRUCTURED failure (Success: false) as nothing aborted — card untouched', async () => {\n executeGQL.mockResolvedValue({\n CancelRealtimeSessionTool: { AbortedCount: 0, Success: false, ErrorMessage: 'registry exploded' },\n });\n const results = collectResults(service);\n\n const ok = await service.CancelDelegation('call-1');\n\n expect(ok).toBe(false);\n expect(results).toEqual([]);\n expect(internals(service).inFlightCallIds.has('call-1')).toBe(true);\n });\n\n it('is a no-op (no mutation) for a call id that is not tracked in flight', async () => {\n const ok = await service.CancelDelegation('call-unknown');\n expect(ok).toBe(false);\n expect(executeGQL).not.toHaveBeenCalled();\n });\n\n it('is a no-op (no mutation) when no session is open', async () => {\n internals(service).agentSessionId = null;\n const ok = await service.CancelDelegation('call-1');\n expect(ok).toBe(false);\n expect(executeGQL).not.toHaveBeenCalled();\n });\n\n it('tolerates a failed mutation (false, logged, card untouched)', async () => {\n executeGQL.mockRejectedValue(new Error('network down'));\n const results = collectResults(service);\n\n const ok = await service.CancelDelegation('call-1');\n\n expect(ok).toBe(false);\n expect(results).toEqual([]);\n });\n});\n\ndescribe('RealtimeSessionService — CancelInFlightDelegations (sweep cancel)', () => {\n let service: RealtimeSessionService;\n let executeGQL: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n service = new RealtimeSessionService();\n executeGQL = vi.fn(async () => ({ CancelRealtimeSessionTool: { AbortedCount: 2, Success: true } }));\n service.Provider = { ExecuteGQL: executeGQL } as unknown as IMetadataProvider;\n internals(service).agentSessionId = 'sess-1';\n });\n\n it('cancels ALL tracked in-flight calls with ONE callId-less mutation and flips every card', async () => {\n internals(service).inFlightCallIds.add('call-1');\n internals(service).inFlightCallIds.add('call-2');\n const results = collectResults(service);\n\n const count = await service.CancelInFlightDelegations();\n\n expect(count).toBe(2);\n expect(executeGQL).toHaveBeenCalledTimes(1);\n expect(executeGQL).toHaveBeenCalledWith(\n expect.stringContaining('CancelRealtimeSessionTool'),\n { agentSessionId: 'sess-1', callId: null }\n );\n expect(results.map(r => r.CallID).sort()).toEqual(['call-1', 'call-2']);\n expect(results.every(r => !r.Success && r.Output === 'Cancelled by user')).toBe(true);\n expect(internals(service).inFlightCallIds.size).toBe(0);\n });\n\n it('returns 0 without a mutation when nothing is tracked in flight', async () => {\n const count = await service.CancelInFlightDelegations();\n expect(count).toBe(0);\n expect(executeGQL).not.toHaveBeenCalled();\n });\n\n it('returns 0 (cards untouched) when the server aborted nothing', async () => {\n executeGQL.mockResolvedValue({ CancelRealtimeSessionTool: { AbortedCount: 0, Success: true } });\n internals(service).inFlightCallIds.add('call-1');\n const results = collectResults(service);\n\n const count = await service.CancelInFlightDelegations();\n\n expect(count).toBe(0);\n expect(results).toEqual([]);\n expect(internals(service).inFlightCallIds.has('call-1')).toBe(true);\n });\n});\n\ndescribe('RealtimeSessionService — usage telemetry relay (OnUsage → RelayRealtimeUsage)', () => {\n let service: RealtimeSessionService;\n let executeGQL: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n vi.useFakeTimers();\n service = new RealtimeSessionService();\n executeGQL = vi.fn(async () => ({ RelayRealtimeUsage: true }));\n service.Provider = { ExecuteGQL: executeGQL } as unknown as IMetadataProvider;\n internals(service).agentSessionId = 'sess-1';\n });\n\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it('accumulates deltas and relays ONE debounced mutation (~10s) with the summed totals', async () => {\n internals(service).onUsageDelta({ InputTokens: 100, OutputTokens: 10 });\n internals(service).onUsageDelta({ InputTokens: 20, OutputTokens: 5 });\n\n await vi.advanceTimersByTimeAsync(9999);\n expect(executeGQL).not.toHaveBeenCalled();\n\n await vi.advanceTimersByTimeAsync(1);\n expect(executeGQL).toHaveBeenCalledTimes(1);\n expect(executeGQL).toHaveBeenCalledWith(\n expect.stringContaining('RelayRealtimeUsage'),\n { agentSessionId: 'sess-1', inputTokens: 120, outputTokens: 15 }\n );\n // Accumulators were consumed by the flush.\n expect(internals(service).pendingUsageInput).toBe(0);\n expect(internals(service).pendingUsageOutput).toBe(0);\n });\n\n it('ignores all-zero / negative / missing deltas (no timer armed, no mutation)', async () => {\n internals(service).onUsageDelta({});\n internals(service).onUsageDelta({ InputTokens: -5, OutputTokens: 0 });\n internals(service).onUsageDelta({ InputTokens: Number.NaN });\n\n await vi.advanceTimersByTimeAsync(60000);\n expect(executeGQL).not.toHaveBeenCalled();\n expect(internals(service).usageFlushTimer).toBeNull();\n });\n\n it('clamps a negative component while accumulating the positive one', async () => {\n internals(service).onUsageDelta({ InputTokens: -3, OutputTokens: 7 });\n\n await vi.advanceTimersByTimeAsync(10000);\n expect(executeGQL).toHaveBeenCalledWith(\n expect.stringContaining('RelayRealtimeUsage'),\n { agentSessionId: 'sess-1', inputTokens: 0, outputTokens: 7 }\n );\n });\n\n it('re-accumulates on a failed relay so the next flush retries the same deltas', async () => {\n executeGQL.mockRejectedValueOnce(new Error('network down'));\n internals(service).onUsageDelta({ InputTokens: 50, OutputTokens: 5 });\n await vi.advanceTimersByTimeAsync(10000); // flush fails\n\n expect(internals(service).pendingUsageInput).toBe(50);\n expect(internals(service).pendingUsageOutput).toBe(5);\n\n internals(service).onUsageDelta({ InputTokens: 10, OutputTokens: 0 });\n await vi.advanceTimersByTimeAsync(10000); // retry carries the combined totals\n\n expect(executeGQL).toHaveBeenLastCalledWith(\n expect.stringContaining('RelayRealtimeUsage'),\n { agentSessionId: 'sess-1', inputTokens: 60, outputTokens: 5 }\n );\n });\n\n it('flushes the unrelayed remainder at teardown BEFORE closing the server session (no debounce wait)', async () => {\n internals(service).onUsageDelta({ InputTokens: 33, OutputTokens: 4 });\n\n await internals(service).teardown(true);\n\n const mutations = executeGQL.mock.calls.map(c => c[0] as string);\n const usageIdx = mutations.findIndex(m => m.includes('RelayRealtimeUsage'));\n const closeIdx = mutations.findIndex(m => m.includes('CloseAgentSession'));\n expect(usageIdx).toBeGreaterThanOrEqual(0);\n expect(closeIdx).toBeGreaterThan(usageIdx); // usage flushed first, then close\n expect(executeGQL.mock.calls[usageIdx][1]).toEqual({ agentSessionId: 'sess-1', inputTokens: 33, outputTokens: 4 });\n // Teardown leaves the relay reset (no dangling timer / pending totals).\n expect(internals(service).usageFlushTimer).toBeNull();\n expect(internals(service).pendingUsageInput).toBe(0);\n expect(internals(service).pendingUsageOutput).toBe(0);\n });\n\n it('teardown without pending usage relays nothing (no spurious zero-delta mutation)', async () => {\n await internals(service).teardown(true);\n\n const mutations = executeGQL.mock.calls.map(c => c[0] as string);\n expect(mutations.some(m => m.includes('RelayRealtimeUsage'))).toBe(false);\n expect(mutations.some(m => m.includes('CloseAgentSession'))).toBe(true);\n });\n\n it('flushPendingUsage is a no-op without a session id', async () => {\n internals(service).agentSessionId = null;\n internals(service).onUsageDelta({ InputTokens: 9 });\n\n await internals(service).flushPendingUsage();\n\n expect(executeGQL).not.toHaveBeenCalled();\n // The deltas survive for a later flush once a session id exists.\n expect(internals(service).pendingUsageInput).toBe(9);\n });\n});\n\ndescribe('RealtimeSessionService — OnUsage wiring through wireClientHandlers', () => {\n /** Fake client capturing every handler wireClientHandlers registers. */\n class FakeWiredClient {\n public UsageHandler: ((u: RealtimeClientUsage) => void) | null = null;\n OnStateChange(): void { /* captured elsewhere */ }\n OnTranscript(): void { /* not exercised */ }\n OnToolCall(): void { /* not exercised */ }\n OnError(): void { /* not exercised */ }\n OnInterruption(): void { /* not exercised */ }\n OnUsage(handler: (u: RealtimeClientUsage) => void): void {\n this.UsageHandler = handler;\n }\n }\n\n interface WiringInternals {\n agentSessionId: string | null;\n pendingUsageInput: number;\n pendingUsageOutput: number;\n wireClientHandlers(client: FakeWiredClient): void;\n }\n\n it('registers an OnUsage handler that feeds the accumulator', () => {\n const service = new RealtimeSessionService();\n const seam = service as unknown as WiringInternals;\n seam.agentSessionId = 'sess-1';\n const client = new FakeWiredClient();\n\n seam.wireClientHandlers(client);\n expect(client.UsageHandler).toBeTypeOf('function');\n\n client.UsageHandler?.({ InputTokens: 11, OutputTokens: 3 });\n expect(seam.pendingUsageInput).toBe(11);\n expect(seam.pendingUsageOutput).toBe(3);\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=realtime-session-channels.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-session-channels.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/realtime-session-channels.test.ts"],"names":[],"mappings":""}