@memberjunction/ng-conversations 6.2.0-edge.3 → 6.2.0-edge.5

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 (318) hide show
  1. package/README.md +33 -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-agent-picker.component.d.ts +1 -1
  10. package/dist/lib/components/conversation/conversation-agent-picker.component.js +3 -3
  11. package/dist/lib/components/conversation/conversation-agent-picker.component.js.map +1 -1
  12. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +651 -53
  13. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  14. package/dist/lib/components/conversation/conversation-chat-area.component.js +3002 -661
  15. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  16. package/dist/lib/components/conversation/forks-popover.component.d.ts +37 -0
  17. package/dist/lib/components/conversation/forks-popover.component.d.ts.map +1 -0
  18. package/dist/lib/components/conversation/forks-popover.component.js +164 -0
  19. package/dist/lib/components/conversation/forks-popover.component.js.map +1 -0
  20. package/dist/lib/components/export/export-modal.component.d.ts +7 -2
  21. package/dist/lib/components/export/export-modal.component.d.ts.map +1 -1
  22. package/dist/lib/components/export/export-modal.component.js +16 -3
  23. package/dist/lib/components/export/export-modal.component.js.map +1 -1
  24. package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
  25. package/dist/lib/components/message/conversation-message-rating.component.js +11 -9
  26. package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
  27. package/dist/lib/components/message/message-input.component.d.ts +96 -11
  28. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  29. package/dist/lib/components/message/message-input.component.js +253 -112
  30. package/dist/lib/components/message/message-input.component.js.map +1 -1
  31. package/dist/lib/components/message/message-item.component.d.ts +304 -16
  32. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  33. package/dist/lib/components/message/message-item.component.js +2029 -363
  34. package/dist/lib/components/message/message-item.component.js.map +1 -1
  35. package/dist/lib/components/message/message-list.component.d.ts +101 -22
  36. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  37. package/dist/lib/components/message/message-list.component.js +326 -55
  38. package/dist/lib/components/message/message-list.component.js.map +1 -1
  39. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.d.ts +34 -0
  40. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.d.ts.map +1 -0
  41. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.js +75 -0
  42. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.js.map +1 -0
  43. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.d.ts +80 -0
  44. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.d.ts.map +1 -0
  45. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.js +202 -0
  46. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.js.map +1 -0
  47. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.d.ts +45 -0
  48. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.d.ts.map +1 -0
  49. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.js +123 -0
  50. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.js.map +1 -0
  51. package/dist/lib/components/realtime/capture/realtime-capture-channel.d.ts +90 -0
  52. package/dist/lib/components/realtime/capture/realtime-capture-channel.d.ts.map +1 -0
  53. package/dist/lib/components/realtime/capture/realtime-capture-channel.js +223 -0
  54. package/dist/lib/components/realtime/capture/realtime-capture-channel.js.map +1 -0
  55. package/dist/lib/components/realtime/capture/realtime-capture-model.d.ts +98 -0
  56. package/dist/lib/components/realtime/capture/realtime-capture-model.d.ts.map +1 -0
  57. package/dist/lib/components/realtime/capture/realtime-capture-model.js +161 -0
  58. package/dist/lib/components/realtime/capture/realtime-capture-model.js.map +1 -0
  59. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.d.ts +48 -0
  60. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.d.ts.map +1 -0
  61. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.js +205 -0
  62. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.js.map +1 -0
  63. package/dist/lib/components/realtime/channels/client-context-channel.d.ts +19 -2
  64. package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -1
  65. package/dist/lib/components/realtime/channels/client-context-channel.js +83 -9
  66. package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -1
  67. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +30 -9
  68. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -1
  69. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +78 -14
  70. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -1
  71. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.d.ts +71 -0
  72. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.d.ts.map +1 -0
  73. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.js +259 -0
  74. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.js.map +1 -0
  75. package/dist/lib/components/realtime/identity-verification/identity-verification-model.d.ts +129 -0
  76. package/dist/lib/components/realtime/identity-verification/identity-verification-model.d.ts.map +1 -0
  77. package/dist/lib/components/realtime/identity-verification/identity-verification-model.js +373 -0
  78. package/dist/lib/components/realtime/identity-verification/identity-verification-model.js.map +1 -0
  79. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.d.ts +77 -0
  80. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.d.ts.map +1 -0
  81. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.js +420 -0
  82. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.js.map +1 -0
  83. package/dist/lib/components/realtime/interactive-component/component-contract.d.ts +83 -0
  84. package/dist/lib/components/realtime/interactive-component/component-contract.d.ts.map +1 -0
  85. package/dist/lib/components/realtime/interactive-component/component-contract.js +292 -0
  86. package/dist/lib/components/realtime/interactive-component/component-contract.js.map +1 -0
  87. package/dist/lib/components/realtime/interactive-component/component-data-state.d.ts +39 -0
  88. package/dist/lib/components/realtime/interactive-component/component-data-state.d.ts.map +1 -0
  89. package/dist/lib/components/realtime/interactive-component/component-data-state.js +152 -0
  90. package/dist/lib/components/realtime/interactive-component/component-data-state.js.map +1 -0
  91. package/dist/lib/components/realtime/interactive-component/component-instance-engine.d.ts +109 -0
  92. package/dist/lib/components/realtime/interactive-component/component-instance-engine.d.ts.map +1 -0
  93. package/dist/lib/components/realtime/interactive-component/component-instance-engine.js +146 -0
  94. package/dist/lib/components/realtime/interactive-component/component-instance-engine.js.map +1 -0
  95. package/dist/lib/components/realtime/interactive-component/component-spec-content.d.ts +19 -0
  96. package/dist/lib/components/realtime/interactive-component/component-spec-content.d.ts.map +1 -0
  97. package/dist/lib/components/realtime/interactive-component/component-spec-content.js +39 -0
  98. package/dist/lib/components/realtime/interactive-component/component-spec-content.js.map +1 -0
  99. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.d.ts +183 -0
  100. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.d.ts.map +1 -0
  101. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.js +761 -0
  102. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.js.map +1 -0
  103. package/dist/lib/components/realtime/interactive-component/interactive-component-config.d.ts +25 -0
  104. package/dist/lib/components/realtime/interactive-component/interactive-component-config.d.ts.map +1 -0
  105. package/dist/lib/components/realtime/interactive-component/interactive-component-config.js +57 -0
  106. package/dist/lib/components/realtime/interactive-component/interactive-component-config.js.map +1 -0
  107. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.d.ts +40 -0
  108. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.d.ts.map +1 -0
  109. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.js +97 -0
  110. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.js.map +1 -0
  111. package/dist/lib/components/realtime/interactive-component/interactive-component-types.d.ts +144 -0
  112. package/dist/lib/components/realtime/interactive-component/interactive-component-types.d.ts.map +1 -0
  113. package/dist/lib/components/realtime/interactive-component/interactive-component-types.js +57 -0
  114. package/dist/lib/components/realtime/interactive-component/interactive-component-types.js.map +1 -0
  115. package/dist/lib/components/realtime/interactive-component/react-component-handle.d.ts +36 -0
  116. package/dist/lib/components/realtime/interactive-component/react-component-handle.d.ts.map +1 -0
  117. package/dist/lib/components/realtime/interactive-component/react-component-handle.js +55 -0
  118. package/dist/lib/components/realtime/interactive-component/react-component-handle.js.map +1 -0
  119. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.d.ts +55 -0
  120. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.d.ts.map +1 -0
  121. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.js +210 -0
  122. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.js.map +1 -0
  123. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.d.ts +32 -0
  124. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.d.ts.map +1 -0
  125. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js +90 -0
  126. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js.map +1 -0
  127. package/dist/lib/components/realtime/media/media-channel.d.ts +7 -0
  128. package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -1
  129. package/dist/lib/components/realtime/media/media-channel.js +28 -1
  130. package/dist/lib/components/realtime/media/media-channel.js.map +1 -1
  131. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +8 -1
  132. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  133. package/dist/lib/components/realtime/realtime-agent-banner.component.js +89 -71
  134. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  135. package/dist/lib/components/realtime/realtime-agent-orb.component.d.ts +21 -0
  136. package/dist/lib/components/realtime/realtime-agent-orb.component.d.ts.map +1 -0
  137. package/dist/lib/components/realtime/realtime-agent-orb.component.js +49 -0
  138. package/dist/lib/components/realtime/realtime-agent-orb.component.js.map +1 -0
  139. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +44 -11
  140. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
  141. package/dist/lib/components/realtime/realtime-agent-picker.component.js +162 -50
  142. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
  143. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +8 -2
  144. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -1
  145. package/dist/lib/components/realtime/realtime-audio-visuals.js +14 -18
  146. package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -1
  147. package/dist/lib/components/realtime/realtime-composer.component.d.ts +42 -2
  148. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
  149. package/dist/lib/components/realtime/realtime-composer.component.js +137 -102
  150. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  151. package/dist/lib/components/realtime/realtime-perception-chip.component.d.ts +71 -0
  152. package/dist/lib/components/realtime/realtime-perception-chip.component.d.ts.map +1 -0
  153. package/dist/lib/components/realtime/realtime-perception-chip.component.js +221 -0
  154. package/dist/lib/components/realtime/realtime-perception-chip.component.js.map +1 -0
  155. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +264 -22
  156. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  157. package/dist/lib/components/realtime/realtime-session-overlay.component.js +851 -135
  158. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  159. package/dist/lib/components/realtime/realtime-surface-placement-prefs.d.ts +14 -0
  160. package/dist/lib/components/realtime/realtime-surface-placement-prefs.d.ts.map +1 -0
  161. package/dist/lib/components/realtime/realtime-surface-placement-prefs.js +14 -0
  162. package/dist/lib/components/realtime/realtime-surface-placement-prefs.js.map +1 -0
  163. package/dist/lib/components/realtime/realtime-surface-stage.model.d.ts +74 -0
  164. package/dist/lib/components/realtime/realtime-surface-stage.model.d.ts.map +1 -0
  165. package/dist/lib/components/realtime/realtime-surface-stage.model.js +171 -0
  166. package/dist/lib/components/realtime/realtime-surface-stage.model.js.map +1 -0
  167. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +71 -13
  168. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
  169. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +232 -73
  170. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
  171. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +5 -0
  172. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
  173. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +8 -0
  174. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
  175. package/dist/lib/components/realtime/realtime-ui-config.d.ts +12 -2
  176. package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -1
  177. package/dist/lib/components/realtime/realtime-ui-config.js +5 -1
  178. package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -1
  179. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +10 -1
  180. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
  181. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +42 -2
  182. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
  183. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts +20 -3
  184. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts.map +1 -1
  185. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js +44 -10
  186. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js.map +1 -1
  187. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +28 -44
  188. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
  189. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +76 -162
  190. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
  191. package/dist/lib/components/search/search-panel.component.d.ts +2 -0
  192. package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
  193. package/dist/lib/components/search/search-panel.component.js +25 -12
  194. package/dist/lib/components/search/search-panel.component.js.map +1 -1
  195. package/dist/lib/components/sidebar/routines-section.component.js +1 -1
  196. package/dist/lib/components/sidebar/routines-section.component.js.map +1 -1
  197. package/dist/lib/components/task/tasks-full-view.component.d.ts +152 -31
  198. package/dist/lib/components/task/tasks-full-view.component.d.ts.map +1 -1
  199. package/dist/lib/components/task/tasks-full-view.component.js +2227 -214
  200. package/dist/lib/components/task/tasks-full-view.component.js.map +1 -1
  201. package/dist/lib/components/tasks/tasks-dropdown.component.js +4 -4
  202. package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
  203. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +33 -32
  204. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  205. package/dist/lib/components/workspace/conversation-workspace.component.js +72 -88
  206. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  207. package/dist/lib/conversations.module.d.ts +30 -29
  208. package/dist/lib/conversations.module.d.ts.map +1 -1
  209. package/dist/lib/conversations.module.js +27 -5
  210. package/dist/lib/conversations.module.js.map +1 -1
  211. package/dist/lib/events/chat-events.d.ts +25 -0
  212. package/dist/lib/events/chat-events.d.ts.map +1 -1
  213. package/dist/lib/events/chat-events.js +36 -0
  214. package/dist/lib/events/chat-events.js.map +1 -1
  215. package/dist/lib/models/agent-turn.model.d.ts +5 -0
  216. package/dist/lib/models/agent-turn.model.d.ts.map +1 -1
  217. package/dist/lib/models/agent-turn.model.js.map +1 -1
  218. package/dist/lib/services/agent-state.service.d.ts +34 -8
  219. package/dist/lib/services/agent-state.service.d.ts.map +1 -1
  220. package/dist/lib/services/agent-state.service.js +90 -37
  221. package/dist/lib/services/agent-state.service.js.map +1 -1
  222. package/dist/lib/services/artifact-state.service.d.ts +0 -9
  223. package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
  224. package/dist/lib/services/artifact-state.service.js +1 -32
  225. package/dist/lib/services/artifact-state.service.js.map +1 -1
  226. package/dist/lib/services/browser-realtime-media-host.d.ts +19 -7
  227. package/dist/lib/services/browser-realtime-media-host.d.ts.map +1 -1
  228. package/dist/lib/services/browser-realtime-media-host.js +21 -72
  229. package/dist/lib/services/browser-realtime-media-host.js.map +1 -1
  230. package/dist/lib/services/conversation-agent.service.d.ts +48 -16
  231. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  232. package/dist/lib/services/conversation-agent.service.js +110 -35
  233. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  234. package/dist/lib/services/conversation-detail-window.store.d.ts +22 -4
  235. package/dist/lib/services/conversation-detail-window.store.d.ts.map +1 -1
  236. package/dist/lib/services/conversation-detail-window.store.js +50 -9
  237. package/dist/lib/services/conversation-detail-window.store.js.map +1 -1
  238. package/dist/lib/services/conversation-naming.d.ts +72 -22
  239. package/dist/lib/services/conversation-naming.d.ts.map +1 -1
  240. package/dist/lib/services/conversation-naming.js +93 -12
  241. package/dist/lib/services/conversation-naming.js.map +1 -1
  242. package/dist/lib/services/conversation-tasks-filter.d.ts +15 -0
  243. package/dist/lib/services/conversation-tasks-filter.d.ts.map +1 -0
  244. package/dist/lib/services/conversation-tasks-filter.js +69 -0
  245. package/dist/lib/services/conversation-tasks-filter.js.map +1 -0
  246. package/dist/lib/services/data-cache.service.d.ts +13 -5
  247. package/dist/lib/services/data-cache.service.d.ts.map +1 -1
  248. package/dist/lib/services/data-cache.service.js +39 -19
  249. package/dist/lib/services/data-cache.service.js.map +1 -1
  250. package/dist/lib/services/export.service.d.ts +26 -9
  251. package/dist/lib/services/export.service.d.ts.map +1 -1
  252. package/dist/lib/services/export.service.js +61 -18
  253. package/dist/lib/services/export.service.js.map +1 -1
  254. package/dist/lib/services/realtime-audio-recorder.d.ts +115 -79
  255. package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -1
  256. package/dist/lib/services/realtime-audio-recorder.js +273 -186
  257. package/dist/lib/services/realtime-audio-recorder.js.map +1 -1
  258. package/dist/lib/services/realtime-pairing.d.ts +10 -5
  259. package/dist/lib/services/realtime-pairing.d.ts.map +1 -1
  260. package/dist/lib/services/realtime-pairing.js +15 -6
  261. package/dist/lib/services/realtime-pairing.js.map +1 -1
  262. package/dist/lib/services/realtime-session.service.d.ts +31 -2
  263. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  264. package/dist/lib/services/realtime-session.service.js +34 -2
  265. package/dist/lib/services/realtime-session.service.js.map +1 -1
  266. package/dist/lib/services/recording/libopus-wasm-binary.d.ts +3 -0
  267. package/dist/lib/services/recording/libopus-wasm-binary.d.ts.map +1 -0
  268. package/dist/lib/services/recording/libopus-wasm-binary.js +489 -0
  269. package/dist/lib/services/recording/libopus-wasm-binary.js.map +1 -0
  270. package/dist/lib/services/recording/libopus-worker-source.d.ts +48 -0
  271. package/dist/lib/services/recording/libopus-worker-source.d.ts.map +1 -0
  272. package/dist/lib/services/recording/libopus-worker-source.js +170 -0
  273. package/dist/lib/services/recording/libopus-worker-source.js.map +1 -0
  274. package/dist/lib/services/recording/linear-resampler.d.ts +45 -0
  275. package/dist/lib/services/recording/linear-resampler.d.ts.map +1 -0
  276. package/dist/lib/services/recording/linear-resampler.js +85 -0
  277. package/dist/lib/services/recording/linear-resampler.js.map +1 -0
  278. package/dist/lib/services/recording/opus-packet-encoder.d.ts +50 -0
  279. package/dist/lib/services/recording/opus-packet-encoder.d.ts.map +1 -0
  280. package/dist/lib/services/recording/opus-packet-encoder.js +41 -0
  281. package/dist/lib/services/recording/opus-packet-encoder.js.map +1 -0
  282. package/dist/lib/services/recording/wasm-opus-encoder.d.ts +86 -0
  283. package/dist/lib/services/recording/wasm-opus-encoder.d.ts.map +1 -0
  284. package/dist/lib/services/recording/wasm-opus-encoder.js +232 -0
  285. package/dist/lib/services/recording/wasm-opus-encoder.js.map +1 -0
  286. package/dist/lib/services/recording/webcodecs-opus-encoder.d.ts +39 -0
  287. package/dist/lib/services/recording/webcodecs-opus-encoder.d.ts.map +1 -0
  288. package/dist/lib/services/recording/webcodecs-opus-encoder.js +101 -0
  289. package/dist/lib/services/recording/webcodecs-opus-encoder.js.map +1 -0
  290. package/dist/lib/services/search.service.d.ts +7 -2
  291. package/dist/lib/services/search.service.d.ts.map +1 -1
  292. package/dist/lib/services/search.service.js +16 -20
  293. package/dist/lib/services/search.service.js.map +1 -1
  294. package/dist/lib/utils/conversation-branching.d.ts +4 -0
  295. package/dist/lib/utils/conversation-branching.d.ts.map +1 -0
  296. package/dist/lib/utils/conversation-branching.js +5 -0
  297. package/dist/lib/utils/conversation-branching.js.map +1 -0
  298. package/dist/lib/utils/conversation-forks.d.ts +315 -0
  299. package/dist/lib/utils/conversation-forks.d.ts.map +1 -0
  300. package/dist/lib/utils/conversation-forks.js +456 -0
  301. package/dist/lib/utils/conversation-forks.js.map +1 -0
  302. package/dist/lib/utils/distinct-artifacts.d.ts +9 -3
  303. package/dist/lib/utils/distinct-artifacts.d.ts.map +1 -1
  304. package/dist/lib/utils/distinct-artifacts.js +24 -5
  305. package/dist/lib/utils/distinct-artifacts.js.map +1 -1
  306. package/dist/public-api.d.ts +23 -1
  307. package/dist/public-api.d.ts.map +1 -1
  308. package/dist/public-api.js +30 -1
  309. package/dist/public-api.js.map +1 -1
  310. package/package.json +37 -33
  311. package/dist/lib/components/thread/thread-panel.component.d.ts +0 -126
  312. package/dist/lib/components/thread/thread-panel.component.d.ts.map +0 -1
  313. package/dist/lib/components/thread/thread-panel.component.js +0 -440
  314. package/dist/lib/components/thread/thread-panel.component.js.map +0 -1
  315. package/dist/lib/services/realtime-pcm-wav.d.ts +0 -79
  316. package/dist/lib/services/realtime-pcm-wav.d.ts.map +0 -1
  317. package/dist/lib/services/realtime-pcm-wav.js +0 -213
  318. package/dist/lib/services/realtime-pcm-wav.js.map +0 -1
