@memberjunction/ng-conversations 5.43.0 → 5.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (405) hide show
  1. package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts +0 -1
  2. package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts.map +1 -1
  3. package/dist/lib/components/active-tasks/active-tasks-panel.component.js +56 -52
  4. package/dist/lib/components/active-tasks/active-tasks-panel.component.js.map +1 -1
  5. package/dist/lib/components/artifact/artifact-share-modal.component.d.ts +3 -1
  6. package/dist/lib/components/artifact/artifact-share-modal.component.d.ts.map +1 -1
  7. package/dist/lib/components/artifact/artifact-share-modal.component.js +52 -52
  8. package/dist/lib/components/artifact/artifact-share-modal.component.js.map +1 -1
  9. package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
  10. package/dist/lib/components/collection/collection-form-modal.component.js +10 -14
  11. package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
  12. package/dist/lib/components/collection/collection-share-modal.component.d.ts +3 -1
  13. package/dist/lib/components/collection/collection-share-modal.component.d.ts.map +1 -1
  14. package/dist/lib/components/collection/collection-share-modal.component.js +56 -56
  15. package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -1
  16. package/dist/lib/components/collection/collection-tree.component.d.ts +3 -1
  17. package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
  18. package/dist/lib/components/collection/collection-tree.component.js +10 -7
  19. package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
  20. package/dist/lib/components/collection/collection-view.component.d.ts +3 -1
  21. package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
  22. package/dist/lib/components/collection/collection-view.component.js +29 -41
  23. package/dist/lib/components/collection/collection-view.component.js.map +1 -1
  24. package/dist/lib/components/collection/collections-full-view.component.d.ts +4 -0
  25. package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
  26. package/dist/lib/components/collection/collections-full-view.component.js +134 -166
  27. package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
  28. package/dist/lib/components/composer/ai-composer.component.d.ts +103 -0
  29. package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -0
  30. package/dist/lib/components/composer/ai-composer.component.js +263 -0
  31. package/dist/lib/components/composer/ai-composer.component.js.map +1 -0
  32. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +76 -12
  33. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  34. package/dist/lib/components/conversation/conversation-chat-area.component.js +522 -158
  35. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  36. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +1 -1
  37. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
  38. package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
  39. package/dist/lib/components/conversation/pinned-messages-panel.component.js +6 -9
  40. package/dist/lib/components/conversation/pinned-messages-panel.component.js.map +1 -1
  41. package/dist/lib/components/library/library-full-view.component.d.ts.map +1 -1
  42. package/dist/lib/components/library/library-full-view.component.js +20 -24
  43. package/dist/lib/components/library/library-full-view.component.js.map +1 -1
  44. package/dist/lib/components/members/members-modal.component.d.ts.map +1 -1
  45. package/dist/lib/components/members/members-modal.component.js +10 -11
  46. package/dist/lib/components/members/members-modal.component.js.map +1 -1
  47. package/dist/lib/components/message/message-input.component.d.ts +87 -23
  48. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  49. package/dist/lib/components/message/message-input.component.js +245 -158
  50. package/dist/lib/components/message/message-input.component.js.map +1 -1
  51. package/dist/lib/components/message/message-item.component.d.ts +11 -3
  52. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  53. package/dist/lib/components/message/message-item.component.js +73 -21
  54. package/dist/lib/components/message/message-item.component.js.map +1 -1
  55. package/dist/lib/components/message/message-list.component.js +6 -9
  56. package/dist/lib/components/message/message-list.component.js.map +1 -1
  57. package/dist/lib/components/overlay/chat-overlay.component.d.ts +4 -1
  58. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  59. package/dist/lib/components/overlay/chat-overlay.component.js +9 -4
  60. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  61. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +45 -0
  62. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +1 -1
  63. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +10 -0
  64. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +1 -1
  65. package/dist/lib/components/realtime/channels/client-context-channel.d.ts +46 -0
  66. package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -0
  67. package/dist/lib/components/realtime/channels/client-context-channel.js +174 -0
  68. package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -0
  69. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.d.ts +123 -0
  70. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.d.ts.map +1 -0
  71. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js +397 -0
  72. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js.map +1 -0
  73. package/dist/lib/components/realtime/media/media-channel-state.d.ts +103 -0
  74. package/dist/lib/components/realtime/media/media-channel-state.d.ts.map +1 -0
  75. package/dist/lib/components/realtime/media/media-channel-state.js +143 -0
  76. package/dist/lib/components/realtime/media/media-channel-state.js.map +1 -0
  77. package/dist/lib/components/realtime/media/media-channel-tools.d.ts +24 -0
  78. package/dist/lib/components/realtime/media/media-channel-tools.d.ts.map +1 -0
  79. package/dist/lib/components/realtime/media/media-channel-tools.js +107 -0
  80. package/dist/lib/components/realtime/media/media-channel-tools.js.map +1 -0
  81. package/dist/lib/components/realtime/media/media-channel.d.ts +89 -0
  82. package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -0
  83. package/dist/lib/components/realtime/media/media-channel.js +253 -0
  84. package/dist/lib/components/realtime/media/media-channel.js.map +1 -0
  85. package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts +141 -0
  86. package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts.map +1 -0
  87. package/dist/lib/components/realtime/media/realtime-media-surface.component.js +574 -0
  88. package/dist/lib/components/realtime/media/realtime-media-surface.component.js.map +1 -0
  89. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +59 -14
  90. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -1
  91. package/dist/lib/components/realtime/realtime-activity-rail.component.js +277 -74
  92. package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
  93. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +28 -27
  94. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  95. package/dist/lib/components/realtime/realtime-agent-banner.component.js +144 -143
  96. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  97. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +12 -0
  98. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
  99. package/dist/lib/components/realtime/realtime-agent-picker.component.js +105 -43
  100. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
  101. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +2 -2
  102. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -1
  103. package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -1
  104. package/dist/lib/components/realtime/realtime-composer.component.d.ts +41 -7
  105. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
  106. package/dist/lib/components/realtime/realtime-composer.component.js +216 -102
  107. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  108. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +0 -2
  109. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -1
  110. package/dist/lib/components/realtime/realtime-delegation-card.component.js +67 -71
  111. package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
  112. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +364 -44
  113. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  114. package/dist/lib/components/realtime/realtime-session-overlay.component.js +839 -153
  115. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  116. package/dist/lib/components/realtime/realtime-session-state.d.ts +5 -5
  117. package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -1
  118. package/dist/lib/components/realtime/realtime-session-state.js.map +1 -1
  119. package/dist/lib/components/realtime/realtime-surface-tab-style.d.ts +70 -0
  120. package/dist/lib/components/realtime/realtime-surface-tab-style.d.ts.map +1 -0
  121. package/dist/lib/components/realtime/realtime-surface-tab-style.js +115 -0
  122. package/dist/lib/components/realtime/realtime-surface-tab-style.js.map +1 -0
  123. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +55 -57
  124. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
  125. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +165 -143
  126. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
  127. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +80 -71
  128. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
  129. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +83 -113
  130. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
  131. package/dist/lib/components/realtime/realtime-ui-config.d.ts +270 -0
  132. package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -0
  133. package/dist/lib/components/realtime/realtime-ui-config.js +212 -0
  134. package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -0
  135. package/dist/lib/components/search/search-panel.component.d.ts +2 -0
  136. package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
  137. package/dist/lib/components/search/search-panel.component.js +92 -101
  138. package/dist/lib/components/search/search-panel.component.js.map +1 -1
  139. package/dist/lib/components/share/share-modal.component.d.ts.map +1 -1
  140. package/dist/lib/components/share/share-modal.component.js +10 -11
  141. package/dist/lib/components/share/share-modal.component.js.map +1 -1
  142. package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -1
  143. package/dist/lib/components/shared/user-picker.component.js +12 -15
  144. package/dist/lib/components/shared/user-picker.component.js.map +1 -1
  145. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +11 -3
  146. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
  147. package/dist/lib/components/sidebar/conversation-sidebar.component.js +34 -10
  148. package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
  149. package/dist/lib/components/sidebar/routines-section.component.d.ts +73 -0
  150. package/dist/lib/components/sidebar/routines-section.component.d.ts.map +1 -0
  151. package/dist/lib/components/sidebar/routines-section.component.js +211 -0
  152. package/dist/lib/components/sidebar/routines-section.component.js.map +1 -0
  153. package/dist/lib/components/tasks/tasks-dropdown.component.d.ts +12 -0
  154. package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
  155. package/dist/lib/components/tasks/tasks-dropdown.component.js +37 -1
  156. package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
  157. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +16 -5
  158. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  159. package/dist/lib/components/workspace/conversation-workspace.component.js +51 -31
  160. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  161. package/dist/lib/composer-plugins/agent-mention.provider.d.ts +16 -0
  162. package/dist/lib/composer-plugins/agent-mention.provider.d.ts.map +1 -0
  163. package/dist/lib/composer-plugins/agent-mention.provider.js +28 -0
  164. package/dist/lib/composer-plugins/agent-mention.provider.js.map +1 -0
  165. package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts +20 -0
  166. package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts.map +1 -0
  167. package/dist/lib/composer-plugins/base-conversation-mention.provider.js +32 -0
  168. package/dist/lib/composer-plugins/base-conversation-mention.provider.js.map +1 -0
  169. package/dist/lib/composer-plugins/load-composer-plugins.d.ts +9 -0
  170. package/dist/lib/composer-plugins/load-composer-plugins.d.ts.map +1 -0
  171. package/dist/lib/composer-plugins/load-composer-plugins.js +17 -0
  172. package/dist/lib/composer-plugins/load-composer-plugins.js.map +1 -0
  173. package/dist/lib/composer-plugins/record-mention.provider.d.ts +14 -0
  174. package/dist/lib/composer-plugins/record-mention.provider.d.ts.map +1 -0
  175. package/dist/lib/composer-plugins/record-mention.provider.js +26 -0
  176. package/dist/lib/composer-plugins/record-mention.provider.js.map +1 -0
  177. package/dist/lib/composer-plugins/skill-command.provider.d.ts +15 -0
  178. package/dist/lib/composer-plugins/skill-command.provider.d.ts.map +1 -0
  179. package/dist/lib/composer-plugins/skill-command.provider.js +27 -0
  180. package/dist/lib/composer-plugins/skill-command.provider.js.map +1 -0
  181. package/dist/lib/conversations.module.d.ts +68 -64
  182. package/dist/lib/conversations.module.d.ts.map +1 -1
  183. package/dist/lib/conversations.module.js +69 -18
  184. package/dist/lib/conversations.module.js.map +1 -1
  185. package/dist/lib/models/conversation-state.model.d.ts +6 -3
  186. package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
  187. package/dist/lib/models/conversation-state.model.js.map +1 -1
  188. package/dist/lib/services/conversation-agent.service.d.ts +9 -2
  189. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  190. package/dist/lib/services/conversation-agent.service.js +26 -2
  191. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  192. package/dist/lib/services/conversation-attachment.service.d.ts +1 -1
  193. package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
  194. package/dist/lib/services/conversation-attachment.service.js.map +1 -1
  195. package/dist/lib/services/mention-autocomplete.service.d.ts +42 -19
  196. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  197. package/dist/lib/services/mention-autocomplete.service.js +113 -18
  198. package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
  199. package/dist/lib/services/realtime-audio-recorder.d.ts +143 -0
  200. package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -0
  201. package/dist/lib/services/realtime-audio-recorder.js +379 -0
  202. package/dist/lib/services/realtime-audio-recorder.js.map +1 -0
  203. package/dist/lib/services/realtime-pcm-wav.d.ts +75 -0
  204. package/dist/lib/services/realtime-pcm-wav.d.ts.map +1 -0
  205. package/dist/lib/services/realtime-pcm-wav.js +205 -0
  206. package/dist/lib/services/realtime-pcm-wav.js.map +1 -0
  207. package/dist/lib/services/realtime-session-review.service.d.ts +28 -1
  208. package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -1
  209. package/dist/lib/services/realtime-session-review.service.js +12 -3
  210. package/dist/lib/services/realtime-session-review.service.js.map +1 -1
  211. package/dist/lib/services/realtime-session.service.d.ts +210 -20
  212. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  213. package/dist/lib/services/realtime-session.service.js +452 -21
  214. package/dist/lib/services/realtime-session.service.js.map +1 -1
  215. package/dist/lib/services/realtime-sessions-adapter.js +1 -1
  216. package/dist/lib/services/realtime-sessions-adapter.js.map +1 -1
  217. package/dist/lib/services/ui-command-handler.service.d.ts +7 -2
  218. package/dist/lib/services/ui-command-handler.service.d.ts.map +1 -1
  219. package/dist/lib/services/ui-command-handler.service.js +6 -2
  220. package/dist/lib/services/ui-command-handler.service.js.map +1 -1
  221. package/dist/lib/utils/plan-mode-preference.d.ts +62 -0
  222. package/dist/lib/utils/plan-mode-preference.d.ts.map +1 -0
  223. package/dist/lib/utils/plan-mode-preference.js +130 -0
  224. package/dist/lib/utils/plan-mode-preference.js.map +1 -0
  225. package/dist/public-api.d.ts +29 -3
  226. package/dist/public-api.d.ts.map +1 -1
  227. package/dist/public-api.js +46 -3
  228. package/dist/public-api.js.map +1 -1
  229. package/package.json +30 -26
  230. package/dist/__tests__/attachment-badge.test.d.ts +0 -2
  231. package/dist/__tests__/attachment-badge.test.d.ts.map +0 -1
  232. package/dist/__tests__/attachment-badge.test.js +0 -66
  233. package/dist/__tests__/attachment-badge.test.js.map +0 -1
  234. package/dist/__tests__/channel-optional-surface.test.d.ts +0 -2
  235. package/dist/__tests__/channel-optional-surface.test.d.ts.map +0 -1
  236. package/dist/__tests__/channel-optional-surface.test.js +0 -53
  237. package/dist/__tests__/channel-optional-surface.test.js.map +0 -1
  238. package/dist/__tests__/chat-events.test.d.ts +0 -14
  239. package/dist/__tests__/chat-events.test.d.ts.map +0 -1
  240. package/dist/__tests__/chat-events.test.js +0 -109
  241. package/dist/__tests__/chat-events.test.js.map +0 -1
  242. package/dist/__tests__/collections-full-view.test.d.ts +0 -2
  243. package/dist/__tests__/collections-full-view.test.d.ts.map +0 -1
  244. package/dist/__tests__/collections-full-view.test.js +0 -225
  245. package/dist/__tests__/collections-full-view.test.js.map +0 -1
  246. package/dist/__tests__/conversation-cache.test.d.ts +0 -2
  247. package/dist/__tests__/conversation-cache.test.d.ts.map +0 -1
  248. package/dist/__tests__/conversation-cache.test.js +0 -233
  249. package/dist/__tests__/conversation-cache.test.js.map +0 -1
  250. package/dist/__tests__/conversation-naming.test.d.ts +0 -2
  251. package/dist/__tests__/conversation-naming.test.d.ts.map +0 -1
  252. package/dist/__tests__/conversation-naming.test.js +0 -110
  253. package/dist/__tests__/conversation-naming.test.js.map +0 -1
  254. package/dist/__tests__/delegation-result-parser.test.d.ts +0 -2
  255. package/dist/__tests__/delegation-result-parser.test.d.ts.map +0 -1
  256. package/dist/__tests__/delegation-result-parser.test.js +0 -107
  257. package/dist/__tests__/delegation-result-parser.test.js.map +0 -1
  258. package/dist/__tests__/distinct-artifacts.test.d.ts +0 -2
  259. package/dist/__tests__/distinct-artifacts.test.d.ts.map +0 -1
  260. package/dist/__tests__/distinct-artifacts.test.js +0 -56
  261. package/dist/__tests__/distinct-artifacts.test.js.map +0 -1
  262. package/dist/__tests__/event-wiring.test.d.ts +0 -15
  263. package/dist/__tests__/event-wiring.test.d.ts.map +0 -1
  264. package/dist/__tests__/event-wiring.test.js +0 -100
  265. package/dist/__tests__/event-wiring.test.js.map +0 -1
  266. package/dist/__tests__/index.test.d.ts +0 -2
  267. package/dist/__tests__/index.test.d.ts.map +0 -1
  268. package/dist/__tests__/index.test.js +0 -7
  269. package/dist/__tests__/index.test.js.map +0 -1
  270. package/dist/__tests__/narration-template.test.d.ts +0 -2
  271. package/dist/__tests__/narration-template.test.d.ts.map +0 -1
  272. package/dist/__tests__/narration-template.test.js +0 -76
  273. package/dist/__tests__/narration-template.test.js.map +0 -1
  274. package/dist/__tests__/notification-model.test.d.ts +0 -2
  275. package/dist/__tests__/notification-model.test.d.ts.map +0 -1
  276. package/dist/__tests__/notification-model.test.js +0 -68
  277. package/dist/__tests__/notification-model.test.js.map +0 -1
  278. package/dist/__tests__/realtime-agent-picker-models.test.d.ts +0 -2
  279. package/dist/__tests__/realtime-agent-picker-models.test.d.ts.map +0 -1
  280. package/dist/__tests__/realtime-agent-picker-models.test.js +0 -49
  281. package/dist/__tests__/realtime-agent-picker-models.test.js.map +0 -1
  282. package/dist/__tests__/realtime-audio-visuals.test.d.ts +0 -2
  283. package/dist/__tests__/realtime-audio-visuals.test.d.ts.map +0 -1
  284. package/dist/__tests__/realtime-audio-visuals.test.js +0 -123
  285. package/dist/__tests__/realtime-audio-visuals.test.js.map +0 -1
  286. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts +0 -2
  287. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts.map +0 -1
  288. package/dist/__tests__/realtime-delegation-card-cancel.test.js +0 -48
  289. package/dist/__tests__/realtime-delegation-card-cancel.test.js.map +0 -1
  290. package/dist/__tests__/realtime-disclosure.test.d.ts +0 -2
  291. package/dist/__tests__/realtime-disclosure.test.d.ts.map +0 -1
  292. package/dist/__tests__/realtime-disclosure.test.js +0 -164
  293. package/dist/__tests__/realtime-disclosure.test.js.map +0 -1
  294. package/dist/__tests__/realtime-pairing.test.d.ts +0 -2
  295. package/dist/__tests__/realtime-pairing.test.d.ts.map +0 -1
  296. package/dist/__tests__/realtime-pairing.test.js +0 -207
  297. package/dist/__tests__/realtime-pairing.test.js.map +0 -1
  298. package/dist/__tests__/realtime-review-lifecycle.test.d.ts +0 -2
  299. package/dist/__tests__/realtime-review-lifecycle.test.d.ts.map +0 -1
  300. package/dist/__tests__/realtime-review-lifecycle.test.js +0 -154
  301. package/dist/__tests__/realtime-review-lifecycle.test.js.map +0 -1
  302. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts +0 -2
  303. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts.map +0 -1
  304. package/dist/__tests__/realtime-session-cancel-usage.test.js +0 -230
  305. package/dist/__tests__/realtime-session-cancel-usage.test.js.map +0 -1
  306. package/dist/__tests__/realtime-session-channels.test.d.ts +0 -2
  307. package/dist/__tests__/realtime-session-channels.test.d.ts.map +0 -1
  308. package/dist/__tests__/realtime-session-channels.test.js +0 -252
  309. package/dist/__tests__/realtime-session-channels.test.js.map +0 -1
  310. package/dist/__tests__/realtime-session-client-tools.test.d.ts +0 -2
  311. package/dist/__tests__/realtime-session-client-tools.test.d.ts.map +0 -1
  312. package/dist/__tests__/realtime-session-client-tools.test.js +0 -103
  313. package/dist/__tests__/realtime-session-client-tools.test.js.map +0 -1
  314. package/dist/__tests__/realtime-session-minimized.test.d.ts +0 -2
  315. package/dist/__tests__/realtime-session-minimized.test.d.ts.map +0 -1
  316. package/dist/__tests__/realtime-session-minimized.test.js +0 -32
  317. package/dist/__tests__/realtime-session-minimized.test.js.map +0 -1
  318. package/dist/__tests__/realtime-session-mint.test.d.ts +0 -2
  319. package/dist/__tests__/realtime-session-mint.test.d.ts.map +0 -1
  320. package/dist/__tests__/realtime-session-mint.test.js +0 -69
  321. package/dist/__tests__/realtime-session-mint.test.js.map +0 -1
  322. package/dist/__tests__/realtime-session-policy.test.d.ts +0 -2
  323. package/dist/__tests__/realtime-session-policy.test.d.ts.map +0 -1
  324. package/dist/__tests__/realtime-session-policy.test.js +0 -303
  325. package/dist/__tests__/realtime-session-policy.test.js.map +0 -1
  326. package/dist/__tests__/realtime-session-review.service.test.d.ts +0 -2
  327. package/dist/__tests__/realtime-session-review.service.test.d.ts.map +0 -1
  328. package/dist/__tests__/realtime-session-review.service.test.js +0 -743
  329. package/dist/__tests__/realtime-session-review.service.test.js.map +0 -1
  330. package/dist/__tests__/realtime-session-state.test.d.ts +0 -2
  331. package/dist/__tests__/realtime-session-state.test.d.ts.map +0 -1
  332. package/dist/__tests__/realtime-session-state.test.js +0 -83
  333. package/dist/__tests__/realtime-session-state.test.js.map +0 -1
  334. package/dist/__tests__/realtime-session-timeline-card.test.d.ts +0 -2
  335. package/dist/__tests__/realtime-session-timeline-card.test.d.ts.map +0 -1
  336. package/dist/__tests__/realtime-session-timeline-card.test.js +0 -106
  337. package/dist/__tests__/realtime-session-timeline-card.test.js.map +0 -1
  338. package/dist/__tests__/realtime-session-timeline.test.d.ts +0 -2
  339. package/dist/__tests__/realtime-session-timeline.test.d.ts.map +0 -1
  340. package/dist/__tests__/realtime-session-timeline.test.js +0 -142
  341. package/dist/__tests__/realtime-session-timeline.test.js.map +0 -1
  342. package/dist/__tests__/realtime-sessions-adapter.test.d.ts +0 -19
  343. package/dist/__tests__/realtime-sessions-adapter.test.d.ts.map +0 -1
  344. package/dist/__tests__/realtime-sessions-adapter.test.js +0 -188
  345. package/dist/__tests__/realtime-sessions-adapter.test.js.map +0 -1
  346. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts +0 -2
  347. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts.map +0 -1
  348. package/dist/__tests__/realtime-surface-panel-prefs.test.js +0 -100
  349. package/dist/__tests__/realtime-surface-panel-prefs.test.js.map +0 -1
  350. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts +0 -2
  351. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts.map +0 -1
  352. package/dist/__tests__/realtime-surface-tabs-model.test.js +0 -193
  353. package/dist/__tests__/realtime-surface-tabs-model.test.js.map +0 -1
  354. package/dist/__tests__/remote-browser-audio-player.test.d.ts +0 -2
  355. package/dist/__tests__/remote-browser-audio-player.test.d.ts.map +0 -1
  356. package/dist/__tests__/remote-browser-audio-player.test.js +0 -137
  357. package/dist/__tests__/remote-browser-audio-player.test.js.map +0 -1
  358. package/dist/__tests__/remote-browser-channel.test.d.ts +0 -2
  359. package/dist/__tests__/remote-browser-channel.test.d.ts.map +0 -1
  360. package/dist/__tests__/remote-browser-channel.test.js +0 -585
  361. package/dist/__tests__/remote-browser-channel.test.js.map +0 -1
  362. package/dist/__tests__/search-service.test.d.ts +0 -2
  363. package/dist/__tests__/search-service.test.d.ts.map +0 -1
  364. package/dist/__tests__/search-service.test.js +0 -114
  365. package/dist/__tests__/search-service.test.js.map +0 -1
  366. package/dist/__tests__/slot-defaults.test.d.ts +0 -24
  367. package/dist/__tests__/slot-defaults.test.d.ts.map +0 -1
  368. package/dist/__tests__/slot-defaults.test.js +0 -63
  369. package/dist/__tests__/slot-defaults.test.js.map +0 -1
  370. package/dist/__tests__/toast-service.test.d.ts +0 -2
  371. package/dist/__tests__/toast-service.test.d.ts.map +0 -1
  372. package/dist/__tests__/toast-service.test.js +0 -143
  373. package/dist/__tests__/toast-service.test.js.map +0 -1
  374. package/dist/__tests__/user-authorization.test.d.ts +0 -2
  375. package/dist/__tests__/user-authorization.test.d.ts.map +0 -1
  376. package/dist/__tests__/user-authorization.test.js +0 -97
  377. package/dist/__tests__/user-authorization.test.js.map +0 -1
  378. package/dist/__tests__/voice-session-narration.test.d.ts +0 -2
  379. package/dist/__tests__/voice-session-narration.test.d.ts.map +0 -1
  380. package/dist/__tests__/voice-session-narration.test.js +0 -609
  381. package/dist/__tests__/voice-session-narration.test.js.map +0 -1
  382. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts +0 -2
  383. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts.map +0 -1
  384. package/dist/__tests__/whiteboard-artifact-viewer.test.js +0 -101
  385. package/dist/__tests__/whiteboard-artifact-viewer.test.js.map +0 -1
  386. package/dist/__tests__/whiteboard-channel.test.d.ts +0 -2
  387. package/dist/__tests__/whiteboard-channel.test.d.ts.map +0 -1
  388. package/dist/__tests__/whiteboard-channel.test.js +0 -260
  389. package/dist/__tests__/whiteboard-channel.test.js.map +0 -1
  390. package/dist/__tests__/whiteboard-restore-state.test.d.ts +0 -2
  391. package/dist/__tests__/whiteboard-restore-state.test.d.ts.map +0 -1
  392. package/dist/__tests__/whiteboard-restore-state.test.js +0 -108
  393. package/dist/__tests__/whiteboard-restore-state.test.js.map +0 -1
  394. package/dist/lib/components/mention/mention-dropdown.component.d.ts +0 -53
  395. package/dist/lib/components/mention/mention-dropdown.component.d.ts.map +0 -1
  396. package/dist/lib/components/mention/mention-dropdown.component.js +0 -276
  397. package/dist/lib/components/mention/mention-dropdown.component.js.map +0 -1
  398. package/dist/lib/components/mention/mention-editor.component.d.ts +0 -256
  399. package/dist/lib/components/mention/mention-editor.component.d.ts.map +0 -1
  400. package/dist/lib/components/mention/mention-editor.component.js +0 -1233
  401. package/dist/lib/components/mention/mention-editor.component.js.map +0 -1
  402. package/dist/lib/components/message/message-input-box.component.d.ts +0 -137
  403. package/dist/lib/components/message/message-input-box.component.d.ts.map +0 -1
  404. package/dist/lib/components/message/message-input-box.component.js +0 -321
  405. package/dist/lib/components/message/message-input-box.component.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-attachment.service.js","sourceRoot":"","sources":["../../../src/lib/services/conversation-attachment.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { RunView, Metadata, UserInfo, IMetadataProvider } from '@memberjunction/core';\nimport {\n MJConversationDetailAttachmentEntity,\n MJConversationDetailArtifactEntity,\n MJArtifactVersionEntity,\n MJArtifactEntity,\n MJAIModalityEntity,\n ArtifactMetadataEngine\n} from '@memberjunction/core-entities';\nimport {\n ConversationUtility,\n AttachmentContent,\n AttachmentType\n} from '@memberjunction/ai-core-plus';\nimport { MessageAttachment } from '../components/message/message-item.component';\nimport { PendingAttachment } from '../components/mention/mention-editor.component';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Service for managing conversation attachments.\n * Handles loading, saving, and converting attachments between different formats.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ConversationAttachmentService {\n private _provider: IMetadataProvider | null = null;\n\n constructor() {}\n\n /**\n * Set the metadata provider this service should use. When unset, falls back to Metadata.Provider.\n */\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n }\n\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n\n /**\n * Load all attachments for a list of conversation detail IDs.\n * Returns a map of ConversationDetailID -> MessageAttachment[]\n */\n async loadAttachmentsForMessages(\n conversationDetailIds: string[],\n contextUser?: UserInfo\n ): Promise<Map<string, MessageAttachment[]>> {\n const result = new Map<string, MessageAttachment[]>();\n\n if (!conversationDetailIds || conversationDetailIds.length === 0) {\n return result;\n }\n\n try {\n const rv = RunView.FromMetadataProvider(this.Provider);\n const idList = conversationDetailIds.map(id => `'${id}'`).join(',');\n\n // Load input artifacts (ConversationDetailArtifact with Direction='Input').\n // Since the backfill migration (V202605271400__Backfill_Attachment_Artifacts)\n // converted all legacy ConversationDetailAttachment rows to artifact pairs,\n // the artifact junction is the single source of truth — no separate attachment\n // query needed.\n const artifactLinksResult = await rv.RunView<MJConversationDetailArtifactEntity>({\n EntityName: 'MJ: Conversation Detail Artifacts',\n ExtraFilter: `ConversationDetailID IN (${idList}) AND Direction = 'Input'`,\n ResultType: 'entity_object'\n }, contextUser);\n\n if (artifactLinksResult.Success && artifactLinksResult.Results && artifactLinksResult.Results.length > 0) {\n // Load the referenced artifact versions AND their parent artifacts in parallel\n // so we can resolve the semantic artifact-type name for the tile badge.\n const versionIds = artifactLinksResult.Results.map(l => `'${l.ArtifactVersionID}'`).join(',');\n const versionsResult = await rv.RunView<MJArtifactVersionEntity>({\n EntityName: 'MJ: Artifact Versions',\n ExtraFilter: `ID IN (${versionIds})`,\n ResultType: 'entity_object'\n }, contextUser);\n\n if (versionsResult.Success && versionsResult.Results) {\n const versionMap = new Map<string, MJArtifactVersionEntity>();\n for (const v of versionsResult.Results) {\n versionMap.set(v.ID, v);\n }\n\n // Bulk-load parent artifacts to get TypeID, then resolve type names via cached engine.\n const artifactIds = Array.from(new Set(versionsResult.Results.map(v => v.ArtifactID).filter(Boolean)));\n const artifactMap = new Map<string, MJArtifactEntity>();\n if (artifactIds.length > 0) {\n const artifactIdList = artifactIds.map(id => `'${id}'`).join(',');\n const artifactsResult = await rv.RunView<MJArtifactEntity>({\n EntityName: 'MJ: Artifacts',\n ExtraFilter: `ID IN (${artifactIdList})`,\n ResultType: 'entity_object'\n }, contextUser);\n if (artifactsResult.Success && artifactsResult.Results) {\n for (const a of artifactsResult.Results) {\n artifactMap.set(a.ID, a);\n }\n }\n // Ensure the artifact-type cache is populated so FindArtifactTypeByID resolves.\n await ArtifactMetadataEngine.Instance.Config(false, contextUser);\n }\n\n for (const link of artifactLinksResult.Results) {\n const version = versionMap.get(link.ArtifactVersionID);\n if (version) {\n const parentArtifact = artifactMap.get(version.ArtifactID);\n const artifactType = parentArtifact\n ? ArtifactMetadataEngine.Instance.FindArtifactTypeByID(parentArtifact.TypeID)\n : undefined;\n const detailId = link.ConversationDetailID;\n if (!result.has(detailId)) {\n result.set(detailId, []);\n }\n result.get(detailId)!.push({\n id: link.ID,\n type: version.ContentMode === 'File' ? this.getMimeAttachmentType(version.MimeType || '') : 'Document',\n mimeType: version.MimeType || 'text/plain',\n fileName: version.FileName || version.Name || 'Artifact',\n sizeBytes: version.ContentSizeBytes || 0,\n source: 'artifact',\n artifactId: version.ArtifactID || undefined,\n artifactVersionId: version.ID,\n artifactTypeName: artifactType?.Name || undefined\n } as MessageAttachment);\n }\n }\n }\n }\n } catch (error) {\n console.error('Error loading attachments:', error);\n }\n\n return result;\n }\n\n /**\n * Load attachments for a single message\n */\n async loadAttachmentsForMessage(\n conversationDetailId: string,\n contextUser?: UserInfo\n ): Promise<MessageAttachment[]> {\n const map = await this.loadAttachmentsForMessages([conversationDetailId], contextUser);\n return map.get(conversationDetailId) || [];\n }\n\n /**\n * Save pending attachments to the database.\n * Returns the saved attachment entities.\n *\n * @param conversationDetailId - ID of the conversation detail to attach to\n * @param pendingAttachments - Array of pending attachments from the mention editor\n * @param contextUser - User context for the operation\n */\n async saveAttachments(\n conversationDetailId: string,\n pendingAttachments: PendingAttachment[],\n contextUser?: UserInfo\n ): Promise<MJConversationDetailAttachmentEntity[]> {\n const savedAttachments: MJConversationDetailAttachmentEntity[] = [];\n const rejectionMessages: string[] = [];\n const md = this.Provider;\n\n for (let i = 0; i < pendingAttachments.length; i++) {\n const pending = pendingAttachments[i];\n\n try {\n const attachment = await md.GetEntityObject<MJConversationDetailAttachmentEntity>(\n 'MJ: Conversation Detail Attachments',\n contextUser\n );\n\n // Determine attachment type from MIME type\n const attachmentType = ConversationUtility.GetAttachmentTypeFromMime(pending.mimeType);\n\n attachment.ConversationDetailID = conversationDetailId;\n attachment.ModalityID = this.getModalityIdForType(attachmentType);\n attachment.MimeType = pending.mimeType;\n attachment.FileName = pending.fileName;\n attachment.FileSizeBytes = pending.sizeBytes;\n attachment.Width = pending.width ?? null;\n attachment.Height = pending.height ?? null;\n attachment.DurationSeconds = null; // PendingAttachment doesn't have duration\n attachment.DisplayOrder = i;\n attachment.ThumbnailBase64 = pending.thumbnailUrl ?? null;\n\n // For artifact references, create a ConversationDetailArtifact with Direction='Input'\n // instead of a ConversationDetailAttachment\n if (pending.source === 'artifact' && pending.artifactVersionId) {\n const artifactLink = await md.GetEntityObject<MJConversationDetailArtifactEntity>(\n 'MJ: Conversation Detail Artifacts',\n contextUser\n );\n artifactLink.ConversationDetailID = conversationDetailId;\n artifactLink.ArtifactVersionID = pending.artifactVersionId;\n artifactLink.Direction = 'Input';\n const artifactSaved = await artifactLink.Save();\n if (!artifactSaved) {\n console.error('Failed to save artifact input link:', artifactLink.LatestResult);\n }\n continue; // Skip creating a ConversationDetailAttachment for artifacts\n }\n\n // Store inline data for uploaded files\n if (pending.dataUrl) {\n const base64Data = this.extractBase64FromDataUrl(pending.dataUrl);\n attachment.InlineData = base64Data;\n }\n\n const saved = await attachment.Save();\n if (saved) {\n savedAttachments.push(attachment);\n } else {\n const message = attachment.LatestResult?.CompleteMessage\n ?? `Attachment \"${pending.fileName}\" was rejected by the server.`;\n console.error('Failed to save attachment:', attachment.LatestResult);\n rejectionMessages.push(message);\n }\n } catch (error) {\n console.error('Error saving attachment:', error);\n rejectionMessages.push(\n `Attachment \"${pending.fileName}\" failed to upload: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n // Surface server-side rejections (e.g. unregistered MIME types) to the\n // caller — throwing here lets the message-input toast pipeline display\n // the actual server message rather than silently dropping the file.\n if (rejectionMessages.length > 0) {\n throw new Error(rejectionMessages.join('\\n'));\n }\n\n return savedAttachments;\n }\n\n /**\n * Create attachment reference tokens for message text.\n * These tokens are stored in the Message field to reference attachments.\n */\n createAttachmentReferences(attachments: MJConversationDetailAttachmentEntity[]): string {\n return attachments\n .map(att => {\n const content: AttachmentContent = {\n _mode: 'attachment',\n id: att.ID,\n type: this.getAttachmentTypeFromModality(att.ModalityID),\n mimeType: att.MimeType,\n fileName: att.FileName ?? undefined,\n sizeBytes: att.FileSizeBytes,\n width: att.Width ?? undefined,\n height: att.Height ?? undefined,\n durationSeconds: att.DurationSeconds ?? undefined,\n thumbnailBase64: att.ThumbnailBase64 ?? undefined\n };\n return ConversationUtility.CreateAttachmentReference(content);\n })\n .join(' ');\n }\n\n /**\n * Convert a database entity to a MessageAttachment for display\n */\n private convertToMessageAttachment(entity: MJConversationDetailAttachmentEntity): MessageAttachment {\n // Determine content URL\n let contentUrl: string | undefined;\n let thumbnailUrl: string | undefined;\n\n if (entity.InlineData) {\n // Create data URL from inline data\n contentUrl = `data:${entity.MimeType};base64,${entity.InlineData}`;\n } else if (entity.FileID) {\n // TODO: Integrate with MJStorage to get pre-authenticated URL\n contentUrl = undefined; // Will need to be loaded separately\n }\n\n // Use thumbnail if available\n if (entity.ThumbnailBase64) {\n thumbnailUrl = entity.ThumbnailBase64.startsWith('data:')\n ? entity.ThumbnailBase64\n : `data:image/jpeg;base64,${entity.ThumbnailBase64}`;\n }\n\n return {\n id: entity.ID,\n type: this.getAttachmentTypeFromModality(entity.ModalityID),\n mimeType: entity.MimeType,\n fileName: entity.FileName,\n sizeBytes: entity.FileSizeBytes,\n width: entity.Width ?? undefined,\n height: entity.Height ?? undefined,\n thumbnailUrl: thumbnailUrl,\n contentUrl: contentUrl\n };\n }\n\n /**\n * Get the AttachmentType from a modality ID\n */\n private getAttachmentTypeFromModality(modalityId: string): AttachmentType {\n const modality = AIEngineBase.Instance.Modalities.find(m => UUIDsEqual(m.ID, modalityId))\n\n const name = modality?.Name?.toLowerCase() || '';\n\n if (name === 'image') return 'Image';\n if (name === 'video') return 'Video';\n if (name === 'audio') return 'Audio';\n\n return 'Document';\n }\n\n /**\n * Get the AttachmentType from a MIME type string\n */\n private getMimeAttachmentType(mimeType: string): 'Image' | 'Video' | 'Audio' | 'Document' {\n if (mimeType.startsWith('image/')) return 'Image';\n if (mimeType.startsWith('video/')) return 'Video';\n if (mimeType.startsWith('audio/')) return 'Audio';\n return 'Document';\n }\n\n /**\n * Get the modality ID for an attachment type\n */\n private getModalityIdForType(type: AttachmentType): string {\n // Map AttachmentType to modality name\n // AttachmentType is 'Image' | 'Video' | 'Audio' | 'Document'\n // Modality names are 'Image', 'Audio', 'Video', 'File'\n let modalityName = type.toLowerCase().trim();\n if (modalityName === 'document') {\n modalityName = 'file';\n }\n\n const modality = AIEngineBase.Instance.Modalities.find(m => m.Name?.trim().toLowerCase() === modalityName);\n if (modality) {\n return modality.ID;\n }\n\n // Fallback to 'file' modality if specific type not found\n // recursive call, so long as the current modality isn't file as that\n // would cause infinite recursion/stack overflow\n if (modalityName !== 'file') {\n return this.getModalityIdForType('Document');\n }\n else {\n return '';\n }\n }\n \n /**\n * Extract base64 data from a data URL\n */\n private extractBase64FromDataUrl(dataUrl: string): string {\n const matches = dataUrl.match(/^data:[^;]+;base64,(.+)$/);\n return matches ? matches[1] : dataUrl;\n }\n\n /**\n * Create a thumbnail from an image file.\n * Returns a base64 data URL of the thumbnail.\n */\n async createThumbnail(\n file: File,\n maxSize: number = 200\n ): Promise<string | null> {\n return new Promise((resolve) => {\n if (!file.type.startsWith('image/')) {\n resolve(null);\n return;\n }\n\n const reader = new FileReader();\n reader.onload = (e) => {\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement('canvas');\n let width = img.width;\n let height = img.height;\n\n // Scale down to maxSize\n if (width > height) {\n if (width > maxSize) {\n height = Math.round((height * maxSize) / width);\n width = maxSize;\n }\n } else {\n if (height > maxSize) {\n width = Math.round((width * maxSize) / height);\n height = maxSize;\n }\n }\n\n canvas.width = width;\n canvas.height = height;\n\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.drawImage(img, 0, 0, width, height);\n resolve(canvas.toDataURL('image/jpeg', 0.7));\n } else {\n resolve(null);\n }\n };\n img.onerror = () => resolve(null);\n img.src = e.target?.result as string;\n };\n reader.onerror = () => resolve(null);\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Get image dimensions from a file\n */\n async getImageDimensions(file: File): Promise<{ width: number; height: number } | null> {\n return new Promise((resolve) => {\n if (!file.type.startsWith('image/')) {\n resolve(null);\n return;\n }\n\n const reader = new FileReader();\n reader.onload = (e) => {\n const img = new Image();\n img.onload = () => {\n resolve({ width: img.width, height: img.height });\n };\n img.onerror = () => resolve(null);\n img.src = e.target?.result as string;\n };\n reader.onerror = () => resolve(null);\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Process a file and create a PendingAttachment.\n * This creates the data structure needed for the mention editor component.\n */\n async processFile(file: File): Promise<PendingAttachment> {\n // Read file data URL\n const dataUrl = await this.fileToDataUrl(file);\n\n const pending: PendingAttachment = {\n id: this.generateTempId(),\n file: file,\n dataUrl: dataUrl,\n mimeType: file.type,\n fileName: file.name,\n sizeBytes: file.size\n };\n\n // Get image dimensions and create thumbnail\n const type = ConversationUtility.GetAttachmentTypeFromMime(file.type);\n if (type === 'Image') {\n const dimensions = await this.getImageDimensions(file);\n if (dimensions) {\n pending.width = dimensions.width;\n pending.height = dimensions.height;\n }\n\n const thumbnail = await this.createThumbnail(file);\n if (thumbnail) {\n pending.thumbnailUrl = thumbnail;\n }\n }\n\n return pending;\n }\n\n /**\n * Convert a file to a data URL\n */\n private fileToDataUrl(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Generate a temporary ID for pending attachments\n */\n private generateTempId(): string {\n return `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n}\n"]}
1
+ {"version":3,"file":"conversation-attachment.service.js","sourceRoot":"","sources":["../../../src/lib/services/conversation-attachment.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { RunView, Metadata, UserInfo, IMetadataProvider } from '@memberjunction/core';\nimport {\n MJConversationDetailAttachmentEntity,\n MJConversationDetailArtifactEntity,\n MJArtifactVersionEntity,\n MJArtifactEntity,\n MJAIModalityEntity,\n ArtifactMetadataEngine\n} from '@memberjunction/core-entities';\nimport {\n ConversationUtility,\n AttachmentContent,\n AttachmentType\n} from '@memberjunction/ai-core-plus';\nimport { MessageAttachment } from '../components/message/message-item.component';\nimport { PendingAttachment } from '@memberjunction/ng-composer';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Service for managing conversation attachments.\n * Handles loading, saving, and converting attachments between different formats.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ConversationAttachmentService {\n private _provider: IMetadataProvider | null = null;\n\n constructor() {}\n\n /**\n * Set the metadata provider this service should use. When unset, falls back to Metadata.Provider.\n */\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n }\n\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n\n /**\n * Load all attachments for a list of conversation detail IDs.\n * Returns a map of ConversationDetailID -> MessageAttachment[]\n */\n async loadAttachmentsForMessages(\n conversationDetailIds: string[],\n contextUser?: UserInfo\n ): Promise<Map<string, MessageAttachment[]>> {\n const result = new Map<string, MessageAttachment[]>();\n\n if (!conversationDetailIds || conversationDetailIds.length === 0) {\n return result;\n }\n\n try {\n const rv = RunView.FromMetadataProvider(this.Provider);\n const idList = conversationDetailIds.map(id => `'${id}'`).join(',');\n\n // Load input artifacts (ConversationDetailArtifact with Direction='Input').\n // Since the backfill migration (V202605271400__Backfill_Attachment_Artifacts)\n // converted all legacy ConversationDetailAttachment rows to artifact pairs,\n // the artifact junction is the single source of truth — no separate attachment\n // query needed.\n const artifactLinksResult = await rv.RunView<MJConversationDetailArtifactEntity>({\n EntityName: 'MJ: Conversation Detail Artifacts',\n ExtraFilter: `ConversationDetailID IN (${idList}) AND Direction = 'Input'`,\n ResultType: 'entity_object'\n }, contextUser);\n\n if (artifactLinksResult.Success && artifactLinksResult.Results && artifactLinksResult.Results.length > 0) {\n // Load the referenced artifact versions AND their parent artifacts in parallel\n // so we can resolve the semantic artifact-type name for the tile badge.\n const versionIds = artifactLinksResult.Results.map(l => `'${l.ArtifactVersionID}'`).join(',');\n const versionsResult = await rv.RunView<MJArtifactVersionEntity>({\n EntityName: 'MJ: Artifact Versions',\n ExtraFilter: `ID IN (${versionIds})`,\n ResultType: 'entity_object'\n }, contextUser);\n\n if (versionsResult.Success && versionsResult.Results) {\n const versionMap = new Map<string, MJArtifactVersionEntity>();\n for (const v of versionsResult.Results) {\n versionMap.set(v.ID, v);\n }\n\n // Bulk-load parent artifacts to get TypeID, then resolve type names via cached engine.\n const artifactIds = Array.from(new Set(versionsResult.Results.map(v => v.ArtifactID).filter(Boolean)));\n const artifactMap = new Map<string, MJArtifactEntity>();\n if (artifactIds.length > 0) {\n const artifactIdList = artifactIds.map(id => `'${id}'`).join(',');\n const artifactsResult = await rv.RunView<MJArtifactEntity>({\n EntityName: 'MJ: Artifacts',\n ExtraFilter: `ID IN (${artifactIdList})`,\n ResultType: 'entity_object'\n }, contextUser);\n if (artifactsResult.Success && artifactsResult.Results) {\n for (const a of artifactsResult.Results) {\n artifactMap.set(a.ID, a);\n }\n }\n // Ensure the artifact-type cache is populated so FindArtifactTypeByID resolves.\n await ArtifactMetadataEngine.Instance.Config(false, contextUser);\n }\n\n for (const link of artifactLinksResult.Results) {\n const version = versionMap.get(link.ArtifactVersionID);\n if (version) {\n const parentArtifact = artifactMap.get(version.ArtifactID);\n const artifactType = parentArtifact\n ? ArtifactMetadataEngine.Instance.FindArtifactTypeByID(parentArtifact.TypeID)\n : undefined;\n const detailId = link.ConversationDetailID;\n if (!result.has(detailId)) {\n result.set(detailId, []);\n }\n result.get(detailId)!.push({\n id: link.ID,\n type: version.ContentMode === 'File' ? this.getMimeAttachmentType(version.MimeType || '') : 'Document',\n mimeType: version.MimeType || 'text/plain',\n fileName: version.FileName || version.Name || 'Artifact',\n sizeBytes: version.ContentSizeBytes || 0,\n source: 'artifact',\n artifactId: version.ArtifactID || undefined,\n artifactVersionId: version.ID,\n artifactTypeName: artifactType?.Name || undefined\n } as MessageAttachment);\n }\n }\n }\n }\n } catch (error) {\n console.error('Error loading attachments:', error);\n }\n\n return result;\n }\n\n /**\n * Load attachments for a single message\n */\n async loadAttachmentsForMessage(\n conversationDetailId: string,\n contextUser?: UserInfo\n ): Promise<MessageAttachment[]> {\n const map = await this.loadAttachmentsForMessages([conversationDetailId], contextUser);\n return map.get(conversationDetailId) || [];\n }\n\n /**\n * Save pending attachments to the database.\n * Returns the saved attachment entities.\n *\n * @param conversationDetailId - ID of the conversation detail to attach to\n * @param pendingAttachments - Array of pending attachments from the mention editor\n * @param contextUser - User context for the operation\n */\n async saveAttachments(\n conversationDetailId: string,\n pendingAttachments: PendingAttachment[],\n contextUser?: UserInfo\n ): Promise<MJConversationDetailAttachmentEntity[]> {\n const savedAttachments: MJConversationDetailAttachmentEntity[] = [];\n const rejectionMessages: string[] = [];\n const md = this.Provider;\n\n for (let i = 0; i < pendingAttachments.length; i++) {\n const pending = pendingAttachments[i];\n\n try {\n const attachment = await md.GetEntityObject<MJConversationDetailAttachmentEntity>(\n 'MJ: Conversation Detail Attachments',\n contextUser\n );\n\n // Determine attachment type from MIME type\n const attachmentType = ConversationUtility.GetAttachmentTypeFromMime(pending.mimeType);\n\n attachment.ConversationDetailID = conversationDetailId;\n attachment.ModalityID = this.getModalityIdForType(attachmentType);\n attachment.MimeType = pending.mimeType;\n attachment.FileName = pending.fileName;\n attachment.FileSizeBytes = pending.sizeBytes;\n attachment.Width = pending.width ?? null;\n attachment.Height = pending.height ?? null;\n attachment.DurationSeconds = null; // PendingAttachment doesn't have duration\n attachment.DisplayOrder = i;\n attachment.ThumbnailBase64 = pending.thumbnailUrl ?? null;\n\n // For artifact references, create a ConversationDetailArtifact with Direction='Input'\n // instead of a ConversationDetailAttachment\n if (pending.source === 'artifact' && pending.artifactVersionId) {\n const artifactLink = await md.GetEntityObject<MJConversationDetailArtifactEntity>(\n 'MJ: Conversation Detail Artifacts',\n contextUser\n );\n artifactLink.ConversationDetailID = conversationDetailId;\n artifactLink.ArtifactVersionID = pending.artifactVersionId;\n artifactLink.Direction = 'Input';\n const artifactSaved = await artifactLink.Save();\n if (!artifactSaved) {\n console.error('Failed to save artifact input link:', artifactLink.LatestResult);\n }\n continue; // Skip creating a ConversationDetailAttachment for artifacts\n }\n\n // Store inline data for uploaded files\n if (pending.dataUrl) {\n const base64Data = this.extractBase64FromDataUrl(pending.dataUrl);\n attachment.InlineData = base64Data;\n }\n\n const saved = await attachment.Save();\n if (saved) {\n savedAttachments.push(attachment);\n } else {\n const message = attachment.LatestResult?.CompleteMessage\n ?? `Attachment \"${pending.fileName}\" was rejected by the server.`;\n console.error('Failed to save attachment:', attachment.LatestResult);\n rejectionMessages.push(message);\n }\n } catch (error) {\n console.error('Error saving attachment:', error);\n rejectionMessages.push(\n `Attachment \"${pending.fileName}\" failed to upload: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n // Surface server-side rejections (e.g. unregistered MIME types) to the\n // caller — throwing here lets the message-input toast pipeline display\n // the actual server message rather than silently dropping the file.\n if (rejectionMessages.length > 0) {\n throw new Error(rejectionMessages.join('\\n'));\n }\n\n return savedAttachments;\n }\n\n /**\n * Create attachment reference tokens for message text.\n * These tokens are stored in the Message field to reference attachments.\n */\n createAttachmentReferences(attachments: MJConversationDetailAttachmentEntity[]): string {\n return attachments\n .map(att => {\n const content: AttachmentContent = {\n _mode: 'attachment',\n id: att.ID,\n type: this.getAttachmentTypeFromModality(att.ModalityID),\n mimeType: att.MimeType,\n fileName: att.FileName ?? undefined,\n sizeBytes: att.FileSizeBytes,\n width: att.Width ?? undefined,\n height: att.Height ?? undefined,\n durationSeconds: att.DurationSeconds ?? undefined,\n thumbnailBase64: att.ThumbnailBase64 ?? undefined\n };\n return ConversationUtility.CreateAttachmentReference(content);\n })\n .join(' ');\n }\n\n /**\n * Convert a database entity to a MessageAttachment for display\n */\n private convertToMessageAttachment(entity: MJConversationDetailAttachmentEntity): MessageAttachment {\n // Determine content URL\n let contentUrl: string | undefined;\n let thumbnailUrl: string | undefined;\n\n if (entity.InlineData) {\n // Create data URL from inline data\n contentUrl = `data:${entity.MimeType};base64,${entity.InlineData}`;\n } else if (entity.FileID) {\n // TODO: Integrate with MJStorage to get pre-authenticated URL\n contentUrl = undefined; // Will need to be loaded separately\n }\n\n // Use thumbnail if available\n if (entity.ThumbnailBase64) {\n thumbnailUrl = entity.ThumbnailBase64.startsWith('data:')\n ? entity.ThumbnailBase64\n : `data:image/jpeg;base64,${entity.ThumbnailBase64}`;\n }\n\n return {\n id: entity.ID,\n type: this.getAttachmentTypeFromModality(entity.ModalityID),\n mimeType: entity.MimeType,\n fileName: entity.FileName,\n sizeBytes: entity.FileSizeBytes,\n width: entity.Width ?? undefined,\n height: entity.Height ?? undefined,\n thumbnailUrl: thumbnailUrl,\n contentUrl: contentUrl\n };\n }\n\n /**\n * Get the AttachmentType from a modality ID\n */\n private getAttachmentTypeFromModality(modalityId: string): AttachmentType {\n const modality = AIEngineBase.Instance.Modalities.find(m => UUIDsEqual(m.ID, modalityId))\n\n const name = modality?.Name?.toLowerCase() || '';\n\n if (name === 'image') return 'Image';\n if (name === 'video') return 'Video';\n if (name === 'audio') return 'Audio';\n\n return 'Document';\n }\n\n /**\n * Get the AttachmentType from a MIME type string\n */\n private getMimeAttachmentType(mimeType: string): 'Image' | 'Video' | 'Audio' | 'Document' {\n if (mimeType.startsWith('image/')) return 'Image';\n if (mimeType.startsWith('video/')) return 'Video';\n if (mimeType.startsWith('audio/')) return 'Audio';\n return 'Document';\n }\n\n /**\n * Get the modality ID for an attachment type\n */\n private getModalityIdForType(type: AttachmentType): string {\n // Map AttachmentType to modality name\n // AttachmentType is 'Image' | 'Video' | 'Audio' | 'Document'\n // Modality names are 'Image', 'Audio', 'Video', 'File'\n let modalityName = type.toLowerCase().trim();\n if (modalityName === 'document') {\n modalityName = 'file';\n }\n\n const modality = AIEngineBase.Instance.Modalities.find(m => m.Name?.trim().toLowerCase() === modalityName);\n if (modality) {\n return modality.ID;\n }\n\n // Fallback to 'file' modality if specific type not found\n // recursive call, so long as the current modality isn't file as that\n // would cause infinite recursion/stack overflow\n if (modalityName !== 'file') {\n return this.getModalityIdForType('Document');\n }\n else {\n return '';\n }\n }\n \n /**\n * Extract base64 data from a data URL\n */\n private extractBase64FromDataUrl(dataUrl: string): string {\n const matches = dataUrl.match(/^data:[^;]+;base64,(.+)$/);\n return matches ? matches[1] : dataUrl;\n }\n\n /**\n * Create a thumbnail from an image file.\n * Returns a base64 data URL of the thumbnail.\n */\n async createThumbnail(\n file: File,\n maxSize: number = 200\n ): Promise<string | null> {\n return new Promise((resolve) => {\n if (!file.type.startsWith('image/')) {\n resolve(null);\n return;\n }\n\n const reader = new FileReader();\n reader.onload = (e) => {\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement('canvas');\n let width = img.width;\n let height = img.height;\n\n // Scale down to maxSize\n if (width > height) {\n if (width > maxSize) {\n height = Math.round((height * maxSize) / width);\n width = maxSize;\n }\n } else {\n if (height > maxSize) {\n width = Math.round((width * maxSize) / height);\n height = maxSize;\n }\n }\n\n canvas.width = width;\n canvas.height = height;\n\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.drawImage(img, 0, 0, width, height);\n resolve(canvas.toDataURL('image/jpeg', 0.7));\n } else {\n resolve(null);\n }\n };\n img.onerror = () => resolve(null);\n img.src = e.target?.result as string;\n };\n reader.onerror = () => resolve(null);\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Get image dimensions from a file\n */\n async getImageDimensions(file: File): Promise<{ width: number; height: number } | null> {\n return new Promise((resolve) => {\n if (!file.type.startsWith('image/')) {\n resolve(null);\n return;\n }\n\n const reader = new FileReader();\n reader.onload = (e) => {\n const img = new Image();\n img.onload = () => {\n resolve({ width: img.width, height: img.height });\n };\n img.onerror = () => resolve(null);\n img.src = e.target?.result as string;\n };\n reader.onerror = () => resolve(null);\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Process a file and create a PendingAttachment.\n * This creates the data structure needed for the mention editor component.\n */\n async processFile(file: File): Promise<PendingAttachment> {\n // Read file data URL\n const dataUrl = await this.fileToDataUrl(file);\n\n const pending: PendingAttachment = {\n id: this.generateTempId(),\n file: file,\n dataUrl: dataUrl,\n mimeType: file.type,\n fileName: file.name,\n sizeBytes: file.size\n };\n\n // Get image dimensions and create thumbnail\n const type = ConversationUtility.GetAttachmentTypeFromMime(file.type);\n if (type === 'Image') {\n const dimensions = await this.getImageDimensions(file);\n if (dimensions) {\n pending.width = dimensions.width;\n pending.height = dimensions.height;\n }\n\n const thumbnail = await this.createThumbnail(file);\n if (thumbnail) {\n pending.thumbnailUrl = thumbnail;\n }\n }\n\n return pending;\n }\n\n /**\n * Convert a file to a data URL\n */\n private fileToDataUrl(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Generate a temporary ID for pending attachments\n */\n private generateTempId(): string {\n return `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n}\n"]}
@@ -1,32 +1,37 @@
1
1
  import { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';
2
2
  import { UserInfo, EntityInfo, QueryInfo, IMetadataProvider } from '@memberjunction/core';
3
- import * as i0 from "@angular/core";
3
+ import { BaseSingleton } from '@memberjunction/global';
4
+ import { MentionSuggestion } from '@memberjunction/ng-composer';
4
5
  /**
5
- * Item in the autocomplete dropdown
6
+ * Shared engine behind the conversations composer plugins (the agent-mentions /
7
+ * record-mentions / skill-commands `ComposerTriggerProvider`s) and the mention-parsing
8
+ * consumers (message routing, saved-message badge rendering). Loads the
9
+ * permission-filtered agent / user / entity / query / skill caches once per session and
10
+ * serves ranked `MentionSuggestion` lists per trigger char.
11
+ *
12
+ * NOT an Angular DI service — it's a `BaseSingleton` engine so the
13
+ * ClassFactory-instantiated trigger providers (which live outside Angular DI) and the
14
+ * Angular components share ONE instance (one cache warm-up) via
15
+ * `MentionAutocompleteService.Instance`.
6
16
  */
7
- export interface MentionSuggestion {
8
- type: 'agent' | 'user' | 'entity' | 'query';
9
- id: string;
10
- name: string;
11
- displayName: string;
12
- description?: string;
13
- avatarUrl?: string;
14
- imageUrl?: string;
15
- icon?: string;
16
- }
17
- /**
18
- * Service for autocomplete suggestions when typing @mentions
19
- */
20
- export declare class MentionAutocompleteService {
17
+ export declare class MentionAutocompleteService extends BaseSingleton<MentionAutocompleteService> {
18
+ protected constructor();
19
+ /** The process-wide shared instance (Global Object Store backed). */
20
+ static get Instance(): MentionAutocompleteService;
21
21
  private agentsCache;
22
22
  private usersCache;
23
23
  private entitiesCache;
24
24
  private queriesCache;
25
+ /** Active skills the current user can Run — surfaced under the '/' trigger. */
26
+ private skillsCache;
27
+ /** Default icon for a skill with no IconClass of its own. */
28
+ private defaultSkillIcon;
25
29
  /** Generic icon for all query mentions, sourced from the 'MJ: Queries' entity. */
26
30
  private queriesEntityIcon;
27
31
  private isInitialized;
28
32
  private initializationPromise;
29
- constructor();
33
+ /** True once the caches have loaded (agents/users/entities/queries/skills). */
34
+ get IsInitialized(): boolean;
30
35
  /**
31
36
  * Initialize the service by loading agents and users
32
37
  * Prevents concurrent initialization with promise lock
@@ -42,6 +47,12 @@ export declare class MentionAutocompleteService {
42
47
  * Agents with explicit permission records are checked against the user.
43
48
  */
44
49
  private filterAgentsByRunPermission;
50
+ /**
51
+ * Filter Active skills to those the current user has 'run' permission for.
52
+ * Skills with no permission records are open to everyone (canRun = true);
53
+ * skills with explicit records are checked against the user (open-by-default).
54
+ */
55
+ private filterSkillsByRunPermission;
45
56
  /**
46
57
  * Load entities the current user has read permission for.
47
58
  * These are the candidates surfaced for #entity mentions.
@@ -68,11 +79,25 @@ export declare class MentionAutocompleteService {
68
79
  * Capped to keep the dropdown light (entity/query sets can be large).
69
80
  */
70
81
  private getEntityAndQuerySuggestions;
82
+ /**
83
+ * Get skill suggestions for '/'-mentions, ranked by query match. Each carries the skill's own
84
+ * IconClass/Color (UX metadata) so the dropdown + inserted chip render distinctly per skill.
85
+ */
86
+ private getSkillSuggestions;
71
87
  /**
72
88
  * Calculate match score for ranking
73
89
  * Higher score = better match
74
90
  */
75
91
  private calculateMatchScore;
92
+ /**
93
+ * Map an agent's AI Agent Configuration presets into the composer's generic
94
+ * `MentionSuggestionPreset` shape so the chip's preset picker works without the
95
+ * composer knowing anything about agents.
96
+ *
97
+ * IMPORTANT: preset.ID is the AIAgentConfiguration.ID (preset ID), not
98
+ * AIConfigurationID — the backend mapping converts preset ID -> AIConfigurationID.
99
+ */
100
+ private getAgentPresets;
76
101
  /**
77
102
  * Get icon for agent based on type/name
78
103
  */
@@ -102,7 +127,5 @@ export declare class MentionAutocompleteService {
102
127
  * Resets initialization state and reloads agents
103
128
  */
104
129
  refresh(currentUser: UserInfo): Promise<void>;
105
- static ɵfac: i0.ɵɵFactoryDeclaration<MentionAutocompleteService, never>;
106
- static ɵprov: i0.ɵɵInjectableDeclaration<MentionAutocompleteService>;
107
130
  }
108
131
  //# sourceMappingURL=mention-autocomplete.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mention-autocomplete.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/mention-autocomplete.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAY,UAAU,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;;AAGpG;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,qBAGa,0BAA0B;IACrC,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,YAAY,CAAmB;IACvC,kFAAkF;IAClF,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,qBAAqB,CAA8B;;IAI3D;;;OAGG;IACG,UAAU,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBpF;;OAEG;YACW,mBAAmB;IAiCjC;;;;OAIG;YACW,2BAA2B;IAkBzC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAiB5B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAShC;;;;;OAKG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,GAAE,OAAc,EAAE,OAAO,GAAE,MAAY,GAAG,iBAAiB,EAAE;IAwDvG;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IA2CpC;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;OAEG;IACH,OAAO,CAAC,YAAY;IAepB;;OAEG;IACH,kBAAkB,IAAI,uBAAuB,EAAE;IAI/C;;OAEG;IACH,iBAAiB,IAAI,QAAQ,EAAE;IAI/B;;OAEG;IACH,oBAAoB,IAAI,UAAU,EAAE;IAIpC;;OAEG;IACH,mBAAmB,IAAI,SAAS,EAAE;IAIlC;;OAEG;IACH,oBAAoB,IAAI,MAAM;IAI9B;;;OAGG;IACG,OAAO,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;yCAxVxC,0BAA0B;6CAA1B,0BAA0B;CA6VtC"}
1
+ {"version":3,"file":"mention-autocomplete.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/mention-autocomplete.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EAAE,QAAQ,EAAY,UAAU,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEpG,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAA2B,MAAM,6BAA6B,CAAC;AAEzF;;;;;;;;;;;GAWG;AACH,qBAAa,0BAA2B,SAAQ,aAAa,CAAC,0BAA0B,CAAC;IACvF,SAAS;IAIT,qEAAqE;IACrE,WAAkB,QAAQ,IAAI,0BAA0B,CAEvD;IAED,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,YAAY,CAAmB;IACvC,+EAA+E;IAC/E,OAAO,CAAC,WAAW,CAAyB;IAC5C,6DAA6D;IAC7D,OAAO,CAAC,gBAAgB,CAAqC;IAC7D,kFAAkF;IAClF,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,qBAAqB,CAA8B;IAE3D,+EAA+E;IAC/E,IAAW,aAAa,IAAI,OAAO,CAElC;IAED;;;OAGG;IACG,UAAU,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBpF;;OAEG;YACW,mBAAmB;IAuCjC;;;;OAIG;YACW,2BAA2B;IAkBzC;;;;OAIG;YACW,2BAA2B;IAUzC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAiB5B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAShC;;;;;OAKG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,GAAE,OAAc,EAAE,OAAO,GAAE,MAAY,GAAG,iBAAiB,EAAE;IA6DvG;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IA2CpC;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IA0B3B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAmBvB;;OAEG;IACH,OAAO,CAAC,YAAY;IAepB;;OAEG;IACH,kBAAkB,IAAI,uBAAuB,EAAE;IAI/C;;OAEG;IACH,iBAAiB,IAAI,QAAQ,EAAE;IAI/B;;OAEG;IACH,oBAAoB,IAAI,UAAU,EAAE;IAIpC;;OAEG;IACH,mBAAmB,IAAI,SAAS,EAAE;IAIlC;;OAEG;IACH,oBAAoB,IAAI,MAAM;IAI9B;;;OAGG;IACG,OAAO,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAKpD"}
@@ -1,20 +1,42 @@
1
- import { Injectable } from '@angular/core';
2
1
  import { Metadata } from '@memberjunction/core';
3
- import { AIEngineBase, AIAgentPermissionHelper } from '@memberjunction/ai-engine-base';
4
- import * as i0 from "@angular/core";
2
+ import { AIEngineBase, AIAgentPermissionHelper, AISkillPermissionHelper } from '@memberjunction/ai-engine-base';
3
+ import { BaseSingleton } from '@memberjunction/global';
5
4
  /**
6
- * Service for autocomplete suggestions when typing @mentions
5
+ * Shared engine behind the conversations composer plugins (the agent-mentions /
6
+ * record-mentions / skill-commands `ComposerTriggerProvider`s) and the mention-parsing
7
+ * consumers (message routing, saved-message badge rendering). Loads the
8
+ * permission-filtered agent / user / entity / query / skill caches once per session and
9
+ * serves ranked `MentionSuggestion` lists per trigger char.
10
+ *
11
+ * NOT an Angular DI service — it's a `BaseSingleton` engine so the
12
+ * ClassFactory-instantiated trigger providers (which live outside Angular DI) and the
13
+ * Angular components share ONE instance (one cache warm-up) via
14
+ * `MentionAutocompleteService.Instance`.
7
15
  */
8
- export class MentionAutocompleteService {
16
+ export class MentionAutocompleteService extends BaseSingleton {
17
+ constructor() {
18
+ super();
19
+ }
20
+ /** The process-wide shared instance (Global Object Store backed). */
21
+ static get Instance() {
22
+ return super.getInstance();
23
+ }
9
24
  agentsCache = [];
10
25
  usersCache = [];
11
26
  entitiesCache = [];
12
27
  queriesCache = [];
28
+ /** Active skills the current user can Run — surfaced under the '/' trigger. */
29
+ skillsCache = [];
30
+ /** Default icon for a skill with no IconClass of its own. */
31
+ defaultSkillIcon = 'fa-solid fa-wand-magic-sparkles';
13
32
  /** Generic icon for all query mentions, sourced from the 'MJ: Queries' entity. */
14
33
  queriesEntityIcon = 'fa-solid fa-database';
15
34
  isInitialized = false;
16
35
  initializationPromise = null;
17
- constructor() { }
36
+ /** True once the caches have loaded (agents/users/entities/queries/skills). */
37
+ get IsInitialized() {
38
+ return this.isInitialized;
39
+ }
18
40
  /**
19
41
  * Initialize the service by loading agents and users
20
42
  * Prevents concurrent initialization with promise lock
@@ -57,6 +79,11 @@ export class MentionAutocompleteService {
57
79
  // Load queries the current user can run (also surfaced under the '#' trigger)
58
80
  this.queriesCache = this.loadRunnableQueries(currentUser, provider);
59
81
  this.queriesEntityIcon = this.resolveQueriesEntityIcon(provider);
82
+ // Load Active skills the current user can Run (surfaced under the '/' trigger). Mirrors the
83
+ // agent filter: open-by-default unless a skill has explicit permission rows. The agent's
84
+ // AcceptsSkills gate is applied server-side at run time, so the picker shows the user's full
85
+ // run-permitted set regardless of which agent ends up handling the message.
86
+ this.skillsCache = await this.filterSkillsByRunPermission(currentUser);
60
87
  this.isInitialized = true;
61
88
  }
62
89
  catch (error) {
@@ -84,6 +111,21 @@ export class MentionAutocompleteService {
84
111
  }
85
112
  return permitted;
86
113
  }
114
+ /**
115
+ * Filter Active skills to those the current user has 'run' permission for.
116
+ * Skills with no permission records are open to everyone (canRun = true);
117
+ * skills with explicit records are checked against the user (open-by-default).
118
+ */
119
+ async filterSkillsByRunPermission(user) {
120
+ try {
121
+ const runnable = await AISkillPermissionHelper.GetAccessibleSkills(user, 'run');
122
+ return runnable.filter(s => s.Status === 'Active');
123
+ }
124
+ catch {
125
+ // Fail closed — no skills on error.
126
+ return [];
127
+ }
128
+ }
87
129
  /**
88
130
  * Load entities the current user has read permission for.
89
131
  * These are the candidates surfaced for #entity mentions.
@@ -147,10 +189,13 @@ export class MentionAutocompleteService {
147
189
  * @returns Filtered and ranked suggestions
148
190
  */
149
191
  getSuggestions(query, includeUsers = true, trigger = '@') {
150
- // The '#' trigger searches entities + queries; '@' searches agents + users
192
+ // The '#' trigger searches entities + queries; '/' searches skills; '@' searches agents + users
151
193
  if (trigger === '#') {
152
194
  return this.getEntityAndQuerySuggestions(query);
153
195
  }
196
+ if (trigger === '/') {
197
+ return this.getSkillSuggestions(query);
198
+ }
154
199
  const lowerQuery = query.toLowerCase().trim();
155
200
  const suggestions = [];
156
201
  // Add agent suggestions
@@ -164,7 +209,10 @@ export class MentionAutocompleteService {
164
209
  displayName: agent.Name || 'Unknown',
165
210
  description: agent.Description || undefined,
166
211
  imageUrl: agent.LogoURL || undefined, // Agent logo/avatar image
167
- icon: this.getAgentIcon(agent)
212
+ icon: this.getAgentIcon(agent),
213
+ // Configuration presets ride on the suggestion — the (AI-blind) composer
214
+ // renders a preset picker on the inserted chip when there are 2+.
215
+ presets: this.getAgentPresets(agent.ID)
168
216
  });
169
217
  }
170
218
  }
@@ -178,8 +226,7 @@ export class MentionAutocompleteService {
178
226
  id: user.ID,
179
227
  name: user.Name,
180
228
  displayName: user.Name,
181
- description: user.Email || undefined,
182
- avatarUrl: undefined // Future: load user avatars
229
+ description: user.Email || undefined
183
230
  });
184
231
  }
185
232
  }
@@ -238,6 +285,35 @@ export class MentionAutocompleteService {
238
285
  .slice(0, MAX_SUGGESTIONS)
239
286
  .map(x => x.suggestion);
240
287
  }
288
+ /**
289
+ * Get skill suggestions for '/'-mentions, ranked by query match. Each carries the skill's own
290
+ * IconClass/Color (UX metadata) so the dropdown + inserted chip render distinctly per skill.
291
+ */
292
+ getSkillSuggestions(query) {
293
+ const lowerQuery = query.toLowerCase().trim();
294
+ const MAX_SUGGESTIONS = 12;
295
+ return this.skillsCache
296
+ .map(skill => ({
297
+ score: this.calculateMatchScore(skill.Name || '', lowerQuery),
298
+ suggestion: {
299
+ type: 'skill',
300
+ id: skill.ID,
301
+ name: skill.Name || 'Unknown Skill',
302
+ displayName: skill.Name || 'Unknown Skill',
303
+ description: skill.Description || undefined,
304
+ icon: skill.IconClass || this.defaultSkillIcon,
305
+ color: skill.Color || undefined
306
+ }
307
+ }))
308
+ .filter(x => x.score > 0 || !lowerQuery)
309
+ .sort((a, b) => {
310
+ if (b.score !== a.score)
311
+ return b.score - a.score;
312
+ return a.suggestion.name.localeCompare(b.suggestion.name);
313
+ })
314
+ .slice(0, MAX_SUGGESTIONS)
315
+ .map(x => x.suggestion);
316
+ }
241
317
  /**
242
318
  * Calculate match score for ranking
243
319
  * Higher score = better match
@@ -264,6 +340,33 @@ export class MentionAutocompleteService {
264
340
  }
265
341
  return 0; // No match
266
342
  }
343
+ /**
344
+ * Map an agent's AI Agent Configuration presets into the composer's generic
345
+ * `MentionSuggestionPreset` shape so the chip's preset picker works without the
346
+ * composer knowing anything about agents.
347
+ *
348
+ * IMPORTANT: preset.ID is the AIAgentConfiguration.ID (preset ID), not
349
+ * AIConfigurationID — the backend mapping converts preset ID -> AIConfigurationID.
350
+ */
351
+ getAgentPresets(agentId) {
352
+ try {
353
+ const presets = AIEngineBase.Instance.GetAgentConfigurationPresets(agentId, true);
354
+ if (!presets || presets.length === 0) {
355
+ return undefined;
356
+ }
357
+ return presets.map(p => ({
358
+ ID: p.ID,
359
+ Name: p.Name,
360
+ DisplayName: p.DisplayName || undefined,
361
+ Description: p.Description || undefined,
362
+ IsDefault: p.IsDefault
363
+ }));
364
+ }
365
+ catch {
366
+ // Presets are a chip nicety — never let them break suggestion building
367
+ return undefined;
368
+ }
369
+ }
267
370
  /**
268
371
  * Get icon for agent based on type/name
269
372
  */
@@ -324,13 +427,5 @@ export class MentionAutocompleteService {
324
427
  this.initializationPromise = null;
325
428
  await this.initialize(currentUser);
326
429
  }
327
- static ɵfac = function MentionAutocompleteService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MentionAutocompleteService)(); };
328
- static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MentionAutocompleteService, factory: MentionAutocompleteService.ɵfac, providedIn: 'root' });
329
430
  }
