@memberjunction/ng-conversations 6.2.0-edge.0 → 6.2.0-edge.2

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/README.md +43 -2
  2. package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts +19 -3
  3. package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts.map +1 -1
  4. package/dist/lib/components/active-tasks/active-tasks-panel.component.js +39 -7
  5. package/dist/lib/components/active-tasks/active-tasks-panel.component.js.map +1 -1
  6. package/dist/lib/components/agent/active-agent-indicator.component.d.ts +74 -6
  7. package/dist/lib/components/agent/active-agent-indicator.component.d.ts.map +1 -1
  8. package/dist/lib/components/agent/active-agent-indicator.component.js +111 -21
  9. package/dist/lib/components/agent/active-agent-indicator.component.js.map +1 -1
  10. package/dist/lib/components/agent/agent-process-panel.component.d.ts +31 -5
  11. package/dist/lib/components/agent/agent-process-panel.component.d.ts.map +1 -1
  12. package/dist/lib/components/agent/agent-process-panel.component.js +71 -15
  13. package/dist/lib/components/agent/agent-process-panel.component.js.map +1 -1
  14. package/dist/lib/components/artifact/artifact-share-modal.component.d.ts +65 -9
  15. package/dist/lib/components/artifact/artifact-share-modal.component.d.ts.map +1 -1
  16. package/dist/lib/components/artifact/artifact-share-modal.component.js +169 -57
  17. package/dist/lib/components/artifact/artifact-share-modal.component.js.map +1 -1
  18. package/dist/lib/components/attachment/image-viewer.component.d.ts +77 -11
  19. package/dist/lib/components/attachment/image-viewer.component.d.ts.map +1 -1
  20. package/dist/lib/components/attachment/image-viewer.component.js +181 -47
  21. package/dist/lib/components/attachment/image-viewer.component.js.map +1 -1
  22. package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts +129 -19
  23. package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts.map +1 -1
  24. package/dist/lib/components/collection/artifact-collection-picker-modal.component.js +350 -116
  25. package/dist/lib/components/collection/artifact-collection-picker-modal.component.js.map +1 -1
  26. package/dist/lib/components/collection/artifact-create-modal.component.d.ts +60 -8
  27. package/dist/lib/components/collection/artifact-create-modal.component.d.ts.map +1 -1
  28. package/dist/lib/components/collection/artifact-create-modal.component.js +130 -46
  29. package/dist/lib/components/collection/artifact-create-modal.component.js.map +1 -1
  30. package/dist/lib/components/collection/collection-artifact-card.component.d.ts +63 -3
  31. package/dist/lib/components/collection/collection-artifact-card.component.d.ts.map +1 -1
  32. package/dist/lib/components/collection/collection-artifact-card.component.js +113 -19
  33. package/dist/lib/components/collection/collection-artifact-card.component.js.map +1 -1
  34. package/dist/lib/components/collection/collection-form-modal.component.d.ts +54 -8
  35. package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
  36. package/dist/lib/components/collection/collection-form-modal.component.js +130 -46
  37. package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
  38. package/dist/lib/components/collection/collection-share-modal.component.d.ts +70 -10
  39. package/dist/lib/components/collection/collection-share-modal.component.d.ts.map +1 -1
  40. package/dist/lib/components/collection/collection-share-modal.component.js +175 -53
  41. package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -1
  42. package/dist/lib/components/collection/collection-tree.component.d.ts +89 -9
  43. package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
  44. package/dist/lib/components/collection/collection-tree.component.js +220 -70
  45. package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
  46. package/dist/lib/components/collection/collection-view.component.d.ts +89 -11
  47. package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
  48. package/dist/lib/components/collection/collection-view.component.js +154 -40
  49. package/dist/lib/components/collection/collection-view.component.js.map +1 -1
  50. package/dist/lib/components/collection/collections-full-view.component.d.ts +390 -38
  51. package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
  52. package/dist/lib/components/collection/collections-full-view.component.js +951 -367
  53. package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
  54. package/dist/lib/components/composer/ai-composer.component.d.ts +213 -18
  55. package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -1
  56. package/dist/lib/components/composer/ai-composer.component.js +388 -44
  57. package/dist/lib/components/composer/ai-composer.component.js.map +1 -1
  58. package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts +12 -1
  59. package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts.map +1 -1
  60. package/dist/lib/components/conversation/conversation-agent-picker.component.js +26 -4
  61. package/dist/lib/components/conversation/conversation-agent-picker.component.js.map +1 -1
  62. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +1191 -124
  63. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  64. package/dist/lib/components/conversation/conversation-chat-area.component.js +2816 -785
  65. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  66. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +139 -19
  67. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
  68. package/dist/lib/components/conversation/conversation-empty-state.component.js +296 -59
  69. package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
  70. package/dist/lib/components/conversation/conversation-list.component.d.ts +579 -78
  71. package/dist/lib/components/conversation/conversation-list.component.d.ts.map +1 -1
  72. package/dist/lib/components/conversation/conversation-list.component.js +2322 -823
  73. package/dist/lib/components/conversation/conversation-list.component.js.map +1 -1
  74. package/dist/lib/components/conversation/pinned-messages-panel.component.d.ts +42 -4
  75. package/dist/lib/components/conversation/pinned-messages-panel.component.d.ts.map +1 -1
  76. package/dist/lib/components/conversation/pinned-messages-panel.component.js +93 -21
  77. package/dist/lib/components/conversation/pinned-messages-panel.component.js.map +1 -1
  78. package/dist/lib/components/dialogs/input-dialog.component.d.ts +57 -11
  79. package/dist/lib/components/dialogs/input-dialog.component.d.ts.map +1 -1
  80. package/dist/lib/components/dialogs/input-dialog.component.js +128 -16
  81. package/dist/lib/components/dialogs/input-dialog.component.js.map +1 -1
  82. package/dist/lib/components/dialogs/rating-dialog.component.d.ts +68 -10
  83. package/dist/lib/components/dialogs/rating-dialog.component.d.ts.map +1 -1
  84. package/dist/lib/components/dialogs/rating-dialog.component.js +151 -27
  85. package/dist/lib/components/dialogs/rating-dialog.component.js.map +1 -1
  86. package/dist/lib/components/export/export-modal.component.d.ts +84 -10
  87. package/dist/lib/components/export/export-modal.component.d.ts.map +1 -1
  88. package/dist/lib/components/export/export-modal.component.js +173 -49
  89. package/dist/lib/components/export/export-modal.component.js.map +1 -1
  90. package/dist/lib/components/global-tasks/global-tasks-panel.component.d.ts +29 -3
  91. package/dist/lib/components/global-tasks/global-tasks-panel.component.d.ts.map +1 -1
  92. package/dist/lib/components/global-tasks/global-tasks-panel.component.js +58 -12
  93. package/dist/lib/components/global-tasks/global-tasks-panel.component.js.map +1 -1
  94. package/dist/lib/components/library/library-full-view.component.d.ts +57 -8
  95. package/dist/lib/components/library/library-full-view.component.d.ts.map +1 -1
  96. package/dist/lib/components/library/library-full-view.component.js +119 -35
  97. package/dist/lib/components/library/library-full-view.component.js.map +1 -1
  98. package/dist/lib/components/members/members-modal.component.d.ts +76 -10
  99. package/dist/lib/components/members/members-modal.component.d.ts.map +1 -1
  100. package/dist/lib/components/members/members-modal.component.js +164 -50
  101. package/dist/lib/components/members/members-modal.component.js.map +1 -1
  102. package/dist/lib/components/message/actionable-commands.component.d.ts +49 -5
  103. package/dist/lib/components/message/actionable-commands.component.d.ts.map +1 -1
  104. package/dist/lib/components/message/actionable-commands.component.js +140 -26
  105. package/dist/lib/components/message/actionable-commands.component.js.map +1 -1
  106. package/dist/lib/components/message/conversation-message-rating.component.d.ts +46 -10
  107. package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
  108. package/dist/lib/components/message/conversation-message-rating.component.js +120 -36
  109. package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
  110. package/dist/lib/components/message/message-input.component.d.ts +613 -74
  111. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  112. package/dist/lib/components/message/message-input.component.js +1390 -422
  113. package/dist/lib/components/message/message-input.component.js.map +1 -1
  114. package/dist/lib/components/message/message-item.component.d.ts +490 -29
  115. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  116. package/dist/lib/components/message/message-item.component.js +1088 -244
  117. package/dist/lib/components/message/message-item.component.js.map +1 -1
  118. package/dist/lib/components/message/message-list.component.d.ts +297 -29
  119. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  120. package/dist/lib/components/message/message-list.component.js +598 -123
  121. package/dist/lib/components/message/message-list.component.js.map +1 -1
  122. package/dist/lib/components/navigation/conversation-navigation.component.d.ts +64 -5
  123. package/dist/lib/components/navigation/conversation-navigation.component.d.ts.map +1 -1
  124. package/dist/lib/components/navigation/conversation-navigation.component.js +101 -11
  125. package/dist/lib/components/navigation/conversation-navigation.component.js.map +1 -1
  126. package/dist/lib/components/notification/activity-indicator.component.d.ts +6 -2
  127. package/dist/lib/components/notification/activity-indicator.component.d.ts.map +1 -1
  128. package/dist/lib/components/notification/activity-indicator.component.js +13 -3
  129. package/dist/lib/components/notification/activity-indicator.component.js.map +1 -1
  130. package/dist/lib/components/notification/notification-badge.component.d.ts +15 -3
  131. package/dist/lib/components/notification/notification-badge.component.d.ts.map +1 -1
  132. package/dist/lib/components/notification/notification-badge.component.js +36 -8
  133. package/dist/lib/components/notification/notification-badge.component.js.map +1 -1
  134. package/dist/lib/components/overlay/chat-overlay.component.d.ts +1 -1
  135. package/dist/lib/components/overlay/chat-overlay.component.js +4 -4
  136. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  137. package/dist/lib/components/project/project-form-modal.component.d.ts +93 -11
  138. package/dist/lib/components/project/project-form-modal.component.d.ts.map +1 -1
  139. package/dist/lib/components/project/project-form-modal.component.js +348 -87
  140. package/dist/lib/components/project/project-form-modal.component.js.map +1 -1
  141. package/dist/lib/components/project/project-selector.component.d.ts +78 -8
  142. package/dist/lib/components/project/project-selector.component.d.ts.map +1 -1
  143. package/dist/lib/components/project/project-selector.component.js +177 -46
  144. package/dist/lib/components/project/project-selector.component.js.map +1 -1
  145. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +1 -1
  146. package/dist/lib/components/realtime/realtime-activity-rail.component.js +2 -2
  147. package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
  148. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +1 -1
  149. package/dist/lib/components/realtime/realtime-delegation-card.component.js +2 -2
  150. package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
  151. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +2 -2
  152. package/dist/lib/components/realtime/realtime-session-overlay.component.js +18 -18
  153. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  154. package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts +47 -23
  155. package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts.map +1 -1
  156. package/dist/lib/components/realtime/realtime-session-timeline-card.component.js +136 -92
  157. package/dist/lib/components/realtime/realtime-session-timeline-card.component.js.map +1 -1
  158. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +2 -2
  159. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +4 -4
  160. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
  161. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +1 -1
  162. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +3 -3
  163. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
  164. package/dist/lib/components/realtime/realtime-ui-config.d.ts +13 -11
  165. package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -1
  166. package/dist/lib/components/realtime/realtime-ui-config.js +29 -25
  167. package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -1
  168. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +3 -1
  169. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
  170. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +6 -2
  171. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
  172. package/dist/lib/components/search/search-panel.component.d.ts +133 -22
  173. package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
  174. package/dist/lib/components/search/search-panel.component.js +312 -83
  175. package/dist/lib/components/search/search-panel.component.js.map +1 -1
  176. package/dist/lib/components/share/share-modal.component.d.ts +69 -9
  177. package/dist/lib/components/share/share-modal.component.d.ts.map +1 -1
  178. package/dist/lib/components/share/share-modal.component.js +139 -31
  179. package/dist/lib/components/share/share-modal.component.js.map +1 -1
  180. package/dist/lib/components/shared/user-picker.component.d.ts +48 -8
  181. package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -1
  182. package/dist/lib/components/shared/user-picker.component.js +110 -30
  183. package/dist/lib/components/shared/user-picker.component.js.map +1 -1
  184. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +114 -11
  185. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
  186. package/dist/lib/components/sidebar/conversation-sidebar.component.js +199 -21
  187. package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
  188. package/dist/lib/components/sidebar/routines-section.component.d.ts +20 -1
  189. package/dist/lib/components/sidebar/routines-section.component.d.ts.map +1 -1
  190. package/dist/lib/components/sidebar/routines-section.component.js +25 -5
  191. package/dist/lib/components/sidebar/routines-section.component.js.map +1 -1
  192. package/dist/lib/components/slots/slot-interfaces.d.ts +19 -0
  193. package/dist/lib/components/slots/slot-interfaces.d.ts.map +1 -1
  194. package/dist/lib/components/slots/slot-interfaces.js.map +1 -1
  195. package/dist/lib/components/task/tasks-full-view.component.d.ts +95 -13
  196. package/dist/lib/components/task/tasks-full-view.component.d.ts.map +1 -1
  197. package/dist/lib/components/task/tasks-full-view.component.js +223 -75
  198. package/dist/lib/components/task/tasks-full-view.component.js.map +1 -1
  199. package/dist/lib/components/tasks/task-widget.component.d.ts +46 -6
  200. package/dist/lib/components/tasks/task-widget.component.d.ts.map +1 -1
  201. package/dist/lib/components/tasks/task-widget.component.js +100 -16
  202. package/dist/lib/components/tasks/task-widget.component.js.map +1 -1
  203. package/dist/lib/components/tasks/tasks-dropdown.component.d.ts +64 -7
  204. package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
  205. package/dist/lib/components/tasks/tasks-dropdown.component.js +127 -27
  206. package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
  207. package/dist/lib/components/thread/thread-panel.component.d.ts +66 -8
  208. package/dist/lib/components/thread/thread-panel.component.d.ts.map +1 -1
  209. package/dist/lib/components/thread/thread-panel.component.js +146 -36
  210. package/dist/lib/components/thread/thread-panel.component.js.map +1 -1
  211. package/dist/lib/components/toast/toast.component.d.ts +11 -1
  212. package/dist/lib/components/toast/toast.component.d.ts.map +1 -1
  213. package/dist/lib/components/toast/toast.component.js +25 -5
  214. package/dist/lib/components/toast/toast.component.js.map +1 -1
  215. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +385 -42
  216. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  217. package/dist/lib/components/workspace/conversation-workspace.component.js +891 -292
  218. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  219. package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts +8 -0
  220. package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts.map +1 -1
  221. package/dist/lib/composer-plugins/base-conversation-mention.provider.js +8 -1
  222. package/dist/lib/composer-plugins/base-conversation-mention.provider.js.map +1 -1
  223. package/dist/lib/directives/chat-slot.directive.d.ts +5 -1
  224. package/dist/lib/directives/chat-slot.directive.d.ts.map +1 -1
  225. package/dist/lib/directives/chat-slot.directive.js.map +1 -1
  226. package/dist/lib/directives/search-shortcut.directive.d.ts +9 -1
  227. package/dist/lib/directives/search-shortcut.directive.d.ts.map +1 -1
  228. package/dist/lib/directives/search-shortcut.directive.js +14 -4
  229. package/dist/lib/directives/search-shortcut.directive.js.map +1 -1
  230. package/dist/lib/events/chat-events.d.ts +34 -7
  231. package/dist/lib/events/chat-events.d.ts.map +1 -1
  232. package/dist/lib/events/chat-events.js +37 -7
  233. package/dist/lib/events/chat-events.js.map +1 -1
  234. package/dist/lib/models/agent-turn.model.d.ts +113 -0
  235. package/dist/lib/models/agent-turn.model.d.ts.map +1 -0
  236. package/dist/lib/models/agent-turn.model.js +12 -0
  237. package/dist/lib/models/agent-turn.model.js.map +1 -0
  238. package/dist/lib/models/collection-view.model.js.map +1 -1
  239. package/dist/lib/models/conversation-state.model.d.ts +8 -0
  240. package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
  241. package/dist/lib/models/conversation-state.model.js.map +1 -1
  242. package/dist/lib/models/lazy-artifact-info.d.ts +44 -12
  243. package/dist/lib/models/lazy-artifact-info.d.ts.map +1 -1
  244. package/dist/lib/models/lazy-artifact-info.js +98 -34
  245. package/dist/lib/models/lazy-artifact-info.js.map +1 -1
  246. package/dist/lib/services/active-tasks.service.d.ts +30 -4
  247. package/dist/lib/services/active-tasks.service.d.ts.map +1 -1
  248. package/dist/lib/services/active-tasks.service.js +71 -19
  249. package/dist/lib/services/active-tasks.service.js.map +1 -1
  250. package/dist/lib/services/agent-state.service.d.ts +17 -1
  251. package/dist/lib/services/agent-state.service.d.ts.map +1 -1
  252. package/dist/lib/services/agent-state.service.js +48 -16
  253. package/dist/lib/services/agent-state.service.js.map +1 -1
  254. package/dist/lib/services/artifact-permission.service.d.ts +39 -0
  255. package/dist/lib/services/artifact-permission.service.d.ts.map +1 -1
  256. package/dist/lib/services/artifact-permission.service.js +152 -17
  257. package/dist/lib/services/artifact-permission.service.js.map +1 -1
  258. package/dist/lib/services/artifact-state.service.d.ts +58 -5
  259. package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
  260. package/dist/lib/services/artifact-state.service.js +135 -35
  261. package/dist/lib/services/artifact-state.service.js.map +1 -1
  262. package/dist/lib/services/collection-permission.service.d.ts +28 -0
  263. package/dist/lib/services/collection-permission.service.d.ts.map +1 -1
  264. package/dist/lib/services/collection-permission.service.js +88 -32
  265. package/dist/lib/services/collection-permission.service.js.map +1 -1
  266. package/dist/lib/services/collection-state.service.d.ts +11 -1
  267. package/dist/lib/services/collection-state.service.d.ts.map +1 -1
  268. package/dist/lib/services/collection-state.service.js +25 -5
  269. package/dist/lib/services/collection-state.service.js.map +1 -1
  270. package/dist/lib/services/conversation-agent.service.d.ts +47 -4
  271. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  272. package/dist/lib/services/conversation-agent.service.js +85 -20
  273. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  274. package/dist/lib/services/conversation-attachment.service.d.ts +17 -0
  275. package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
  276. package/dist/lib/services/conversation-attachment.service.js +38 -10
  277. package/dist/lib/services/conversation-attachment.service.js.map +1 -1
  278. package/dist/lib/services/conversation-liveness-dom.service.d.ts +42 -0
  279. package/dist/lib/services/conversation-liveness-dom.service.d.ts.map +1 -0
  280. package/dist/lib/services/conversation-liveness-dom.service.js +74 -0
  281. package/dist/lib/services/conversation-liveness-dom.service.js.map +1 -0
  282. package/dist/lib/services/conversation-streaming.service.d.ts +22 -0
  283. package/dist/lib/services/conversation-streaming.service.d.ts.map +1 -1
  284. package/dist/lib/services/conversation-streaming.service.js +50 -10
  285. package/dist/lib/services/conversation-streaming.service.js.map +1 -1
  286. package/dist/lib/services/data-cache.service.d.ts +31 -0
  287. package/dist/lib/services/data-cache.service.d.ts.map +1 -1
  288. package/dist/lib/services/data-cache.service.js +71 -15
  289. package/dist/lib/services/data-cache.service.js.map +1 -1
  290. package/dist/lib/services/dialog.service.d.ts +13 -0
  291. package/dist/lib/services/dialog.service.d.ts.map +1 -1
  292. package/dist/lib/services/dialog.service.js +25 -5
  293. package/dist/lib/services/dialog.service.js.map +1 -1
  294. package/dist/lib/services/export.service.d.ts +2 -0
  295. package/dist/lib/services/export.service.d.ts.map +1 -1
  296. package/dist/lib/services/export.service.js +5 -1
  297. package/dist/lib/services/export.service.js.map +1 -1
  298. package/dist/lib/services/mention-parser.service.d.ts +10 -0
  299. package/dist/lib/services/mention-parser.service.d.ts.map +1 -1
  300. package/dist/lib/services/mention-parser.service.js +25 -5
  301. package/dist/lib/services/mention-parser.service.js.map +1 -1
  302. package/dist/lib/services/notification.service.d.ts +54 -6
  303. package/dist/lib/services/notification.service.d.ts.map +1 -1
  304. package/dist/lib/services/notification.service.js +123 -27
  305. package/dist/lib/services/notification.service.js.map +1 -1
  306. package/dist/lib/services/realtime-audio-recorder.d.ts +4 -4
  307. package/dist/lib/services/realtime-audio-recorder.js +12 -12
  308. package/dist/lib/services/realtime-audio-recorder.js.map +1 -1
  309. package/dist/lib/services/realtime-pcm-wav.d.ts +4 -0
  310. package/dist/lib/services/realtime-pcm-wav.d.ts.map +1 -1
  311. package/dist/lib/services/realtime-pcm-wav.js +10 -2
  312. package/dist/lib/services/realtime-pcm-wav.js.map +1 -1
  313. package/dist/lib/services/search.service.d.ts +42 -9
  314. package/dist/lib/services/search.service.d.ts.map +1 -1
  315. package/dist/lib/services/search.service.js +103 -23
  316. package/dist/lib/services/search.service.js.map +1 -1
  317. package/dist/lib/services/toast.service.d.ts +19 -1
  318. package/dist/lib/services/toast.service.d.ts.map +1 -1
  319. package/dist/lib/services/toast.service.js +45 -9
  320. package/dist/lib/services/toast.service.js.map +1 -1
  321. package/dist/lib/services/ui-command-handler.service.d.ts +56 -5
  322. package/dist/lib/services/ui-command-handler.service.d.ts.map +1 -1
  323. package/dist/lib/services/ui-command-handler.service.js +113 -16
  324. package/dist/lib/services/ui-command-handler.service.js.map +1 -1
  325. package/dist/lib/utils/agent-artifact-summary.d.ts +2 -2
  326. package/dist/lib/utils/agent-artifact-summary.js +3 -3
  327. package/dist/lib/utils/agent-artifact-summary.js.map +1 -1
  328. package/dist/lib/utils/agent-turn-routing.d.ts +70 -0
  329. package/dist/lib/utils/agent-turn-routing.d.ts.map +1 -0
  330. package/dist/lib/utils/agent-turn-routing.js +84 -0
  331. package/dist/lib/utils/agent-turn-routing.js.map +1 -0
  332. package/dist/lib/utils/artifact-panel-action.d.ts +15 -4
  333. package/dist/lib/utils/artifact-panel-action.d.ts.map +1 -1
  334. package/dist/lib/utils/artifact-panel-action.js +10 -2
  335. package/dist/lib/utils/artifact-panel-action.js.map +1 -1
  336. package/dist/lib/utils/decision-routing.d.ts +68 -0
  337. package/dist/lib/utils/decision-routing.d.ts.map +1 -0
  338. package/dist/lib/utils/decision-routing.js +101 -0
  339. package/dist/lib/utils/decision-routing.js.map +1 -0
  340. package/dist/lib/utils/distinct-artifacts.d.ts +2 -0
  341. package/dist/lib/utils/distinct-artifacts.d.ts.map +1 -1
  342. package/dist/lib/utils/distinct-artifacts.js +5 -1
  343. package/dist/lib/utils/distinct-artifacts.js.map +1 -1
  344. package/dist/lib/utils/plan-mode-preference.d.ts +2 -2
  345. package/dist/lib/utils/plan-mode-preference.js +6 -6
  346. package/dist/lib/utils/plan-mode-preference.js.map +1 -1
  347. package/dist/public-api.d.ts +5 -0
  348. package/dist/public-api.d.ts.map +1 -1
  349. package/dist/public-api.js +8 -0
  350. package/dist/public-api.js.map +1 -1
  351. package/package.json +32 -32
