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

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 (279) hide show
  1. package/README.md +4 -7
  2. package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
  3. package/dist/lib/components/collection/collection-view.component.js +1 -0
  4. package/dist/lib/components/collection/collection-view.component.js.map +1 -1
  5. package/dist/lib/components/composer/ai-composer.component.d.ts +14 -2
  6. package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -1
  7. package/dist/lib/components/composer/ai-composer.component.js +35 -4
  8. package/dist/lib/components/composer/ai-composer.component.js.map +1 -1
  9. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +632 -55
  10. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  11. package/dist/lib/components/conversation/conversation-chat-area.component.js +2748 -624
  12. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  13. package/dist/lib/components/conversation/forks-popover.component.d.ts +37 -0
  14. package/dist/lib/components/conversation/forks-popover.component.d.ts.map +1 -0
  15. package/dist/lib/components/conversation/forks-popover.component.js +164 -0
  16. package/dist/lib/components/conversation/forks-popover.component.js.map +1 -0
  17. package/dist/lib/components/export/export-modal.component.d.ts +7 -2
  18. package/dist/lib/components/export/export-modal.component.d.ts.map +1 -1
  19. package/dist/lib/components/export/export-modal.component.js +16 -3
  20. package/dist/lib/components/export/export-modal.component.js.map +1 -1
  21. package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
  22. package/dist/lib/components/message/conversation-message-rating.component.js +11 -9
  23. package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
  24. package/dist/lib/components/message/message-input.component.d.ts +121 -11
  25. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  26. package/dist/lib/components/message/message-input.component.js +307 -106
  27. package/dist/lib/components/message/message-input.component.js.map +1 -1
  28. package/dist/lib/components/message/message-item.component.d.ts +178 -5
  29. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  30. package/dist/lib/components/message/message-item.component.js +919 -306
  31. package/dist/lib/components/message/message-item.component.js.map +1 -1
  32. package/dist/lib/components/message/message-list.component.d.ts +92 -21
  33. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  34. package/dist/lib/components/message/message-list.component.js +337 -52
  35. package/dist/lib/components/message/message-list.component.js.map +1 -1
  36. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.d.ts +34 -0
  37. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.d.ts.map +1 -0
  38. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.js +75 -0
  39. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.js.map +1 -0
  40. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.d.ts +80 -0
  41. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.d.ts.map +1 -0
  42. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.js +202 -0
  43. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.js.map +1 -0
  44. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.d.ts +45 -0
  45. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.d.ts.map +1 -0
  46. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.js +123 -0
  47. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.js.map +1 -0
  48. package/dist/lib/components/realtime/capture/realtime-capture-channel.d.ts +90 -0
  49. package/dist/lib/components/realtime/capture/realtime-capture-channel.d.ts.map +1 -0
  50. package/dist/lib/components/realtime/capture/realtime-capture-channel.js +223 -0
  51. package/dist/lib/components/realtime/capture/realtime-capture-channel.js.map +1 -0
  52. package/dist/lib/components/realtime/capture/realtime-capture-model.d.ts +98 -0
  53. package/dist/lib/components/realtime/capture/realtime-capture-model.d.ts.map +1 -0
  54. package/dist/lib/components/realtime/capture/realtime-capture-model.js +161 -0
  55. package/dist/lib/components/realtime/capture/realtime-capture-model.js.map +1 -0
  56. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.d.ts +48 -0
  57. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.d.ts.map +1 -0
  58. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.js +205 -0
  59. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.js.map +1 -0
  60. package/dist/lib/components/realtime/channels/client-context-channel.d.ts +19 -2
  61. package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -1
  62. package/dist/lib/components/realtime/channels/client-context-channel.js +83 -9
  63. package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -1
  64. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +30 -9
  65. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -1
  66. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +78 -14
  67. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -1
  68. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.d.ts +71 -0
  69. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.d.ts.map +1 -0
  70. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.js +259 -0
  71. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.js.map +1 -0
  72. package/dist/lib/components/realtime/identity-verification/identity-verification-model.d.ts +129 -0
  73. package/dist/lib/components/realtime/identity-verification/identity-verification-model.d.ts.map +1 -0
  74. package/dist/lib/components/realtime/identity-verification/identity-verification-model.js +373 -0
  75. package/dist/lib/components/realtime/identity-verification/identity-verification-model.js.map +1 -0
  76. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.d.ts +77 -0
  77. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.d.ts.map +1 -0
  78. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.js +420 -0
  79. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.js.map +1 -0
  80. package/dist/lib/components/realtime/interactive-component/component-contract.d.ts +83 -0
  81. package/dist/lib/components/realtime/interactive-component/component-contract.d.ts.map +1 -0
  82. package/dist/lib/components/realtime/interactive-component/component-contract.js +292 -0
  83. package/dist/lib/components/realtime/interactive-component/component-contract.js.map +1 -0
  84. package/dist/lib/components/realtime/interactive-component/component-data-state.d.ts +39 -0
  85. package/dist/lib/components/realtime/interactive-component/component-data-state.d.ts.map +1 -0
  86. package/dist/lib/components/realtime/interactive-component/component-data-state.js +152 -0
  87. package/dist/lib/components/realtime/interactive-component/component-data-state.js.map +1 -0
  88. package/dist/lib/components/realtime/interactive-component/component-instance-engine.d.ts +109 -0
  89. package/dist/lib/components/realtime/interactive-component/component-instance-engine.d.ts.map +1 -0
  90. package/dist/lib/components/realtime/interactive-component/component-instance-engine.js +146 -0
  91. package/dist/lib/components/realtime/interactive-component/component-instance-engine.js.map +1 -0
  92. package/dist/lib/components/realtime/interactive-component/component-spec-content.d.ts +19 -0
  93. package/dist/lib/components/realtime/interactive-component/component-spec-content.d.ts.map +1 -0
  94. package/dist/lib/components/realtime/interactive-component/component-spec-content.js +39 -0
  95. package/dist/lib/components/realtime/interactive-component/component-spec-content.js.map +1 -0
  96. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.d.ts +183 -0
  97. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.d.ts.map +1 -0
  98. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.js +761 -0
  99. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.js.map +1 -0
  100. package/dist/lib/components/realtime/interactive-component/interactive-component-config.d.ts +25 -0
  101. package/dist/lib/components/realtime/interactive-component/interactive-component-config.d.ts.map +1 -0
  102. package/dist/lib/components/realtime/interactive-component/interactive-component-config.js +57 -0
  103. package/dist/lib/components/realtime/interactive-component/interactive-component-config.js.map +1 -0
  104. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.d.ts +40 -0
  105. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.d.ts.map +1 -0
  106. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.js +97 -0
  107. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.js.map +1 -0
  108. package/dist/lib/components/realtime/interactive-component/interactive-component-types.d.ts +144 -0
  109. package/dist/lib/components/realtime/interactive-component/interactive-component-types.d.ts.map +1 -0
  110. package/dist/lib/components/realtime/interactive-component/interactive-component-types.js +57 -0
  111. package/dist/lib/components/realtime/interactive-component/interactive-component-types.js.map +1 -0
  112. package/dist/lib/components/realtime/interactive-component/react-component-handle.d.ts +36 -0
  113. package/dist/lib/components/realtime/interactive-component/react-component-handle.d.ts.map +1 -0
  114. package/dist/lib/components/realtime/interactive-component/react-component-handle.js +55 -0
  115. package/dist/lib/components/realtime/interactive-component/react-component-handle.js.map +1 -0
  116. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.d.ts +55 -0
  117. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.d.ts.map +1 -0
  118. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.js +210 -0
  119. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.js.map +1 -0
  120. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.d.ts +32 -0
  121. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.d.ts.map +1 -0
  122. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js +90 -0
  123. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js.map +1 -0
  124. package/dist/lib/components/realtime/media/media-channel.d.ts +7 -0
  125. package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -1
  126. package/dist/lib/components/realtime/media/media-channel.js +28 -1
  127. package/dist/lib/components/realtime/media/media-channel.js.map +1 -1
  128. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +8 -1
  129. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  130. package/dist/lib/components/realtime/realtime-agent-banner.component.js +89 -71
  131. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  132. package/dist/lib/components/realtime/realtime-agent-orb.component.d.ts +21 -0
  133. package/dist/lib/components/realtime/realtime-agent-orb.component.d.ts.map +1 -0
  134. package/dist/lib/components/realtime/realtime-agent-orb.component.js +49 -0
  135. package/dist/lib/components/realtime/realtime-agent-orb.component.js.map +1 -0
  136. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +44 -11
  137. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
  138. package/dist/lib/components/realtime/realtime-agent-picker.component.js +162 -50
  139. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
  140. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +8 -2
  141. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -1
  142. package/dist/lib/components/realtime/realtime-audio-visuals.js +14 -18
  143. package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -1
  144. package/dist/lib/components/realtime/realtime-composer.component.d.ts +42 -2
  145. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
  146. package/dist/lib/components/realtime/realtime-composer.component.js +137 -102
  147. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  148. package/dist/lib/components/realtime/realtime-perception-chip.component.d.ts +71 -0
  149. package/dist/lib/components/realtime/realtime-perception-chip.component.d.ts.map +1 -0
  150. package/dist/lib/components/realtime/realtime-perception-chip.component.js +221 -0
  151. package/dist/lib/components/realtime/realtime-perception-chip.component.js.map +1 -0
  152. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +264 -22
  153. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  154. package/dist/lib/components/realtime/realtime-session-overlay.component.js +851 -135
  155. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  156. package/dist/lib/components/realtime/realtime-surface-placement-prefs.d.ts +14 -0
  157. package/dist/lib/components/realtime/realtime-surface-placement-prefs.d.ts.map +1 -0
  158. package/dist/lib/components/realtime/realtime-surface-placement-prefs.js +14 -0
  159. package/dist/lib/components/realtime/realtime-surface-placement-prefs.js.map +1 -0
  160. package/dist/lib/components/realtime/realtime-surface-stage.model.d.ts +74 -0
  161. package/dist/lib/components/realtime/realtime-surface-stage.model.d.ts.map +1 -0
  162. package/dist/lib/components/realtime/realtime-surface-stage.model.js +171 -0
  163. package/dist/lib/components/realtime/realtime-surface-stage.model.js.map +1 -0
  164. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +71 -13
  165. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
  166. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +232 -73
  167. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
  168. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +5 -0
  169. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
  170. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +8 -0
  171. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
  172. package/dist/lib/components/realtime/realtime-ui-config.d.ts +12 -2
  173. package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -1
  174. package/dist/lib/components/realtime/realtime-ui-config.js +5 -1
  175. package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -1
  176. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +10 -1
  177. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
  178. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +42 -2
  179. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
  180. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts +20 -3
  181. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts.map +1 -1
  182. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js +44 -10
  183. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js.map +1 -1
  184. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +28 -44
  185. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
  186. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +76 -162
  187. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
  188. package/dist/lib/components/search/search-panel.component.d.ts +2 -0
  189. package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
  190. package/dist/lib/components/search/search-panel.component.js +25 -12
  191. package/dist/lib/components/search/search-panel.component.js.map +1 -1
  192. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +22 -31
  193. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  194. package/dist/lib/components/workspace/conversation-workspace.component.js +50 -63
  195. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  196. package/dist/lib/conversations.module.d.ts +30 -29
  197. package/dist/lib/conversations.module.d.ts.map +1 -1
  198. package/dist/lib/conversations.module.js +27 -5
  199. package/dist/lib/conversations.module.js.map +1 -1
  200. package/dist/lib/events/chat-events.d.ts +25 -0
  201. package/dist/lib/events/chat-events.d.ts.map +1 -1
  202. package/dist/lib/events/chat-events.js +36 -0
  203. package/dist/lib/events/chat-events.js.map +1 -1
  204. package/dist/lib/models/agent-turn.model.d.ts +5 -0
  205. package/dist/lib/models/agent-turn.model.d.ts.map +1 -1
  206. package/dist/lib/models/agent-turn.model.js.map +1 -1
  207. package/dist/lib/services/agent-state.service.d.ts +34 -8
  208. package/dist/lib/services/agent-state.service.d.ts.map +1 -1
  209. package/dist/lib/services/agent-state.service.js +82 -29
  210. package/dist/lib/services/agent-state.service.js.map +1 -1
  211. package/dist/lib/services/artifact-state.service.d.ts +0 -9
  212. package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
  213. package/dist/lib/services/artifact-state.service.js +1 -32
  214. package/dist/lib/services/artifact-state.service.js.map +1 -1
  215. package/dist/lib/services/browser-realtime-media-host.d.ts +12 -0
  216. package/dist/lib/services/browser-realtime-media-host.d.ts.map +1 -1
  217. package/dist/lib/services/browser-realtime-media-host.js +19 -0
  218. package/dist/lib/services/browser-realtime-media-host.js.map +1 -1
  219. package/dist/lib/services/browser-recording-unload-guard.d.ts +30 -0
  220. package/dist/lib/services/browser-recording-unload-guard.d.ts.map +1 -0
  221. package/dist/lib/services/browser-recording-unload-guard.js +43 -0
  222. package/dist/lib/services/browser-recording-unload-guard.js.map +1 -0
  223. package/dist/lib/services/conversation-agent.service.d.ts +35 -11
  224. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  225. package/dist/lib/services/conversation-agent.service.js +65 -20
  226. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  227. package/dist/lib/services/conversation-detail-window.store.d.ts +22 -4
  228. package/dist/lib/services/conversation-detail-window.store.d.ts.map +1 -1
  229. package/dist/lib/services/conversation-detail-window.store.js +50 -9
  230. package/dist/lib/services/conversation-detail-window.store.js.map +1 -1
  231. package/dist/lib/services/conversation-naming.d.ts +72 -22
  232. package/dist/lib/services/conversation-naming.d.ts.map +1 -1
  233. package/dist/lib/services/conversation-naming.js +84 -10
  234. package/dist/lib/services/conversation-naming.js.map +1 -1
  235. package/dist/lib/services/data-cache.service.d.ts +13 -5
  236. package/dist/lib/services/data-cache.service.d.ts.map +1 -1
  237. package/dist/lib/services/data-cache.service.js +39 -19
  238. package/dist/lib/services/data-cache.service.js.map +1 -1
  239. package/dist/lib/services/export.service.d.ts +26 -9
  240. package/dist/lib/services/export.service.d.ts.map +1 -1
  241. package/dist/lib/services/export.service.js +61 -18
  242. package/dist/lib/services/export.service.js.map +1 -1
  243. package/dist/lib/services/realtime-audio-recorder.d.ts +33 -5
  244. package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -1
  245. package/dist/lib/services/realtime-audio-recorder.js +71 -11
  246. package/dist/lib/services/realtime-audio-recorder.js.map +1 -1
  247. package/dist/lib/services/realtime-pairing.d.ts +10 -5
  248. package/dist/lib/services/realtime-pairing.d.ts.map +1 -1
  249. package/dist/lib/services/realtime-pairing.js +15 -6
  250. package/dist/lib/services/realtime-pairing.js.map +1 -1
  251. package/dist/lib/services/realtime-session.service.d.ts +3 -2
  252. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  253. package/dist/lib/services/realtime-session.service.js +7 -2
  254. package/dist/lib/services/realtime-session.service.js.map +1 -1
  255. package/dist/lib/services/search.service.d.ts +7 -2
  256. package/dist/lib/services/search.service.d.ts.map +1 -1
  257. package/dist/lib/services/search.service.js +13 -4
  258. package/dist/lib/services/search.service.js.map +1 -1
  259. package/dist/lib/util/frame-zone.d.ts +10 -0
  260. package/dist/lib/util/frame-zone.d.ts.map +1 -0
  261. package/dist/lib/util/frame-zone.js +10 -0
  262. package/dist/lib/util/frame-zone.js.map +1 -0
  263. package/dist/lib/utils/conversation-branching.d.ts +4 -0
  264. package/dist/lib/utils/conversation-branching.d.ts.map +1 -0
  265. package/dist/lib/utils/conversation-branching.js +5 -0
  266. package/dist/lib/utils/conversation-branching.js.map +1 -0
  267. package/dist/lib/utils/conversation-forks.d.ts +315 -0
  268. package/dist/lib/utils/conversation-forks.d.ts.map +1 -0
  269. package/dist/lib/utils/conversation-forks.js +456 -0
  270. package/dist/lib/utils/conversation-forks.js.map +1 -0
  271. package/dist/public-api.d.ts +23 -1
  272. package/dist/public-api.d.ts.map +1 -1
  273. package/dist/public-api.js +30 -1
  274. package/dist/public-api.js.map +1 -1
  275. package/package.json +37 -32
  276. package/dist/lib/components/thread/thread-panel.component.d.ts +0 -126
  277. package/dist/lib/components/thread/thread-panel.component.d.ts.map +0 -1
  278. package/dist/lib/components/thread/thread-panel.component.js +0 -440
  279. package/dist/lib/components/thread/thread-panel.component.js.map +0 -1
