@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
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=realtime-pairing.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-pairing.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/realtime-pairing.test.ts"],"names":[],"mappings":""}
@@ -1,207 +0,0 @@
1
- import { describe, it, expect, vi, afterEach } from 'vitest';
2
- import { AIEngineBase } from '@memberjunction/ai-engine-base';
3
- import { BuildRealtimeConfigOverridesJson, ConstrainTargetsToPairings, DefaultPairedTargetId, FilterRealtimeCoAgents, LoadCoAgentPairings, PairingsAllowTarget, SortPairings, } from '../lib/services/realtime-pairing';
4
- /**
5
- * Pure co-agent pairing helpers — the client side of the `MJ: AI Agent Co Agents`
6
- * semantics: a co-agent with ZERO rows is universal (today's flow untouched); with rows,
7
- * its allowed targets are exactly those rows (Sequence order, IsDefault preselected).
8
- * Also covers the pinned `configOverridesJson` envelope builder and the Realtime-type
9
- * co-agent filter.
10
- */
11
- const CO_AGENT = 'C0000000-0000-0000-0000-000000000001';
12
- function pairing(overrides) {
13
- return {
14
- ID: `P-${overrides.TargetAgentID}`,
15
- CoAgentID: CO_AGENT,
16
- TargetAgent: null,
17
- IsDefault: false,
18
- Sequence: 0,
19
- Type: 'CoAgent',
20
- Status: 'Active',
21
- ...overrides,
22
- };
23
- }
24
- const TARGET_A = 'A0000000-0000-0000-0000-00000000000A';
25
- const TARGET_B = 'B0000000-0000-0000-0000-00000000000B';
26
- const TARGET_C = 'D0000000-0000-0000-0000-00000000000D';
27
- const agents = [
28
- { ID: TARGET_A, Name: 'Alpha' },
29
- { ID: TARGET_B, Name: 'Beta' },
30
- { ID: TARGET_C, Name: 'Gamma' },
31
- ];
32
- describe('ConstrainTargetsToPairings', () => {
33
- it('returns the candidates unchanged when there are zero pairing rows (universal co-agent)', () => {
34
- const result = ConstrainTargetsToPairings(agents, []);
35
- expect(result.map(a => a.ID)).toEqual([TARGET_A, TARGET_B, TARGET_C]);
36
- });
37
- it('constrains to exactly the paired targets, in pairing Sequence order', () => {
38
- const pairings = [
39
- pairing({ TargetAgentID: TARGET_C, Sequence: 2 }),
40
- pairing({ TargetAgentID: TARGET_B, Sequence: 1 }),
41
- ];
42
- const result = ConstrainTargetsToPairings(agents, pairings);
43
- expect(result.map(a => a.Name)).toEqual(['Beta', 'Gamma']);
44
- });
45
- it('silently drops paired targets the user cannot see/run (absent from the candidate list)', () => {
46
- const pairings = [
47
- pairing({ TargetAgentID: 'F0000000-0000-0000-0000-0000000000FF', Sequence: 1 }),
48
- pairing({ TargetAgentID: TARGET_A, Sequence: 2 }),
49
- ];
50
- const result = ConstrainTargetsToPairings(agents, pairings);
51
- expect(result.map(a => a.ID)).toEqual([TARGET_A]);
52
- });
53
- it('matches target ids across UUID casing and de-duplicates repeated targets', () => {
54
- const pairings = [
55
- pairing({ TargetAgentID: TARGET_B.toLowerCase(), Sequence: 1 }),
56
- pairing({ TargetAgentID: TARGET_B.toUpperCase(), Sequence: 2 }),
57
- ];
58
- const result = ConstrainTargetsToPairings(agents, pairings);
59
- expect(result.map(a => a.ID)).toEqual([TARGET_B]);
60
- });
61
- });
62
- describe('SortPairings', () => {
63
- it('orders by Sequence ascending with null sequences last, ties by target name', () => {
64
- const rows = [
65
- pairing({ TargetAgentID: TARGET_A, Sequence: null, TargetAgent: 'Alpha' }),
66
- pairing({ TargetAgentID: TARGET_C, Sequence: 1, TargetAgent: 'Gamma' }),
67
- pairing({ TargetAgentID: TARGET_B, Sequence: 1, TargetAgent: 'Beta' }),
68
- ];
69
- expect(SortPairings(rows).map(r => r.TargetAgentID)).toEqual([TARGET_B, TARGET_C, TARGET_A]);
70
- });
71
- it('does not mutate the input array', () => {
72
- const rows = [pairing({ TargetAgentID: TARGET_B, Sequence: 2 }), pairing({ TargetAgentID: TARGET_A, Sequence: 1 })];
73
- SortPairings(rows);
74
- expect(rows[0].TargetAgentID).toBe(TARGET_B);
75
- });
76
- });
77
- describe('DefaultPairedTargetId', () => {
78
- it('returns the IsDefault row target', () => {
79
- const pairings = [
80
- pairing({ TargetAgentID: TARGET_A, Sequence: 1 }),
81
- pairing({ TargetAgentID: TARGET_B, Sequence: 2, IsDefault: true }),
82
- ];
83
- expect(DefaultPairedTargetId(pairings)).toBe(TARGET_B);
84
- });
85
- it('returns the FIRST default in Sequence order when (defensively) more than one exists', () => {
86
- const pairings = [
87
- pairing({ TargetAgentID: TARGET_B, Sequence: 2, IsDefault: true }),
88
- pairing({ TargetAgentID: TARGET_A, Sequence: 1, IsDefault: true }),
89
- ];
90
- expect(DefaultPairedTargetId(pairings)).toBe(TARGET_A);
91
- });
92
- it('returns null when no row is marked default or there are no rows', () => {
93
- expect(DefaultPairedTargetId([pairing({ TargetAgentID: TARGET_A })])).toBeNull();
94
- expect(DefaultPairedTargetId([])).toBeNull();
95
- });
96
- });
97
- describe('PairingsAllowTarget', () => {
98
- it('always allows when there are zero rows (universal co-agent)', () => {
99
- expect(PairingsAllowTarget([], TARGET_A)).toBe(true);
100
- expect(PairingsAllowTarget([], null)).toBe(true);
101
- });
102
- it('allows only the paired targets when rows exist (UUID-casing safe)', () => {
103
- const pairings = [pairing({ TargetAgentID: TARGET_A })];
104
- expect(PairingsAllowTarget(pairings, TARGET_A.toLowerCase())).toBe(true);
105
- expect(PairingsAllowTarget(pairings, TARGET_B)).toBe(false);
106
- });
107
- it('never allows a missing target against a constrained co-agent', () => {
108
- expect(PairingsAllowTarget([pairing({ TargetAgentID: TARGET_A })], null)).toBe(false);
109
- expect(PairingsAllowTarget([pairing({ TargetAgentID: TARGET_A })], '')).toBe(false);
110
- });
111
- });
112
- describe('FilterRealtimeCoAgents', () => {
113
- it('keeps only agents whose Type is Realtime (trim + case-insensitive)', () => {
114
- const candidates = [
115
- { ID: '1', Type: 'Realtime' },
116
- { ID: '2', Type: ' realtime ' },
117
- { ID: '3', Type: 'Loop' },
118
- { ID: '4', Type: null },
119
- ];
120
- expect(FilterRealtimeCoAgents(candidates).map(a => a.ID)).toEqual(['1', '2']);
121
- });
122
- });
123
- describe('LoadCoAgentPairings', () => {
124
- afterEach(() => {
125
- vi.restoreAllMocks();
126
- });
127
- /**
128
- * Stubs the provider-scoped AIEngineBase the loader reads (suite convention: spy on the
129
- * static `GetProviderInstance`, the way other suites spy `AIEngineBase.Instance`). The
130
- * engine cache — not a RunView — is the only data surface the loader touches.
131
- */
132
- function engineReturning(rows) {
133
- const config = vi.fn(async () => {
134
- if (rows instanceof Error) {
135
- throw rows;
136
- }
137
- });
138
- const fakeEngine = {
139
- Config: config,
140
- get AgentCoAgents() {
141
- if (rows instanceof Error) {
142
- throw rows;
143
- }
144
- return rows;
145
- },
146
- };
147
- const getProviderInstance = vi
148
- .spyOn(AIEngineBase, 'GetProviderInstance')
149
- .mockReturnValue(fakeEngine);
150
- return { provider: {}, config, getProviderInstance };
151
- }
152
- it('reads the engine cache filtered to the co-agent (UUID-casing safe) and returns Sequence order', async () => {
153
- const { provider, config, getProviderInstance } = engineReturning([
154
- pairing({ TargetAgentID: TARGET_B, Sequence: 2, CoAgentID: CO_AGENT.toLowerCase() }),
155
- pairing({ TargetAgentID: TARGET_A, Sequence: 1 }),
156
- // Another co-agent's row — must be filtered out client-side.
157
- pairing({ TargetAgentID: TARGET_C, Sequence: 0, CoAgentID: 'E0000000-0000-0000-0000-0000000000EE' }),
158
- // Disabled row — ignored by resolution/pickers.
159
- pairing({ TargetAgentID: TARGET_C, Sequence: 0, Status: 'Disabled' }),
160
- // Reserved relationship type — ignored until its feature ships.
161
- pairing({ TargetAgentID: TARGET_C, Sequence: 0, Type: 'Peer' }),
162
- ]);
163
- const rows = await LoadCoAgentPairings(provider, CO_AGENT);
164
- expect(rows.map(r => r.TargetAgentID)).toEqual([TARGET_A, TARGET_B]);
165
- // Provider-scoped engine instance, lazily configured against the SAME provider.
166
- expect(getProviderInstance).toHaveBeenCalledWith(provider, AIEngineBase);
167
- expect(config).toHaveBeenCalledWith(false, undefined, provider);
168
- });
169
- it('returns plain projected rows carrying the pairing fields the UI consumes', async () => {
170
- const { provider } = engineReturning([
171
- pairing({ TargetAgentID: TARGET_A, Sequence: 3, IsDefault: true, TargetAgent: 'Alpha' }),
172
- ]);
173
- const rows = await LoadCoAgentPairings(provider, CO_AGENT);
174
- expect(rows).toEqual([
175
- {
176
- ID: `P-${TARGET_A}`,
177
- CoAgentID: CO_AGENT,
178
- TargetAgentID: TARGET_A,
179
- TargetAgent: 'Alpha',
180
- IsDefault: true,
181
- Sequence: 3,
182
- },
183
- ]);
184
- });
185
- it('degrades to an empty list (no constraint) when the engine load throws', async () => {
186
- const { provider } = engineReturning(new Error('offline'));
187
- await expect(LoadCoAgentPairings(provider, CO_AGENT)).resolves.toEqual([]);
188
- });
189
- it('returns an empty list without touching the engine when the co-agent id is blank', async () => {
190
- const { provider, getProviderInstance } = engineReturning([]);
191
- await expect(LoadCoAgentPairings(provider, ' ')).resolves.toEqual([]);
192
- expect(getProviderInstance).not.toHaveBeenCalled();
193
- });
194
- });
195
- describe('BuildRealtimeConfigOverridesJson', () => {
196
- it('returns null when nothing was overridden', () => {
197
- expect(BuildRealtimeConfigOverridesJson(null)).toBeNull();
198
- expect(BuildRealtimeConfigOverridesJson(undefined)).toBeNull();
199
- expect(BuildRealtimeConfigOverridesJson(' ')).toBeNull();
200
- });
201
- it('emits the pinned override envelope for an explicit model pick', () => {
202
- const json = BuildRealtimeConfigOverridesJson('model-77');
203
- expect(json).toBe('{"realtime":{"modelPreference":"model-77"}}');
204
- expect(JSON.parse(json)).toEqual({ realtime: { modelPreference: 'model-77' } });
205
- });
206
- });
207
- //# sourceMappingURL=realtime-pairing.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-pairing.test.js","sourceRoot":"","sources":["../../src/__tests__/realtime-pairing.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect, vi, afterEach } from 'vitest';\nimport { IMetadataProvider } from '@memberjunction/core';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport {\n BuildRealtimeConfigOverridesJson,\n ConstrainTargetsToPairings,\n DefaultPairedTargetId,\n FilterRealtimeCoAgents,\n LoadCoAgentPairings,\n PairingsAllowTarget,\n SortPairings,\n RealtimePairedAgentRow,\n} from '../lib/services/realtime-pairing';\n\n/**\n * Pure co-agent pairing helpers — the client side of the `MJ: AI Agent Co Agents`\n * semantics: a co-agent with ZERO rows is universal (today's flow untouched); with rows,\n * its allowed targets are exactly those rows (Sequence order, IsDefault preselected).\n * Also covers the pinned `configOverridesJson` envelope builder and the Realtime-type\n * co-agent filter.\n */\n\nconst CO_AGENT = 'C0000000-0000-0000-0000-000000000001';\n\n/** The engine-cache row shape LoadCoAgentPairings filters on (the new AIAgentCoAgent contract). */\ninterface FakeCoAgentEngineRow extends RealtimePairedAgentRow {\n Type: 'CoAgent' | 'Peer';\n Status: 'Active' | 'Disabled';\n TargetAgentTypeID?: string | null;\n}\n\nfunction pairing(overrides: Partial<FakeCoAgentEngineRow> & { TargetAgentID: string }): FakeCoAgentEngineRow {\n return {\n ID: `P-${overrides.TargetAgentID}`,\n CoAgentID: CO_AGENT,\n TargetAgent: null,\n IsDefault: false,\n Sequence: 0,\n Type: 'CoAgent',\n Status: 'Active',\n ...overrides,\n };\n}\n\nconst TARGET_A = 'A0000000-0000-0000-0000-00000000000A';\nconst TARGET_B = 'B0000000-0000-0000-0000-00000000000B';\nconst TARGET_C = 'D0000000-0000-0000-0000-00000000000D';\n\ninterface FakeAgent { ID: string; Name: string }\nconst agents: FakeAgent[] = [\n { ID: TARGET_A, Name: 'Alpha' },\n { ID: TARGET_B, Name: 'Beta' },\n { ID: TARGET_C, Name: 'Gamma' },\n];\n\ndescribe('ConstrainTargetsToPairings', () => {\n it('returns the candidates unchanged when there are zero pairing rows (universal co-agent)', () => {\n const result = ConstrainTargetsToPairings(agents, []);\n expect(result.map(a => a.ID)).toEqual([TARGET_A, TARGET_B, TARGET_C]);\n });\n\n it('constrains to exactly the paired targets, in pairing Sequence order', () => {\n const pairings = [\n pairing({ TargetAgentID: TARGET_C, Sequence: 2 }),\n pairing({ TargetAgentID: TARGET_B, Sequence: 1 }),\n ];\n const result = ConstrainTargetsToPairings(agents, pairings);\n expect(result.map(a => a.Name)).toEqual(['Beta', 'Gamma']);\n });\n\n it('silently drops paired targets the user cannot see/run (absent from the candidate list)', () => {\n const pairings = [\n pairing({ TargetAgentID: 'F0000000-0000-0000-0000-0000000000FF', Sequence: 1 }),\n pairing({ TargetAgentID: TARGET_A, Sequence: 2 }),\n ];\n const result = ConstrainTargetsToPairings(agents, pairings);\n expect(result.map(a => a.ID)).toEqual([TARGET_A]);\n });\n\n it('matches target ids across UUID casing and de-duplicates repeated targets', () => {\n const pairings = [\n pairing({ TargetAgentID: TARGET_B.toLowerCase(), Sequence: 1 }),\n pairing({ TargetAgentID: TARGET_B.toUpperCase(), Sequence: 2 }),\n ];\n const result = ConstrainTargetsToPairings(agents, pairings);\n expect(result.map(a => a.ID)).toEqual([TARGET_B]);\n });\n});\n\ndescribe('SortPairings', () => {\n it('orders by Sequence ascending with null sequences last, ties by target name', () => {\n const rows = [\n pairing({ TargetAgentID: TARGET_A, Sequence: null, TargetAgent: 'Alpha' }),\n pairing({ TargetAgentID: TARGET_C, Sequence: 1, TargetAgent: 'Gamma' }),\n pairing({ TargetAgentID: TARGET_B, Sequence: 1, TargetAgent: 'Beta' }),\n ];\n expect(SortPairings(rows).map(r => r.TargetAgentID)).toEqual([TARGET_B, TARGET_C, TARGET_A]);\n });\n\n it('does not mutate the input array', () => {\n const rows = [pairing({ TargetAgentID: TARGET_B, Sequence: 2 }), pairing({ TargetAgentID: TARGET_A, Sequence: 1 })];\n SortPairings(rows);\n expect(rows[0].TargetAgentID).toBe(TARGET_B);\n });\n});\n\ndescribe('DefaultPairedTargetId', () => {\n it('returns the IsDefault row target', () => {\n const pairings = [\n pairing({ TargetAgentID: TARGET_A, Sequence: 1 }),\n pairing({ TargetAgentID: TARGET_B, Sequence: 2, IsDefault: true }),\n ];\n expect(DefaultPairedTargetId(pairings)).toBe(TARGET_B);\n });\n\n it('returns the FIRST default in Sequence order when (defensively) more than one exists', () => {\n const pairings = [\n pairing({ TargetAgentID: TARGET_B, Sequence: 2, IsDefault: true }),\n pairing({ TargetAgentID: TARGET_A, Sequence: 1, IsDefault: true }),\n ];\n expect(DefaultPairedTargetId(pairings)).toBe(TARGET_A);\n });\n\n it('returns null when no row is marked default or there are no rows', () => {\n expect(DefaultPairedTargetId([pairing({ TargetAgentID: TARGET_A })])).toBeNull();\n expect(DefaultPairedTargetId([])).toBeNull();\n });\n});\n\ndescribe('PairingsAllowTarget', () => {\n it('always allows when there are zero rows (universal co-agent)', () => {\n expect(PairingsAllowTarget([], TARGET_A)).toBe(true);\n expect(PairingsAllowTarget([], null)).toBe(true);\n });\n\n it('allows only the paired targets when rows exist (UUID-casing safe)', () => {\n const pairings = [pairing({ TargetAgentID: TARGET_A })];\n expect(PairingsAllowTarget(pairings, TARGET_A.toLowerCase())).toBe(true);\n expect(PairingsAllowTarget(pairings, TARGET_B)).toBe(false);\n });\n\n it('never allows a missing target against a constrained co-agent', () => {\n expect(PairingsAllowTarget([pairing({ TargetAgentID: TARGET_A })], null)).toBe(false);\n expect(PairingsAllowTarget([pairing({ TargetAgentID: TARGET_A })], '')).toBe(false);\n });\n});\n\ndescribe('FilterRealtimeCoAgents', () => {\n it('keeps only agents whose Type is Realtime (trim + case-insensitive)', () => {\n const candidates = [\n { ID: '1', Type: 'Realtime' },\n { ID: '2', Type: ' realtime ' },\n { ID: '3', Type: 'Loop' },\n { ID: '4', Type: null },\n ];\n expect(FilterRealtimeCoAgents(candidates).map(a => a.ID)).toEqual(['1', '2']);\n });\n});\n\ndescribe('LoadCoAgentPairings', () => {\n afterEach(() => {\n vi.restoreAllMocks();\n });\n\n /**\n * Stubs the provider-scoped AIEngineBase the loader reads (suite convention: spy on the\n * static `GetProviderInstance`, the way other suites spy `AIEngineBase.Instance`). The\n * engine cache — not a RunView — is the only data surface the loader touches.\n */\n function engineReturning(rows: FakeCoAgentEngineRow[] | Error): {\n provider: IMetadataProvider;\n config: ReturnType<typeof vi.fn>;\n getProviderInstance: ReturnType<typeof vi.spyOn>;\n } {\n const config = vi.fn(async () => {\n if (rows instanceof Error) {\n throw rows;\n }\n });\n const fakeEngine = {\n Config: config,\n get AgentCoAgents(): FakeCoAgentEngineRow[] {\n if (rows instanceof Error) {\n throw rows;\n }\n return rows;\n },\n };\n const getProviderInstance = vi\n .spyOn(AIEngineBase, 'GetProviderInstance')\n .mockReturnValue(fakeEngine as unknown as AIEngineBase);\n return { provider: {} as IMetadataProvider, config, getProviderInstance };\n }\n\n it('reads the engine cache filtered to the co-agent (UUID-casing safe) and returns Sequence order', async () => {\n const { provider, config, getProviderInstance } = engineReturning([\n pairing({ TargetAgentID: TARGET_B, Sequence: 2, CoAgentID: CO_AGENT.toLowerCase() }),\n pairing({ TargetAgentID: TARGET_A, Sequence: 1 }),\n // Another co-agent's row — must be filtered out client-side.\n pairing({ TargetAgentID: TARGET_C, Sequence: 0, CoAgentID: 'E0000000-0000-0000-0000-0000000000EE' }),\n // Disabled row — ignored by resolution/pickers.\n pairing({ TargetAgentID: TARGET_C, Sequence: 0, Status: 'Disabled' }),\n // Reserved relationship type — ignored until its feature ships.\n pairing({ TargetAgentID: TARGET_C, Sequence: 0, Type: 'Peer' }),\n ]);\n const rows = await LoadCoAgentPairings(provider, CO_AGENT);\n expect(rows.map(r => r.TargetAgentID)).toEqual([TARGET_A, TARGET_B]);\n // Provider-scoped engine instance, lazily configured against the SAME provider.\n expect(getProviderInstance).toHaveBeenCalledWith(provider, AIEngineBase);\n expect(config).toHaveBeenCalledWith(false, undefined, provider);\n });\n\n it('returns plain projected rows carrying the pairing fields the UI consumes', async () => {\n const { provider } = engineReturning([\n pairing({ TargetAgentID: TARGET_A, Sequence: 3, IsDefault: true, TargetAgent: 'Alpha' }),\n ]);\n const rows = await LoadCoAgentPairings(provider, CO_AGENT);\n expect(rows).toEqual([\n {\n ID: `P-${TARGET_A}`,\n CoAgentID: CO_AGENT,\n TargetAgentID: TARGET_A,\n TargetAgent: 'Alpha',\n IsDefault: true,\n Sequence: 3,\n },\n ]);\n });\n\n it('degrades to an empty list (no constraint) when the engine load throws', async () => {\n const { provider } = engineReturning(new Error('offline'));\n await expect(LoadCoAgentPairings(provider, CO_AGENT)).resolves.toEqual([]);\n });\n\n it('returns an empty list without touching the engine when the co-agent id is blank', async () => {\n const { provider, getProviderInstance } = engineReturning([]);\n await expect(LoadCoAgentPairings(provider, ' ')).resolves.toEqual([]);\n expect(getProviderInstance).not.toHaveBeenCalled();\n });\n});\n\ndescribe('BuildRealtimeConfigOverridesJson', () => {\n it('returns null when nothing was overridden', () => {\n expect(BuildRealtimeConfigOverridesJson(null)).toBeNull();\n expect(BuildRealtimeConfigOverridesJson(undefined)).toBeNull();\n expect(BuildRealtimeConfigOverridesJson(' ')).toBeNull();\n });\n\n it('emits the pinned override envelope for an explicit model pick', () => {\n const json = BuildRealtimeConfigOverridesJson('model-77');\n expect(json).toBe('{\"realtime\":{\"modelPreference\":\"model-77\"}}');\n expect(JSON.parse(json as string)).toEqual({ realtime: { modelPreference: 'model-77' } });\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- import '@angular/compiler';
2
- //# sourceMappingURL=realtime-review-lifecycle.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-review-lifecycle.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/realtime-review-lifecycle.test.ts"],"names":[],"mappings":"AAEA,OAAO,mBAAmB,CAAC"}
@@ -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":""}