@@ -1 +1 @@
1
- {"version":3,"file":"toast.service.js","sourceRoot":"","sources":["../../../src/lib/services/toast.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAc,MAAM,MAAM,CAAC;;AAenD,MAAM,OAAO,YAAY;IACf,aAAa,GAAG,IAAI,eAAe,CAAU,EAAE,CAAC,CAAC;IAClD,OAAO,GAAwB,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;IAEhE,SAAS,GAAG,CAAC,CAAC;IAEtB;;OAEG;IACI,IAAI,CAAC,OAAe,EAAE,OAAkB,MAAM,EAAE,WAAmB,IAAI;QAC5E,MAAM,KAAK,GAAU;YACnB,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;YAC7C,OAAO;YACP,IAAI;YACJ,QAAQ;YACR,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QAEF,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;QAC/C,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,GAAG,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC;QAEnD,8BAA8B;QAC9B,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjB,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACzB,CAAC,EAAE,QAAQ,CAAC,CAAC;QACf,CAAC;QAED,OAAO,KAAK,CAAC,EAAE,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,OAAO,CAAC,OAAe,EAAE,WAAmB,IAAI;QACrD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAe,EAAE,WAAmB,IAAI;QACnD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACI,OAAO,CAAC,OAAe,EAAE,WAAmB,IAAI;QACrD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACI,IAAI,CAAC,OAAe,EAAE,WAAmB,IAAI;QAClD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACI,OAAO,CAAC,EAAU;QACvB,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;QAC/C,MAAM,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACI,KAAK;QACV,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;sGAzEU,YAAY;gEAAZ,YAAY,WAAZ,YAAY,mBAFX,MAAM;;iFAEP,YAAY;cAHxB,UAAU;eAAC;gBACV,UAAU,EAAE,MAAM;aACnB","sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nexport type ToastType = 'success' | 'error' | 'warning' | 'info';\n\nexport interface Toast {\n id: string;\n message: string;\n type: ToastType;\n duration: number;\n timestamp: number;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ToastService {\n private toastsSubject = new BehaviorSubject<Toast[]>([]);\n public toasts$: Observable<Toast[]> = this.toastsSubject.asObservable();\n\n private idCounter = 0;\n\n /**\n * Show a toast notification\n */\n public show(message: string, type: ToastType = 'info', duration: number = 3000): string {\n const toast: Toast = {\n id: `toast-${++this.idCounter}-${Date.now()}`,\n message,\n type,\n duration,\n timestamp: Date.now()\n };\n\n const currentToasts = this.toastsSubject.value;\n this.toastsSubject.next([...currentToasts, toast]);\n\n // Auto-dismiss after duration\n if (duration > 0) {\n setTimeout(() => {\n this.dismiss(toast.id);\n }, duration);\n }\n\n return toast.id;\n }\n\n /**\n * Show a success toast\n */\n public success(message: string, duration: number = 3000): string {\n return this.show(message, 'success', duration);\n }\n\n /**\n * Show an error toast\n */\n public error(message: string, duration: number = 5000): string {\n return this.show(message, 'error', duration);\n }\n\n /**\n * Show a warning toast\n */\n public warning(message: string, duration: number = 4000): string {\n return this.show(message, 'warning', duration);\n }\n\n /**\n * Show an info toast\n */\n public info(message: string, duration: number = 3000): string {\n return this.show(message, 'info', duration);\n }\n\n /**\n * Dismiss a specific toast by ID\n */\n public dismiss(id: string): void {\n const currentToasts = this.toastsSubject.value;\n const filteredToasts = currentToasts.filter(t => t.id !== id);\n this.toastsSubject.next(filteredToasts);\n }\n\n /**\n * Clear all toasts\n */\n public clear(): void {\n this.toastsSubject.next([]);\n }\n}\n"]}
1
+ {"version":3,"file":"toast.service.js","sourceRoot":"","sources":["../../../src/lib/services/toast.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nexport type ToastType = 'success' | 'error' | 'warning' | 'info';\n\nexport interface Toast {\n id: string;\n message: string;\n type: ToastType;\n duration: number;\n timestamp: number;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ToastService {\n private toastsSubject = new BehaviorSubject<Toast[]>([]);\n public Toasts$: Observable<Toast[]> = this.toastsSubject.asObservable();\n\n /** @deprecated Use {@link Toasts$}. */\n public get toasts$(): Observable<Toast[]> {\n return this.Toasts$;\n }\n /** @deprecated Use {@link Toasts$}. */\n public set toasts$(value: Observable<Toast[]>) {\n this.Toasts$ = value;\n }\n\n private idCounter = 0;\n\n /**\n * Show a toast notification\n */\n public Show(message: string, type: ToastType = 'info', duration: number = 3000): string {\n const toast: Toast = {\n id: `toast-${++this.idCounter}-${Date.now()}`,\n message,\n type,\n duration,\n timestamp: Date.now()\n };\n\n const currentToasts = this.toastsSubject.value;\n this.toastsSubject.next([...currentToasts, toast]);\n\n // Auto-dismiss after duration\n if (duration > 0) {\n setTimeout(() => {\n this.Dismiss(toast.id);\n }, duration);\n }\n\n return toast.id;\n }\n\n /** @deprecated Use {@link Show}. */\n public show(message: string, type: ToastType = 'info', duration: number = 3000): string {\n return this.Show(message, type, duration);\n }\n\n /**\n * Show a success toast\n */\n public Success(message: string, duration: number = 3000): string {\n return this.Show(message, 'success', duration);\n }\n\n /** @deprecated Use {@link Success}. */\n public success(message: string, duration: number = 3000): string {\n return this.Success(message, duration);\n }\n\n /**\n * Show an error toast\n */\n public Error(message: string, duration: number = 5000): string {\n return this.Show(message, 'error', duration);\n }\n\n /** @deprecated Use {@link Error}. */\n public error(message: string, duration: number = 5000): string {\n return this.Error(message, duration);\n }\n\n /**\n * Show a warning toast\n */\n public Warning(message: string, duration: number = 4000): string {\n return this.Show(message, 'warning', duration);\n }\n\n /** @deprecated Use {@link Warning}. */\n public warning(message: string, duration: number = 4000): string {\n return this.Warning(message, duration);\n }\n\n /**\n * Show an info toast\n */\n public Info(message: string, duration: number = 3000): string {\n return this.Show(message, 'info', duration);\n }\n\n /** @deprecated Use {@link Info}. */\n public info(message: string, duration: number = 3000): string {\n return this.Info(message, duration);\n }\n\n /**\n * Dismiss a specific toast by ID\n */\n public Dismiss(id: string): void {\n const currentToasts = this.toastsSubject.value;\n const filteredToasts = currentToasts.filter(t => t.id !== id);\n this.toastsSubject.next(filteredToasts);\n }\n\n /** @deprecated Use {@link Dismiss}. */\n public dismiss(id: string): void {\n return this.Dismiss(id);\n }\n\n /**\n * Clear all toasts\n */\n public Clear(): void {\n this.toastsSubject.next([]);\n }\n\n /** @deprecated Use {@link Clear}. */\n public clear(): void {\n return this.Clear();\n }\n}\n"]}
@@ -6,36 +6,83 @@ export interface ActionableCommandRequest {
6
6
  command: ActionableCommand;
7
7
  conversationId?: string | null;
8
8
  conversationDetailId?: string | null;
9
+ /**
10
+ * Set only on the compose:email over-length fallback: whether the draft body is now on the
11
+ * user's clipboard. The copy overwrites whatever the user had copied, so the host must say it
12
+ * happened, and must not claim it when this is false (no body, clipboard unavailable over plain
13
+ * HTTP, or denied by permissions policy).
14
+ */
15
+ DraftCopiedToClipboard?: boolean;
9
16
  }