@@ -12,8 +12,10 @@ import { ConversationUtility, agentFailureDisposition, agentFailureMessage } fro
12
12
  import { MentionAutocompleteService } from '../../services/mention-autocomplete.service';
13
13
  import { PlanModePreference } from '../../utils/plan-mode-preference';
14
14
  import { MJNotificationService } from '@memberjunction/ng-notifications';
15
+ import { ConversationCallStartOptions } from '../realtime/capture/realtime-capture-channel';
15
16
  import { BuildRealtimeConfigOverridesJson, FilterRealtimeCoAgents, LoadCoAgentPairings, PairingsAllowTarget } from '../../services/realtime-pairing';
16
17
  import { UUIDsEqual } from '@memberjunction/global';
18
+ import { InjectFrameZone } from '../../util/frame-zone';
17
19
  import * as i0 from "@angular/core";
18
20
  import * as i1 from "../../services/dialog.service";
19
21
  import * as i2 from "../../services/toast.service";
@@ -49,6 +51,8 @@ function MessageInputComponent_ng_template_5_Template(rf, ctx) { if (rf & 1) {
49
51
  const ctx_r0 = i0.ɵɵnextContext();
50
52
  i0.ɵɵproperty("Provider", ctx_r0.ProviderToUse)("CurrentUser", ctx_r0.currentUser)("Agents", ctx_r0.voicePickerAgents)("DefaultAgentId", ctx_r0.voicePickerDefaultAgentId)("CoAgents", ctx_r0.voicePickerCoAgents)("DefaultCoAgentId", ctx_r0.voicePickerDefaultCoAgentId);
51
53
  } }