330
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MentionAutocompleteService, [{
331
- type: Injectable,
332
- args: [{
333
- providedIn: 'root'
334
- }]
335
- }], () => [], null); })();
336
431
  //# sourceMappingURL=mention-autocomplete.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mention-autocomplete.service.js","sourceRoot":"","sources":["../../../src/lib/services/mention-autocomplete.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';\nimport { UserInfo, Metadata, EntityInfo, QueryInfo, IMetadataProvider } from '@memberjunction/core';\nimport { AIEngineBase, AIAgentPermissionHelper } from '@memberjunction/ai-engine-base';\n\n/**\n * Item in the autocomplete dropdown\n */\nexport interface MentionSuggestion {\n type: 'agent' | 'user' | 'entity' | 'query';\n id: string;\n name: string;\n displayName: string;\n description?: string;\n avatarUrl?: string; // Deprecated, use imageUrl\n imageUrl?: string; // For agent LogoURL or user avatar\n icon?: string; // FontAwesome class for agents, entities, and queries\n}\n\n/**\n * Service for autocomplete suggestions when typing @mentions\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class MentionAutocompleteService {\n private agentsCache: MJAIAgentEntityExtended[] = [];\n private usersCache: UserInfo[] = [];\n private entitiesCache: EntityInfo[] = [];\n private queriesCache: QueryInfo[] = [];\n /** Generic icon for all query mentions, sourced from the 'MJ: Queries' entity. */\n private queriesEntityIcon = 'fa-solid fa-database';\n private isInitialized = false;\n private initializationPromise: Promise<void> | null = null;\n\n constructor() {}\n\n /**\n * Initialize the service by loading agents and users\n * Prevents concurrent initialization with promise lock\n */\n async initialize(currentUser: UserInfo, provider?: IMetadataProvider): Promise<void> {\n // If already initialized, return immediately\n if (this.isInitialized) {\n return;\n }\n\n // If initialization is in progress, wait for it\n if (this.initializationPromise) {\n return this.initializationPromise;\n }\n\n // Create initialization promise and store it\n this.initializationPromise = this._initializeInternal(currentUser, provider);\n\n try {\n await this.initializationPromise;\n } finally {\n this.initializationPromise = null;\n }\n }\n\n /**\n * Internal initialization logic\n */\n private async _initializeInternal(currentUser: UserInfo, provider?: IMetadataProvider): Promise<void> {\n try {\n // Load agents from AIEngineBase\n await AIEngineBase.Instance.Config(false);\n\n const allAgents = AIEngineBase.Instance.Agents || [];\n\n // Filter by status, hierarchy, and invocation mode first\n const candidateAgents = allAgents.filter(\n a => !a.ParentID && a.Status === 'Active' && a.InvocationMode !== 'Sub-Agent' && !a.IsRestricted\n );\n\n // Filter by user's 'run' permission — respects open-by-default + explicit permissions\n this.agentsCache = await this.filterAgentsByRunPermission(candidateAgents, currentUser);\n\n // Load users from the system (optional - can be expanded later)\n // For now, we'll just use the current user\n this.usersCache = [currentUser];\n\n // Load entities the current user can read (candidates for #entity mentions)\n this.entitiesCache = this.loadReadableEntities(currentUser, provider);\n\n // Load queries the current user can run (also surfaced under the '#' trigger)\n this.queriesCache = this.loadRunnableQueries(currentUser, provider);\n this.queriesEntityIcon = this.resolveQueriesEntityIcon(provider);\n\n this.isInitialized = true;\n } catch (error) {\n console.error('Failed to initialize MentionAutocompleteService:', error);\n throw error;\n }\n }\n\n /**\n * Filter agents to only those the current user has 'run' permission for.\n * Agents with no permission records are open to everyone (canRun = true).\n * Agents with explicit permission records are checked against the user.\n */\n private async filterAgentsByRunPermission(\n agents: MJAIAgentEntityExtended[],\n user: UserInfo\n ): Promise<MJAIAgentEntityExtended[]> {\n const permitted: MJAIAgentEntityExtended[] = [];\n for (const agent of agents) {\n try {\n const canRun = await AIAgentPermissionHelper.HasPermission(agent.ID, user, 'run');\n if (canRun) {\n permitted.push(agent);\n }\n } catch {\n // Fail closed — exclude agent on error\n }\n }\n return permitted;\n }\n\n /**\n * Load entities the current user has read permission for.\n * These are the candidates surfaced for #entity mentions.\n */\n private loadReadableEntities(user: UserInfo, provider?: IMetadataProvider): EntityInfo[] {\n try {\n const md = provider ?? new Metadata();\n return (md.Entities || []).filter(entity => {\n try {\n return entity.GetUserPermisions(user).CanRead;\n } catch {\n // Fail closed — exclude entity on permission-check error\n return false;\n }\n });\n } catch (error) {\n console.error('Failed to load entities for mention autocomplete:', error);\n return [];\n }\n }\n\n /**\n * Load queries the current user has run permission for.\n * These are the candidates surfaced for #query mentions.\n */\n private loadRunnableQueries(user: UserInfo, provider?: IMetadataProvider): QueryInfo[] {\n try {\n const md = provider ?? new Metadata();\n return (md.Queries || []).filter(query => {\n try {\n return query.UserCanRun(user);\n } catch {\n // Fail closed — exclude query on permission-check error\n return false;\n }\n });\n } catch (error) {\n console.error('Failed to load queries for mention autocomplete:', error);\n return [];\n }\n }\n\n /**\n * Resolve the generic icon used for all query mentions from the 'MJ: Queries' entity.\n */\n private resolveQueriesEntityIcon(provider?: IMetadataProvider): string {\n try {\n const md = provider ?? new Metadata();\n return md.EntityByName('MJ: Queries')?.Icon || 'fa-solid fa-database';\n } catch {\n return 'fa-solid fa-database';\n }\n }\n\n /**\n * Get suggestions based on search query\n * @param query The search text after @ symbol\n * @param includeUsers Whether to include users in suggestions\n * @returns Filtered and ranked suggestions\n */\n getSuggestions(query: string, includeUsers: boolean = true, trigger: string = '@'): MentionSuggestion[] {\n // The '#' trigger searches entities + queries; '@' searches agents + users\n if (trigger === '#') {\n return this.getEntityAndQuerySuggestions(query);\n }\n\n const lowerQuery = query.toLowerCase().trim();\n const suggestions: MentionSuggestion[] = [];\n\n // Add agent suggestions\n for (const agent of this.agentsCache) {\n const score = this.calculateMatchScore(agent.Name || '', lowerQuery);\n if (score > 0 || !lowerQuery) {\n suggestions.push({\n type: 'agent',\n id: agent.ID,\n name: agent.Name || 'Unknown',\n displayName: agent.Name || 'Unknown',\n description: agent.Description || undefined,\n imageUrl: agent.LogoURL || undefined, // Agent logo/avatar image\n icon: this.getAgentIcon(agent)\n });\n }\n }\n\n // Add user suggestions (if enabled)\n if (includeUsers) {\n for (const user of this.usersCache) {\n const score = this.calculateMatchScore(user.Name, lowerQuery);\n if (score > 0 || !lowerQuery) {\n suggestions.push({\n type: 'user',\n id: user.ID,\n name: user.Name,\n displayName: user.Name,\n description: user.Email || undefined,\n avatarUrl: undefined // Future: load user avatars\n });\n }\n }\n }\n\n // Sort by relevance: exact match > starts with > contains\n return suggestions.sort((a, b) => {\n const scoreA = this.calculateMatchScore(a.name, lowerQuery);\n const scoreB = this.calculateMatchScore(b.name, lowerQuery);\n if (scoreB !== scoreA) return scoreB - scoreA;\n\n // If scores are equal, sort agents before users\n if (a.type !== b.type) return a.type === 'agent' ? -1 : 1;\n\n // Otherwise alphabetically\n return a.name.localeCompare(b.name);\n });\n }\n\n /**\n * Get entity + query suggestions for #mentions, ranked by query match.\n * Capped to keep the dropdown light (entity/query sets can be large).\n */\n private getEntityAndQuerySuggestions(query: string): MentionSuggestion[] {\n const lowerQuery = query.toLowerCase().trim();\n const MAX_SUGGESTIONS = 12;\n\n const entityItems = this.entitiesCache.map(entity => ({\n label: entity.DisplayNameOrName,\n score: Math.max(\n this.calculateMatchScore(entity.Name || '', lowerQuery),\n this.calculateMatchScore(entity.DisplayName || '', lowerQuery)\n ),\n suggestion: {\n type: 'entity' as const,\n id: entity.ID,\n name: entity.Name,\n displayName: entity.DisplayNameOrName,\n description: entity.Description || undefined,\n icon: entity.Icon || 'fa-solid fa-table'\n }\n }));\n\n const queryItems = this.queriesCache.map(q => ({\n label: q.Name || '',\n score: this.calculateMatchScore(q.Name || '', lowerQuery),\n suggestion: {\n type: 'query' as const,\n id: q.ID,\n name: q.Name || '',\n displayName: q.Name || '',\n description: q.Description || undefined,\n icon: this.queriesEntityIcon\n }\n }));\n\n return [...entityItems, ...queryItems]\n .filter(x => x.score > 0 || !lowerQuery)\n .sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n return a.label.localeCompare(b.label);\n })\n .slice(0, MAX_SUGGESTIONS)\n .map(x => x.suggestion);\n }\n\n /**\n * Calculate match score for ranking\n * Higher score = better match\n */\n private calculateMatchScore(name: string, query: string): number {\n if (!query) return 1; // Show all if no query\n\n const lowerName = name.toLowerCase();\n const lowerQuery = query.toLowerCase();\n\n // Exact match\n if (lowerName === lowerQuery) return 100;\n\n // Starts with\n if (lowerName.startsWith(lowerQuery)) return 50;\n\n // Contains\n if (lowerName.includes(lowerQuery)) return 25;\n\n // Word boundary match (e.g., \"MA\" matches \"Marketing Agent\")\n const words = lowerName.split(/\\s+/);\n for (const word of words) {\n if (word.startsWith(lowerQuery)) return 40;\n }\n\n return 0; // No match\n }\n\n /**\n * Get icon for agent based on type/name\n */\n private getAgentIcon(agent: MJAIAgentEntityExtended): string {\n // Use agent's icon if available, otherwise default based on type\n if (agent.IconClass) return agent.IconClass;\n\n // Default icons based on agent name patterns\n const name = agent.Name?.toLowerCase() || '';\n if (name.includes('marketing')) return 'fa-megaphone';\n if (name.includes('data') || name.includes('analysis')) return 'fa-chart-line';\n if (name.includes('code') || name.includes('developer')) return 'fa-code';\n if (name.includes('design')) return 'fa-palette';\n if (name.includes('conversation') || name.includes('manager')) return 'fa-comments';\n\n return 'fa-robot'; // Default\n }\n\n /**\n * Get available agents for parsing\n */\n getAvailableAgents(): MJAIAgentEntityExtended[] {\n return this.agentsCache;\n }\n\n /**\n * Get available users for parsing\n */\n getAvailableUsers(): UserInfo[] {\n return this.usersCache;\n }\n\n /**\n * Get available entities for parsing\n */\n getAvailableEntities(): EntityInfo[] {\n return this.entitiesCache;\n }\n\n /**\n * Get available queries for parsing\n */\n getAvailableQueries(): QueryInfo[] {\n return this.queriesCache;\n }\n\n /**\n * Get the generic icon used for all query mentions.\n */\n getQueriesEntityIcon(): string {\n return this.queriesEntityIcon;\n }\n\n /**\n * Refresh the caches\n * Resets initialization state and reloads agents\n */\n async refresh(currentUser: UserInfo): Promise<void> {\n this.isInitialized = false;\n this.initializationPromise = null;\n await this.initialize(currentUser);\n }\n}\n"]}
