@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,103 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
2
- import { RealtimeSessionService } from '../lib/services/realtime-session.service';
3
- class FakeRealtimeClient {
4
- ToolResults = [];
5
- ContextNotes = [];
6
- SendToolResult(callId, resultJson) {
7
- this.ToolResults.push({ CallID: callId, ResultJson: resultJson });
8
- }
9
- SendContextNote(text) {
10
- this.ContextNotes.push(text);
11
- }
12
- }
13
- function internals(service) {
14
- return service;
15
- }
16
- describe('RealtimeSessionService — client-executed UI tool routing', () => {
17
- let service;
18
- let fakeClient;
19
- beforeEach(() => {
20
- service = new RealtimeSessionService();
21
- fakeClient = new FakeRealtimeClient();
22
- internals(service).client = fakeClient;
23
- });
24
- it('routes a prefix-matched tool call to the LOCAL handler and feeds its result back', async () => {
25
- const handler = vi.fn((toolName, argsJson) => JSON.stringify({ success: true, summary: `${toolName}:${argsJson}` }));
26
- service.RegisterClientToolHandler('Whiteboard_', handler);
27
- await internals(service).handleToolCall({
28
- CallID: 'call-1',
29
- ToolName: 'Whiteboard_AddNote',
30
- ArgumentsJson: '{"text":"hi"}'
31
- });
32
- expect(handler).toHaveBeenCalledWith('Whiteboard_AddNote', '{"text":"hi"}');
33
- expect(fakeClient.ToolResults).toEqual([
34
- { CallID: 'call-1', ResultJson: JSON.stringify({ success: true, summary: 'Whiteboard_AddNote:{"text":"hi"}' }) }
35
- ]);
36
- });
37
- it('supports async handlers', async () => {
38
- service.RegisterClientToolHandler('Whiteboard_', async () => '{"success":true}');
39
- await internals(service).handleToolCall({ CallID: 'call-2', ToolName: 'Whiteboard_MoveItem', ArgumentsJson: '{}' });
40
- expect(fakeClient.ToolResults).toEqual([{ CallID: 'call-2', ResultJson: '{"success":true}' }]);
41
- });
42
- it('wraps a thrown handler error as { success:false, error } so the model can narrate it', async () => {
43
- service.RegisterClientToolHandler('Whiteboard_', () => {
44
- throw new Error('board offline');
45
- });
46
- await internals(service).handleToolCall({ CallID: 'call-3', ToolName: 'Whiteboard_AddShape', ArgumentsJson: '{}' });
47
- expect(fakeClient.ToolResults).toHaveLength(1);
48
- expect(JSON.parse(fakeClient.ToolResults[0].ResultJson)).toEqual({ success: false, error: 'board offline' });
49
- });
50
- it('does NOT capture non-matching tool names (they take the server-relay path)', async () => {
51
- const handler = vi.fn(() => '{"success":true}');
52
- service.RegisterClientToolHandler('Whiteboard_', handler);
53
- // No agentSessionId is minted, so the server path fails fast — the point is the
54
- // local handler is never consulted and the model still receives an error result.
55
- await internals(service).handleToolCall({ CallID: 'call-4', ToolName: 'invoke-target-agent', ArgumentsJson: '{}' });
56
- expect(handler).not.toHaveBeenCalled();
57
- expect(fakeClient.ToolResults).toHaveLength(1);
58
- expect(JSON.parse(fakeClient.ToolResults[0].ResultJson)).toMatchObject({
59
- error: expect.stringContaining('No active agent session')
60
- });
61
- });
62
- it('UnregisterClientToolHandler removes the route — later calls fall through to the server path', async () => {
63
- const handler = vi.fn(() => '{"success":true}');
64
- service.RegisterClientToolHandler('Whiteboard_', handler);
65
- service.UnregisterClientToolHandler('Whiteboard_');
66
- await internals(service).handleToolCall({ CallID: 'call-5', ToolName: 'Whiteboard_AddNote', ArgumentsJson: '{}' });
67
- expect(handler).not.toHaveBeenCalled();
68
- expect(JSON.parse(fakeClient.ToolResults[0].ResultJson)).toMatchObject({
69
- error: expect.stringContaining('No active agent session')
70
- });
71
- });
72
- it('re-registering the same prefix replaces the handler', async () => {
73
- service.RegisterClientToolHandler('Whiteboard_', () => '{"v":1}');
74
- service.RegisterClientToolHandler('Whiteboard_', () => '{"v":2}');
75
- await internals(service).handleToolCall({ CallID: 'call-6', ToolName: 'Whiteboard_AddText', ArgumentsJson: '{}' });
76
- expect(fakeClient.ToolResults).toEqual([{ CallID: 'call-6', ResultJson: '{"v":2}' }]);
77
- });
78
- });
79
- describe('RealtimeSessionService — SendContextNote guard', () => {
80
- it('is a no-op when no session is live (no client / closed state)', () => {
81
- const service = new RealtimeSessionService();
82
- const fakeClient = new FakeRealtimeClient();
83
- internals(service).client = fakeClient;
84
- // ConnectionState is 'closed' by default — the note must NOT reach the client.
85
- service.SendContextNote('[whiteboard] {"added":[]}');
86
- expect(fakeClient.ContextNotes).toEqual([]);
87
- });
88
- it('ignores empty / whitespace-only notes', () => {
89
- const service = new RealtimeSessionService();
90
- const fakeClient = new FakeRealtimeClient();
91
- internals(service).client = fakeClient;
92
- service.SendContextNote(' ');
93
- expect(fakeClient.ContextNotes).toEqual([]);
94
- });
95
- });
96
- describe('RealtimeSessionService — SaveChannelState guards', () => {
97
- it('returns false when no session id is available (live or explicit)', async () => {
98
- const service = new RealtimeSessionService();
99
- const saved = await service.SaveChannelState('Whiteboard', '{"items":[]}');
100
- expect(saved).toBe(false);
101
- });
102
- });
103
- //# sourceMappingURL=realtime-session-client-tools.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-session-client-tools.test.js","sourceRoot":"","sources":["../../src/__tests__/realtime-session-client-tools.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect, beforeEach, vi } from 'vitest';\nimport { RealtimeSessionService } from '../lib/services/realtime-session.service';\n\n/**\n * CLIENT-EXECUTED UI TOOL routing (the live whiteboard's `Whiteboard_*` path).\n *\n * The registry + routing live behind the service's private tool-call handler, so these tests\n * reach it through a narrow typed seam: a fake realtime client capturing `SendToolResult`, and\n * direct invocation of `handleToolCall` with a synthetic provider tool-call frame.\n */\n\n/** The private surface the tests drive — no `any`, just the members under test. */\ninterface RealtimeSessionInternals {\n client: FakeRealtimeClient | null;\n handleToolCall(call: { CallID: string; ToolName: string; ArgumentsJson: string }): Promise<void>;\n}\n\nclass FakeRealtimeClient {\n public ToolResults: Array<{ CallID: string; ResultJson: string }> = [];\n public ContextNotes: string[] = [];\n public SendToolResult(callId: string, resultJson: string): void {\n this.ToolResults.push({ CallID: callId, ResultJson: resultJson });\n }\n public SendContextNote(text: string): void {\n this.ContextNotes.push(text);\n }\n}\n\nfunction internals(service: RealtimeSessionService): RealtimeSessionInternals {\n return service as unknown as RealtimeSessionInternals;\n}\n\ndescribe('RealtimeSessionService — client-executed UI tool routing', () => {\n let service: RealtimeSessionService;\n let fakeClient: FakeRealtimeClient;\n\n beforeEach(() => {\n service = new RealtimeSessionService();\n fakeClient = new FakeRealtimeClient();\n internals(service).client = fakeClient;\n });\n\n it('routes a prefix-matched tool call to the LOCAL handler and feeds its result back', async () => {\n const handler = vi.fn((toolName: string, argsJson: string) =>\n JSON.stringify({ success: true, summary: `${toolName}:${argsJson}` })\n );\n service.RegisterClientToolHandler('Whiteboard_', handler);\n\n await internals(service).handleToolCall({\n CallID: 'call-1',\n ToolName: 'Whiteboard_AddNote',\n ArgumentsJson: '{\"text\":\"hi\"}'\n });\n\n expect(handler).toHaveBeenCalledWith('Whiteboard_AddNote', '{\"text\":\"hi\"}');\n expect(fakeClient.ToolResults).toEqual([\n { CallID: 'call-1', ResultJson: JSON.stringify({ success: true, summary: 'Whiteboard_AddNote:{\"text\":\"hi\"}' }) }\n ]);\n });\n\n it('supports async handlers', async () => {\n service.RegisterClientToolHandler('Whiteboard_', async () => '{\"success\":true}');\n\n await internals(service).handleToolCall({ CallID: 'call-2', ToolName: 'Whiteboard_MoveItem', ArgumentsJson: '{}' });\n\n expect(fakeClient.ToolResults).toEqual([{ CallID: 'call-2', ResultJson: '{\"success\":true}' }]);\n });\n\n it('wraps a thrown handler error as { success:false, error } so the model can narrate it', async () => {\n service.RegisterClientToolHandler('Whiteboard_', () => {\n throw new Error('board offline');\n });\n\n await internals(service).handleToolCall({ CallID: 'call-3', ToolName: 'Whiteboard_AddShape', ArgumentsJson: '{}' });\n\n expect(fakeClient.ToolResults).toHaveLength(1);\n expect(JSON.parse(fakeClient.ToolResults[0].ResultJson)).toEqual({ success: false, error: 'board offline' });\n });\n\n it('does NOT capture non-matching tool names (they take the server-relay path)', async () => {\n const handler = vi.fn(() => '{\"success\":true}');\n service.RegisterClientToolHandler('Whiteboard_', handler);\n\n // No agentSessionId is minted, so the server path fails fast — the point is the\n // local handler is never consulted and the model still receives an error result.\n await internals(service).handleToolCall({ CallID: 'call-4', ToolName: 'invoke-target-agent', ArgumentsJson: '{}' });\n\n expect(handler).not.toHaveBeenCalled();\n expect(fakeClient.ToolResults).toHaveLength(1);\n expect(JSON.parse(fakeClient.ToolResults[0].ResultJson)).toMatchObject({\n error: expect.stringContaining('No active agent session')\n });\n });\n\n it('UnregisterClientToolHandler removes the route — later calls fall through to the server path', async () => {\n const handler = vi.fn(() => '{\"success\":true}');\n service.RegisterClientToolHandler('Whiteboard_', handler);\n service.UnregisterClientToolHandler('Whiteboard_');\n\n await internals(service).handleToolCall({ CallID: 'call-5', ToolName: 'Whiteboard_AddNote', ArgumentsJson: '{}' });\n\n expect(handler).not.toHaveBeenCalled();\n expect(JSON.parse(fakeClient.ToolResults[0].ResultJson)).toMatchObject({\n error: expect.stringContaining('No active agent session')\n });\n });\n\n it('re-registering the same prefix replaces the handler', async () => {\n service.RegisterClientToolHandler('Whiteboard_', () => '{\"v\":1}');\n service.RegisterClientToolHandler('Whiteboard_', () => '{\"v\":2}');\n\n await internals(service).handleToolCall({ CallID: 'call-6', ToolName: 'Whiteboard_AddText', ArgumentsJson: '{}' });\n\n expect(fakeClient.ToolResults).toEqual([{ CallID: 'call-6', ResultJson: '{\"v\":2}' }]);\n });\n});\n\ndescribe('RealtimeSessionService — SendContextNote guard', () => {\n it('is a no-op when no session is live (no client / closed state)', () => {\n const service = new RealtimeSessionService();\n const fakeClient = new FakeRealtimeClient();\n internals(service).client = fakeClient;\n\n // ConnectionState is 'closed' by default — the note must NOT reach the client.\n service.SendContextNote('[whiteboard] {\"added\":[]}');\n expect(fakeClient.ContextNotes).toEqual([]);\n });\n\n it('ignores empty / whitespace-only notes', () => {\n const service = new RealtimeSessionService();\n const fakeClient = new FakeRealtimeClient();\n internals(service).client = fakeClient;\n\n service.SendContextNote(' ');\n expect(fakeClient.ContextNotes).toEqual([]);\n });\n});\n\ndescribe('RealtimeSessionService — SaveChannelState guards', () => {\n it('returns false when no session id is available (live or explicit)', async () => {\n const service = new RealtimeSessionService();\n const saved = await service.SaveChannelState('Whiteboard', '{\"items\":[]}');\n expect(saved).toBe(false);\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=realtime-session-minimized.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-session-minimized.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/realtime-session-minimized.test.ts"],"names":[],"mappings":""}
@@ -1,32 +0,0 @@
1
- import { describe, it, expect, beforeEach } from 'vitest';
2
- import { RealtimeSessionService } from '../lib/services/realtime-session.service';
3
- describe('RealtimeSessionService — Minimized$ presentation state', () => {
4
- let service;
5
- beforeEach(() => {
6
- service = new RealtimeSessionService();
7
- });
8
- it('starts NOT minimized', () => {
9
- expect(service.IsMinimized).toBe(false);
10
- });
11
- it('SetMinimized(true) flips the state and emits on Minimized$', () => {
12
- const seen = [];
13
- service.Minimized$.subscribe(v => seen.push(v));
14
- service.SetMinimized(true);
15
- expect(service.IsMinimized).toBe(true);
16
- service.SetMinimized(false);
17
- expect(service.IsMinimized).toBe(false);
18
- expect(seen).toEqual([false, true, false]);
19
- });
20
- it('is idempotent — repeated same-value calls do not re-emit', () => {
21
- const seen = [];
22
- service.Minimized$.subscribe(v => seen.push(v));
23
- service.SetMinimized(true);
24
- service.SetMinimized(true);
25
- service.SetMinimized(true);
26
- expect(seen).toEqual([false, true]);
27
- });
28
- it('exposes no agent session id before a session is minted', () => {
29
- expect(service.CurrentAgentSessionId).toBeNull();
30
- });
31
- });
32
- //# sourceMappingURL=realtime-session-minimized.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-session-minimized.test.js","sourceRoot":"","sources":["../../src/__tests__/realtime-session-minimized.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAElF,QAAQ,CAAC,wDAAwD,EAAE,GAAG,EAAE;IACtE,IAAI,OAA+B,CAAC;IAEpC,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,GAAG,IAAI,sBAAsB,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,IAAI,GAAc,EAAE,CAAC;QAC3B,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhD,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEvC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAC5B,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAExC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,IAAI,GAAc,EAAE,CAAC;QAC3B,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhD,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAE3B,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,QAAQ,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, it, expect, beforeEach } from 'vitest';\nimport { RealtimeSessionService } from '../lib/services/realtime-session.service';\n\ndescribe('RealtimeSessionService — Minimized$ presentation state', () => {\n let service: RealtimeSessionService;\n\n beforeEach(() => {\n service = new RealtimeSessionService();\n });\n\n it('starts NOT minimized', () => {\n expect(service.IsMinimized).toBe(false);\n });\n\n it('SetMinimized(true) flips the state and emits on Minimized$', () => {\n const seen: boolean[] = [];\n service.Minimized$.subscribe(v => seen.push(v));\n\n service.SetMinimized(true);\n expect(service.IsMinimized).toBe(true);\n\n service.SetMinimized(false);\n expect(service.IsMinimized).toBe(false);\n\n expect(seen).toEqual([false, true, false]);\n });\n\n it('is idempotent — repeated same-value calls do not re-emit', () => {\n const seen: boolean[] = [];\n service.Minimized$.subscribe(v => seen.push(v));\n\n service.SetMinimized(true);\n service.SetMinimized(true);\n service.SetMinimized(true);\n\n expect(seen).toEqual([false, true]);\n });\n\n it('exposes no agent session id before a session is minted', () => {\n expect(service.CurrentAgentSessionId).toBeNull();\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=realtime-session-mint.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-session-mint.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/realtime-session-mint.test.ts"],"names":[],"mappings":""}
@@ -1,69 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
2
- import { RealtimeSessionService } from '../lib/services/realtime-session.service';
3
- function internals(service) {
4
- return service;
5
- }
6
- const OK_RESULT = {
7
- StartRealtimeClientSession: {
8
- AgentSessionId: 'session-1',
9
- ConversationId: 'conv-1',
10
- Provider: 'openai',
11
- Model: 'gpt-realtime',
12
- EphemeralToken: 'ek_abc',
13
- ExpiresAt: '2026-01-01T00:00:00Z',
14
- SessionConfigJson: '{}'
15
- }
16
- };
17
- describe('RealtimeSessionService — mintSession variable passthrough', () => {
18
- let service;
19
- let executeGQL;
20
- beforeEach(() => {
21
- service = new RealtimeSessionService();
22
- executeGQL = vi.fn(async () => OK_RESULT);
23
- // The service's gql() seam is just `this.Provider as GraphQLDataProvider` — a fake with
24
- // ExecuteGQL is all the mint path touches.
25
- service.Provider = { ExecuteGQL: executeGQL };
26
- });
27
- /** Returns the variables object the mutation was invoked with. */
28
- async function mintAndGetVariables(coAgentId, preferredModelId, configOverridesJson) {
29
- await internals(service).mintSession('target-1', 'conv-1', null, preferredModelId, null, coAgentId, configOverridesJson);
30
- expect(executeGQL).toHaveBeenCalledTimes(1);
31
- return executeGQL.mock.calls[0][1];
32
- }
33
- it('threads coAgentId into the mutation variables when supplied', async () => {
34
- const variables = await mintAndGetVariables('co-explicit');
35
- expect(variables['coAgentId']).toBe('co-explicit');
36
- expect(variables['targetAgentId']).toBe('target-1');
37
- });
38
- it('sends coAgentId: null when omitted (server metadata drives the co-agent choice)', async () => {
39
- const variables = await mintAndGetVariables();
40
- expect(variables['coAgentId']).toBeNull();
41
- });
42
- it('declares $coAgentId in the mutation document and passes it to the field', async () => {
43
- await mintAndGetVariables('co-explicit');
44
- const mutation = executeGQL.mock.calls[0][0];
45
- expect(mutation).toContain('$coAgentId: String');
46
- expect(mutation).toContain('coAgentId: $coAgentId');
47
- });
48
- it('keeps the preferredModelId passthrough intact alongside coAgentId', async () => {
49
- const variables = await mintAndGetVariables('co-explicit', 'model-77');
50
- expect(variables['preferredModelId']).toBe('model-77');
51
- expect(variables['coAgentId']).toBe('co-explicit');
52
- });
53
- it('threads configOverridesJson into the mutation variables when supplied', async () => {
54
- const overrides = '{"realtime":{"modelPreference":"model-77"}}';
55
- const variables = await mintAndGetVariables('co-explicit', 'model-77', overrides);
56
- expect(variables['configOverridesJson']).toBe(overrides);
57
- });
58
- it('sends configOverridesJson: null when omitted (server defaults — today\'s behavior)', async () => {
59
- const variables = await mintAndGetVariables();
60
- expect(variables['configOverridesJson']).toBeNull();
61
- });
62
- it('declares $configOverridesJson in the mutation document and passes it to the field', async () => {
63
- await mintAndGetVariables(null, null, '{"realtime":{}}');
64
- const mutation = executeGQL.mock.calls[0][0];
65
- expect(mutation).toContain('$configOverridesJson: String');
66
- expect(mutation).toContain('configOverridesJson: $configOverridesJson');
67
- });
68
- });
69
- //# sourceMappingURL=realtime-session-mint.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-session-mint.test.js","sourceRoot":"","sources":["../../src/__tests__/realtime-session-mint.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect, beforeEach, vi } from 'vitest';\nimport { IMetadataProvider } from '@memberjunction/core';\nimport { RealtimeSessionService } from '../lib/services/realtime-session.service';\n\n/**\n * Session-mint passthrough — verifies the `StartRealtimeClientSession` mutation variables the\n * service sends, in particular the optional `coAgentId` (highest-precedence step of the server's\n * co-agent resolution chain) and the optional `configOverridesJson` (authorization-gated session\n * config overrides, e.g. `{\"realtime\":{\"modelPreference\":…}}`) alongside the previously-added\n * `preferredModelId`.\n *\n * The mint path lives behind the private `mintSession` method, reached through a narrow typed\n * seam (same approach as the client-tools suite) with the service's `Provider` swapped for a\n * fake whose `ExecuteGQL` captures the mutation + variables.\n */\n\n/** The private surface under test — no `any`, just the member driven by the suite. */\ninterface RealtimeSessionInternals {\n mintSession(\n targetAgentId: string,\n conversationId?: string | null,\n lastSessionId?: string | null,\n preferredModelId?: string | null,\n clientTools?: Array<{ Name: string; Description: string; ParametersSchema: object }> | null,\n coAgentId?: string | null,\n configOverridesJson?: string | null\n ): Promise<unknown>;\n}\n\nfunction internals(service: RealtimeSessionService): RealtimeSessionInternals {\n return service as unknown as RealtimeSessionInternals;\n}\n\nconst OK_RESULT = {\n StartRealtimeClientSession: {\n AgentSessionId: 'session-1',\n ConversationId: 'conv-1',\n Provider: 'openai',\n Model: 'gpt-realtime',\n EphemeralToken: 'ek_abc',\n ExpiresAt: '2026-01-01T00:00:00Z',\n SessionConfigJson: '{}'\n }\n};\n\ndescribe('RealtimeSessionService — mintSession variable passthrough', () => {\n let service: RealtimeSessionService;\n let executeGQL: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n service = new RealtimeSessionService();\n executeGQL = vi.fn(async () => OK_RESULT);\n // The service's gql() seam is just `this.Provider as GraphQLDataProvider` — a fake with\n // ExecuteGQL is all the mint path touches.\n service.Provider = { ExecuteGQL: executeGQL } as unknown as IMetadataProvider;\n });\n\n /** Returns the variables object the mutation was invoked with. */\n async function mintAndGetVariables(\n coAgentId?: string | null,\n preferredModelId?: string | null,\n configOverridesJson?: string | null\n ): Promise<Record<string, unknown>> {\n await internals(service).mintSession('target-1', 'conv-1', null, preferredModelId, null, coAgentId, configOverridesJson);\n expect(executeGQL).toHaveBeenCalledTimes(1);\n return executeGQL.mock.calls[0][1] as Record<string, unknown>;\n }\n\n it('threads coAgentId into the mutation variables when supplied', async () => {\n const variables = await mintAndGetVariables('co-explicit');\n expect(variables['coAgentId']).toBe('co-explicit');\n expect(variables['targetAgentId']).toBe('target-1');\n });\n\n it('sends coAgentId: null when omitted (server metadata drives the co-agent choice)', async () => {\n const variables = await mintAndGetVariables();\n expect(variables['coAgentId']).toBeNull();\n });\n\n it('declares $coAgentId in the mutation document and passes it to the field', async () => {\n await mintAndGetVariables('co-explicit');\n const mutation = executeGQL.mock.calls[0][0] as string;\n expect(mutation).toContain('$coAgentId: String');\n expect(mutation).toContain('coAgentId: $coAgentId');\n });\n\n it('keeps the preferredModelId passthrough intact alongside coAgentId', async () => {\n const variables = await mintAndGetVariables('co-explicit', 'model-77');\n expect(variables['preferredModelId']).toBe('model-77');\n expect(variables['coAgentId']).toBe('co-explicit');\n });\n\n it('threads configOverridesJson into the mutation variables when supplied', async () => {\n const overrides = '{\"realtime\":{\"modelPreference\":\"model-77\"}}';\n const variables = await mintAndGetVariables('co-explicit', 'model-77', overrides);\n expect(variables['configOverridesJson']).toBe(overrides);\n });\n\n it('sends configOverridesJson: null when omitted (server defaults — today\\'s behavior)', async () => {\n const variables = await mintAndGetVariables();\n expect(variables['configOverridesJson']).toBeNull();\n });\n\n it('declares $configOverridesJson in the mutation document and passes it to the field', async () => {\n await mintAndGetVariables(null, null, '{\"realtime\":{}}');\n const mutation = executeGQL.mock.calls[0][0] as string;\n expect(mutation).toContain('$configOverridesJson: String');\n expect(mutation).toContain('configOverridesJson: $configOverridesJson');\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=realtime-session-policy.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"realtime-session-policy.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/realtime-session-policy.test.ts"],"names":[],"mappings":""}
@@ -1,303 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
2
- import { RealtimeSessionService } from '../lib/services/realtime-session.service';
3
- /**
4
- * Provider-agnostic POLICY surfaces of the voice session service that no other suite
5
- * covered: typed-text injection (`SendText`), mic mute toggling, the client→UI
6
- * connection-state mapping (incl. the 'connected' suppression and the error latch),
7
- * session-config parsing resilience, and the `SaveChannelState` failure paths.
8
- *
9
- * Same narrow typed-seam approach as the sibling voice-session suites: a fake realtime
10
- * client + fake Provider, with private members reached through a typed internals cast.
11
- */
12
- class FakeRealtimeClient {
13
- TextsSent = [];
14
- MuteCalls = [];
15
- ToolResults = [];
16
- SendText(text) {
17
- this.TextsSent.push(text);
18
- }
19
- SetMuted(muted) {
20
- this.MuteCalls.push(muted);
21
- }
22
- SendToolResult(callId, resultJson) {
23
- this.ToolResults.push({ CallID: callId, ResultJson: resultJson });
24
- }
25
- async Disconnect() {
26
- // no-op
27
- }
28
- }
29
- function internals(service) {
30
- return service;
31
- }
32
- function latestState(service) {
33
- let state = 'closed';
34
- service.ConnectionState$.subscribe(s => (state = s)).unsubscribe();
35
- return state;
36
- }
37
- describe('RealtimeSessionService — SendText (typed turn injection)', () => {
38
- let service;
39
- let client;
40
- let executeGQL;
41
- beforeEach(() => {
42
- service = new RealtimeSessionService();
43
- client = new FakeRealtimeClient();
44
- executeGQL = vi.fn(async () => ({}));
45
- service.Provider = { ExecuteGQL: executeGQL };
46
- internals(service).client = client;
47
- internals(service).agentSessionId = 'sess-1';
48
- });
49
- it('injects the trimmed text and relays it through the SAME user-turn path as speech', async () => {
50
- internals(service).onClientStateChange('listening');
51
- service.SendText(' hello there ');
52
- await vi.waitFor(() => expect(executeGQL).toHaveBeenCalled());
53
- expect(client.TextsSent).toEqual(['hello there']);
54
- let captions = [];
55
- service.Captions$.subscribe(c => (captions = c)).unsubscribe();
56
- expect(captions).toEqual([{ Role: 'User', Text: 'hello there' }]);
57
- expect(executeGQL).toHaveBeenCalledWith(expect.stringContaining('RelayRealtimeTranscript'), expect.objectContaining({ agentSessionId: 'sess-1', role: 'user', text: 'hello there' }));
58
- });
59
- it('is a no-op for empty / whitespace-only text', () => {
60
- internals(service).onClientStateChange('listening');
61
- service.SendText('');
62
- service.SendText(' ');
63
- expect(client.TextsSent).toEqual([]);
64
- expect(executeGQL).not.toHaveBeenCalled();
65
- });
66
- it('is a no-op when the session is not live (state closed)', () => {
67
- service.SendText('hello');
68
- expect(client.TextsSent).toEqual([]);
69
- expect(executeGQL).not.toHaveBeenCalled();
70
- });
71
- it('is a no-op when there is no client', () => {
72
- internals(service).onClientStateChange('listening');
73
- internals(service).client = null;
74
- service.SendText('hello');
75
- expect(executeGQL).not.toHaveBeenCalled();
76
- });
77
- it('still captions the turn when no agent session id exists (relay silently skipped)', async () => {
78
- internals(service).onClientStateChange('listening');
79
- internals(service).agentSessionId = null;
80
- service.SendText('typed while minting');
81
- await Promise.resolve(); // let the relay microtask settle
82
- expect(client.TextsSent).toEqual(['typed while minting']);
83
- let captions = [];
84
- service.Captions$.subscribe(c => (captions = c)).unsubscribe();
85
- expect(captions).toEqual([{ Role: 'User', Text: 'typed while minting' }]);
86
- expect(executeGQL).not.toHaveBeenCalled();
87
- });
88
- });
89
- describe('RealtimeSessionService — ToggleMute', () => {
90
- let service;
91
- let client;
92
- beforeEach(() => {
93
- service = new RealtimeSessionService();
94
- client = new FakeRealtimeClient();
95
- internals(service).client = client;
96
- });
97
- it('returns false and touches nothing when there is no local stream', () => {
98
- expect(service.ToggleMute()).toBe(false);
99
- expect(client.MuteCalls).toEqual([]);
100
- });
101
- it('returns false when the stream has no audio tracks', () => {
102
- internals(service).localStream = { getAudioTracks: () => [], getTracks: () => [] };
103
- expect(service.ToggleMute()).toBe(false);
104
- expect(client.MuteCalls).toEqual([]);
105
- });
106
- it('mutes via the client when the track is currently enabled', () => {
107
- const track = { enabled: true, stop: () => undefined };
108
- internals(service).localStream = { getAudioTracks: () => [track], getTracks: () => [track] };
109
- expect(service.ToggleMute()).toBe(true);
110
- expect(client.MuteCalls).toEqual([true]);
111
- });
112
- it('unmutes via the client when the track is currently disabled', () => {
113
- const track = { enabled: false, stop: () => undefined };
114
- internals(service).localStream = { getAudioTracks: () => [track], getTracks: () => [track] };
115
- expect(service.ToggleMute()).toBe(false);
116
- expect(client.MuteCalls).toEqual([false]);
117
- });
118
- });
119
- describe('RealtimeSessionService — client→UI connection-state mapping', () => {
120
- let service;
121
- beforeEach(() => {
122
- service = new RealtimeSessionService();
123
- });
124
- it("maps 'connecting' / 'listening' / 'speaking' straight through", () => {
125
- internals(service).onClientStateChange('connecting');
126
- expect(latestState(service)).toBe('connecting');
127
- internals(service).onClientStateChange('listening');
128
- expect(latestState(service)).toBe('listening');
129
- internals(service).onClientStateChange('speaking');
130
- expect(latestState(service)).toBe('speaking');
131
- });
132
- it("suppresses 'connected' — the UI stays in its prior state until the control channel opens", () => {
133
- internals(service).onClientStateChange('connecting');
134
- internals(service).onClientStateChange('connected');
135
- expect(latestState(service)).toBe('connecting');
136
- });
137
- it("maps 'closed' through when no error was recorded", () => {
138
- internals(service).onClientStateChange('listening');
139
- internals(service).onClientStateChange('closed');
140
- expect(latestState(service)).toBe('closed');
141
- });
142
- it("never lets a trailing 'closed' overwrite a terminal 'error'", () => {
143
- internals(service).onClientStateChange('error');
144
- internals(service).onClientStateChange('closed');
145
- expect(latestState(service)).toBe('error');
146
- });
147
- });
148
- describe('RealtimeSessionService — parseSessionConfig resilience', () => {
149
- let service;
150
- beforeEach(() => {
151
- service = new RealtimeSessionService();
152
- });
153
- it('parses a valid config JSON', () => {
154
- expect(internals(service).parseSessionConfig('{"instructions":"be brief"}')).toEqual({ instructions: 'be brief' });
155
- });
156
- it('returns an empty config for null (nothing to apply — the session still opens)', () => {
157
- expect(internals(service).parseSessionConfig(null)).toEqual({});
158
- });
159
- it('returns an empty config (logged) for malformed JSON', () => {
160
- const error = vi.spyOn(console, 'error').mockImplementation(() => undefined);
161
- expect(internals(service).parseSessionConfig('{not json')).toEqual({});
162
- expect(error).toHaveBeenCalledWith(expect.stringContaining('SessionConfigJson'), expect.any(Error));
163
- });
164
- });
165
- describe('RealtimeSessionService — EndVoiceSession / teardown lifecycle', () => {
166
- let service;
167
- let client;
168
- let executeGQL;
169
- beforeEach(() => {
170
- service = new RealtimeSessionService();
171
- client = new FakeRealtimeClient();
172
- executeGQL = vi.fn(async () => ({}));
173
- service.Provider = { ExecuteGQL: executeGQL };
174
- });
175
- it('is a safe no-op when no session is active and none was minted', async () => {
176
- await service.EndVoiceSession();
177
- expect(executeGQL).not.toHaveBeenCalled();
178
- expect(latestState(service)).toBe('closed');
179
- });
180
- it('closes the server session, disconnects the client, stops the mic, and resets state', async () => {
181
- const track = { enabled: true, stop: vi.fn() };
182
- const disconnect = vi.spyOn(client, 'Disconnect');
183
- internals(service).client = client;
184
- internals(service).agentSessionId = 'sess-9';
185
- internals(service).localStream = { getAudioTracks: () => [track], getTracks: () => [track] };
186
- internals(service).onClientStateChange('listening');
187
- service.SetMinimized(true);
188
- await service.EndVoiceSession();
189
- expect(executeGQL).toHaveBeenCalledWith(expect.stringContaining('CloseAgentSession'), { agentSessionId: 'sess-9' });
190
- expect(disconnect).toHaveBeenCalledTimes(1);
191
- expect(track.stop).toHaveBeenCalled();
192
- expect(service.CurrentAgentSessionId).toBeNull();
193
- expect(service.IsMinimized).toBe(false);
194
- expect(service.IsActive).toBe(false);
195
- expect(latestState(service)).toBe('closed');
196
- });
197
- it('teardown clears the client-tool handler registry', async () => {
198
- internals(service).agentSessionId = 'sess-9';
199
- const handler = vi.fn(() => '{"success":true}');
200
- service.RegisterClientToolHandler('Whiteboard_', handler);
201
- await service.EndVoiceSession();
202
- // After teardown the prefix no longer routes locally — the registry was cleared.
203
- internals(service).client = client;
204
- internals(service).agentSessionId = 'sess-10';
205
- await service
206
- .handleToolCall({ CallID: 'c1', ToolName: 'Whiteboard_AddNote', ArgumentsJson: '{}' });
207
- expect(handler).not.toHaveBeenCalled();
208
- });
209
- it('a CloseAgentSession failure is contained (logged) and teardown still completes', async () => {
210
- const error = vi.spyOn(console, 'error').mockImplementation(() => undefined);
211
- executeGQL.mockRejectedValueOnce(new Error('server gone'));
212
- internals(service).agentSessionId = 'sess-9';
213
- await service.EndVoiceSession();
214
- expect(service.CurrentAgentSessionId).toBeNull();
215
- expect(error).toHaveBeenCalledWith(expect.stringContaining('Failed to close server session'), expect.any(Error));
216
- });
217
- it("teardown preserves a terminal 'error' state instead of overwriting it with 'closed'", async () => {
218
- internals(service).agentSessionId = 'sess-9';
219
- internals(service).onClientStateChange('error');
220
- await service.EndVoiceSession();
221
- expect(latestState(service)).toBe('error');
222
- });
223
- });
224
- describe('RealtimeSessionService — SaveChannelState (explicit id + failure paths)', () => {
225
- let service;
226
- let executeGQL;
227
- beforeEach(() => {
228
- service = new RealtimeSessionService();
229
- executeGQL = vi.fn(async () => ({ SaveSessionChannelState: true }));
230
- service.Provider = { ExecuteGQL: executeGQL };
231
- });
232
- it('uses the EXPLICIT session id even when no live session exists (the teardown-flush case)', async () => {
233
- const saved = await service.SaveChannelState('Whiteboard', '{"v":1}', 'closed-session-7');
234
- expect(saved).toBe(true);
235
- expect(executeGQL).toHaveBeenCalledWith(expect.stringContaining('SaveSessionChannelState'), { agentSessionId: 'closed-session-7', channelName: 'Whiteboard', stateJson: '{"v":1}' });
236
- });
237
- it('prefers the explicit id over the live session id', async () => {
238
- internals(service).agentSessionId = 'live-session';
239
- await service.SaveChannelState('Whiteboard', '{}', 'captured-session');
240
- expect(executeGQL.mock.calls[0][1]).toMatchObject({ agentSessionId: 'captured-session' });
241
- });
242
- it('returns false (logged, never thrown) when the mutation throws', async () => {
243
- const error = vi.spyOn(console, 'error').mockImplementation(() => undefined);
244
- executeGQL.mockRejectedValueOnce(new Error('network down'));
245
- const saved = await service.SaveChannelState('Whiteboard', '{}', 'sess-1');
246
- expect(saved).toBe(false);
247
- expect(error).toHaveBeenCalledWith(expect.stringContaining('Failed to save channel state'), expect.any(Error));
248
- });
249
- it('returns false when the server reports a falsy result', async () => {
250
- executeGQL.mockResolvedValueOnce({ SaveSessionChannelState: false });
251
- expect(await service.SaveChannelState('Whiteboard', '{}', 'sess-1')).toBe(false);
252
- executeGQL.mockResolvedValueOnce({});
253
- expect(await service.SaveChannelState('Whiteboard', '{}', 'sess-1')).toBe(false);
254
- });
255
- });
256
- describe('RealtimeSessionService — transcript correction (ReplacesPrevious)', () => {
257
- let service;
258
- let executeGQL;
259
- function transcriptInternals(s) {
260
- return s;
261
- }
262
- function captionsOf(s) {
263
- let captions = [];
264
- s.Captions$.subscribe(c => (captions = c)).unsubscribe();
265
- return captions;
266
- }
267
- beforeEach(() => {
268
- service = new RealtimeSessionService();
269
- executeGQL = vi.fn(async () => ({}));
270
- service.Provider = { ExecuteGQL: executeGQL };
271
- internals(service).agentSessionId = 'sess-1';
272
- });
273
- it('a correction REPLACES the last assistant caption in place and relays update semantics', async () => {
274
- const t = transcriptInternals(service);
275
- await t.onClientTranscript({ Role: 'Assistant', Text: 'The answer is forty-two and', IsFinal: true, Kind: 'normal' });
276
- await t.onClientTranscript({ Role: 'Assistant', Text: 'The answer is', IsFinal: true, Kind: 'normal', ReplacesPrevious: true });
277
- expect(captionsOf(service)).toEqual([{ Role: 'Assistant', Text: 'The answer is' }]); // replaced, not appended
278
- expect(executeGQL).toHaveBeenLastCalledWith(expect.stringContaining('RelayRealtimeTranscript'), expect.objectContaining({ role: 'assistant', text: 'The answer is', replacesPrevious: true }));
279
- });
280
- it('a correction replaces the LAST assistant caption, leaving later user turns alone', async () => {
281
- const t = transcriptInternals(service);
282
- await t.onClientTranscript({ Role: 'Assistant', Text: 'truncated turn that', IsFinal: true, Kind: 'normal' });
283
- await t.onClientTranscript({ Role: 'User', Text: 'wait, stop', IsFinal: true, Kind: 'normal' });
284
- await t.onClientTranscript({ Role: 'Assistant', Text: 'truncated turn', IsFinal: true, Kind: 'normal', ReplacesPrevious: true });
285
- expect(captionsOf(service)).toEqual([
286
- { Role: 'Assistant', Text: 'truncated turn' },
287
- { Role: 'User', Text: 'wait, stop' }
288
- ]);
289
- });
290
- it('a correction with NO prior assistant caption appends (never lost)', async () => {
291
- await transcriptInternals(service).onClientTranscript({
292
- Role: 'Assistant', Text: 'orphan correction', IsFinal: true, Kind: 'normal', ReplacesPrevious: true
293
- });
294
- expect(captionsOf(service)).toEqual([{ Role: 'Assistant', Text: 'orphan correction' }]);
295
- });
296
- it('ordinary finals relay with replacesPrevious=false', async () => {
297
- await transcriptInternals(service).onClientTranscript({
298
- Role: 'Assistant', Text: 'normal turn', IsFinal: true, Kind: 'normal'
299
- });
300
- expect(executeGQL).toHaveBeenLastCalledWith(expect.stringContaining('RelayRealtimeTranscript'), expect.objectContaining({ replacesPrevious: false }));
301
- });
302
- });
303
- //# sourceMappingURL=realtime-session-policy.test.js.map