10
17
  /**
11
18
  * Service for handling UI commands from agents.
12
19
  *
13
- * Generic commands (open:url) are handled directly by this service.
14
- * App-specific commands (open:resource) are emitted for the host application to handle.
20
+ * Generic commands (open:url, and compose:email while it fits in a mailto: URL) are handled
21
+ * directly by this service. App-specific commands (open:resource, and the compose:email
22
+ * over-length fallback) are emitted for the host application to handle.
15
23
  */
16
24
  export declare class UICommandHandlerService {
17
25
  private dataCacheService;
18
26
  /**
19
27
  * Event emitted when an actionable command requires host-app handling.
20
- * Currently only open:resource commands are emitted — open:url is handled directly.
28
+ *
29
+ * open:resource is always emitted. compose:email is emitted ONLY as a fallback, when the draft
30
+ * is too long for a mailto: URL and the host must open the draft artifact instead; a draft
31
+ * within the limit is handled here and never reaches the host. On that fallback the host also
32
+ * owns telling the user why their mail client did not open, because only the host knows whether
33
+ * a draft artifact opened (see {@link ActionableCommandRequest.DraftCopiedToClipboard}).
34
+ * open:url is always handled here.
21
35
  */
22
- actionableCommandRequested: EventEmitter<ActionableCommandRequest>;
36
+ ActionableCommandRequested: EventEmitter<ActionableCommandRequest>;
37
+ /** @deprecated Use {@link ActionableCommandRequested}. */
38
+ get actionableCommandRequested(): EventEmitter<ActionableCommandRequest>;
39
+ /** @deprecated Use {@link ActionableCommandRequested}. */
40
+ set actionableCommandRequested(value: EventEmitter<ActionableCommandRequest>);
23
41
  /**
24
42
  * Event emitted when an automatic command should be executed
25
43
  * Host application should subscribe to this and handle the command appropriately
26
44
  */
27
- automaticCommandRequested: EventEmitter<AutomaticCommand>;
45
+ AutomaticCommandRequested: EventEmitter<AutomaticCommand>;
46
+ /** @deprecated Use {@link AutomaticCommandRequested}. */
47
+ get automaticCommandRequested(): EventEmitter<AutomaticCommand>;
48
+ /** @deprecated Use {@link AutomaticCommandRequested}. */
49
+ set automaticCommandRequested(value: EventEmitter<AutomaticCommand>);
28
50
  constructor(dataCacheService: DataCacheService);
29
51
  /**
30
52
  * Execute an actionable command (triggered by user clicking a button).
31
53
  * Generic commands like open:url are handled directly; others are emitted to the host.
32
54
  */
55
+ ExecuteActionableCommand(command: ActionableCommand, origin?: Omit<ActionableCommandRequest, 'command'>): Promise<void>;
56
+ /** @deprecated Use {@link ExecuteActionableCommand}. */
33
57
  executeActionableCommand(command: ActionableCommand, origin?: Omit<ActionableCommandRequest, 'command'>): Promise<void>;
34
58
  /**
35
59
  * Handle open:url commands directly by opening the URL in a browser tab.
36
60
  * Data URIs are converted to Blob URLs because Chrome blocks window.open with data: URIs.
37
61
  */
38
62
  private handleOpenUrl;
63
+ /**
64
+ * Best-effort copy of an over-length draft's body, so the text is not lost even when the host
65
+ * cannot open the draft artifact.
66
+ *
67
+ * Never rejects, so a clipboard that is unavailable (plain HTTP) or denied by permissions policy
68
+ * cannot stop the fallback. Nothing on the click path awaits before writeText is called, so it
69
+ * still runs inside the click's user activation; the fallback then awaits the outcome only so
70
+ * the host's notice can say whether the copy happened.
71
+ *
72
+ * @returns true only when the body is on the clipboard, so the host never claims a copy that
73
+ * did not happen.
74
+ */
75
+ private copyDraftBody;
76
+ /**
77
+ * Open the user's own mail client with a compose:email draft's fields pre-filled, via a
78
+ * synthesized anchor click.
79
+ *
80
+ * NOTHING IS SENT HERE. The agent drafted; the user sends. This only opens a compose window.
81
+ *
82
+ * Deliberately not window.open: Chrome treats window.open with a non-http scheme as a popup and
83
+ * strands an about:blank tab behind the compose window.
84
+ */
85
+ private openMailto;
39
86
  /**
40
87
  * Open a data URI by converting it to a Blob URL.
41
88
  * Chrome blocks window.open('data:...') for security, so we create a Blob URL instead.
@@ -45,10 +92,14 @@ export declare class UICommandHandlerService {
45
92
  * Execute an automatic command (runs immediately without user interaction)
46
93
  * Special handling: refresh:data commands execute locally, others emit to host
47
94
  */
95
+ ExecuteAutomaticCommand(command: AutomaticCommand): Promise<void>;
96
+ /** @deprecated Use {@link ExecuteAutomaticCommand}. */
48
97
  executeAutomaticCommand(command: AutomaticCommand): Promise<void>;
49
98
  /**
50
99
  * Execute all automatic commands from an agent result
51
100
  */
101
+ ExecuteAutomaticCommands(commands: AutomaticCommand[]): Promise<void>;
102
+ /** @deprecated Use {@link ExecuteAutomaticCommands}. */
52
103
  executeAutomaticCommands(commands: AutomaticCommand[]): Promise<void>;
53
104
  /**
54
105
  * Handle refreshing data (entity data or caches)
@@ -1 +1 @@
1
- {"version":3,"file":"ui-command-handler.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/ui-command-handler.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAsC,MAAM,8BAA8B,CAAC;AACvH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;;AAExD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED;;;;;GAKG;AACH,qBAGa,uBAAuB;IAchC,OAAO,CAAC,gBAAgB;IAb1B;;;OAGG;IACI,0BAA0B,yCAAgD;IAEjF;;;OAGG;IACI,yBAAyB,iCAAwC;gBAG9D,gBAAgB,EAAE,gBAAgB;IAG5C;;;OAGG;IACU,wBAAwB,CAAC,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAcpI;;;OAGG;IACH,OAAO,CAAC,aAAa;IAYrB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAgBnB;;;OAGG;IACU,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAa9E;;OAEG;IACU,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAclF;;;OAGG;YACW,iBAAiB;yCA7GpB,uBAAuB;6CAAvB,uBAAuB;CA8HnC"}
1
+ {"version":3,"file":"ui-command-handler.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/ui-command-handler.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAKjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;;AAExD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;GAMG;AACH,qBAGa,uBAAuB;IAsChC,OAAO,CAAC,gBAAgB;IArC1B;;;;;;;;;OASG;IACI,0BAA0B,yCAAgD;IAEjF,0DAA0D;IAC1D,IAAW,0BAA0B,2CAEpC;IACD,0DAA0D;IAC1D,IAAW,0BAA0B,CAAC,KAAK,wCAAA,EAE1C;IAED;;;OAGG;IACI,yBAAyB,iCAAwC;IAExE,yDAAyD;IACzD,IAAW,yBAAyB,mCAEnC;IACD,yDAAyD;IACzD,IAAW,yBAAyB,CAAC,KAAK,gCAAA,EAEzC;gBAGS,gBAAgB,EAAE,gBAAgB;IAG5C;;;OAGG;IACU,wBAAwB,CAAC,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCpI,wDAAwD;IAC3C,wBAAwB,CAAC,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpI;;;OAGG;IACH,OAAO,CAAC,aAAa;IAYrB;;;;;;;;;;;OAWG;YACW,aAAa;IAY3B;;;;;;;;OAQG;IACH,OAAO,CAAC,UAAU;IASlB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAgBnB;;;OAGG;IACU,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAa9E,uDAAuD;IAC1C,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9E;;OAEG;IACU,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAclF,wDAAwD;IAC3C,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlF;;;OAGG;YACW,iBAAiB;yCArNpB,uBAAuB;6CAAvB,uBAAuB;CAsOnC"}
@@ -1,24 +1,48 @@
1
1
  import { Injectable, EventEmitter } from '@angular/core';
2
+ import { BuildMailtoURL } from '@memberjunction/ai-core-plus';
2
3
  import * as i0 from "@angular/core";
3
4
  import * as i1 from "./data-cache.service";
4
5
  /**
5
6
  * Service for handling UI commands from agents.
6
7
  *
7
- * Generic commands (open:url) are handled directly by this service.
8
- * App-specific commands (open:resource) are emitted for the host application to handle.
8
+ * Generic commands (open:url, and compose:email while it fits in a mailto: URL) are handled
9
+ * directly by this service. App-specific commands (open:resource, and the compose:email
10
+ * over-length fallback) are emitted for the host application to handle.
9
11
  */
10
12
  export class UICommandHandlerService {
11
13
  dataCacheService;
12
14
  /**
13
15
  * Event emitted when an actionable command requires host-app handling.
14
- * Currently only open:resource commands are emitted — open:url is handled directly.
16
+ *
17
+ * open:resource is always emitted. compose:email is emitted ONLY as a fallback, when the draft
18
+ * is too long for a mailto: URL and the host must open the draft artifact instead; a draft
19
+ * within the limit is handled here and never reaches the host. On that fallback the host also
20
+ * owns telling the user why their mail client did not open, because only the host knows whether
21
+ * a draft artifact opened (see {@link ActionableCommandRequest.DraftCopiedToClipboard}).
22
+ * open:url is always handled here.
15
23
  */
16
- actionableCommandRequested = new EventEmitter();
24
+ ActionableCommandRequested = new EventEmitter();
25
+ /** @deprecated Use {@link ActionableCommandRequested}. */
26
+ get actionableCommandRequested() {
27
+ return this.ActionableCommandRequested;
28
+ }
29
+ /** @deprecated Use {@link ActionableCommandRequested}. */
30
+ set actionableCommandRequested(value) {
31
+ this.ActionableCommandRequested = value;
32
+ }
17
33
  /**
18
34
  * Event emitted when an automatic command should be executed
19
35
  * Host application should subscribe to this and handle the command appropriately
20
36
  */
21
- automaticCommandRequested = new EventEmitter();
37
+ AutomaticCommandRequested = new EventEmitter();
38
+ /** @deprecated Use {@link AutomaticCommandRequested}. */
39
+ get automaticCommandRequested() {
40
+ return this.AutomaticCommandRequested;
41
+ }
42
+ /** @deprecated Use {@link AutomaticCommandRequested}. */
43
+ set automaticCommandRequested(value) {
44
+ this.AutomaticCommandRequested = value;
45
+ }
22
46
  constructor(dataCacheService) {
23
47
  this.dataCacheService = dataCacheService;
24
48
  }
@@ -26,19 +50,43 @@ export class UICommandHandlerService {
26
50
  * Execute an actionable command (triggered by user clicking a button).
27
51
  * Generic commands like open:url are handled directly; others are emitted to the host.
28
52
  */
29
- async executeActionableCommand(command, origin) {
53
+ async ExecuteActionableCommand(command, origin) {
30
54
  if (command.type === 'open:url') {
31
55
  this.handleOpenUrl(command);
56
+ return;
57
+ }
58
+ const request = {
59
+ command,
60
+ conversationId: origin?.conversationId ?? null,
61
+ conversationDetailId: origin?.conversationDetailId ?? null
62
+ };
63
+ if (command.type === 'compose:email') {
64
+ const { url, withinLimit } = BuildMailtoURL(command);
65
+ if (withinLimit) {
66
+ this.openMailto(url);
67
+ return;
68
+ }
69
+ // Too long for a mailto: URL. We do NOT open it: a mail client past its limit does not
70
+ // refuse the URL, it opens a draft with the body SILENTLY TRUNCATED and the user sends half
71
+ // a message without noticing. Falls through to the host, which opens the full draft
72
+ // artifact and tells the user what happened.
73
+ request.DraftCopiedToClipboard = await this.copyDraftBody(command);
74
+ }
75
+ // open:resource (and the compose:email fallback above) require app-specific navigation.
76
+ // compose:email is logged by TYPE ONLY: its body is free-text member correspondence, and the
77
+ // whole command object would otherwise land in the browser console and any console-forwarding
78
+ // telemetry.
79
+ if (command.type === 'compose:email') {
80
+ console.log('📤 Emitting actionable command for host app:', command.type);
32
81
  }
33
82
  else {
34
- // open:resource requires app-specific navigation — emit for host to handle
35
83
  console.log('📤 Emitting actionable command for host app:', command);
36
- this.actionableCommandRequested.emit({
37
- command,
38
- conversationId: origin?.conversationId ?? null,
39
- conversationDetailId: origin?.conversationDetailId ?? null
40
- });
41
84
  }
85
+ this.ActionableCommandRequested.emit(request);
86
+ }
87
+ /** @deprecated Use {@link ExecuteActionableCommand}. */
88
+ async executeActionableCommand(command, origin) {
89
+ return this.ExecuteActionableCommand(command, origin);
42
90
  }
43
91
  /**
44
92
  * Handle open:url commands directly by opening the URL in a browser tab.
@@ -55,6 +103,47 @@ export class UICommandHandlerService {
55
103
  window.open(url, target, target === '_blank' ? 'noopener,noreferrer' : undefined);
56
104
  }
57
105
  }
106
+ /**
107
+ * Best-effort copy of an over-length draft's body, so the text is not lost even when the host
108
+ * cannot open the draft artifact.
109
+ *
110
+ * Never rejects, so a clipboard that is unavailable (plain HTTP) or denied by permissions policy
111
+ * cannot stop the fallback. Nothing on the click path awaits before writeText is called, so it
112
+ * still runs inside the click's user activation; the fallback then awaits the outcome only so
113
+ * the host's notice can say whether the copy happened.
114
+ *
115
+ * @returns true only when the body is on the clipboard, so the host never claims a copy that
116
+ * did not happen.
117
+ */
118
+ async copyDraftBody(command) {
119
+ if (!command.body || !navigator.clipboard) {
120
+ return false;
121
+ }
122
+ try {
123
+ await navigator.clipboard.writeText(command.body);
124
+ return true;
125
+ }
126
+ catch {
127
+ return false;
128
+ }
129
+ }
130
+ /**
131
+ * Open the user's own mail client with a compose:email draft's fields pre-filled, via a
132
+ * synthesized anchor click.
133
+ *
134
+ * NOTHING IS SENT HERE. The agent drafted; the user sends. This only opens a compose window.
135
+ *
136
+ * Deliberately not window.open: Chrome treats window.open with a non-http scheme as a popup and
137
+ * strands an about:blank tab behind the compose window.
138
+ */
139
+ openMailto(url) {
140
+ const a = document.createElement('a');
141
+ a.href = url;
142
+ a.style.display = 'none';
143
+ document.body.appendChild(a);
144
+ a.click();
145
+ document.body.removeChild(a);
146
+ }
58
147
  /**
59
148
  * Open a data URI by converting it to a Blob URL.
60
149
  * Chrome blocks window.open('data:...') for security, so we create a Blob URL instead.
@@ -76,7 +165,7 @@ export class UICommandHandlerService {
76
165
  * Execute an automatic command (runs immediately without user interaction)
77
166
  * Special handling: refresh:data commands execute locally, others emit to host
78
167
  */
79
- async executeAutomaticCommand(command) {
168
+ async ExecuteAutomaticCommand(command) {
80
169
  console.log('Executing automatic command:', command);
81
170
  if (command.type === 'refresh:data') {
82
171
  // Handle data refresh locally as it's a generic operation
@@ -85,25 +174,33 @@ export class UICommandHandlerService {
85
174
  else {
86
175
  // Emit other automatic commands (like notifications) for host to handle
87
176
  console.log('📤 Emitting automatic command for host app:', command);
88
- this.automaticCommandRequested.emit(command);
177
+ this.AutomaticCommandRequested.emit(command);
89
178
  }
90
179
  }
180
+ /** @deprecated Use {@link ExecuteAutomaticCommand}. */
181
+ async executeAutomaticCommand(command) {
182
+ return this.ExecuteAutomaticCommand(command);
183
+ }
91
184
  /**
92
185
  * Execute all automatic commands from an agent result
93
186
  */
94
- async executeAutomaticCommands(commands) {
187
+ async ExecuteAutomaticCommands(commands) {
95
188
  if (!commands || commands.length === 0) {
96
189
  return;
97
190
  }
98
191
  for (const command of commands) {
99
192
  try {
100
- await this.executeAutomaticCommand(command);
193
+ await this.ExecuteAutomaticCommand(command);
101
194
  }
102
195
  catch (error) {
103
196
  console.error('Error executing automatic command:', command, error);
104
197
  }
105
198
  }
106
199
  }
200
+ /** @deprecated Use {@link ExecuteAutomaticCommands}. */
201
+ async executeAutomaticCommands(commands) {
202
+ return this.ExecuteAutomaticCommands(commands);
203
+ }
107
204
  /**
108
205
  * Handle refreshing data (entity data or caches)
109
206
  * This is handled locally as it's a generic operation that doesn't require host app knowledge
@@ -1 +1 @@
1
- {"version":3,"file":"ui-command-handler.service.js","sourceRoot":"","sources":["../../../src/lib/services/ui-command-handler.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, EventEmitter } from '@angular/core';\nimport { ActionableCommand, AutomaticCommand, RefreshDataCommand, OpenURLCommand } from '@memberjunction/ai-core-plus';\nimport { DataCacheService } from './data-cache.service';\n\nexport interface ActionableCommandRequest {\n command: ActionableCommand;\n conversationId?: string | null;\n conversationDetailId?: string | null;\n}\n\n/**\n * Service for handling UI commands from agents.\n *\n * Generic commands (open:url) are handled directly by this service.\n * App-specific commands (open:resource) are emitted for the host application to handle.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class UICommandHandlerService {\n /**\n * Event emitted when an actionable command requires host-app handling.\n * Currently only open:resource commands are emitted — open:url is handled directly.\n */\n public actionableCommandRequested = new EventEmitter<ActionableCommandRequest>();\n\n /**\n * Event emitted when an automatic command should be executed\n * Host application should subscribe to this and handle the command appropriately\n */\n public automaticCommandRequested = new EventEmitter<AutomaticCommand>();\n\n constructor(\n private dataCacheService: DataCacheService\n ) {}\n\n /**\n * Execute an actionable command (triggered by user clicking a button).\n * Generic commands like open:url are handled directly; others are emitted to the host.\n */\n public async executeActionableCommand(command: ActionableCommand, origin?: Omit<ActionableCommandRequest, 'command'>): Promise<void> {\n if (command.type === 'open:url') {\n this.handleOpenUrl(command);\n } else {\n // open:resource requires app-specific navigation — emit for host to handle\n console.log('📤 Emitting actionable command for host app:', command);\n this.actionableCommandRequested.emit({\n command,\n conversationId: origin?.conversationId ?? null,\n conversationDetailId: origin?.conversationDetailId ?? null\n });\n }\n }\n\n /**\n * Handle open:url commands directly by opening the URL in a browser tab.\n * Data URIs are converted to Blob URLs because Chrome blocks window.open with data: URIs.\n */\n private handleOpenUrl(command: OpenURLCommand): void {\n const url = command.url;\n const newTab = command.newTab !== false;\n\n if (url.startsWith('data:')) {\n this.openDataUri(url);\n } else {\n const target = newTab ? '_blank' : '_self';\n window.open(url, target, target === '_blank' ? 'noopener,noreferrer' : undefined);\n }\n }\n\n /**\n * Open a data URI by converting it to a Blob URL.\n * Chrome blocks window.open('data:...') for security, so we create a Blob URL instead.\n */\n private openDataUri(dataUri: string): void {\n const [header, base64Data] = dataUri.split(',');\n const mimeMatch = header.match(/data:([^;]+)/);\n const mimeType = mimeMatch ? mimeMatch[1] : 'application/octet-stream';\n\n const byteString = atob(base64Data);\n const byteArray = new Uint8Array(byteString.length);\n for (let i = 0; i < byteString.length; i++) {\n byteArray[i] = byteString.charCodeAt(i);\n }\n\n const blob = new Blob([byteArray], { type: mimeType });\n const blobUrl = URL.createObjectURL(blob);\n window.open(blobUrl, '_blank');\n }\n\n /**\n * Execute an automatic command (runs immediately without user interaction)\n * Special handling: refresh:data commands execute locally, others emit to host\n */\n public async executeAutomaticCommand(command: AutomaticCommand): Promise<void> {\n console.log('Executing automatic command:', command);\n\n if (command.type === 'refresh:data') {\n // Handle data refresh locally as it's a generic operation\n await this.handleRefreshData(command);\n } else {\n // Emit other automatic commands (like notifications) for host to handle\n console.log('📤 Emitting automatic command for host app:', command);\n this.automaticCommandRequested.emit(command);\n }\n }\n\n /**\n * Execute all automatic commands from an agent result\n */\n public async executeAutomaticCommands(commands: AutomaticCommand[]): Promise<void> {\n if (!commands || commands.length === 0) {\n return;\n }\n\n for (const command of commands) {\n try {\n await this.executeAutomaticCommand(command);\n } catch (error) {\n console.error('Error executing automatic command:', command, error);\n }\n }\n }\n\n /**\n * Handle refreshing data (entity data or caches)\n * This is handled locally as it's a generic operation that doesn't require host app knowledge\n */\n private async handleRefreshData(command: RefreshDataCommand): Promise<void> {\n const { scope, entityNames, cacheName } = command;\n\n if (scope === 'entity' && entityNames && entityNames.length > 0) {\n // Refresh specific entity data\n for (const entityName of entityNames) {\n await this.dataCacheService.refreshEntity(entityName);\n }\n console.log('Refreshed entity data:', entityNames);\n } else if (scope === 'cache' && cacheName) {\n // Refresh a specific cache\n await this.dataCacheService.refreshCache(cacheName);\n console.log('Refreshed cache:', cacheName);\n } else {\n console.warn('Invalid refresh:data command parameters:', command);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"ui-command-handler.service.js","sourceRoot":"","sources":["../../../src/lib/services/ui-command-handler.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, EventEmitter } from '@angular/core';\nimport {\n ActionableCommand,\n AutomaticCommand,\n RefreshDataCommand,\n OpenURLCommand,\n ComposeEmailCommand,\n BuildMailtoURL\n} from '@memberjunction/ai-core-plus';\nimport { DataCacheService } from './data-cache.service';\n\nexport interface ActionableCommandRequest {\n command: ActionableCommand;\n conversationId?: string | null;\n conversationDetailId?: string | null;\n /**\n * Set only on the compose:email over-length fallback: whether the draft body is now on the\n * user's clipboard. The copy overwrites whatever the user had copied, so the host must say it\n * happened, and must not claim it when this is false (no body, clipboard unavailable over plain\n * HTTP, or denied by permissions policy).\n */\n DraftCopiedToClipboard?: boolean;\n}\n\n/**\n * Service for handling UI commands from agents.\n *\n * Generic commands (open:url, and compose:email while it fits in a mailto: URL) are handled\n * directly by this service. App-specific commands (open:resource, and the compose:email\n * over-length fallback) are emitted for the host application to handle.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class UICommandHandlerService {\n /**\n * Event emitted when an actionable command requires host-app handling.\n *\n * open:resource is always emitted. compose:email is emitted ONLY as a fallback, when the draft\n * is too long for a mailto: URL and the host must open the draft artifact instead; a draft\n * within the limit is handled here and never reaches the host. On that fallback the host also\n * owns telling the user why their mail client did not open, because only the host knows whether\n * a draft artifact opened (see {@link ActionableCommandRequest.DraftCopiedToClipboard}).\n * open:url is always handled here.\n */\n public ActionableCommandRequested = new EventEmitter<ActionableCommandRequest>();\n\n /** @deprecated Use {@link ActionableCommandRequested}. */\n public get actionableCommandRequested() {\n return this.ActionableCommandRequested;\n }\n /** @deprecated Use {@link ActionableCommandRequested}. */\n public set actionableCommandRequested(value) {\n this.ActionableCommandRequested = value;\n }\n\n /**\n * Event emitted when an automatic command should be executed\n * Host application should subscribe to this and handle the command appropriately\n */\n public AutomaticCommandRequested = new EventEmitter<AutomaticCommand>();\n\n /** @deprecated Use {@link AutomaticCommandRequested}. */\n public get automaticCommandRequested() {\n return this.AutomaticCommandRequested;\n }\n /** @deprecated Use {@link AutomaticCommandRequested}. */\n public set automaticCommandRequested(value) {\n this.AutomaticCommandRequested = value;\n }\n\n constructor(\n private dataCacheService: DataCacheService\n ) {}\n\n /**\n * Execute an actionable command (triggered by user clicking a button).\n * Generic commands like open:url are handled directly; others are emitted to the host.\n */\n public async ExecuteActionableCommand(command: ActionableCommand, origin?: Omit<ActionableCommandRequest, 'command'>): Promise<void> {\n if (command.type === 'open:url') {\n this.handleOpenUrl(command);\n return;\n }\n\n const request: ActionableCommandRequest = {\n command,\n conversationId: origin?.conversationId ?? null,\n conversationDetailId: origin?.conversationDetailId ?? null\n };\n\n if (command.type === 'compose:email') {\n const { url, withinLimit } = BuildMailtoURL(command);\n if (withinLimit) {\n this.openMailto(url);\n return;\n }\n // Too long for a mailto: URL. We do NOT open it: a mail client past its limit does not\n // refuse the URL, it opens a draft with the body SILENTLY TRUNCATED and the user sends half\n // a message without noticing. Falls through to the host, which opens the full draft\n // artifact and tells the user what happened.\n request.DraftCopiedToClipboard = await this.copyDraftBody(command);\n }\n\n // open:resource (and the compose:email fallback above) require app-specific navigation.\n // compose:email is logged by TYPE ONLY: its body is free-text member correspondence, and the\n // whole command object would otherwise land in the browser console and any console-forwarding\n // telemetry.\n if (command.type === 'compose:email') {\n console.log('📤 Emitting actionable command for host app:', command.type);\n } else {\n console.log('📤 Emitting actionable command for host app:', command);\n }\n this.ActionableCommandRequested.emit(request);\n }\n\n /** @deprecated Use {@link ExecuteActionableCommand}. */\n public async executeActionableCommand(command: ActionableCommand, origin?: Omit<ActionableCommandRequest, 'command'>): Promise<void> {\n return this.ExecuteActionableCommand(command, origin);\n }\n\n /**\n * Handle open:url commands directly by opening the URL in a browser tab.\n * Data URIs are converted to Blob URLs because Chrome blocks window.open with data: URIs.\n */\n private handleOpenUrl(command: OpenURLCommand): void {\n const url = command.url;\n const newTab = command.newTab !== false;\n\n if (url.startsWith('data:')) {\n this.openDataUri(url);\n } else {\n const target = newTab ? '_blank' : '_self';\n window.open(url, target, target === '_blank' ? 'noopener,noreferrer' : undefined);\n }\n }\n\n /**\n * Best-effort copy of an over-length draft's body, so the text is not lost even when the host\n * cannot open the draft artifact.\n *\n * Never rejects, so a clipboard that is unavailable (plain HTTP) or denied by permissions policy\n * cannot stop the fallback. Nothing on the click path awaits before writeText is called, so it\n * still runs inside the click's user activation; the fallback then awaits the outcome only so\n * the host's notice can say whether the copy happened.\n *\n * @returns true only when the body is on the clipboard, so the host never claims a copy that\n * did not happen.\n */\n private async copyDraftBody(command: ComposeEmailCommand): Promise<boolean> {\n if (!command.body || !navigator.clipboard) {\n return false;\n }\n try {\n await navigator.clipboard.writeText(command.body);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Open the user's own mail client with a compose:email draft's fields pre-filled, via a\n * synthesized anchor click.\n *\n * NOTHING IS SENT HERE. The agent drafted; the user sends. This only opens a compose window.\n *\n * Deliberately not window.open: Chrome treats window.open with a non-http scheme as a popup and\n * strands an about:blank tab behind the compose window.\n */\n private openMailto(url: string): void {\n const a = document.createElement('a');\n a.href = url;\n a.style.display = 'none';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n }\n\n /**\n * Open a data URI by converting it to a Blob URL.\n * Chrome blocks window.open('data:...') for security, so we create a Blob URL instead.\n */\n private openDataUri(dataUri: string): void {\n const [header, base64Data] = dataUri.split(',');\n const mimeMatch = header.match(/data:([^;]+)/);\n const mimeType = mimeMatch ? mimeMatch[1] : 'application/octet-stream';\n\n const byteString = atob(base64Data);\n const byteArray = new Uint8Array(byteString.length);\n for (let i = 0; i < byteString.length; i++) {\n byteArray[i] = byteString.charCodeAt(i);\n }\n\n const blob = new Blob([byteArray], { type: mimeType });\n const blobUrl = URL.createObjectURL(blob);\n window.open(blobUrl, '_blank');\n }\n\n /**\n * Execute an automatic command (runs immediately without user interaction)\n * Special handling: refresh:data commands execute locally, others emit to host\n */\n public async ExecuteAutomaticCommand(command: AutomaticCommand): Promise<void> {\n console.log('Executing automatic command:', command);\n\n if (command.type === 'refresh:data') {\n // Handle data refresh locally as it's a generic operation\n await this.handleRefreshData(command);\n } else {\n // Emit other automatic commands (like notifications) for host to handle\n console.log('📤 Emitting automatic command for host app:', command);\n this.AutomaticCommandRequested.emit(command);\n }\n }\n\n /** @deprecated Use {@link ExecuteAutomaticCommand}. */\n public async executeAutomaticCommand(command: AutomaticCommand): Promise<void> {\n return this.ExecuteAutomaticCommand(command);\n }\n\n /**\n * Execute all automatic commands from an agent result\n */\n public async ExecuteAutomaticCommands(commands: AutomaticCommand[]): Promise<void> {\n if (!commands || commands.length === 0) {\n return;\n }\n\n for (const command of commands) {\n try {\n await this.ExecuteAutomaticCommand(command);\n } catch (error) {\n console.error('Error executing automatic command:', command, error);\n }\n }\n }\n\n /** @deprecated Use {@link ExecuteAutomaticCommands}. */\n public async executeAutomaticCommands(commands: AutomaticCommand[]): Promise<void> {\n return this.ExecuteAutomaticCommands(commands);\n }\n\n /**\n * Handle refreshing data (entity data or caches)\n * This is handled locally as it's a generic operation that doesn't require host app knowledge\n */\n private async handleRefreshData(command: RefreshDataCommand): Promise<void> {\n const { scope, entityNames, cacheName } = command;\n\n if (scope === 'entity' && entityNames && entityNames.length > 0) {\n // Refresh specific entity data\n for (const entityName of entityNames) {\n await this.dataCacheService.refreshEntity(entityName);\n }\n console.log('Refreshed entity data:', entityNames);\n } else if (scope === 'cache' && cacheName) {\n // Refresh a specific cache\n await this.dataCacheService.refreshCache(cacheName);\n console.log('Refreshed cache:', cacheName);\n } else {\n console.warn('Invalid refresh:data command parameters:', command);\n }\n }\n}\n"]}
@@ -30,9 +30,9 @@ export interface AgentArtifactRow {
30
30
  export interface AgentArtifactSummary {
31
31
  artifactId: string;
32
32
  artifactName: string;
33
- artifactType: string;
33
+ ArtifactType: string;
34
34
  /** Newest first, so `versions[0]` is the latest. */
35
- versions: Array<{
35
+ Versions: Array<{
36
36
  versionId: string;
37
37
  versionNumber: number;
38
38
  versionName: string | null;
@@ -33,12 +33,12 @@ export function GroupVersionsByArtifact(versions, artifactsById) {
33
33
  summary = {
34
34
  artifactId: version.ArtifactID,
35
35
  artifactName: artifact.Name,
36
- artifactType: artifact.Type,
37
- versions: []
36
+ ArtifactType: artifact.Type,
37
+ Versions: []
38
38
  };
39
39
  byArtifact.set(version.ArtifactID, summary);
40
40
  }
41
- summary.versions.push({
41
+ summary.Versions.push({
42
42
  versionId: version.ID,
43
43
  versionNumber: version.VersionNumber,
44
44
  versionName: version.Name
@@ -1 +1 @@
1
- {"version":3,"file":"agent-artifact-summary.js","sourceRoot":"","sources":["../../../src/lib/utils/agent-artifact-summary.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiCH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CACnC,QAA4C,EAC5C,aAAoD;IAEpD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAC;IAE3D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,6EAA6E;YAC7E,8EAA8E;YAC9E,wEAAwE;YACxE,SAAS;QACb,CAAC;QACD,IAAI,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,GAAG;gBACN,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,YAAY,EAAE,QAAQ,CAAC,IAAI;gBAC3B,YAAY,EAAE,QAAQ,CAAC,IAAI;gBAC3B,QAAQ,EAAE,EAAE;aACf,CAAC;YACF,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAClB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,WAAW,EAAE,OAAO,CAAC,IAAI;SAC5B,CAAC,CAAC;IACP,CAAC;IACD,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC","sourcesContent":["/**\n * Grouping for the \"Prior Artifacts Created by This Agent\" block fed to the Check Sage Intent\n * prompt.\n *\n * PURE (no Angular, no entities, no provider) so the ordering contract below is unit-testable\n * without the service's DI — same reason `conversation-detail-window.ts` and `date-jump.ts`\n * live out here rather than on their consumers.\n */\n\n/** The version fields the grouping needs. Structural, so the RunView row type satisfies it. */\nexport interface AgentArtifactVersionRow {\n ID: string;\n ArtifactID: string;\n VersionNumber: number;\n Name: string | null;\n}\n\n/** The artifact fields the prompt prints. */\nexport interface AgentArtifactRow {\n ID: string;\n Name: string;\n Type: string;\n}\n\n/**\n * One artifact an agent produced in this conversation, with its versions newest-first.\n *\n * Deliberately narrower than the array-scan shape it replaces, which also carried `runId`,\n * `artifactDescription`, `versionDescription` and `createdAt` — none of which the intent\n * prompt ever read. Dropping them is what lets the caller resolve this without joining back\n * to agent runs, turning a four-table reconstruction into two reads.\n */\nexport interface AgentArtifactSummary {\n artifactId: string;\n artifactName: string;\n artifactType: string;\n /** Newest first, so `versions[0]` is the latest. */\n versions: Array<{ versionId: string; versionNumber: number; versionName: string | null }>;\n}\n\n/**\n * Folds versions into per-artifact summaries.\n *\n * NO SORT, and that is deliberate rather than an omission. The caller reads versions\n * `__mj_CreatedAt DESC`, so inserting in arrival order leaves each artifact's versions\n * newest-first AND leaves the Map ordered by whichever artifact was touched most recently —\n * which is exactly what the explicit sort in the array-scan version used to compute. The\n * assumption is load-bearing and invisible, so it is pinned by tests.\n *\n * @param versions - Artifact versions, newest first\n * @param artifactsById - The artifact rows behind those versions\n */\nexport function GroupVersionsByArtifact(\n versions: readonly AgentArtifactVersionRow[],\n artifactsById: ReadonlyMap<string, AgentArtifactRow>\n): AgentArtifactSummary[] {\n const byArtifact = new Map<string, AgentArtifactSummary>();\n\n for (const version of versions) {\n const artifact = artifactsById.get(version.ArtifactID);\n if (!artifact) {\n // Mirrors the stored query's INNER JOIN semantics. A version can outlive the\n // artifact row the caller can read; emitting a summary with an undefined name\n // would put the string \"undefined\" straight into the classifier prompt.\n continue;\n }\n let summary = byArtifact.get(version.ArtifactID);\n if (!summary) {\n summary = {\n artifactId: version.ArtifactID,\n artifactName: artifact.Name,\n artifactType: artifact.Type,\n versions: []\n };\n byArtifact.set(version.ArtifactID, summary);\n }\n summary.versions.push({\n versionId: version.ID,\n versionNumber: version.VersionNumber,\n versionName: version.Name\n });\n }\n return [...byArtifact.values()];\n}\n"]}
1
+ {"version":3,"file":"agent-artifact-summary.js","sourceRoot":"","sources":["../../../src/lib/utils/agent-artifact-summary.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiCH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CACnC,QAA4C,EAC5C,aAAoD;IAEpD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAC;IAE3D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,6EAA6E;YAC7E,8EAA8E;YAC9E,wEAAwE;YACxE,SAAS;QACb,CAAC;QACD,IAAI,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,GAAG;gBACN,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,YAAY,EAAE,QAAQ,CAAC,IAAI;gBAC3B,YAAY,EAAE,QAAQ,CAAC,IAAI;gBAC3B,QAAQ,EAAE,EAAE;aACf,CAAC;YACF,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAClB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,WAAW,EAAE,OAAO,CAAC,IAAI;SAC5B,CAAC,CAAC;IACP,CAAC;IACD,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC","sourcesContent":["/**\n * Grouping for the \"Prior Artifacts Created by This Agent\" block fed to the Check Sage Intent\n * prompt.\n *\n * PURE (no Angular, no entities, no provider) so the ordering contract below is unit-testable\n * without the service's DI — same reason `conversation-detail-window.ts` and `date-jump.ts`\n * live out here rather than on their consumers.\n */\n\n/** The version fields the grouping needs. Structural, so the RunView row type satisfies it. */\nexport interface AgentArtifactVersionRow {\n ID: string;\n ArtifactID: string;\n VersionNumber: number;\n Name: string | null;\n}\n\n/** The artifact fields the prompt prints. */\nexport interface AgentArtifactRow {\n ID: string;\n Name: string;\n Type: string;\n}\n\n/**\n * One artifact an agent produced in this conversation, with its versions newest-first.\n *\n * Deliberately narrower than the array-scan shape it replaces, which also carried `runId`,\n * `artifactDescription`, `versionDescription` and `createdAt` — none of which the intent\n * prompt ever read. Dropping them is what lets the caller resolve this without joining back\n * to agent runs, turning a four-table reconstruction into two reads.\n */\nexport interface AgentArtifactSummary {\n artifactId: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined\n artifactName: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined\n ArtifactType: string;\n /** Newest first, so `versions[0]` is the latest. */\n Versions: Array<{ versionId: string; versionNumber: number; versionName: string | null }>;\n}\n\n/**\n * Folds versions into per-artifact summaries.\n *\n * NO SORT, and that is deliberate rather than an omission. The caller reads versions\n * `__mj_CreatedAt DESC`, so inserting in arrival order leaves each artifact's versions\n * newest-first AND leaves the Map ordered by whichever artifact was touched most recently —\n * which is exactly what the explicit sort in the array-scan version used to compute. The\n * assumption is load-bearing and invisible, so it is pinned by tests.\n *\n * @param versions - Artifact versions, newest first\n * @param artifactsById - The artifact rows behind those versions\n */\nexport function GroupVersionsByArtifact(\n versions: readonly AgentArtifactVersionRow[],\n artifactsById: ReadonlyMap<string, AgentArtifactRow>\n): AgentArtifactSummary[] {\n const byArtifact = new Map<string, AgentArtifactSummary>();\n\n for (const version of versions) {\n const artifact = artifactsById.get(version.ArtifactID);\n if (!artifact) {\n // Mirrors the stored query's INNER JOIN semantics. A version can outlive the\n // artifact row the caller can read; emitting a summary with an undefined name\n // would put the string \"undefined\" straight into the classifier prompt.\n continue;\n }\n let summary = byArtifact.get(version.ArtifactID);\n if (!summary) {\n summary = {\n artifactId: version.ArtifactID,\n artifactName: artifact.Name,\n ArtifactType: artifact.Type,\n Versions: []\n };\n byArtifact.set(version.ArtifactID, summary);\n }\n summary.Versions.push({\n versionId: version.ID,\n versionNumber: version.VersionNumber,\n versionName: version.Name\n });\n }\n return [...byArtifact.values()];\n}\n"]}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @fileoverview Pure routing rules for an agent turn: which agent answers a message, and whether
3
+ * any does. Kept free of Angular and of I/O so the whole matrix (reply mode × mention × allowed
4
+ * list × route) is testable directly; `MessageInputComponent` supplies the candidates.
5
+ *
6
+ * @module @memberjunction/ng-conversations
7
+ */
8
+ import type { AgentReplyMode, AgentTurnTarget } from '../models/agent-turn.model';
9
+ /** The agent each route would use for one message, before the host's rules are applied. */
10
+ export interface AgentTurnCandidates {
11
+ /** Agents the message tags, in the order they appear. */
12
+ MentionedAgentIds: readonly string[];
13
+ /** The last agent that answered in the conversation, other than the conversation manager. */
14
+ ContinuityAgentId: string | null;
15
+ /**
16
+ * True when a routing decision put `ContinuityAgentId` there in place of the last agent that
17
+ * answered. The turn is then labelled `DecisionRouted` instead of `Continuity`.
18
+ */
19
+ ContinuityDecisionRouted?: boolean;
20
+ /** The agent pinned on the conversation. */
21
+ ConversationDefaultAgentId: string | null;
22
+ /** The host's `DefaultAgentId` input. */
23
+ HostDefaultAgentId: string | null;
24
+ /** MJ's conversation manager agent. */
25
+ ConversationManagerAgentId: string | null;
26
+ }
27
+ /** The host's rules for the chat. */
28
+ export interface AgentTurnRules {
29
+ /** When a message starts a turn. */
30
+ ReplyMode: AgentReplyMode;
31
+ /** The agents that may answer. Null allows every agent. */
32
+ AllowedAgentIDs: readonly string[] | null;
33
+ }
34
+ /**
35
+ * Picks the agent and route for one message, or null when no turn starts.
36
+ *
37
+ * The order is MJ's: the first tagged agent the host allows, then (under `Always` only) the last
38
+ * agent that answered, the conversation's pinned agent, the host's default agent, and the
39
+ * conversation manager. A candidate the host doesn't allow is skipped. A continuity candidate that
40
+ * a routing decision chose (`ContinuityDecisionRouted`) takes the `DecisionRouted` label.
41
+ *
42
+ * A continuity or default candidate that `isKnownAgent` doesn't recognise falls back to the
43
+ * conversation manager, as MJ always has, rather than to the next route. A tagged agent is taken
44
+ * as tagged.
45
+ *
46
+ * @param candidates The agent each route would use.
47
+ * @param rules The host's reply mode and allowed list.
48
+ * @param isKnownAgent True when the agent exists in the client's agent catalog.
49
+ */
50
+ export declare function ResolveAgentTurn(candidates: AgentTurnCandidates, rules: AgentTurnRules, isKnownAgent: (agentId: string) => boolean): AgentTurnTarget | null;
51
+ /** A task-graph step that runs an agent, as the conversation manager emits it. */
52
+ interface AgentTaskStep {
53
+ kind: string;
54
+ configuration?: {
55
+ agentName?: string;
56
+ } | object;
57
+ }
58
+ /**
59
+ * The agent names in a task graph that the host doesn't allow. The conversation manager can
60
+ * answer with a multi-step workflow instead of a single delegation; each `Agent` step names the
61
+ * agent that runs it, so the allowed list has to hold there too.
62
+ *
63
+ * @param steps The graph's tasks.
64
+ * @param allowedAgentIDs The host's allowed list. Null allows every agent.
65
+ * @param resolveAgentId Maps an agent name to its ID, or null when no such agent exists.
66
+ * @returns The disallowed names, each once, in the order they appear. Empty when all are allowed.
67
+ */
68
+ export declare function FindDisallowedTaskGraphAgents(steps: ReadonlyArray<AgentTaskStep>, allowedAgentIDs: readonly string[] | null, resolveAgentId: (agentName: string) => string | null): string[];
69
+ export {};
70
+ //# sourceMappingURL=agent-turn-routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-turn-routing.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/agent-turn-routing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAkB,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElG,2FAA2F;AAC3F,MAAM,WAAW,mBAAmB;IAChC,yDAAyD;IACzD,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,6FAA6F;IAC7F,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,4CAA4C;IAC5C,0BAA0B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,yCAAyC;IACzC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,uCAAuC;IACvC,0BAA0B,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED,qCAAqC;AACrC,MAAM,WAAW,cAAc;IAC3B,oCAAoC;IACpC,SAAS,EAAE,cAAc,CAAC;IAC1B,2DAA2D;IAC3D,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CAC7C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC5B,UAAU,EAAE,mBAAmB,EAC/B,KAAK,EAAE,cAAc,EACrB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAC3C,eAAe,GAAG,IAAI,CAsBxB;AAUD,kFAAkF;AAClF,UAAU,aAAa;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC;CACnD;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CACzC,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,EACnC,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,EACzC,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GACrD,MAAM,EAAE,CAYV"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @fileoverview Pure routing rules for an agent turn: which agent answers a message, and whether
3
+ * any does. Kept free of Angular and of I/O so the whole matrix (reply mode × mention × allowed
4
+ * list × route) is testable directly; `MessageInputComponent` supplies the candidates.
5
+ *
6
+ * @module @memberjunction/ng-conversations
7
+ */
8
+ import { IsAgentAllowed } from '@memberjunction/ai-core-plus';
9
+ /**
10
+ * Picks the agent and route for one message, or null when no turn starts.
11
+ *
12
+ * The order is MJ's: the first tagged agent the host allows, then (under `Always` only) the last
13
+ * agent that answered, the conversation's pinned agent, the host's default agent, and the
14
+ * conversation manager. A candidate the host doesn't allow is skipped. A continuity candidate that
15
+ * a routing decision chose (`ContinuityDecisionRouted`) takes the `DecisionRouted` label.
16
+ *
17
+ * A continuity or default candidate that `isKnownAgent` doesn't recognise falls back to the
18
+ * conversation manager, as MJ always has, rather than to the next route. A tagged agent is taken
19
+ * as tagged.
20
+ *
21
+ * @param candidates The agent each route would use.
22
+ * @param rules The host's reply mode and allowed list.
23
+ * @param isKnownAgent True when the agent exists in the client's agent catalog.
24
+ */
25
+ export function ResolveAgentTurn(candidates, rules, isKnownAgent) {
26
+ const mentioned = candidates.MentionedAgentIds.find(id => IsAgentAllowed(id, rules.AllowedAgentIDs));
27
+ if (mentioned) {
28
+ return { AgentId: mentioned, Route: 'Mention' };
29
+ }
30
+ if (rules.ReplyMode === 'MentionOnly') {
31
+ return null;
32
+ }
33
+ const implicitRoutes = [
34
+ [candidates.ContinuityDecisionRouted ? 'DecisionRouted' : 'Continuity', candidates.ContinuityAgentId],
35
+ ['ConversationDefault', candidates.ConversationDefaultAgentId],
36
+ ['HostDefault', candidates.HostDefaultAgentId],
37
+ ];
38
+ for (const [route, agentId] of implicitRoutes) {
39
+ if (agentId && IsAgentAllowed(agentId, rules.AllowedAgentIDs)) {
40
+ return isKnownAgent(agentId)
41
+ ? { AgentId: agentId, Route: route }
42
+ : conversationManagerTarget(candidates, rules);
43
+ }
44
+ }
45
+ return conversationManagerTarget(candidates, rules);
46
+ }
47
+ /** The conversation manager's turn, when there is one and the host allows it. */
48
+ function conversationManagerTarget(candidates, rules) {
49
+ const agentId = candidates.ConversationManagerAgentId;
50
+ return agentId && IsAgentAllowed(agentId, rules.AllowedAgentIDs)
51
+ ? { AgentId: agentId, Route: 'ConversationManager' }
52
+ : null;
53
+ }
54
+ /**
55
+ * The agent names in a task graph that the host doesn't allow. The conversation manager can
56
+ * answer with a multi-step workflow instead of a single delegation; each `Agent` step names the
57
+ * agent that runs it, so the allowed list has to hold there too.
58
+ *
59
+ * @param steps The graph's tasks.
60
+ * @param allowedAgentIDs The host's allowed list. Null allows every agent.
61
+ * @param resolveAgentId Maps an agent name to its ID, or null when no such agent exists.
62
+ * @returns The disallowed names, each once, in the order they appear. Empty when all are allowed.
63
+ */
64
+ export function FindDisallowedTaskGraphAgents(steps, allowedAgentIDs, resolveAgentId) {
65
+ if (allowedAgentIDs == null) {
66
+ return [];
67
+ }
68
+ const disallowed = [];
69
+ for (const step of steps) {
70
+ const agentName = step.kind === 'Agent' ? agentNameOf(step.configuration) : null;
71
+ if (agentName && !IsAgentAllowed(resolveAgentId(agentName), allowedAgentIDs) && !disallowed.includes(agentName)) {
72
+ disallowed.push(agentName);
73
+ }
74
+ }
75
+ return disallowed;
76
+ }
77
+ /** The `agentName` of an Agent step's configuration, when it has one. */
78
+ function agentNameOf(configuration) {
79
+ if (configuration && 'agentName' in configuration && typeof configuration.agentName === 'string') {
80
+ return configuration.agentName;
81
+ }
82
+ return null;
83
+ }
84
+ //# sourceMappingURL=agent-turn-routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-turn-routing.js","sourceRoot":"","sources":["../../../src/lib/utils/agent-turn-routing.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Pure routing rules for an agent turn: which agent answers a message, and whether\n * any does. Kept free of Angular and of I/O so the whole matrix (reply mode × mention × allowed\n * list × route) is testable directly; `MessageInputComponent` supplies the candidates.\n *\n * @module @memberjunction/ng-conversations\n */\n\nimport { IsAgentAllowed } from '@memberjunction/ai-core-plus';\nimport type { AgentReplyMode, AgentTurnRoute, AgentTurnTarget } from '../models/agent-turn.model';\n\n/** The agent each route would use for one message, before the host's rules are applied. */\nexport interface AgentTurnCandidates {\n /** Agents the message tags, in the order they appear. */\n MentionedAgentIds: readonly string[];\n /** The last agent that answered in the conversation, other than the conversation manager. */\n ContinuityAgentId: string | null;\n /**\n * True when a routing decision put `ContinuityAgentId` there in place of the last agent that\n * answered. The turn is then labelled `DecisionRouted` instead of `Continuity`.\n */\n ContinuityDecisionRouted?: boolean;\n /** The agent pinned on the conversation. */\n ConversationDefaultAgentId: string | null;\n /** The host's `DefaultAgentId` input. */\n HostDefaultAgentId: string | null;\n /** MJ's conversation manager agent. */\n ConversationManagerAgentId: string | null;\n}\n\n/** The host's rules for the chat. */\nexport interface AgentTurnRules {\n /** When a message starts a turn. */\n ReplyMode: AgentReplyMode;\n /** The agents that may answer. Null allows every agent. */\n AllowedAgentIDs: readonly string[] | null;\n}\n\n/**\n * Picks the agent and route for one message, or null when no turn starts.\n *\n * The order is MJ's: the first tagged agent the host allows, then (under `Always` only) the last\n * agent that answered, the conversation's pinned agent, the host's default agent, and the\n * conversation manager. A candidate the host doesn't allow is skipped. A continuity candidate that\n * a routing decision chose (`ContinuityDecisionRouted`) takes the `DecisionRouted` label.\n *\n * A continuity or default candidate that `isKnownAgent` doesn't recognise falls back to the\n * conversation manager, as MJ always has, rather than to the next route. A tagged agent is taken\n * as tagged.\n *\n * @param candidates The agent each route would use.\n * @param rules The host's reply mode and allowed list.\n * @param isKnownAgent True when the agent exists in the client's agent catalog.\n */\nexport function ResolveAgentTurn(\n candidates: AgentTurnCandidates,\n rules: AgentTurnRules,\n isKnownAgent: (agentId: string) => boolean\n): AgentTurnTarget | null {\n const mentioned = candidates.MentionedAgentIds.find(id => IsAgentAllowed(id, rules.AllowedAgentIDs));\n if (mentioned) {\n return { AgentId: mentioned, Route: 'Mention' };\n }\n if (rules.ReplyMode === 'MentionOnly') {\n return null;\n }\n\n const implicitRoutes: ReadonlyArray<[AgentTurnRoute, string | null]> = [\n [candidates.ContinuityDecisionRouted ? 'DecisionRouted' : 'Continuity', candidates.ContinuityAgentId],\n ['ConversationDefault', candidates.ConversationDefaultAgentId],\n ['HostDefault', candidates.HostDefaultAgentId],\n ];\n for (const [route, agentId] of implicitRoutes) {\n if (agentId && IsAgentAllowed(agentId, rules.AllowedAgentIDs)) {\n return isKnownAgent(agentId)\n ? { AgentId: agentId, Route: route }\n : conversationManagerTarget(candidates, rules);\n }\n }\n return conversationManagerTarget(candidates, rules);\n}\n\n/** The conversation manager's turn, when there is one and the host allows it. */\nfunction conversationManagerTarget(candidates: AgentTurnCandidates, rules: AgentTurnRules): AgentTurnTarget | null {\n const agentId = candidates.ConversationManagerAgentId;\n return agentId && IsAgentAllowed(agentId, rules.AllowedAgentIDs)\n ? { AgentId: agentId, Route: 'ConversationManager' }\n : null;\n}\n\n/** A task-graph step that runs an agent, as the conversation manager emits it. */\ninterface AgentTaskStep {\n kind: string;\n configuration?: { agentName?: string } | object;\n}\n\n/**\n * The agent names in a task graph that the host doesn't allow. The conversation manager can\n * answer with a multi-step workflow instead of a single delegation; each `Agent` step names the\n * agent that runs it, so the allowed list has to hold there too.\n *\n * @param steps The graph's tasks.\n * @param allowedAgentIDs The host's allowed list. Null allows every agent.\n * @param resolveAgentId Maps an agent name to its ID, or null when no such agent exists.\n * @returns The disallowed names, each once, in the order they appear. Empty when all are allowed.\n */\nexport function FindDisallowedTaskGraphAgents(\n steps: ReadonlyArray<AgentTaskStep>,\n allowedAgentIDs: readonly string[] | null,\n resolveAgentId: (agentName: string) => string | null\n): string[] {\n if (allowedAgentIDs == null) {\n return [];\n }\n const disallowed: string[] = [];\n for (const step of steps) {\n const agentName = step.kind === 'Agent' ? agentNameOf(step.configuration) : null;\n if (agentName && !IsAgentAllowed(resolveAgentId(agentName), allowedAgentIDs) && !disallowed.includes(agentName)) {\n disallowed.push(agentName);\n }\n }\n return disallowed;\n}\n\n/** The `agentName` of an Agent step's configuration, when it has one. */\nfunction agentNameOf(configuration: AgentTaskStep['configuration']): string | null {\n if (configuration && 'agentName' in configuration && typeof configuration.agentName === 'string') {\n return configuration.agentName;\n }\n return null;\n}\n"]}