1
+ {"version":3,"file":"mention-autocomplete.service.js","sourceRoot":"","sources":["../../../src/lib/services/mention-autocomplete.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';\nimport { MJAISkillEntity } from '@memberjunction/core-entities';\nimport { UserInfo, Metadata, EntityInfo, QueryInfo, IMetadataProvider } from '@memberjunction/core';\nimport { AIEngineBase, AIAgentPermissionHelper, AISkillPermissionHelper } from '@memberjunction/ai-engine-base';\nimport { BaseSingleton } from '@memberjunction/global';\nimport { MentionSuggestion, MentionSuggestionPreset } from '@memberjunction/ng-composer';\n\n/**\n * Shared engine behind the conversations composer plugins (the agent-mentions /\n * record-mentions / skill-commands `ComposerTriggerProvider`s) and the mention-parsing\n * consumers (message routing, saved-message badge rendering). Loads the\n * permission-filtered agent / user / entity / query / skill caches once per session and\n * serves ranked `MentionSuggestion` lists per trigger char.\n *\n * NOT an Angular DI service — it's a `BaseSingleton` engine so the\n * ClassFactory-instantiated trigger providers (which live outside Angular DI) and the\n * Angular components share ONE instance (one cache warm-up) via\n * `MentionAutocompleteService.Instance`.\n */\nexport class MentionAutocompleteService extends BaseSingleton<MentionAutocompleteService> {\n protected constructor() {\n super();\n }\n\n /** The process-wide shared instance (Global Object Store backed). */\n public static get Instance(): MentionAutocompleteService {\n return super.getInstance<MentionAutocompleteService>();\n }\n\n private agentsCache: MJAIAgentEntityExtended[] = [];\n private usersCache: UserInfo[] = [];\n private entitiesCache: EntityInfo[] = [];\n private queriesCache: QueryInfo[] = [];\n /** Active skills the current user can Run — surfaced under the '/' trigger. */\n private skillsCache: MJAISkillEntity[] = [];\n /** Default icon for a skill with no IconClass of its own. */\n private defaultSkillIcon = 'fa-solid fa-wand-magic-sparkles';\n /** Generic icon for all query mentions, sourced from the 'MJ: Queries' entity. */\n private queriesEntityIcon = 'fa-solid fa-database';\n private isInitialized = false;\n private initializationPromise: Promise<void> | null = null;\n\n /** True once the caches have loaded (agents/users/entities/queries/skills). */\n public get IsInitialized(): boolean {\n return this.isInitialized;\n }\n\n /**\n * Initialize the service by loading agents and users\n * Prevents concurrent initialization with promise lock\n */\n async initialize(currentUser: UserInfo, provider?: IMetadataProvider): Promise<void> {\n // If already initialized, return immediately\n if (this.isInitialized) {\n return;\n }\n\n // If initialization is in progress, wait for it\n if (this.initializationPromise) {\n return this.initializationPromise;\n }\n\n // Create initialization promise and store it\n this.initializationPromise = this._initializeInternal(currentUser, provider);\n\n try {\n await this.initializationPromise;\n } finally {\n this.initializationPromise = null;\n }\n }\n\n /**\n * Internal initialization logic\n */\n private async _initializeInternal(currentUser: UserInfo, provider?: IMetadataProvider): Promise<void> {\n try {\n // Load agents from AIEngineBase\n await AIEngineBase.Instance.Config(false);\n\n const allAgents = AIEngineBase.Instance.Agents || [];\n\n // Filter by status, hierarchy, and invocation mode first\n const candidateAgents = allAgents.filter(\n a => !a.ParentID && a.Status === 'Active' && a.InvocationMode !== 'Sub-Agent' && !a.IsRestricted\n );\n\n // Filter by user's 'run' permission — respects open-by-default + explicit permissions\n this.agentsCache = await this.filterAgentsByRunPermission(candidateAgents, currentUser);\n\n // Load users from the system (optional - can be expanded later)\n // For now, we'll just use the current user\n this.usersCache = [currentUser];\n\n // Load entities the current user can read (candidates for #entity mentions)\n this.entitiesCache = this.loadReadableEntities(currentUser, provider);\n\n // Load queries the current user can run (also surfaced under the '#' trigger)\n this.queriesCache = this.loadRunnableQueries(currentUser, provider);\n this.queriesEntityIcon = this.resolveQueriesEntityIcon(provider);\n\n // Load Active skills the current user can Run (surfaced under the '/' trigger). Mirrors the\n // agent filter: open-by-default unless a skill has explicit permission rows. The agent's\n // AcceptsSkills gate is applied server-side at run time, so the picker shows the user's full\n // run-permitted set regardless of which agent ends up handling the message.\n this.skillsCache = await this.filterSkillsByRunPermission(currentUser);\n\n this.isInitialized = true;\n } catch (error) {\n console.error('Failed to initialize MentionAutocompleteService:', error);\n throw error;\n }\n }\n\n /**\n * Filter agents to only those the current user has 'run' permission for.\n * Agents with no permission records are open to everyone (canRun = true).\n * Agents with explicit permission records are checked against the user.\n */\n private async filterAgentsByRunPermission(\n agents: MJAIAgentEntityExtended[],\n user: UserInfo\n ): Promise<MJAIAgentEntityExtended[]> {\n const permitted: MJAIAgentEntityExtended[] = [];\n for (const agent of agents) {\n try {\n const canRun = await AIAgentPermissionHelper.HasPermission(agent.ID, user, 'run');\n if (canRun) {\n permitted.push(agent);\n }\n } catch {\n // Fail closed — exclude agent on error\n }\n }\n return permitted;\n }\n\n /**\n * Filter Active skills to those the current user has 'run' permission for.\n * Skills with no permission records are open to everyone (canRun = true);\n * skills with explicit records are checked against the user (open-by-default).\n */\n private async filterSkillsByRunPermission(user: UserInfo): Promise<MJAISkillEntity[]> {\n try {\n const runnable = await AISkillPermissionHelper.GetAccessibleSkills(user, 'run');\n return runnable.filter(s => s.Status === 'Active');\n } catch {\n // Fail closed — no skills on error.\n return [];\n }\n }\n\n /**\n * Load entities the current user has read permission for.\n * These are the candidates surfaced for #entity mentions.\n */\n private loadReadableEntities(user: UserInfo, provider?: IMetadataProvider): EntityInfo[] {\n try {\n const md = provider ?? new Metadata();\n return (md.Entities || []).filter(entity => {\n try {\n return entity.GetUserPermisions(user).CanRead;\n } catch {\n // Fail closed — exclude entity on permission-check error\n return false;\n }\n });\n } catch (error) {\n console.error('Failed to load entities for mention autocomplete:', error);\n return [];\n }\n }\n\n /**\n * Load queries the current user has run permission for.\n * These are the candidates surfaced for #query mentions.\n */\n private loadRunnableQueries(user: UserInfo, provider?: IMetadataProvider): QueryInfo[] {\n try {\n const md = provider ?? new Metadata();\n return (md.Queries || []).filter(query => {\n try {\n return query.UserCanRun(user);\n } catch {\n // Fail closed — exclude query on permission-check error\n return false;\n }\n });\n } catch (error) {\n console.error('Failed to load queries for mention autocomplete:', error);\n return [];\n }\n }\n\n /**\n * Resolve the generic icon used for all query mentions from the 'MJ: Queries' entity.\n */\n private resolveQueriesEntityIcon(provider?: IMetadataProvider): string {\n try {\n const md = provider ?? new Metadata();\n return md.EntityByName('MJ: Queries')?.Icon || 'fa-solid fa-database';\n } catch {\n return 'fa-solid fa-database';\n }\n }\n\n /**\n * Get suggestions based on search query\n * @param query The search text after @ symbol\n * @param includeUsers Whether to include users in suggestions\n * @returns Filtered and ranked suggestions\n */\n getSuggestions(query: string, includeUsers: boolean = true, trigger: string = '@'): MentionSuggestion[] {\n // The '#' trigger searches entities + queries; '/' searches skills; '@' searches agents + users\n if (trigger === '#') {\n return this.getEntityAndQuerySuggestions(query);\n }\n if (trigger === '/') {\n return this.getSkillSuggestions(query);\n }\n\n const lowerQuery = query.toLowerCase().trim();\n const suggestions: MentionSuggestion[] = [];\n\n // Add agent suggestions\n for (const agent of this.agentsCache) {\n const score = this.calculateMatchScore(agent.Name || '', lowerQuery);\n if (score > 0 || !lowerQuery) {\n suggestions.push({\n type: 'agent',\n id: agent.ID,\n name: agent.Name || 'Unknown',\n displayName: agent.Name || 'Unknown',\n description: agent.Description || undefined,\n imageUrl: agent.LogoURL || undefined, // Agent logo/avatar image\n icon: this.getAgentIcon(agent),\n // Configuration presets ride on the suggestion — the (AI-blind) composer\n // renders a preset picker on the inserted chip when there are 2+.\n presets: this.getAgentPresets(agent.ID)\n });\n }\n }\n\n // Add user suggestions (if enabled)\n if (includeUsers) {\n for (const user of this.usersCache) {\n const score = this.calculateMatchScore(user.Name, lowerQuery);\n if (score > 0 || !lowerQuery) {\n suggestions.push({\n type: 'user',\n id: user.ID,\n name: user.Name,\n displayName: user.Name,\n description: user.Email || undefined\n });\n }\n }\n }\n\n // Sort by relevance: exact match > starts with > contains\n return suggestions.sort((a, b) => {\n const scoreA = this.calculateMatchScore(a.name, lowerQuery);\n const scoreB = this.calculateMatchScore(b.name, lowerQuery);\n if (scoreB !== scoreA) return scoreB - scoreA;\n\n // If scores are equal, sort agents before users\n if (a.type !== b.type) return a.type === 'agent' ? -1 : 1;\n\n // Otherwise alphabetically\n return a.name.localeCompare(b.name);\n });\n }\n\n /**\n * Get entity + query suggestions for #mentions, ranked by query match.\n * Capped to keep the dropdown light (entity/query sets can be large).\n */\n private getEntityAndQuerySuggestions(query: string): MentionSuggestion[] {\n const lowerQuery = query.toLowerCase().trim();\n const MAX_SUGGESTIONS = 12;\n\n const entityItems = this.entitiesCache.map(entity => ({\n label: entity.DisplayNameOrName,\n score: Math.max(\n this.calculateMatchScore(entity.Name || '', lowerQuery),\n this.calculateMatchScore(entity.DisplayName || '', lowerQuery)\n ),\n suggestion: {\n type: 'entity' as const,\n id: entity.ID,\n name: entity.Name,\n displayName: entity.DisplayNameOrName,\n description: entity.Description || undefined,\n icon: entity.Icon || 'fa-solid fa-table'\n }\n }));\n\n const queryItems = this.queriesCache.map(q => ({\n label: q.Name || '',\n score: this.calculateMatchScore(q.Name || '', lowerQuery),\n suggestion: {\n type: 'query' as const,\n id: q.ID,\n name: q.Name || '',\n displayName: q.Name || '',\n description: q.Description || undefined,\n icon: this.queriesEntityIcon\n }\n }));\n\n return [...entityItems, ...queryItems]\n .filter(x => x.score > 0 || !lowerQuery)\n .sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n return a.label.localeCompare(b.label);\n })\n .slice(0, MAX_SUGGESTIONS)\n .map(x => x.suggestion);\n }\n\n /**\n * Get skill suggestions for '/'-mentions, ranked by query match. Each carries the skill's own\n * IconClass/Color (UX metadata) so the dropdown + inserted chip render distinctly per skill.\n */\n private getSkillSuggestions(query: string): MentionSuggestion[] {\n const lowerQuery = query.toLowerCase().trim();\n const MAX_SUGGESTIONS = 12;\n\n return this.skillsCache\n .map(skill => ({\n score: this.calculateMatchScore(skill.Name || '', lowerQuery),\n suggestion: {\n type: 'skill' as const,\n id: skill.ID,\n name: skill.Name || 'Unknown Skill',\n displayName: skill.Name || 'Unknown Skill',\n description: skill.Description || undefined,\n icon: skill.IconClass || this.defaultSkillIcon,\n color: skill.Color || undefined\n }\n }))\n .filter(x => x.score > 0 || !lowerQuery)\n .sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n return a.suggestion.name.localeCompare(b.suggestion.name);\n })\n .slice(0, MAX_SUGGESTIONS)\n .map(x => x.suggestion);\n }\n\n /**\n * Calculate match score for ranking\n * Higher score = better match\n */\n private calculateMatchScore(name: string, query: string): number {\n if (!query) return 1; // Show all if no query\n\n const lowerName = name.toLowerCase();\n const lowerQuery = query.toLowerCase();\n\n // Exact match\n if (lowerName === lowerQuery) return 100;\n\n // Starts with\n if (lowerName.startsWith(lowerQuery)) return 50;\n\n // Contains\n if (lowerName.includes(lowerQuery)) return 25;\n\n // Word boundary match (e.g., \"MA\" matches \"Marketing Agent\")\n const words = lowerName.split(/\\s+/);\n for (const word of words) {\n if (word.startsWith(lowerQuery)) return 40;\n }\n\n return 0; // No match\n }\n\n /**\n * Map an agent's AI Agent Configuration presets into the composer's generic\n * `MentionSuggestionPreset` shape so the chip's preset picker works without the\n * composer knowing anything about agents.\n *\n * IMPORTANT: preset.ID is the AIAgentConfiguration.ID (preset ID), not\n * AIConfigurationID — the backend mapping converts preset ID -> AIConfigurationID.\n */\n private getAgentPresets(agentId: string): MentionSuggestionPreset[] | undefined {\n try {\n const presets = AIEngineBase.Instance.GetAgentConfigurationPresets(agentId, true);\n if (!presets || presets.length === 0) {\n return undefined;\n }\n return presets.map(p => ({\n ID: p.ID,\n Name: p.Name,\n DisplayName: p.DisplayName || undefined,\n Description: p.Description || undefined,\n IsDefault: p.IsDefault\n }));\n } catch {\n // Presets are a chip nicety — never let them break suggestion building\n return undefined;\n }\n }\n\n /**\n * Get icon for agent based on type/name\n */\n private getAgentIcon(agent: MJAIAgentEntityExtended): string {\n // Use agent's icon if available, otherwise default based on type\n if (agent.IconClass) return agent.IconClass;\n\n // Default icons based on agent name patterns\n const name = agent.Name?.toLowerCase() || '';\n if (name.includes('marketing')) return 'fa-megaphone';\n if (name.includes('data') || name.includes('analysis')) return 'fa-chart-line';\n if (name.includes('code') || name.includes('developer')) return 'fa-code';\n if (name.includes('design')) return 'fa-palette';\n if (name.includes('conversation') || name.includes('manager')) return 'fa-comments';\n\n return 'fa-robot'; // Default\n }\n\n /**\n * Get available agents for parsing\n */\n getAvailableAgents(): MJAIAgentEntityExtended[] {\n return this.agentsCache;\n }\n\n /**\n * Get available users for parsing\n */\n getAvailableUsers(): UserInfo[] {\n return this.usersCache;\n }\n\n /**\n * Get available entities for parsing\n */\n getAvailableEntities(): EntityInfo[] {\n return this.entitiesCache;\n }\n\n /**\n * Get available queries for parsing\n */\n getAvailableQueries(): QueryInfo[] {\n return this.queriesCache;\n }\n\n /**\n * Get the generic icon used for all query mentions.\n */\n getQueriesEntityIcon(): string {\n return this.queriesEntityIcon;\n }\n\n /**\n * Refresh the caches\n * Resets initialization state and reloads agents\n */\n async refresh(currentUser: UserInfo): Promise<void> {\n this.isInitialized = false;\n this.initializationPromise = null;\n await this.initialize(currentUser);\n }\n}\n"]}