@@ -12,6 +12,7 @@ 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';
17
18
  import { InjectFrameZone } from '../../util/frame-zone';
@@ -105,6 +106,17 @@ export class MessageInputComponent extends BaseAngularComponent {
105
106
  * Blocks sending. Distinct from {@link Disabled}, which means the composer is busy.
106
107
  */
107
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;
108
120
  Placeholder = 'Type a message... (Ctrl+Enter to send)';
109
121
  /** @deprecated Use {@link Placeholder}. */
110
122
  set placeholder(value) {
@@ -501,6 +513,16 @@ export class MessageInputComponent extends BaseAngularComponent {
501
513
  * reading past the floor). Null (the default) reads the whole conversation.
502
514
  */
503
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;
504
526
  /**
505
527
  * Runs agent turns on the host's server instead of MJ's own path. The chat area still picks
506
528
  * the agent and fires {@link BeforeAgentTurn}; it then calls the handler once per turn, before
@@ -528,6 +550,8 @@ export class MessageInputComponent extends BaseAngularComponent {
528
550
  * `MJ: AI Prompt Runs` row, even when the answer comes too late to be used.
529
551
  */
530
552
  EnableDecisionRouting = false;
553
+ /** The send slot was clicked in `stop` mode; the chat area stops the run(s). */
554
+ StopClicked = new EventEmitter();
531
555
  MessageSent = new EventEmitter();
532
556
  /**
533
557
  * @deprecated Use {@link MessageSent}.
@@ -861,6 +885,14 @@ export class MessageInputComponent extends BaseAngularComponent {
861
885
  setTimeout(() => this.InputBox?.focus(), 50);
862
886
  }
863
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
+ }
864
896
  IsSending = false;
865
897
  /** @deprecated Use {@link IsSending}. */
866
898
  get isSending() {
@@ -1289,11 +1321,11 @@ export class MessageInputComponent extends BaseAngularComponent {
1289
1321
  this.VoicePickerDefaultCoAgentId = await this.loadPersistedCoAgentId();
1290
1322
  this.ShowRealtimeAgentPicker = true;
1291
1323
  }
1292
- /** 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. */
1293
1325
  async OnRealtimeAgentPicked(pick) {
1294
1326
  this.ShowRealtimeAgentPicker = false;
1295
1327
  this.persistCoAgentChoice(pick.CoAgentId);
1296
- 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);
1297
1329
  }
1298
1330
  /** @deprecated Use {@link OnRealtimeAgentPicked}. */
1299
1331
  async onRealtimeAgentPicked(pick) {
@@ -1364,7 +1396,7 @@ export class MessageInputComponent extends BaseAngularComponent {
1364
1396
  * uses exactly that model or fails with a clear reason (no silent fallback) — and is
1365
1397
  * mirrored into `configOverridesJson` (`{"realtime":{"modelPreference":…}}`, the
1366
1398
  * pinned override envelope). An explicit co-agent choice (picker pick or persisted
1367
- * preference) rides along as `coAgentId`.
1399
+ * preference) rides along as `coAgentId`. The session runs on {@link TargetBranchID}.
1368
1400
  *
1369
1401
  * Interactive-channel tools (e.g. the live whiteboard's `Whiteboard_*` set) are NOT
1370
1402
  * passed here — the session service resolves the active channel plugins from the
@@ -1376,7 +1408,9 @@ export class MessageInputComponent extends BaseAngularComponent {
1376
1408
  // App awareness: the app the session runs in + the live app-context snapshot (where the
1377
1409
  // user is, what they see, capability manifest) — drives the server-side app cascade + the
1378
1410
  // mint-time prompt injection, and seeds the ClientContextChannel's streaming.
1379
- 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 });
1380
1414
  }
1381
1415
  catch (error) {
1382
1416
  console.error('Failed to start voice session:', error);
@@ -1596,7 +1630,12 @@ export class MessageInputComponent extends BaseAngularComponent {
1596
1630
  // Store attachments locally since we'll clear them after send
1597
1631
  const attachmentsToSave = [...this.pendingAttachments];
1598
1632
  try {
1599
- 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);
1600
1639
  const saved = await messageDetail.Save();
1601
1640
  if (saved) {
1602
1641
  // Save attachments if any were pending
@@ -1672,7 +1711,11 @@ export class MessageInputComponent extends BaseAngularComponent {
1672
1711
  return;
1673
1712
  this.IsSending = true;
1674
1713
  try {
1675
- 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);
1676
1719
  const saved = await messageDetail.Save();
1677
1720
  if (saved) {
1678
1721
  await this.handleSuccessfulSend(messageDetail);
@@ -1702,18 +1745,28 @@ export class MessageInputComponent extends BaseAngularComponent {
1702
1745
  * tick — the `attachmentsChanged` event chain hasn't propagated yet, so
1703
1746
  * `this.pendingAttachments` may not contain the attachment. Pass it in
1704
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.
1705
1756
  */
1706
- async SendMessageWithText(text, extraAttachments) {
1757
+ async SendMessageWithText(text, extraAttachments, options) {
1707
1758
  if (this.ReadOnly) {
1708
1759
  return false;
1709
1760
  }
1761
+ const isResend = options?.IsResend === true;
1762
+ const draftAttachments = isResend ? [] : this.pendingAttachments;
1710
1763
  const merged = (() => {
1711
1764
  if (!extraAttachments || extraAttachments.length === 0) {
1712
- return [...this.pendingAttachments];
1765
+ return [...draftAttachments];
1713
1766
  }
1714
1767
  const seen = new Set();
1715
1768
  const out = [];
1716
- for (const a of [...this.pendingAttachments, ...extraAttachments]) {
1769
+ for (const a of [...draftAttachments, ...extraAttachments]) {
1717
1770
  if (seen.has(a.id))
1718
1771
  continue;
1719
1772
  seen.add(a.id);
@@ -1732,11 +1785,16 @@ export class MessageInputComponent extends BaseAngularComponent {
1732
1785
  this.IsSending = true;
1733
1786
  const attachmentsToSave = merged;
1734
1787
  try {
1788
+ const branchId = await this.resolveSendBranch(options?.TargetBranchID);
1789
+ if (branchId === undefined) {
1790
+ return false;
1791
+ }
1735
1792
  const detail = await this.dataCache.createConversationDetail(this.CurrentUser);
1736
1793
  detail.ConversationID = this.ConversationId;
1737
1794
  detail.Message = text?.trim() || '';
1738
1795
  detail.Role = 'User';
1739
1796
  detail.UserID = this.CurrentUser.ID; // Set the user who sent the message
1797
+ detail.BranchID = branchId;
1740
1798
  if (this.ParentMessageId) {
1741
1799
  detail.ParentID = this.ParentMessageId;
1742
1800
  }
@@ -1777,16 +1835,18 @@ export class MessageInputComponent extends BaseAngularComponent {
1777
1835
  return false;
1778
1836
  }
1779
1837
  }
1780
- // Clear pending attachments after successful send
1781
- this.pendingAttachments = [];
1782
- // Also clear the mention editor's content + its own attachments list.
1783
- // The user-initiated send path (MessageInputBoxComponent.onSendClick)
1784
- // calls mentionEditor.clear() — we bypass that path here, so the chips
1785
- // would otherwise stay on screen after the message goes out.
1786
- 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
+ }
1787
1847
  this.MessageSent.emit(detail);
1788
1848
  const mentionResult = this.parseMentionsFromMessage(detail.Message);
1789
- const isFirstMessage = this.ConversationHistory.length === 0;
1849
+ const isFirstMessage = !isResend && this.ConversationHistory.length === 0;
1790
1850
  await this.routeMessage(detail, mentionResult, isFirstMessage);
1791
1851
  return true;
1792
1852
  }
@@ -1808,28 +1868,86 @@ export class MessageInputComponent extends BaseAngularComponent {
1808
1868
  return this.SendMessageWithText(text, extraAttachments);
1809
1869
  }
1810
1870
  /**
1811
- * 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.
1812
1896
  */
1813
- async createMessageDetail() {
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)
1927
+ */
1928
+ async createMessageDetail(branchId) {
1814
1929
  const detail = await this.dataCache.createConversationDetail(this.CurrentUser);
1815
1930
  detail.ConversationID = this.ConversationId;
1816
1931
  detail.Message = this.MessageText.trim();
1817
1932
  detail.Role = 'User';
1818
1933
  detail.UserID = this.CurrentUser.ID; // Set the user who sent the message
1934
+ detail.BranchID = branchId;
1819
1935
  if (this.ParentMessageId) {
1820
1936
  detail.ParentID = this.ParentMessageId;
1821
1937
  }
1822
1938
  return detail;
1823
1939
  }
1824
1940
  /**
1825
- * 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)
1826
1943
  */
1827
- async createMessageDetailFromText(text) {
1944
+ async createMessageDetailFromText(text, branchId) {
1828
1945
  const detail = await this.dataCache.createConversationDetail(this.CurrentUser);
1829
1946
  detail.ConversationID = this.ConversationId;
1830
1947
  detail.Message = text;
1831
1948
  detail.Role = 'User';
1832
1949
  detail.UserID = this.CurrentUser.ID; // Set the user who sent the message
1950
+ detail.BranchID = branchId;
1833
1951
  if (this.ParentMessageId) {
1834
1952
  detail.ParentID = this.ParentMessageId;
1835
1953
  }
@@ -1863,8 +1981,13 @@ export class MessageInputComponent extends BaseAngularComponent {
1863
1981
  * last agent's place ({@link decideAgentRouting}).
1864
1982
  * {@link BeforeAgentTurn} is then fired once, before any reply row exists, and the turn runs on
1865
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.
1866
1988
  */
1867
- async routeMessage(messageDetail, mentionResult, isFirstMessage) {
1989
+ async routeMessage(messageDetail, mentionResult, isFirstMessage, turnBranchId) {
1990
+ const branchId = turnBranchId !== undefined ? turnBranchId : (messageDetail.BranchID ?? null);
1868
1991
  // A Plan Mode choice made on the new-conversation composer (no conversation yet) lives in a
1869
1992
  // pending bucket — the FIRST routed message claims it onto the real conversation so the
1870
1993
  // toggle carries across the empty-state → chat-area transition without bleeding into other
@@ -1890,7 +2013,7 @@ export class MessageInputComponent extends BaseAngularComponent {
1890
2013
  // another conversation, and the chat area then rebinds its history and pinned agent, so a
1891
2014
  // read after the routing decision could see another conversation's state (or none).
1892
2015
  const candidates = this.agentTurnCandidates(this.agentMentionIds(mentionResult));
1893
- const routing = await this.decideAgentRouting(messageDetail, candidates);
2016
+ const routing = await this.decideAgentRouting(messageDetail, candidates, branchId);
1894
2017
  const target = this.resolveAgentTurnTarget(candidates, routing);
1895
2018
  if (!target) {
1896
2019
  await this.finishWithoutAgentTurn(messageDetail, 'NoAgent');
@@ -1901,7 +2024,7 @@ export class MessageInputComponent extends BaseAngularComponent {
1901
2024
  await this.finishWithoutAgentTurn(messageDetail, 'Declined');
1902
2025
  return;
1903
2026
  }
1904
- await this.runAgentTurn(messageDetail, mentionResult, turn, routing);
2027
+ await this.runAgentTurn(messageDetail, mentionResult, turn, branchId, routing);
1905
2028
  }
1906
2029
  /**
1907
2030
  * Asks the routing decision for this message when {@link EnableDecisionRouting} is on and the
@@ -1909,8 +2032,9 @@ export class MessageInputComponent extends BaseAngularComponent {
1909
2032
  * when anything fails: the message then keeps today's routing.
1910
2033
  *
1911
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.
1912
2036
  */
1913
- async decideAgentRouting(message, candidates) {
2037
+ async decideAgentRouting(message, candidates, branchId) {
1914
2038
  const continuityAgentId = candidates.ContinuityAgentId;
1915
2039
  const qualifies = ShouldRunRoutingDecision({
1916
2040
  Enabled: this.EnableDecisionRouting,
@@ -1928,7 +2052,7 @@ export class MessageInputComponent extends BaseAngularComponent {
1928
2052
  if (!CanAskRoutingDecision(input)) {
1929
2053
  return null;
1930
2054
  }
1931
- input.ArtifactVersions = await this.loadRoutingArtifactVersions(message.ConversationID, input.Participants);
2055
+ input.ArtifactVersions = await this.loadRoutingArtifactVersions(message.ConversationID, branchId, input.Participants);
1932
2056
  const outcome = await RunRoutingDecision(input, params => this.agentService.RunDecision(params));
1933
2057
  LogStatusEx({
1934
2058
  message: `Decision routing: ${outcome.Verdict}, ${outcome.Reason} (prompt run ${outcome.PromptRunID ?? 'none'})`,
@@ -1955,7 +2079,7 @@ export class MessageInputComponent extends BaseAngularComponent {
1955
2079
  */
1956
2080
  buildRoutingDecisionInput(message, continuityAgentId) {
1957
2081
  const history = this.ConversationHistory.filter(row => this.isWithinHistoryFloor(row) && !UUIDsEqual(row.ID, message.ID));
1958
- const findAgent = (agentId) => AIEngineBase.Instance.Agents.find(a => UUIDsEqual(a.ID, agentId));
2082
+ const findAgent = (agentId) => AIEngineBase.Instance.ReadableAgents.find(a => UUIDsEqual(a.ID, agentId));
1959
2083
  const runnable = this.mentionAutocomplete.GetAvailableAgents();
1960
2084
  const findRunnable = (agentId) => runnable.find(a => UUIDsEqual(a.ID, agentId));
1961
2085
  const manager = this.ConverationManagerAgent;
@@ -1969,11 +2093,11 @@ export class MessageInputComponent extends BaseAngularComponent {
1969
2093
  AllowedAgentIDs: this.AllowedAgentIDs
1970
2094
  };
1971
2095
  }
1972
- /** Every participant's artifact versions in this conversation, for the artifact question. */
1973
- 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) {
1974
2098
  const artifactsByAgent = await Promise.all(participants.map(async (participant) => ({
1975
2099
  Agent: participant.Agent,
1976
- Artifacts: await this.agentService.FindAgentArtifacts(conversationId, participant.Agent.ID, this.AgentHistoryFrom)
2100
+ Artifacts: await this.agentService.FindAgentArtifacts(conversationId, participant.Agent.ID, this.AgentHistoryFrom, branchId)
1977
2101
  })));
1978
2102
  return BuildRoutingArtifactVersions(artifactsByAgent);
1979
2103
  }
@@ -2041,23 +2165,26 @@ export class MessageInputComponent extends BaseAngularComponent {
2041
2165
  * Runs a turn that {@link BeforeAgentTurn} let through, on the host's handler or MJ's path.
2042
2166
  * The routing decision, when there was one, supplies the artifact version the turn's agent
2043
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.
2044
2171
  */
2045
- async runAgentTurn(userMessage, mentionResult, turn, routing = null) {
2172
+ async runAgentTurn(userMessage, mentionResult, turn, branchId, routing = null) {
2046
2173
  const mention = turn.Route === 'Mention' ? this.findAgentMention(mentionResult, turn.AgentId) : null;
2047
2174
  const targetArtifactVersionId = ArtifactVersionForTurn(routing, turn.AgentId);
2048
2175
  if (this.AgentTurnHandler) {
2049
- await this.runHostAgentTurn(this.AgentTurnHandler, userMessage, turn, mention, targetArtifactVersionId);
2176
+ await this.runHostAgentTurn(this.AgentTurnHandler, userMessage, turn, mention, targetArtifactVersionId, branchId);
2050
2177
  return;
2051
2178
  }
2052
2179
  if (mention) {
2053
- await this.invokeAgentDirectly(userMessage, mention, userMessage.ConversationID);
2180
+ await this.invokeAgentDirectly(userMessage, mention, userMessage.ConversationID, branchId);
2054
2181
  }
2055
2182
  else if (turn.Route === 'ConversationManager' || (turn.Route === 'Redirect' && this.isConversationManager(turn.AgentId))) {
2056
- await this.runConversationManagerTurn(userMessage, mentionResult);
2183
+ await this.runConversationManagerTurn(userMessage, mentionResult, branchId);
2057
2184
  }
2058
2185
  else {
2059
2186
  // Pinned and host defaults keep their direct call even when they name the manager, as before.
2060
- await this.handleAgentContinuity(userMessage, turn.AgentId, targetArtifactVersionId);
2187
+ await this.handleAgentContinuity(userMessage, turn.AgentId, branchId, targetArtifactVersionId);
2061
2188
  }
2062
2189
  }
2063
2190
  /**
@@ -2102,30 +2229,33 @@ export class MessageInputComponent extends BaseAngularComponent {
2102
2229
  * ({@link decideAgentRouting}); the prompt-based check stays unused. A confident answer from it
2103
2230
  * may name the artifact version this agent should continue from.
2104
2231
  *
2232
+ * @param branchId The turn's branch (null is Main).
2105
2233
  * @param targetArtifactVersionId The artifact version the routing decision named, or null.
2106
2234
  */
2107
- async handleAgentContinuity(messageDetail, agentId, targetArtifactVersionId = null) {
2108
- 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
2109
2237
  );
2110
2238
  }
2111
2239
  /**
2112
2240
  * The conversation manager's turn. When an earlier message @mentioned the manager with a
2113
2241
  * configuration preset, the preset keeps applying and the manager answers directly;
2114
2242
  * otherwise it evaluates the message and may delegate.
2243
+ *
2244
+ * @param branchId The turn's branch (null is Main).
2115
2245
  */
2116
- async runConversationManagerTurn(messageDetail, mentionResult) {
2246
+ async runConversationManagerTurn(messageDetail, mentionResult, branchId) {
2117
2247
  const manager = this.ConverationManagerAgent;
2118
2248
  const managerPreset = manager?.ID && messageDetail.ConversationID
2119
- ? await this.agentService.FindConfigurationPresetForAgent(messageDetail.ConversationID, manager.ID)
2249
+ ? await this.agentService.FindConfigurationPresetForAgent(messageDetail.ConversationID, manager.ID, branchId)
2120
2250
  : undefined;
2121
2251
  if (manager?.ID && managerPreset) {
2122
- 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
2123
2253
  null, // Sage doesn't use artifact info
2124
2254
  managerPreset // Pass the already-found config preset
2125
2255
  );
2126
2256
  return;
2127
2257
  }
2128
- await this.processMessageThroughAgent(messageDetail, mentionResult);
2258
+ await this.processMessageThroughAgent(messageDetail, mentionResult, branchId);
2129
2259
  }
2130
2260
  /**
2131
2261
  * The newest reply from an agent other than the conversation manager — among the replies a
@@ -2157,15 +2287,15 @@ export class MessageInputComponent extends BaseAngularComponent {
2157
2287
  }
2158
2288
  /** True when the agent is in the client's agent catalog. */
2159
2289
  isKnownAgent(agentId) {
2160
- return AIEngineBase.Instance.Agents.some(a => UUIDsEqual(a.ID, agentId));
2290
+ return AIEngineBase.Instance.ReadableAgents.some(a => UUIDsEqual(a.ID, agentId));
2161
2291
  }
2162
2292
  /** The agent's name, when the client's agent catalog has it. */
2163
2293
  agentNameFor(agentId) {
2164
- return AIEngineBase.Instance.Agents.find(a => UUIDsEqual(a.ID, agentId))?.Name ?? null;
2294
+ return AIEngineBase.Instance.ReadableAgents.find(a => UUIDsEqual(a.ID, agentId))?.Name ?? null;
2165
2295
  }
2166
2296
  /** The ID of the agent with this name, or null when there is none. */
2167
2297
  agentIdByName(agentName) {
2168
- return AIEngineBase.Instance.Agents.find(a => a.Name === agentName)?.ID ?? null;
2298
+ return AIEngineBase.Instance.ReadableAgents.find(a => a.Name === agentName)?.ID ?? null;
2169
2299
  }
2170
2300
  /** True when the agent is MJ's conversation manager. */
2171
2301
  isConversationManager(agentId) {
@@ -2190,9 +2320,11 @@ export class MessageInputComponent extends BaseAngularComponent {
2190
2320
  * Runs the turn through the host's {@link AgentTurnHandler} instead of MJ's path. Nothing is
2191
2321
  * written here: the host writes the reply rows and reports them, and each is shown like a row
2192
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`.
2193
2325
  */
2194
- async runHostAgentTurn(handler, userMessage, turn, mention, targetArtifactVersionId) {
2195
- 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);
2196
2328
  const result = await this.callAgentTurnHandler(handler, request);
2197
2329
  if (!result.Success) {
2198
2330
  this.notifyAgentTurnProblem(result.ErrorMessage || 'The agent could not answer this message.', 'error');
@@ -2220,10 +2352,12 @@ export class MessageInputComponent extends BaseAngularComponent {
2220
2352
  *
2221
2353
  * @param targetArtifactVersionId The artifact version the routing decision named for this
2222
2354
  * turn's agent, or null.
2355
+ * @param branchId The turn's branch (null is Main).
2223
2356
  */
2224
- buildAgentTurnRequest(userMessage, turn, mention, targetArtifactVersionId) {
2357
+ buildAgentTurnRequest(userMessage, turn, mention, targetArtifactVersionId, branchId) {
2225
2358
  return {
2226
2359
  ConversationId: userMessage.ConversationID,
2360
+ BranchID: branchId,
2227
2361
  UserMessageId: userMessage.ID,
2228
2362
  MessageText: userMessage.Message ?? '',
2229
2363
  AgentId: turn.AgentId,
@@ -2256,10 +2390,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2256
2390
  this.AfterAgentTurn.emit(new AfterAgentTurnEventArgs(conversationId, agentRunId ?? result.agentRun?.ID ?? '', result));
2257
2391
  }
2258
2392
  /**
2259
- * Checks if message should continue with the previous agent
2260
- * 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
2261
2395
  */
2262
- async checkContinuityIntent(agentId, message) {
2396
+ async checkContinuityIntent(agentId, message, branchId) {
2263
2397
  // FAST PATH: If message contains form response syntax, skip the intent check entirely
2264
2398
  // Form responses always continue with the agent that requested the form
2265
2399
  // Don't show "Analyzing intent..." message for this obvious case
@@ -2281,7 +2415,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2281
2415
  console.warn('⚠️ No conversation id available for intent check');
2282
2416
  return { decision: 'UNSURE', reasoning: 'Conversation not available' };
2283
2417
  }
2284
- 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);
2285
2419
  return intent;
2286
2420
  }
2287
2421
  catch (error) {
@@ -2392,8 +2526,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2392
2526
  * Process the message through agents (multi-stage: Sage -> possible sub-agent)
2393
2527
  * Only called when there's no @mention and no implicit agent context.
2394
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).
2395
2531
  */
2396
- async processMessageThroughAgent(userMessage, mentionResult) {
2532
+ async processMessageThroughAgent(userMessage, mentionResult, branchId) {
2397
2533
  let taskId = null;
2398
2534
  let conversationManagerMessage = null;
2399
2535
  // CRITICAL: Capture conversationId from user message at start
@@ -2401,13 +2537,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2401
2537
  const conversationId = userMessage.ConversationID;
2402
2538
  try {
2403
2539
  // Create AI message for Sage BEFORE invoking
2404
- conversationManagerMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2405
- conversationManagerMessage.ConversationID = conversationId;
2406
- conversationManagerMessage.Role = 'AI';
2540
+ conversationManagerMessage = await this.createTurnRow(conversationId, branchId);
2407
2541
  conversationManagerMessage.Message = '⏳ Starting...';
2408
2542
  conversationManagerMessage.ParentID = userMessage.ID;
2409
2543
  conversationManagerMessage.Status = 'In-Progress';
2410
- conversationManagerMessage.HiddenToUser = false;
2411
2544
  // Use the preloaded Sage agent instead of looking it up
2412
2545
  if (this.ConverationManagerAgent?.ID) {
2413
2546
  conversationManagerMessage.AgentID = this.ConverationManagerAgent.ID;
@@ -2444,7 +2577,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2444
2577
  }
2445
2578
  // Stage 2: Check for task graph (multi-step orchestration)
2446
2579
  if (result.payload?.taskGraph) {
2447
- await this.handleTaskGraphExecution(userMessage, result, conversationId, conversationManagerMessage);
2580
+ await this.handleTaskGraphExecution(userMessage, result, conversationId, branchId, conversationManagerMessage);
2448
2581
  // Remove CM from active tasks
2449
2582
  if (taskId) {
2450
2583
  // Task removed in markMessageComplete() - this.activeTasks.remove(taskId);
@@ -2453,7 +2586,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2453
2586
  // Stage 3: Check for sub-agent invocation (single-step delegation)
2454
2587
  else if (result.agentRun.FinalStep === 'Success' && result.payload?.invokeAgent) {
2455
2588
  // Reuse the existing conversationManagerMessage instead of creating new ones
2456
- await this.handleSubAgentInvocation(userMessage, result, conversationId, conversationManagerMessage);
2589
+ await this.handleSubAgentInvocation(userMessage, result, conversationId, branchId, conversationManagerMessage);
2457
2590
  // Remove CM from active tasks
2458
2591
  if (taskId) {
2459
2592
  // Task removed in markMessageComplete() - this.activeTasks.remove(taskId);
@@ -2500,7 +2633,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2500
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
2501
2634
  await this.updateConversationDetail(conversationManagerMessage, conversationManagerMessage.Message, 'Complete', result);
2502
2635
  this.MessageSent.emit(conversationManagerMessage);
2503
- await this.handleSilentObservation(userMessage, conversationId);
2636
+ await this.handleSilentObservation(userMessage, conversationId, branchId);
2504
2637
  // Clean up completion timestamp after delay
2505
2638
  this.cleanupCompletionTimestamp(conversationManagerMessage.ID);
2506
2639
  }
@@ -2552,8 +2685,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2552
2685
  * Single-task graphs are no longer special-cased here. The old client-side fork ran them through
2553
2686
  * a different code path entirely; they now submit like any other graph, and the decision about
2554
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.
2555
2690
  */
2556
- async handleTaskGraphExecution(userMessage, managerResult, conversationId, conversationManagerMessage) {
2691
+ async handleTaskGraphExecution(userMessage, managerResult, conversationId, branchId, conversationManagerMessage) {
2557
2692
  // `payload` is untyped by construction (an agent's payload shape is agent-specific), so pin the
2558
2693
  // graph to the operation's own input contract at the boundary rather than letting it stay loose.
2559
2694
  const taskGraph = managerResult.payload?.taskGraph;
@@ -2570,13 +2705,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2570
2705
  const reasoning = taskGraph.reasoning || 'Executing multi-step workflow';
2571
2706
  const taskCount = Array.isArray(taskGraph.tasks) ? taskGraph.tasks.length : 0;
2572
2707
  // A message the user can watch. Progress frames from the dispatcher land against this ID.
2573
- const taskExecutionMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2574
- taskExecutionMessage.ConversationID = conversationId;
2575
- taskExecutionMessage.Role = 'AI';
2708
+ const taskExecutionMessage = await this.createTurnRow(conversationId, branchId);
2576
2709
  taskExecutionMessage.Message = `⏳ **${workflowName}**\n\n${reasoning}\n\nSubmitting ${taskCount} task(s)…`;
2577
2710
  taskExecutionMessage.ParentID = conversationManagerMessage.ID;
2578
2711
  taskExecutionMessage.Status = 'In-Progress';
2579
- taskExecutionMessage.HiddenToUser = false;
2580
2712
  await taskExecutionMessage.Save();
2581
2713
  this.MessageSent.emit(taskExecutionMessage);
2582
2714
  const callback = this.createMessageProgressCallback(taskExecutionMessage.ID);
@@ -2675,13 +2807,13 @@ export class MessageInputComponent extends BaseAngularComponent {
2675
2807
  * artifact below the window's oldest row — and a null payload is a legal agent input, so
2676
2808
  * the miss surfaces as the agent regenerating from scratch instead of modifying. Covers
2677
2809
  * system-visibility artifacts (Agent Manager and friends) for free: the query filters on
2678
- * Direction, not on Visibility.
2810
+ * Direction, not on Visibility. Only the path of `branchId` (null is Main) is read.
2679
2811
  */
2680
- async loadPreviousPayloadForAgent(agentId) {
2812
+ async loadPreviousPayloadForAgent(agentId, branchId) {
2681
2813
  if (!this.ConversationId) {
2682
2814
  return { payload: null, artifactInfo: null };
2683
2815
  }
2684
- const source = await this.agentService.FindLatestAgentOutputVersion(this.ConversationId, agentId, this.AgentHistoryFrom);
2816
+ const source = await this.agentService.FindLatestAgentOutputVersion(this.ConversationId, agentId, this.AgentHistoryFrom, branchId);
2685
2817
  if (!source || source.payload == null) {
2686
2818
  console.log(`📦 No previous payload found for agent ${agentId}`);
2687
2819
  return { payload: null, artifactInfo: null };
@@ -2699,8 +2831,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2699
2831
  /**
2700
2832
  * Handle sub-agent invocation based on Sage's payload
2701
2833
  * Reuses the existing conversationManagerMessage to avoid creating multiple records
2834
+ *
2835
+ * @param branchId The turn's branch (null is Main).
2702
2836
  */
2703
- async handleSubAgentInvocation(userMessage, managerResult, conversationId, conversationManagerMessage) {
2837
+ async handleSubAgentInvocation(userMessage, managerResult, conversationId, branchId, conversationManagerMessage) {
2704
2838
  const payload = managerResult.payload;
2705
2839
  const agentName = payload.invokeAgent;
2706
2840
  const reasoning = payload.reasoning || 'Delegating to specialist agent';
@@ -2708,7 +2842,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2708
2842
  let agentResponseMessage = null;
2709
2843
  try {
2710
2844
  // Look up the agent to get its ID
2711
- const agent = AIEngineBase.Instance.Agents.find(a => a.Name === agentName);
2845
+ const agent = AIEngineBase.Instance.ReadableAgents.find(a => a.Name === agentName);
2712
2846
  // The manager routes only among the allowed agents, but its answer is model output: hold
2713
2847
  // the host's list here too, before any row is written for the delegate.
2714
2848
  if (this.AllowedAgentIDs != null && !IsAgentAllowed(agent?.ID, this.AllowedAgentIDs)) {
@@ -2716,13 +2850,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2716
2850
  return;
2717
2851
  }
2718
2852
  // Create AI response message BEFORE invoking agent (for duration tracking)
2719
- agentResponseMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2720
- agentResponseMessage.ConversationID = conversationId;
2721
- agentResponseMessage.Role = 'AI';
2853
+ agentResponseMessage = await this.createTurnRow(conversationId, branchId);
2722
2854
  agentResponseMessage.Message = '⏳ Starting...'; // Initial message
2723
2855
  agentResponseMessage.ParentID = conversationManagerMessage.ID; // Thread under delegation message
2724
2856
  agentResponseMessage.Status = 'In-Progress';
2725
- agentResponseMessage.HiddenToUser = false;
2726
2857
  // Set AgentID immediately for proper attribution
2727
2858
  if (agent?.ID) {
2728
2859
  agentResponseMessage.AgentID = agent.ID;
@@ -2741,11 +2872,11 @@ export class MessageInputComponent extends BaseAngularComponent {
2741
2872
  });
2742
2873
  // Load previous payload if agent has been invoked before
2743
2874
  const { payload: previousPayload, artifactInfo } = agent?.ID
2744
- ? await this.loadPreviousPayloadForAgent(agent.ID)
2875
+ ? await this.loadPreviousPayloadForAgent(agent.ID, branchId)
2745
2876
  : { payload: null, artifactInfo: null };
2746
2877
  // Find configuration preset from previous @mention in conversation history
2747
2878
  const configurationPresetId = agent?.ID
2748
- ? await this.agentService.FindConfigurationPresetForAgent(conversationId, agent.ID)
2879
+ ? await this.agentService.FindConfigurationPresetForAgent(conversationId, agent.ID, branchId)
2749
2880
  : undefined;
2750
2881
  // Invoke the sub-agent with progress callback
2751
2882
  const subResult = await this.agentService.invokeSubAgent(agentName, conversationId, userMessage, this.ConversationHistory, reasoning, agentResponseMessage.ID, previousPayload, // Pass previous payload for continuity
@@ -2835,8 +2966,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2835
2966
  /**
2836
2967
  * Handle silent observation - when Sage stays silent,
2837
2968
  * check if we should continue with the last agent for iterative refinement
2969
+ *
2970
+ * @param branchId The turn's branch (null is Main).
2838
2971
  */
2839
- async handleSilentObservation(userMessage, conversationId) {
2972
+ async handleSilentObservation(userMessage, conversationId, branchId) {
2840
2973
  // Find the last AI message (excluding Sage) this turn may read
2841
2974
  const lastAIMessage = this.findLastNonSageReply();
2842
2975
  if (!lastAIMessage || !lastAIMessage.AgentID) {
@@ -2851,7 +2984,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2851
2984
  return;
2852
2985
  }
2853
2986
  // Load the agent entity to get its name
2854
- const previousAgent = AIEngineBase.Instance.Agents.find(a => UUIDsEqual(a.ID, lastAIMessage.AgentID));
2987
+ const previousAgent = AIEngineBase.Instance.ReadableAgents.find(a => UUIDsEqual(a.ID, lastAIMessage.AgentID));
2855
2988
  if (!previousAgent) {
2856
2989
  console.warn('⚠️ Could not load previous agent - marking complete');
2857
2990
  await this.updateConversationDetail(userMessage, userMessage.Message, 'Complete');
@@ -2863,7 +2996,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2863
2996
  // Resolved by QUERY, not from the window's artifact maps: `lastAIMessage` can sit inside
2864
2997
  // the loaded window while its artifact does not, and this path silently degrades to a
2865
2998
  // null payload when the lookup misses.
2866
- const source = await this.agentService.FindLatestAgentOutputVersion(conversationId, lastAIMessage.AgentID, this.AgentHistoryFrom);
2999
+ const source = await this.agentService.FindLatestAgentOutputVersion(conversationId, lastAIMessage.AgentID, this.AgentHistoryFrom, branchId);
2867
3000
  if (source && source.payload != null) {
2868
3001
  previousPayload = source.payload;
2869
3002
  previousArtifactInfo = {
@@ -2874,13 +3007,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2874
3007
  console.log('📦 Loaded previous OUTPUT artifact as payload for continuity', previousArtifactInfo);
2875
3008
  }
2876
3009
  // Create status message showing agent continuity
2877
- const statusMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2878
- statusMessage.ConversationID = conversationId;
2879
- statusMessage.Role = 'AI';
3010
+ const statusMessage = await this.createTurnRow(conversationId, branchId);
2880
3011
  statusMessage.Message = `Continuing with **${agentName}** for refinement...`;
2881
3012
  statusMessage.ParentID = userMessage.ID;
2882
3013
  statusMessage.Status = 'Complete';
2883
- statusMessage.HiddenToUser = false;
2884
3014
  statusMessage.AgentID = this.ConverationManagerAgent?.ID || null;
2885
3015
  await statusMessage.Save();
2886
3016
  this.MessageSent.emit(statusMessage);
@@ -2904,13 +3034,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2904
3034
  // Task removed in markMessageComplete() - this.activeTasks.remove(taskId);
2905
3035
  if (continuityResult && continuityResult.success) {
2906
3036
  // Create response message
2907
- const agentResponseMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2908
- agentResponseMessage.ConversationID = conversationId;
2909
- agentResponseMessage.Role = 'AI';
3037
+ const agentResponseMessage = await this.createTurnRow(conversationId, branchId);
2910
3038
  agentResponseMessage.Message = continuityResult.agentRun?.Message || `✅ **${agentName}** completed refinement`;
2911
3039
  agentResponseMessage.ParentID = statusMessage.ID;
2912
3040
  agentResponseMessage.Status = 'Complete';
2913
- agentResponseMessage.HiddenToUser = false;
2914
3041
  agentResponseMessage.AgentID = lastAIMessage.AgentID;
2915
3042
  await agentResponseMessage.Save();
2916
3043
  this.MessageSent.emit(agentResponseMessage);
@@ -2936,8 +3063,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2936
3063
  /**
2937
3064
  * Invoke an agent directly when mentioned with @ symbol
2938
3065
  * Bypasses Sage completely - no status messages
3066
+ *
3067
+ * @param branchId The turn's branch (null is Main).
2939
3068
  */
2940
- async invokeAgentDirectly(userMessage, agentMention, conversationId) {
3069
+ async invokeAgentDirectly(userMessage, agentMention, conversationId, branchId) {
2941
3070
  const agentName = agentMention.name;
2942
3071
  // Add agent to active tasks
2943
3072
  const taskId = this.activeTasks.add({
@@ -2957,15 +3086,12 @@ export class MessageInputComponent extends BaseAngularComponent {
2957
3086
  await userMessage.Save();
2958
3087
  this.MessageSent.emit(userMessage);
2959
3088
  // Look up the agent to get its ID
2960
- const agent = AIEngineBase.Instance.Agents.find(a => a.Name === agentName);
3089
+ const agent = AIEngineBase.Instance.ReadableAgents.find(a => a.Name === agentName);
2961
3090
  // Create AI response message BEFORE invoking agent (for duration tracking)
2962
- agentResponseMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
2963
- agentResponseMessage.ConversationID = conversationId;
2964
- agentResponseMessage.Role = 'AI';
3091
+ agentResponseMessage = await this.createTurnRow(conversationId, branchId);
2965
3092
  agentResponseMessage.Message = '⏳ Starting...'; // Initial message
2966
3093
  agentResponseMessage.ParentID = userMessage.ID;
2967
3094
  agentResponseMessage.Status = 'In-Progress';
2968
- agentResponseMessage.HiddenToUser = false;
2969
3095
  // Set AgentID immediately for proper attribution
2970
3096
  if (agent?.ID) {
2971
3097
  agentResponseMessage.AgentID = agent.ID;
@@ -2975,7 +3101,7 @@ export class MessageInputComponent extends BaseAngularComponent {
2975
3101
  this.MessageSent.emit(agentResponseMessage);
2976
3102
  // Load previous payload if agent has been invoked before
2977
3103
  const { payload: previousPayload, artifactInfo } = agent?.ID
2978
- ? await this.loadPreviousPayloadForAgent(agent.ID)
3104
+ ? await this.loadPreviousPayloadForAgent(agent.ID, branchId)
2979
3105
  : { payload: null, artifactInfo: null };
2980
3106
  // Invoke the agent directly
2981
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
@@ -2995,12 +3121,12 @@ export class MessageInputComponent extends BaseAngularComponent {
2995
3121
  // Stage 1: Check for task graph (multi-step orchestration)
2996
3122
  if (result.payload?.taskGraph) {
2997
3123
  console.log('📋 Task graph detected from @mention, starting task orchestration');
2998
- await this.handleTaskGraphExecution(userMessage, result, conversationId, agentResponseMessage);
3124
+ await this.handleTaskGraphExecution(userMessage, result, conversationId, branchId, agentResponseMessage);
2999
3125
  }
3000
3126
  // Stage 2: Check for sub-agent invocation (single-step delegation)
3001
3127
  else if (result.agentRun.FinalStep === 'Success' && result.payload?.invokeAgent) {
3002
3128
  console.log('🎯 Sub-agent invocation detected from @mention');
3003
- await this.handleSubAgentInvocation(userMessage, result, conversationId, agentResponseMessage);
3129
+ await this.handleSubAgentInvocation(userMessage, result, conversationId, branchId, agentResponseMessage);
3004
3130
  }
3005
3131
  // Stage 3: Normal chat response
3006
3132
  else {
@@ -3032,11 +3158,12 @@ export class MessageInputComponent extends BaseAngularComponent {
3032
3158
  * Continue with the same agent from previous message (implicit continuation)
3033
3159
  * Bypasses Sage - no status messages
3034
3160
  *
3161
+ * @param branchId The turn's branch (null is Main).
3035
3162
  * @param targetArtifactVersionId Optional specific artifact version to use as payload (from intent check)
3036
3163
  */
3037
- async continueWithAgent(userMessage, agentId, conversationId, targetArtifactVersionId) {
3164
+ async continueWithAgent(userMessage, agentId, conversationId, branchId, targetArtifactVersionId) {
3038
3165
  // Load the agent entity to get its name
3039
- const agent = AIEngineBase.Instance.Agents.find(a => UUIDsEqual(a.ID, agentId));
3166
+ const agent = AIEngineBase.Instance.ReadableAgents.find(a => UUIDsEqual(a.ID, agentId));
3040
3167
  if (!agent) {
3041
3168
  if (!IsAgentAllowed(this.ConverationManagerAgent?.ID, this.AllowedAgentIDs)) {
3042
3169
  console.warn('⚠️ Could not load agent for continuation, and Sage is not allowed in this chat');
@@ -3044,7 +3171,7 @@ export class MessageInputComponent extends BaseAngularComponent {
3044
3171
  return;
3045
3172
  }
3046
3173
  console.warn('⚠️ Could not load agent for continuation - falling back to Sage');
3047
- await this.processMessageThroughAgent(userMessage, { mentions: [], agentMention: null, userMentions: [], entityMentions: [], skillMentions: [] });
3174
+ await this.processMessageThroughAgent(userMessage, { mentions: [], agentMention: null, userMentions: [], entityMentions: [], skillMentions: [] }, branchId);
3048
3175
  return;
3049
3176
  }
3050
3177
  const agentName = agent.Name || 'Agent';
@@ -3072,7 +3199,7 @@ export class MessageInputComponent extends BaseAngularComponent {
3072
3199
  }
3073
3200
  // Extract configuration preset from the User message that @mentioned this agent
3074
3201
  // Uses the shared helper method in the agent service
3075
- previousConfigurationId = await this.agentService.FindConfigurationPresetForAgent(conversationId, agentId);
3202
+ previousConfigurationId = await this.agentService.FindConfigurationPresetForAgent(conversationId, agentId, branchId);
3076
3203
  // Fall back to the chat header's mode-picker selection when nothing
3077
3204
  // in the message history pinned a preset. The picker reflects the
3078
3205
  // user's persistent per-agent mode preference (Draft / Standard /
@@ -3089,7 +3216,7 @@ export class MessageInputComponent extends BaseAngularComponent {
3089
3216
  // used to walk is the loaded window, so the artifact it is looking for is exactly the
3090
3217
  // one most likely to be missing from it.
3091
3218
  if (!previousPayload) {
3092
- const source = await this.agentService.FindLatestAgentOutputVersion(conversationId, agentId, this.AgentHistoryFrom);
3219
+ const source = await this.agentService.FindLatestAgentOutputVersion(conversationId, agentId, this.AgentHistoryFrom, branchId);
3093
3220
  if (source && source.payload != null) {
3094
3221
  previousPayload = source.payload;
3095
3222
  previousArtifactInfo = {
@@ -3104,7 +3231,7 @@ export class MessageInputComponent extends BaseAngularComponent {
3104
3231
  }
3105
3232
  }
3106
3233
  // Execute the agent with the gathered context
3107
- await this.executeAgentContinuation(userMessage, agentId, agentName, conversationId, previousPayload, previousArtifactInfo, previousConfigurationId);
3234
+ await this.executeAgentContinuation(userMessage, agentId, agentName, conversationId, branchId, previousPayload, previousArtifactInfo, previousConfigurationId);
3108
3235
  }
3109
3236
  /**
3110
3237
  * Executes agent continuation with all context already gathered.
@@ -3114,11 +3241,12 @@ export class MessageInputComponent extends BaseAngularComponent {
3114
3241
  * @param agentId The agent ID to invoke
3115
3242
  * @param agentName The agent's display name
3116
3243
  * @param conversationId The conversation ID
3244
+ * @param branchId The turn's branch (null is Main); the reply row is written there
3117
3245
  * @param previousPayload Optional payload from previous artifact
3118
3246
  * @param previousArtifactInfo Optional artifact info (id, versionId, versionNumber)
3119
3247
  * @param configurationId Optional configuration preset ID to use
3120
3248
  */
3121
- async executeAgentContinuation(userMessage, agentId, agentName, conversationId, previousPayload, previousArtifactInfo, configurationId) {
3249
+ async executeAgentContinuation(userMessage, agentId, agentName, conversationId, branchId, previousPayload, previousArtifactInfo, configurationId) {
3122
3250
  // Add agent to active tasks
3123
3251
  const taskId = this.activeTasks.add({
3124
3252
  agentName: agentName,
@@ -3137,13 +3265,10 @@ export class MessageInputComponent extends BaseAngularComponent {
3137
3265
  await userMessage.Save();
3138
3266
  this.MessageSent.emit(userMessage);
3139
3267
  // Create AI response message BEFORE invoking agent (for duration tracking)
3140
- agentResponseMessage = await this.dataCache.createConversationDetail(this.CurrentUser);
3141
- agentResponseMessage.ConversationID = conversationId;
3142
- agentResponseMessage.Role = 'AI';
3268
+ agentResponseMessage = await this.createTurnRow(conversationId, branchId);
3143
3269
  agentResponseMessage.Message = '⏳ Starting...'; // Initial message
3144
3270
  agentResponseMessage.ParentID = userMessage.ID;
3145
3271
  agentResponseMessage.Status = 'In-Progress';
3146
- agentResponseMessage.HiddenToUser = false;
3147
3272
  agentResponseMessage.AgentID = agentId;
3148
3273
  // Save the record to establish __mj_CreatedAt timestamp
3149
3274
  await agentResponseMessage.Save();
@@ -3333,7 +3458,7 @@ export class MessageInputComponent extends BaseAngularComponent {
3333
3458
  // (when the run produced an artifact); the shared dedupe key folds the two into one
3334
3459
  // toast, and this wording — the later of the two — is what stays on screen.
3335
3460
  const agent = task.agentId
3336
- ? AIEngineBase.Instance.Agents.find(a => UUIDsEqual(a.ID, task.agentId))
3461
+ ? AIEngineBase.Instance.ReadableAgents.find(a => UUIDsEqual(a.ID, task.agentId))
3337
3462
  : undefined;
3338
3463
  // The task carries the name from send time; the engine has the current one (the
3339
3464
  // first exchange auto-names the conversation). The placeholder a brand-new
@@ -3400,11 +3525,11 @@ export class MessageInputComponent extends BaseAngularComponent {
3400
3525
  } if (rf & 2) {
3401
3526
  let _t;
3402
3527
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.InputBox = _t.first);
3403
- } }, 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", 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: 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) {
3404
3529
  i0.ɵɵelementStart(0, "div", 2, 0);
3405
3530
  i0.ɵɵconditionalCreate(2, MessageInputComponent_Conditional_2_Template, 4, 1, "div", 3);
3406
3531
  i0.ɵɵelementStart(3, "mj-ai-composer", 4, 1);
3407
- 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(); });
3408
3533
  i0.ɵɵelementEnd();
3409
3534
  i0.ɵɵtemplate(5, MessageInputComponent_ng_template_5_Template, 1, 6, "ng-template", 5);
3410
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(); });
@@ -3414,14 +3539,14 @@ export class MessageInputComponent extends BaseAngularComponent {
3414
3539
  i0.ɵɵadvance(2);
3415
3540
  i0.ɵɵconditional(ctx.isProcessing ? 2 : -1);
3416
3541
  i0.ɵɵadvance();
3417
- 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);
3418
3543
  i0.ɵɵadvance(2);
3419
3544
  i0.ɵɵproperty("cdkConnectedOverlayOrigin", pickerOrigin_r3)("cdkConnectedOverlayOpen", ctx.showRealtimeAgentPicker)("cdkConnectedOverlayPositions", ctx.pickerOverlayPositions)("cdkConnectedOverlayPush", true)("cdkConnectedOverlayHasBackdrop", true);
3420
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}"] });
3421
3546
  }
3422
3547
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MessageInputComponent, [{
3423
3548
  type: Component,
3424
- 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"] }]
3425
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: [{
3426
3551
  type: Input
3427
3552
  }], conversationId: [{
@@ -3440,6 +3565,16 @@ export class MessageInputComponent extends BaseAngularComponent {
3440
3565
  type: Input
3441
3566
  }], ReadOnly: [{
3442
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
3443
3578
  }], Placeholder: [{
3444
3579
  type: Input
3445
3580
  }], placeholder: [{
@@ -3548,12 +3683,18 @@ export class MessageInputComponent extends BaseAngularComponent {
3548
3683
  type: Input
3549
3684
  }], AgentHistoryFrom: [{
3550
3685
  type: Input
3686
+ }], TargetBranchID: [{
3687
+ type: Input
3688
+ }], ResolveTargetBranch: [{
3689
+ type: Input
3551
3690
  }], AgentTurnHandler: [{
3552
3691
  type: Input
3553
3692
  }], AutoNameConversation: [{
3554
3693
  type: Input
3555
3694
  }], EnableDecisionRouting: [{
3556
3695
  type: Input
3696
+ }], StopClicked: [{
3697
+ type: Output
3557
3698
  }], MessageSent: [{
3558
3699
  type: Output
3559
3700
  }], messageSent: [{
@@ -3632,5 +3773,5 @@ export class MessageInputComponent extends BaseAngularComponent {
3632
3773
  }], ComposerBlurred: [{
3633
3774
  type: Output
3634
3775
  }] }); })();
3635
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageInputComponent, { className: "MessageInputComponent", filePath: "src/lib/components/message/message-input.component.ts", lineNumber: 70 }); })();
3776
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageInputComponent, { className: "MessageInputComponent", filePath: "src/lib/components/message/message-input.component.ts", lineNumber: 71 }); })();
3636
3777
  //# sourceMappingURL=message-input.component.js.map