54
+ /** Streamed-delta render cadence where no animation frame will come (hidden tab, no rAF). */
55
+ const STREAMED_FRAME_FALLBACK_MS = 50;
52
56
  export class MessageInputComponent extends BaseAngularComponent {
53
57
  dialogService;
54
58
  toastService;
@@ -102,6 +106,17 @@ export class MessageInputComponent extends BaseAngularComponent {
102
106
  * Blocks sending. Distinct from {@link Disabled}, which means the composer is busy.
103
107
  */
104
108
  ReadOnly = false;
109
+ // ── The send slot as a stop control (pass-through to the composer; the chat area decides) ──
110
+ /** What the send slot is doing; see `SendSlotMode` in `@memberjunction/ng-composer`. */
111
+ SendSlotMode = 'send';
112
+ /** How many things a stop would stop; above 1 the slot reads "Stop all". */
113
+ StopCount = 0;
114
+ /** Tooltip and accessible name of the slot in `stop` mode. */
115
+ StopLabel = 'Stop';
116
+ /** Status line shown bottom-left inside the composer while non-null. */
117
+ StatusText = null;
118
+ /** Elapsed time after the status text, kept out of the live region and dropped on narrow screens. */
119
+ StatusElapsed = null;
105
120
  Placeholder = 'Type a message... (Ctrl+Enter to send)';
106
121
  /** @deprecated Use {@link Placeholder}. */
107
122
  set placeholder(value) {
@@ -498,6 +513,16 @@ export class MessageInputComponent extends BaseAngularComponent {
498
513
  * reading past the floor). Null (the default) reads the whole conversation.
499
514
  */
500
515
  AgentHistoryFrom = null;
516
+ /**
517
+ * The fork new messages from this composer go to; null (the default) is Main. The agent turn of a
518
+ * message, and the agent-history reads it makes, use the message's branch.
519
+ */
520
+ TargetBranchID = null;
521
+ /**
522
+ * When set, called once at the start of each send to get the branch of the new user row; undefined
523
+ * stops the send and nothing is written. A host uses it to create a draft fork on its first send.
524
+ */
525
+ ResolveTargetBranch = null;
501
526
  /**
502
527
  * Runs agent turns on the host's server instead of MJ's own path. The chat area still picks
503
528
  * the agent and fires {@link BeforeAgentTurn}; it then calls the handler once per turn, before
@@ -525,6 +550,8 @@ export class MessageInputComponent extends BaseAngularComponent {
525
550
  * `MJ: AI Prompt Runs` row, even when the answer comes too late to be used.
526
551
  */
527
552
  EnableDecisionRouting = false;
553
+ /** The send slot was clicked in `stop` mode; the chat area stops the run(s). */
554
+ StopClicked = new EventEmitter();
528
555
  MessageSent = new EventEmitter();
529
556
  /**
530
557
  * @deprecated Use {@link MessageSent}.
@@ -534,6 +561,14 @@ export class MessageInputComponent extends BaseAngularComponent {
534
561
  * initialise in order, and the other way round this captures undefined.
535
562
  */
536
563
  messageSent = this.MessageSent;
564
+ /**
565
+ * A streamed final-response delta was applied to an in-progress message: `Message` holds the
566
+ * full reply so far. Informational, so no Before/After pair; coalesced to at most one emission
567
+ * per animation frame; silent once the message has settled, because the completion path owns
568
+ * the final render. Hosts refresh the bubble in place on this, while {@link MessageSent} keeps
569
+ * announcing new and status-changed messages.
570
+ */
571
+ MessageStreamed = new EventEmitter();
537
572
  AgentResponse = new EventEmitter();
538
573
  /**
539
574
  * @deprecated Use {@link AgentResponse}.
@@ -850,6 +885,14 @@ export class MessageInputComponent extends BaseAngularComponent {
850
885
  setTimeout(() => this.InputBox?.focus(), 50);
851
886
  }
852
887
  }
888
+ /**
889
+ * Puts the text of a send that did not go out back into the composer. Text the composer holds
890
+ * already stays first, and the returned text follows it on a new line.
891
+ */
892
+ restoreUnsentText(text) {
893
+ const current = this.GetSerializedDraft();
894
+ this.SetDraft(current ? `${current}\n${text}` : text);
895
+ }
853
896
  IsSending = false;
854
897
  /** @deprecated Use {@link IsSending}. */
855
898
  get isSending() {
@@ -906,6 +949,7 @@ export class MessageInputComponent extends BaseAngularComponent {
906
949
  }
907
950
  // Track completion timestamps to prevent race conditions with late progress updates
908
951
  completionTimestamps = new Map();
952
+ ngZone = InjectFrameZone();
909
953
  // Track registered streaming callbacks for cleanup
910
954
  registeredCallbacks = new Map();
911
955
  // After a post-ACK disconnect, keep observing ConversationDetail.Status until
@@ -1277,11 +1321,11 @@ export class MessageInputComponent extends BaseAngularComponent {
1277
1321
  this.VoicePickerDefaultCoAgentId = await this.loadPersistedCoAgentId();
1278
1322
  this.ShowRealtimeAgentPicker = true;
1279
1323
  }
1280
- /** User confirmed an agent (+ optional co-agent / voice model) in the voice picker — start the call. */
1324
+ /** User confirmed an agent (+ optional co-agent / voice model / voice and its avatar) in the voice picker — start the call. */
1281
1325
  async OnRealtimeAgentPicked(pick) {
1282
1326
  this.ShowRealtimeAgentPicker = false;
1283
1327
  this.persistCoAgentChoice(pick.CoAgentId);
1284
- await this.startRealtimeWithAgent(pick.Agent.ID, pick.Agent.Name || this.resolveRealtimeAgentName(), pick.PreferredModelId, pick.CoAgentId, BuildRealtimeConfigOverridesJson(pick.PreferredModelId, pick.PreferredVoice), pick.RecordingConsent);
1328
+ await this.startRealtimeWithAgent(pick.Agent.ID, pick.Agent.Name || this.resolveRealtimeAgentName(), pick.PreferredModelId, pick.CoAgentId, BuildRealtimeConfigOverridesJson(pick.PreferredModelId, pick.PreferredVoice, pick.PreferredAvatarId), pick.RecordingConsent);
1285
1329
  }
1286
1330
  /** @deprecated Use {@link OnRealtimeAgentPicked}. */
1287
1331
  async onRealtimeAgentPicked(pick) {
@@ -1352,7 +1396,7 @@ export class MessageInputComponent extends BaseAngularComponent {
1352
1396
  * uses exactly that model or fails with a clear reason (no silent fallback) — and is
1353
1397
  * mirrored into `configOverridesJson` (`{"realtime":{"modelPreference":…}}`, the
1354
1398
  * pinned override envelope). An explicit co-agent choice (picker pick or persisted
1355
- * preference) rides along as `coAgentId`.
1399
+ * preference) rides along as `coAgentId`. The session runs on {@link TargetBranchID}.
1356
1400
  *
1357
1401
  * Interactive-channel tools (e.g. the live whiteboard's `Whiteboard_*` set) are NOT
1358
1402
  * passed here — the session service resolves the active channel plugins from the
@@ -1364,7 +1408,9 @@ export class MessageInputComponent extends BaseAngularComponent {
1364
1408
  // App awareness: the app the session runs in + the live app-context snapshot (where the
1365
1409
  // user is, what they see, capability manifest) — drives the server-side app cascade + the
1366
1410
  // mint-time prompt injection, and seeds the ClientContextChannel's streaming.
1367
- this.ApplicationId, this.AppContext);
1411
+ this.ApplicationId, this.AppContext,
1412
+ // The channels this UI brings to its calls (the camera and screen share), on the fork it posts to.
1413
+ { ...ConversationCallStartOptions(), ConversationBranchID: this.TargetBranchID });
1368
1414
  }
1369
1415
  catch (error) {
1370
1416
  console.error('Failed to start voice session:', error);
@@ -1414,11 +1460,51 @@ export class MessageInputComponent extends BaseAngularComponent {
1414
1460
  * Create a progress callback for a specific message ID.
1415
1461
  * This callback will be invoked by the streaming service when progress updates arrive.
1416
1462
  */
1463
+ /**
1464
+ * Emits {@link MessageStreamed} for a coalesced frame of streamed deltas, unless the message
1465
+ * settled in the meantime: then the completion path has already reconciled the bubble and a
1466
+ * late frame has nothing to add. Settled is read off the captured entity's status and off the
1467
+ * callback registration, which markMessageComplete drops: a frame can sleep through completion
1468
+ * in a hidden tab, and the registration outlasts every other trace of it.
1469
+ */
1470
+ emitStreamedUpdate(messageId, message) {
1471
+ if (message.Status !== 'In-Progress' || !this.registeredCallbacks.has(messageId)) {
1472
+ return;
1473
+ }
1474
+ if (this.MessageStreamed.observed) {
1475
+ this.MessageStreamed.emit(message);
1476
+ }
1477
+ else {
1478
+ // TRANSITIONAL: a host that still binds only the old output keeps streaming on MessageSent at
1479
+ // the coalesced cadence. Remove once direct hosts bind MessageStreamed. Re-enters the zone
1480
+ // because MessageSent handlers replace template-bound state.
1481
+ this.ngZone.run(() => this.MessageSent.emit(message));
1482
+ }
1483
+ }
1484
+ /**
1485
+ * Runs `callback` on the next animation frame, outside Angular: the in-place render checks its
1486
+ * own child view, so a zone-triggered application tick per frame would be pure waste, and the
1487
+ * paths that do touch template-bound state re-enter the zone themselves. A hidden tab never
1488
+ * paints a frame, so there (and without requestAnimationFrame) a short timer stands in; the
1489
+ * browser throttles it in the background, the right cadence for a bubble nobody is looking at.
1490
+ */
1491
+ scheduleFrame(callback) {
1492
+ this.ngZone.runOutsideAngular(() => {
1493
+ if (typeof requestAnimationFrame === 'function' && !document.hidden) {
1494
+ requestAnimationFrame(callback);
1495
+ }
1496
+ else {
1497
+ setTimeout(callback, STREAMED_FRAME_FALLBACK_MS);
1498
+ }
1499
+ });
1500
+ }
1417
1501
  createMessageProgressCallback(messageId) {
1418
1502
  // Resolve the message once and reuse it for the callback's lifetime: streamed
1419
1503
  // final-response updates arrive per content delta, and re-awaiting the cache on
1420
1504
  // every delta both wastes work and (on a cold cache) races concurrent loads.
1421
1505
  let resolvedMessage = null;
1506
+ // One pending frame per message: deltas arriving inside a frame collapse into one emission.
1507
+ let streamedFramePending = false;
1422
1508
  return async (progress) => {
1423
1509
  try {
1424
1510
  // Get message from cache (single source of truth)
@@ -1444,9 +1530,15 @@ export class MessageInputComponent extends BaseAngularComponent {
1444
1530
  // bubble with the server-saved final message, so no append/merge is needed here.
1445
1531
  if (progress.streaming) {
1446
1532
  message.Message = progress.streaming.content;
1447
- this.MessageSent.emit(message);
1448
- // Keep the tasks dropdown on a stable status line rather than the growing reply text.
1449
- this.activeTasks.updateStatusByConversationDetailId(message.ID, 'Responding…');
1533
+ if (!streamedFramePending) {
1534
+ streamedFramePending = true;
1535
+ this.scheduleFrame(() => {
1536
+ streamedFramePending = false;
1537
+ this.emitStreamedUpdate(messageId, message);
1538
+ });
1539
+ // Keep the tasks dropdown on a stable status line rather than the growing reply text.
1540
+ this.activeTasks.updateStatusByConversationDetailId(message.ID, 'Responding…');
1541
+ }
1450
1542
  return;
1451
1543
  }
1452
1544
  // Default: plain message (used by RunAIAgentResolver and TaskOrchestrator without step info)
@@ -1538,7 +1630,12 @@ export class MessageInputComponent extends BaseAngularComponent {
1538
1630
  // Store attachments locally since we'll clear them after send
1539
1631
  const attachmentsToSave = [...this.pendingAttachments];
1540
1632
  try {
1541
- const messageDetail = await this.createMessageDetailFromText(text?.trim() || '');
1633
+ const branchId = await this.resolveSendBranch(undefined);
1634
+ if (branchId === undefined) {
1635
+ this.restoreUnsentText(text);
1636
+ return;
1637
+ }
1638
+ const messageDetail = await this.createMessageDetailFromText(text?.trim() || '', branchId);
1542
1639
  const saved = await messageDetail.Save();
1543
1640
  if (saved) {
1544
1641
  // Save attachments if any were pending
@@ -1614,7 +1711,11 @@ export class MessageInputComponent extends BaseAngularComponent {
1614
1711
  return;
1615
1712
  this.IsSending = true;
1616
1713
  try {
1617
- const messageDetail = await this.createMessageDetail();
1714
+ const branchId = await this.resolveSendBranch(undefined);
1715
+ if (branchId === undefined) {
1716
+ return;
1717
+ }
1718
+ const messageDetail = await this.createMessageDetail(branchId);
1618
1719
  const saved = await messageDetail.Save();
1619
1720
  if (saved) {
1620
1721
  await this.handleSuccessfulSend(messageDetail);
@@ -1644,18 +1745,28 @@ export class MessageInputComponent extends BaseAngularComponent {
1644
1745
  * tick — the `attachmentsChanged` event chain hasn't propagated yet, so
1645
1746
  * `this.pendingAttachments` may not contain the attachment. Pass it in
1646
1747
  * explicitly and we merge + dedupe (by `id`) before saving.
1748
+ *
1749
+ * `options.IsResend` sends an edited copy of an earlier message. The composer's draft is left
1750
+ * alone: only `extraAttachments` are saved with the message, and the pending attachments and
1751
+ * editor text are not cleared. The send never counts as the conversation's first message, so
1752
+ * it does not name the conversation or claim a pending Plan Mode choice.
1753
+ *
1754
+ * `options.TargetBranchID` writes the message to that fork (null is Main) instead of the
1755
+ * composer's own target.
1647
1756
  */
1648
- async SendMessageWithText(text, extraAttachments) {
1757
+ async SendMessageWithText(text, extraAttachments, options) {
1649
1758
  if (this.ReadOnly) {
1650
1759
  return false;
1651
1760
  }
1761
+ const isResend = options?.IsResend === true;
1762
+ const draftAttachments = isResend ? [] : this.pendingAttachments;
1652
1763
  const merged = (() => {
1653
1764
  if (!extraAttachments || extraAttachments.length === 0) {
1654
- return [...this.pendingAttachments];
1765
+ return [...draftAttachments];
1655
1766
  }
1656
1767
  const seen = new Set();
1657
1768
  const out = [];
1658
- for (const a of [...this.pendingAttachments, ...extraAttachments]) {
1769
+ for (const a of [...draftAttachments, ...extraAttachments]) {
1659
1770
  if (seen.has(a.id))
1660
1771
  continue;
1661
1772
  seen.add(a.id);
@@ -1674,11 +1785,16 @@ export class MessageInputComponent extends BaseAngularComponent {
1674
1785
  this.IsSending = true;
1675
1786
  const attachmentsToSave = merged;
1676
1787
  try {
1788
+ const branchId = await this.resolveSendBranch(options?.TargetBranchID);
1789
+ if (branchId === undefined) {
1790
+ return false;
1791
+ }
1677
1792
  const detail = await this.dataCache.createConversationDetail(this.CurrentUser);
1678
1793
  detail.ConversationID = this.ConversationId;
1679
1794
  detail.Message = text?.trim() || '';
1680
1795
  detail.Role = 'User';
1681
1796
  detail.UserID = this.CurrentUser.ID; // Set the user who sent the message
1797
+ detail.BranchID = branchId;
1682
1798
  if (this.ParentMessageId) {
1683
1799
  detail.ParentID = this.ParentMessageId;
1684
1800
  }
@@ -1719,16 +1835,18 @@ export class MessageInputComponent extends BaseAngularComponent {
1719
1835
  return false;
1720
1836
  }
1721
1837
  }
1722
- // Clear pending attachments after successful send
1723
- this.pendingAttachments = [];
1724
- // Also clear the mention editor's content + its own attachments list.
1725
- // The user-initiated send path (MessageInputBoxComponent.onSendClick)
1726
- // calls mentionEditor.clear() — we bypass that path here, so the chips
1727
- // would otherwise stay on screen after the message goes out.
1728
- this.InputBox?.mentionEditor?.clear();
1838
+ if (!isResend) {
1839
+ // Clear pending attachments after successful send
1840
+ this.pendingAttachments = [];
1841
+ // Also clear the mention editor's content + its own attachments list.
1842
+ // The user-initiated send path (MessageInputBoxComponent.onSendClick)
1843
+ // calls mentionEditor.clear() — we bypass that path here, so the chips
1844
+ // would otherwise stay on screen after the message goes out.
1845
+ this.InputBox?.mentionEditor?.clear();
1846
+ }
1729
1847
  this.MessageSent.emit(detail);
1730
1848
  const mentionResult = this.parseMentionsFromMessage(detail.Message);
1731
- const isFirstMessage = this.ConversationHistory.length === 0;
1849
+ const isFirstMessage = !isResend && this.ConversationHistory.length === 0;
1732
1850
  await this.routeMessage(detail, mentionResult, isFirstMessage);
1733
1851
  return true;
1734
1852
  }
@@ -1750,28 +1868,86 @@ export class MessageInputComponent extends BaseAngularComponent {
1750
1868
  return this.SendMessageWithText(text, extraAttachments);
1751
1869
  }
1752
1870
  /**
1753
- * Creates and configures a new conversation detail message
1871
+ * Routes an existing user message through the agent path again, so the agent writes a new reply
1872
+ * on `targetBranchId` (default: the message's own branch). No message is saved, and the
1873
+ * composer's draft and pending attachments are left alone. The rerun never counts as the
1874
+ * conversation's first message. `IsSending` stays true until the agent turn ends, so no other
1875
+ * send starts meanwhile.
1876
+ *
1877
+ * @returns false, with no agent turn, when the composer is read-only or already sending.
1878
+ */
1879
+ async RerunAgentForMessage(userMessage, targetBranchId) {
1880
+ if (this.ReadOnly || this.IsSending) {
1881
+ return false;
1882
+ }
1883
+ this.IsSending = true;
1884
+ try {
1885
+ const mentionResult = this.parseMentionsFromMessage(userMessage.Message || '');
1886
+ await this.routeMessage(userMessage, mentionResult, false, targetBranchId !== undefined ? targetBranchId : (userMessage.BranchID ?? null));
1887
+ return true;
1888
+ }
1889
+ finally {
1890
+ this.IsSending = false;
1891
+ }
1892
+ }
1893
+ /**
1894
+ * The branch of a new user row: `explicit` when given, else the {@link ResolveTargetBranch} answer
1895
+ * when set, else {@link TargetBranchID}. Undefined when the resolver declined or failed.
1896
+ */
1897
+ async resolveSendBranch(explicit) {
1898
+ if (explicit !== undefined) {
1899
+ return explicit;
1900
+ }
1901
+ const resolve = this.ResolveTargetBranch;
1902
+ if (!resolve) {
1903
+ return this.TargetBranchID ?? null;
1904
+ }
1905
+ try {
1906
+ return await resolve();
1907
+ }
1908
+ catch (error) {
1909
+ console.error('Could not resolve the fork of the message:', error);
1910
+ return undefined;
1911
+ }
1912
+ }
1913
+ /**
1914
+ * A new AI row of an agent turn: in `conversationId`, on the turn's branch `branchId` (null is
1915
+ * Main), visible. The caller sets Message, ParentID, Status and AgentID, then saves it.
1916
+ */
1917
+ async createTurnRow(conversationId, branchId) {
1918
+ const row = await this.dataCache.createConversationDetail(this.CurrentUser);
1919
+ row.ConversationID = conversationId;
1920
+ row.BranchID = branchId;
1921
+ row.Role = 'AI';
1922
+ row.HiddenToUser = false;
1923
+ return row;
1924
+ }
1925
+ /**
1926
+ * Creates and configures a new conversation detail message on `branchId` (null is Main)
1754
1927
  */
1755
- async createMessageDetail() {
1928
+ async createMessageDetail(branchId) {
1756
1929
  const detail = await this.dataCache.createConversationDetail(this.CurrentUser);
1757
1930
  detail.ConversationID = this.ConversationId;
1758
1931
  detail.Message = this.MessageText.trim();
1759
1932
  detail.Role = 'User';
1760
1933
  detail.UserID = this.CurrentUser.ID; // Set the user who sent the message
1934
+ detail.BranchID = branchId;
1761
1935
  if (this.ParentMessageId) {
1762
1936
  detail.ParentID = this.ParentMessageId;
1763
1937
  }
1764
1938
  return detail;
1765
1939
  }
1766
1940
  /**
1767
- * Creates and configures a new conversation detail message from provided text
1941
+ * Creates and configures a new conversation detail message from provided text, on `branchId`
1942
+ * (null is Main)
1768
1943
  */
1769
- async createMessageDetailFromText(text) {
1944
+ async createMessageDetailFromText(text, branchId) {
1770
1945
  const detail = await this.dataCache.createConversationDetail(this.CurrentUser);
1771
1946
  detail.ConversationID = this.ConversationId;
1772
1947
  detail.Message = text;
1773
1948
  detail.Role = 'User';
1774
1949
  detail.UserID = this.CurrentUser.ID; // Set the user who sent the message
1950
+ detail.BranchID = branchId;
1775
1951
  if (this.ParentMessageId) {
1776
1952
  detail.ParentID = this.ParentMessageId;
1777
1953
  }
@@ -1805,8 +1981,13 @@ export class MessageInputComponent extends BaseAngularComponent {
1805
1981
  * last agent's place ({@link decideAgentRouting}).
1806
1982
  * {@link BeforeAgentTurn} is then fired once, before any reply row exists, and the turn runs on
1807
1983
  * MJ's path or through the host's {@link AgentTurnHandler}.
1984
+ *
1985
+ * `turnBranchId` overrides the turn's branch (a rerun into a new fork); else the turn runs on
1986
+ * the message's branch. The branch is fixed here and passed down the turn, so every row and
1987
+ * agent-history read of this turn uses it, whatever the composer targets later.
1808
1988
  */
1809
- async routeMessage(messageDetail, mentionResult, isFirstMessage) {
1989
+ async routeMessage(messageDetail, mentionResult, isFirstMessage, turnBranchId) {
1990
+ const branchId = turnBranchId !== undefined ? turnBranchId : (messageDetail.BranchID ?? null);
1810
1991
  // A Plan Mode choice made on the new-conversation composer (no conversation yet) lives in a
1811
1992
  // pending bucket — the FIRST routed message claims it onto the real conversation so the
1812
1993
  // toggle carries across the empty-state → chat-area transition without bleeding into other
@@ -1832,7 +2013,7 @@ export class MessageInputComponent extends BaseAngularComponent {
1832
2013
  // another conversation, and the chat area then rebinds its history and pinned agent, so a
1833
2014
  // read after the routing decision could see another conversation's state (or none).
1834
2015
  const candidates = this.agentTurnCandidates(this.agentMentionIds(mentionResult));
1835
- const routing = await this.decideAgentRouting(messageDetail, candidates);
2016
+ const routing = await this.decideAgentRouting(messageDetail, candidates, branchId);
1836
2017
  const target = this.resolveAgentTurnTarget(candidates, routing);
1837
2018
  if (!target) {
1838
2019
  await this.finishWithoutAgentTurn(messageDetail, 'NoAgent');
@@ -1843,7 +2024,7 @@ export class MessageInputComponent extends BaseAngularComponent {
1843
2024
  await this.finishWithoutAgentTurn(messageDetail, 'Declined');
1844
2025
  return;
1845
2026
  }
1846
- await this.runAgentTurn(messageDetail, mentionResult, turn, routing);
2027
+ await this.runAgentTurn(messageDetail, mentionResult, turn, branchId, routing);
1847
2028
  }
1848
2029
  /**
1849
2030
  * Asks the routing decision for this message when {@link EnableDecisionRouting} is on and the
@@ -1851,8 +2032,9 @@ export class MessageInputComponent extends BaseAngularComponent {
1851
2032
  * when anything fails: the message then keeps today's routing.
1852
2033
  *
1853
2034
  * @param candidates The turn's candidates, read before any await (see {@link routeMessage}).
2035
+ * @param branchId The turn's branch (null is Main); the artifact versions are read on its path.
1854
2036
  */
1855
- async decideAgentRouting(message, candidates) {
2037
+ async decideAgentRouting(message, candidates, branchId) {
1856
2038
  const continuityAgentId = candidates.ContinuityAgentId;
1857
2039
  const qualifies = ShouldRunRoutingDecision({
1858
2040
  Enabled: this.EnableDecisionRouting,
@@ -1870,7 +2052,7 @@ export class MessageInputComponent extends BaseAngularComponent {
1870
2052
  if (!CanAskRoutingDecision(input)) {
1871
2053
  return null;
1872
2054
  }
1873
- input.ArtifactVersions = await this.loadRoutingArtifactVersions(message.ConversationID, input.Participants);
2055
+ input.ArtifactVersions = await this.loadRoutingArtifactVersions(message.ConversationID, branchId, input.Participants);
1874
2056
  const outcome = await RunRoutingDecision(input, params => this.agentService.RunDecision(params));
1875
2057
  LogStatusEx({
1876
2058
  message: `Decision routing: ${outcome.Verdict}, ${outcome.Reason} (prompt run ${outcome.PromptRunID ?? 'none'})`,
@@ -1911,11 +2093,11 @@ export class MessageInputComponent extends BaseAngularComponent {
1911
2093
  AllowedAgentIDs: this.AllowedAgentIDs
1912
2094
  };
1913
2095
  }
1914
- /** Every participant's artifact versions in this conversation, for the artifact question. */
1915
- async loadRoutingArtifactVersions(conversationId, participants) {
2096
+ /** Every participant's artifact versions on the path of `branchId` in this conversation, for the artifact question. */
2097
+ async loadRoutingArtifactVersions(conversationId, branchId, participants) {
1916
2098
  const artifactsByAgent = await Promise.all(participants.map(async (participant) => ({
1917
2099
  Agent: participant.Agent,
1918
- Artifacts: await this.agentService.FindAgentArtifacts(conversationId, participant.Agent.ID, this.AgentHistoryFrom)
2100
+ Artifacts: await this.agentService.FindAgentArtifacts(conversationId, participant.Agent.ID, this.AgentHistoryFrom, branchId)
1919
2101
  })));
1920
2102
  return BuildRoutingArtifactVersions(artifactsByAgent);
1921
2103
  }
@@ -1983,23 +2165,26 @@ export class MessageInputComponent extends BaseAngularComponent {
1983
2165
  * Runs a turn that {@link BeforeAgentTurn} let through, on the host's handler or MJ's path.
1984
2166
  * The routing decision, when there was one, supplies the artifact version the turn's agent
1985
2167
  * continues from; a host's handler receives it as `TargetArtifactVersionId`.
2168
+ *
2169
+ * @param branchId The turn's branch (null is Main): every row the turn writes and every
2170
+ * agent-history read it makes uses it.
1986
2171
  */
1987
- async runAgentTurn(userMessage, mentionResult, turn, routing = null) {
2172
+ async runAgentTurn(userMessage, mentionResult, turn, branchId, routing = null) {
1988
2173
  const mention = turn.Route === 'Mention' ? this.findAgentMention(mentionResult, turn.AgentId) : null;
1989
2174
  const targetArtifactVersionId = ArtifactVersionForTurn(routing, turn.AgentId);
1990
2175
  if (this.AgentTurnHandler) {
1991
- await this.runHostAgentTurn(this.AgentTurnHandler, userMessage, turn, mention, targetArtifactVersionId);
2176
+ await this.runHostAgentTurn(this.AgentTurnHandler, userMessage, turn, mention, targetArtifactVersionId, branchId);
1992
2177
  return;
1993
2178
  }
1994
2179
  if (mention) {
1995
- await this.invokeAgentDirectly(userMessage, mention, userMessage.ConversationID);
2180
+ await this.invokeAgentDirectly(userMessage, mention, userMessage.ConversationID, branchId);
1996
2181
  }
1997
2182
  else if (turn.Route === 'ConversationManager' || (turn.Route === 'Redirect' && this.isConversationManager(turn.AgentId))) {
1998
- await this.runConversationManagerTurn(userMessage, mentionResult);
2183
+ await this.runConversationManagerTurn(userMessage, mentionResult, branchId);
1999
2184
  }
2000
2185
  else {
2001
2186
  // Pinned and host defaults keep their direct call even when they name the manager, as before.
2002
- await this.handleAgentContinuity(userMessage, turn.AgentId, targetArtifactVersionId);
2187
+ await this.handleAgentContinuity(userMessage, turn.AgentId, branchId, targetArtifactVersionId);
2003
2188
  }
2004
2189
  }
2005
2190
  /**
@@ -2044,30 +2229,33 @@ export class MessageInputComponent extends BaseAngularComponent {
2044
2229
  * ({@link decideAgentRouting}); the prompt-based check stays unused. A confident answer from it
2045
2230
  * may name the artifact version this agent should continue from.
2046
2231
  *
2232
+ * @param branchId The turn's branch (null is Main).
2047
2233
  * @param targetArtifactVersionId The artifact version the routing decision named, or null.
2048
2234
  */
2049
- async handleAgentContinuity(messageDetail, agentId, targetArtifactVersionId = null) {
2050
- await this.continueWithAgent(messageDetail, agentId, messageDetail.ConversationID, targetArtifactVersionId ?? undefined // set only by a confident routing decision
2235
+ async handleAgentContinuity(messageDetail, agentId, branchId, targetArtifactVersionId = null) {
2236
+ await this.continueWithAgent(messageDetail, agentId, messageDetail.ConversationID, branchId, targetArtifactVersionId ?? undefined // set only by a confident routing decision
2051
2237
  );
2052
2238
  }
2053
2239
  /**
2054
2240
  * The conversation manager's turn. When an earlier message @mentioned the manager with a
2055
2241
  * configuration preset, the preset keeps applying and the manager answers directly;
2056
2242
  * otherwise it evaluates the message and may delegate.
2243
+ *
2244
+ * @param branchId The turn's branch (null is Main).
2057
2245
  */
2058
- async runConversationManagerTurn(messageDetail, mentionResult) {
2246
+ async runConversationManagerTurn(messageDetail, mentionResult, branchId) {
2059
2247
  const manager = this.ConverationManagerAgent;
2060
2248
  const managerPreset = manager?.ID && messageDetail.ConversationID
2061
- ? await this.agentService.FindConfigurationPresetForAgent(messageDetail.ConversationID, manager.ID)
2249
+ ? await this.agentService.FindConfigurationPresetForAgent(messageDetail.ConversationID, manager.ID, branchId)
2062
2250
  : undefined;
2063
2251
  if (manager?.ID && managerPreset) {
2064
- await this.executeAgentContinuation(messageDetail, manager.ID, manager.Name || 'Sage', messageDetail.ConversationID, null, // Sage doesn't use payload continuity
2252
+ await this.executeAgentContinuation(messageDetail, manager.ID, manager.Name || 'Sage', messageDetail.ConversationID, branchId, null, // Sage doesn't use payload continuity
2065
2253
  null, // Sage doesn't use artifact info
2066
2254
  managerPreset // Pass the already-found config preset
2067
2255
  );
2068
2256
  return;
2069
2257
  }
2070
- await this.processMessageThroughAgent(messageDetail, mentionResult);
2258
+ await this.processMessageThroughAgent(messageDetail, mentionResult, branchId);
2071
2259
  }
2072
2260
  /**
2073
2261
  * The newest reply from an agent other than the conversation manager — among the replies a
@@ -2132,9 +2320,11 @@ export class MessageInputComponent extends BaseAngularComponent {
2132
2320
  * Runs the turn through the host's {@link AgentTurnHandler} instead of MJ's path. Nothing is
2133
2321
  * written here: the host writes the reply rows and reports them, and each is shown like a row
2134
2322
  * MJ wrote — one still In-Progress is followed like any other in-progress reply.
2323
+ *
2324
+ * @param branchId The turn's branch (null is Main), sent to the handler as `BranchID`.
2135
2325
  */
2136
- async runHostAgentTurn(handler, userMessage, turn, mention, targetArtifactVersionId) {
2137
- const request = this.buildAgentTurnRequest(userMessage, turn, mention, targetArtifactVersionId);
2326
+ async runHostAgentTurn(handler, userMessage, turn, mention, targetArtifactVersionId, branchId) {
2327
+ const request = this.buildAgentTurnRequest(userMessage, turn, mention, targetArtifactVersionId, branchId);
2138
2328
  const result = await this.callAgentTurnHandler(handler, request);
2139
2329
  if (!result.Success) {
2140
2330
  this.notifyAgentTurnProblem(result.ErrorMessage || 'The agent could not answer this message.', 'error');
@@ -2162,10 +2352,12 @@ export class MessageInputComponent extends BaseAngularComponent {
2162
2352
  *
2163
2353
  * @param targetArtifactVersionId The artifact version the routing decision named for this
2164
2354
  * turn's agent, or null.
2355
+ * @param branchId The turn's branch (null is Main).
2165
2356
  */
2166
- buildAgentTurnRequest(userMessage, turn, mention, targetArtifactVersionId) {
2357
+ buildAgentTurnRequest(userMessage, turn, mention, targetArtifactVersionId, branchId) {
2167
2358
  return {
2168
2359
  ConversationId: userMessage.ConversationID,
2360
+ BranchID: branchId,
2169
2361
  UserMessageId: userMessage.ID,
2170
2362
  MessageText: userMessage.Message ?? '',
2171
2363
  AgentId: turn.AgentId,
@@ -2198,10 +2390,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2198
2390
  this.AfterAgentTurn.emit(new AfterAgentTurnEventArgs(conversationId, agentRunId ?? result.agentRun?.ID ?? '', result));
2199
2391
  }
2200
2392
  /**
2201
- * Checks if message should continue with the previous agent
2202
- * Emits events to show temporary intent checking message in conversation
2393
+ * Checks if message should continue with the previous agent, reading the path of `branchId`
2394
+ * (null is Main). Emits events to show temporary intent checking message in conversation
2203
2395
  */
2204
- async checkContinuityIntent(agentId, message) {
2396
+ async checkContinuityIntent(agentId, message, branchId) {
2205
2397
  // FAST PATH: If message contains form response syntax, skip the intent check entirely
2206
2398
  // Form responses always continue with the agent that requested the form
2207
2399
  // Don't show "Analyzing intent..." message for this obvious case
@@ -2223,7 +2415,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2223
2415
  console.warn('⚠️ No conversation id available for intent check');
2224
2416
  return { decision: 'UNSURE', reasoning: 'Conversation not available' };
2225
2417
  }
2226
- const intent = await this.agentService.checkAgentContinuityIntent(this.ConversationId, agentId, message, this.ConversationHistory);
2418
+ const intent = await this.agentService.checkAgentContinuityIntent(this.ConversationId, agentId, message, this.ConversationHistory, branchId);
2227
2419
  return intent;
2228
2420
  }
2229
2421
  catch (error) {
@@ -2334,8 +2526,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2334
2526
  * Process the message through agents (multi-stage: Sage -> possible sub-agent)
2335
2527
  * Only called when there's no @mention and no implicit agent context.
2336
2528
  * {@link BeforeAgentTurn} has already fired — routing announces the turn before any row exists.
2529
+ *
2530
+ * @param branchId The turn's branch (null is Main).
2337
2531
  */
2338
- async processMessageThroughAgent(userMessage, mentionResult) {
2532
+ async processMessageThroughAgent(userMessage, mentionResult, branchId) {
2339
2533
  let taskId = null;
2340
2534
  let conversationManagerMessage = null;
2341
2535
  // CRITICAL: Capture conversationId from user message at start
@@ -2343,13 +2537,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2343
2537
  const conversationId = userMessage.ConversationID;
2344
2538
  try {
2345
2539
  // Create AI message for Sage BEFORE invoking
2346
- conversationManagerMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2347
- conversationManagerMessage.ConversationID = conversationId;
2348
- conversationManagerMessage.Role = 'AI';
2540
+ conversationManagerMessage = await this.createTurnRow(conversationId, branchId);
2349
2541
  conversationManagerMessage.Message = '⏳ Starting...';
2350
2542
  conversationManagerMessage.ParentID = userMessage.ID;
2351
2543
  conversationManagerMessage.Status = 'In-Progress';
2352
- conversationManagerMessage.HiddenToUser = false;
2353
2544
  // Use the preloaded Sage agent instead of looking it up
2354
2545
  if (this.ConverationManagerAgent?.ID) {
2355
2546
  conversationManagerMessage.AgentID = this.ConverationManagerAgent.ID;
@@ -2386,7 +2577,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2386
2577
  }
2387
2578
  // Stage 2: Check for task graph (multi-step orchestration)
2388
2579
  if (result.payload?.taskGraph) {
2389
- await this.handleTaskGraphExecution(userMessage, result, conversationId, conversationManagerMessage);
2580
+ await this.handleTaskGraphExecution(userMessage, result, conversationId, branchId, conversationManagerMessage);
2390
2581
  // Remove CM from active tasks
2391
2582
  if (taskId) {
2392
2583
  // Task removed in markMessageComplete() - this.activeTasks.remove(taskId);
@@ -2395,7 +2586,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2395
2586
  // Stage 3: Check for sub-agent invocation (single-step delegation)
2396
2587
  else if (result.agentRun.FinalStep === 'Success' && result.payload?.invokeAgent) {
2397
2588
  // Reuse the existing conversationManagerMessage instead of creating new ones
2398
- await this.handleSubAgentInvocation(userMessage, result, conversationId, conversationManagerMessage);
2589
+ await this.handleSubAgentInvocation(userMessage, result, conversationId, branchId, conversationManagerMessage);
2399
2590
  // Remove CM from active tasks
2400
2591
  if (taskId) {
2401
2592
  // Task removed in markMessageComplete() - this.activeTasks.remove(taskId);
@@ -2442,7 +2633,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2442
2633
  // use update helper to ensure that if there is a race condition with more streaming updates we don't allow that to override this final message
2443
2634
  await this.updateConversationDetail(conversationManagerMessage, conversationManagerMessage.Message, 'Complete', result);
2444
2635
  this.MessageSent.emit(conversationManagerMessage);
2445
- await this.handleSilentObservation(userMessage, conversationId);
2636
+ await this.handleSilentObservation(userMessage, conversationId, branchId);
2446
2637
  // Clean up completion timestamp after delay
2447
2638
  this.cleanupCompletionTimestamp(conversationManagerMessage.ID);
2448
2639
  }
@@ -2494,8 +2685,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2494
2685
  * Single-task graphs are no longer special-cased here. The old client-side fork ran them through
2495
2686
  * a different code path entirely; they now submit like any other graph, and the decision about
2496
2687
  * whether a one-node graph is worth durable machinery moves server-side where it can be recorded.
2688
+ *
2689
+ * @param branchId The turn's branch (null is Main); the task-graph message is written there.
2497
2690
  */
2498
- async handleTaskGraphExecution(userMessage, managerResult, conversationId, conversationManagerMessage) {
2691
+ async handleTaskGraphExecution(userMessage, managerResult, conversationId, branchId, conversationManagerMessage) {
2499
2692
  // `payload` is untyped by construction (an agent's payload shape is agent-specific), so pin the
2500
2693
  // graph to the operation's own input contract at the boundary rather than letting it stay loose.
2501
2694
  const taskGraph = managerResult.payload?.taskGraph;
@@ -2512,13 +2705,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2512
2705
  const reasoning = taskGraph.reasoning || 'Executing multi-step workflow';
2513
2706
  const taskCount = Array.isArray(taskGraph.tasks) ? taskGraph.tasks.length : 0;
2514
2707
  // A message the user can watch. Progress frames from the dispatcher land against this ID.
2515
- const taskExecutionMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2516
- taskExecutionMessage.ConversationID = conversationId;
2517
- taskExecutionMessage.Role = 'AI';
2708
+ const taskExecutionMessage = await this.createTurnRow(conversationId, branchId);
2518
2709
  taskExecutionMessage.Message = `⏳ **${workflowName}**\n\n${reasoning}\n\nSubmitting ${taskCount} task(s)…`;
2519
2710
  taskExecutionMessage.ParentID = conversationManagerMessage.ID;
2520
2711
  taskExecutionMessage.Status = 'In-Progress';
2521
- taskExecutionMessage.HiddenToUser = false;
2522
2712
  await taskExecutionMessage.Save();
2523
2713
  this.MessageSent.emit(taskExecutionMessage);
2524
2714
  const callback = this.createMessageProgressCallback(taskExecutionMessage.ID);
@@ -2617,13 +2807,13 @@ export class MessageInputComponent extends BaseAngularComponent {
2617
2807
  * artifact below the window's oldest row — and a null payload is a legal agent input, so
2618
2808
  * the miss surfaces as the agent regenerating from scratch instead of modifying. Covers
2619
2809
  * system-visibility artifacts (Agent Manager and friends) for free: the query filters on
2620
- * Direction, not on Visibility.
2810
+ * Direction, not on Visibility. Only the path of `branchId` (null is Main) is read.
2621
2811
  */
2622
- async loadPreviousPayloadForAgent(agentId) {
2812
+ async loadPreviousPayloadForAgent(agentId, branchId) {
2623
2813
  if (!this.ConversationId) {
2624
2814
  return { payload: null, artifactInfo: null };
2625
2815
  }
2626
- const source = await this.agentService.FindLatestAgentOutputVersion(this.ConversationId, agentId, this.AgentHistoryFrom);
2816
+ const source = await this.agentService.FindLatestAgentOutputVersion(this.ConversationId, agentId, this.AgentHistoryFrom, branchId);
2627
2817
  if (!source || source.payload == null) {
2628
2818
  console.log(`📦 No previous payload found for agent ${agentId}`);
2629
2819
  return { payload: null, artifactInfo: null };
@@ -2641,8 +2831,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2641
2831
  /**
2642
2832
  * Handle sub-agent invocation based on Sage's payload
2643
2833
  * Reuses the existing conversationManagerMessage to avoid creating multiple records
2834
+ *
2835
+ * @param branchId The turn's branch (null is Main).
2644
2836
  */
2645
- async handleSubAgentInvocation(userMessage, managerResult, conversationId, conversationManagerMessage) {
2837
+ async handleSubAgentInvocation(userMessage, managerResult, conversationId, branchId, conversationManagerMessage) {
2646
2838
  const payload = managerResult.payload;
2647
2839
  const agentName = payload.invokeAgent;
2648
2840
  const reasoning = payload.reasoning || 'Delegating to specialist agent';
@@ -2658,13 +2850,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2658
2850
  return;
2659
2851
  }
2660
2852
  // Create AI response message BEFORE invoking agent (for duration tracking)
2661
- agentResponseMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2662
- agentResponseMessage.ConversationID = conversationId;
2663
- agentResponseMessage.Role = 'AI';
2853
+ agentResponseMessage = await this.createTurnRow(conversationId, branchId);
2664
2854
  agentResponseMessage.Message = '⏳ Starting...'; // Initial message
2665
2855
  agentResponseMessage.ParentID = conversationManagerMessage.ID; // Thread under delegation message
2666
2856
  agentResponseMessage.Status = 'In-Progress';
2667
- agentResponseMessage.HiddenToUser = false;
2668
2857
  // Set AgentID immediately for proper attribution
2669
2858
  if (agent?.ID) {
2670
2859
  agentResponseMessage.AgentID = agent.ID;
@@ -2683,11 +2872,11 @@ export class MessageInputComponent extends BaseAngularComponent {
2683
2872
  });
2684
2873
  // Load previous payload if agent has been invoked before
2685
2874
  const { payload: previousPayload, artifactInfo } = agent?.ID
2686
- ? await this.loadPreviousPayloadForAgent(agent.ID)
2875
+ ? await this.loadPreviousPayloadForAgent(agent.ID, branchId)
2687
2876
  : { payload: null, artifactInfo: null };
2688
2877
  // Find configuration preset from previous @mention in conversation history
2689
2878
  const configurationPresetId = agent?.ID
2690
- ? await this.agentService.FindConfigurationPresetForAgent(conversationId, agent.ID)
2879
+ ? await this.agentService.FindConfigurationPresetForAgent(conversationId, agent.ID, branchId)
2691
2880
  : undefined;
2692
2881
  // Invoke the sub-agent with progress callback
2693
2882
  const subResult = await this.agentService.invokeSubAgent(agentName, conversationId, userMessage, this.ConversationHistory, reasoning, agentResponseMessage.ID, previousPayload, // Pass previous payload for continuity
@@ -2777,8 +2966,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2777
2966
  /**
2778
2967
  * Handle silent observation - when Sage stays silent,
2779
2968
  * check if we should continue with the last agent for iterative refinement
2969
+ *
2970
+ * @param branchId The turn's branch (null is Main).
2780
2971
  */
2781
- async handleSilentObservation(userMessage, conversationId) {
2972
+ async handleSilentObservation(userMessage, conversationId, branchId) {
2782
2973
  // Find the last AI message (excluding Sage) this turn may read
2783
2974
  const lastAIMessage = this.findLastNonSageReply();
2784
2975
  if (!lastAIMessage || !lastAIMessage.AgentID) {
@@ -2805,7 +2996,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2805
2996
  // Resolved by QUERY, not from the window's artifact maps: `lastAIMessage` can sit inside
2806
2997
  // the loaded window while its artifact does not, and this path silently degrades to a
2807
2998
  // null payload when the lookup misses.
2808
- const source = await this.agentService.FindLatestAgentOutputVersion(conversationId, lastAIMessage.AgentID, this.AgentHistoryFrom);
2999
+ const source = await this.agentService.FindLatestAgentOutputVersion(conversationId, lastAIMessage.AgentID, this.AgentHistoryFrom, branchId);
2809
3000
  if (source && source.payload != null) {
2810
3001
  previousPayload = source.payload;
2811
3002
  previousArtifactInfo = {
@@ -2816,13 +3007,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2816
3007
  console.log('📦 Loaded previous OUTPUT artifact as payload for continuity', previousArtifactInfo);
2817
3008
  }
2818
3009
  // Create status message showing agent continuity
2819
- const statusMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2820
- statusMessage.ConversationID = conversationId;
2821
- statusMessage.Role = 'AI';
3010
+ const statusMessage = await this.createTurnRow(conversationId, branchId);
2822
3011
  statusMessage.Message = `Continuing with **${agentName}** for refinement...`;
2823
3012
  statusMessage.ParentID = userMessage.ID;
2824
3013
  statusMessage.Status = 'Complete';
2825
- statusMessage.HiddenToUser = false;
2826
3014
  statusMessage.AgentID = this.ConverationManagerAgent?.ID || null;
2827
3015
  await statusMessage.Save();
2828
3016
  this.MessageSent.emit(statusMessage);
@@ -2846,13 +3034,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2846
3034
  // Task removed in markMessageComplete() - this.activeTasks.remove(taskId);
2847
3035
  if (continuityResult && continuityResult.success) {
2848
3036
  // Create response message
2849
- const agentResponseMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2850
- agentResponseMessage.ConversationID = conversationId;
2851
- agentResponseMessage.Role = 'AI';
3037
+ const agentResponseMessage = await this.createTurnRow(conversationId, branchId);
2852
3038
  agentResponseMessage.Message = continuityResult.agentRun?.Message || `✅ **${agentName}** completed refinement`;
2853
3039
  agentResponseMessage.ParentID = statusMessage.ID;
2854
3040
  agentResponseMessage.Status = 'Complete';
2855
- agentResponseMessage.HiddenToUser = false;
2856
3041
  agentResponseMessage.AgentID = lastAIMessage.AgentID;
2857
3042
  await agentResponseMessage.Save();
2858
3043
  this.MessageSent.emit(agentResponseMessage);
@@ -2878,8 +3063,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2878
3063
  /**
2879
3064
  * Invoke an agent directly when mentioned with @ symbol
2880
3065
  * Bypasses Sage completely - no status messages
3066
+ *
3067
+ * @param branchId The turn's branch (null is Main).
2881
3068
  */
2882
- async invokeAgentDirectly(userMessage, agentMention, conversationId) {
3069
+ async invokeAgentDirectly(userMessage, agentMention, conversationId, branchId) {
2883
3070
  const agentName = agentMention.name;
2884
3071
  // Add agent to active tasks
2885
3072
  const taskId = this.activeTasks.add({
@@ -2901,13 +3088,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2901
3088
  // Look up the agent to get its ID
2902
3089
  const agent = AIEngineBase.Instance.Agents.find(a => a.Name === agentName);
2903
3090
  // Create AI response message BEFORE invoking agent (for duration tracking)
2904
- agentResponseMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2905
- agentResponseMessage.ConversationID = conversationId;
2906
- agentResponseMessage.Role = 'AI';
3091
+ agentResponseMessage = await this.createTurnRow(conversationId, branchId);
2907
3092
  agentResponseMessage.Message = '⏳ Starting...'; // Initial message
2908
3093
  agentResponseMessage.ParentID = userMessage.ID;
2909
3094
  agentResponseMessage.Status = 'In-Progress';
2910
- agentResponseMessage.HiddenToUser = false;
2911
3095
  // Set AgentID immediately for proper attribution
2912
3096
  if (agent?.ID) {
2913
3097
  agentResponseMessage.AgentID = agent.ID;
@@ -2917,7 +3101,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2917
3101
  this.MessageSent.emit(agentResponseMessage);
2918
3102
  // Load previous payload if agent has been invoked before
2919
3103
  const { payload: previousPayload, artifactInfo } = agent?.ID
2920
- ? await this.loadPreviousPayloadForAgent(agent.ID)
3104
+ ? await this.loadPreviousPayloadForAgent(agent.ID, branchId)
2921
3105
  : { payload: null, artifactInfo: null };
2922
3106
  // Invoke the agent directly
2923
3107
  const result = await this.agentService.invokeSubAgent(agentName, conversationId, userMessage, this.ConversationHistory, `User mentioned agent directly with @${agentName}`, agentResponseMessage.ID, previousPayload, // Pass previous payload for continuity
@@ -2937,12 +3121,12 @@ export class MessageInputComponent extends BaseAngularComponent {
2937
3121
  // Stage 1: Check for task graph (multi-step orchestration)
2938
3122
  if (result.payload?.taskGraph) {
2939
3123
  console.log('📋 Task graph detected from @mention, starting task orchestration');
2940
- await this.handleTaskGraphExecution(userMessage, result, conversationId, agentResponseMessage);
3124
+ await this.handleTaskGraphExecution(userMessage, result, conversationId, branchId, agentResponseMessage);
2941
3125
  }
2942
3126
  // Stage 2: Check for sub-agent invocation (single-step delegation)
2943
3127
  else if (result.agentRun.FinalStep === 'Success' && result.payload?.invokeAgent) {
2944
3128
  console.log('🎯 Sub-agent invocation detected from @mention');
2945
- await this.handleSubAgentInvocation(userMessage, result, conversationId, agentResponseMessage);
3129
+ await this.handleSubAgentInvocation(userMessage, result, conversationId, branchId, agentResponseMessage);
2946
3130
  }
2947
3131
  // Stage 3: Normal chat response
2948
3132
  else {
@@ -2974,9 +3158,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2974
3158
  * Continue with the same agent from previous message (implicit continuation)
2975
3159
  * Bypasses Sage - no status messages
2976
3160
  *
3161
+ * @param branchId The turn's branch (null is Main).
2977
3162
  * @param targetArtifactVersionId Optional specific artifact version to use as payload (from intent check)
2978
3163
  */
2979
- async continueWithAgent(userMessage, agentId, conversationId, targetArtifactVersionId) {
3164
+ async continueWithAgent(userMessage, agentId, conversationId, branchId, targetArtifactVersionId) {
2980
3165
  // Load the agent entity to get its name
2981
3166
  const agent = AIEngineBase.Instance.Agents.find(a => UUIDsEqual(a.ID, agentId));
2982
3167
  if (!agent) {
@@ -2986,7 +3171,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2986
3171
  return;
2987
3172
  }
2988
3173
  console.warn('⚠️ Could not load agent for continuation - falling back to Sage');
2989
- await this.processMessageThroughAgent(userMessage, { mentions: [], agentMention: null, userMentions: [], entityMentions: [], skillMentions: [] });
3174
+ await this.processMessageThroughAgent(userMessage, { mentions: [], agentMention: null, userMentions: [], entityMentions: [], skillMentions: [] }, branchId);
2990
3175
  return;
2991
3176
  }
2992
3177
  const agentName = agent.Name || 'Agent';
@@ -3014,7 +3199,7 @@ export class MessageInputComponent extends BaseAngularComponent {
3014
3199
  }
3015
3200
  // Extract configuration preset from the User message that @mentioned this agent
3016
3201
  // Uses the shared helper method in the agent service
3017
- previousConfigurationId = await this.agentService.FindConfigurationPresetForAgent(conversationId, agentId);
3202
+ previousConfigurationId = await this.agentService.FindConfigurationPresetForAgent(conversationId, agentId, branchId);
3018
3203
  // Fall back to the chat header's mode-picker selection when nothing
3019
3204
  // in the message history pinned a preset. The picker reflects the
3020
3205
  // user's persistent per-agent mode preference (Draft / Standard /
@@ -3031,7 +3216,7 @@ export class MessageInputComponent extends BaseAngularComponent {
3031
3216
  // used to walk is the loaded window, so the artifact it is looking for is exactly the
3032
3217
  // one most likely to be missing from it.
3033
3218
  if (!previousPayload) {
3034
- const source = await this.agentService.FindLatestAgentOutputVersion(conversationId, agentId, this.AgentHistoryFrom);
3219
+ const source = await this.agentService.FindLatestAgentOutputVersion(conversationId, agentId, this.AgentHistoryFrom, branchId);
3035
3220
  if (source && source.payload != null) {
3036
3221
  previousPayload = source.payload;
3037
3222
  previousArtifactInfo = {
@@ -3046,7 +3231,7 @@ export class MessageInputComponent extends BaseAngularComponent {
3046
3231
  }
3047
3232
  }
3048
3233
  // Execute the agent with the gathered context
3049
- await this.executeAgentContinuation(userMessage, agentId, agentName, conversationId, previousPayload, previousArtifactInfo, previousConfigurationId);
3234
+ await this.executeAgentContinuation(userMessage, agentId, agentName, conversationId, branchId, previousPayload, previousArtifactInfo, previousConfigurationId);
3050
3235
  }
3051
3236
  /**
3052
3237
  * Executes agent continuation with all context already gathered.
@@ -3056,11 +3241,12 @@ export class MessageInputComponent extends BaseAngularComponent {
3056
3241
  * @param agentId The agent ID to invoke
3057
3242
  * @param agentName The agent's display name
3058
3243
  * @param conversationId The conversation ID
3244
+ * @param branchId The turn's branch (null is Main); the reply row is written there
3059
3245
  * @param previousPayload Optional payload from previous artifact
3060
3246
  * @param previousArtifactInfo Optional artifact info (id, versionId, versionNumber)
3061
3247
  * @param configurationId Optional configuration preset ID to use
3062
3248
  */
3063
- async executeAgentContinuation(userMessage, agentId, agentName, conversationId, previousPayload, previousArtifactInfo, configurationId) {
3249
+ async executeAgentContinuation(userMessage, agentId, agentName, conversationId, branchId, previousPayload, previousArtifactInfo, configurationId) {
3064
3250
  // Add agent to active tasks
3065
3251
  const taskId = this.activeTasks.add({
3066
3252
  agentName: agentName,
@@ -3079,13 +3265,10 @@ export class MessageInputComponent extends BaseAngularComponent {
3079
3265
  await userMessage.Save();
3080
3266
  this.MessageSent.emit(userMessage);
3081
3267
  // Create AI response message BEFORE invoking agent (for duration tracking)
3082
- agentResponseMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
3083
- agentResponseMessage.ConversationID = conversationId;
3084
- agentResponseMessage.Role = 'AI';
3268
+ agentResponseMessage = await this.createTurnRow(conversationId, branchId);
3085
3269
  agentResponseMessage.Message = '⏳ Starting...'; // Initial message
3086
3270
  agentResponseMessage.ParentID = userMessage.ID;
3087
3271
  agentResponseMessage.Status = 'In-Progress';
3088
- agentResponseMessage.HiddenToUser = false;
3089
3272
  agentResponseMessage.AgentID = agentId;
3090
3273
  // Save the record to establish __mj_CreatedAt timestamp
3091
3274
  await agentResponseMessage.Save();
@@ -3342,11 +3525,11 @@ export class MessageInputComponent extends BaseAngularComponent {
3342
3525
  } if (rf & 2) {
3343
3526
  let _t;
3344
3527
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.InputBox = _t.first);
3345
- } }, inputs: { ConversationId: "ConversationId", conversationId: "conversationId", ConversationName: "ConversationName", conversationName: "conversationName", CurrentUser: "CurrentUser", currentUser: "currentUser", Disabled: "Disabled", disabled: "disabled", ReadOnly: "ReadOnly", Placeholder: "Placeholder", placeholder: "placeholder", ParentMessageId: "ParentMessageId", parentMessageId: "parentMessageId", EnableAttachments: "EnableAttachments", enableAttachments: "enableAttachments", EnableMentions: "EnableMentions", enableMentions: "enableMentions", EnableAgentMentions: "EnableAgentMentions", enableAgentMentions: "enableAgentMentions", EnableEntityMentions: "EnableEntityMentions", enableEntityMentions: "enableEntityMentions", EnableSkillCommands: "EnableSkillCommands", enableSkillCommands: "enableSkillCommands", EnablePlanMode: "EnablePlanMode", enablePlanMode: "enablePlanMode", EnableRealtime: "EnableRealtime", enableRealtime: "enableRealtime", MaxAttachments: "MaxAttachments", maxAttachments: "maxAttachments", MaxAttachmentSizeBytes: "MaxAttachmentSizeBytes", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", AcceptedFileTypes: "AcceptedFileTypes", acceptedFileTypes: "acceptedFileTypes", ArtifactsByDetailId: "ArtifactsByDetailId", artifactsByDetailId: "artifactsByDetailId", SystemArtifactsByDetailId: "SystemArtifactsByDetailId", systemArtifactsByDetailId: "systemArtifactsByDetailId", AgentRunsByDetailId: "AgentRunsByDetailId", agentRunsByDetailId: "agentRunsByDetailId", EmptyStateMode: "EmptyStateMode", emptyStateMode: "emptyStateMode", AppContext: "AppContext", appContext: "appContext", DefaultAgentId: "DefaultAgentId", defaultAgentId: "defaultAgentId", ConversationDefaultAgentId: "ConversationDefaultAgentId", conversationDefaultAgentId: "conversationDefaultAgentId", AgentConfigurationPresetId: "AgentConfigurationPresetId", agentConfigurationPresetId: "agentConfigurationPresetId", InitialMessage: "InitialMessage", initialMessage: "initialMessage", InitialAttachments: "InitialAttachments", initialAttachments: "initialAttachments", ConversationHistory: "ConversationHistory", conversationHistory: "conversationHistory", InProgressMessageIds: "InProgressMessageIds", inProgressMessageIds: "inProgressMessageIds", ApplicationId: "ApplicationId", applicationId: "applicationId", AgentReplyMode: "AgentReplyMode", AllowedAgentIDs: "AllowedAgentIDs", MentionPeople: "MentionPeople", AgentHistoryFrom: "AgentHistoryFrom", AgentTurnHandler: "AgentTurnHandler", AutoNameConversation: "AutoNameConversation", EnableDecisionRouting: "EnableDecisionRouting", InitialDraft: "InitialDraft", initialDraft: "initialDraft" }, outputs: { MessageSent: "MessageSent", messageSent: "messageSent", AgentResponse: "AgentResponse", agentResponse: "agentResponse", BeforeAgentTurn: "BeforeAgentTurn", beforeAgentTurn: "beforeAgentTurn", AfterAgentTurn: "AfterAgentTurn", afterAgentTurn: "afterAgentTurn", AgentRunDetected: "AgentRunDetected", agentRunDetected: "agentRunDetected", AgentRunUpdate: "AgentRunUpdate", agentRunUpdate: "agentRunUpdate", MessageComplete: "MessageComplete", messageComplete: "messageComplete", ArtifactCreated: "ArtifactCreated", artifactCreated: "artifactCreated", ConversationRenamed: "ConversationRenamed", conversationRenamed: "conversationRenamed", IntentCheckStarted: "IntentCheckStarted", intentCheckStarted: "intentCheckStarted", IntentCheckCompleted: "IntentCheckCompleted", intentCheckCompleted: "intentCheckCompleted", InitialMessageAutoSendStarted: "InitialMessageAutoSendStarted", initialMessageAutoSendStarted: "initialMessageAutoSendStarted", InitialMessageAutoSendFailed: "InitialMessageAutoSendFailed", initialMessageAutoSendFailed: "initialMessageAutoSendFailed", EmptyStateSubmit: "EmptyStateSubmit", emptyStateSubmit: "emptyStateSubmit", UploadStateChanged: "UploadStateChanged", uploadStateChanged: "uploadStateChanged", InitialDraftApplied: "InitialDraftApplied", initialDraftApplied: "initialDraftApplied", DraftStateChanged: "DraftStateChanged", ComposerBlurred: "ComposerBlurred" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 6, vars: 29, consts: [["pickerOrigin", "cdkOverlayOrigin"], ["inputBox", ""], ["cdkOverlayOrigin", "", 1, "message-input-wrapper"], [1, "processing-indicator"], [3, "valueChange", "blurred", "textSubmitted", "attachmentsChanged", "attachmentError", "voiceRequested", "voiceOptionsRequested", "planModeToggle", "placeholder", "disabled", "showCharacterCount", "enableMentions", "EnableAgentMentions", "EnableEntityMentions", "EnableSkillCommands", "TargetAgentId", "AllowedAgentIDs", "MentionPeople", "enableAttachments", "maxAttachments", "maxAttachmentSizeBytes", "acceptedFileTypes", "currentUser", "Provider", "rows", "enableRealtime", "voiceActive", "canStartRealtime", "enablePlanMode", "planModeActive", "value"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "cdk-overlay-transparent-backdrop", 3, "backdropClick", "detach", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPush", "cdkConnectedOverlayHasBackdrop"], [1, "fas", "fa-circle-notch", "fa-spin"], [3, "AgentPicked", "Cancelled", "Provider", "CurrentUser", "Agents", "DefaultAgentId", "CoAgents", "DefaultCoAgentId"]], template: function MessageInputComponent_Template(rf, ctx) { if (rf & 1) {
3528
+ } }, inputs: { ConversationId: "ConversationId", conversationId: "conversationId", ConversationName: "ConversationName", conversationName: "conversationName", CurrentUser: "CurrentUser", currentUser: "currentUser", Disabled: "Disabled", disabled: "disabled", ReadOnly: "ReadOnly", SendSlotMode: "SendSlotMode", StopCount: "StopCount", StopLabel: "StopLabel", StatusText: "StatusText", StatusElapsed: "StatusElapsed", Placeholder: "Placeholder", placeholder: "placeholder", ParentMessageId: "ParentMessageId", parentMessageId: "parentMessageId", EnableAttachments: "EnableAttachments", enableAttachments: "enableAttachments", EnableMentions: "EnableMentions", enableMentions: "enableMentions", EnableAgentMentions: "EnableAgentMentions", enableAgentMentions: "enableAgentMentions", EnableEntityMentions: "EnableEntityMentions", enableEntityMentions: "enableEntityMentions", EnableSkillCommands: "EnableSkillCommands", enableSkillCommands: "enableSkillCommands", EnablePlanMode: "EnablePlanMode", enablePlanMode: "enablePlanMode", EnableRealtime: "EnableRealtime", enableRealtime: "enableRealtime", MaxAttachments: "MaxAttachments", maxAttachments: "maxAttachments", MaxAttachmentSizeBytes: "MaxAttachmentSizeBytes", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", AcceptedFileTypes: "AcceptedFileTypes", acceptedFileTypes: "acceptedFileTypes", ArtifactsByDetailId: "ArtifactsByDetailId", artifactsByDetailId: "artifactsByDetailId", SystemArtifactsByDetailId: "SystemArtifactsByDetailId", systemArtifactsByDetailId: "systemArtifactsByDetailId", AgentRunsByDetailId: "AgentRunsByDetailId", agentRunsByDetailId: "agentRunsByDetailId", EmptyStateMode: "EmptyStateMode", emptyStateMode: "emptyStateMode", AppContext: "AppContext", appContext: "appContext", DefaultAgentId: "DefaultAgentId", defaultAgentId: "defaultAgentId", ConversationDefaultAgentId: "ConversationDefaultAgentId", conversationDefaultAgentId: "conversationDefaultAgentId", AgentConfigurationPresetId: "AgentConfigurationPresetId", agentConfigurationPresetId: "agentConfigurationPresetId", InitialMessage: "InitialMessage", initialMessage: "initialMessage", InitialAttachments: "InitialAttachments", initialAttachments: "initialAttachments", ConversationHistory: "ConversationHistory", conversationHistory: "conversationHistory", InProgressMessageIds: "InProgressMessageIds", inProgressMessageIds: "inProgressMessageIds", ApplicationId: "ApplicationId", applicationId: "applicationId", AgentReplyMode: "AgentReplyMode", AllowedAgentIDs: "AllowedAgentIDs", MentionPeople: "MentionPeople", AgentHistoryFrom: "AgentHistoryFrom", TargetBranchID: "TargetBranchID", ResolveTargetBranch: "ResolveTargetBranch", AgentTurnHandler: "AgentTurnHandler", AutoNameConversation: "AutoNameConversation", EnableDecisionRouting: "EnableDecisionRouting", InitialDraft: "InitialDraft", initialDraft: "initialDraft" }, outputs: { StopClicked: "StopClicked", MessageSent: "MessageSent", messageSent: "messageSent", MessageStreamed: "MessageStreamed", AgentResponse: "AgentResponse", agentResponse: "agentResponse", BeforeAgentTurn: "BeforeAgentTurn", beforeAgentTurn: "beforeAgentTurn", AfterAgentTurn: "AfterAgentTurn", afterAgentTurn: "afterAgentTurn", AgentRunDetected: "AgentRunDetected", agentRunDetected: "agentRunDetected", AgentRunUpdate: "AgentRunUpdate", agentRunUpdate: "agentRunUpdate", MessageComplete: "MessageComplete", messageComplete: "messageComplete", ArtifactCreated: "ArtifactCreated", artifactCreated: "artifactCreated", ConversationRenamed: "ConversationRenamed", conversationRenamed: "conversationRenamed", IntentCheckStarted: "IntentCheckStarted", intentCheckStarted: "intentCheckStarted", IntentCheckCompleted: "IntentCheckCompleted", intentCheckCompleted: "intentCheckCompleted", InitialMessageAutoSendStarted: "InitialMessageAutoSendStarted", initialMessageAutoSendStarted: "initialMessageAutoSendStarted", InitialMessageAutoSendFailed: "InitialMessageAutoSendFailed", initialMessageAutoSendFailed: "initialMessageAutoSendFailed", EmptyStateSubmit: "EmptyStateSubmit", emptyStateSubmit: "emptyStateSubmit", UploadStateChanged: "UploadStateChanged", uploadStateChanged: "uploadStateChanged", InitialDraftApplied: "InitialDraftApplied", initialDraftApplied: "initialDraftApplied", DraftStateChanged: "DraftStateChanged", ComposerBlurred: "ComposerBlurred" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 6, vars: 34, consts: [["pickerOrigin", "cdkOverlayOrigin"], ["inputBox", ""], ["cdkOverlayOrigin", "", 1, "message-input-wrapper"], [1, "processing-indicator"], [3, "StopClicked", "valueChange", "blurred", "textSubmitted", "attachmentsChanged", "attachmentError", "voiceRequested", "voiceOptionsRequested", "planModeToggle", "placeholder", "disabled", "showCharacterCount", "enableMentions", "EnableAgentMentions", "EnableEntityMentions", "EnableSkillCommands", "TargetAgentId", "AllowedAgentIDs", "MentionPeople", "enableAttachments", "maxAttachments", "maxAttachmentSizeBytes", "acceptedFileTypes", "currentUser", "Provider", "rows", "enableRealtime", "voiceActive", "canStartRealtime", "enablePlanMode", "planModeActive", "SendSlotMode", "StopCount", "StopLabel", "StatusText", "StatusElapsed", "value"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "cdk-overlay-transparent-backdrop", 3, "backdropClick", "detach", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPush", "cdkConnectedOverlayHasBackdrop"], [1, "fas", "fa-circle-notch", "fa-spin"], [3, "AgentPicked", "Cancelled", "Provider", "CurrentUser", "Agents", "DefaultAgentId", "CoAgents", "DefaultCoAgentId"]], template: function MessageInputComponent_Template(rf, ctx) { if (rf & 1) {
3346
3529
  i0.ɵɵelementStart(0, "div", 2, 0);
3347
3530
  i0.ɵɵconditionalCreate(2, MessageInputComponent_Conditional_2_Template, 4, 1, "div", 3);
3348
3531
  i0.ɵɵelementStart(3, "mj-ai-composer", 4, 1);
3349
- i0.ɵɵlistener("valueChange", function MessageInputComponent_Template_mj_ai_composer_valueChange_3_listener($event) { return ctx.OnComposerValueChanged($event); })("blurred", function MessageInputComponent_Template_mj_ai_composer_blurred_3_listener() { return ctx.ComposerBlurred.emit(); })("textSubmitted", function MessageInputComponent_Template_mj_ai_composer_textSubmitted_3_listener($event) { return ctx.onTextSubmitted($event); })("attachmentsChanged", function MessageInputComponent_Template_mj_ai_composer_attachmentsChanged_3_listener($event) { return ctx.onAttachmentsChanged($event); })("attachmentError", function MessageInputComponent_Template_mj_ai_composer_attachmentError_3_listener($event) { return ctx.onAttachmentError($event); })("voiceRequested", function MessageInputComponent_Template_mj_ai_composer_voiceRequested_3_listener() { return ctx.onStartRealtime(); })("voiceOptionsRequested", function MessageInputComponent_Template_mj_ai_composer_voiceOptionsRequested_3_listener() { return ctx.onRealtimeOptions(); })("planModeToggle", function MessageInputComponent_Template_mj_ai_composer_planModeToggle_3_listener() { return ctx.TogglePlanMode(); });
3532
+ i0.ɵɵlistener("StopClicked", function MessageInputComponent_Template_mj_ai_composer_StopClicked_3_listener() { return ctx.StopClicked.emit(); })("valueChange", function MessageInputComponent_Template_mj_ai_composer_valueChange_3_listener($event) { return ctx.OnComposerValueChanged($event); })("blurred", function MessageInputComponent_Template_mj_ai_composer_blurred_3_listener() { return ctx.ComposerBlurred.emit(); })("textSubmitted", function MessageInputComponent_Template_mj_ai_composer_textSubmitted_3_listener($event) { return ctx.onTextSubmitted($event); })("attachmentsChanged", function MessageInputComponent_Template_mj_ai_composer_attachmentsChanged_3_listener($event) { return ctx.onAttachmentsChanged($event); })("attachmentError", function MessageInputComponent_Template_mj_ai_composer_attachmentError_3_listener($event) { return ctx.onAttachmentError($event); })("voiceRequested", function MessageInputComponent_Template_mj_ai_composer_voiceRequested_3_listener() { return ctx.onStartRealtime(); })("voiceOptionsRequested", function MessageInputComponent_Template_mj_ai_composer_voiceOptionsRequested_3_listener() { return ctx.onRealtimeOptions(); })("planModeToggle", function MessageInputComponent_Template_mj_ai_composer_planModeToggle_3_listener() { return ctx.TogglePlanMode(); });
3350
3533
  i0.ɵɵelementEnd();
3351
3534
  i0.ɵɵtemplate(5, MessageInputComponent_ng_template_5_Template, 1, 6, "ng-template", 5);
3352
3535
  i0.ɵɵlistener("backdropClick", function MessageInputComponent_Template_ng_template_backdropClick_5_listener() { return ctx.onRealtimeAgentPickerCancelled(); })("detach", function MessageInputComponent_Template_ng_template_detach_5_listener() { return ctx.onRealtimeAgentPickerCancelled(); });
@@ -3356,14 +3539,14 @@ export class MessageInputComponent extends BaseAngularComponent {
3356
3539
  i0.ɵɵadvance(2);
3357
3540
  i0.ɵɵconditional(ctx.isProcessing ? 2 : -1);
3358
3541
  i0.ɵɵadvance();
3359
- i0.ɵɵproperty("placeholder", ctx.placeholder)("disabled", ctx.disabled || ctx.isProcessing)("showCharacterCount", false)("enableMentions", ctx.enableMentions)("EnableAgentMentions", ctx.enableAgentMentions)("EnableEntityMentions", ctx.enableEntityMentions)("EnableSkillCommands", ctx.enableSkillCommands)("TargetAgentId", ctx.pickerTargetAgentId)("AllowedAgentIDs", ctx.AllowedAgentIDs)("MentionPeople", ctx.MentionPeople)("enableAttachments", ctx.enableAttachments)("maxAttachments", ctx.maxAttachments)("maxAttachmentSizeBytes", ctx.maxAttachmentSizeBytes)("acceptedFileTypes", ctx.acceptedFileTypes)("currentUser", ctx.currentUser)("Provider", ctx.Provider)("rows", 3)("enableRealtime", ctx.enableRealtime)("voiceActive", ctx.voiceActive)("canStartRealtime", ctx.canStartRealtime)("enablePlanMode", ctx.enablePlanMode)("planModeActive", ctx.PlanModeEnabled)("value", ctx.messageText);
3542
+ i0.ɵɵproperty("placeholder", ctx.placeholder)("disabled", ctx.disabled || ctx.isProcessing)("showCharacterCount", false)("enableMentions", ctx.enableMentions)("EnableAgentMentions", ctx.enableAgentMentions)("EnableEntityMentions", ctx.enableEntityMentions)("EnableSkillCommands", ctx.enableSkillCommands)("TargetAgentId", ctx.pickerTargetAgentId)("AllowedAgentIDs", ctx.AllowedAgentIDs)("MentionPeople", ctx.MentionPeople)("enableAttachments", ctx.enableAttachments)("maxAttachments", ctx.maxAttachments)("maxAttachmentSizeBytes", ctx.maxAttachmentSizeBytes)("acceptedFileTypes", ctx.acceptedFileTypes)("currentUser", ctx.currentUser)("Provider", ctx.Provider)("rows", 3)("enableRealtime", ctx.enableRealtime)("voiceActive", ctx.voiceActive)("canStartRealtime", ctx.canStartRealtime)("enablePlanMode", ctx.enablePlanMode)("planModeActive", ctx.PlanModeEnabled)("SendSlotMode", ctx.SendSlotMode)("StopCount", ctx.StopCount)("StopLabel", ctx.StopLabel)("StatusText", ctx.StatusText)("StatusElapsed", ctx.StatusElapsed)("value", ctx.messageText);
3360
3543
  i0.ɵɵadvance(2);
3361
3544
  i0.ɵɵproperty("cdkConnectedOverlayOrigin", pickerOrigin_r3)("cdkConnectedOverlayOpen", ctx.showRealtimeAgentPicker)("cdkConnectedOverlayPositions", ctx.pickerOverlayPositions)("cdkConnectedOverlayPush", true)("cdkConnectedOverlayHasBackdrop", true);
3362
3545
  } }, dependencies: [i11.CdkConnectedOverlay, i11.CdkOverlayOrigin, i12.RealtimeAgentPickerComponent, i13.AiComposerComponent], styles: [".message-input-wrapper[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n}\n\n\n\n\n.processing-indicator[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n background: color-mix(in srgb, var(--mj-bg-surface-card) 95%, transparent);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n z-index: 10;\n pointer-events: none;\n}\n.processing-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n.processing-indicator[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}"] });
3363
3546
  }
3364
3547
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MessageInputComponent, [{
3365
3548
  type: Component,
3366
- args: [{ standalone: false, selector: 'mj-message-input', template: "<div class=\"message-input-wrapper\" cdkOverlayOrigin #pickerOrigin=\"cdkOverlayOrigin\">\n <!-- Processing Indicator Overlay -->\n @if (isProcessing) {\n <div class=\"processing-indicator\">\n <i class=\"fas fa-circle-notch fa-spin\"></i>\n <span>{{ processingMessage }}</span>\n </div>\n }\n\n <!-- AI composer (mic + Plan Mode buttons live in its in-composer toolbar): wraps the\n generic mj-message-input-box with the '@' agent / '#' record / '/' skill trigger\n plugins built in \u2014 all three on by default, preserving the standard chat behavior. -->\n <mj-ai-composer\n #inputBox\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled || isProcessing\"\n [showCharacterCount]=\"false\"\n [enableMentions]=\"enableMentions\"\n [EnableAgentMentions]=\"enableAgentMentions\"\n [EnableEntityMentions]=\"enableEntityMentions\"\n [EnableSkillCommands]=\"enableSkillCommands\"\n [TargetAgentId]=\"pickerTargetAgentId\"\n [AllowedAgentIDs]=\"AllowedAgentIDs\"\n [MentionPeople]=\"MentionPeople\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n [currentUser]=\"currentUser\"\n [Provider]=\"Provider\"\n [rows]=\"3\"\n [enableRealtime]=\"enableRealtime\"\n [voiceActive]=\"voiceActive\"\n [canStartRealtime]=\"canStartRealtime\"\n [enablePlanMode]=\"enablePlanMode\"\n [planModeActive]=\"PlanModeEnabled\"\n [value]=\"messageText\"\n (valueChange)=\"OnComposerValueChanged($event)\"\n (blurred)=\"ComposerBlurred.emit()\"\n (textSubmitted)=\"onTextSubmitted($event)\"\n (attachmentsChanged)=\"onAttachmentsChanged($event)\"\n (attachmentError)=\"onAttachmentError($event)\"\n (voiceRequested)=\"onStartRealtime()\"\n (voiceOptionsRequested)=\"onRealtimeOptions()\"\n (planModeToggle)=\"TogglePlanMode()\">\n </mj-ai-composer>\n\n <!-- Voice agent/co-agent/model picker \u2014 shown when starting a call on a conversation\n with NO prior agent participation, or on demand via the caret next to the phone\n button (any conversation). Rendered in a body-level CDK overlay anchored above the\n composer so it POPS OUT of the chat overlay's clipping border instead of being cut\n off at the top of a narrow (~390px) overlay. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"pickerOrigin\"\n [cdkConnectedOverlayOpen]=\"showRealtimeAgentPicker\"\n [cdkConnectedOverlayPositions]=\"pickerOverlayPositions\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (backdropClick)=\"onRealtimeAgentPickerCancelled()\"\n (detach)=\"onRealtimeAgentPickerCancelled()\">\n <mj-realtime-agent-picker\n [Provider]=\"ProviderToUse\"\n [CurrentUser]=\"currentUser\"\n [Agents]=\"voicePickerAgents\"\n [DefaultAgentId]=\"voicePickerDefaultAgentId\"\n [CoAgents]=\"voicePickerCoAgents\"\n [DefaultCoAgentId]=\"voicePickerDefaultCoAgentId\"\n (AgentPicked)=\"onRealtimeAgentPicked($event)\"\n (Cancelled)=\"onRealtimeAgentPickerCancelled()\">\n </mj-realtime-agent-picker>\n </ng-template>\n</div>\n\n<!-- The voice \"call mode\" overlay is hosted by <mj-conversation-chat-area> (it fills the\n whole conversation panel in place); this component only owns the trigger wiring. -->\n", styles: [".message-input-wrapper {\n position: relative;\n width: 100%;\n}\n\n/* Plan Mode moved into the in-composer toolbar (message-input-box) as a toggle icon button\n next to the attachment/voice buttons \u2014 see .plan-mode-button-icon there. */\n\n.processing-indicator {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n background: color-mix(in srgb, var(--mj-bg-surface-card) 95%, transparent);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n z-index: 10;\n pointer-events: none;\n}\n.processing-indicator i {\n color: var(--mj-brand-primary);\n}\n.processing-indicator span {\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n"] }]
3549
+ args: [{ standalone: false, selector: 'mj-message-input', template: "<div class=\"message-input-wrapper\" cdkOverlayOrigin #pickerOrigin=\"cdkOverlayOrigin\">\n <!-- Processing Indicator Overlay -->\n @if (isProcessing) {\n <div class=\"processing-indicator\">\n <i class=\"fas fa-circle-notch fa-spin\"></i>\n <span>{{ processingMessage }}</span>\n </div>\n }\n\n <!-- AI composer (mic + Plan Mode buttons live in its in-composer toolbar): wraps the\n generic mj-message-input-box with the '@' agent / '#' record / '/' skill trigger\n plugins built in \u2014 all three on by default, preserving the standard chat behavior. -->\n <mj-ai-composer\n #inputBox\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled || isProcessing\"\n [showCharacterCount]=\"false\"\n [enableMentions]=\"enableMentions\"\n [EnableAgentMentions]=\"enableAgentMentions\"\n [EnableEntityMentions]=\"enableEntityMentions\"\n [EnableSkillCommands]=\"enableSkillCommands\"\n [TargetAgentId]=\"pickerTargetAgentId\"\n [AllowedAgentIDs]=\"AllowedAgentIDs\"\n [MentionPeople]=\"MentionPeople\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n [currentUser]=\"currentUser\"\n [Provider]=\"Provider\"\n [rows]=\"3\"\n [enableRealtime]=\"enableRealtime\"\n [voiceActive]=\"voiceActive\"\n [canStartRealtime]=\"canStartRealtime\"\n [enablePlanMode]=\"enablePlanMode\"\n [planModeActive]=\"PlanModeEnabled\"\n [SendSlotMode]=\"SendSlotMode\"\n [StopCount]=\"StopCount\"\n [StopLabel]=\"StopLabel\"\n [StatusText]=\"StatusText\"\n [StatusElapsed]=\"StatusElapsed\"\n (StopClicked)=\"StopClicked.emit()\"\n [value]=\"messageText\"\n (valueChange)=\"OnComposerValueChanged($event)\"\n (blurred)=\"ComposerBlurred.emit()\"\n (textSubmitted)=\"onTextSubmitted($event)\"\n (attachmentsChanged)=\"onAttachmentsChanged($event)\"\n (attachmentError)=\"onAttachmentError($event)\"\n (voiceRequested)=\"onStartRealtime()\"\n (voiceOptionsRequested)=\"onRealtimeOptions()\"\n (planModeToggle)=\"TogglePlanMode()\">\n </mj-ai-composer>\n\n <!-- Voice agent/co-agent/model picker \u2014 shown when starting a call on a conversation\n with NO prior agent participation, or on demand via the caret next to the phone\n button (any conversation). Rendered in a body-level CDK overlay anchored above the\n composer so it POPS OUT of the chat overlay's clipping border instead of being cut\n off at the top of a narrow (~390px) overlay. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"pickerOrigin\"\n [cdkConnectedOverlayOpen]=\"showRealtimeAgentPicker\"\n [cdkConnectedOverlayPositions]=\"pickerOverlayPositions\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (backdropClick)=\"onRealtimeAgentPickerCancelled()\"\n (detach)=\"onRealtimeAgentPickerCancelled()\">\n <mj-realtime-agent-picker\n [Provider]=\"ProviderToUse\"\n [CurrentUser]=\"currentUser\"\n [Agents]=\"voicePickerAgents\"\n [DefaultAgentId]=\"voicePickerDefaultAgentId\"\n [CoAgents]=\"voicePickerCoAgents\"\n [DefaultCoAgentId]=\"voicePickerDefaultCoAgentId\"\n (AgentPicked)=\"onRealtimeAgentPicked($event)\"\n (Cancelled)=\"onRealtimeAgentPickerCancelled()\">\n </mj-realtime-agent-picker>\n </ng-template>\n</div>\n\n<!-- The voice \"call mode\" overlay is hosted by <mj-conversation-chat-area> (it fills the\n whole conversation panel in place); this component only owns the trigger wiring. -->\n", styles: [".message-input-wrapper {\n position: relative;\n width: 100%;\n}\n\n/* Plan Mode moved into the in-composer toolbar (message-input-box) as a toggle icon button\n next to the attachment/voice buttons \u2014 see .plan-mode-button-icon there. */\n\n.processing-indicator {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n background: color-mix(in srgb, var(--mj-bg-surface-card) 95%, transparent);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n z-index: 10;\n pointer-events: none;\n}\n.processing-indicator i {\n color: var(--mj-brand-primary);\n}\n.processing-indicator span {\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n"] }]
3367
3550
  }], () => [{ type: i1.DialogService }, { type: i2.ToastService }, { type: i3.ConversationAgentService }, { type: i4.DataCacheService }, { type: i5.ActiveTasksService }, { type: i6.ConversationStreamingService }, { type: i7.MentionParserService }, { type: i8.ConversationAttachmentService }, { type: i9.ConversationBridgeService }, { type: i10.RealtimeSessionService }], { ConversationId: [{
3368
3551
  type: Input
3369
3552
  }], conversationId: [{
@@ -3382,6 +3565,16 @@ export class MessageInputComponent extends BaseAngularComponent {
3382
3565
  type: Input
3383
3566
  }], ReadOnly: [{
3384
3567
  type: Input
3568
+ }], SendSlotMode: [{
3569
+ type: Input
3570
+ }], StopCount: [{
3571
+ type: Input
3572
+ }], StopLabel: [{
3573
+ type: Input
3574
+ }], StatusText: [{
3575
+ type: Input
3576
+ }], StatusElapsed: [{
3577
+ type: Input
3385
3578
  }], Placeholder: [{
3386
3579
  type: Input
3387
3580
  }], placeholder: [{
@@ -3490,16 +3683,24 @@ export class MessageInputComponent extends BaseAngularComponent {
3490
3683
  type: Input
3491
3684
  }], AgentHistoryFrom: [{
3492
3685
  type: Input
3686
+ }], TargetBranchID: [{
3687
+ type: Input
3688
+ }], ResolveTargetBranch: [{
3689
+ type: Input
3493
3690
  }], AgentTurnHandler: [{
3494
3691
  type: Input
3495
3692
  }], AutoNameConversation: [{
3496
3693
  type: Input
3497
3694
  }], EnableDecisionRouting: [{
3498
3695
  type: Input
3696
+ }], StopClicked: [{
3697
+ type: Output
3499
3698
  }], MessageSent: [{
3500
3699
  type: Output
3501
3700
  }], messageSent: [{
3502
3701
  type: Output
3702
+ }], MessageStreamed: [{
3703
+ type: Output
3503
3704
  }], AgentResponse: [{
3504
3705
  type: Output
3505
3706
  }], agentResponse: [{
@@ -3572,5 +3773,5 @@ export class MessageInputComponent extends BaseAngularComponent {
3572
3773
  }], ComposerBlurred: [{
3573
3774
  type: Output
3574
3775
  }] }); })();
3575
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageInputComponent, { className: "MessageInputComponent", filePath: "src/lib/components/message/message-input.component.ts", lineNumber: 66 }); })();
3776
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageInputComponent, { className: "MessageInputComponent", filePath: "src/lib/components/message/message-input.component.ts", lineNumber: 71 }); })();
3576
3777
  //# sourceMappingURL=message-input.component.js.map