@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,585 +0,0 @@
1
- // The Remote Browser channel imports its standalone Angular surface component (partial-compiled
2
- // Angular libs require the JIT compiler in this node test environment), so load the compiler FIRST.
3
- import '@angular/compiler';
4
- import { describe, it, expect, beforeEach } from 'vitest';
5
- import { EventEmitter } from '@angular/core';
6
- import { MJGlobal } from '@memberjunction/global';
7
- import { BaseRealtimeChannelClient } from '../lib/components/realtime/channels/base-realtime-channel-client';
8
- import { LoadRealtimeRemoteBrowserChannel, RemoteBrowserChannel } from '../lib/components/realtime/remote-browser/remote-browser-channel';
9
- import { MapToViewportCoords, RemoteBrowserSurfaceComponent } from '../lib/components/realtime/remote-browser/remote-browser-surface.component';
10
- import { MapToolToAction, REMOTE_BROWSER_TOOL_DEFINITIONS, REMOTE_BROWSER_TOOL_NAMES, REMOTE_BROWSER_TOOL_PREFIX, RemoteBrowserToolArgError } from '../lib/components/realtime/remote-browser/remote-browser-tools';
11
- LoadRealtimeRemoteBrowserChannel();
12
- /**
13
- * Builds a fake channel context that records `SendContextNote` notes and `ExecuteServerAction`
14
- * calls, and replies with a fixed server response. `sessionId` defaults to a live id so tools
15
- * can run; pass `null` to exercise the no-session path.
16
- */
17
- function makeContext(log, response, sessionId = 'session-1') {
18
- return {
19
- AgentName: 'Sage',
20
- SendContextNote: (text) => log.Notes.push(text),
21
- RequestSave: () => undefined,
22
- SetFocusMode: () => undefined,
23
- SaveAsArtifact: async () => null,
24
- AgentSessionID: sessionId,
25
- ExecuteServerAction: async (query, variables) => {
26
- log.Calls.push({ Query: query, Variables: variables });
27
- return response;
28
- }
29
- };
30
- }
31
- /**
32
- * Shrinks a channel's session-id wait (the {@link BaseRealtimeChannelClient.ResolveAgentSessionId}
33
- * bounds) so the no-session / mint-race tests resolve fast instead of waiting the 8s default.
34
- */
35
- function shrinkSessionWait(channel, timeoutMs = 80, intervalMs = 10) {
36
- const c = channel;
37
- c.SessionIdWaitTimeoutMs = timeoutMs;
38
- c.SessionIdWaitIntervalMs = intervalMs;
39
- }
40
- /**
41
- * Builds a context whose `AgentSessionID` starts null and flips to `id` after `delayMs` — models the
42
- * MINT RACE where the realtime model fires a tool the beat before `mintSession` binds the id. The
43
- * getter (not a static field) is what {@link BaseRealtimeChannelClient.ResolveAgentSessionId} polls.
44
- */
45
- function makeDelayedSessionContext(log, response, id, delayMs) {
46
- let current = null;
47
- setTimeout(() => { current = id; }, delayMs);
48
- return {
49
- AgentName: 'Sage',
50
- SendContextNote: (text) => log.Notes.push(text),
51
- RequestSave: () => undefined,
52
- SetFocusMode: () => undefined,
53
- SaveAsArtifact: async () => null,
54
- get AgentSessionID() { return current; },
55
- ExecuteServerAction: async (query, variables) => {
56
- log.Calls.push({ Query: query, Variables: variables });
57
- return response;
58
- }
59
- };
60
- }
61
- /** Parses a channel tool-result JSON string into a typed shape. */
62
- function parseResult(json) {
63
- return JSON.parse(json);
64
- }
65
- describe('Remote Browser — MapToolToAction (tool → server action)', () => {
66
- it('maps browser_OpenUrl to a navigate action carrying the url', () => {
67
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.OpenUrl, { url: 'https://example.com' }))
68
- .toEqual({ Kind: 'navigate', Url: 'https://example.com' });
69
- });
70
- it('throws a model-readable error when browser_OpenUrl is missing its url', () => {
71
- expect(() => MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.OpenUrl, {})).toThrow(RemoteBrowserToolArgError);
72
- });
73
- it('maps browser_Click by selector', () => {
74
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Click, { selector: '#go' }))
75
- .toEqual({ Kind: 'click', Selector: '#go', X: undefined, Y: undefined });
76
- });
77
- it('maps browser_Click by x/y coordinates', () => {
78
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Click, { x: 12, y: 34 }))
79
- .toEqual({ Kind: 'click', Selector: undefined, X: 12, Y: 34 });
80
- });
81
- it('throws when browser_Click has neither a selector nor both coordinates', () => {
82
- expect(() => MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Click, { x: 12 })).toThrow(RemoteBrowserToolArgError);
83
- expect(() => MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Click, {})).toThrow(RemoteBrowserToolArgError);
84
- });
85
- it('maps browser_Type with optional selector, and allows empty text', () => {
86
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Type, { text: 'hello', selector: '#q' }))
87
- .toEqual({ Kind: 'type', Text: 'hello', Selector: '#q' });
88
- // empty string is a VALID value to type (clears / types nothing) — only a non-string is rejected
89
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Type, { text: '' }))
90
- .toEqual({ Kind: 'type', Text: '', Selector: undefined });
91
- });
92
- it('throws when browser_Type is missing text entirely', () => {
93
- expect(() => MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Type, {})).toThrow(RemoteBrowserToolArgError);
94
- });
95
- it('maps browser_Key, requiring a key', () => {
96
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Key, { key: 'Enter' })).toEqual({ Kind: 'key', Key: 'Enter' });
97
- expect(() => MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Key, {})).toThrow(RemoteBrowserToolArgError);
98
- });
99
- it('maps browser_Scroll with optional deltas + selector', () => {
100
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Scroll, { deltaY: 200 }))
101
- .toEqual({ Kind: 'scroll', DeltaX: undefined, DeltaY: 200, Selector: undefined });
102
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Scroll, {}))
103
- .toEqual({ Kind: 'scroll', DeltaX: undefined, DeltaY: undefined, Selector: undefined });
104
- });
105
- it('maps the argument-less navigation + read tools', () => {
106
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Back, {})).toEqual({ Kind: 'back' });
107
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Forward, {})).toEqual({ Kind: 'forward' });
108
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.GetPageText, {})).toEqual({ Kind: 'getPageText' });
109
- });
110
- it('maps browser_Wait with optional ms + selector', () => {
111
- expect(MapToolToAction(REMOTE_BROWSER_TOOL_NAMES.Wait, { ms: 500 }))
112
- .toEqual({ Kind: 'wait', Ms: 500, Selector: undefined });
113
- });
114
- it('throws on an unknown tool name', () => {
115
- expect(() => MapToolToAction('browser_Teleport', {})).toThrow(RemoteBrowserToolArgError);
116
- });
117
- });
118
- describe('RemoteBrowserChannel — plugin contract + ApplyAgentTool round-trip', () => {
119
- let channel;
120
- let log;
121
- beforeEach(() => {
122
- channel = new RemoteBrowserChannel();
123
- log = { Notes: [], Calls: [] };
124
- });
125
- it('is resolvable from the ClassFactory by its registry ClientPluginClass key', () => {
126
- const registration = MJGlobal.Instance.ClassFactory.GetRegistration(BaseRealtimeChannelClient, 'RealtimeRemoteBrowserChannel');
127
- expect(registration).toBeTruthy();
128
- const instance = MJGlobal.Instance.ClassFactory.CreateInstance(BaseRealtimeChannelClient, 'RealtimeRemoteBrowserChannel');
129
- expect(instance).toBeInstanceOf(RemoteBrowserChannel);
130
- });
131
- it('contributes the channel contract: name, prefix, tab chrome, tool set, surface', () => {
132
- expect(channel.ChannelName).toBe('Remote Browser');
133
- expect(channel.ToolNamePrefix).toBe(REMOTE_BROWSER_TOOL_PREFIX);
134
- expect(channel.TabTitle).toBe('Browser');
135
- expect(channel.TabIcon).toBe('fa-solid fa-globe');
136
- expect(channel.GetToolDefinitions()).toBe(REMOTE_BROWSER_TOOL_DEFINITIONS);
137
- expect(channel.GetSurfaceComponent()).toBe(RemoteBrowserSurfaceComponent);
138
- });
139
- it('supplies first-run onboarding details (heading, description, tips, icon)', () => {
140
- const details = channel.GetOnboardingDetails();
141
- expect(details).not.toBeNull();
142
- expect(details?.Heading).toBe('Remote Browser');
143
- expect(details?.IconClass).toBe('fa-solid fa-globe');
144
- expect(details?.Description?.length).toBeGreaterThan(0);
145
- expect((details?.Tips?.length ?? 0)).toBeGreaterThan(0);
146
- });
147
- it('drives the ExecuteRemoteBrowserAction mutation with flat variables and reports success', async () => {
148
- channel.Initialize(makeContext(log, { ExecuteRemoteBrowserAction: { Success: true, CurrentUrl: 'https://example.com', Detail: null } }));
149
- const resultJson = await channel.ApplyAgentTool('browser_OpenUrl', JSON.stringify({ url: 'https://example.com' }));
150
- const result = parseResult(resultJson);
151
- expect(result.success).toBe(true);
152
- expect(result.currentUrl).toBe('https://example.com');
153
- expect(log.Calls).toHaveLength(1);
154
- expect(log.Calls[0].Query).toContain('ExecuteRemoteBrowserAction');
155
- expect(log.Calls[0].Variables).toMatchObject({
156
- agentSessionID: 'session-1', kind: 'navigate', url: 'https://example.com',
157
- selector: null, x: null, y: null, text: null, key: null, deltaX: null, deltaY: null, ms: null
158
- });
159
- // PERCEPTION: the agent is told where the page went (no spoken reply requested).
160
- expect(log.Notes).toEqual(['[browser] current page: https://example.com']);
161
- });
162
- it('returns the server Detail for read tools and does NOT push a context note without a URL', async () => {
163
- channel.Initialize(makeContext(log, { ExecuteRemoteBrowserAction: { Success: true, CurrentUrl: null, Detail: 'Page text here' } }));
164
- const result = parseResult(await channel.ApplyAgentTool('browser_GetPageText', '{}'));
165
- expect(result.success).toBe(true);
166
- expect(result.detail).toBe('Page text here');
167
- expect(log.Notes).toEqual([]);
168
- });
169
- it('maps a server failure to a failed result with the server Detail (never throws)', async () => {
170
- channel.Initialize(makeContext(log, { ExecuteRemoteBrowserAction: { Success: false, CurrentUrl: null, Detail: 'Selector not found' } }));
171
- const result = parseResult(await channel.ApplyAgentTool('browser_Click', JSON.stringify({ selector: '#missing' })));
172
- expect(result.success).toBe(false);
173
- expect(result.error).toBe('Selector not found');
174
- });
175
- it('returns a failed result (no server call) when arguments are invalid', async () => {
176
- channel.Initialize(makeContext(log, { ExecuteRemoteBrowserAction: { Success: true, CurrentUrl: null, Detail: null } }));
177
- const result = parseResult(await channel.ApplyAgentTool('browser_OpenUrl', '{}'));
178
- expect(result.success).toBe(false);
179
- expect(result.error).toContain('url');
180
- expect(log.Calls).toHaveLength(0); // bad args never reach the server
181
- });
182
- it('returns a failed result when no live session is available', async () => {
183
- channel.Initialize(makeContext(log, null, null));
184
- shrinkSessionWait(channel); // null-forever session: don't wait the full 8s before failing
185
- const result = parseResult(await channel.ApplyAgentTool('browser_Back', '{}'));
186
- expect(result.success).toBe(false);
187
- expect(result.error).toContain('No live browser session');
188
- expect(log.Calls).toHaveLength(0);
189
- });
190
- it('WAITS for the session id (mint race) and then drives the action once it binds', async () => {
191
- // Session id is null at invocation and flips live ~20ms later — the tool should wait, not fail.
192
- channel.Initialize(makeDelayedSessionContext(log, { ExecuteRemoteBrowserAction: { Success: true, CurrentUrl: 'https://x', Detail: null } }, 'session-late', 20));
193
- shrinkSessionWait(channel, 500, 5);
194
- const result = parseResult(await channel.ApplyAgentTool('browser_Back', '{}'));
195
- expect(result.success).toBe(true);
196
- expect(log.Calls).toHaveLength(1);
197
- // The action carried the id that arrived AFTER the tool was invoked.
198
- expect(log.Calls[0].Variables.agentSessionID).toBe('session-late');
199
- });
200
- it('maps a null server response to a failed result (best-effort transport)', async () => {
201
- channel.Initialize(makeContext(log, null));
202
- const result = parseResult(await channel.ApplyAgentTool('browser_Back', '{}'));
203
- expect(result.success).toBe(false);
204
- expect(result.error).toContain('no response from the server');
205
- });
206
- it('tolerates malformed args JSON for an argument-less tool (parses to {})', async () => {
207
- channel.Initialize(makeContext(log, { ExecuteRemoteBrowserAction: { Success: true, CurrentUrl: 'https://x', Detail: null } }));
208
- const result = parseResult(await channel.ApplyAgentTool('browser_Forward', 'not json'));
209
- expect(result.success).toBe(true);
210
- expect(log.Calls[0].Variables.kind).toBe('forward');
211
- });
212
- });
213
- describe('RemoteBrowserChannel — visual interpreter (browser_DescribePage / browser_LocateElement)', () => {
214
- let channel;
215
- let log;
216
- beforeEach(() => {
217
- channel = new RemoteBrowserChannel();
218
- log = { Notes: [], Calls: [] };
219
- });
220
- it('routes browser_DescribePage to the InterpretRemoteBrowserPage mutation and returns the description', async () => {
221
- channel.Initialize(makeContext(log, {
222
- InterpretRemoteBrowserPage: { Description: 'A login page with email and password fields.', Elements: [], Detail: null }
223
- }));
224
- const resultJson = await channel.ApplyAgentTool('browser_DescribePage', '{}');
225
- const result = JSON.parse(resultJson);
226
- expect(log.Calls).toHaveLength(1);
227
- expect(log.Calls[0].Query).toContain('InterpretRemoteBrowserPage');
228
- // DescribePage carries no target query.
229
- expect(log.Calls[0].Variables).toMatchObject({ agentSessionID: 'session-1', query: null });
230
- expect(result.description).toBe('A login page with email and password fields.');
231
- });
232
- it('routes browser_LocateElement to the interpret mutation with the query and returns found + centroid', async () => {
233
- channel.Initialize(makeContext(log, {
234
- InterpretRemoteBrowserPage: {
235
- Description: 'A login page.',
236
- Elements: [{ Label: 'Sign In button', X: 320, Y: 480, Confidence: 0.9 }],
237
- Detail: null
238
- }
239
- }));
240
- const resultJson = await channel.ApplyAgentTool('browser_LocateElement', JSON.stringify({ description: 'the blue Sign In button' }));
241
- const result = JSON.parse(resultJson);
242
- expect(log.Calls).toHaveLength(1);
243
- expect(log.Calls[0].Query).toContain('InterpretRemoteBrowserPage');
244
- expect(log.Calls[0].Variables).toMatchObject({ agentSessionID: 'session-1', query: 'the blue Sign In button' });
245
- expect(result.found).toBe(true);
246
- expect(result.element).toEqual({ label: 'Sign In button', x: 320, y: 480 });
247
- expect(result.all).toHaveLength(1);
248
- });
249
- it('reports found:false with a null element when no element is localized', async () => {
250
- channel.Initialize(makeContext(log, {
251
- InterpretRemoteBrowserPage: { Description: 'A login page.', Elements: [], Detail: null }
252
- }));
253
- const resultJson = await channel.ApplyAgentTool('browser_LocateElement', JSON.stringify({ description: 'the logout link' }));
254
- const result = JSON.parse(resultJson);
255
- expect(result.found).toBe(false);
256
- expect(result.element).toBeNull();
257
- });
258
- it('rejects browser_LocateElement without a description (no server call)', async () => {
259
- channel.Initialize(makeContext(log, { InterpretRemoteBrowserPage: { Description: null, Elements: [], Detail: null } }));
260
- const result = parseResult(await channel.ApplyAgentTool('browser_LocateElement', '{}'));
261
- expect(result.success).toBe(false);
262
- expect(result.error).toContain('description');
263
- expect(log.Calls).toHaveLength(0);
264
- });
265
- it('keeps the null-session guard for the interpreter tools (no server call)', async () => {
266
- channel.Initialize(makeContext(log, null, null));
267
- shrinkSessionWait(channel); // null-forever session: fail fast instead of waiting the full 8s
268
- const result = parseResult(await channel.ApplyAgentTool('browser_DescribePage', '{}'));
269
- expect(result.success).toBe(false);
270
- expect(result.error).toContain('No live browser session');
271
- expect(log.Calls).toHaveLength(0);
272
- });
273
- });
274
- describe('RemoteBrowserChannel — live screencast (pushed frames)', () => {
275
- let channel;
276
- let log;
277
- beforeEach(() => {
278
- channel = new RemoteBrowserChannel();
279
- log = { Notes: [], Calls: [] };
280
- });
281
- /** Minimal surface double recording the frames it was asked to render + its Streaming flag. */
282
- function makeSurface() {
283
- const surface = {
284
- Streaming: false,
285
- Interactive: false,
286
- AudioAvailable: false,
287
- AudioMuted: false,
288
- HumanInput: new EventEmitter(),
289
- AudioMutedChange: new EventEmitter(),
290
- RenderedFrames: [],
291
- RenderFrame(dataBase64) {
292
- this.RenderedFrames.push(dataBase64);
293
- },
294
- SetCurrentUrl() { }
295
- };
296
- return surface;
297
- }
298
- /** Flushes microtasks so BindSurface's fire-and-forget startScreencast resolves. */
299
- function flush() {
300
- return new Promise((resolve) => setTimeout(resolve, 0));
301
- }
302
- it('starts the screencast and flips the surface to Streaming when the backend supports it', async () => {
303
- channel.Initialize(makeContext(log, { StartRemoteBrowserScreencast: { Streaming: true } }));
304
- const surface = makeSurface();
305
- channel.BindSurface(surface);
306
- await flush();
307
- // The start mutation ran with the session id…
308
- const startCall = log.Calls.find(c => c.Query.includes('StartRemoteBrowserScreencast'));
309
- expect(startCall).toBeTruthy();
310
- expect(startCall?.Variables).toMatchObject({ agentSessionID: 'session-1' });
311
- // …and the surface was switched to canvas mode.
312
- expect(surface.Streaming).toBe(true);
313
- });
314
- it('forwards pushed frames to the surface canvas once streaming', async () => {
315
- channel.Initialize(makeContext(log, { StartRemoteBrowserScreencast: { Streaming: true } }));
316
- const surface = makeSurface();
317
- channel.BindSurface(surface);
318
- await flush();
319
- channel.OnScreencastFrame('AAAA');
320
- channel.OnScreencastFrame('BBBB');
321
- expect(surface.RenderedFrames).toEqual(['AAAA', 'BBBB']);
322
- });
323
- it('does NOT flip Streaming or forward frames when the backend lacks ScreenStreaming', async () => {
324
- channel.Initialize(makeContext(log, { StartRemoteBrowserScreencast: { Streaming: false } }));
325
- const surface = makeSurface();
326
- channel.BindSurface(surface);
327
- await flush();
328
- expect(surface.Streaming).toBe(false);
329
- channel.OnScreencastFrame('AAAA');
330
- expect(surface.RenderedFrames).toEqual([]); // ignored — channel is not streaming
331
- });
332
- it('stops the screencast on UnbindSurface when it had started', async () => {
333
- channel.Initialize(makeContext(log, { StartRemoteBrowserScreencast: { Streaming: true } }));
334
- const surface = makeSurface();
335
- channel.BindSurface(surface);
336
- await flush();
337
- channel.UnbindSurface();
338
- await flush();
339
- const stopCall = log.Calls.find(c => c.Query.includes('StopRemoteBrowserScreencast'));
340
- expect(stopCall).toBeTruthy();
341
- expect(stopCall?.Variables).toMatchObject({ agentSessionID: 'session-1' });
342
- // After unbind, late frames are ignored (not streaming, no surface).
343
- channel.OnScreencastFrame('CCCC');
344
- expect(surface.RenderedFrames).toEqual([]);
345
- });
346
- });
347
- describe('RemoteBrowserChannel — human takeover (relay surface input to the server)', () => {
348
- let channel;
349
- let log;
350
- beforeEach(() => {
351
- channel = new RemoteBrowserChannel();
352
- log = { Notes: [], Calls: [] };
353
- });
354
- /** Minimal surface double exposing the takeover wiring: Interactive flag + HumanInput emitter + FetchSelection. */
355
- function makeSurface() {
356
- const surface = {
357
- Streaming: false,
358
- Interactive: false,
359
- AudioAvailable: false,
360
- AudioMuted: false,
361
- HumanInput: new EventEmitter(),
362
- AudioMutedChange: new EventEmitter(),
363
- // BindSurface sets this to the channel's copy-out fetcher; captured so a test can call it.
364
- FetchSelection: null,
365
- RenderFrame() { },
366
- SetCurrentUrl() { }
367
- };
368
- return surface;
369
- }
370
- it('enables takeover by default on bind (Interactive = true)', () => {
371
- channel.Initialize(makeContext(log, { StartRemoteBrowserScreencast: { Streaming: true } }));
372
- const surface = makeSurface();
373
- channel.BindSurface(surface);
374
- expect(surface.Interactive).toBe(true);
375
- });
376
- it('forwards a pointer-click HumanInput to the relay mutation with viewport coords + button', () => {
377
- channel.Initialize(makeContext(log, { RelayRemoteBrowserHumanInput: true }));
378
- const surface = makeSurface();
379
- channel.BindSurface(surface);
380
- surface.HumanInput.emit({ kind: 'pointer-click', x: 320, y: 480, button: 'left' });
381
- const relayCall = log.Calls.find(c => c.Query.includes('RelayRemoteBrowserHumanInput'));
382
- expect(relayCall).toBeTruthy();
383
- expect(relayCall?.Variables).toMatchObject({
384
- agentSessionID: 'session-1', kind: 'pointer-click', x: 320, y: 480, button: 'left', key: null
385
- });
386
- });
387
- it('forwards a scroll HumanInput to the relay mutation with viewport coords + wheel deltas', () => {
388
- channel.Initialize(makeContext(log, { RelayRemoteBrowserHumanInput: true }));
389
- const surface = makeSurface();
390
- channel.BindSurface(surface);
391
- surface.HumanInput.emit({ kind: 'scroll', x: 100, y: 200, deltaX: 12, deltaY: -48 });
392
- const relayCall = log.Calls.find(c => c.Query.includes('RelayRemoteBrowserHumanInput'));
393
- expect(relayCall).toBeTruthy();
394
- expect(relayCall?.Variables).toMatchObject({
395
- agentSessionID: 'session-1', kind: 'scroll', x: 100, y: 200, button: null, key: null, deltaX: 12, deltaY: -48
396
- });
397
- });
398
- it('forwards a key HumanInput with the key string (null pointer coords)', () => {
399
- channel.Initialize(makeContext(log, { RelayRemoteBrowserHumanInput: true }));
400
- const surface = makeSurface();
401
- channel.BindSurface(surface);
402
- surface.HumanInput.emit({ kind: 'key', key: 'Enter' });
403
- const relayCall = log.Calls.find(c => c.Query.includes('RelayRemoteBrowserHumanInput'));
404
- expect(relayCall?.Variables).toMatchObject({
405
- agentSessionID: 'session-1', kind: 'key', x: null, y: null, button: null, key: 'Enter', modifiers: null
406
- });
407
- });
408
- it('relays held modifiers as a comma-separated list (Ctrl/Cmd+A select-all)', () => {
409
- channel.Initialize(makeContext(log, { RelayRemoteBrowserHumanInput: true }));
410
- const surface = makeSurface();
411
- channel.BindSurface(surface);
412
- surface.HumanInput.emit({ kind: 'key', key: 'a', modifiers: ['Control'] });
413
- const relayCall = log.Calls.find(c => c.Query.includes('RelayRemoteBrowserHumanInput'));
414
- expect(relayCall?.Variables).toMatchObject({ kind: 'key', key: 'a', modifiers: 'Control' });
415
- });
416
- it('relays a shift-click with the modifier carried on the pointer-click', () => {
417
- channel.Initialize(makeContext(log, { RelayRemoteBrowserHumanInput: true }));
418
- const surface = makeSurface();
419
- channel.BindSurface(surface);
420
- surface.HumanInput.emit({ kind: 'pointer-click', x: 5, y: 6, button: 'left', modifiers: ['Shift'] });
421
- const relayCall = log.Calls.find(c => c.Query.includes('RelayRemoteBrowserHumanInput'));
422
- expect(relayCall?.Variables).toMatchObject({ kind: 'pointer-click', x: 5, y: 6, modifiers: 'Shift' });
423
- });
424
- it('relays a click-drag as pointer-down then pointer-up (drag text selection)', () => {
425
- channel.Initialize(makeContext(log, { RelayRemoteBrowserHumanInput: true }));
426
- const surface = makeSurface();
427
- channel.BindSurface(surface);
428
- surface.HumanInput.emit({ kind: 'pointer-down', x: 10, y: 20 });
429
- surface.HumanInput.emit({ kind: 'pointer-up', x: 80, y: 20 });
430
- const relayed = log.Calls
431
- .filter(c => c.Query.includes('RelayRemoteBrowserHumanInput'))
432
- .map(c => c.Variables.kind);
433
- expect(relayed).toEqual(['pointer-down', 'pointer-up']);
434
- });
435
- it('forwards a text (paste) HumanInput carrying the pasted text (paste-in)', () => {
436
- channel.Initialize(makeContext(log, { RelayRemoteBrowserHumanInput: true }));
437
- const surface = makeSurface();
438
- channel.BindSurface(surface);
439
- surface.HumanInput.emit({ kind: 'text', text: 'clipboard contents' });
440
- const relayCall = log.Calls.find(c => c.Query.includes('RelayRemoteBrowserHumanInput'));
441
- expect(relayCall?.Variables).toMatchObject({
442
- agentSessionID: 'session-1', kind: 'text', text: 'clipboard contents', x: null, y: null, key: null
443
- });
444
- });
445
- it('wires FetchSelection (copy-out) to the GetRemoteBrowserSelection query and returns its text', async () => {
446
- channel.Initialize(makeContext(log, { GetRemoteBrowserSelection: { Text: 'remote selected text' } }));
447
- const surface = makeSurface();
448
- channel.BindSurface(surface);
449
- // BindSurface installs the copy-out fetcher; calling it should hit the selection query.
450
- const text = await surface.FetchSelection?.();
451
- expect(text).toBe('remote selected text');
452
- const selCall = log.Calls.find(c => c.Query.includes('GetRemoteBrowserSelection'));
453
- expect(selCall?.Variables).toMatchObject({ agentSessionID: 'session-1' });
454
- });
455
- it('FetchSelection returns "" on a null server response (best-effort copy-out)', async () => {
456
- channel.Initialize(makeContext(log, null));
457
- const surface = makeSurface();
458
- channel.BindSurface(surface);
459
- expect(await surface.FetchSelection?.()).toBe('');
460
- });
461
- it('stops forwarding after UnbindSurface (subscription torn down)', () => {
462
- channel.Initialize(makeContext(log, { RelayRemoteBrowserHumanInput: true }));
463
- const surface = makeSurface();
464
- channel.BindSurface(surface);
465
- channel.UnbindSurface();
466
- surface.HumanInput.emit({ kind: 'pointer-move', x: 1, y: 2 });
467
- expect(log.Calls.find(c => c.Query.includes('RelayRemoteBrowserHumanInput'))).toBeUndefined();
468
- });
469
- });
470
- describe('RemoteBrowserChannel — browser_AchieveGoal (async start + poll)', () => {
471
- let channel;
472
- let log;
473
- beforeEach(() => {
474
- channel = new RemoteBrowserChannel();
475
- log = { Notes: [], Calls: [] };
476
- });
477
- /** Shrinks the goal poll cadence/deadline so tests don't wait the 2.5s/5min production bounds. */
478
- function shrinkGoalPoll(c, intervalMs = 5, timeoutMs = 500) {
479
- const x = c;
480
- x.GoalPollIntervalMs = intervalMs;
481
- x.GoalPollTimeoutMs = timeoutMs;
482
- }
483
- /**
484
- * Builds a context that answers the START mutation with a `Running` + GoalRunID, then answers each
485
- * subsequent POLL query from `pollResults` in order (the last entry repeats if polled further).
486
- * `startPayload`/poll entries are the inner payload objects (or null to simulate a dropped response).
487
- */
488
- function makeGoalContext(startPayload, pollResults) {
489
- let pollIdx = 0;
490
- return {
491
- AgentName: 'Sage',
492
- SendContextNote: (text) => log.Notes.push(text),
493
- RequestSave: () => undefined,
494
- SetFocusMode: () => undefined,
495
- SaveAsArtifact: async () => null,
496
- AgentSessionID: 'session-1',
497
- ExecuteServerAction: async (query, variables) => {
498
- log.Calls.push({ Query: query, Variables: variables });
499
- if (query.includes('ExecuteRemoteBrowserGoal')) {
500
- return (startPayload ? { ExecuteRemoteBrowserGoal: startPayload } : null);
501
- }
502
- if (query.includes('GetRemoteBrowserGoalResult')) {
503
- const r = pollResults[Math.min(pollIdx, pollResults.length - 1)];
504
- pollIdx++;
505
- return (r ? { GetRemoteBrowserGoalResult: r } : null);
506
- }
507
- return null;
508
- }
509
- };
510
- }
511
- it('starts the goal, polls past Running ticks, and returns the terminal success', async () => {
512
- channel.Initialize(makeGoalContext({ Success: true, GoalRunID: 'g1', Status: 'Running' }, [
513
- { Status: 'Running', GoalRunID: 'g1' },
514
- { Status: 'Running', GoalRunID: 'g1' },
515
- { Success: true, GoalRunID: 'g1', Status: 'Completed', StepCount: 6, CurrentUrl: 'https://done', Detail: 'Goal done' }
516
- ]));
517
- shrinkGoalPoll(channel);
518
- const result = parseResult(await channel.ApplyAgentTool('browser_AchieveGoal', JSON.stringify({ goal: 'open the dashboard' })));
519
- expect(result.success).toBe(true);
520
- expect(result.detail).toBe('Goal done');
521
- // One start mutation + at least one poll that returned terminal.
522
- expect(log.Calls.some(c => c.Query.includes('ExecuteRemoteBrowserGoal'))).toBe(true);
523
- expect(log.Calls.filter(c => c.Query.includes('GetRemoteBrowserGoalResult')).length).toBeGreaterThanOrEqual(1);
524
- // The start mutation carried the goal; polls carried the GoalRunID.
525
- const startCall = log.Calls.find(c => c.Query.includes('ExecuteRemoteBrowserGoal'));
526
- expect(startCall?.Variables).toMatchObject({ agentSessionID: 'session-1', goal: 'open the dashboard' });
527
- const pollCall = log.Calls.find(c => c.Query.includes('GetRemoteBrowserGoalResult'));
528
- expect(pollCall?.Variables).toMatchObject({ agentSessionID: 'session-1', goalRunID: 'g1' });
529
- });
530
- it('surfaces the terminal failure detail when the goal completes unsuccessfully', async () => {
531
- channel.Initialize(makeGoalContext({ Success: true, GoalRunID: 'g1', Status: 'Running' }, [{ Success: false, GoalRunID: 'g1', Status: 'Impossible', Detail: 'The page has no login form.' }]));
532
- shrinkGoalPoll(channel);
533
- const result = parseResult(await channel.ApplyAgentTool('browser_AchieveGoal', JSON.stringify({ goal: 'log in' })));
534
- expect(result.success).toBe(false);
535
- expect(result.error).toBe('The page has no login form.');
536
- });
537
- it('fails fast when the goal could not be started (no response from the server)', async () => {
538
- channel.Initialize(makeGoalContext(null, []));
539
- shrinkGoalPoll(channel);
540
- const result = parseResult(await channel.ApplyAgentTool('browser_AchieveGoal', JSON.stringify({ goal: 'do a thing' })));
541
- expect(result.success).toBe(false);
542
- expect(result.error).toContain('could not be started');
543
- // No poll attempted when the start failed.
544
- expect(log.Calls.some(c => c.Query.includes('GetRemoteBrowserGoalResult'))).toBe(false);
545
- });
546
- it('reports "still running" when the goal never reaches a terminal status before the deadline', async () => {
547
- channel.Initialize(makeGoalContext({ Success: true, GoalRunID: 'g1', Status: 'Running' }, [{ Status: 'Running', GoalRunID: 'g1' }] // every poll stays Running
548
- ));
549
- shrinkGoalPoll(channel, 5, 30); // tiny deadline so the loop exits fast
550
- const result = parseResult(await channel.ApplyAgentTool('browser_AchieveGoal', JSON.stringify({ goal: 'browse forever' })));
551
- expect(result.success).toBe(false);
552
- expect(result.error).toContain('still be running');
553
- });
554
- it('requires a goal argument (no server call)', async () => {
555
- channel.Initialize(makeGoalContext({ Success: true, GoalRunID: 'g1', Status: 'Running' }, []));
556
- const result = parseResult(await channel.ApplyAgentTool('browser_AchieveGoal', '{}'));
557
- expect(result.success).toBe(false);
558
- expect(result.error).toContain('goal');
559
- expect(log.Calls).toHaveLength(0);
560
- });
561
- });
562
- describe('MapToViewportCoords (display → viewport coordinate mapping)', () => {
563
- it('maps a click on a scaled-up canvas back to viewport pixels', () => {
564
- // Canvas internal resolution 1280x720, displayed at 640x360 (2x downscale) at offset (100, 50).
565
- // A click at display (420, 230) → local (320, 180) → viewport (640, 360).
566
- const rect = { left: 100, top: 50, width: 640, height: 360 };
567
- expect(MapToViewportCoords(420, 230, rect, 1280, 720)).toEqual({ x: 640, y: 360 });
568
- });
569
- it('maps 1:1 when the display size equals the internal resolution', () => {
570
- const rect = { left: 0, top: 0, width: 800, height: 600 };
571
- expect(MapToViewportCoords(120, 90, rect, 800, 600)).toEqual({ x: 120, y: 90 });
572
- });
573
- it('rounds to integer viewport coordinates', () => {
574
- const rect = { left: 0, top: 0, width: 300, height: 300 };
575
- // 101/300 * 1000 = 336.67 → 337 ; 100/300 * 1000 = 333.33 → 333
576
- expect(MapToViewportCoords(101, 100, rect, 1000, 1000)).toEqual({ x: 337, y: 333 });
577
- });
578
- it('returns null on a zero-size rect (divide-by-zero guard)', () => {
579
- expect(MapToViewportCoords(10, 10, { left: 0, top: 0, width: 0, height: 0 }, 1280, 720)).toBeNull();
580
- });
581
- it('returns null on an un-sized canvas', () => {
582
- expect(MapToViewportCoords(10, 10, { left: 0, top: 0, width: 640, height: 360 }, 0, 0)).toBeNull();
583
- });
584
- });
585
- //# sourceMappingURL=remote-browser-channel.test.js.map